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 "fontutils.h"
23 #include "iconutils.h"
24 #include "mainwindow.h"
25 #include "painterutils.h"
27 SegmentedControl::SegmentedControl(QWidget *parent) : QWidget(parent) {
28 setAttribute(Qt::WA_OpaquePaintEvent);
30 setMouseTracking(true);
32 hoveredAction = nullptr;
33 checkedAction = nullptr;
34 pressedAction = nullptr;
37 connect(qApp, &QGuiApplication::paletteChanged, this, [this] {
43 QAction *SegmentedControl::addAction(QAction *action) {
44 QWidget::addAction(action);
45 action->setCheckable(true);
46 actionList.append(action);
50 bool SegmentedControl::setCheckedAction(int index) {
52 checkedAction = nullptr;
55 QAction *newCheckedAction = actionList.at(index);
56 return setCheckedAction(newCheckedAction);
59 bool SegmentedControl::setCheckedAction(QAction *action) {
60 if (checkedAction == action) {
63 if (checkedAction) checkedAction->setChecked(false);
64 checkedAction = action;
65 checkedAction->setChecked(true);
70 QSize SegmentedControl::minimumSizeHint() const {
71 int itemsWidth = calculateButtonWidth() * actionList.size() * 1.2;
72 return (QSize(itemsWidth, QFontMetrics(font()).height() * 1.8));
75 void SegmentedControl::paintEvent(QPaintEvent * /*event*/) {
76 const int height = rect().height();
77 const int width = rect().width();
81 // Calculate Buttons Size & Location
82 const int buttonWidth = width / actionList.size();
84 const qreal pixelRatio = devicePixelRatioF();
85 QPen pen(borderColor);
86 const qreal penWidth = 1. / pixelRatio;
87 pen.setWidthF(penWidth);
91 QRect rect(0, 0, buttonWidth, height);
92 const int actionCount = actionList.size();
93 for (int i = 0; i < actionCount; i++) {
94 QAction *action = actionList.at(i);
95 if (i + 1 == actionCount) {
97 rect.setWidth(width - buttonWidth * (actionCount - 1));
98 paintButton(&p, rect, action);
100 paintButton(&p, rect, action);
101 rect.moveLeft(rect.x() + rect.width());
106 void SegmentedControl::mouseMoveEvent(QMouseEvent *event) {
107 QAction *action = findHoveredAction(event->pos());
109 if (!action && hoveredAction) {
110 hoveredAction = nullptr;
112 } else if (action && action != hoveredAction) {
113 hoveredAction = action;
118 MainWindow::instance()->statusBar()->showMessage(action->statusTip());
122 void SegmentedControl::mousePressEvent(QMouseEvent *event) {
123 QWidget::mousePressEvent(event);
125 pressedAction = hoveredAction;
130 void SegmentedControl::mouseReleaseEvent(QMouseEvent *event) {
131 QWidget::mouseReleaseEvent(event);
132 pressedAction = nullptr;
134 bool changed = setCheckedAction(hoveredAction);
135 if (changed) hoveredAction->trigger();
139 void SegmentedControl::leaveEvent(QEvent *event) {
140 QWidget::leaveEvent(event);
142 MainWindow::instance()->statusBar()->clearMessage();
143 hoveredAction = nullptr;
144 pressedAction = nullptr;
148 void SegmentedControl::setupColors() {
149 selectedColor = palette().color(QPalette::Base);
150 if (selectedColor.value() > 128) {
152 backgroundColor = selectedColor.darker(factor);
153 borderColor = backgroundColor;
154 hoveredColor = backgroundColor.darker(factor);
155 pressedColor = hoveredColor.darker(factor);
158 backgroundColor = selectedColor.lighter(factor);
159 borderColor = backgroundColor;
160 hoveredColor = backgroundColor.lighter(factor);
161 pressedColor = hoveredColor.lighter(factor);
165 QAction *SegmentedControl::findHoveredAction(const QPoint &pos) const {
166 const int w = width();
167 if (pos.y() <= 0 || pos.x() >= w || pos.y() >= height()) return nullptr;
169 int buttonWidth = w / actionList.size();
171 int buttonIndex = pos.x() / buttonWidth;
173 if (buttonIndex >= actionList.size()) return nullptr;
174 return actionList[buttonIndex];
177 int SegmentedControl::calculateButtonWidth() const {
178 QFontMetrics fontMetrics(font());
179 int tmpItemWidth, itemWidth = 0;
180 for (QAction *action : actionList) {
181 tmpItemWidth = fontMetrics.width(action->text());
182 if (itemWidth < tmpItemWidth) itemWidth = tmpItemWidth;
187 void SegmentedControl::paintButton(QPainter *painter, const QRect &rect, const QAction *action) {
189 painter->translate(rect.topLeft());
191 const int height = rect.height();
192 const int width = rect.width();
195 if (action == checkedAction) {
197 } else if (action == pressedAction) {
199 } else if (action == hoveredAction) {
204 painter->fillRect(0, 0, width, height, c);
206 const QString text = action->text();
208 painter->setPen(palette().windowText().color());
209 painter->drawText(0, 0, width, height, Qt::AlignCenter, text);
211 if (action->property("notifyCount").isValid()) {
212 QRect textBox = painter->boundingRect(rect, Qt::AlignCenter, text);
213 painter->translate((width + textBox.width()) / 2 + 10, (height - textBox.height()) / 2);
214 PainterUtils::paintBadge(painter, action->property("notifyCount").toString(), false, c);