]> granicus.if.org Git - transmission/commitdiff
Improve overall look of torrents in main window
authorMike Gelfand <mikedld@mikedld.com>
Sat, 17 Jan 2015 16:59:42 +0000 (16:59 +0000)
committerMike Gelfand <mikedld@mikedld.com>
Sat, 17 Jan 2015 16:59:42 +0000 (16:59 +0000)
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.

qt/filterbar.cc
qt/torrent-delegate-min.cc
qt/torrent-delegate.cc
qt/utils.h

index 0880f37b3df057bf3bc6664b7678ba16b6dbc36f..99bb7121b0aa868655c94f998d9e0e1e63aa1371 100644 (file)
@@ -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);
         }
 
index fd5b6bc7a6f2ba6e61e624f81643bb9fecb8e643..ef992e45fe6092b653bab333f754b78ed6e564c9 100644 (file)
@@ -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<int> (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<int>(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<int> (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<int> (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);
index 1926f70b4389d71a3f6fe8d49b47c9fb65657d72..df6f76ef7aa5b0443c7257b5039704c772d800df 100644 (file)
@@ -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<int> (statusFont.pointSize () * 0.9));
+    const QFontMetrics statusFM (statusFont);
+    const QSize statusSize (statusFM.size (0, myStatusText));
+
+    progressFont.setPointSize (static_cast<int> (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<int> (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<int> (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);
index cfa039d31293ed5f847530a2fdf0aa4fd54f5873..ce18a1e29015873ff678498a351b4c88f0215091 100644 (file)
 #ifndef QTR_UTILS
 #define QTR_UTILS
 
-#include <QString>
-#include <QObject>
 #include <QIcon>
+#include <QObject>
+#include <QRect>
+#include <QString>
 
 #include <cctype> // 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);