Fix RsElidedItemDelegate for StyleSheet

Now StyleSheet is applied well.
This commit is contained in:
Phenom 2020-05-03 20:31:32 +02:00
parent d833049dce
commit 0eaa121457
14 changed files with 577 additions and 398 deletions

View File

@ -34,6 +34,7 @@
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
#include "gui/chat/ChatDialog.h" #include "gui/chat/ChatDialog.h"
#include "gui/Circles/CreateCircleDialog.h" #include "gui/Circles/CreateCircleDialog.h"
#include "gui/common/FilesDefs.h"
#include "gui/common/UIStateHelper.h" #include "gui/common/UIStateHelper.h"
#include "gui/common/UserNotify.h" #include "gui/common/UserNotify.h"
#include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/GxsIdDetails.h"
@ -358,6 +359,9 @@ IdDialog::IdDialog(QWidget *parent) : MainPage(parent), ui(new Ui::IdDialog)
ui->idTreeWidget->setColumnWidth(RSID_COL_IDTYPE, 18 * fontWidth); ui->idTreeWidget->setColumnWidth(RSID_COL_IDTYPE, 18 * fontWidth);
ui->idTreeWidget->setColumnWidth(RSID_COL_VOTES, 2 * fontWidth); ui->idTreeWidget->setColumnWidth(RSID_COL_VOTES, 2 * fontWidth);
ui->idTreeWidget->setItemDelegateForColumn(
RSID_COL_NICKNAME,
new GxsIdTreeItemDelegate());
ui->idTreeWidget->setItemDelegateForColumn( ui->idTreeWidget->setItemDelegateForColumn(
RSID_COL_VOTES, RSID_COL_VOTES,
new ReputationItemDelegate(RsReputationLevel(0xff))); new ReputationItemDelegate(RsReputationLevel(0xff)));
@ -638,7 +642,6 @@ void IdDialog::loadCircles(const std::list<RsGroupMetaData>& groupInfo)
RsGxsCircleDetails details; RsGxsCircleDetails details;
rsGxsCircles->getCircleDetails(RsGxsCircleId(vit->mGroupId), details) ; rsGxsCircles->getCircleDetails(RsGxsCircleId(vit->mGroupId), details) ;
bool should_re_add = true ;
bool am_I_in_circle = details.mAmIAllowed ; bool am_I_in_circle = details.mAmIAllowed ;
bool am_I_admin (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) ; bool am_I_admin (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) ;
bool am_I_subscribed (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) ; bool am_I_subscribed (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) ;
@ -774,10 +777,13 @@ void IdDialog::loadCircles(const std::list<RsGroupMetaData>& groupInfo)
std::cerr << " no existing sub item. Creating new one." << std::endl; std::cerr << " no existing sub item. Creating new one." << std::endl;
#endif #endif
subitem = new RSTreeWidgetItem(NULL); subitem = new RSTreeWidgetItem(NULL);
subitem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,Qt::UserRole,QString::fromStdString(it->first.toStdString())); subitem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,Qt::UserRole,QString::fromStdString(it->first.toStdString()));
//Icon PlaceHolder
subitem->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,FilesDefs::getIconFromQtResourcePath(":/icons/png/anonymous.png"));
RsIdentityDetails idd ; RsIdentityDetails idd ;
bool has_id = rsIdentity->getIdDetails(it->first,idd) ; //bool has_id =
rsIdentity->getIdDetails(it->first,idd) ;
// QPixmap pixmap ; // QPixmap pixmap ;
@ -842,30 +848,30 @@ void IdDialog::loadCircles(const std::list<RsGroupMetaData>& groupInfo)
} }
} }
// The bullet colors below are for the *Membership*. This is independent from admin rights, which cannot be shown as a color. // The bullet colors below are for the *Membership*. This is independent from admin rights, which cannot be shown as a color.
// Admin/non admin is shows using Bold font. // Admin/non admin is shows using Bold font.
if(am_I_in_circle) if(am_I_in_circle)
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(IMAGE_MEMBER)) ; item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,FilesDefs::getIconFromQtResourcePath(IMAGE_MEMBER)) ;
else if(am_I_invited || am_I_pending) else if(am_I_invited || am_I_pending)
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(IMAGE_INVITED)) ; item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,FilesDefs::getIconFromQtResourcePath(IMAGE_INVITED)) ;
else else
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(IMAGE_UNKNOWN)) ; item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,FilesDefs::getIconFromQtResourcePath(IMAGE_UNKNOWN)) ;
} }
} }
static void mark_matching_tree(QTreeWidget *w, const std::set<RsGxsId>& members, int col) //static void mark_matching_tree(QTreeWidget *w, const std::set<RsGxsId>& members, int col)
{ //{
w->selectionModel()->clearSelection() ; // w->selectionModel()->clearSelection() ;
//
for(std::set<RsGxsId>::const_iterator it(members.begin());it!=members.end();++it) // for(std::set<RsGxsId>::const_iterator it(members.begin());it!=members.end();++it)
{ // {
QList<QTreeWidgetItem*> clist = w->findItems( QString::fromStdString((*it).toStdString()), Qt::MatchExactly|Qt::MatchRecursive, col); // QList<QTreeWidgetItem*> clist = w->findItems( QString::fromStdString((*it).toStdString()), Qt::MatchExactly|Qt::MatchRecursive, col);
//
foreach(QTreeWidgetItem* item, clist) // foreach(QTreeWidgetItem* item, clist)
item->setSelected(true) ; // item->setSelected(true) ;
} // }
} //}
bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id)
{ {
@ -1252,7 +1258,7 @@ void IdDialog::updateIdList()
ui->removeIdentity->setEnabled(false); ui->removeIdentity->setEnabled(false);
ui->editIdentity->setEnabled(false); ui->editIdentity->setEnabled(false);
int accept = filter; //int accept = filter;
RsThread::async([this]() RsThread::async([this]()
{ {
@ -1359,9 +1365,10 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
} }
item->setText(RSID_COL_NICKNAME, QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); item->setText(RSID_COL_NICKNAME, QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE));
item->setText(RSID_COL_KEYID, QString::fromStdString(data.mMeta.mGroupId.toStdString())); item->setData(RSID_COL_NICKNAME, Qt::UserRole, QString::fromStdString(data.mMeta.mGroupId.toStdString()));
item->setText(RSID_COL_KEYID, QString::fromStdString(data.mMeta.mGroupId.toStdString()));
if(isBanned) if(isBanned)
{ {
item->setForeground(RSID_COL_NICKNAME,QBrush(Qt::red)); item->setForeground(RSID_COL_NICKNAME,QBrush(Qt::red));
@ -1411,14 +1418,16 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
item->setToolTip(RSID_COL_IDTYPE, tooltip) ; item->setToolTip(RSID_COL_IDTYPE, tooltip) ;
} }
QPixmap pixmap ; //QPixmap pixmap ;
//
//if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::SMALL))
// pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::SMALL) ;
//
//item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
// Icon Place Holder
item->setIcon(RSID_COL_NICKNAME,FilesDefs::getIconFromQtResourcePath(":/icons/png/anonymous.png"));
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::SMALL)) QString tooltip;
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::SMALL) ;
item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
QString tooltip;
if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)
{ {
@ -1541,10 +1550,6 @@ void IdDialog::loadIdentities(const std::map<RsGxsGroupId,RsGxsIdGroup>& ids_set
else else
allItem->addChild(item); allItem->addChild(item);
GxsIdLabel *label = new GxsIdLabel();
label->setId(RsGxsId(data.mMeta.mGroupId)) ;
ui->treeWidget_membership->setItemWidget(item,0,label) ;
} }
} }

View File

@ -85,25 +85,32 @@ void ElidedLabel::paintEvent(QPaintEvent *event)
td.setHtml(mContent); td.setHtml(mContent);
plainText = td.toPlainText(); plainText = td.toPlainText();
} }
QRect cr(contentsRect()); QRect cr(contentsRect());
cr.adjust(margin(), margin(), -margin(), -margin()); cr.adjust(margin(), margin(), -margin(), -margin());
bool didElide = paintElidedLine(painter,plainText,cr,alignment(),wordWrap(),true,mRectElision); bool didElide = paintElidedLine(&painter,plainText,cr,font(),alignment(),wordWrap(),true,&mRectElision);
//Send signal if changed //Send signal if changed
if (didElide != mElided) if (didElide != mElided)
{ {
mElided = didElide; mElided = didElide;
emit elisionChanged(didElide); emit elisionChanged(didElide);
} }
} }
bool ElidedLabel::paintElidedLine(QPainter& painter,QString plainText,const QRect& cr,Qt::Alignment alignment,bool wordWrap,bool drawRoundRect,QRect& rectElision) bool ElidedLabel::paintElidedLine( QPainter* painter, QString plainText
, const QRect& cr, QFont useFont
, Qt::Alignment alignment, bool wordWrap
, bool drawRoundedRect, QRect* rectElision/*=nullptr*/)
{ {
if (rectElision) *rectElision = QRect();
if (plainText.isEmpty())
return false;
QList<QPair<QTextLine,QPoint> > lLines; QList<QPair<QTextLine,QPoint> > lLines;
QString elidedLastLine = ""; QString elidedLastLine = "";
QFontMetrics fontMetrics = painter.fontMetrics(); QFontMetrics fontMetrics = QFontMetrics(useFont);
bool didElide = false; bool didElide = false;
QChar ellipsisChar(0x2026);//= "…" QChar ellipsisChar(0x2026);//= "…"
@ -113,12 +120,13 @@ bool ElidedLabel::paintElidedLine(QPainter& painter,QString plainText,const QRec
plainText = plainText.replace("\n",QChar(QChar::LineSeparator)); plainText = plainText.replace("\n",QChar(QChar::LineSeparator));
plainText = plainText.replace("\r",QChar(QChar::LineSeparator)); plainText = plainText.replace("\r",QChar(QChar::LineSeparator));
QTextLayout textLayout(plainText, painter.font()); QTextLayout textLayout(plainText, useFont);
QTextOption to = textLayout.textOption(); QTextOption to = textLayout.textOption();
to.setAlignment(alignment); to.setAlignment(alignment);
to.setWrapMode(wordWrap ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::NoWrap); to.setWrapMode(wordWrap ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::NoWrap);
textLayout.setTextOption(to); textLayout.setTextOption(to);
if (painter) painter->save();
textLayout.beginLayout(); textLayout.beginLayout();
forever { forever {
//Get new line for text. //Get new line for text.
@ -138,7 +146,13 @@ bool ElidedLabel::paintElidedLine(QPainter& painter,QString plainText,const QRec
//The next line can't be written. //The next line can't be written.
QString lastLine = plainText.mid(line.textStart()).split(QChar(QChar::LineSeparator)).at(0); QString lastLine = plainText.mid(line.textStart()).split(QChar(QChar::LineSeparator)).at(0);
QTextLine lineEnd = textLayout.createLine(); QTextLine lineEnd = textLayout.createLine();
if (!lineEnd.isValid() && (wordWrap || (fontMetrics.width(lastLine) < cr.width()))) { if (!lineEnd.isValid() && (wordWrap
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|| (fontMetrics.width(lastLine) < cr.width()) ))
#else
|| (fontMetrics.horizontalAdvance(lastLine) < cr.width()) ))
#endif
{
//No more text for next line so this one is OK //No more text for next line so this one is OK
lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y))); lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y)));
elidedLastLine=""; elidedLastLine="";
@ -176,13 +190,17 @@ bool ElidedLabel::paintElidedLine(QPainter& painter,QString plainText,const QRec
//Now we know how many lines to redraw at good position //Now we know how many lines to redraw at good position
foreach (pair, lLines){ foreach (pair, lLines){
lastPos = pair.second + QPoint(0+ cr.left(), iTransY + cr.top()); lastPos = pair.second + QPoint(0+ cr.left(), iTransY + cr.top());
pair.first.draw(&painter, lastPos); if (painter) pair.first.draw(painter, lastPos);
} }
//Print last elided line //Print last elided line
if (didElide) if (didElide)
{ {
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
int width = fontMetrics.width(elidedLastLine); int width = fontMetrics.width(elidedLastLine);
#else
int width = fontMetrics.horizontalAdvance(elidedLastLine);
#endif
if (lastPos.y() == -1){ if (lastPos.y() == -1){
y = iTransY;// Only one line y = iTransY;// Only one line
} else { } else {
@ -200,26 +218,32 @@ bool ElidedLabel::paintElidedLine(QPainter& painter,QString plainText,const QRec
iTransX = 0; iTransX = 0;
} }
if(width+iTransX+cr.left() <= cr.right()) if(width+iTransX+cr.left() <= cr.right())
painter.drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine); if (painter)
{
painter->setFont(useFont);
painter->drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine);
}
//Draw button to get ToolTip //Draw button to get ToolTip
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
int fontWidth = fontMetrics.width(ellipsisChar);
#else
int fontWidth = fontMetrics.horizontalAdvance(ellipsisChar);
#endif
QRect mRectElision = QRect( iTransX + width - fontWidth + cr.left()
, y + cr.top()
, fontWidth
, fontMetrics.height() - 1);
if (rectElision)
*rectElision = mRectElision;
if(drawRoundRect) if(drawRoundedRect)
{ if (painter) painter->drawRoundedRect(mRectElision, 2 , 2);
rectElision = QRect(iTransX + width - fontMetrics.width(ellipsisChar) + cr.left()
, y + cr.top()
, fontMetrics.width(ellipsisChar)
, fontMetrics.height() - 1);
painter.drawRoundRect(rectElision);
}
else
rectElision = QRect();
} }
else
rectElision = QRect();
return didElide;
if (painter) painter->restore();
return didElide;
} }
void ElidedLabel::mousePressEvent(QMouseEvent *ev) void ElidedLabel::mousePressEvent(QMouseEvent *ev)

View File

@ -48,7 +48,23 @@ public:
QColor textColor() const { return mTextColor; } QColor textColor() const { return mTextColor; }
void setTextColor(const QColor &color); void setTextColor(const QColor &color);
static bool paintElidedLine(QPainter& painter, QString plainText, const QRect &cr, Qt::Alignment alignment, bool wordWrap, bool drawRoundRect, QRect &rectElision); /**
* @brief paintElidedLine: Draw elided() line to a painter.
* @param painter: wher to paint line. If null, only calculate rectElision.
* painter pen have to be setted before. This doesn't paint background.
* @param plainText: Plain text to paint.
* @param cr: Area where to paint. If too close, text is elided.
* @param font: Font to use to pain text.
* @param alignment: Which alignement to use for text.
* @param wordWrap: If it elide by char or by word.
* @param drawRoundRect: If rounded rect around is need. To notice user he can click on it.
* @param rectElision: Where elision occurs. To manage click. Can be omitted.
* @return If text need to be elided.
*/
static bool paintElidedLine( QPainter* painter, QString plainText
, const QRect& cr, QFont font
, Qt::Alignment alignment,bool wordWrap
, bool drawRoundedRect,QRect* rectElision = nullptr);
public slots: public slots:
void setText(const QString &text); void setText(const QString &text);

View File

@ -145,6 +145,48 @@ QIcon FilesDefs::getIconFromQtResourcePath(const QString& resource_path)
return icon; return icon;
} }
QIcon FilesDefs::getIconFromGxsIdCache(const RsGxsId& id,const QIcon& setIcon, bool& exist)
{
static std::map<RsGxsId,QIcon> mIconCache;
exist = false;
QIcon icon;
#ifdef DEBUG_FILESDEFS
std::cerr << "Creating Icon from id " << id.toStdString() ;
#endif
if (setIcon.isNull())
{
if (id.isNull())
return getIconFromQtResourcePath(":/icons/notification.png");
auto item = mIconCache.find(id);
if (item == mIconCache.end())
{
#ifdef DEBUG_FILESDEFS
std::cerr << " Not in cache. And not setted." << std::endl;
#endif
icon = getIconFromQtResourcePath(":/icons/png/anonymous.png");
}
else
{
#ifdef DEBUG_FILESDEFS
std::cerr << " In cache. " << std::endl;
#endif
icon = item->second;
exist = true;
}
}
else
{
#ifdef DEBUG_FILESDEFS
std::cerr << " Have to set it." << std::endl;
#endif
icon = setIcon;
mIconCache[id] = icon;
}
return icon;
}
QIcon FilesDefs::getIconFromFileType(const QString& filename) QIcon FilesDefs::getIconFromFileType(const QString& filename)
{ {
return getIconFromQtResourcePath(getInfoFromFilename(filename,true,true)); return getIconFromQtResourcePath(getInfoFromFilename(filename,true,true));

View File

@ -24,6 +24,8 @@
#include <QString> #include <QString>
#include <QIcon> #include <QIcon>
#include "retroshare/rsids.h"
class FilesDefs class FilesDefs
{ {
public: public:
@ -35,6 +37,7 @@ public:
static QIcon getIconFromQtResourcePath(const QString& resource_path); static QIcon getIconFromQtResourcePath(const QString& resource_path);
static QPixmap getPixmapFromQtResourcePath(const QString& resource_path); static QPixmap getPixmapFromQtResourcePath(const QString& resource_path);
static QIcon getIconFromGxsIdCache(const RsGxsId& id, const QIcon& setIcon, bool& exist);
// This method returns a QIcon that is suitable to represent a file of a particular type (image, movie, etc.) // This method returns a QIcon that is suitable to represent a file of a particular type (image, movie, etc.)

View File

@ -20,170 +20,229 @@
#include "RSElidedItemDelegate.h" #include "RSElidedItemDelegate.h"
#include "gui/common/StyledElidedLabel.h"
#include "util/rsdebug.h"
#include <QApplication>
#include <QPainter> #include <QPainter>
#include <QTextDocument> #include <QTextDocument>
#include <QTextLayout> #include <QTextLayout>
#include <QToolTip> #include <QToolTip>
RSElidedItemDelegate::RSElidedItemDelegate(QObject *parent) RSElidedItemDelegate::RSElidedItemDelegate(QObject *parent)
: RSItemDelegate(parent) : RSStyledItemDelegate(parent)
, mElided(false) , mOnlyPlainText(false), mPaintRoundedRect(true)
, mOnlyPlainText(false)
, mContent("")
{ {
mRectElision = QRect(); }
QSize RSElidedItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem ownOption (option);
initStyleOption(&ownOption, index);
const QWidget* widget = option.widget;
QStyle* ownStyle = widget ? widget->style() : QApplication::style();
//Only need "…" for text
ownOption.text = "";
QRect checkRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &ownOption, widget);
QRect iconRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemDecoration, &ownOption, widget);
QRect textRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemText, &ownOption, widget);
QSize contSize = ownStyle->sizeFromContents( QStyle::CT_ItemViewItem,&ownOption
,QSize( checkRect.width()+iconRect.width()+textRect.width()
,qMax(checkRect.height(),qMax(iconRect.height(),textRect.height()))),widget);
return contSize;
} }
void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{ {
RSItemDelegate::paint(painter, option, index); if(!index.isValid())
}
void RSElidedItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
const QRect &rect, const QString &text) const
{
if (!text.isEmpty())
{ {
mContent = text; RsErr() << __PRETTY_FUNCTION__ << " attempt to draw an invalid index." << std::endl;
QList<QPair<QTextLine,QPoint> > lLines; return ;
QString elidedLastLine = "";
QFontMetrics fontMetrics = option.fontMetrics;
QRect cr = rect;
cr.adjust(spacing().width(), spacing().height(), -spacing().width(), -spacing().height());
bool didElide = false;
QChar ellipsisChar(0x2026);//= "…"
int lineSpacing = fontMetrics.lineSpacing();
int y = 0;
QString plainText = "";
if (mOnlyPlainText)
{
plainText = mContent;
} else {
QTextDocument td;
td.setHtml(mContent);
plainText = td.toPlainText();
}
plainText = plainText.replace("\n",QChar(QChar::LineSeparator));
plainText = plainText.replace("\r",QChar(QChar::LineSeparator));
if (painter) {
painter->setFont(option.font);
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
cg = QPalette::Inactive;
QColor textColor = option.palette.color(cg, QPalette::Text);
painter->setPen(textColor);
}
QTextLayout textLayout(plainText, option.font);
QTextOption to = textLayout.textOption();
to.setAlignment(option.displayAlignment);
#if QT_VERSION >= 0x050000
bool wordWrap = option.features.testFlag(QStyleOptionViewItem::WrapText);
#else
bool wordWrap = false;
#endif
to.setWrapMode(wordWrap ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::NoWrap);
textLayout.setTextOption(to);
textLayout.beginLayout();
forever {
//Get new line for text.
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;// No more line to write
line.setLineWidth(cr.width());
int nextLineY = y + lineSpacing;
if ((cr.height() >= nextLineY + lineSpacing) && wordWrap) {
//Line written normaly, next line will too
lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y)));
y = nextLineY;
} else {
//The next line can't be written.
QString lastLine = plainText.mid(line.textStart()).split(QChar(QChar::LineSeparator)).at(0);
QTextLine lineEnd = textLayout.createLine();
if (!lineEnd.isValid() && (wordWrap
|| (fontMetrics.width(lastLine) < cr.width()))) {
//No more text for next line so this one is OK
lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y)));
elidedLastLine="";
didElide = false;
} else {
//Text is left, so get elided text
if (lastLine == "") {
elidedLastLine = ellipsisChar;
} else {
elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, cr.width()-1);
if (elidedLastLine.right(1) != ellipsisChar)
elidedLastLine.append(ellipsisChar);//New line at end
}
didElide = true;
break;
}
}
}
textLayout.endLayout();
int iTransX, iTransY = iTransX = 0;
int iHeight = lLines.count() * lineSpacing;
if (didElide) iHeight += lineSpacing;
//Compute lines translation with alignment
if (option.displayAlignment & Qt::AlignTop)
iTransY = 0;
if (option.displayAlignment & Qt::AlignBottom)
iTransY = cr.height() - iHeight;
if (option.displayAlignment & Qt::AlignVCenter)
iTransY = (cr.height() - iHeight) / 2;
QPair<QTextLine,QPoint> pair;
QPoint lastPos(-1,-1);
//Now we know how many lines to redraw at good position
foreach (pair, lLines){
lastPos = pair.second + QPoint(0 + cr.left(), iTransY + cr.top());
if (painter) pair.first.draw(painter, lastPos);
}
//Print last elided line
if (didElide) {
int width = fontMetrics.width(elidedLastLine);
if (lastPos.y() == -1){
y = iTransY;// Only one line
} else {
y = lastPos.y() + lineSpacing;
}
if (width < cr.width()){
//Text don't taking all line (with line break), so align it
if (option.displayAlignment & Qt::AlignLeft)
iTransX = 0;
if (option.displayAlignment & Qt::AlignRight)
iTransX = cr.width() - width;
if (option.displayAlignment & Qt::AlignHCenter)
iTransX = (cr.width() - width) / 2;
if (option.displayAlignment & Qt::AlignJustify)
iTransX = 0;
}
if (painter) painter->drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine);
//Draw button to get ToolTip
mRectElision = QRect(iTransX + width - fontMetrics.width(ellipsisChar) + cr.left()
, y + cr.top()
, fontMetrics.width(ellipsisChar)
, fontMetrics.height() - 1);
if (painter) painter->drawRoundRect(mRectElision);
} else {
mRectElision = QRect();
}
mElided = didElide;
} }
painter->save();
// To draw with default for debug purpose
//QStyledItemDelegate::paint(painter, option, index);
QStyleOptionViewItem ownOption (option);
initStyleOption(&ownOption, index);
//Prefer use icon from option
if (!option.icon.isNull())
ownOption.icon = option.icon;
const QWidget* widget = option.widget;
QStyle* ownStyle = widget ? widget->style() : QApplication::style();
if (!mOnlyPlainText)
{
QTextDocument td;
td.setHtml(ownOption.text);
ownOption.text = td.toPlainText();
}
//Get Font as option.font is not accurate
if (index.data(Qt::FontRole).type() == QVariant::Font) {
QFont font = index.data(Qt::FontRole).value<QFont>();
ownOption.font = font;
ownOption.fontMetrics = QFontMetrics(font);
}
QColor textColor;
if (index.data(Qt::TextColorRole).canConvert(QMetaType::QColor)) {
textColor = QColor(index.data(Qt::TextColorRole).toString());//Needs to pass from string else loose RBG format.
}
if (index.data(Qt::BackgroundRole).canConvert(QMetaType::QBrush)) {
QBrush brush(index.data(Qt::BackgroundRole).convert(QMetaType::QBrush));
ownOption.backgroundBrush = brush;
}
//Code from: https://code.woboq.org/qt5/qtbase/src/widgets/styles/qcommonstyle.cpp.html#2271
QRect checkRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &ownOption, widget);
QRect iconRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemDecoration, &ownOption, widget);
QRect textRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemText, &ownOption, widget);
// draw the background
ownStyle->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, widget);
// draw the check mark
if (ownOption.features & QStyleOptionViewItem::HasCheckIndicator) {
QStyleOptionViewItem option(*&ownOption);
option.rect = checkRect;
option.state = option.state & ~QStyle::State_HasFocus;
switch (ownOption.checkState) {
case Qt::Unchecked:
option.state |= QStyle::State_Off;
break;
case Qt::PartiallyChecked:
option.state |= QStyle::State_NoChange;
break;
case Qt::Checked:
option.state |= QStyle::State_On;
break;
}
ownStyle->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget);
}
// 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);
}
// draw the text
if (!ownOption.text.isEmpty()) {
QPalette::ColorGroup cg = ownOption.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (cg == QPalette::Normal && !(ownOption.state & QStyle::State_Active))
cg = QPalette::Inactive;
if (ownOption.state & QStyle::State_Selected) {
painter->setPen(ownOption.palette.color(cg, QPalette::HighlightedText));
} else {
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
// So we print default in image and get it's color...
QSize moSize=sizeHint(option,index);
QImage moImg(moSize,QImage::Format_ARGB32);
QPainter moPnt;
moPnt.begin(&moImg);
moPnt.setPen(Qt::black);//Fill Image with Black
moPnt.setBrush(Qt::black);
moPnt.drawRect(moImg.rect());
QStyleOptionViewItem moOption (option);
// Define option to get only what we want
{
moOption.rect = QRect(QPoint(0,0),moSize);
moOption.state = QStyle::State_MouseOver | QStyle::State_Enabled | QStyle::State_Sibling;
moOption.text = "████████████████";
// Remove unwanted info. Yes it can draw without that all public data ...
moOption.backgroundBrush = QBrush();
moOption.checkState = Qt::Unchecked;
moOption.decorationAlignment = Qt::AlignLeft;
moOption.decorationPosition = QStyleOptionViewItem::Left;
moOption.decorationSize = QSize();
moOption.displayAlignment = Qt::AlignLeft | Qt::AlignTop;
moOption.features=0;
moOption.font = QFont();
moOption.icon = QIcon();
moOption.index = QModelIndex();
moOption.locale = QLocale();
moOption.showDecorationSelected = false;
moOption.textElideMode = Qt::ElideNone;
moOption.viewItemPosition = QStyleOptionViewItem::Middle;
//moOption.widget = nullptr; //Needed.
moOption.direction = Qt::LayoutDirectionAuto;
moOption.fontMetrics = QFontMetrics(QFont());
moOption.palette = QPalette();
moOption.styleObject = nullptr;
}
QStyledItemDelegate::paint(&moPnt, moOption, QModelIndex());
//// But these lines doesn't works.
{
//QStyleOptionViewItem moOptionsState;
//moOptionsState.initFrom(moOption.widget);
//moOptionsState.rect = QRect(QPoint(0,0),moSize);
//moOptionsState.state = QStyle::State_MouseOver | QStyle::State_Enabled | QStyle::State_Sibling;
//moOptionsState.text = "████████";
//moOptionsState.widget = option.widget;
//QStyledItemDelegate::paint(&moPnt, moOptionsState, QModelIndex());
}
moPnt.end();
// To save what it paint
//moImg.save("image.bmp");
// Get Color in this black rect.
QColor moColor;
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) == moColorBorder)
moColor = QColor(moImg.pixelColor(x,y).name());
else
{
if (moColorBorder.spec() == QColor::Invalid)
{
// First pixel border move inside
x+=5;
y+=5;
}
moColorBorder = QColor(moImg.pixelColor(x,y).name());
}
}
// If not found color is black too.
if (moColor.spec() == QColor::Invalid)
moColor = Qt::black;
painter->setPen(moColor);
}
else
if (textColor.spec()==QColor::Invalid) {
painter->setPen(ownOption.palette.color(cg, QPalette::Text));
} else { //Only get color from index for unselected(as Qt does)
painter->setPen(textColor);
}
}
if (ownOption.state & QStyle::State_Editing) {
painter->setPen(ownOption.palette.color(cg, QPalette::Text));
painter->drawRect(textRect.adjusted(0, 0, -1, -1));
}
//d->viewItemDrawText(p, &ownOption, textRect);
QTextLayout textLayout(ownOption.text, painter->font());
QTextOption to = textLayout.textOption();
StyledElidedLabel::paintElidedLine(painter,ownOption.text,textRect,ownOption.font,ownOption.displayAlignment,to.wrapMode()&QTextOption::WordWrap,mPaintRoundedRect);
}
painter->restore();
} }
bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
@ -192,38 +251,39 @@ bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
QMouseEvent *ev = static_cast<QMouseEvent *>(event); QMouseEvent *ev = static_cast<QMouseEvent *>(event);
if (ev) { if (ev) {
if (ev->buttons()==Qt::LeftButton) { if (ev->buttons()==Qt::LeftButton) {
QVariant var = index.data();
if (index.data().type() == QVariant::String) { if (index.data().type() == QVariant::String) {
QString text = index.data().toString(); QString text = index.data().toString();
if (!text.isEmpty()) { if (!text.isEmpty()) {
QRect rect = option.rect;
//Get decoration Rect to get rect == to rect sent in drawDisplay QStyleOptionViewItem ownOption (option);
if (index.data(Qt::DecorationRole).type() == QVariant::Pixmap) { initStyleOption(&ownOption, index);
QPixmap pixmap = index.data(Qt::DecorationRole).value<QPixmap>();
if (!pixmap.isNull()) rect.adjust(pixmap.width() + 6,0,0,0);//Don't know where come from these 6 pixels... const QWidget* widget = option.widget;
} QStyle* ownStyle = widget ? widget->style() : QApplication::style();
if (index.data(Qt::DecorationRole).type() == QVariant::Image) {
QImage image = index.data(Qt::DecorationRole).value<QImage>(); if (!mOnlyPlainText)
if (!image.isNull()) rect.adjust(image.width() + 6,0,0,0);//Don't know where come from these 6 pixels... {
} QTextDocument td;
if (index.data(Qt::DecorationRole).type() == QVariant::Icon) { td.setHtml(ownOption.text);
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>(); ownOption.text = td.toPlainText();
if (!icon.isNull()) {
QSize size = icon.actualSize(rect.size());
rect.adjust(size.width() + 6,0,0,0);//Don't know where come from these 6 pixels...
}
} }
//Get Font as option.font is not accurate //Get Font as option.font is not accurate
QStyleOptionViewItem newOption = option;
if (index.data(Qt::FontRole).type() == QVariant::Font) { if (index.data(Qt::FontRole).type() == QVariant::Font) {
QFont font = index.data(Qt::FontRole).value<QFont>(); QFont font = index.data(Qt::FontRole).value<QFont>();
newOption.font = font; ownOption.font = font;
newOption.fontMetrics = QFontMetrics(font); ownOption.fontMetrics = QFontMetrics(font);
} }
QRect textRect = ownStyle->subElementRect(QStyle::SE_ItemViewItemText, &ownOption, widget);
QTextLayout textLayout(text, ownOption.font);
QTextOption to = textLayout.textOption();
//Update RSElidedItemDelegate as only one delegate for all items //Update RSElidedItemDelegate as only one delegate for all items
drawDisplay(NULL, newOption, rect, text); QRect rectElision;
if (mElided && (mRectElision.contains(ev->pos()))){ bool elided = StyledElidedLabel::paintElidedLine(nullptr,text,textRect,ownOption.font,ownOption.displayAlignment,to.wrapMode()&QTextOption::WordWrap,true,&rectElision);
QToolTip::showText(ev->globalPos(),QString("<FONT>") + mContent + QString("</FONT>")); if (elided && (rectElision.contains(ev->pos()))){
QToolTip::showText(ev->globalPos(),QString("<FONT>") + text + QString("</FONT>"));
return true; // eat event return true; // eat event
} }
} }
@ -231,5 +291,5 @@ bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
} }
} }
} }
return RSItemDelegate::editorEvent(event, model, option, index); return RSStyledItemDelegate::editorEvent(event, model, option, index);
} }

View File

@ -23,36 +23,32 @@
#include <gui/common/RSItemDelegate.h> #include <gui/common/RSItemDelegate.h>
class RSElidedItemDelegate : public RSItemDelegate class RSElidedItemDelegate : public RSStyledItemDelegate
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool isElided READ isElided)
Q_PROPERTY(bool isOnlyPlainText READ isOnlyPlainText WRITE setOnlyPlainText) Q_PROPERTY(bool isOnlyPlainText READ isOnlyPlainText WRITE setOnlyPlainText)
Q_PROPERTY(QRect rectElision READ rectElision) Q_PROPERTY(bool paintRoundedRect READ paintRoundedRect WRITE setPaintRoundedRect)
public: public:
RSElidedItemDelegate(QObject *parent = 0); RSElidedItemDelegate(QObject *parent = 0);
void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool isElided() const { return mElided; }
bool isOnlyPlainText() const { return mOnlyPlainText; } bool isOnlyPlainText() const { return mOnlyPlainText; }
void setOnlyPlainText(const bool &value) { mOnlyPlainText = value; } void setOnlyPlainText(const bool &value) { mOnlyPlainText = value; }
QRect rectElision() { return mRectElision; } bool paintRoundedRect() const { return mPaintRoundedRect; }
void setPaintRoundedRect(const bool &value) { mPaintRoundedRect = value; }
protected: protected:
void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
const QRect &rect, const QString &text) const;
bool editorEvent(QEvent *event, bool editorEvent(QEvent *event,
QAbstractItemModel *model, QAbstractItemModel *model,
const QStyleOptionViewItem &option, const QStyleOptionViewItem &option,
const QModelIndex &index); const QModelIndex &index) override;
private: private:
mutable bool mElided;
bool mOnlyPlainText; bool mOnlyPlainText;
mutable QString mContent; bool mPaintRoundedRect;
mutable QRect mRectElision;
}; };

View File

@ -19,6 +19,7 @@
*******************************************************************************/ *******************************************************************************/
#include "RSItemDelegate.h" #include "RSItemDelegate.h"
#include "util/rsdebug.h"
RSItemDelegate::RSItemDelegate(QObject *parent) : QItemDelegate(parent) RSItemDelegate::RSItemDelegate(QObject *parent) : QItemDelegate(parent)
{ {
@ -61,3 +62,48 @@ void RSItemDelegate::setSpacing(const QSize &spacing)
{ {
m_spacing = spacing; m_spacing = spacing;
} }
/** RSStyledItemDelegate **/
RSStyledItemDelegate::RSStyledItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
}
void RSStyledItemDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem ownOption (option);
if (m_noFocusRect.indexOf(index.column()) >= 0) {
ownOption.state &= ~QStyle::State_HasFocus; // don't show text and focus rectangle
}
QStyledItemDelegate::paint (painter, ownOption, index);
}
QSize RSStyledItemDelegate::sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem ownOption (option);
if (m_noFocusRect.indexOf(index.column()) >= 0) {
ownOption.state &= ~QStyle::State_HasFocus; // don't show text and focus rectangle
}
QSize size = QStyledItemDelegate::sizeHint(ownOption, index);
size += m_spacing;
return size;
}
void RSStyledItemDelegate::removeFocusRect(int column)
{
if (m_noFocusRect.indexOf(column) == -1) {
m_noFocusRect.push_back(column);
}
}
void RSStyledItemDelegate::setSpacing(const QSize &spacing)
{
m_spacing = spacing;
}

View File

@ -22,14 +22,32 @@
#define _RSITEMDELEGATE_H #define _RSITEMDELEGATE_H
#include <QItemDelegate> #include <QItemDelegate>
#include <QStyledItemDelegate>
class RSItemDelegate : public QItemDelegate class RSItemDelegate : public QItemDelegate
{ {
public: public:
RSItemDelegate(QObject *parent = 0); RSItemDelegate(QObject *parent = nullptr);
void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void removeFocusRect(int column);
void setSpacing(const QSize &spacing);
QSize spacing() const { return m_spacing; }
private:
QList<int> m_noFocusRect;
QSize m_spacing;
};
class RSStyledItemDelegate : public QStyledItemDelegate
{
public:
RSStyledItemDelegate(QObject *parent = nullptr);
void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void removeFocusRect(int column); void removeFocusRect(int column);
void setSpacing(const QSize &spacing); void setSpacing(const QSize &spacing);

View File

@ -27,7 +27,7 @@
/** Constructor */ /** Constructor */
GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask,bool auto_tooltip,QTreeWidget *parent) GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask,bool auto_tooltip,QTreeWidget *parent)
: QObject(NULL), RSTreeWidgetItem(compareRole, parent), mColumn(0), mIconTypeMask(icon_mask),mAutoTooltip(auto_tooltip) : QObject(NULL), RSTreeWidgetItem(compareRole, parent), mColumn(0), mAutoTooltip(auto_tooltip), mIconTypeMask(icon_mask)
{ {
init(); init();
} }
@ -35,8 +35,8 @@ GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *
void GxsIdRSTreeWidgetItem::init() void GxsIdRSTreeWidgetItem::init()
{ {
mIdFound = false; mIdFound = false;
mBannedState = false ;
mRetryWhenFailed = false; mRetryWhenFailed = false;
mBannedState = false ;
} }
static void fillGxsIdRSTreeWidgetItemCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/) static void fillGxsIdRSTreeWidgetItemCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/)
@ -179,101 +179,41 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
return RSTreeWidgetItem::data(column, role); return RSTreeWidgetItem::data(column, role);
} }
QSize GxsIdTreeItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
RsGxsId id(index.data(Qt::UserRole).toString().toStdString());
if(id.isNull())
return QStyledItemDelegate::sizeHint(option,index);
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
// disable default icon
opt.icon = QIcon();
const QRect r = option.rect;
QString str;
QList<QIcon> icons;
QString comment;
QFontMetricsF fm(option.font);
float f = fm.height();
QIcon icon ;
if(!GxsIdDetails::MakeIdDesc(id, true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR))
{
icon = GxsIdDetails::getLoadingIcon(id);
launchAsyncLoading();
}
else
icon = *icons.begin();
QPixmap pix = icon.pixmap(r.size());
return QSize(1.2*(pix.width() + fm.width(str)),std::max(1.1*pix.height(),1.4*fm.height()));
}
void GxsIdTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const void GxsIdTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const
{ {
if(!index.isValid()) if(!index.isValid())
{ {
std::cerr << "(EE) attempt to draw an invalid index." << std::endl; RsErr() << __PRETTY_FUNCTION__ << " attempt to draw an invalid index." << std::endl;
return ; return ;
} }
QStyleOptionViewItem ownOption (option);
initStyleOption(&ownOption, index);
RsGxsId id(index.data(Qt::UserRole).toString().toStdString()); RsGxsId id(index.data(Qt::UserRole).toString().toStdString());
QString cmt;
if(id.isNull())
return QStyledItemDelegate::paint(painter,option,index);
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
// disable default icon
opt.icon = QIcon();
// draw default item
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
QRect r = option.rect;
QString str;
QString comment;
QFontMetricsF fm(painter->font());
float f = fm.height();
QIcon icon ;
if(id.isNull()) if(id.isNull())
{ {
str = tr("[Notification]"); if (ownOption.icon.isNull())
icon = QIcon(":/icons/notification.png"); ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/notification.png");
} }
else if(! computeNameIconAndComment(id,str,icon,comment)) else
if(mReloadPeriod > 3) {
if(! computeNameIconAndComment(id,ownOption.text,ownOption.icon,cmt))
{ {
str = tr("[Unknown]"); if(mReloadPeriod > 3)
icon = QIcon(":/icons/anonymous.png"); {
} ownOption.text = tr("[Unknown]");
else ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/png/anonymous.png");
{ }
icon = GxsIdDetails::getLoadingIcon(id); else
launchAsyncLoading(); {
ownOption.icon = GxsIdDetails::getLoadingIcon(id);
launchAsyncLoading();
}
} }
}
QRect pixmaprect(r); RSElidedItemDelegate::paint(painter,ownOption,index);
pixmaprect.adjust(r.height(),0,0,0);
QPixmap pix = icon.pixmap(pixmaprect.size());
const QPoint p = QPoint(r.height()/2.0, (r.height() - pix.height())/2);
// draw pixmap at center of item
painter->drawPixmap(r.topLeft() + p, pix);
QRect mRectElision;
r.adjust(pix.height()+f,(r.height()-f)/2.0,0,0);
bool didElide = ElidedLabel::paintElidedLine(*painter,str,r,Qt::AlignLeft,false,false,mRectElision);
} }

View File

@ -27,8 +27,10 @@
#include "retroshare/rsidentity.h" #include "retroshare/rsidentity.h"
#include "retroshare/rspeers.h" #include "retroshare/rspeers.h"
#include "gui/common/FilesDefs.h"
#include "gui/common/RSTreeWidgetItem.h" #include "gui/common/RSTreeWidgetItem.h"
#include "gui/common/ElidedLabel.h" #include "gui/common/RSElidedItemDelegate.h"
#include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/GxsIdDetails.h"
/***** /*****
@ -70,7 +72,7 @@ private:
bool mIdFound; bool mIdFound;
bool mBannedState ; bool mBannedState ;
bool mRetryWhenFailed; bool mRetryWhenFailed;
bool mAutoTooltip; bool mAutoTooltip;
RsReputationLevel mReputationLevel; RsReputationLevel mReputationLevel;
uint32_t mIconTypeMask; uint32_t mIconTypeMask;
RsGxsImage mAvatar; RsGxsImage mAvatar;
@ -78,18 +80,17 @@ private:
// This class is responsible of rendering authors of type RsGxsId in tree views. Used in forums, messages, etc. // This class is responsible of rendering authors of type RsGxsId in tree views. Used in forums, messages, etc.
class GxsIdTreeItemDelegate: public QStyledItemDelegate class GxsIdTreeItemDelegate: public RSElidedItemDelegate
{ {
Q_OBJECT Q_OBJECT
public: public:
GxsIdTreeItemDelegate() GxsIdTreeItemDelegate(QObject *parent = nullptr)
{ :RSElidedItemDelegate(parent), mLoading(false), mReloadPeriod(0)
mLoading = false; {
mReloadPeriod = 0; //setPaintRoudedRect(false);
} }
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
void launchAsyncLoading() const void launchAsyncLoading() const
@ -116,22 +117,27 @@ public:
return true; return true;
} }
static bool computeNameIconAndComment(const RsGxsId& id,QString& name,QIcon& icon,QString& comment) static bool computeNameIconAndComment(const RsGxsId& id,QString& name,QIcon& icon,QString& comment)
{ {
QList<QIcon> icons; QList<QIcon> icons;
bool exist = false;
if(rsPeers->isFriend(RsPeerId(id))) // horrible trick because some widgets still use locations as IDs (e.g. messages)
{ if(rsPeers->isFriend(RsPeerId(id))) // horrible trick because some widgets still use locations as IDs (e.g. messages)
{
name = QString::fromUtf8(rsPeers->getPeerName(RsPeerId(id)).c_str()) ; name = QString::fromUtf8(rsPeers->getPeerName(RsPeerId(id)).c_str()) ;
icon = QIcon(":/icons/avatar_128.png"); icon = FilesDefs::getIconFromQtResourcePath(":/icons/avatar_128.png");
} }
else if(!GxsIdDetails::MakeIdDesc(id, true, name, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR))
return false;
else else
icon = *icons.begin(); if(!GxsIdDetails::MakeIdDesc(id, true, name, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR))
return false;
else
icon = *icons.begin();
return true; FilesDefs::getIconFromGxsIdCache(id,icon,exist);
}
return true;
}
private slots: private slots:
void reload() { mLoading=false; emit commitData(NULL) ; } void reload() { mLoading=false; emit commitData(NULL) ; }

View File

@ -28,6 +28,7 @@
#include "util/HandleRichText.h" #include "util/HandleRichText.h"
#include "util/DateTime.h" #include "util/DateTime.h"
#include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/GxsIdDetails.h"
#include "gui/gxs/GxsIdTreeWidgetItem.h"
#include "GxsForumModel.h" #include "GxsForumModel.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxsforums.h" #include "retroshare/rsgxsforums.h"
@ -669,7 +670,16 @@ QVariant RsGxsForumModel::displayRole(const ForumModelPostEntry& fmpe,int col) c
} }
case COLUMN_THREAD_DISTRIBUTION: case COLUMN_THREAD_DISTRIBUTION:
case COLUMN_THREAD_AUTHOR: return QVariant(); case COLUMN_THREAD_AUTHOR:{
QString name;
RsGxsId id = RsGxsId(fmpe.mAuthorId.toStdString());
if(id.isNull())
return QVariant(tr("[Notification]"));
if(GxsIdTreeItemDelegate::computeName(id,name))
return name;
return QVariant(tr("[Unknown]"));
}
case COLUMN_THREAD_MSGID: return QVariant(); case COLUMN_THREAD_MSGID: return QVariant();
#ifdef TODO #ifdef TODO
if (filterColumn == COLUMN_THREAD_CONTENT) { if (filterColumn == COLUMN_THREAD_CONTENT) {
@ -700,12 +710,17 @@ QVariant RsGxsForumModel::userRole(const ForumModelPostEntry& fmpe,int col) cons
QVariant RsGxsForumModel::decorationRole(const ForumModelPostEntry& fmpe,int col) const QVariant RsGxsForumModel::decorationRole(const ForumModelPostEntry& fmpe,int col) const
{ {
if(col == COLUMN_THREAD_DISTRIBUTION) bool exist=false;
return QVariant(fmpe.mReputationWarningLevel); switch(col)
else if(col == COLUMN_THREAD_READ) {
return QVariant(fmpe.mMsgStatus); case COLUMN_THREAD_DISTRIBUTION:
else return QVariant(fmpe.mReputationWarningLevel);
return QVariant(); case COLUMN_THREAD_READ:
return QVariant(fmpe.mMsgStatus);
case COLUMN_THREAD_AUTHOR://Return icon as place holder.
return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.mAuthorId.toStdString()),QIcon(), exist);
}
return QVariant();
} }
const RsGxsGroupId& RsGxsForumModel::currentGroupId() const const RsGxsGroupId& RsGxsForumModel::currentGroupId() const

View File

@ -487,7 +487,16 @@ QVariant RsMessageModel::displayRole(const Rs::Msgs::MsgInfoSummary& fmpe,int co
} }
return text; return text;
} }
case COLUMN_THREAD_AUTHOR: return QVariant(); case COLUMN_THREAD_AUTHOR:{
QString name;
RsGxsId id = RsGxsId(fmpe.srcId.toStdString());
if(id.isNull())
return QVariant(tr("[Notification]"));
if(GxsIdTreeItemDelegate::computeName(id,name))
return name;
return QVariant(tr("[Unknown]"));
}
default: default:
return QVariant("[ TODO ]"); return QVariant("[ TODO ]");
@ -510,42 +519,41 @@ QVariant RsMessageModel::userRole(const Rs::Msgs::MsgInfoSummary& fmpe,int col)
QVariant RsMessageModel::decorationRole(const Rs::Msgs::MsgInfoSummary& fmpe,int col) const QVariant RsMessageModel::decorationRole(const Rs::Msgs::MsgInfoSummary& fmpe,int col) const
{ {
if(col == COLUMN_THREAD_READ) bool exist=false;
if(fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER)) switch(col)
return FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png"); {
else case COLUMN_THREAD_READ:
return FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png"); return (fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER))
? FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")
: FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png");
case COLUMN_THREAD_SUBJECT:
{
if(fmpe.msgflags & RS_MSG_NEW ) return FilesDefs::getIconFromQtResourcePath(":/images/message-state-new.png");
if(fmpe.msgflags & RS_MSG_USER_REQUEST) return FilesDefs::getIconFromQtResourcePath(":/images/user/user_request16.png");
if(fmpe.msgflags & RS_MSG_FRIEND_RECOMMENDATION) return FilesDefs::getIconFromQtResourcePath(":/images/user/friend_suggestion16.png");
if(fmpe.msgflags & RS_MSG_PUBLISH_KEY) return FilesDefs::getIconFromQtResourcePath(":/images/share-icon-16.png");
if(col == COLUMN_THREAD_SUBJECT) if(fmpe.msgflags & RS_MSG_UNREAD_BY_USER)
{ {
if(fmpe.msgflags & RS_MSG_NEW ) return FilesDefs::getIconFromQtResourcePath(":/images/message-state-new.png"); if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_REPLIED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied.png");
if(fmpe.msgflags & RS_MSG_USER_REQUEST) return FilesDefs::getIconFromQtResourcePath(":/images/user/user_request16.png"); if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_FORWARDED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-forwarded.png");
if(fmpe.msgflags & RS_MSG_FRIEND_RECOMMENDATION) return FilesDefs::getIconFromQtResourcePath(":/images/user/friend_suggestion16.png"); if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == (RS_MSG_REPLIED | RS_MSG_FORWARDED)) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied-forw.png");
if(fmpe.msgflags & RS_MSG_PUBLISH_KEY) return FilesDefs::getIconFromQtResourcePath(":/images/share-icon-16.png");
if(fmpe.msgflags & RS_MSG_UNREAD_BY_USER) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail.png");
{ }
if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_REPLIED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied.png"); if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_REPLIED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied-read.png");
if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_FORWARDED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-forwarded.png"); if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_FORWARDED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-forwarded-read.png");
if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == (RS_MSG_REPLIED | RS_MSG_FORWARDED)) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied-forw.png"); if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == (RS_MSG_REPLIED | RS_MSG_FORWARDED)) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied-forw-read.png");
return FilesDefs::getIconFromQtResourcePath(":/images/message-mail.png"); return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-read.png");
} }
if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_REPLIED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied-read.png");
if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_FORWARDED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-forwarded-read.png");
if((fmpe.msgflags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == (RS_MSG_REPLIED | RS_MSG_FORWARDED)) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-replied-forw-read.png");
return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-read.png"); case COLUMN_THREAD_STAR:
} return FilesDefs::getIconFromQtResourcePath((fmpe.msgflags & RS_MSG_STAR) ? (IMAGE_STAR_ON ): (IMAGE_STAR_OFF));
if(col == COLUMN_THREAD_STAR)
return FilesDefs::getIconFromQtResourcePath((fmpe.msgflags & RS_MSG_STAR) ? (IMAGE_STAR_ON ): (IMAGE_STAR_OFF));
bool isNew = fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER);
if(col == COLUMN_THREAD_READ)
return FilesDefs::getIconFromQtResourcePath(isNew ? ":/images/message-state-unread.png": ":/images/message-state-read.png");
case COLUMN_THREAD_AUTHOR://Return icon as place holder.
return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.srcId.toStdString()),QIcon(), exist);
}
return QVariant(); return QVariant();
} }

View File

@ -147,11 +147,11 @@ MessagesDialog::MessagesDialog(QWidget *parent)
changeBox(0); // set to inbox changeBox(0); // set to inbox
ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_AUTHOR,new GxsIdTreeItemDelegate()) ;
RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this);
itemDelegate->setSpacing(QSize(0, 2)); itemDelegate->setSpacing(QSize(0, 2));
ui.messageTreeWidget->setItemDelegate(itemDelegate); ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_SUBJECT,itemDelegate);
ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_AUTHOR,new GxsIdTreeItemDelegate()) ;
// workaround for Qt bug, should be solved in next Qt release 4.7.0 // workaround for Qt bug, should be solved in next Qt release 4.7.0
// http://bugreports.qt.nokia.com/browse/QTBUG-8270 // http://bugreports.qt.nokia.com/browse/QTBUG-8270