]> git.sur5r.net Git - minitube/blob - src/segmentedcontrol.cpp
New upstream version 2.1.3
[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 "fontutils.h"
23 #include "mainwindow.h"
24 #include "painterutils.h"
25
26 static const QColor borderColor = QColor(0x26, 0x26, 0x26);
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     setMouseTracking(true);
40
41     d->hoveredAction = 0;
42     d->checkedAction = 0;
43     d->pressedAction = 0;
44 }
45
46 SegmentedControl::~SegmentedControl() {
47     delete d;
48 }
49
50 QAction *SegmentedControl::addAction(QAction *action) {
51     QWidget::addAction(action);
52     action->setCheckable(true);
53     d->actionList.append(action);
54     return action;
55 }
56
57 bool SegmentedControl::setCheckedAction(int index) {
58     if (index < 0) {
59         d->checkedAction = 0;
60         return true;
61     }
62     QAction* newCheckedAction = d->actionList.at(index);
63     return setCheckedAction(newCheckedAction);
64 }
65
66 bool SegmentedControl::setCheckedAction(QAction *action) {
67     if (d->checkedAction == action) {
68         return false;
69     }
70     if (d->checkedAction)
71         d->checkedAction->setChecked(false);
72     d->checkedAction = action;
73     d->checkedAction->setChecked(true);
74     update();
75     return true;
76 }
77
78 QSize SegmentedControl::minimumSizeHint (void) const {
79     int itemsWidth = calculateButtonWidth() * d->actionList.size() * 1.2;
80     return(QSize(itemsWidth, QFontMetrics(font()).height() * 1.9));
81 }
82
83 void SegmentedControl::paintEvent (QPaintEvent * /*event*/) {
84     int height = rect().height();
85     int width = rect().width();
86
87     QPainter p(this);
88
89     QLinearGradient linearGrad(rect().topLeft(), rect().bottomLeft());
90     linearGrad.setColorAt(0, borderColor);
91     linearGrad.setColorAt(1, QColor(0x3c, 0x3c, 0x3c));
92     p.fillRect(rect(), QBrush(linearGrad));
93
94     // Calculate Buttons Size & Location
95     const int buttonWidth = width / d->actionList.size();
96
97     // Draw Buttons
98     QRect rect(0, 0, buttonWidth, height);
99     const int actionCount = d->actionList.size();
100     for (int i = 0; i < actionCount; i++) {
101         QAction *action = d->actionList.at(i);
102
103         if (i + 1 == actionCount) {
104             rect.setWidth(width - buttonWidth * (actionCount-1));
105             drawButton(&p, rect, action);
106         } else {
107             drawButton(&p, rect, action);
108             rect.moveLeft(rect.x() + rect.width());
109         }
110
111     }
112
113 }
114
115 void SegmentedControl::mouseMoveEvent (QMouseEvent *event) {
116     QWidget::mouseMoveEvent(event);
117
118     QAction *action = hoveredAction(event->pos());
119
120     if (!action && d->hoveredAction) {
121         d->hoveredAction = 0;
122         update();
123     } else if (action && action != d->hoveredAction) {
124         d->hoveredAction = action;
125         action->hover();
126         update();
127
128         // status tip
129         MainWindow::instance()->statusBar()->showMessage(action->statusTip());
130     }
131 }
132
133 void SegmentedControl::mousePressEvent(QMouseEvent *event) {
134     QWidget::mousePressEvent(event);
135     if (d->hoveredAction) {
136         d->pressedAction = d->hoveredAction;
137         update();
138     }
139 }
140
141 void SegmentedControl::mouseReleaseEvent(QMouseEvent *event) {
142     QWidget::mouseReleaseEvent(event);
143     d->pressedAction = 0;
144     if (d->hoveredAction) {
145         bool changed = setCheckedAction(d->hoveredAction);
146         if (changed) d->hoveredAction->trigger();
147     }
148 }
149
150 void SegmentedControl::leaveEvent(QEvent *event) {
151     QWidget::leaveEvent(event);
152     // status tip
153     // static_cast<QMainWindow*>(window())->statusBar()->clearMessage();
154     d->hoveredAction = 0;
155     d->pressedAction = 0;
156     update();
157 }
158
159 QAction *SegmentedControl::hoveredAction(const QPoint& pos) const {
160     if (pos.y() <= 0 || pos.y() >= height())
161         return 0;
162
163     int buttonWidth = width() / d->actionList.size();
164     int buttonsWidth = width();
165     int buttonsX = 0;
166
167     if (pos.x() <= buttonsX || pos.x() >= (buttonsX + buttonsWidth))
168         return 0;
169
170     int buttonIndex = (pos.x() - buttonsX) / buttonWidth;
171
172     if (buttonIndex >= d->actionList.size())
173         return 0;
174     return(d->actionList[buttonIndex]);
175 }
176
177 int SegmentedControl::calculateButtonWidth (void) const {
178     QFont smallerBoldFont = FontUtils::smallBold();
179     QFontMetrics fontMetrics(smallerBoldFont);
180     int tmpItemWidth, itemWidth = 0;
181     foreach (QAction *action, d->actionList) {
182         tmpItemWidth = fontMetrics.width(action->text());
183         if (itemWidth < tmpItemWidth) itemWidth = tmpItemWidth;
184     }
185     return itemWidth;
186 }
187
188 void SegmentedControl::drawButton (QPainter *painter,
189                               const QRect& rect,
190                               const QAction *action) {
191     if (action == d->checkedAction)
192         drawSelectedButton(painter, rect, action);
193     else
194         drawUnselectedButton(painter, rect, action);
195 }
196
197 void SegmentedControl::drawUnselectedButton (QPainter *painter,
198                                         const QRect& rect,
199                                         const QAction *action) {
200     paintButton(painter, rect, action);
201 }
202
203 void SegmentedControl::drawSelectedButton (QPainter *painter,
204                                       const QRect& rect,
205                                       const QAction *action) {
206     painter->save();
207     painter->translate(rect.topLeft());
208
209     const int width = rect.width();
210     const int height = rect.height();
211     const int hCenter = width * .5;
212     QRadialGradient gradient(hCenter, 0,
213                              width,
214                              hCenter, 0);
215     gradient.setColorAt(1, Qt::black);
216     gradient.setColorAt(0, QColor(0x33, 0x33, 0x33));
217     painter->fillRect(0, 0, width, height, QBrush(gradient));
218
219     painter->restore();
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     if (action == d->pressedAction && action != d->checkedAction) {
231         const int hCenter = width * .5;
232         QRadialGradient gradient(hCenter, 0,
233                                  width,
234                                  hCenter, 0);
235         gradient.setColorAt(1, QColor(0x00, 0x00, 0x00, 0));
236         gradient.setColorAt(0, QColor(0x00, 0x00, 0x00, 16));
237         painter->fillRect(0, 0, width, height, QBrush(gradient));
238     } else if (action == d->hoveredAction && action != d->checkedAction) {
239         const int hCenter = width * .5;
240         QRadialGradient gradient(hCenter, 0,
241                                  width,
242                                  hCenter, 0);
243         gradient.setColorAt(1, QColor(0xff, 0xff, 0xff, 0));
244         gradient.setColorAt(0, QColor(0xff, 0xff, 0xff, 16));
245         painter->fillRect(0, 0, width, height, QBrush(gradient));
246     }
247
248     painter->setPen(borderColor);
249 #if defined(APP_MAC) | defined(APP_WIN)
250     painter->drawRect(-1, -1, width, height);
251 #else
252     painter->drawRect(0, 0, width, height - 1);
253 #endif
254
255     painter->setFont(FontUtils::smallBold());
256
257     const QString text = action->text();
258
259     // text shadow
260     painter->setPen(QColor(0, 0, 0, 128));
261     painter->drawText(0, -1, width, height, Qt::AlignCenter, text);
262
263     painter->setPen(QPen(Qt::white, 1));
264     painter->drawText(0, 0, width, height, Qt::AlignCenter, text);
265
266     if (action->property("notifyCount").isValid()) {
267         QRect textBox = painter->boundingRect(rect,
268                                               Qt::AlignCenter,
269                                               text);
270         painter->translate((width + textBox.width()) / 2 + 10, (height - 20) / 2);
271         PainterUtils::paintBadge(painter, action->property("notifyCount").toString());
272     }
273
274     painter->restore();
275 }