diff --git a/retroshare-gui/src/gui/MessagesDialog.cpp b/retroshare-gui/src/gui/MessagesDialog.cpp index 4ef41546f..2a31939f2 100644 --- a/retroshare-gui/src/gui/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/MessagesDialog.cpp @@ -19,36 +19,37 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ +#include +#include +#include #include #include #include -#include -#include -#include #include "MessagesDialog.h" -#include "msgs/MessageComposer.h" -#include "msgs/MessageWidget.h" -#include "msgs/TagsMenu.h" -#include "msgs/MessageUserNotify.h" -#include "settings/rsharesettings.h" + +#include "notifyqt.h" #include "common/TagDefs.h" #include "common/PeerDefs.h" -#include "common/RSItemDelegate.h" -#include "gui/gxs/GxsIdTreeWidgetItem.h" -#include "gui/gxs/GxsIdDetails.h" +#include "common/RSElidedItemDelegate.h" +#include "gxs/GxsIdTreeWidgetItem.h" +#include "gxs/GxsIdDetails.h" +#include "msgs/MessageComposer.h" +#include "msgs/MessageInterface.h" +#include "msgs/MessageUserNotify.h" +#include "msgs/MessageWidget.h" +#include "msgs/TagsMenu.h" +#include "settings/rsharesettings.h" + #include "util/DateTime.h" #include "util/RsProtectedTimer.h" #include "util/QtVersion.h" -#include "notifyqt.h" #include #include #include -#include "gui/msgs/MessageInterface.h" - /* Images for context menu icons */ #define IMAGE_MESSAGE ":/images/folder-draft.png" #define IMAGE_MESSAGEREMOVE ":/images/message-mail-imapdelete.png" @@ -197,7 +198,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) mMessageCompareRole->setRole(COLUMN_ATTACHEMENTS, ROLE_SORT); mMessageCompareRole->setRole(COLUMN_STAR, ROLE_SORT); - RSItemDelegate *itemDelegate = new RSItemDelegate(this); + RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); itemDelegate->setSpacing(QSize(0, 2)); ui.messageTreeWidget->setItemDelegate(itemDelegate); diff --git a/retroshare-gui/src/gui/common/ElidedLabel.cpp b/retroshare-gui/src/gui/common/ElidedLabel.cpp index 0dd4f69b6..450c49b14 100644 --- a/retroshare-gui/src/gui/common/ElidedLabel.cpp +++ b/retroshare-gui/src/gui/common/ElidedLabel.cpp @@ -179,7 +179,7 @@ void ElidedLabel::paintEvent(QPaintEvent *event) QPoint lastPos(-1,-1); //Now we know how many lines to redraw at good position foreach (pair, lLines){ - lastPos = pair.second + QPoint(0, iTransY); + lastPos = pair.second + QPoint(0+ cr.left(), iTransY + cr.top()); pair.first.draw(&painter, lastPos); } @@ -203,10 +203,10 @@ void ElidedLabel::paintEvent(QPaintEvent *event) iTransX = 0; } - painter.drawText(QPoint(iTransX, y + fontMetrics.ascent()), elidedLastLine); + painter.drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine); //Draw button to get ToolTip - mRectElision = QRect(iTransX + width - fontMetrics.width(ellipsisChar) - , y + mRectElision = QRect(iTransX + width - fontMetrics.width(ellipsisChar) + cr.left() + , y + cr.top() , fontMetrics.width(ellipsisChar) , fontMetrics.height() - 1); painter.drawRoundRect(mRectElision); diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp index 12408b92a..79f6172ac 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp @@ -30,7 +30,7 @@ #include "retroshare/rsgxsflags.h" #include "PopularityDefs.h" -#include "RSItemDelegate.h" +#include "RSElidedItemDelegate.h" #include "RSTreeWidgetItem.h" #include "gui/common/ElidedLabel.h" #include "gui/settings/rsharesettings.h" @@ -89,7 +89,7 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) : } /* Add own item delegate */ - RSItemDelegate *itemDelegate = new RSItemDelegate(this); + RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); itemDelegate->setSpacing(QSize(0, 2)); ui->treeWidget->setItemDelegate(itemDelegate); diff --git a/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp b/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp new file mode 100644 index 000000000..d632e54e5 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp @@ -0,0 +1,227 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "RSElidedItemDelegate.h" + +#include +#include +#include +#include + +RSElidedItemDelegate::RSElidedItemDelegate(QObject *parent) + : RSItemDelegate(parent) + , mElided(false) + , mOnlyPlainText(false) + , mContent("") +{ + mRectElision = QRect(); +} + +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()) + { + mContent = text; + QList > 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); + 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(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(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 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; + } +} + +bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent *ev = static_cast(event); + if (ev) { + if (ev->buttons()==Qt::LeftButton) { + 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(); + 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(); + 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(); + if (!icon.isNull()) { + QSize size = icon.actualSize(rect.size()); + rect.adjust(size.width() + 6,0,0,0);//Don't know where come from these 6 pixels... + } + } + //Get Font as option.font is not accurate + QStyleOptionViewItem newOption = option; + if (index.data(Qt::FontRole).type() == QVariant::Font) { + QFont font = index.data(Qt::FontRole).value(); + newOption.font = font; + newOption.fontMetrics = QFontMetrics(font); + } + + //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("") + mContent + QString("")); + return true; // eat event + } + } + } + } + } + } + return RSItemDelegate::editorEvent(event, model, option, index); +} diff --git a/retroshare-gui/src/gui/common/RSElidedItemDelegate.h b/retroshare-gui/src/gui/common/RSElidedItemDelegate.h new file mode 100644 index 000000000..1addfafe0 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSElidedItemDelegate.h @@ -0,0 +1,60 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RSELIDEDITEMDELEGATE_H +#define RSELIDEDITEMDELEGATE_H + +#include + +class RSElidedItemDelegate : public RSItemDelegate +{ + Q_OBJECT + Q_PROPERTY(bool isElided READ isElided) + Q_PROPERTY(bool isOnlyPlainText READ isOnlyPlainText WRITE setOnlyPlainText) + Q_PROPERTY(QRect rectElision READ rectElision) + +public: + RSElidedItemDelegate(QObject *parent = 0); + + void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + + bool isElided() const { return mElided; } + bool isOnlyPlainText() const { return mOnlyPlainText; } + void setOnlyPlainText(const bool &value) { mOnlyPlainText = value; } + QRect rectElision() { return mRectElision; } + +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); + +private: + mutable bool mElided; + bool mOnlyPlainText; + mutable QString mContent; + mutable QRect mRectElision; + +}; + +#endif // RSELIDEDITEMDELEGATE_H diff --git a/retroshare-gui/src/gui/common/RSItemDelegate.h b/retroshare-gui/src/gui/common/RSItemDelegate.h index 1b4aedf8f..c7fbf0a70 100644 --- a/retroshare-gui/src/gui/common/RSItemDelegate.h +++ b/retroshare-gui/src/gui/common/RSItemDelegate.h @@ -35,7 +35,7 @@ public: void removeFocusRect(int column); void setSpacing(const QSize &spacing); - + QSize spacing() const { return m_spacing; } private: QList m_noFocusRect; QSize m_spacing; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 24c4729cd..6a9c14bc0 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -30,7 +30,7 @@ #include "GxsForumsDialog.h" #include "gui/RetroShareLink.h" #include "gui/common/RSTreeWidgetItem.h" -#include "gui/common/RSItemDelegate.h" +#include "gui/common/RSElidedItemDelegate.h" #include "gui/settings/rsharesettings.h" #include "gui/gxs/GxsIdTreeWidgetItem.h" #include "gui/gxs/GxsIdDetails.h" @@ -161,7 +161,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget connect(ui->actionSave_image, SIGNAL(triggered()), this, SLOT(saveImage())); /* Set own item delegate */ - RSItemDelegate *itemDelegate = new RSItemDelegate(this); + RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); itemDelegate->setSpacing(QSize(0, 2)); ui->threadTreeWidget->setItemDelegate(itemDelegate); @@ -208,8 +208,8 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget ui->postText->clear(); ui->by_label->setId(RsGxsId()); ui->time_label->clear() ; - ui->line->hide() ; - ui->line_2->hide() ; + ui->lineRight->hide() ; + ui->lineLeft->hide() ; ui->by_text_label->hide() ; ui->by_label->hide() ; ui->postText->setImageBlockWidget(ui->imageBlockWidget); @@ -963,7 +963,8 @@ void GxsForumThreadWidget::fillThreadProgress(int current, int count) { // show fill progress if (count) { - ui->progressBar->setValue(current * ui->progressBar->maximum() / count); + int max = ui->progressBar->maximum(); + ui->progressBar->setValue(current * max / count); } } @@ -1380,8 +1381,8 @@ void GxsForumThreadWidget::insertMessage() ui->postText->clear(); ui->by_label->setId(RsGxsId()); ui->time_label->clear() ; - ui->line->hide() ; - ui->line_2->hide() ; + ui->lineRight->hide() ; + ui->lineLeft->hide() ; ui->by_text_label->hide() ; ui->by_label->hide() ; @@ -1442,8 +1443,8 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) ui->time_label->setText(DateTime::formatLongDateTime(msg.mMeta.mPublishTs)); ui->by_label->setId(msg.mMeta.mAuthorId) ; - ui->line->show() ; - ui->line_2->show() ; + ui->lineRight->show() ; + ui->lineLeft->show() ; ui->by_text_label->show() ; ui->by_label->show() ; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui index fcd3ab348..a086d110c 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui @@ -13,7 +13,7 @@ Form - + 0 @@ -31,8 +31,8 @@ Qt::Vertical - - + + @@ -47,7 +47,7 @@ QFrame::Sunken - + 2 @@ -128,7 +128,7 @@ - + Qt::Horizontal @@ -347,21 +347,21 @@ - + Qt::Vertical - + Qt::Vertical - + Qt::Horizontal @@ -470,8 +470,8 @@ - - + + diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index ea2bc97e6..f399f9603 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -492,6 +492,7 @@ HEADERS += rshare.h \ gui/common/RSTreeWidgetItem.h \ gui/common/RSFeedWidget.h \ gui/common/RSTabWidget.h \ + gui/common/RSElidedItemDelegate.h \ gui/common/RSItemDelegate.h \ gui/common/PeerDefs.h \ gui/common/FilesDefs.h \ @@ -801,6 +802,7 @@ SOURCES += main.cpp \ gui/common/RSTreeWidgetItem.cpp \ gui/common/RSFeedWidget.cpp \ gui/common/RSTabWidget.cpp \ + gui/common/RSElidedItemDelegate.cpp \ gui/common/RSItemDelegate.cpp \ gui/common/PeerDefs.cpp \ gui/common/FilesDefs.cpp \