diff --git a/src/libs/vwidgets/fancytabbar/fancytab.cpp b/src/libs/vwidgets/fancytabbar/fancytab.cpp new file mode 100644 index 000000000..a01749bf0 --- /dev/null +++ b/src/libs/vwidgets/fancytabbar/fancytab.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "fancytab.h" + +#include + +//--------------------------------------------------------------------------------------------------------------------- +FancyTab::FancyTab(QWidget *tabbar) + : m_icon(), + m_text(), + m_toolTip(), + m_enabled(false), + m_Animator(), + m_TabBar(tabbar), + m_Fader(0) +{ + m_Animator.setPropertyName("fader"); + m_Animator.setTargetObject(this); +} + +//--------------------------------------------------------------------------------------------------------------------- +float FancyTab::fader() +{ + return m_Fader; +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTab::fadeIn() +{ + m_Animator.stop(); + m_Animator.setDuration(80); + m_Animator.setEndValue(40); + m_Animator.start(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTab::fadeOut() +{ + m_Animator.stop(); + m_Animator.setDuration(160); + m_Animator.setEndValue(0); + m_Animator.start(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTab::setFader(float value) +{ + m_Fader = value; + m_TabBar->update(); +} diff --git a/src/libs/vwidgets/fancytabbar/fancytab.h b/src/libs/vwidgets/fancytabbar/fancytab.h new file mode 100644 index 000000000..8b3ee4adc --- /dev/null +++ b/src/libs/vwidgets/fancytabbar/fancytab.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef FANCYTAB_H +#define FANCYTAB_H + +#include +#include + +class FancyTab : public QObject +{ + friend class FancyTabBar; + Q_OBJECT + + Q_PROPERTY(float fader READ fader WRITE setFader) +public: + explicit FancyTab(QWidget *tabbar); + + float fader(); + void setFader(float value); + + void fadeIn(); + void fadeOut(); + +private: + Q_DISABLE_COPY(FancyTab) + QIcon m_icon; + QString m_text; + QString m_toolTip; + bool m_enabled; + QPropertyAnimation m_Animator; + QWidget *m_TabBar; + float m_Fader; +}; + +#endif // FANCYTAB_H diff --git a/src/libs/vwidgets/fancytabbar/fancytabbar.cpp b/src/libs/vwidgets/fancytabbar/fancytabbar.cpp new file mode 100644 index 000000000..d4b8e52ba --- /dev/null +++ b/src/libs/vwidgets/fancytabbar/fancytabbar.cpp @@ -0,0 +1,657 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "fancytabbar.h" +#include "stylehelper.h" + +#include +#include +#include +#include +#include + +const int FancyTabBar::m_rounding = 22; +const int FancyTabBar::m_textPadding = 4; + +//--------------------------------------------------------------------------------------------------------------------- +FancyTabBar::FancyTabBar(const TabBarPosition position, QWidget *parent) + : QWidget(parent), + m_position(position), + m_hoverRect(), + m_hoverIndex(-1), + m_currentIndex(-1), + m_attachedTabs(), + m_timerTriggerChangedSignal() +{ + if (m_position == FancyTabBar::Above || m_position == FancyTabBar::Below) + { + setMinimumHeight(qMax(2 * m_rounding, 40)); + setMaximumHeight(TabSizeHint(false).height()); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + } + else + { + setMinimumWidth(qMax(2 * m_rounding, 40)); + setMaximumWidth(TabSizeHint(false).width()); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + } + + setAttribute(Qt::WA_Hover, true); + setFocusPolicy(Qt::NoFocus); + setMouseTracking(true); // Needed for hover events + m_timerTriggerChangedSignal.setSingleShot(true); + + // We use a zerotimer to keep the sidebar responsive + connect(&m_timerTriggerChangedSignal, &QTimer::timeout, this, &FancyTabBar::EmitCurrentIndex); +} + +//--------------------------------------------------------------------------------------------------------------------- +FancyTabBar::~FancyTabBar() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +QSize FancyTabBar::TabSizeHint(bool minimum) const +{ + QFont boldFont(font()); + boldFont.setPointSizeF(StyleHelper::sidebarFontSize()); + boldFont.setBold(true); + QFontMetrics fm(boldFont); + int spacing = 8; + int width = 60 + spacing + 2; + int maxLabelwidth = 0; + for (int tab=0 ; tab maxLabelwidth) + { + maxLabelwidth = width; + } + } + int iconHeight = minimum ? 0 : 32; + + return QSize(qMax(width, maxLabelwidth + 4), iconHeight + spacing + fm.height()); +} + +//--------------------------------------------------------------------------------------------------------------------- +QPoint FancyTabBar::GetCorner(const QRect& rect, const Corner corner) const +{ + switch(m_position) + { + case Above: + switch(corner) + { + case OutsideBeginning: + return rect.topLeft(); + case OutsideEnd: + return rect.topRight(); + case InsideBeginning: + return rect.bottomLeft(); + case InsideEnd: + return rect.bottomRight(); + default: + break; + } + case Below: + switch(corner) + { + case OutsideBeginning: + return rect.bottomLeft(); + case OutsideEnd: + return rect.bottomRight(); + case InsideBeginning: + return rect.topLeft(); + case InsideEnd: + return rect.topRight(); + default: + break; + } + case Left: + switch(corner) + { + case OutsideBeginning: + return rect.topLeft(); + case OutsideEnd: + return rect.bottomLeft(); + case InsideBeginning: + return rect.topRight(); + case InsideEnd: + return rect.bottomRight(); + default: + break; + } + case Right: + switch(corner) + { + case OutsideBeginning: + return rect.topRight(); + case OutsideEnd: + return rect.bottomRight(); + case InsideBeginning: + return rect.topLeft(); + case InsideEnd: + return rect.bottomLeft(); + default: + break; + } + default: + break; + } + + Q_ASSERT("that's impossible!"); + + return QPoint(); +} + +//--------------------------------------------------------------------------------------------------------------------- +// You can pass this method a QRect and tell it to move its edges to the outside (+) +// or inside (-) of the rect. For example, with a TabBar at the Above, +// +// adjustRect(QRect(0,0,10,10), 1, 2, 3, -4) // thats a 10 by 10 QRect, starting at 0/0 +// +// gives +// +// QRect(-3, -1, 9, 13) // 9 by 13 rect, starting at -3/-1. +QRect FancyTabBar::AdjustRect(const QRect& rect, const qint8 offsetOutside, const qint8 offsetInside, + const qint8 offsetBeginning, const qint8 offsetEnd) const +{ + switch(m_position) + { + case Above: + return rect.adjusted(-offsetBeginning, -offsetOutside, offsetEnd, offsetInside); + case Below: + return rect.adjusted(-offsetBeginning, -offsetInside, -offsetBeginning, offsetOutside); + case Left: + return rect.adjusted(-offsetOutside, -offsetBeginning, offsetInside, offsetEnd); + case Right: + return rect.adjusted(-offsetInside, -offsetBeginning, offsetOutside, offsetEnd); + default: + break; + } + + Q_ASSERT("that's impossible!"); + return QRect(); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Same with a point: + means towards Outside/End, - means towards Inside/Beginning +QPoint FancyTabBar::AdjustPoint(const QPoint& point, const qint8 offsetInsideOutside, + const qint8 offsetBeginningEnd) const +{ + switch(m_position) + { + case Above: + return point + QPoint(offsetBeginningEnd, -offsetInsideOutside); + case Below: + return point + QPoint(offsetBeginningEnd, offsetInsideOutside); + case Left: + return point + QPoint(-offsetInsideOutside, offsetBeginningEnd); + case Right: + return point + QPoint(offsetInsideOutside, offsetBeginningEnd); + default: + break; + } + + Q_ASSERT("that's impossible!"); + return QPoint(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + QPainter painter(this); + + // paint background + QRect rectangle = AdjustRect(rect(), 0, -1, 0, 0); + QLinearGradient lg; + + lg.setStart(GetCorner(rectangle, OutsideBeginning)); + lg.setFinalStop(GetCorner(rectangle, InsideBeginning)); + lg.setColorAt(0.0, QColor(64, 64, 64, 255)); + lg.setColorAt(1.0, QColor(130, 130, 130, 255)); + painter.fillRect(rectangle, lg); + + // draw dark widget bordert on inner inside (e.g. bottom if the widget position is top) + painter.setPen(StyleHelper::borderColor()); + painter.drawLine(AdjustPoint(GetCorner(rectangle, InsideBeginning), -1, 0), + AdjustPoint(GetCorner(rectangle, InsideEnd), -1, 0)); + + // draw bright widget border on outer inside (e.g. bottom if the widget position is top) + painter.setPen(StyleHelper::sidebarHighlight()); + painter.drawLine(GetCorner(rectangle, InsideBeginning), GetCorner(rectangle, InsideEnd)); + + // paint inactive tabs + for (int i = 0; i < Count(); ++i) + { + if (i != CurrentIndex()) + { + PaintTab(&painter, i); + } + } + + // paint active tab last, since it overlaps the neighbors + if (CurrentIndex() != -1) + { + PaintTab(&painter, CurrentIndex()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +// Handle hover events for mouse fade ins +void FancyTabBar::mouseMoveEvent(QMouseEvent *e) +{ + int newHover = -1; + for (int i = 0; i < Count(); ++i) + { + QRect area = TabRect(i); + if (area.contains(e->pos())) + { + newHover = i; + break; + } + } + if (newHover == m_hoverIndex) + { + return; + } + + if (ValidIndex(m_hoverIndex)) + { + m_attachedTabs[m_hoverIndex]->fadeOut(); + } + + m_hoverIndex = newHover; + + if (ValidIndex(m_hoverIndex)) + { + m_attachedTabs[m_hoverIndex]->fadeIn(); + m_hoverRect = TabRect(m_hoverIndex); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool FancyTabBar::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) + { + if (ValidIndex(m_hoverIndex)) + { + QString tt = TabToolTip(m_hoverIndex); + if (!tt.isEmpty()) + { + QToolTip::showText(static_cast(event)->globalPos(), tt, this); + return true; + } + } + } + return QWidget::event(event); +} + +//--------------------------------------------------------------------------------------------------------------------- +// Resets hover animation on mouse enter +void FancyTabBar::enterEvent(QEvent *e) +{ + Q_UNUSED(e) + m_hoverRect = QRect(); + m_hoverIndex = -1; +} + +//--------------------------------------------------------------------------------------------------------------------- +// Resets hover animation on mouse leave +void FancyTabBar::leaveEvent(QEvent *e) +{ + Q_UNUSED(e) + m_hoverIndex = -1; + m_hoverRect = QRect(); + for (int i = 0 ; i < m_attachedTabs.count() ; ++i) + { + m_attachedTabs[i]->fadeOut(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool FancyTabBar::ValidIndex(int index) const +{ + return index >= 0 && index < m_attachedTabs.count(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::SetOrientation(const FancyTabBar::TabBarPosition p) +{ + m_position = p; +} + +//--------------------------------------------------------------------------------------------------------------------- +QSize FancyTabBar::sizeHint() const +{ + QSize sh = TabSizeHint(); + // return QSize(sh.width(), sh.height() * mAttachedTabs.count()); + + if (m_position == Above || m_position == Below) + { + return QSize(sh.width() * m_attachedTabs.count(), sh.height()); + } + else + { + return QSize(sh.width(), sh.height() * m_attachedTabs.count()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QSize FancyTabBar::minimumSizeHint() const +{ + const QSize sh = TabSizeHint(true); +// return QSize(sh.width(), sh.height() * mAttachedTabs.count()); + + if(m_position == Above || m_position == Below) + { + return QSize(sh.width() * m_attachedTabs.count(), sh.height()); + } + else + { + return QSize(sh.width(), sh.height() * m_attachedTabs.count()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QRect FancyTabBar::TabRect(int index) const +{ + QSize sh = TabSizeHint(); + + if(m_position == Above || m_position == Below) + { + if (sh.width() * m_attachedTabs.count() > width()) + { + sh.setWidth(width() / m_attachedTabs.count()); + } + + return QRect(index * sh.width(), 0, sh.width(), sh.height()); + } + else + { + if (sh.height() * m_attachedTabs.count() > height()) + { + sh.setHeight(height() / m_attachedTabs.count()); + } + + return QRect(0, index * sh.height(), sh.width(), sh.height()); + } + +} + +//--------------------------------------------------------------------------------------------------------------------- +// This keeps the sidebar responsive since +// we get a repaint before loading the +// mode itself +void FancyTabBar::EmitCurrentIndex() +{ + emit CurrentChanged(m_currentIndex); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::mousePressEvent(QMouseEvent *e) +{ + e->accept(); + for (int index = 0; index < m_attachedTabs.count(); ++index) + { + if (TabRect(index).contains(e->pos())) + { + if (IsTabEnabled(index)) + { + m_currentIndex = index; + update(); + m_timerTriggerChangedSignal.start(0); + } + break; + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::PaintTab(QPainter *painter, int tabIndex) const +{ + if (!ValidIndex(tabIndex)) + { + qWarning("invalid index"); + return; + } + painter->save(); + + QRect rect = TabRect(tabIndex); + bool selected = (tabIndex == m_currentIndex); + bool enabled = IsTabEnabled(tabIndex); + + if(selected) + { + // background + painter->save(); + QLinearGradient grad(GetCorner(rect, OutsideBeginning), GetCorner(rect, InsideBeginning)); + grad.setColorAt(0, QColor(255, 255, 255, 140)); + grad.setColorAt(1, QColor(255, 255, 255, 210)); + painter->fillRect(AdjustRect(rect, 0, 0, 0, -1), grad); + painter->restore(); + + // shadows (the black lines immediately before/after (active && selected)-backgrounds) + painter->setPen(QColor(0, 0, 0, 110)); + painter->drawLine(AdjustPoint(GetCorner(rect, OutsideBeginning), 0, -1), + AdjustPoint(GetCorner(rect, InsideBeginning), 0, -1)); + painter->drawLine(GetCorner(rect, OutsideEnd), GetCorner(rect, InsideEnd)); + + // thin shadow on the outside of active tab + painter->setPen(QColor(0, 0, 0, 40)); + painter->drawLine(GetCorner(rect, OutsideBeginning), GetCorner(rect, OutsideEnd)); + + // highlights + painter->setPen(QColor(255, 255, 255, 50)); + painter->drawLine(AdjustPoint(GetCorner(rect, OutsideBeginning), 0, -2), + AdjustPoint(GetCorner(rect, InsideBeginning), 0, -2)); + painter->drawLine(AdjustPoint(GetCorner(rect, OutsideEnd), 0, 1), + AdjustPoint(GetCorner(rect, InsideEnd), 0, 1)); + + painter->setPen(QColor(255, 255, 255, 40)); + // thin white line towards beginning + painter->drawLine(AdjustPoint(GetCorner(rect, OutsideBeginning), 0, 0), + AdjustPoint(GetCorner(rect, InsideBeginning), 0, 0)); + // thin white line on inside border + painter->drawLine(AdjustPoint(GetCorner(rect, InsideBeginning), 0, 1), + AdjustPoint(GetCorner(rect, InsideEnd), 0, -1)); + // thin white line towards end + painter->drawLine(AdjustPoint(GetCorner(rect, OutsideEnd), 0, -1), + AdjustPoint(GetCorner(rect, InsideEnd), 0, -1)); + } + + QString tabText(this->TabText(tabIndex)); + QRect tabTextRect(rect); + const bool drawIcon = rect.height() > 36; + QRect tabIconRect(tabTextRect); + tabTextRect.translate(0, drawIcon ? -2 : 1); + QFont boldFont(painter->font()); + boldFont.setPointSizeF(StyleHelper::sidebarFontSize()); + boldFont.setBold(true); + painter->setFont(boldFont); + painter->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110)); + const int textFlags = Qt::AlignCenter | (drawIcon ? Qt::AlignBottom : Qt::AlignVCenter) | Qt::TextWordWrap; + if (enabled) + { + painter->drawText(tabTextRect, textFlags, tabText); + painter->setPen(selected ? QColor(60, 60, 60) : StyleHelper::panelTextColor()); + } + else + { + painter->setPen(selected ? StyleHelper::panelTextColor() : QColor(255, 255, 255, 120)); + } + +#if defined(Q_OS_MAC) + bool isMac=true; +#else + bool isMac = false; +#endif + + // hover + if(!isMac && !selected && enabled) + { + painter->save(); + int fader = int(m_attachedTabs[tabIndex]->fader()); + QLinearGradient grad(GetCorner(rect, OutsideBeginning), GetCorner(rect, InsideBeginning)); + + grad.setColorAt(0, Qt::transparent); + grad.setColorAt(0.5, QColor(255, 255, 255, fader)); + grad.setColorAt(1, Qt::transparent); + painter->fillRect(rect, grad); + painter->setPen(QPen(grad, 1.0)); + + if(m_position == Above || m_position == Below) + { + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + painter->drawLine(rect.topRight(), rect.bottomRight()); + } + else + { + painter->drawLine(rect.topLeft(), rect.topRight()); + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + } + + painter->restore(); + } + + if (!enabled) + { + painter->setOpacity(0.7); + } + + if (drawIcon) + { + int textHeight = painter->fontMetrics().boundingRect(QRect(0, 0, width(), height()), Qt::TextWordWrap, + tabText).height(); + tabIconRect.adjust(0, 4, 0, -textHeight); + StyleHelper::drawIconWithShadow(TabIcon(tabIndex), tabIconRect, painter, + enabled ? QIcon::Normal : QIcon::Disabled); + } + + painter->translate(0, -1); + painter->drawText(tabTextRect, textFlags, tabText); + painter->restore(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::SetCurrentIndex(int index) +{ + if (IsTabEnabled(index)) + { + m_currentIndex = index; + update(); + emit CurrentChanged(m_currentIndex); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +int FancyTabBar::CurrentIndex() const +{ + return m_currentIndex; +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::SetTabToolTip(int index, QString toolTip) +{ + m_attachedTabs[index]->m_toolTip = toolTip; +} + +//--------------------------------------------------------------------------------------------------------------------- +QString FancyTabBar::TabToolTip(int index) const +{ + return m_attachedTabs.at(index)->m_toolTip; +} + +//--------------------------------------------------------------------------------------------------------------------- +QIcon FancyTabBar::TabIcon(int index) const +{ + return m_attachedTabs.at(index)->m_icon; +} + +//--------------------------------------------------------------------------------------------------------------------- +QString FancyTabBar::TabText(int index) const +{ + return m_attachedTabs.at(index)->m_text; +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::SetTabText(int index, QString text) const +{ + m_attachedTabs.at(index)->m_text=text; +} + +//--------------------------------------------------------------------------------------------------------------------- +int FancyTabBar::Count() const +{ + return m_attachedTabs.count(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::SetTabEnabled(int index, bool enable) +{ + Q_ASSERT(index < m_attachedTabs.size()); + Q_ASSERT(index >= 0); + + if (index < m_attachedTabs.size() && index >= 0) + { + m_attachedTabs[index]->m_enabled = enable; + update(TabRect(index)); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool FancyTabBar::IsTabEnabled(int index) const +{ + Q_ASSERT(index < m_attachedTabs.size()); + Q_ASSERT(index >= 0); + + if (index < m_attachedTabs.size() && index >= 0) + { + return m_attachedTabs[index]->m_enabled; + } + + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::InsertTab(int index, const QIcon &icon, const QString &label) +{ + FancyTab *tab = new FancyTab(this); + tab->m_icon = icon; + tab->m_text = label; + m_attachedTabs.insert(index, tab); +} + +//--------------------------------------------------------------------------------------------------------------------- +void FancyTabBar::RemoveTab(int index) +{ + FancyTab *tab = m_attachedTabs.takeAt(index); + delete tab; +} diff --git a/src/libs/vwidgets/fancytabbar/fancytabbar.h b/src/libs/vwidgets/fancytabbar/fancytabbar.h new file mode 100644 index 000000000..c5cfc49aa --- /dev/null +++ b/src/libs/vwidgets/fancytabbar/fancytabbar.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef FANCYTABWIDGET_H +#define FANCYTABWIDGET_H + +#include +#include +#include +#include + +class QPainter; + +#include "fancytab.h" + +class FancyTabBar : public QWidget +{ + Q_OBJECT + +public: + enum TabBarPosition + { + Above, + Below, + Left, + Right + }; + + FancyTabBar(const TabBarPosition position, QWidget *parent = nullptr); + virtual ~FancyTabBar(); + + virtual QSize sizeHint() const Q_DECL_OVERRIDE; + virtual QSize minimumSizeHint() const Q_DECL_OVERRIDE; + + void SetOrientation(const TabBarPosition p); + + void SetTabEnabled(int index, bool enable); + bool IsTabEnabled(int index) const; + + void InsertTab(int index, const QIcon &icon, const QString &label); + void RemoveTab(int index); + + void SetCurrentIndex(int index); + int CurrentIndex() const; + + void SetTabToolTip(int index, QString toolTip); + QString TabToolTip(int index) const; + + QIcon TabIcon(int index) const; + + QString TabText(int index) const; + void SetTabText(int index, QString text) const; + + int Count() const; + QRect TabRect(int index) const; + +signals: + void CurrentChanged(int); + +protected: + virtual bool event(QEvent *event) Q_DECL_OVERRIDE; + virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; + virtual void enterEvent(QEvent *) Q_DECL_OVERRIDE; + virtual void leaveEvent(QEvent *) Q_DECL_OVERRIDE; + +private slots: + void EmitCurrentIndex(); + +private: + Q_DISABLE_COPY(FancyTabBar) + + enum Corner { OutsideBeginning, OutsideEnd, InsideBeginning, InsideEnd }; + + static const int m_rounding; + static const int m_textPadding; + + TabBarPosition m_position; + QRect m_hoverRect; + int m_hoverIndex; + int m_currentIndex; + QList m_attachedTabs; + QTimer m_timerTriggerChangedSignal; + + QPoint GetCorner(const QRect& rect, const Corner corner) const; + + QRect AdjustRect(const QRect& rect, const qint8 offsetOutside, const qint8 offsetInside, const qint8 offsetStart, + const qint8 offsetEnd) const; + + // Same with a point. + means towards Outside/End, - means towards Inside/Beginning + QPoint AdjustPoint(const QPoint& point, const qint8 offsetInsideOutside, const qint8 offsetBeginningEnd) const; + + QSize TabSizeHint(bool minimum = false) const; + void PaintTab(QPainter *painter, int tabIndex) const; + bool ValidIndex(int index) const; +}; + +#endif // FANCYTABWIDGET_H diff --git a/src/libs/vwidgets/fancytabbar/stylehelper.cpp b/src/libs/vwidgets/fancytabbar/stylehelper.cpp new file mode 100644 index 000000000..f6620320a --- /dev/null +++ b/src/libs/vwidgets/fancytabbar/stylehelper.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stylehelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------------------------------------------------- +qreal StyleHelper::sidebarFontSize() +{ +#if defined(Q_OS_MAC) + return 10; +#else + return 7.5; +#endif +} + +//--------------------------------------------------------------------------------------------------------------------- +QColor StyleHelper::panelTextColor(bool lightColored) +{ + //qApp->palette().highlightedText().color(); + if (!lightColored) + { + return Qt::white; + } + else + { + return Qt::black; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +// Invalid by default, setBaseColor needs to be called at least once +QColor StyleHelper::m_baseColor; +QColor StyleHelper::m_requestedBaseColor; + +//--------------------------------------------------------------------------------------------------------------------- +QColor StyleHelper::baseColor(bool lightColored) +{ + if (!lightColored) + { + return m_baseColor; + } + else + { + return m_baseColor.lighter(230); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QColor StyleHelper::borderColor(bool lightColored) +{ + QColor result = baseColor(lightColored); + result.setHsv(result.hue(), + result.saturation(), + result.value() / 2); + return result; +} + +//--------------------------------------------------------------------------------------------------------------------- +QColor StyleHelper::sidebarHighlight() +{ + return QColor(255, 255, 255, 40); +} + +//--------------------------------------------------------------------------------------------------------------------- +// We try to ensure that the actual color used are within +// reasonalbe bounds while generating the actual baseColor +// from the users request. +void StyleHelper::setBaseColor(const QColor &newcolor) +{ + m_requestedBaseColor = newcolor; + + QColor color; + color.setHsv(newcolor.hue(), + static_cast(newcolor.saturation() * 0.7), + 64 + newcolor.value() / 3); + + if (color.isValid() && color != m_baseColor) + { + m_baseColor = color; + foreach (QWidget *w, QApplication::topLevelWidgets()) + { + w->update(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +// Draws a cached pixmap with shadow +void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, + int radius, const QColor &color, const QPoint &offset) +{ + QPixmap cache; + QString pixmapName = QString::fromLatin1("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); + + if (!QPixmapCache::find(pixmapName, cache)) + { + QPixmap px = icon.pixmap(rect.size()); + cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); + cache.fill(Qt::transparent); + + QPainter cachePainter(&cache); + if (iconMode == QIcon::Disabled) + { + QImage im = px.toImage().convertToFormat(QImage::Format_ARGB32); + for (int y=0; y(im.scanLine(y)); + for (int x=0; x(qGray(pixel)); + *scanLine = qRgba(intensity, intensity, intensity, qAlpha(pixel)); + ++scanLine; + } + } + px = QPixmap::fromImage(im); + } + + // Draw shadow + QImage tmp(px.size() + QSize(radius * 2, radius * 2 + 1), QImage::Format_ARGB32_Premultiplied); + tmp.fill(Qt::transparent); + + QPainter tmpPainter(&tmp); + tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); + tmpPainter.drawPixmap(QPoint(radius, radius), px); + tmpPainter.end(); + + // blur the alpha channel + QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); + blurred.fill(Qt::transparent); + QPainter blurPainter(&blurred); + qt_blurImage(&blurPainter, tmp, radius, false, true); + blurPainter.end(); + + tmp = blurred; + + // blacken the image... + tmpPainter.begin(&tmp); + tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); + tmpPainter.fillRect(tmp.rect(), color); + tmpPainter.end(); + + tmpPainter.begin(&tmp); + tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); + tmpPainter.fillRect(tmp.rect(), color); + tmpPainter.end(); + + // draw the blurred drop shadow... + cachePainter.drawImage(QRect(0, 0, cache.rect().width(), cache.rect().height()), tmp); + + // Draw the actual pixmap... + cachePainter.drawPixmap(QPoint(radius, radius) + offset, px); + QPixmapCache::insert(pixmapName, cache); + } + + QRect targetRect = cache.rect(); + targetRect.moveCenter(rect.center()); + p->drawPixmap(targetRect.topLeft() - offset, cache); +} diff --git a/src/libs/vwidgets/fancytabbar/stylehelper.h b/src/libs/vwidgets/fancytabbar/stylehelper.h new file mode 100644 index 000000000..12198eb47 --- /dev/null +++ b/src/libs/vwidgets/fancytabbar/stylehelper.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef STYLEHELPER_H +#define STYLEHELPER_H + +#include +#include + +class QPalette; +class QPainter; +class QRect; + +// Note, this is exported but in a private header as qtopengl depends on it. +// We should consider adding this as a public helper function. +void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); + +// Helper class holding all custom color values +class StyleHelper +{ +public: + static const unsigned int DEFAULT_BASE_COLOR = 0x666666; + + static qreal sidebarFontSize(); + // This is our color table, all colors derive from baseColor + static QColor baseColor(bool lightColored = false); + static QColor panelTextColor(bool lightColored = false); + static QColor borderColor(bool lightColored = false); + static QColor sidebarHighlight(); + + // Sets the base color and makes sure all top level widgets are updated + static void setBaseColor(const QColor &color); + static void drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, + int radius = 3, const QColor &color = QColor(0, 0, 0, 130), + const QPoint &offset = QPoint(1, -2)); + +private: + static QColor m_baseColor; + static QColor m_requestedBaseColor; +}; + +#endif // STYLEHELPER_H diff --git a/src/libs/vwidgets/vwidgets.pri b/src/libs/vwidgets/vwidgets.pri index 1f3219b8f..5b16032b7 100644 --- a/src/libs/vwidgets/vwidgets.pri +++ b/src/libs/vwidgets/vwidgets.pri @@ -1,35 +1,41 @@ -# ADD TO EACH PATH $$PWD VARIABLE!!!!!! -# This need for corect working file translations.pro - -SOURCES += \ - $$PWD/vmaingraphicsscene.cpp \ - $$PWD/vmaingraphicsview.cpp \ - $$PWD/vwidgetpopup.cpp \ - $$PWD/vcontrolpointspline.cpp \ - $$PWD/vgraphicssimpletextitem.cpp \ - $$PWD/vsimplepoint.cpp \ - $$PWD/vabstractsimple.cpp \ - $$PWD/vnobrushscalepathitem.cpp \ - $$PWD/vsimplecurve.cpp \ - $$PWD/vabstractmainwindow.cpp \ - $$PWD/vtextgraphicsitem.cpp \ - $$PWD/vgrainlineitem.cpp \ - $$PWD/vpieceitem.cpp - -win32-msvc*:SOURCES += $$PWD/stable.cpp - -HEADERS += \ - $$PWD/stable.h \ - $$PWD/vmaingraphicsscene.h \ - $$PWD/vmaingraphicsview.h \ - $$PWD/vwidgetpopup.h \ - $$PWD/vcontrolpointspline.h \ - $$PWD/vgraphicssimpletextitem.h \ - $$PWD/vsimplepoint.h \ - $$PWD/vabstractsimple.h \ - $$PWD/vnobrushscalepathitem.h \ - $$PWD/vsimplecurve.h \ - $$PWD/vabstractmainwindow.h \ - $$PWD/vtextgraphicsitem.h \ - $$PWD/vgrainlineitem.h \ - $$PWD/vpieceitem.h +# ADD TO EACH PATH $$PWD VARIABLE!!!!!! +# This need for corect working file translations.pro + +SOURCES += \ + $$PWD/vmaingraphicsscene.cpp \ + $$PWD/vmaingraphicsview.cpp \ + $$PWD/vwidgetpopup.cpp \ + $$PWD/vcontrolpointspline.cpp \ + $$PWD/vgraphicssimpletextitem.cpp \ + $$PWD/vsimplepoint.cpp \ + $$PWD/vabstractsimple.cpp \ + $$PWD/vnobrushscalepathitem.cpp \ + $$PWD/vsimplecurve.cpp \ + $$PWD/vabstractmainwindow.cpp \ + $$PWD/vtextgraphicsitem.cpp \ + $$PWD/vgrainlineitem.cpp \ + $$PWD/vpieceitem.cpp \ + $$PWD/fancytabbar/fancytab.cpp \ + $$PWD/fancytabbar/fancytabbar.cpp \ + $$PWD/fancytabbar/stylehelper.cpp + +win32-msvc*:SOURCES += $$PWD/stable.cpp + +HEADERS += \ + $$PWD/stable.h \ + $$PWD/vmaingraphicsscene.h \ + $$PWD/vmaingraphicsview.h \ + $$PWD/vwidgetpopup.h \ + $$PWD/vcontrolpointspline.h \ + $$PWD/vgraphicssimpletextitem.h \ + $$PWD/vsimplepoint.h \ + $$PWD/vabstractsimple.h \ + $$PWD/vnobrushscalepathitem.h \ + $$PWD/vsimplecurve.h \ + $$PWD/vabstractmainwindow.h \ + $$PWD/vtextgraphicsitem.h \ + $$PWD/vgrainlineitem.h \ + $$PWD/vpieceitem.h \ + $$PWD/fancytabbar/fancytab.h \ + $$PWD/fancytabbar/fancytabbar.h \ + $$PWD/fancytabbar/stylehelper.h