]> git.sur5r.net Git - minitube/blob - src/segmentedcontrol.cpp
1af157e950d77cccd6b83a128a1ed9c477d5cf04
[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 "fontutils.h"
24 #include "iconutils.h"
25 #include "painterutils.h"
26
27 SegmentedControl::SegmentedControl (QWidget *parent) : QWidget(parent) {
28     setAttribute(Qt::WA_OpaquePaintEvent);
29
30     setMouseTracking(true);
31
32     hoveredAction = 0;
33     checkedAction = 0;
34     pressedAction = 0;
35
36 #ifdef APP_WIN
37     selectedColor = palette().color(QPalette::Base);
38 #else
39     selectedColor = palette().color(QPalette::Window);
40 #endif
41     int darkerFactor = 105;
42     backgroundColor = selectedColor.darker(darkerFactor);
43     borderColor = backgroundColor;
44     hoveredColor = backgroundColor.darker(darkerFactor);
45     pressedColor = hoveredColor.darker(darkerFactor);
46 }
47
48 QAction *SegmentedControl::addAction(QAction *action) {
49     QWidget::addAction(action);
50     action->setCheckable(true);
51     actionList.append(action);
52     return action;
53 }
54
55 bool SegmentedControl::setCheckedAction(int index) {
56     if (index < 0) {
57         checkedAction = 0;
58         return true;
59     }
60     QAction* newCheckedAction = actionList.at(index);
61     return setCheckedAction(newCheckedAction);
62 }
63
64 bool SegmentedControl::setCheckedAction(QAction *action) {
65     if (checkedAction == action) {
66         return false;
67     }
68     if (checkedAction)
69         checkedAction->setChecked(false);
70     checkedAction = action;
71     checkedAction->setChecked(true);
72     update();
73     return true;
74 }
75
76 QSize SegmentedControl::minimumSizeHint (void) const {
77     int itemsWidth = calculateButtonWidth() * actionList.size() * 1.2;
78     return(QSize(itemsWidth, QFontMetrics(font()).height() * 1.8));
79 }
80
81 void SegmentedControl::paintEvent (QPaintEvent * /*event*/) {
82     const int height = rect().height();
83     const int width = rect().width();
84
85     QPainter p(this);
86
87     // Calculate Buttons Size & Location
88     const int buttonWidth = width / actionList.size();
89
90     const qreal pixelRatio = IconUtils::pixelRatio();
91
92     QPen pen(borderColor);
93     const qreal penWidth = 1. / pixelRatio;
94     pen.setWidthF(penWidth);
95     p.setPen(pen);
96
97     // Draw Buttons
98     QRect rect(0, 0, buttonWidth, height);
99     const int actionCount = actionList.size();
100     for (int i = 0; i < actionCount; i++) {
101         QAction *action = actionList.at(i);
102         if (i + 1 == actionCount) {
103             // last button
104             rect.setWidth(width - buttonWidth * (actionCount-1));
105             paintButton(&p, rect, action);
106         } else {
107             paintButton(&p, rect, action);
108             rect.moveLeft(rect.x() + rect.width());
109         }
110     }
111     const qreal y = height - penWidth;
112     p.drawLine(QPointF(0, y), QPointF(width, y));
113 }
114
115 void SegmentedControl::mouseMoveEvent (QMouseEvent *event) {
116     QAction *action = findHoveredAction(event->pos());
117
118     if (!action && hoveredAction) {
119         hoveredAction = 0;
120         update();
121     } else if (action && action != hoveredAction) {
122         hoveredAction = action;
123         action->hover();
124         update();
125
126         // status tip
127         MainWindow::instance()->statusBar()->showMessage(action->statusTip());
128     }
129 }
130
131 void SegmentedControl::mousePressEvent(QMouseEvent *event) {
132     QWidget::mousePressEvent(event);
133     if (hoveredAction) {
134         pressedAction = hoveredAction;
135         update();
136     }
137 }
138
139 void SegmentedControl::mouseReleaseEvent(QMouseEvent *event) {
140     QWidget::mouseReleaseEvent(event);
141     pressedAction = 0;
142     if (hoveredAction) {
143         bool changed = setCheckedAction(hoveredAction);
144         if (changed) hoveredAction->trigger();
145     }
146 }
147
148 void SegmentedControl::leaveEvent(QEvent *event) {
149     QWidget::leaveEvent(event);
150     // status tip
151     MainWindow::instance()->statusBar()->clearMessage();
152     hoveredAction = 0;
153     pressedAction = 0;
154     update();
155 }
156
157 QAction *SegmentedControl::findHoveredAction(const QPoint& pos) const {
158     const int w = width();
159     if (pos.y() <= 0 || pos.x() >= w || pos.y() >= height())
160         return 0;
161
162     int buttonWidth = w / actionList.size();
163
164     int buttonIndex = pos.x() / buttonWidth;
165
166     if (buttonIndex >= actionList.size())
167         return 0;
168     return actionList[buttonIndex];
169 }
170
171 int SegmentedControl::calculateButtonWidth() const {
172     QFontMetrics fontMetrics(font());
173     int tmpItemWidth, itemWidth = 0;
174     for (QAction *action : actionList) {
175         tmpItemWidth = fontMetrics.width(action->text());
176         if (itemWidth < tmpItemWidth) itemWidth = tmpItemWidth;
177     }
178     return itemWidth;
179 }
180
181 void SegmentedControl::paintButton(QPainter *painter, const QRect& rect, const QAction *action) {
182     painter->save();
183     painter->translate(rect.topLeft());
184
185     const int height = rect.height();
186     const int width = rect.width();
187
188     QColor c;
189     if (action == checkedAction) {
190         c = selectedColor;
191     } else if (action == pressedAction) {
192         c = pressedColor;
193     } else if (action == hoveredAction) {
194         c = hoveredColor;
195     } else {
196         c = backgroundColor;
197     }
198     painter->fillRect(0, 0, width, height, c);
199
200     const QString text = action->text();
201
202     painter->setPen(palette().windowText().color());
203     painter->drawText(0, 0, width, height, Qt::AlignCenter, text);
204
205     if (action->property("notifyCount").isValid()) {
206         QRect textBox = painter->boundingRect(rect,
207                                               Qt::AlignCenter,
208                                               text);
209         painter->translate((width + textBox.width()) / 2 + 10, (height - textBox.height()) / 2);
210         PainterUtils::paintBadge(painter, action->property("notifyCount").toString(), false, QColor(0,0,0,64));
211     }
212
213     painter->restore();
214 }