1 /*
2 * This file Copyright (C) 2012-2015 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 */
8
9 #include <QApplication>
10 #include <QStyle>
11 #include <QStylePainter>
12
13 #include "FilterBarComboBox.h"
14 #include "StyleHelper.h"
15 #include "Utils.h"
16
17 namespace
18 {
19
getHSpacing(QWidget const * w)20 int getHSpacing(QWidget const* w)
21 {
22 return qMax(3, w->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing, nullptr, w));
23 }
24
25 } // namespace
26
FilterBarComboBox(QWidget * parent)27 FilterBarComboBox::FilterBarComboBox(QWidget* parent) :
28 QComboBox(parent)
29 {
30 setSizeAdjustPolicy(QComboBox::AdjustToContents);
31 }
32
minimumSizeHint() const33 QSize FilterBarComboBox::minimumSizeHint() const
34 {
35 QFontMetrics fm(fontMetrics());
36 QSize const textSize = fm.boundingRect(itemText(0)).size();
37 QSize const countSize = fm.boundingRect(itemData(0, CountStringRole).toString()).size();
38 return calculateSize(textSize, countSize);
39 }
40
sizeHint() const41 QSize FilterBarComboBox::sizeHint() const
42 {
43 QFontMetrics fm(fontMetrics());
44 QSize maxTextSize(0, 0);
45 QSize maxCountSize(0, 0);
46
47 for (int i = 0, n = count(); i < n; ++i)
48 {
49 QSize const textSize = fm.boundingRect(itemText(i)).size();
50 maxTextSize.setHeight(qMax(maxTextSize.height(), textSize.height()));
51 maxTextSize.setWidth(qMax(maxTextSize.width(), textSize.width()));
52
53 QSize const countSize = fm.boundingRect(itemData(i, CountStringRole).toString()).size();
54 maxCountSize.setHeight(qMax(maxCountSize.height(), countSize.height()));
55 maxCountSize.setWidth(qMax(maxCountSize.width(), countSize.width()));
56 }
57
58 return calculateSize(maxTextSize, maxCountSize);
59 }
60
calculateSize(QSize const & textSize,QSize const & countSize) const61 QSize FilterBarComboBox::calculateSize(QSize const& textSize, QSize const& countSize) const
62 {
63 int const hmargin = getHSpacing(this);
64
65 QStyleOptionComboBox option;
66 initStyleOption(&option);
67
68 QSize contentSize = iconSize() + QSize(4, 2);
69 contentSize.setHeight(qMax(contentSize.height(), textSize.height()));
70 contentSize.rwidth() += hmargin + textSize.width();
71 contentSize.rwidth() += hmargin + countSize.width();
72
73 return style()->sizeFromContents(QStyle::CT_ComboBox, &option, contentSize, this).expandedTo(qApp->globalStrut());
74 }
75
paintEvent(QPaintEvent * e)76 void FilterBarComboBox::paintEvent(QPaintEvent* e)
77 {
78 Q_UNUSED(e)
79
80 QStylePainter painter(this);
81 painter.setPen(palette().color(QPalette::Text));
82
83 // draw the combobox frame, focusrect and selected etc.
84 QStyleOptionComboBox opt;
85 initStyleOption(&opt);
86 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
87
88 // draw the icon and text
89 QModelIndex const modelIndex = model()->index(currentIndex(), 0, rootModelIndex());
90
91 if (modelIndex.isValid())
92 {
93 QStyle* s = style();
94 int const hmargin = getHSpacing(this);
95
96 QRect rect = s->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
97 rect.adjust(2, 1, -2, -1);
98
99 // draw the icon
100 QIcon const icon = Utils::getIconFromIndex(modelIndex);
101
102 if (!icon.isNull())
103 {
104 QRect const iconRect = QStyle::alignedRect(opt.direction, Qt::AlignLeft | Qt::AlignVCenter, opt.iconSize, rect);
105 icon.paint(&painter, iconRect, Qt::AlignCenter, StyleHelper::getIconMode(opt.state), QIcon::Off);
106 Utils::narrowRect(rect, iconRect.width() + hmargin, 0, opt.direction);
107 }
108
109 // draw the count
110 QString text = modelIndex.data(CountStringRole).toString();
111
112 if (!text.isEmpty())
113 {
114 QPen const pen = painter.pen();
115 painter.setPen(Utils::getFadedColor(pen.color()));
116 QRect const textRect = QStyle::alignedRect(opt.direction, Qt::AlignRight | Qt::AlignVCenter,
117 QSize(opt.fontMetrics.width(text), rect.height()), rect);
118 painter.drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, text);
119 Utils::narrowRect(rect, 0, textRect.width() + hmargin, opt.direction);
120 painter.setPen(pen);
121 }
122
123 // draw the text
124 text = modelIndex.data(Qt::DisplayRole).toString();
125 text = painter.fontMetrics().elidedText(text, Qt::ElideRight, rect.width());
126 painter.drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, text);
127 }
128 }
129