Merge pull request #1926 from PhenomRetroShare/Fix_GroupTreeWidgetQSS

Fix GroupTreeWidget with RSElidedItemDelegate for StyleSheet.
This commit is contained in:
defnax 2020-05-11 14:39:17 +02:00 committed by GitHub
commit d1c065559e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 130 deletions

View File

@ -18,28 +18,20 @@
* *
*******************************************************************************/
#include <iostream>
#include "GroupTreeWidget.h"
#include "ui_GroupTreeWidget.h"
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QMovie>
#include <QToolButton>
#include "retroshare/rsgxsflags.h"
#include "PopularityDefs.h"
#include "RSElidedItemDelegate.h"
#include "RSTreeWidgetItem.h"
#include "gui/common/ElidedLabel.h"
#include "gui/settings/rsharesettings.h"
#include "util/QtVersion.h"
#include "util/DateTime.h"
#include <QMenu>
#include <stdint.h>
#define COLUMN_NAME 0
@ -66,9 +58,6 @@
#define FILTER_NAME_INDEX 0
#define FILTER_DESC_INDEX 1
Q_DECLARE_METATYPE(ElidedLabel*)
Q_DECLARE_METATYPE(QLabel*)
GroupTreeWidget::GroupTreeWidget(QWidget *parent) :
QWidget(parent), ui(new Ui::GroupTreeWidget)
{
@ -143,7 +132,7 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) :
/* Initialize display button */
initDisplayMenu(ui->displayButton);
ui->treeWidget->setIconSize(QSize(S*1.8,S*1.8));
ui->treeWidget->setIconSize(QSize(S*1.8,S*1.8));
}
GroupTreeWidget::~GroupTreeWidget()
@ -151,38 +140,6 @@ GroupTreeWidget::~GroupTreeWidget()
delete ui;
}
static void getNameWidget(QTreeWidget *treeWidget, QTreeWidgetItem *item, ElidedLabel *&nameLabel, QLabel *&waitLabel)
{
QWidget *widget = treeWidget->itemWidget(item, COLUMN_NAME);
if (!widget) {
widget = new QWidget;
widget->setAttribute(Qt::WA_TranslucentBackground);
nameLabel = new ElidedLabel(widget);
waitLabel = new QLabel(widget);
QMovie *movie = new QMovie(":/images/loader/circleball-16.gif");
waitLabel->setMovie(movie);
waitLabel->setHidden(true);
widget->setProperty("nameLabel", qVariantFromValue(nameLabel));
widget->setProperty("waitLabel", qVariantFromValue(waitLabel));
QHBoxLayout *layout = new QHBoxLayout;
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(nameLabel);
layout->addWidget(waitLabel);
widget->setLayout(layout);
treeWidget->setItemWidget(item, COLUMN_NAME, widget);
} else {
nameLabel = widget->property("nameLabel").value<ElidedLabel*>();
waitLabel = widget->property("waitLabel").value<QLabel*>();
}
}
void GroupTreeWidget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
@ -346,11 +303,6 @@ void GroupTreeWidget::updateColors()
}
item->setForeground(COLUMN_NAME, brush);
ElidedLabel *nameLabel = NULL;
QLabel *waitLabel = NULL;
getNameWidget(ui->treeWidget, item, nameLabel, waitLabel);
nameLabel->setTextColor(brush.color());
}
}
@ -390,24 +342,21 @@ QTreeWidgetItem *GroupTreeWidget::addCategoryItem(const QString &name, const QIc
QFont font;
QTreeWidgetItem *item = new QTreeWidgetItem();
ui->treeWidget->addTopLevelItem(item);
// To get StyleSheet for Items
ui->treeWidget->style()->unpolish(ui->treeWidget);
ui->treeWidget->style()->polish(ui->treeWidget);
ElidedLabel *nameLabel = NULL;
QLabel *waitLabel = NULL;
getNameWidget(ui->treeWidget, item, nameLabel, waitLabel);
nameLabel->setText(name);
item->setText(COLUMN_NAME, name);
item->setData(COLUMN_DATA, ROLE_NAME, name);
font = item->font(COLUMN_NAME);
font.setBold(true);
item->setFont(COLUMN_NAME, font);
nameLabel->setFont(font);
item->setIcon(COLUMN_NAME, icon);
int S = QFontMetricsF(font).height();
item->setSizeHint(COLUMN_NAME, QSize(S*1.9, S*1.9));
item->setForeground(COLUMN_NAME, QBrush(textColorCategory()));
nameLabel->setTextColor(textColorCategory());
item->setData(COLUMN_DATA, ROLE_COLOR, GROUPTREEWIDGET_COLOR_CATEGORY);
item->setExpanded(expand);
@ -437,19 +386,19 @@ void GroupTreeWidget::setDistSearchVisible(bool visible)
bool GroupTreeWidget::isSearchRequestResult(QPoint &point,QString& group_id,uint32_t& search_req_id)
{
QTreeWidgetItem *item = ui->treeWidget->itemAt(point);
QTreeWidgetItem *item = ui->treeWidget->itemAt(point);
if (item == NULL)
return false;
QTreeWidgetItem *parent = item->parent();
QTreeWidgetItem *parent = item->parent();
if(parent == NULL)
return false ;
if(parent == NULL)
return false ;
search_req_id = parent->data(COLUMN_DATA, ROLE_REQUEST_ID).toUInt();
group_id = itemId(item) ;
group_id = itemId(item) ;
return search_req_id > 0;
return search_req_id > 0;
}
bool GroupTreeWidget::isSearchRequestItem(QPoint &point,uint32_t& search_req_id)
@ -514,11 +463,7 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
categoryItem->addChild(item);
}
ElidedLabel *nameLabel = NULL;
QLabel *waitLabel = NULL;
getNameWidget(ui->treeWidget, item, nameLabel, waitLabel);
nameLabel->setText(itemInfo.name);
item->setText(COLUMN_NAME, itemInfo.name);
item->setData(COLUMN_DATA, ROLE_NAME, itemInfo.name);
item->setData(COLUMN_DATA, ROLE_DESCRIPTION, itemInfo.description);
@ -535,12 +480,7 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
item->setData(COLUMN_DATA, ROLE_POSTS, -itemInfo.max_visible_posts);// negative for correct sorting
/* Set icon */
if (waitLabel->isVisible()) {
/* Item is waiting, save icon in role */
item->setData(COLUMN_DATA, ROLE_SAVED_ICON, itemInfo.icon);
} else {
item->setIcon(COLUMN_NAME, itemInfo.icon);
}
item->setIcon(COLUMN_NAME, itemInfo.icon);
/* Set popularity */
QString tooltip = PopularityDefs::tooltip(itemInfo.popularity);
@ -582,7 +522,6 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
item->setData(COLUMN_DATA, ROLE_COLOR, GROUPTREEWIDGET_COLOR_STANDARD);
}
item->setForeground(COLUMN_NAME, brush);
nameLabel->setTextColor(brush.color());
/* Calculate score */
calculateScore(item, filterText);
@ -616,11 +555,8 @@ void GroupTreeWidget::setUnreadCount(QTreeWidgetItem *item, int unreadCount)
if (item == NULL) {
return;
}
ElidedLabel *nameLabel = NULL;
QLabel *waitLabel = NULL;
getNameWidget(ui->treeWidget, item, nameLabel, waitLabel);
QFont font = nameLabel->font();
QFont font = item->font(COLUMN_NAME);
if (unreadCount) {
item->setData(COLUMN_DATA, ROLE_UNREAD, unreadCount);
@ -631,7 +567,7 @@ void GroupTreeWidget::setUnreadCount(QTreeWidgetItem *item, int unreadCount)
font.setBold(false);
}
nameLabel->setFont(font);
item->setFont(COLUMN_NAME, font);
}
QTreeWidgetItem *GroupTreeWidget::getItemFromId(const QString &id)
@ -677,40 +613,7 @@ bool GroupTreeWidget::setWaiting(const QString &id, bool wait)
return false;
}
ElidedLabel *nameLabel = NULL;
QLabel *waitLabel = NULL;
getNameWidget(ui->treeWidget, item, nameLabel, waitLabel);
if (wait) {
if (waitLabel->isVisible()) {
/* Allready waiting */
} else {
/* Save icon in role */
QIcon icon = item->icon(COLUMN_NAME);
item->setData(COLUMN_DATA, ROLE_SAVED_ICON, icon);
/* Create empty icon of the same size */
QPixmap pixmap(ui->treeWidget->iconSize());
pixmap.fill(Qt::transparent);
item->setIcon(COLUMN_NAME, QIcon(pixmap));
/* Show waitLabel and hide nameLabel */
nameLabel->setHidden(true);
waitLabel->setVisible(true);
waitLabel->movie()->start();
}
} else {
if (waitLabel->isVisible()) {
/* Show nameLabel and hide waitLabel */
waitLabel->movie()->stop();
waitLabel->setHidden(true);
nameLabel->setVisible(true);
/* Set icon saved in role */
item->setIcon(COLUMN_NAME, item->data(COLUMN_DATA, ROLE_SAVED_ICON).value<QIcon>());
item->setData(COLUMN_DATA, ROLE_SAVED_ICON, QIcon());
}
}
item->setData(COLUMN_NAME, Qt::StatusTipRole, wait ? "waiting" : "");
return true;
}

View File

@ -21,8 +21,6 @@
#ifndef GROUPTREEWIDGET_H
#define GROUPTREEWIDGET_H
#include <QWidget>
#include <QIcon>
#include <QTreeWidgetItem>
#include <QDateTime>
@ -109,7 +107,8 @@ public:
void setTextColorCategory(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_CATEGORY] = color; }
void setTextColorPrivateKey(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_PRIVATEKEY] = color; }
bool getGroupName(QString id, QString& name);
bool getGroupName(QString id, QString& name);
int subscribeFlags(const QString &id);

View File

@ -23,12 +23,19 @@
#include "gui/common/StyledElidedLabel.h"
#include "util/rsdebug.h"
#include <QAbstractItemView>
#include <QApplication>
#include <QPainter>
#include <QTextDocument>
#include <QTextLayout>
#include <QTimer>
#include <QToolTip>
#include <QtMath>
#include <cmath>
#include <chrono>
RSElidedItemDelegate::RSElidedItemDelegate(QObject *parent)
: RSStyledItemDelegate(parent)
, mOnlyPlainText(false), mPaintRoundedRect(true)
@ -124,13 +131,49 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
}
// draw the icon
{
QIcon::Mode mode = QIcon::Normal;
if (!(ownOption.state & QStyle::State_Enabled))
mode = QIcon::Disabled;
else if (ownOption.state & QStyle::State_Selected)
mode = QIcon::Selected;
QIcon::State state = ownOption.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
ownOption.icon.paint(painter, iconRect, ownOption.decorationAlignment, mode, state);
if (!ownOption.icon.isNull())
{
QString status;
if (index.data(Qt::StatusTipRole).canConvert(QMetaType::QString))
status = index.data(Qt::StatusTipRole).toString();
// Draw item Icon
{
QIcon::Mode mode = QIcon::Normal;
if (!(ownOption.state & QStyle::State_Enabled))
mode = QIcon::Disabled;
else if (ownOption.state & QStyle::State_Selected)
mode = QIcon::Selected;
QIcon::State state = ownOption.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
ownOption.icon.paint(painter, iconRect, ownOption.decorationAlignment, mode, state);
}
// Then overlay with waiting
if (status.toLower() == "waiting")
{
const QAbstractItemView* aiv = dynamic_cast<const QAbstractItemView*>(option.widget);
if (aiv)
QTimer::singleShot(200, aiv->viewport(), SLOT(update()));
QSize waitSize=iconRect.size();
qreal diag = qMin(waitSize.height(),waitSize.height())*std::sqrt(2);
auto now = std::chrono::system_clock::now().time_since_epoch();
auto s = std::chrono::duration_cast<std::chrono::seconds>(now).count();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - std::chrono::duration_cast<std::chrono::seconds>(now)).count();
int duration = 3;// Time (s) to make a revolution.
auto time = (s%duration)*1000 + ms;
qreal angle = 360.0*(time/(duration*1000.0));
qreal add = 120*(time/(duration*1000.0))*abs(sin(qDegreesToRadians(angle/2)));
painter->setPen(QPen(QBrush(ownOption.palette.color(QPalette::Normal, QPalette::WindowText)),diag/10,Qt::DotLine,Qt::RoundCap));
painter->drawEllipse( iconRect.x()+iconRect.width() /2 + (diag/4)*cos(qDegreesToRadians(angle ))
, iconRect.y()+iconRect.height()/2 + (diag/4)*sin(qDegreesToRadians(angle )), 1, 1);
painter->setPen(QPen(QBrush(ownOption.palette.color(QPalette::Normal, QPalette::Midlight)),diag/10,Qt::DotLine,Qt::RoundCap));
painter->drawEllipse( iconRect.x()+iconRect.width() /2 + (diag/4)*cos(qDegreesToRadians(angle- add))
, iconRect.y()+iconRect.height()/2 + (diag/4)*sin(qDegreesToRadians(angle- add)), 1, 1);
painter->setPen(QPen(QBrush(ownOption.palette.color(QPalette::Normal, QPalette::Window)),diag/10,Qt::DotLine,Qt::RoundCap));
painter->drawEllipse( iconRect.x()+iconRect.width() /2 + (diag/4)*cos(qDegreesToRadians(angle-2*add))
, iconRect.y()+iconRect.height()/2 + (diag/4)*sin(qDegreesToRadians(angle-2*add)), 1, 1);
}
}
}
// draw the text
if (!ownOption.text.isEmpty()) {
@ -141,6 +184,7 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
if (ownOption.state & QStyle::State_Selected) {
painter->setPen(ownOption.palette.color(cg, QPalette::HighlightedText));
} else {
#if QT_VERSION >= QT_VERSION_CHECK(5,6,0)
if (ownOption.state & QStyle::State_MouseOver) {
//TODO: Manage to get palette with HOVER css pseudoclass
// For now this is hidden by Qt: https://code.woboq.org/qt5/qtbase/src/widgets/styles/qstylesheetstyle.cpp.html#6103
@ -158,7 +202,7 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
{
moOption.rect = QRect(QPoint(0,0),moSize);
moOption.state = QStyle::State_MouseOver | QStyle::State_Enabled | QStyle::State_Sibling;
moOption.text = "████████████████";
moOption.text = " ████████████████";//Add a blank char to get BackGround Color at top left
// Remove unwanted info. Yes it can draw without that all public data ...
moOption.backgroundBrush = QBrush();
moOption.checkState = Qt::Unchecked;
@ -200,11 +244,12 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
// Get Color in this black rect.
QColor moColor;
QColor moBGColor=moImg.pixelColor(1,1); //BackGround may be paint.
QColor moColorBorder;// To avoid Border pixel
int moWidth = moImg.size().width(), moHeight = moImg.size().height();
for (int x = 0; (x<moWidth) && (moColor.spec() == QColor::Invalid); x++)
for (int y = 0; (y<moHeight) && (moColor.spec() == QColor::Invalid); y++)
if (moImg.pixelColor(x,y) != Qt::black)
if (moImg.pixelColor(x,y) != moBGColor)
{
if (moImg.pixelColor(x,y) == moColorBorder)
moColor = QColor(moImg.pixelColor(x,y).name());
@ -220,13 +265,14 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
}
}
// If not found color is black too.
// If not found color is same as BackGround.
if (moColor.spec() == QColor::Invalid)
moColor = Qt::black;
moColor = moBGColor;
painter->setPen(moColor);
}
else
#endif
if (textColor.spec()==QColor::Invalid) {
painter->setPen(ownOption.palette.color(cg, QPalette::Text));
} else { //Only get color from index for unselected(as Qt does)

View File

@ -26,6 +26,9 @@
class RSElidedItemDelegate : public RSStyledItemDelegate
{
Q_OBJECT
// For now, these properties cannot be changed by StyleSheet
// If needed, you can add properties to owner widget then copy them in this delegate.
Q_PROPERTY(bool isOnlyPlainText READ isOnlyPlainText WRITE setOnlyPlainText)
Q_PROPERTY(bool paintRoundedRect READ paintRoundedRect WRITE setPaintRoundedRect)
@ -49,7 +52,6 @@ protected:
private:
bool mOnlyPlainText;
bool mPaintRoundedRect;
};
#endif // RSELIDEDITEMDELEGATE_H

View File

@ -2143,3 +2143,9 @@ PostedCardView > QFrame#mainFrame[new=true] {
WireGroupItem QFrame#frame{
background: transparent;
}
GxsChannelDialog GroupTreeWidget QTreeWidget#treeWidget::item{
/*background-color: #F00000;*/
/*padding: 20px;*/
}