LP-56 - Better txpid option namings, fix tabs-spaces, tooltips. headers, variable...
[librepilot.git] / ground / openpilotgcs / src / plugins / config / fancytabwidget.cpp
bloba34d176e2b9bb05906eba70803a7944b78518be6
1 /**
2 ******************************************************************************
4 * @file fancytabwidget.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
7 * @addtogroup GCSPlugins GCS Plugins
8 * @{
9 * @addtogroup CorePlugin Core Plugin
10 * @{
11 * @brief The Core GCS plugin
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "fancytabwidget.h"
30 #include <utils/stylehelper.h>
31 #include <utils/styledbar.h>
33 #include <QDebug>
34 #include <QtPlugin>
35 #include <QColorDialog>
36 #include <QHBoxLayout>
37 #include <QVBoxLayout>
38 #include <QMouseEvent>
39 // #include <QWindowsStyle>
40 #include <QPainter>
41 #include <QSplitter>
42 #include <QStackedLayout>
43 #include <QStatusBar>
44 #include <QToolButton>
45 #include <QToolTip>
47 const int FancyTabBar::m_rounding = 22;
48 const int FancyTabBar::m_textPadding = 4;
50 FancyTabBar::FancyTabBar(QWidget *parent, bool isVertical)
51 : QWidget(parent)
53 verticalTabs = isVertical;
54 setIconSize(16);
55 m_hoverIndex = -1;
56 m_currentIndex = 0;
57 if (isVertical) {
58 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
59 } else {
60 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
62 // setStyle(new QWindowsStyle);
63 setMinimumWidth(qMax(2 * m_rounding, 40));
64 setAttribute(Qt::WA_Hover, true);
65 setFocusPolicy(Qt::NoFocus);
66 m_hoverControl.setFrameRange(0, 20);
67 m_hoverControl.setDuration(130);
68 m_hoverControl.setCurveShape(QTimeLine::EaseInCurve);
69 connect(&m_hoverControl, SIGNAL(frameChanged(int)), this, SLOT(updateHover()));
70 setMouseTracking(true); // Needed for hover events
73 FancyTabBar::~FancyTabBar()
75 delete style();
78 QSize FancyTabBar::tabSizeHint(bool minimum) const
80 QFont boldFont(font());
82 boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
83 boldFont.setBold(true);
84 QFontMetrics fm(boldFont);
85 int spacing = 6;
86 int width = 90 + spacing + 2;
88 int iconHeight = minimum ? 0 : iconSize;
89 return QSize(width, iconHeight + spacing + fm.height());
92 void FancyTabBar::paintEvent(QPaintEvent *event)
94 Q_UNUSED(event)
95 QPainter p(this);
97 for (int i = 0; i < count(); ++i) {
98 if (i != currentIndex()) {
99 paintTab(&p, i);
103 // paint active tab last, since it overlaps the neighbors
104 paintTab(&p, currentIndex());
107 // Handle hover events for mouse fade ins
108 void FancyTabBar::mouseMoveEvent(QMouseEvent *e)
110 if (!m_hoverRect.contains(e->pos())) {
111 int newHover = -1;
112 for (int i = 0; i < count(); ++i) {
113 QRect area = tabRect(i);
114 if (area.contains(e->pos())) {
115 newHover = i;
116 break;
120 m_hoverControl.stop();
121 m_hoverIndex = newHover;
122 update(m_hoverRect);
123 m_hoverRect = QRect();
125 if (m_hoverIndex >= 0) {
126 m_hoverRect = tabRect(m_hoverIndex);
127 m_hoverControl.start();
132 bool FancyTabBar::event(QEvent *event)
134 if (event->type() == QEvent::ToolTip) {
135 if (m_hoverIndex >= 0 && m_hoverIndex < m_tabs.count()) {
136 QString tt = tabToolTip(m_hoverIndex);
137 if (!tt.isEmpty()) {
138 QToolTip::showText(static_cast<QHelpEvent *>(event)->globalPos(), tt, this);
139 return true;
143 return QWidget::event(event);
146 void FancyTabBar::updateHover()
148 update(m_hoverRect);
151 // Resets hover animation on mouse enter
152 void FancyTabBar::enterEvent(QEvent *e)
154 Q_UNUSED(e)
155 m_hoverRect = QRect();
156 m_hoverIndex = -1;
159 // Resets hover animation on mouse enter
160 void FancyTabBar::leaveEvent(QEvent *e)
162 Q_UNUSED(e)
163 if (m_hoverIndex >= 0) {
164 m_hoverIndex = -1;
165 update(m_hoverRect);
166 m_hoverRect = QRect();
170 void FancyTabBar::updateTabNameIcon(int index, const QIcon &icon, const QString &label)
172 m_tabs[index].icon = icon;
173 m_tabs[index].text = label;
176 QSize FancyTabBar::sizeHint() const
178 QSize sh = tabSizeHint();
180 if (verticalTabs) {
181 return QSize(sh.width(), sh.height() * m_tabs.count());
183 return QSize(sh.width() * m_tabs.count(), sh.height());
186 QSize FancyTabBar::minimumSizeHint() const
188 QSize sh = tabSizeHint(true);
190 if (verticalTabs) {
191 return QSize(sh.width(), sh.height() * m_tabs.count());
193 return QSize(sh.width() * m_tabs.count(), sh.height());
196 QRect FancyTabBar::tabRect(int index) const
198 QSize sh = tabSizeHint();
200 if (verticalTabs) {
201 if (sh.height() * m_tabs.count() > height()) {
202 sh.setHeight(height() / m_tabs.count());
205 return QRect(0, index * sh.height(), sh.width(), sh.height());
208 if (sh.width() * m_tabs.count() > width()) {
209 sh.setWidth(width() / m_tabs.count());
212 return QRect(index * sh.width(), 0, sh.width(), sh.height());
215 void FancyTabBar::mousePressEvent(QMouseEvent *e)
217 e->accept();
218 for (int i = 0; i < m_tabs.count(); ++i) {
219 if (tabRect(i).contains(e->pos())) {
220 setCurrentIndex(i);
221 break;
226 void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
228 painter->save();
230 QRect rect = tabRect(tabIndex);
232 bool selected = (tabIndex == m_currentIndex);
233 bool hover = (tabIndex == m_hoverIndex);
235 #ifdef Q_WS_MAC
236 hover = false; // Dont hover on Mac
237 #endif
239 QColor background = QColor(0, 0, 0, 10);
240 QColor hoverColor;
242 if (hover) {
243 hoverColor = QColor(255, 255, 255, m_hoverControl.currentFrame());
246 QColor light = QColor(255, 255, 255, 40);
247 QColor dark = QColor(0, 0, 0, 60);
249 if (selected) {
250 QLinearGradient selectedGradient(rect.bottomRight(), QPoint(rect.center().x(), rect.top()));
251 selectedGradient.setColorAt(0, Qt::white);
252 selectedGradient.setColorAt(0.3, Qt::white);
253 selectedGradient.setColorAt(0.7, QColor(210, 210, 220)); // give a blue-ish color
255 painter->fillRect(rect, selectedGradient);
256 painter->setPen(QColor(200, 200, 200));
257 painter->drawLine(rect.topLeft(), rect.bottomLeft());
258 painter->setPen(QColor(150, 160, 200));
259 painter->drawLine(rect.topRight(), rect.bottomRight());
260 } else {
261 painter->fillRect(rect, background);
262 if (hover) {
263 painter->fillRect(rect, hoverColor);
265 painter->setPen(QPen(light, 0));
266 painter->drawLine(rect.topLeft(), rect.bottomLeft());
267 painter->setPen(QPen(dark, 0));
268 painter->drawLine(rect.topRight(), rect.bottomRight());
271 QString tabText(this->tabText(tabIndex));
272 QRect tabTextRect(tabRect(tabIndex));
273 QRect tabIconRect(tabTextRect);
274 QFont boldFont(painter->font());
275 boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
276 boldFont.setBold(true);
277 painter->setFont(boldFont);
278 painter->setPen(selected ? Utils::StyleHelper::panelTextColor() : QColor(30, 30, 30, 80));
279 int textFlags = Qt::AlignCenter | Qt::AlignBottom | Qt::ElideRight | Qt::TextWordWrap;
280 painter->drawText(tabTextRect, textFlags, tabText);
281 painter->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor());
282 int textHeight = painter->fontMetrics().boundingRect(QRect(0, 0, width(), height()), Qt::TextWordWrap, tabText).height();
283 tabIconRect.adjust(0, 4, 0, -textHeight);
284 int iconSize = qMin(tabIconRect.width(), tabIconRect.height());
285 if (iconSize > 4) {
286 style()->drawItemPixmap(painter, tabIconRect, Qt::AlignCenter | Qt::AlignVCenter,
287 tabIcon(tabIndex).pixmap(tabIconRect.size()));
289 painter->translate(0, -1);
290 painter->drawText(tabTextRect, textFlags, tabText);
291 painter->restore();
294 void FancyTabBar::setCurrentIndex(int index)
296 bool proceed = true;
297 emit aboutToChange(&proceed);
299 if (!proceed) {
300 return;
302 m_currentIndex = index;
303 update();
304 emit currentChanged(index);
307 //////
308 // FancyColorButton
309 //////
311 class FancyColorButton : public QWidget {
312 public:
313 FancyColorButton(QWidget *parent)
314 : m_parent(parent)
316 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
319 void mousePressEvent(QMouseEvent *ev)
321 if (ev->modifiers() & Qt::ShiftModifier) {
322 Utils::StyleHelper::setBaseColor(QColorDialog::getColor(Utils::StyleHelper::baseColor(), m_parent));
325 private:
326 QWidget *m_parent;
329 //////
330 // FancyTabWidget
331 //////
333 FancyTabWidget::FancyTabWidget(QWidget *parent, bool isVertical)
334 : QWidget(parent)
336 m_tabBar = new FancyTabBar(this, isVertical);
337 m_selectionWidget = new QWidget(this);
338 QBoxLayout *selectionLayout;
339 if (isVertical) {
340 selectionLayout = new QVBoxLayout;
341 } else {
342 selectionLayout = new QHBoxLayout;
344 selectionLayout->setSpacing(0);
345 selectionLayout->setMargin(0);
347 Utils::StyledBar *bar = new Utils::StyledBar;
348 QBoxLayout *layout;
349 if (isVertical) {
350 layout = new QHBoxLayout(bar);
351 } else {
352 layout = new QVBoxLayout(bar);
354 layout->setMargin(0);
355 layout->setSpacing(0);
356 layout->addWidget(new FancyColorButton(this));
357 selectionLayout->addWidget(bar);
359 selectionLayout->addWidget(m_tabBar, 1);
360 m_selectionWidget->setLayout(selectionLayout);
361 if (isVertical) {
362 m_selectionWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
363 } else {
364 m_selectionWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
367 m_cornerWidgetContainer = new QWidget(this);
368 if (isVertical) {
369 m_cornerWidgetContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
370 } else {
371 m_cornerWidgetContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
373 m_cornerWidgetContainer->setAutoFillBackground(false);
375 QBoxLayout *cornerWidgetLayout;
376 if (isVertical) {
377 cornerWidgetLayout = new QVBoxLayout;
378 } else {
379 cornerWidgetLayout = new QHBoxLayout;
381 cornerWidgetLayout->setSpacing(0);
382 cornerWidgetLayout->setMargin(0);
383 cornerWidgetLayout->addStretch();
384 m_cornerWidgetContainer->setLayout(cornerWidgetLayout);
386 selectionLayout->addWidget(m_cornerWidgetContainer, 0);
388 m_modesStack = new QStackedLayout;
389 m_statusBar = new QStatusBar;
390 m_statusBar->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
392 QVBoxLayout *vlayout = new QVBoxLayout;
393 vlayout->setMargin(0);
394 vlayout->setSpacing(0);
395 vlayout->addLayout(m_modesStack);
396 if (!isVertical) {
397 vlayout->addWidget(m_selectionWidget);
399 // vlayout->addWidget(m_statusBar); //status bar is not used for now
401 QHBoxLayout *mainLayout = new QHBoxLayout;
402 mainLayout->setMargin(0);
403 mainLayout->setSpacing(1);
404 if (isVertical) {
405 mainLayout->addWidget(m_selectionWidget);
407 mainLayout->addLayout(vlayout);
408 setLayout(mainLayout);
410 connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(showWidget(int)));
413 void FancyTabWidget::insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label)
415 m_modesStack->insertWidget(index, tab);
416 m_tabBar->insertTab(index, icon, label);
419 void FancyTabWidget::removeTab(int index)
421 m_modesStack->removeWidget(m_modesStack->widget(index));
422 m_tabBar->removeTab(index);
425 void FancyTabWidget::updateTabNameIcon(int index, const QIcon &icon, const QString &label)
427 m_tabBar->updateTabNameIcon(index, icon, label);
428 m_tabBar->repaint();
432 void FancyTabWidget::setBackgroundBrush(const QBrush &brush)
434 QPalette pal = m_tabBar->palette();
436 pal.setBrush(QPalette::Mid, brush);
437 m_tabBar->setPalette(pal);
438 pal = m_cornerWidgetContainer->palette();
439 pal.setBrush(QPalette::Mid, brush);
440 m_cornerWidgetContainer->setPalette(pal);
443 void FancyTabWidget::paintEvent(QPaintEvent *event)
445 Q_UNUSED(event)
446 QPainter p(this);
448 QRect rect = m_selectionWidget->geometry().adjusted(0, 0, 1, 0);
449 rect = style()->visualRect(layoutDirection(), geometry(), rect);
450 Utils::StyleHelper::verticalGradient(&p, rect, rect);
451 p.setPen(Utils::StyleHelper::borderColor());
452 p.drawLine(rect.topLeft(), rect.topRight());
455 void FancyTabWidget::insertCornerWidget(int pos, QWidget *widget)
457 QHBoxLayout *layout = static_cast<QHBoxLayout *>(m_cornerWidgetContainer->layout());
459 layout->insertWidget(pos, widget);
462 int FancyTabWidget::cornerWidgetCount() const
464 return m_cornerWidgetContainer->layout()->count();
467 void FancyTabWidget::addCornerWidget(QWidget *widget)
469 m_cornerWidgetContainer->layout()->addWidget(widget);
472 int FancyTabWidget::currentIndex() const
474 return m_tabBar->currentIndex();
477 QStatusBar *FancyTabWidget::statusBar() const
479 return m_statusBar;
482 void FancyTabWidget::setCurrentIndex(int index)
484 m_tabBar->setCurrentIndex(index);
487 void FancyTabWidget::showWidget(int index)
489 emit currentAboutToShow(index);
491 m_modesStack->setCurrentIndex(index);
492 emit currentChanged(index);
495 void FancyTabWidget::setTabToolTip(int index, const QString &toolTip)
497 m_tabBar->setTabToolTip(index, toolTip);
499 QWidget *FancyTabWidget::currentWidget()
501 return m_modesStack->currentWidget();