From: Mike Gelfand Date: Sat, 17 Jan 2015 16:59:42 +0000 (+0000) Subject: Improve overall look of torrents in main window X-Git-Tag: 2.90~238 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=efc04fdd77fa79777da793ed2ea02ad1675b02a5;p=transmission Improve overall look of torrents in main window Refactor and use the same code to calculate element positions in sizeHint () and paint () to prevent discrepancies. While we are at it, properly support RTL layout. --- diff --git a/qt/filterbar.cc b/qt/filterbar.cc index 0880f37b3..99bb7121b 100644 --- a/qt/filterbar.cc +++ b/qt/filterbar.cc @@ -53,15 +53,6 @@ namespace fadedColor.setAlpha (128); return fadedColor; } - - void - narrowRect (QRect& rect, int dx1, int dx2, Qt::LayoutDirection direction) - { - if (direction == Qt::LeftToRight) - rect.adjust (dx1, 0, -dx2, 0); - else - rect.adjust (dx2, 0, -dx1, 0); - } } FilterBarComboBoxDelegate::FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo): @@ -117,13 +108,13 @@ FilterBarComboBoxDelegate::paint (QPainter * painter, decorationRect = QStyle::alignedRect (option.direction, Qt::AlignLeft|Qt::AlignVCenter, decorationRect.size (), boundingBox); - narrowRect (boundingBox, decorationRect.width () + hmargin, 0, option.direction); + Utils::narrowRect (boundingBox, decorationRect.width () + hmargin, 0, option.direction); QRect countRect = rect (option, index, TorrentCountStringRole); countRect = QStyle::alignedRect (option.direction, Qt::AlignRight|Qt::AlignVCenter, countRect.size (), boundingBox); - narrowRect (boundingBox, 0, countRect.width () + hmargin, option.direction); + Utils::narrowRect (boundingBox, 0, countRect.width () + hmargin, option.direction); const QRect displayRect = boundingBox; drawBackground (painter, option, index); @@ -263,7 +254,7 @@ FilterBarComboBox::paintEvent (QPaintEvent * e) const QRect iconRect = QStyle::alignedRect(opt.direction, Qt::AlignLeft | Qt::AlignVCenter, opt.iconSize, rect); painter.drawPixmap (iconRect.topLeft (), pixmap); - narrowRect (rect, iconRect.width () + hmargin, 0, opt.direction); + Utils::narrowRect (rect, iconRect.width () + hmargin, 0, opt.direction); } // draw the count @@ -275,7 +266,7 @@ FilterBarComboBox::paintEvent (QPaintEvent * e) const QRect textRect = QStyle::alignedRect(opt.direction, Qt::AlignRight | Qt::AlignVCenter, QSize (opt.fontMetrics.width (text), rect.height ()), rect); painter.drawText (textRect, Qt::AlignRight | Qt::AlignVCenter, text); - narrowRect (rect, 0, textRect.width () + hmargin, opt.direction); + Utils::narrowRect (rect, 0, textRect.width () + hmargin, opt.direction); painter.setPen (pen); } diff --git a/qt/torrent-delegate-min.cc b/qt/torrent-delegate-min.cc index fd5b6bc7a..ef992e45f 100644 --- a/qt/torrent-delegate-min.cc +++ b/qt/torrent-delegate-min.cc @@ -26,6 +26,7 @@ #include "torrent.h" #include "torrent-delegate-min.h" #include "torrent-model.h" +#include "utils.h" enum { @@ -43,31 +44,83 @@ enum **** ***/ +namespace +{ + class ItemLayout + { + private: + QString myNameText; + QString myStatusText; + + public: + QFont nameFont; + QFont statusFont; + + QRect iconRect; + QRect emblemRect; + QRect nameRect; + QRect statusRect; + QRect barRect; + + public: + ItemLayout(const QString& nameText, const QString& statusText, const QIcon& emblemIcon, + const QFont& baseFont, Qt::LayoutDirection direction, const QPoint& topLeft, int width); + + QSize size () const + { + return (iconRect | nameRect | statusRect | barRect).size (); + } + + QString nameText () const { return elidedText (nameFont, myNameText, nameRect.width ()); } + QString statusText () const { return myStatusText; } + + private: + QString elidedText (const QFont& font, const QString& text, int width) const + { + return QFontMetrics (font).elidedText (text, Qt::ElideRight, width); + } + }; + + ItemLayout::ItemLayout(const QString& nameText, const QString& statusText, const QIcon& emblemIcon, + const QFont& baseFont, Qt::LayoutDirection direction, const QPoint& topLeft, int width): + myNameText (nameText), + myStatusText (statusText), + nameFont (baseFont), + statusFont (baseFont) + { + const QStyle * style (qApp->style ()); + const int iconSize (style->pixelMetric (QStyle::PM_SmallIconSize)); + + const QFontMetrics nameFM (nameFont); + const QSize nameSize (nameFM.size (0, myNameText)); + + statusFont.setPointSize (static_cast (statusFont.pointSize () * 0.85)); + const QFontMetrics statusFM (statusFont); + const QSize statusSize (statusFM.size (0, myStatusText)); + + QRect baseRect (topLeft, QSize (width, qMax (iconSize, qMax (nameSize.height (), qMax (statusSize.height (), static_cast(BAR_HEIGHT)))))); + + iconRect = style->alignedRect (direction, Qt::AlignLeft | Qt::AlignVCenter, QSize (iconSize, iconSize), baseRect); + emblemRect = style->alignedRect (direction, Qt::AlignRight | Qt::AlignBottom, + emblemIcon.actualSize (iconRect.size () / 2, QIcon::Normal, QIcon::On), + iconRect); + barRect = style->alignedRect (direction, Qt::AlignRight | Qt::AlignVCenter, QSize (BAR_WIDTH, BAR_HEIGHT), baseRect); + Utils::narrowRect (baseRect, iconRect.width () + GUI_PAD, barRect.width () + GUI_PAD, direction); + statusRect = style->alignedRect (direction, Qt::AlignRight | Qt::AlignVCenter, QSize (statusSize.width (), baseRect.height ()), baseRect); + Utils::narrowRect (baseRect, 0, statusRect.width () + GUI_PAD, direction); + nameRect = baseRect; + } +} + QSize TorrentDelegateMin::sizeHint (const QStyleOptionViewItem & option, const Torrent & tor) const { - const QStyle* style (qApp->style()); - static const int iconSize (style->pixelMetric (QStyle::PM_SmallIconSize)); - - QFont nameFont (option.font); - const QFontMetrics nameFM (nameFont); const bool isMagnet (!tor.hasMetadata()); - const QString nameStr = (isMagnet ? progressString (tor) : tor.name()); - const int nameWidth = nameFM.width (nameStr); - - QFont statusFont (option.font); - statusFont.setPointSize (static_cast (option.font.pointSize() * 0.85)); - const QFontMetrics statusFM (statusFont); - const QString statusStr (shortStatusString (tor)); - const int statusWidth = statusFM.width (statusStr); - - const QSize m (margin (*style)); - - return QSize (m.width()*2 + iconSize + GUI_PAD + nameWidth - + GUI_PAD + statusWidth - + GUI_PAD + BAR_WIDTH, - m.height()*2 + std::max (nameFM.height(), (int)BAR_HEIGHT)); + const QSize m (margin (*qApp->style())); + const ItemLayout layout (isMagnet ? progressString (tor) : tor.name(), shortStatusString (tor), QIcon (), + option.font, option.direction, QPoint (0, 0), option.rect.width () - m.width () * 2); + return layout.size () + m * 2; } void @@ -75,20 +128,10 @@ TorrentDelegateMin::drawTorrent (QPainter * painter, const QStyleOptionViewItem & option, const Torrent & tor) const { - const bool isPaused (tor.isPaused()); const QStyle * style (qApp->style()); - static const int iconSize (style->pixelMetric (QStyle::PM_SmallIconSize)); - QFont nameFont (option.font); - const QFontMetrics nameFM (nameFont); + const bool isPaused (tor.isPaused()); const bool isMagnet (!tor.hasMetadata()); - const QString nameStr = (isMagnet ? progressString (tor) : tor.name()); - - QFont statusFont (option.font); - statusFont.setPointSize (static_cast (option.font.pointSize() * 0.85)); - const QFontMetrics statusFM (statusFont); - const QString statusStr (shortStatusString (tor)); - const QSize statusSize (statusFM.size (0, statusStr)); const bool isItemSelected ((option.state & QStyle::State_Selected) != 0); const bool isItemEnabled ((option.state & QStyle::State_Enabled) != 0); @@ -141,41 +184,23 @@ TorrentDelegateMin::drawTorrent (QPainter * painter, // layout const QSize m (margin (*style)); - QRect fillArea (option.rect); - fillArea.adjust (m.width(), m.height(), -m.width(), -m.height()); - const QRect iconArea (fillArea.x(), - fillArea.y() + (fillArea.height() - iconSize) / 2, - iconSize, - iconSize); - const QRect emblemRect (style->alignedRect (option.direction, Qt::AlignRight | Qt::AlignBottom, - emblemIcon.actualSize (QSize (iconSize / 2, iconSize / 2), emblemIm, qs), - iconArea)); - const QRect barArea (fillArea.x() + fillArea.width() - BAR_WIDTH, - fillArea.y() + (fillArea.height() - BAR_HEIGHT) / 2, - BAR_WIDTH, - BAR_HEIGHT); - const QRect statusArea (barArea.x() - GUI_PAD - statusSize.width(), - fillArea.y() + (fillArea.height() - statusSize.height()) / 2, - fillArea.width(), - fillArea.height()); - const QRect nameArea (iconArea.x() + iconArea.width() + GUI_PAD, - fillArea.y(), - statusArea.x() - (iconArea.x() + iconArea.width() + GUI_PAD * 2), - fillArea.height()); + const QRect contentRect (option.rect.adjusted (m.width(), m.height(), -m.width(), -m.height())); + const ItemLayout layout (isMagnet ? progressString (tor) : tor.name(), shortStatusString (tor), emblemIcon, + option.font, option.direction, contentRect.topLeft (), contentRect.width ()); // render if (tor.hasError() && !isItemSelected) painter->setPen (QColor ("red")); else painter->setPen (option.palette.color (cg, cr)); - tor.getMimeTypeIcon().paint (painter, iconArea, Qt::AlignCenter, im, qs); + tor.getMimeTypeIcon().paint (painter, layout.iconRect, Qt::AlignCenter, im, qs); if (!emblemIcon.isNull ()) - emblemIcon.paint (painter, emblemRect, Qt::AlignCenter, emblemIm, qs); - painter->setFont (nameFont); - painter->drawText (nameArea, 0, nameFM.elidedText (nameStr, Qt::ElideRight, nameArea.width())); - painter->setFont (statusFont); - painter->drawText (statusArea, 0, statusStr); - myProgressBarStyle->rect = barArea; + emblemIcon.paint (painter, layout.emblemRect, Qt::AlignCenter, emblemIm, qs); + painter->setFont (layout.nameFont); + painter->drawText (layout.nameRect, Qt::AlignLeft | Qt::AlignVCenter, layout.nameText ()); + painter->setFont (layout.statusFont); + painter->drawText (layout.statusRect, Qt::AlignLeft | Qt::AlignVCenter, layout.statusText ()); + myProgressBarStyle->rect = layout.barRect; if (tor.isDownloading()) { myProgressBarStyle->palette.setBrush (QPalette::Highlight, blueBrush); diff --git a/qt/torrent-delegate.cc b/qt/torrent-delegate.cc index 1926f70b4..df6f76ef7 100644 --- a/qt/torrent-delegate.cc +++ b/qt/torrent-delegate.cc @@ -24,6 +24,7 @@ #include "torrent.h" #include "torrent-delegate.h" #include "torrent-model.h" +#include "utils.h" enum { @@ -38,6 +39,89 @@ QColor TorrentDelegate::greenBack; QColor TorrentDelegate::blueBack; QColor TorrentDelegate::silverBack; +namespace +{ + class ItemLayout + { + private: + QString myNameText; + QString myStatusText; + QString myProgressText; + + public: + QFont nameFont; + QFont statusFont; + QFont progressFont; + + QRect iconRect; + QRect emblemRect; + QRect nameRect; + QRect statusRect; + QRect barRect; + QRect progressRect; + + public: + ItemLayout(const QString& nameText, const QString& statusText, const QString& progressText, + const QIcon& emblemIcon, const QFont& baseFont, Qt::LayoutDirection direction, + const QPoint& topLeft, int width); + + QSize size () const + { + return (iconRect | nameRect | statusRect | barRect | progressRect).size (); + } + + QString nameText () const { return elidedText (nameFont, myNameText, nameRect.width ()); } + QString statusText () const { return elidedText (statusFont, myStatusText, statusRect.width ()); } + QString progressText () const { return elidedText (progressFont, myProgressText, progressRect.width ()); } + + private: + QString elidedText (const QFont& font, const QString& text, int width) const + { + return QFontMetrics (font).elidedText (text, Qt::ElideRight, width); + } + }; + + ItemLayout::ItemLayout(const QString& nameText, const QString& statusText, const QString& progressText, + const QIcon& emblemIcon, const QFont& baseFont, Qt::LayoutDirection direction, + const QPoint& topLeft, int width): + myNameText (nameText), + myStatusText (statusText), + myProgressText (progressText), + nameFont (baseFont), + statusFont (baseFont), + progressFont (baseFont) + { + const QStyle * style (qApp->style ()); + const int iconSize (style->pixelMetric (QStyle::PM_LargeIconSize)); + + nameFont.setWeight (QFont::Bold); + const QFontMetrics nameFM (nameFont); + const QSize nameSize (nameFM.size (0, myNameText)); + + statusFont.setPointSize (static_cast (statusFont.pointSize () * 0.9)); + const QFontMetrics statusFM (statusFont); + const QSize statusSize (statusFM.size (0, myStatusText)); + + progressFont.setPointSize (static_cast (progressFont.pointSize () * 0.9)); + const QFontMetrics progressFM (progressFont); + const QSize progressSize (progressFM.size (0, myProgressText)); + + QRect baseRect (topLeft, QSize (width, 0)); + Utils::narrowRect (baseRect, iconSize + GUI_PAD, 0, direction); + + nameRect = baseRect.adjusted(0, 0, 0, nameSize.height ()); + statusRect = nameRect.adjusted(0, nameRect.height () + 1, 0, statusSize.height () + 1); + barRect = statusRect.adjusted(0, statusRect.height () + 1, 0, BAR_HEIGHT + 1); + progressRect = barRect.adjusted (0, barRect.height () + 1, 0, progressSize.height () + 1); + iconRect = style->alignedRect (direction, Qt::AlignLeft | Qt::AlignVCenter, + QSize (iconSize, iconSize), + QRect (topLeft, QSize (width, progressRect.bottom () - nameRect.top ()))); + emblemRect = style->alignedRect (direction, Qt::AlignRight | Qt::AlignBottom, + emblemIcon.actualSize (iconRect.size () / 2, QIcon::Normal, QIcon::On), + iconRect); + } +} + TorrentDelegate::TorrentDelegate (QObject * parent): QStyledItemDelegate (parent), myProgressBarStyle (new QStyleOptionProgressBar) @@ -168,7 +252,7 @@ TorrentDelegate::progressString (const Torrent& tor) const str += tr ("Remaining time unknown"); } - return str; + return str.trimmed (); } QString @@ -187,7 +271,7 @@ TorrentDelegate::shortTransferString (const Torrent& tor) const else if (haveUp) str = Formatter::uploadSpeedToString(tor.uploadSpeed()); - return str; + return str.trimmed (); } QString @@ -215,7 +299,7 @@ TorrentDelegate::shortStatusString (const Torrent& tor) const break; } - return str; + return str.trimmed (); } QString @@ -271,46 +355,20 @@ TorrentDelegate::statusString (const Torrent& tor) const str += tr (" - ") + s; } - return str; + return str.trimmed (); } /*** **** ***/ -namespace -{ - int MAX3 (int a, int b, int c) - { - const int ab (a > b ? a : b); - return ab > c ? ab : c; - } -} - QSize TorrentDelegate::sizeHint (const QStyleOptionViewItem& option, const Torrent& tor) const { - const QStyle* style (qApp->style ()); - static const int iconSize (style->pixelMetric (QStyle::PM_MessageBoxIconSize)); - - QFont nameFont (option.font); - nameFont.setWeight (QFont::Bold); - const QFontMetrics nameFM (nameFont); - const QString nameStr (tor.name ()); - const int nameWidth = nameFM.width (nameStr); - QFont statusFont (option.font); - statusFont.setPointSize (static_cast (option.font.pointSize () * 0.9)); - const QFontMetrics statusFM (statusFont); - const QString statusStr (statusString (tor)); - const int statusWidth = statusFM.width (statusStr); - QFont progressFont (statusFont); - const QFontMetrics progressFM (progressFont); - const QString progressStr (progressString (tor)); - const int progressWidth = progressFM.width (progressStr); - const QSize m (margin (*style)); - return QSize (m.width()*2 + iconSize + GUI_PAD + MAX3 (nameWidth, statusWidth, progressWidth), - //m.height()*3 + nameFM.lineSpacing() + statusFM.lineSpacing()*2 + progressFM.lineSpacing()); - m.height()*3 + nameFM.lineSpacing() + statusFM.lineSpacing() + BAR_HEIGHT + progressFM.lineSpacing()); + const QSize m (margin (*qApp->style ())); + const ItemLayout layout (tor.name (), progressString (tor), statusString (tor), QIcon (), + option.font, option.direction, QPoint (0, 0), option.rect.width () - m.width () * 2); + return layout.size () + m * 2; } QSize @@ -358,19 +416,7 @@ TorrentDelegate::drawTorrent (QPainter * painter, const Torrent & tor) const { const QStyle * style (qApp->style ()); - static const int iconSize (style->pixelMetric (QStyle::PM_LargeIconSize)); - QFont nameFont (option.font); - nameFont.setWeight (QFont::Bold); - const QFontMetrics nameFM (nameFont); - const QString nameStr (tor.name ()); - const QSize nameSize (nameFM.size (0, nameStr)); - QFont statusFont (option.font); - statusFont.setPointSize (static_cast (option.font.pointSize () * 0.9)); - const QFontMetrics statusFM (statusFont); - const QString statusStr (progressString (tor)); - QFont progressFont (statusFont); - const QFontMetrics progressFM (progressFont); - const QString progressStr (statusString (tor)); + const bool isPaused (tor.isPaused ()); const bool isItemSelected ((option.state & QStyle::State_Selected) != 0); @@ -424,37 +470,25 @@ TorrentDelegate::drawTorrent (QPainter * painter, // layout const QSize m (margin (*style)); - QRect fillArea (option.rect); - fillArea.adjust (m.width(), m.height(), -m.width(), -m.height()); - QRect iconArea (fillArea.x (), fillArea.y () + (fillArea.height () - iconSize) / 2, iconSize, iconSize); - QRect emblemRect (style->alignedRect (option.direction, Qt::AlignRight | Qt::AlignBottom, - emblemIcon.actualSize (QSize (iconSize / 2, iconSize / 2), emblemIm, qs), iconArea)); - QRect nameArea (iconArea.x () + iconArea.width () + GUI_PAD, fillArea.y (), - fillArea.width () - GUI_PAD - iconArea.width (), nameSize.height ()); - QRect statusArea (nameArea); - statusArea.moveTop (nameArea.y () + nameFM.lineSpacing ()); - statusArea.setHeight (nameSize.height ()); - QRect barArea (statusArea); - barArea.setHeight (BAR_HEIGHT); - barArea.moveTop (statusArea.y () + statusFM.lineSpacing ()); - QRect progArea (statusArea); - progArea.moveTop (barArea.y () + barArea.height ()); + const QRect contentRect (option.rect.adjusted (m.width(), m.height(), -m.width(), -m.height())); + const ItemLayout layout (tor.name (), progressString (tor), statusString (tor), emblemIcon, + option.font, option.direction, contentRect.topLeft (), contentRect.width ()); // render if (tor.hasError () && !isItemSelected) painter->setPen (QColor ("red")); else painter->setPen (option.palette.color (cg, cr)); - tor.getMimeTypeIcon().paint (painter, iconArea, Qt::AlignCenter, im, qs); + tor.getMimeTypeIcon().paint (painter, layout.iconRect, Qt::AlignCenter, im, qs); if (!emblemIcon.isNull ()) - emblemIcon.paint (painter, emblemRect, Qt::AlignCenter, emblemIm, qs); - painter->setFont (nameFont); - painter->drawText (nameArea, 0, nameFM.elidedText (nameStr, Qt::ElideRight, nameArea.width ())); - painter->setFont (statusFont); - painter->drawText (statusArea, 0, statusFM.elidedText (statusStr, Qt::ElideRight, statusArea.width ())); - painter->setFont (progressFont); - painter->drawText (progArea, 0, progressFM.elidedText (progressStr, Qt::ElideRight, progArea.width ())); - myProgressBarStyle->rect = barArea; + emblemIcon.paint (painter, layout.emblemRect, Qt::AlignCenter, emblemIm, qs); + painter->setFont (layout.nameFont); + painter->drawText (layout.nameRect, Qt::AlignLeft | Qt::AlignVCenter, layout.nameText ()); + painter->setFont (layout.statusFont); + painter->drawText (layout.statusRect, Qt::AlignLeft | Qt::AlignVCenter, layout.statusText ()); + painter->setFont (layout.progressFont); + painter->drawText (layout.progressRect, Qt::AlignLeft | Qt::AlignVCenter, layout.progressText ()); + myProgressBarStyle->rect = layout.barRect; if (tor.isDownloading()) { myProgressBarStyle->palette.setBrush (QPalette::Highlight, blueBrush); diff --git a/qt/utils.h b/qt/utils.h index cfa039d31..ce18a1e29 100644 --- a/qt/utils.h +++ b/qt/utils.h @@ -10,9 +10,10 @@ #ifndef QTR_UTILS #define QTR_UTILS -#include -#include #include +#include +#include +#include #include // isxdigit() @@ -34,6 +35,13 @@ class Utils: public QObject static QString removeTrailingDirSeparator (const QString& path); + static void narrowRect (QRect& rect, int dx1, int dx2, Qt::LayoutDirection direction) + { + if (direction == Qt::RightToLeft) + qSwap (dx1, dx2); + rect.adjust (dx1, 0, -dx2, 0); + } + // meh static void toStderr (const QString& qstr);