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
9 * @addtogroup CorePlugin Core Plugin
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
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>
35 #include <QColorDialog>
36 #include <QHBoxLayout>
37 #include <QVBoxLayout>
38 #include <QMouseEvent>
39 // #include <QWindowsStyle>
42 #include <QStackedLayout>
44 #include <QToolButton>
47 const int FancyTabBar::m_rounding
= 22;
48 const int FancyTabBar::m_textPadding
= 4;
50 FancyTabBar::FancyTabBar(QWidget
*parent
, bool isVertical
)
53 verticalTabs
= isVertical
;
58 setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Expanding
);
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()
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
);
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
)
97 for (int i
= 0; i
< count(); ++i
) {
98 if (i
!= currentIndex()) {
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())) {
112 for (int i
= 0; i
< count(); ++i
) {
113 QRect area
= tabRect(i
);
114 if (area
.contains(e
->pos())) {
120 m_hoverControl
.stop();
121 m_hoverIndex
= newHover
;
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
);
138 QToolTip::showText(static_cast<QHelpEvent
*>(event
)->globalPos(), tt
, this);
143 return QWidget::event(event
);
146 void FancyTabBar::updateHover()
151 // Resets hover animation on mouse enter
152 void FancyTabBar::enterEvent(QEvent
*e
)
155 m_hoverRect
= QRect();
159 // Resets hover animation on mouse enter
160 void FancyTabBar::leaveEvent(QEvent
*e
)
163 if (m_hoverIndex
>= 0) {
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();
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);
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();
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
)
218 for (int i
= 0; i
< m_tabs
.count(); ++i
) {
219 if (tabRect(i
).contains(e
->pos())) {
226 void FancyTabBar::paintTab(QPainter
*painter
, int tabIndex
) const
230 QRect rect
= tabRect(tabIndex
);
232 bool selected
= (tabIndex
== m_currentIndex
);
233 bool hover
= (tabIndex
== m_hoverIndex
);
236 hover
= false; // Dont hover on Mac
239 QColor background
= QColor(0, 0, 0, 10);
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);
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());
261 painter
->fillRect(rect
, background
);
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());
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
);
294 void FancyTabBar::setCurrentIndex(int index
)
297 emit
aboutToChange(&proceed
);
302 m_currentIndex
= index
;
304 emit
currentChanged(index
);
311 class FancyColorButton
: public QWidget
{
313 FancyColorButton(QWidget
*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
));
333 FancyTabWidget::FancyTabWidget(QWidget
*parent
, bool isVertical
)
336 m_tabBar
= new FancyTabBar(this, isVertical
);
337 m_selectionWidget
= new QWidget(this);
338 QBoxLayout
*selectionLayout
;
340 selectionLayout
= new QVBoxLayout
;
342 selectionLayout
= new QHBoxLayout
;
344 selectionLayout
->setSpacing(0);
345 selectionLayout
->setMargin(0);
347 Utils::StyledBar
*bar
= new Utils::StyledBar
;
350 layout
= new QHBoxLayout(bar
);
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
);
362 m_selectionWidget
->setSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Expanding
);
364 m_selectionWidget
->setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
);
367 m_cornerWidgetContainer
= new QWidget(this);
369 m_cornerWidgetContainer
->setSizePolicy(QSizePolicy::Minimum
, QSizePolicy::Preferred
);
371 m_cornerWidgetContainer
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Minimum
);
373 m_cornerWidgetContainer
->setAutoFillBackground(false);
375 QBoxLayout
*cornerWidgetLayout
;
377 cornerWidgetLayout
= new QVBoxLayout
;
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
);
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);
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
);
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
)
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
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();