mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-27 07:47:03 -05:00
Merge remote-tracking branch 'upstream/master' into pqihandlerOptim
This commit is contained in:
commit
7349f42154
@ -34,6 +34,7 @@
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "gui/chat/ChatDialog.h"
|
||||
#include "gui/Circles/CreateCircleDialog.h"
|
||||
#include "gui/common/FilesDefs.h"
|
||||
#include "gui/common/UIStateHelper.h"
|
||||
#include "gui/common/UserNotify.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_VOTES, 2 * fontWidth);
|
||||
|
||||
ui->idTreeWidget->setItemDelegateForColumn(
|
||||
RSID_COL_NICKNAME,
|
||||
new GxsIdTreeItemDelegate());
|
||||
ui->idTreeWidget->setItemDelegateForColumn(
|
||||
RSID_COL_VOTES,
|
||||
new ReputationItemDelegate(RsReputationLevel(0xff)));
|
||||
@ -638,7 +642,6 @@ void IdDialog::loadCircles(const std::list<RsGroupMetaData>& groupInfo)
|
||||
RsGxsCircleDetails details;
|
||||
rsGxsCircles->getCircleDetails(RsGxsCircleId(vit->mGroupId), details) ;
|
||||
|
||||
bool should_re_add = true ;
|
||||
bool am_I_in_circle = details.mAmIAllowed ;
|
||||
bool am_I_admin (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) ;
|
||||
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;
|
||||
#endif
|
||||
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 ;
|
||||
bool has_id = rsIdentity->getIdDetails(it->first,idd) ;
|
||||
//bool has_id =
|
||||
rsIdentity->getIdDetails(it->first,idd) ;
|
||||
|
||||
// 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.
|
||||
// Admin/non admin is shows using Bold font.
|
||||
|
||||
// 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.
|
||||
|
||||
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)
|
||||
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(IMAGE_INVITED)) ;
|
||||
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,FilesDefs::getIconFromQtResourcePath(IMAGE_INVITED)) ;
|
||||
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)
|
||||
{
|
||||
w->selectionModel()->clearSelection() ;
|
||||
|
||||
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);
|
||||
|
||||
foreach(QTreeWidgetItem* item, clist)
|
||||
item->setSelected(true) ;
|
||||
}
|
||||
}
|
||||
//static void mark_matching_tree(QTreeWidget *w, const std::set<RsGxsId>& members, int col)
|
||||
//{
|
||||
// w->selectionModel()->clearSelection() ;
|
||||
//
|
||||
// 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);
|
||||
//
|
||||
// foreach(QTreeWidgetItem* item, clist)
|
||||
// item->setSelected(true) ;
|
||||
// }
|
||||
//}
|
||||
|
||||
bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id)
|
||||
{
|
||||
@ -1252,7 +1258,7 @@ void IdDialog::updateIdList()
|
||||
ui->removeIdentity->setEnabled(false);
|
||||
ui->editIdentity->setEnabled(false);
|
||||
|
||||
int accept = filter;
|
||||
//int accept = filter;
|
||||
|
||||
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_KEYID, QString::fromStdString(data.mMeta.mGroupId.toStdString()));
|
||||
|
||||
item->setText(RSID_COL_NICKNAME, QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE));
|
||||
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)
|
||||
{
|
||||
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) ;
|
||||
}
|
||||
|
||||
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))
|
||||
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::SMALL) ;
|
||||
|
||||
item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
|
||||
|
||||
QString tooltip;
|
||||
QString tooltip;
|
||||
|
||||
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
|
||||
allItem->addChild(item);
|
||||
|
||||
GxsIdLabel *label = new GxsIdLabel();
|
||||
label->setId(RsGxsId(data.mMeta.mGroupId)) ;
|
||||
|
||||
ui->treeWidget_membership->setItemWidget(item,0,label) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include "ui_PostedItem.h"
|
||||
|
||||
#include <retroshare/rsposted.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define LINK_IMAGE ":/images/thumb-link.png"
|
||||
@ -46,20 +48,40 @@
|
||||
// BasePostedItem //
|
||||
//========================================================================================
|
||||
|
||||
BasePostedItem::BasePostedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData &group_meta, const RsGxsMessageId& post_id, bool isHome, bool autoUpdate) :
|
||||
GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, post_id, isHome, rsPosted, autoUpdate),
|
||||
mGroupMeta(group_meta)
|
||||
BasePostedItem::BasePostedItem( FeedHolder *feedHolder, uint32_t feedId
|
||||
, const RsGroupMetaData &group_meta, const RsGxsMessageId& post_id
|
||||
, bool isHome, bool autoUpdate)
|
||||
: GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, post_id, isHome, rsPosted, autoUpdate)
|
||||
, mInFill(false), mGroupMeta(group_meta)
|
||||
, mLoaded(false), mIsLoadingGroup(false), mIsLoadingMessage(false), mIsLoadingComment(false)
|
||||
{
|
||||
mPost.mMeta.mMsgId = post_id;
|
||||
mPost.mMeta.mGroupId = mGroupMeta.mGroupId;
|
||||
mLoaded = false;
|
||||
mPost.mMeta.mMsgId = post_id;
|
||||
mPost.mMeta.mGroupId = mGroupMeta.mGroupId;
|
||||
}
|
||||
|
||||
BasePostedItem::BasePostedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId& post_id, bool isHome, bool autoUpdate) :
|
||||
GxsFeedItem(feedHolder, feedId, groupId, post_id, isHome, rsPosted, autoUpdate)
|
||||
BasePostedItem::BasePostedItem( FeedHolder *feedHolder, uint32_t feedId
|
||||
, const RsGxsGroupId &groupId, const RsGxsMessageId& post_id
|
||||
, bool isHome, bool autoUpdate)
|
||||
: GxsFeedItem(feedHolder, feedId, groupId, post_id, isHome, rsPosted, autoUpdate)
|
||||
, mInFill(false)
|
||||
, mLoaded(false), mIsLoadingGroup(false), mIsLoadingMessage(false), mIsLoadingComment(false)
|
||||
{
|
||||
mPost.mMeta.mMsgId = post_id;
|
||||
mLoaded = false;
|
||||
mPost.mMeta.mMsgId = post_id;
|
||||
}
|
||||
|
||||
BasePostedItem::~BasePostedItem()
|
||||
{
|
||||
auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
|
||||
while( (mIsLoadingGroup || mIsLoadingMessage || mIsLoadingComment)
|
||||
&& std::chrono::steady_clock::now() < timeout)
|
||||
{
|
||||
RsDbg() << __PRETTY_FUNCTION__ << " is Waiting "
|
||||
<< (mIsLoadingGroup ? "Group " : "")
|
||||
<< (mIsLoadingMessage ? "Message " : "")
|
||||
<< (mIsLoadingComment ? "Comment " : "")
|
||||
<< "loading finished." << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
|
||||
void BasePostedItem::paintEvent(QPaintEvent *e)
|
||||
@ -96,6 +118,7 @@ bool BasePostedItem::setPost(const RsPostedPost &post, bool doFill)
|
||||
|
||||
void BasePostedItem::loadGroup()
|
||||
{
|
||||
mIsLoadingGroup = true;
|
||||
RsThread::async([this]()
|
||||
{
|
||||
// 1 - get group data
|
||||
@ -110,13 +133,14 @@ void BasePostedItem::loadGroup()
|
||||
if(!rsPosted->getBoardsInfo(groupIds,groups))
|
||||
{
|
||||
RsErr() << "GxsPostedGroupItem::loadGroup() ERROR getting data" << std::endl;
|
||||
mIsLoadingGroup = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (groups.size() != 1)
|
||||
{
|
||||
std::cerr << "GxsPostedGroupItem::loadGroup() Wrong number of Items";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "GxsPostedGroupItem::loadGroup() Wrong number of Items" << std::endl;
|
||||
mIsLoadingGroup = false;
|
||||
return;
|
||||
}
|
||||
RsPostedGroup group(groups[0]);
|
||||
@ -127,7 +151,8 @@ void BasePostedItem::loadGroup()
|
||||
* thread, for example to update the data model with new information
|
||||
* after a blocking call to RetroShare API complete */
|
||||
|
||||
mGroupMeta = group.mMeta;
|
||||
mGroupMeta = group.mMeta;
|
||||
mIsLoadingGroup = false;
|
||||
|
||||
}, this );
|
||||
});
|
||||
@ -135,6 +160,7 @@ void BasePostedItem::loadGroup()
|
||||
|
||||
void BasePostedItem::loadMessage()
|
||||
{
|
||||
mIsLoadingMessage = true;
|
||||
RsThread::async([this]()
|
||||
{
|
||||
// 1 - get group data
|
||||
@ -145,15 +171,16 @@ void BasePostedItem::loadMessage()
|
||||
if(! rsPosted->getBoardContent( groupId(), std::set<RsGxsMessageId>( { messageId() } ),posts,comments))
|
||||
{
|
||||
RsErr() << "BasePostedItem::loadMessage() ERROR getting data" << std::endl;
|
||||
mIsLoadingMessage = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (posts.size() == 1)
|
||||
{
|
||||
std::cerr << (void*)this << ": Obtained post, with msgId = " << posts[0].mMeta.mMsgId << std::endl;
|
||||
const RsPostedPost& post(posts[0]);
|
||||
const RsPostedPost& post(posts[0]);
|
||||
|
||||
RsQThreadUtils::postToObject( [post,this]() { setPost(post,true); }, this );
|
||||
RsQThreadUtils::postToObject( [post,this]() { setPost(post,true); mIsLoadingMessage = false;}, this );
|
||||
}
|
||||
else if(comments.size() == 1)
|
||||
{
|
||||
@ -162,21 +189,21 @@ void BasePostedItem::loadMessage()
|
||||
|
||||
RsQThreadUtils::postToObject( [cmt,this]()
|
||||
{
|
||||
setComment(cmt);
|
||||
setComment(cmt);
|
||||
|
||||
//Change this item to be uploaded with thread element.
|
||||
setMessageId(cmt.mMeta.mThreadId);
|
||||
requestMessage();
|
||||
|
||||
mIsLoadingMessage = false;
|
||||
}, this );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "GxsChannelPostItem::loadMessage() Wrong number of Items. Remove It.";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "GxsChannelPostItem::loadMessage() Wrong number of Items. Remove It." << std::endl;
|
||||
|
||||
RsQThreadUtils::postToObject( [this]() { removeItem(); }, this );
|
||||
RsQThreadUtils::postToObject( [this]() { removeItem(); mIsLoadingMessage = false;}, this );
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -188,7 +215,7 @@ void BasePostedItem::loadComment()
|
||||
std::cerr << "GxsChannelPostItem::loadComment()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mIsLoadingComment = true;
|
||||
RsThread::async([this]()
|
||||
{
|
||||
// 1 - get group data
|
||||
@ -204,15 +231,16 @@ void BasePostedItem::loadComment()
|
||||
if(! rsPosted->getBoardContent( groupId(),msgIds,posts,comments))
|
||||
{
|
||||
RsErr() << "BasePostedItem::loadGroup() ERROR getting data" << std::endl;
|
||||
mIsLoadingComment = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int comNb = comments.size();
|
||||
int comNb = comments.size();
|
||||
|
||||
RsQThreadUtils::postToObject( [comNb,this]()
|
||||
{
|
||||
setCommentsSize(comNb);
|
||||
|
||||
setCommentsSize(comNb);
|
||||
mIsLoadingComment = false;
|
||||
}, this );
|
||||
});
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class PostedItem;
|
||||
}
|
||||
|
||||
class FeedHolder;
|
||||
class RsPostedPost;
|
||||
struct RsPostedPost;
|
||||
|
||||
class BasePostedItem : public GxsFeedItem
|
||||
{
|
||||
@ -40,7 +40,7 @@ class BasePostedItem : public GxsFeedItem
|
||||
public:
|
||||
BasePostedItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId& messageId, bool isHome, bool autoUpdate);
|
||||
BasePostedItem(FeedHolder *parent, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId& post_id, bool isHome, bool autoUpdate);
|
||||
virtual ~BasePostedItem()=default;
|
||||
virtual ~BasePostedItem();
|
||||
|
||||
bool setPost(const RsPostedPost& post, bool doFill = true);
|
||||
|
||||
@ -64,15 +64,15 @@ protected:
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
|
||||
/* GxsGroupFeedItem */
|
||||
virtual QString groupName();
|
||||
virtual QString groupName() override;
|
||||
virtual void loadGroup() override;
|
||||
virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_UNKNOWN; }
|
||||
virtual RetroShareLink::enumType getLinkType() override { return RetroShareLink::TYPE_UNKNOWN; }
|
||||
|
||||
/* GxsFeedItem */
|
||||
virtual QString messageName();
|
||||
virtual QString messageName() override;
|
||||
|
||||
virtual void loadMessage();
|
||||
virtual void loadComment();
|
||||
virtual void loadMessage() override;
|
||||
virtual void loadComment() override;
|
||||
|
||||
bool mInFill;
|
||||
RsGroupMetaData mGroupMeta;
|
||||
@ -80,7 +80,7 @@ protected:
|
||||
|
||||
virtual void setup()=0;
|
||||
virtual void fill()=0;
|
||||
virtual void doExpand(bool open)=0;
|
||||
virtual void doExpand(bool open) override =0;
|
||||
virtual void setComment(const RsGxsComment&)=0;
|
||||
virtual void setReadStatus(bool isNew, bool isUnread)=0;
|
||||
virtual void setCommentsSize(int comNb)=0;
|
||||
@ -89,7 +89,10 @@ protected:
|
||||
virtual void toggleNotes()=0;
|
||||
|
||||
private:
|
||||
bool mLoaded;
|
||||
bool mLoaded;
|
||||
bool mIsLoadingGroup;
|
||||
bool mIsLoadingMessage;
|
||||
bool mIsLoadingComment;
|
||||
};
|
||||
|
||||
class PostedItem: public BasePostedItem
|
||||
|
@ -200,12 +200,14 @@ ChatWidget::ChatWidget(QWidget *parent)
|
||||
#endif
|
||||
|
||||
QMenu *menu = new QMenu();
|
||||
menu->addAction(ui->actionMessageHistory);
|
||||
menu->addMenu(fontmenu);
|
||||
menu->addSeparator();
|
||||
menu->addAction(ui->actionSaveChatHistory);
|
||||
menu->addAction(ui->actionClearChatHistory);
|
||||
menu->addAction(ui->actionDeleteChatHistory);
|
||||
menu->addAction(ui->actionSaveChatHistory);
|
||||
menu->addAction(ui->actionMessageHistory);
|
||||
|
||||
ui->pushtoolsButton->setMenu(menu);
|
||||
menu->addMenu(fontmenu);
|
||||
|
||||
ui->actionSendAsPlainText->setChecked(Settings->getChatSendAsPlainTextByDef());
|
||||
ui->chatTextEdit->setOnlyPlainText(ui->actionSendAsPlainText->isChecked());
|
||||
@ -1906,11 +1908,8 @@ void ChatWidget::updateCMPreview()
|
||||
|
||||
void ChatWidget::quote()
|
||||
{
|
||||
QString text = ui->textBrowser->textCursor().selection().toPlainText();
|
||||
QStringList sl = text.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
|
||||
text = sl.join("\n> ");
|
||||
text.replace(QChar(-4), " "); // Char used when image on text.
|
||||
emit ui->chatTextEdit->append(QString("> ") + text);
|
||||
QString text = RsHtml::makeQuotedText(ui->textBrowser);
|
||||
emit ui->chatTextEdit->append(text);
|
||||
}
|
||||
|
||||
void ChatWidget::dropPlacemark()
|
||||
|
@ -774,9 +774,12 @@ border-image: url(:/images/closepressed.png)
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Chat menu</p></body></html></string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/options2.png</normaloff>:/icons/png/options2.png</iconset>
|
||||
<normaloff>:/icons/png/menu.png</normaloff>:/icons/png/menu.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
|
@ -85,25 +85,32 @@ void ElidedLabel::paintEvent(QPaintEvent *event)
|
||||
td.setHtml(mContent);
|
||||
plainText = td.toPlainText();
|
||||
}
|
||||
QRect cr(contentsRect());
|
||||
QRect cr(contentsRect());
|
||||
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
|
||||
|
||||
if (didElide != mElided)
|
||||
{
|
||||
{
|
||||
mElided = 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;
|
||||
QString elidedLastLine = "";
|
||||
QFontMetrics fontMetrics = painter.fontMetrics();
|
||||
QFontMetrics fontMetrics = QFontMetrics(useFont);
|
||||
|
||||
bool didElide = false;
|
||||
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("\r",QChar(QChar::LineSeparator));
|
||||
|
||||
QTextLayout textLayout(plainText, painter.font());
|
||||
QTextLayout textLayout(plainText, useFont);
|
||||
QTextOption to = textLayout.textOption();
|
||||
to.setAlignment(alignment);
|
||||
to.setWrapMode(wordWrap ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::NoWrap);
|
||||
textLayout.setTextOption(to);
|
||||
|
||||
if (painter) painter->save();
|
||||
textLayout.beginLayout();
|
||||
forever {
|
||||
//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.
|
||||
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()))) {
|
||||
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
|
||||
lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y)));
|
||||
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
|
||||
foreach (pair, lLines){
|
||||
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
|
||||
if (didElide)
|
||||
{
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||
int width = fontMetrics.width(elidedLastLine);
|
||||
#else
|
||||
int width = fontMetrics.horizontalAdvance(elidedLastLine);
|
||||
#endif
|
||||
if (lastPos.y() == -1){
|
||||
y = iTransY;// Only one line
|
||||
} else {
|
||||
@ -200,26 +218,32 @@ bool ElidedLabel::paintElidedLine(QPainter& painter,QString plainText,const QRec
|
||||
iTransX = 0;
|
||||
}
|
||||
|
||||
if(width+iTransX+cr.left() <= cr.right())
|
||||
painter.drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine);
|
||||
if(width+iTransX+cr.left() <= cr.right())
|
||||
if (painter)
|
||||
{
|
||||
painter->setFont(useFont);
|
||||
painter->drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine);
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
rectElision = QRect(iTransX + width - fontMetrics.width(ellipsisChar) + cr.left()
|
||||
, y + cr.top()
|
||||
, fontMetrics.width(ellipsisChar)
|
||||
, fontMetrics.height() - 1);
|
||||
painter.drawRoundRect(rectElision);
|
||||
}
|
||||
else
|
||||
rectElision = QRect();
|
||||
if(drawRoundedRect)
|
||||
if (painter) painter->drawRoundedRect(mRectElision, 2 , 2);
|
||||
}
|
||||
else
|
||||
rectElision = QRect();
|
||||
|
||||
return didElide;
|
||||
|
||||
if (painter) painter->restore();
|
||||
return didElide;
|
||||
}
|
||||
|
||||
void ElidedLabel::mousePressEvent(QMouseEvent *ev)
|
||||
|
@ -48,7 +48,23 @@ public:
|
||||
QColor textColor() const { return mTextColor; }
|
||||
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:
|
||||
void setText(const QString &text);
|
||||
|
@ -145,6 +145,48 @@ QIcon FilesDefs::getIconFromQtResourcePath(const QString& resource_path)
|
||||
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)
|
||||
{
|
||||
return getIconFromQtResourcePath(getInfoFromFilename(filename,true,true));
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
|
||||
#include "retroshare/rsids.h"
|
||||
|
||||
class FilesDefs
|
||||
{
|
||||
public:
|
||||
@ -35,6 +37,7 @@ public:
|
||||
|
||||
static QIcon getIconFromQtResourcePath(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.)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -31,6 +31,7 @@ class MimeTextEdit : public RSTextEdit
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColorQuote READ textColorQuote WRITE setTextColorQuote)
|
||||
Q_PROPERTY(QVariant textColorQuotes READ textColorQuotes WRITE setTextColorQuotes)
|
||||
|
||||
public:
|
||||
MimeTextEdit(QWidget *parent = 0);
|
||||
@ -48,12 +49,14 @@ public:
|
||||
void addContextMenuAction(QAction *action);
|
||||
|
||||
QColor textColorQuote() const { return highliter->textColorQuote();}
|
||||
QVariant textColorQuotes() const { return highliter->textColorQuotes();}
|
||||
bool onlyPlainText() const {return mOnlyPlainText;}
|
||||
|
||||
void setMaxBytes(int limit) {mMaxBytes = limit;}
|
||||
|
||||
public slots:
|
||||
void setTextColorQuote(QColor textColorQuote) { highliter->setTextColorQuote(textColorQuote);}
|
||||
void setTextColorQuotes(QVariant textColorQuotes) { highliter->setTextColorQuotes(textColorQuotes);}
|
||||
void setOnlyPlainText(bool bOnlyPlainText) {mOnlyPlainText = bOnlyPlainText;}
|
||||
|
||||
signals:
|
||||
|
@ -20,170 +20,275 @@
|
||||
|
||||
#include "RSElidedItemDelegate.h"
|
||||
|
||||
#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)
|
||||
: RSItemDelegate(parent)
|
||||
, mElided(false)
|
||||
, mOnlyPlainText(false)
|
||||
, mContent("")
|
||||
: RSStyledItemDelegate(parent)
|
||||
, mOnlyPlainText(false), mPaintRoundedRect(true)
|
||||
{
|
||||
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
|
||||
{
|
||||
RSItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
void RSElidedItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QRect &rect, const QString &text) const
|
||||
{
|
||||
if (!text.isEmpty())
|
||||
if(!index.isValid())
|
||||
{
|
||||
mContent = text;
|
||||
QList<QPair<QTextLine,QPoint> > lLines;
|
||||
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;
|
||||
RsErr() << __PRETTY_FUNCTION__ << " attempt to draw an invalid index." << std::endl;
|
||||
return ;
|
||||
}
|
||||
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
|
||||
{
|
||||
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()) {
|
||||
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 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
|
||||
// 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 = " ████████████████";//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;
|
||||
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 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) != moBGColor)
|
||||
{
|
||||
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 same as BackGround.
|
||||
if (moColor.spec() == QColor::Invalid)
|
||||
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)
|
||||
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)
|
||||
@ -192,38 +297,39 @@ bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
|
||||
QMouseEvent *ev = static_cast<QMouseEvent *>(event);
|
||||
if (ev) {
|
||||
if (ev->buttons()==Qt::LeftButton) {
|
||||
QVariant var = index.data();
|
||||
if (index.data().type() == QVariant::String) {
|
||||
QString text = index.data().toString();
|
||||
if (!text.isEmpty()) {
|
||||
QRect rect = option.rect;
|
||||
//Get decoration Rect to get rect == to rect sent in drawDisplay
|
||||
if (index.data(Qt::DecorationRole).type() == QVariant::Pixmap) {
|
||||
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...
|
||||
}
|
||||
if (index.data(Qt::DecorationRole).type() == QVariant::Image) {
|
||||
QImage image = index.data(Qt::DecorationRole).value<QImage>();
|
||||
if (!image.isNull()) rect.adjust(image.width() + 6,0,0,0);//Don't know where come from these 6 pixels...
|
||||
}
|
||||
if (index.data(Qt::DecorationRole).type() == QVariant::Icon) {
|
||||
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>();
|
||||
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...
|
||||
}
|
||||
|
||||
QStyleOptionViewItem ownOption (option);
|
||||
initStyleOption(&ownOption, index);
|
||||
|
||||
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
|
||||
QStyleOptionViewItem newOption = option;
|
||||
if (index.data(Qt::FontRole).type() == QVariant::Font) {
|
||||
QFont font = index.data(Qt::FontRole).value<QFont>();
|
||||
newOption.font = font;
|
||||
newOption.fontMetrics = QFontMetrics(font);
|
||||
ownOption.font = 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
|
||||
drawDisplay(NULL, newOption, rect, text);
|
||||
if (mElided && (mRectElision.contains(ev->pos()))){
|
||||
QToolTip::showText(ev->globalPos(),QString("<FONT>") + mContent + QString("</FONT>"));
|
||||
QRect rectElision;
|
||||
bool elided = StyledElidedLabel::paintElidedLine(nullptr,text,textRect,ownOption.font,ownOption.displayAlignment,to.wrapMode()&QTextOption::WordWrap,true,&rectElision);
|
||||
if (elided && (rectElision.contains(ev->pos()))){
|
||||
QToolTip::showText(ev->globalPos(),QString("<FONT>") + text + QString("</FONT>"));
|
||||
return true; // eat event
|
||||
}
|
||||
}
|
||||
@ -231,5 +337,5 @@ bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
|
||||
}
|
||||
}
|
||||
}
|
||||
return RSItemDelegate::editorEvent(event, model, option, index);
|
||||
return RSStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
@ -23,37 +23,35 @@
|
||||
|
||||
#include <gui/common/RSItemDelegate.h>
|
||||
|
||||
class RSElidedItemDelegate : public RSItemDelegate
|
||||
class RSElidedItemDelegate : public RSStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isElided READ isElided)
|
||||
|
||||
// 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(QRect rectElision READ rectElision)
|
||||
Q_PROPERTY(bool paintRoundedRect READ paintRoundedRect WRITE setPaintRoundedRect)
|
||||
|
||||
public:
|
||||
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; }
|
||||
void setOnlyPlainText(const bool &value) { mOnlyPlainText = value; }
|
||||
QRect rectElision() { return mRectElision; }
|
||||
bool paintRoundedRect() const { return mPaintRoundedRect; }
|
||||
void setPaintRoundedRect(const bool &value) { mPaintRoundedRect = value; }
|
||||
|
||||
protected:
|
||||
void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QRect &rect, const QString &text) const;
|
||||
bool editorEvent(QEvent *event,
|
||||
QAbstractItemModel *model,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index);
|
||||
const QModelIndex &index) override;
|
||||
|
||||
private:
|
||||
mutable bool mElided;
|
||||
bool mOnlyPlainText;
|
||||
mutable QString mContent;
|
||||
mutable QRect mRectElision;
|
||||
|
||||
bool mPaintRoundedRect;
|
||||
};
|
||||
|
||||
#endif // RSELIDEDITEMDELEGATE_H
|
||||
|
@ -19,6 +19,7 @@
|
||||
*******************************************************************************/
|
||||
|
||||
#include "RSItemDelegate.h"
|
||||
#include "util/rsdebug.h"
|
||||
|
||||
RSItemDelegate::RSItemDelegate(QObject *parent) : QItemDelegate(parent)
|
||||
{
|
||||
@ -61,3 +62,48 @@ void RSItemDelegate::setSpacing(const QSize &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;
|
||||
}
|
||||
|
@ -22,14 +22,32 @@
|
||||
#define _RSITEMDELEGATE_H
|
||||
|
||||
#include <QItemDelegate>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class RSItemDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
RSItemDelegate(QObject *parent = 0);
|
||||
RSItemDelegate(QObject *parent = nullptr);
|
||||
|
||||
void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
QSize sizeHint (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 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 setSpacing(const QSize &spacing);
|
||||
|
@ -34,6 +34,7 @@ class RSTextBrowser : public QTextBrowser
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColorQuote READ textColorQuote WRITE setTextColorQuote)
|
||||
Q_PROPERTY(QVariant textColorQuotes READ textColorQuotes WRITE setTextColorQuotes)
|
||||
|
||||
public:
|
||||
explicit RSTextBrowser(QWidget *parent = 0);
|
||||
@ -52,11 +53,13 @@ public:
|
||||
virtual QVariant loadResource(int type, const QUrl &name);
|
||||
|
||||
QColor textColorQuote() const { return highlighter->textColorQuote();}
|
||||
QVariant textColorQuotes() const { return highlighter->textColorQuotes();}
|
||||
bool getShowImages() const { return mShowImages; }
|
||||
|
||||
public slots:
|
||||
void showImages();
|
||||
void setTextColorQuote(QColor textColorQuote) { highlighter->setTextColorQuote(textColorQuote);}
|
||||
void setTextColorQuotes(QVariant textColorQuotes) { highlighter->setTextColorQuotes(textColorQuotes);}
|
||||
|
||||
private slots:
|
||||
void linkClicked(const QUrl &url);
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
/** Constructor */
|
||||
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();
|
||||
}
|
||||
@ -35,8 +35,8 @@ GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *
|
||||
void GxsIdRSTreeWidgetItem::init()
|
||||
{
|
||||
mIdFound = false;
|
||||
mBannedState = false ;
|
||||
mRetryWhenFailed = false;
|
||||
mBannedState = false ;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
|
||||
QStyleOptionViewItem ownOption (option);
|
||||
initStyleOption(&ownOption, index);
|
||||
|
||||
RsGxsId id(index.data(Qt::UserRole).toString().toStdString());
|
||||
|
||||
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 ;
|
||||
QString cmt;
|
||||
|
||||
if(id.isNull())
|
||||
{
|
||||
str = tr("[Notification]");
|
||||
icon = QIcon(":/icons/notification.png");
|
||||
if (ownOption.icon.isNull())
|
||||
ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/notification.png");
|
||||
}
|
||||
else if(! computeNameIconAndComment(id,str,icon,comment))
|
||||
if(mReloadPeriod > 3)
|
||||
else
|
||||
{
|
||||
if(! computeNameIconAndComment(id,ownOption.text,ownOption.icon,cmt))
|
||||
{
|
||||
str = tr("[Unknown]");
|
||||
icon = QIcon(":/icons/anonymous.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
icon = GxsIdDetails::getLoadingIcon(id);
|
||||
launchAsyncLoading();
|
||||
if(mReloadPeriod > 3)
|
||||
{
|
||||
ownOption.text = tr("[Unknown]");
|
||||
ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/png/anonymous.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
ownOption.icon = GxsIdDetails::getLoadingIcon(id);
|
||||
launchAsyncLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QRect pixmaprect(r);
|
||||
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);
|
||||
RSElidedItemDelegate::paint(painter,ownOption,index);
|
||||
}
|
||||
|
@ -27,8 +27,10 @@
|
||||
#include "retroshare/rsidentity.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
|
||||
#include "gui/common/FilesDefs.h"
|
||||
#include "gui/common/RSTreeWidgetItem.h"
|
||||
#include "gui/common/ElidedLabel.h"
|
||||
#include "gui/common/RSElidedItemDelegate.h"
|
||||
|
||||
#include "gui/gxs/GxsIdDetails.h"
|
||||
|
||||
/*****
|
||||
@ -70,7 +72,7 @@ private:
|
||||
bool mIdFound;
|
||||
bool mBannedState ;
|
||||
bool mRetryWhenFailed;
|
||||
bool mAutoTooltip;
|
||||
bool mAutoTooltip;
|
||||
RsReputationLevel mReputationLevel;
|
||||
uint32_t mIconTypeMask;
|
||||
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.
|
||||
|
||||
class GxsIdTreeItemDelegate: public QStyledItemDelegate
|
||||
class GxsIdTreeItemDelegate: public RSElidedItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GxsIdTreeItemDelegate()
|
||||
{
|
||||
mLoading = false;
|
||||
mReloadPeriod = 0;
|
||||
}
|
||||
GxsIdTreeItemDelegate(QObject *parent = nullptr)
|
||||
:RSElidedItemDelegate(parent), 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 launchAsyncLoading() const
|
||||
@ -116,22 +117,27 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool computeNameIconAndComment(const RsGxsId& id,QString& name,QIcon& icon,QString& comment)
|
||||
{
|
||||
QList<QIcon> icons;
|
||||
static bool computeNameIconAndComment(const RsGxsId& id,QString& name,QIcon& icon,QString& comment)
|
||||
{
|
||||
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()) ;
|
||||
icon = QIcon(":/icons/avatar_128.png");
|
||||
}
|
||||
else if(!GxsIdDetails::MakeIdDesc(id, true, name, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR))
|
||||
return false;
|
||||
icon = FilesDefs::getIconFromQtResourcePath(":/icons/avatar_128.png");
|
||||
}
|
||||
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:
|
||||
void reload() { mLoading=false; emit commitData(NULL) ; }
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "util/HandleRichText.h"
|
||||
#include "util/DateTime.h"
|
||||
#include "gui/gxs/GxsIdDetails.h"
|
||||
#include "gui/gxs/GxsIdTreeWidgetItem.h"
|
||||
#include "GxsForumModel.h"
|
||||
#include "retroshare/rsgxsflags.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_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();
|
||||
#ifdef TODO
|
||||
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
|
||||
{
|
||||
if(col == COLUMN_THREAD_DISTRIBUTION)
|
||||
return QVariant(fmpe.mReputationWarningLevel);
|
||||
else if(col == COLUMN_THREAD_READ)
|
||||
return QVariant(fmpe.mMsgStatus);
|
||||
else
|
||||
return QVariant();
|
||||
bool exist=false;
|
||||
switch(col)
|
||||
{
|
||||
case COLUMN_THREAD_DISTRIBUTION:
|
||||
return QVariant(fmpe.mReputationWarningLevel);
|
||||
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
|
||||
|
@ -292,9 +292,6 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
|
||||
|
||||
mLastViewType = -1;
|
||||
|
||||
// load settings
|
||||
processSettings(true);
|
||||
|
||||
float f = QFontMetricsF(font()).height()/14.0f ;
|
||||
|
||||
/* Set header resize modes and initial section sizes */
|
||||
@ -328,6 +325,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
|
||||
|
||||
//ui->threadTreeWidget->installEventFilter(this) ;
|
||||
|
||||
// load settings
|
||||
processSettings(true);
|
||||
|
||||
blankPost();
|
||||
|
||||
ui->subscribeToolButton->setToolTip(tr( "<p>Subscribing to the forum will gather \
|
||||
|
@ -91,6 +91,7 @@
|
||||
<file>icons/png/leave2.png</file>
|
||||
<file>icons/png/messages-notify.png</file>
|
||||
<file>icons/png/messages.png</file>
|
||||
<file>icons/png/menu.png</file>
|
||||
<file>icons/png/microphone_mute.png</file>
|
||||
<file>icons/png/microphone.png</file>
|
||||
<file>icons/png/netgraph.png</file>
|
||||
|
BIN
retroshare-gui/src/gui/icons/png/menu.png
Normal file
BIN
retroshare-gui/src/gui/icons/png/menu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -418,16 +418,23 @@ void ImHistoryBrowser::customContextMenuRequested(QPoint /*pos*/)
|
||||
|
||||
void ImHistoryBrowser::copyMessage()
|
||||
{
|
||||
QListWidgetItem *currentItem = ui.listWidget->currentItem();
|
||||
if (currentItem) {
|
||||
uint32_t msgId = currentItem->data(ROLE_MSGID).toString().toInt();
|
||||
HistoryMsg msg;
|
||||
if (rsHistory->getMessage(msgId, msg)) {
|
||||
QTextDocument doc;
|
||||
doc.setHtml(QString::fromUtf8(msg.message.c_str()));
|
||||
QApplication::clipboard()->setText(doc.toPlainText());
|
||||
}
|
||||
}
|
||||
QListWidgetItem *currentItem = ui.listWidget->currentItem();
|
||||
if (currentItem) {
|
||||
uint32_t msgId = currentItem->data(ROLE_MSGID).toString().toInt();
|
||||
HistoryMsg msg;
|
||||
if (rsHistory->getMessage(msgId, msg)) {
|
||||
RsIdentityDetails details;
|
||||
QString name = (rsIdentity->getIdDetails(RsGxsId(msg.peerName), details))
|
||||
? QString::fromUtf8(details.mNickname.c_str())
|
||||
: QString::fromUtf8(msg.peerName.c_str());
|
||||
QDateTime date = msg.incoming
|
||||
? QDateTime::fromTime_t(msg.sendTime)
|
||||
: QDateTime::fromTime_t(msg.recvTime);
|
||||
QTextDocument doc;
|
||||
doc.setHtml(QString::fromUtf8(msg.message.c_str()));
|
||||
QApplication::clipboard()->setText("> " + date.toString() + " " + name + ":" + doc.toPlainText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImHistoryBrowser::removeMessages()
|
||||
|
@ -487,7 +487,16 @@ QVariant RsMessageModel::displayRole(const Rs::Msgs::MsgInfoSummary& fmpe,int co
|
||||
}
|
||||
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:
|
||||
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
|
||||
{
|
||||
if(col == COLUMN_THREAD_READ)
|
||||
if(fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER))
|
||||
return FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png");
|
||||
else
|
||||
return FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png");
|
||||
bool exist=false;
|
||||
switch(col)
|
||||
{
|
||||
case COLUMN_THREAD_READ:
|
||||
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_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(fmpe.msgflags & RS_MSG_UNREAD_BY_USER)
|
||||
{
|
||||
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_FORWARDED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-forwarded.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_UNREAD_BY_USER)
|
||||
{
|
||||
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_FORWARDED) return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-forwarded.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");
|
||||
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-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.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");
|
||||
}
|
||||
|
||||
return FilesDefs::getIconFromQtResourcePath(":/images/message-mail-read.png");
|
||||
}
|
||||
|
||||
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_STAR:
|
||||
return FilesDefs::getIconFromQtResourcePath((fmpe.msgflags & RS_MSG_STAR) ? (IMAGE_STAR_ON ): (IMAGE_STAR_OFF));
|
||||
|
||||
case COLUMN_THREAD_AUTHOR://Return icon as place holder.
|
||||
return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.srcId.toStdString()),QIcon(), exist);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
@ -147,11 +147,11 @@ MessagesDialog::MessagesDialog(QWidget *parent)
|
||||
|
||||
changeBox(0); // set to inbox
|
||||
|
||||
ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_AUTHOR,new GxsIdTreeItemDelegate()) ;
|
||||
|
||||
RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this);
|
||||
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
|
||||
// http://bugreports.qt.nokia.com/browse/QTBUG-8270
|
||||
@ -484,10 +484,9 @@ int MessagesDialog::getSelectedMsgCount (QList<QModelIndex> *items, QList<QModel
|
||||
items->append(m);
|
||||
|
||||
if (m.data(RsMessageModel::UnreadRole).toBool())
|
||||
if (itemsUnread)
|
||||
itemsUnread->append(m);
|
||||
else if(itemsRead)
|
||||
itemsRead->append(m);
|
||||
{ if (itemsUnread) itemsUnread->append(m); }
|
||||
else
|
||||
{ if (itemsRead) itemsRead->append(m); }
|
||||
|
||||
if (itemsStar && m.data(RsMessageModel::MsgFlagsRole).toInt() & RS_MSG_STAR)
|
||||
itemsStar->append(m);
|
||||
|
@ -571,54 +571,63 @@ IdEditDialog QLabel#info_label
|
||||
background: #FFFFD7;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
|
||||
}
|
||||
|
||||
GenCertDialog QComboBox#genPGPuser {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QSpinBox#hiddenport_spinBox {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QLineEdit#hiddenaddr_input {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QLineEdit#password2_input {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QLineEdit#password_input {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QLineEdit#nickname_input {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QLineEdit#node_input {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QLineEdit#name_input {
|
||||
border: 2px solid #0099cc;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
GenCertDialog QPushButton#genButton {
|
||||
border-image: url(:/images/btn_blue.png) 4;
|
||||
border-width: 4;
|
||||
@ -890,3 +899,11 @@ WireDialog QFrame#frame{
|
||||
WireDialog QWidget#scrollAreaWidgetContents_groups{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
MessagesDialog QWidget#messageTreeWidget::item {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
GxsForumThreadWidget QWidget#threadTreeWidget::item {
|
||||
padding: 2px;
|
||||
}
|
||||
|
@ -2143,3 +2143,14 @@ PostedCardView > QFrame#mainFrame[new=true] {
|
||||
WireGroupItem QFrame#frame{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
GxsChannelDialog GroupTreeWidget QTreeWidget#treeWidget::item{
|
||||
/*background-color: #F00000;*/
|
||||
/*padding: 20px;*/
|
||||
}
|
||||
|
||||
RSTextBrowser, MimeTextEdit
|
||||
{
|
||||
/*qproperty-textColorQuote: rgb(125, 125, 255);*/
|
||||
/*qproperty-textColorQuotes: ColorList(#0000ff #00ff00 #00ffff #ff0000 #ff00ff #ffff00 #ffffff);*/
|
||||
}
|
||||
|
@ -1215,8 +1215,10 @@ QString RsHtml::makeQuotedText(RSTextBrowser *browser)
|
||||
}
|
||||
QStringList sl = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
|
||||
text = sl.join("\n> ");
|
||||
text.replace("\n> >","\n>>"); // Don't add space for already quotted lines.
|
||||
text.replace(QChar(-4)," ");//Char used when image on text.
|
||||
return QString("> ") + text;
|
||||
QString quote = (text.left(1) == ">") ? QString(">") : QString("> ");
|
||||
return quote + text;
|
||||
}
|
||||
|
||||
void RsHtml::insertSpoilerText(QTextCursor cursor)
|
||||
|
@ -23,35 +23,90 @@
|
||||
RsSyntaxHighlighter::RsSyntaxHighlighter(QTextEdit *parent)
|
||||
: QSyntaxHighlighter(parent)
|
||||
{
|
||||
|
||||
quotationFormats.append(QTextCharFormat());
|
||||
}
|
||||
|
||||
void RsSyntaxHighlighter::highlightBlock(const QString &text)
|
||||
QColor RsSyntaxHighlighter::textColorQuote () const
|
||||
{
|
||||
QRegExp endl("[\\r\\n\\x2028]"); //Usually 0x2028 cahracter is used for newline, no idea why
|
||||
int index = 0;
|
||||
QStringList lines = text.split(endl);
|
||||
foreach (const QString &line, lines) {
|
||||
if(line.trimmed().startsWith('>')) {
|
||||
setFormat(index, line.length(), quotationFormat);
|
||||
}
|
||||
index += line.length() + 1;
|
||||
}
|
||||
//Make it work with the compact chat style
|
||||
if(lines.length() > 0){
|
||||
int i = lines[0].indexOf(": >");
|
||||
if(i != -1) {
|
||||
setFormat(i+2, lines[0].length()-i-2, quotationFormat);
|
||||
}
|
||||
}
|
||||
return quotationFormats.at(0).foreground().color();
|
||||
}
|
||||
QVariant RsSyntaxHighlighter::textColorQuotes() const
|
||||
{
|
||||
QList<QVariant> l;
|
||||
foreach(auto i, quotationFormats)
|
||||
l.append(QVariant(i.foreground().color()));
|
||||
|
||||
return QVariant(l);
|
||||
}
|
||||
|
||||
void RsSyntaxHighlighter::setTextColorQuote(QColor textColorQuote)
|
||||
{
|
||||
quotationFormat.setForeground(textColorQuote);
|
||||
quotationFormats[0].setForeground(textColorQuote);
|
||||
this->rehighlight();
|
||||
}
|
||||
|
||||
void RsSyntaxHighlighter::setTextColorQuotes(QVariant textColorQuotes)
|
||||
{
|
||||
QStringList parList = textColorQuotes.toStringList();
|
||||
if ((parList.size() == 2) && (parList.at(0).toLower() == "colorlist"))
|
||||
{
|
||||
QStringList colList = parList.at(1).split(" ");
|
||||
quotationFormats.clear();
|
||||
for(int i = 0; i < colList.size(); i++)
|
||||
{
|
||||
quotationFormats.append(QTextCharFormat());
|
||||
quotationFormats[i].setForeground(QColor(colList[i]));
|
||||
}
|
||||
}
|
||||
|
||||
this->rehighlight();
|
||||
}
|
||||
|
||||
void RsSyntaxHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
if (text == "") return;
|
||||
|
||||
QRegExp endl("[\\r\\n\\x2028]"); //Usually 0x2028 character is used for newline, no idea why
|
||||
int index = 0;
|
||||
QStringList lines = text.split(endl);
|
||||
foreach (const QString &cLine, lines) {
|
||||
QString line =cLine;
|
||||
line.replace(QChar::Nbsp,QChar::Space);
|
||||
int count = 0;
|
||||
for( int i=0; i<line.length(); i++ ){
|
||||
if( line[i] == '>' )
|
||||
count++;
|
||||
else if( line[i] != QChar::Space )
|
||||
break;
|
||||
}
|
||||
//Make it work with the compact chat style
|
||||
int start = line.indexOf(": >");
|
||||
if( start != -1 )
|
||||
start += 2; // Start at ">" not ":"
|
||||
else
|
||||
start = 0;
|
||||
|
||||
if(count && start > count ) {
|
||||
// Found but already quotted
|
||||
start = 0;
|
||||
} else {
|
||||
if (start && !count) {
|
||||
// Start to count after name: >
|
||||
for(int i=start; i<line.length(); i++){
|
||||
if( line[i] == '>' )
|
||||
count++;
|
||||
else if( line[i] != QChar::Space )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count) {
|
||||
setFormat(index + start, line.length() - start, quotationFormats.at(qMin(count-1,quotationFormats.size()-1)));
|
||||
}
|
||||
index += line.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Dumping the raw unicode string into the console in Base64 encoding
|
||||
/*
|
||||
QByteArray uniline;
|
||||
|
@ -30,22 +30,22 @@ class RsSyntaxHighlighter : public QSyntaxHighlighter
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColorQuote READ textColorQuote WRITE setTextColorQuote)
|
||||
Q_PROPERTY(QVariant textColorQuotes READ textColorQuotes WRITE setTextColorQuotes)
|
||||
|
||||
public:
|
||||
RsSyntaxHighlighter(QTextEdit *parent = 0);
|
||||
QColor textColorQuote() const { return quotationFormat.foreground().color(); };
|
||||
QColor textColorQuote () const;
|
||||
QVariant textColorQuotes() const;
|
||||
|
||||
public slots:
|
||||
void setTextColorQuote (QColor textColorQuote);
|
||||
void setTextColorQuotes(QVariant textColorQuotes);
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text);
|
||||
|
||||
private:
|
||||
QTextCharFormat quotationFormat;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void setTextColorQuote(QColor textColorQuote);
|
||||
|
||||
QList<QTextCharFormat> quotationFormats;
|
||||
};
|
||||
|
||||
#endif // RSSYNTAXHIGHLIGHTER_H
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <QFontDialog>
|
||||
|
||||
#include "misc.h"
|
||||
#include "util/rsdebug.h"
|
||||
|
||||
// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB)
|
||||
// use Binary prefix standards from IEC 60027-2
|
||||
@ -416,12 +417,17 @@ void misc::clearLayout(QLayout * layout) {
|
||||
|
||||
while (auto item = layout->takeAt(0))
|
||||
{
|
||||
if (auto *widget = item->widget())
|
||||
//First get all pointers, else item may be deleted when last object removed and get SIGSEGV
|
||||
auto *widget = item->widget();
|
||||
auto *spacer = item->spacerItem();
|
||||
//Then Clear Layout
|
||||
clearLayout(item->layout());
|
||||
//Last clear objects
|
||||
if (widget)
|
||||
widget->deleteLater();
|
||||
if (auto *spacer = item->spacerItem())
|
||||
if (spacer)
|
||||
delete spacer;
|
||||
|
||||
clearLayout(item->layout());
|
||||
delete item;
|
||||
//delete item;//Auto deleted by Qt.
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user