]> git.sur5r.net Git - minitube/blob - src/segmentedcontrol.cpp
Imported Upstream version 2.5.1
[minitube] / src / segmentedcontrol.cpp
1 /* $BEGIN_LICENSE
2
3 This file is part of Minitube.
4 Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
5
6 Minitube is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Minitube is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Minitube.  If not, see <http://www.gnu.org/licenses/>.
18
19 $END_LICENSE */
20
21 #include "segmentedcontrol.h"
22 #include "mainwindow.h"
23 #include "painterutils.h"
24 #include "fontutils.h"
25
26 static const QColor borderColor = QColor(158, 157, 159);
27
28 class SegmentedControl::Private {
29 public:
30     QList<QAction *> actionList;
31     QAction *checkedAction;
32     QAction *hoveredAction;
33     QAction *pressedAction;
34 };
35
36 SegmentedControl::SegmentedControl (QWidget *parent)
37     : QWidget(parent), d(new SegmentedControl::Private) {
38
39     setFont(FontUtils::small());
40
41     setMouseTracking(true);
42
43     d->hoveredAction = 0;
44     d->checkedAction = 0;
45     d->pressedAction = 0;
46 }
47
48 SegmentedControl::~SegmentedControl() {
49     delete d;
50 }
51
52 QAction *SegmentedControl::addAction(QAction *action) {
53     QWidget::addAction(action);
54     action->setCheckable(true);
55     d->actionList.append(action);
56     return action;
57 }
58
59 bool SegmentedControl::setCheckedAction(int index) {
60     if (index < 0) {
61         d->checkedAction = 0;
62         return true;
63     }
64     QAction* newCheckedAction = d->actionList.at(index);
65     return setCheckedAction(newCheckedAction);
66 }
67
68 bool SegmentedControl::setCheckedAction(QAction *action) {
69     if (d->checkedAction == action) {
70         return false;
71     }
72     if (d->checkedAction)
73         d->checkedAction->setChecked(false);
74     d->checkedAction = action;
75     d->checkedAction->setChecked(true);
76     update();
77     return true;
78 }
79
80 QSize SegmentedControl::minimumSizeHint (void) const {
81     int itemsWidth = calculateButtonWidth() * d->actionList.size() * 1.2;
82     return(QSize(itemsWidth, QFontMetrics(font()).height() * 1.9));
83 }
84
85 void SegmentedControl::paintEvent (QPaintEvent * /*event*/) {
86     int height = rect().height();
87     int width = rect().width();
88
89     QPainter p(this);
90
91     QLinearGradient linearGrad(rect().topLeft(), rect().bottomLeft());
92     linearGrad.setColorAt(0, QColor(185, 183, 185));
93     linearGrad.setColorAt(1, QColor(176, 176, 178));
94     p.fillRect(rect(), QBrush(linearGrad));
95
96     // Calculate Buttons Size & Location
97     const int buttonWidth = width / d->actionList.size();
98
99     // Draw Buttons
100     QRect rect(0, 0, buttonWidth, height);
101     const int actionCount = d->actionList.size();
102     for (int i = 0; i < actionCount; i++) {
103         QAction *action = d->actionList.at(i);
104         if (i + 1 == actionCount) {
105             rect.setWidth(width - buttonWidth * (actionCount-1));
106             drawButton(&p, rect, action);
107         } else {
108             drawButton(&p, rect, action);
109             rect.moveLeft(rect.x() + rect.width());
110         }
111     }
112 }
113
114 void SegmentedControl::mouseMoveEvent (QMouseEvent *event) {
115     QWidget::mouseMoveEvent(event);
116
117     QAction *action = hoveredAction(event->pos());
118
119     if (!action && d->hoveredAction) {
120         d->hoveredAction = 0;
121         update();
122     } else if (action && action != d->hoveredAction) {
123         d->hoveredAction = action;
124         action->hover();
125         update();
126
127         // status tip
128         MainWindow::instance()->statusBar()->showMessage(action->statusTip());
129     }
130 }
131
132 void SegmentedControl::mousePressEvent(QMouseEvent *event) {
133     QWidget::mousePressEvent(event);
134     if (d->hoveredAction) {
135         d->pressedAction = d->hoveredAction;
136         update();
137     }
138 }
139
140 void SegmentedControl::mouseReleaseEvent(QMouseEvent *event) {
141     QWidget::mouseReleaseEvent(event);
142     d->pressedAction = 0;
143     if (d->hoveredAction) {
144         bool changed = setCheckedAction(d->hoveredAction);
145         if (changed) d->hoveredAction->trigger();
146     }
147 }
148
149 void SegmentedControl::leaveEvent(QEvent *event) {
150     QWidget::leaveEvent(event);
151     // status tip
152     MainWindow::instance()->statusBar()->clearMessage();
153     d->hoveredAction = 0;
154     d->pressedAction = 0;
155     update();
156 }
157
158 QAction *SegmentedControl::hoveredAction(const QPoint& pos) const {
159     if (pos.y() <= 0 || pos.y() >= height())
160         return 0;
161
162     int buttonWidth = width() / d->actionList.size();
163     int buttonsWidth = width();
164     int buttonsX = 0;
165
166     if (pos.x() <= buttonsX || pos.x() >= (buttonsX + buttonsWidth))
167         return 0;
168
169     int buttonIndex = (pos.x() - buttonsX) / buttonWidth;
170
171     if (buttonIndex >= d->actionList.size())
172         return 0;
173     return(d->actionList[buttonIndex]);
174 }
175
176 int SegmentedControl::calculateButtonWidth() const {
177     QFontMetrics fontMetrics(font());
178     int tmpItemWidth, itemWidth = 0;
179     foreach (QAction *action, d->actionList) {
180         tmpItemWidth = fontMetrics.width(action->text());
181         if (itemWidth < tmpItemWidth) itemWidth = tmpItemWidth;
182     }
183     return itemWidth;
184 }
185
186 void SegmentedControl::drawButton (QPainter *painter,
187                               const QRect& rect,
188                               const QAction *action) {
189     if (action == d->checkedAction)
190         drawSelectedButton(painter, rect, action);
191     else
192         drawUnselectedButton(painter, rect, action);
193 }
194
195 void SegmentedControl::drawUnselectedButton (QPainter *painter,
196                                         const QRect& rect,
197                                         const QAction *action) {
198     painter->setPen(QColor(0, 0, 0, 128));
199     paintButton(painter, rect, action);
200 }
201
202 void SegmentedControl::drawSelectedButton (QPainter *painter,
203                                       const QRect& rect,
204                                       const QAction *action) {
205     painter->save();
206     painter->translate(rect.topLeft());
207
208     const int width = rect.width();
209     const int height = rect.height();
210     const int hCenter = width * .5;
211     QRadialGradient gradient(hCenter, 0,
212                              width,
213                              hCenter, 0);
214     gradient.setColorAt(1, QColor(212, 210, 212));
215     gradient.setColorAt(0, QColor(203, 203, 205));
216     painter->fillRect(0, 0, width, height, QBrush(gradient));
217
218     painter->restore();
219     painter->setPen(palette().windowText().color());
220     paintButton(painter, rect, action);
221 }
222
223 void SegmentedControl::paintButton(QPainter *painter, const QRect& rect, const QAction *action) {
224     painter->save();
225     painter->translate(rect.topLeft());
226
227     const int height = rect.height();
228     const int width = rect.width();
229
230     painter->save();
231     painter->setPen(QPen(borderColor, 1.0 / qApp->devicePixelRatio()));
232 #if defined(APP_MAC) | defined(APP_WIN)
233     painter->drawRect(-1, -1, width, height);
234 #else
235     painter->drawRect(0, 0, width, height - 1);
236 #endif
237     painter->restore();
238
239     const QString text = action->text();
240
241     // text shadow
242     /*
243     painter->setPen(QColor(0, 0, 0, 128));
244     painter->drawText(0, -1, width, height, Qt::AlignCenter, text);
245     */
246
247     painter->drawText(0, 0, width, height, Qt::AlignCenter, text);
248
249     if (action->property("notifyCount").isValid()) {
250         QRect textBox = painter->boundingRect(rect,
251                                               Qt::AlignCenter,
252                                               text);
253         painter->translate((width + textBox.width()) / 2 + 10, (height - 20) / 2);
254         PainterUtils::paintBadge(painter, action->property("notifyCount").toString());
255     }
256
257     if (action == d->pressedAction && action != d->checkedAction) {
258         const int hCenter = width * .5;
259         QRadialGradient gradient(hCenter, 0,
260                                  width,
261                                  hCenter, 0);
262         gradient.setColorAt(1, QColor(0x00, 0x00, 0x00, 0));
263         gradient.setColorAt(0, QColor(0x00, 0x00, 0x00, 32));
264         painter->fillRect(0, 0, width, height, QBrush(gradient));
265     } else if (action == d->hoveredAction && action != d->checkedAction) {
266         const int hCenter = width * .5;
267         QRadialGradient gradient(hCenter, 0,
268                                  width,
269                                  hCenter, 0);
270         gradient.setColorAt(1, QColor(0x00, 0x00, 0x00, 0));
271         gradient.setColorAt(0, QColor(0x00, 0x00, 0x00, 16));
272         painter->fillRect(0, 0, width, height, QBrush(gradient));
273     }
274
275     painter->restore();
276 }