3 This file is part of Minitube.
4 Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
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.
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.
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/>.
21 #include "segmentedcontrol.h"
22 #include "mainwindow.h"
23 #include "painterutils.h"
24 #include "fontutils.h"
26 static const QColor borderColor = QColor(158, 157, 159);
28 class SegmentedControl::Private {
30 QList<QAction *> actionList;
31 QAction *checkedAction;
32 QAction *hoveredAction;
33 QAction *pressedAction;
36 SegmentedControl::SegmentedControl (QWidget *parent)
37 : QWidget(parent), d(new SegmentedControl::Private) {
39 setFont(FontUtils::small());
41 setMouseTracking(true);
48 SegmentedControl::~SegmentedControl() {
52 QAction *SegmentedControl::addAction(QAction *action) {
53 QWidget::addAction(action);
54 action->setCheckable(true);
55 d->actionList.append(action);
59 bool SegmentedControl::setCheckedAction(int index) {
64 QAction* newCheckedAction = d->actionList.at(index);
65 return setCheckedAction(newCheckedAction);
68 bool SegmentedControl::setCheckedAction(QAction *action) {
69 if (d->checkedAction == action) {
73 d->checkedAction->setChecked(false);
74 d->checkedAction = action;
75 d->checkedAction->setChecked(true);
80 QSize SegmentedControl::minimumSizeHint (void) const {
81 int itemsWidth = calculateButtonWidth() * d->actionList.size() * 1.2;
82 return(QSize(itemsWidth, QFontMetrics(font()).height() * 1.9));
85 void SegmentedControl::paintEvent (QPaintEvent * /*event*/) {
86 int height = rect().height();
87 int width = rect().width();
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));
96 // Calculate Buttons Size & Location
97 const int buttonWidth = width / d->actionList.size();
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);
108 drawButton(&p, rect, action);
109 rect.moveLeft(rect.x() + rect.width());
114 void SegmentedControl::mouseMoveEvent (QMouseEvent *event) {
115 QWidget::mouseMoveEvent(event);
117 QAction *action = hoveredAction(event->pos());
119 if (!action && d->hoveredAction) {
120 d->hoveredAction = 0;
122 } else if (action && action != d->hoveredAction) {
123 d->hoveredAction = action;
128 MainWindow::instance()->statusBar()->showMessage(action->statusTip());
132 void SegmentedControl::mousePressEvent(QMouseEvent *event) {
133 QWidget::mousePressEvent(event);
134 if (d->hoveredAction) {
135 d->pressedAction = d->hoveredAction;
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();
149 void SegmentedControl::leaveEvent(QEvent *event) {
150 QWidget::leaveEvent(event);
152 MainWindow::instance()->statusBar()->clearMessage();
153 d->hoveredAction = 0;
154 d->pressedAction = 0;
158 QAction *SegmentedControl::hoveredAction(const QPoint& pos) const {
159 if (pos.y() <= 0 || pos.y() >= height())
162 int buttonWidth = width() / d->actionList.size();
163 int buttonsWidth = width();
166 if (pos.x() <= buttonsX || pos.x() >= (buttonsX + buttonsWidth))
169 int buttonIndex = (pos.x() - buttonsX) / buttonWidth;
171 if (buttonIndex >= d->actionList.size())
173 return(d->actionList[buttonIndex]);
176 int SegmentedControl::calculateButtonWidth (void) 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;
186 void SegmentedControl::drawButton (QPainter *painter,
188 const QAction *action) {
189 if (action == d->checkedAction)
190 drawSelectedButton(painter, rect, action);
192 drawUnselectedButton(painter, rect, action);
195 void SegmentedControl::drawUnselectedButton (QPainter *painter,
197 const QAction *action) {
198 painter->setPen(QPen(QColor(0, 0, 0, 128), 1));
199 paintButton(painter, rect, action);
202 void SegmentedControl::drawSelectedButton (QPainter *painter,
204 const QAction *action) {
206 painter->translate(rect.topLeft());
208 const int width = rect.width();
209 const int height = rect.height();
210 const int hCenter = width * .5;
211 QRadialGradient gradient(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));
219 painter->setPen(QPen(QColor(0, 0, 0, 232), 1));
220 paintButton(painter, rect, action);
223 void SegmentedControl::paintButton(QPainter *painter, const QRect& rect, const QAction *action) {
225 painter->translate(rect.topLeft());
227 const int height = rect.height();
228 const int width = rect.width();
231 painter->setPen(borderColor);
232 #if defined(APP_MAC) | defined(APP_WIN)
233 painter->drawRect(-1, -1, width, height);
235 painter->drawRect(0, 0, width, height - 1);
239 const QString text = action->text();
243 painter->setPen(QColor(0, 0, 0, 128));
244 painter->drawText(0, -1, width, height, Qt::AlignCenter, text);
247 painter->drawText(0, 0, width, height, Qt::AlignCenter, text);
249 if (action->property("notifyCount").isValid()) {
250 QRect textBox = painter->boundingRect(rect,
253 painter->translate((width + textBox.width()) / 2 + 10, (height - 20) / 2);
254 PainterUtils::paintBadge(painter, action->property("notifyCount").toString());
257 if (action == d->pressedAction && action != d->checkedAction) {
258 const int hCenter = width * .5;
259 QRadialGradient gradient(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,
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));