2018-10-19 19:10:22 +02:00
|
|
|
/*
|
|
|
|
* Strawberry Music Player
|
|
|
|
* This file was part of Clementine.
|
|
|
|
* Copyright 2018, Vikram Ambrose <ambroseworks@gmail.com>
|
|
|
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
|
|
|
*
|
|
|
|
* Strawberry is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Strawberry is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include "fancytabwidget.h"
|
2018-10-19 19:10:22 +02:00
|
|
|
#include "stylehelper.h"
|
|
|
|
#include "core/logging.h"
|
|
|
|
|
|
|
|
#include <QDebug>
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
#include <QTabBar>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QWidget>
|
2018-10-19 19:10:22 +02:00
|
|
|
#include <QMap>
|
|
|
|
#include <QHash>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QString>
|
|
|
|
#include <QIcon>
|
2018-10-19 19:10:22 +02:00
|
|
|
#include <QMenu>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QPainter>
|
|
|
|
#include <QColor>
|
|
|
|
#include <QRect>
|
|
|
|
#include <QFont>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QSignalMapper>
|
2018-10-19 19:10:22 +02:00
|
|
|
#include <QStylePainter>
|
|
|
|
#include <QTimer>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QLayout>
|
2018-10-19 19:10:22 +02:00
|
|
|
#include <QVBoxLayout>
|
|
|
|
#include <QMouseEvent>
|
|
|
|
#include <QSettings>
|
|
|
|
#include <QSize>
|
|
|
|
#include <QPoint>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QTransform>
|
2018-10-19 19:10:22 +02:00
|
|
|
#include <QAction>
|
2018-05-01 00:41:33 +02:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
const QSize FancyTabWidget::IconSize_LargeSidebar = QSize(24, 24);
|
|
|
|
const QSize FancyTabWidget::IconSize_SmallSidebar = QSize(22, 22);
|
|
|
|
const QSize FancyTabWidget::TabSize_LargeSidebar = QSize(70, 47);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
class FancyTabBar: public QTabBar {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
private:
|
|
|
|
int mouseHoverTabIndex = -1;
|
2018-10-20 22:16:22 +02:00
|
|
|
QMap<QWidget*, QString> labelCache;
|
2018-10-19 19:10:22 +02:00
|
|
|
QMap<int, QWidget*> spacers;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
public:
|
|
|
|
explicit FancyTabBar(QWidget* parent=0) : QTabBar(parent) {
|
|
|
|
setMouseTracking(true);
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QSize sizeHint() const {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QSize size(QTabBar::sizeHint());
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
FancyTabWidget *tabWidget = (FancyTabWidget*) parentWidget();
|
|
|
|
if (tabWidget->mode() == FancyTabWidget::Mode_Tabs || tabWidget->mode() == FancyTabWidget::Mode_IconOnlyTabs) return size;
|
|
|
|
|
|
|
|
QSize tabSize(tabSizeHint(0));
|
|
|
|
size.setWidth(tabSize.width());
|
|
|
|
int guessHeight = tabSize.height()*count();
|
|
|
|
if (guessHeight > size.height())
|
|
|
|
size.setHeight(guessHeight);
|
|
|
|
return size;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-08-29 21:42:24 +02:00
|
|
|
}
|
2018-10-19 19:10:22 +02:00
|
|
|
|
|
|
|
int width() {
|
|
|
|
return tabSizeHint(0).width();
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
protected:
|
|
|
|
QSize tabSizeHint(int index) const {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
FancyTabWidget *tabWidget = (FancyTabWidget*) parentWidget();
|
|
|
|
QSize size = FancyTabWidget::TabSize_LargeSidebar;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
if(tabWidget->mode() != FancyTabWidget::Mode_LargeSidebar) {
|
|
|
|
size = QTabBar::tabSizeHint(index);
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
return size;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void leaveEvent(QEvent *event) {
|
|
|
|
mouseHoverTabIndex = -1;
|
|
|
|
update();
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void mouseMoveEvent(QMouseEvent *event) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QPoint pos = event->pos();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
mouseHoverTabIndex = tabAt(pos);
|
|
|
|
if (mouseHoverTabIndex > -1)
|
|
|
|
update();
|
|
|
|
QTabBar::mouseMoveEvent(event);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void paintEvent(QPaintEvent *pe) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
FancyTabWidget *tabWidget = (FancyTabWidget*) parentWidget();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
bool verticalTextTabs = false;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
if (tabWidget->mode() == FancyTabWidget::Mode_SmallSidebar)
|
|
|
|
verticalTextTabs = true;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// if LargeSidebar, restore spacers
|
2018-10-20 22:16:22 +02:00
|
|
|
if (tabWidget->mode() == FancyTabWidget::Mode_LargeSidebar && spacers.count() > 0) {
|
2018-10-19 19:10:22 +02:00
|
|
|
for (int index : spacers.keys()) {
|
|
|
|
tabWidget->insertTab(index, spacers[index], QIcon(), QString());
|
|
|
|
tabWidget->setTabEnabled(index, false);
|
|
|
|
}
|
|
|
|
spacers.clear();
|
|
|
|
}
|
2018-10-20 22:16:22 +02:00
|
|
|
else if (tabWidget->mode() != FancyTabWidget::Mode_LargeSidebar) {
|
2018-10-19 19:10:22 +02:00
|
|
|
// traverse in the opposite order to save indices of spacers
|
|
|
|
for (int i = count() - 1; i >= 0; --i) {
|
|
|
|
// spacers are disabled tabs
|
|
|
|
if (!isTabEnabled(i) && !spacers.contains(i)) {
|
|
|
|
spacers[i] = tabWidget->widget(i);
|
|
|
|
tabWidget->removeTab(i);
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Restore any label text that was hidden/cached for the IconOnlyTabs mode
|
|
|
|
if (labelCache.count() > 0 && tabWidget->mode() != FancyTabWidget::Mode_IconOnlyTabs) {
|
|
|
|
for (int i =0; i < count(); i++) {
|
|
|
|
setTabText(i, labelCache[tabWidget->widget(i)]);
|
|
|
|
}
|
|
|
|
labelCache.clear();
|
|
|
|
}
|
|
|
|
if (tabWidget->mode() != FancyTabWidget::Mode_LargeSidebar && tabWidget->mode() != FancyTabWidget::Mode_SmallSidebar) {
|
|
|
|
// Cache and hide label text for IconOnlyTabs mode
|
|
|
|
if (tabWidget->mode() == FancyTabWidget::Mode_IconOnlyTabs && labelCache.count() == 0) {
|
|
|
|
for(int i =0; i < count(); i++) {
|
|
|
|
labelCache[tabWidget->widget(i)] = tabText(i);
|
|
|
|
setTabText(i, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QTabBar::paintEvent(pe);
|
|
|
|
return;
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QStylePainter p(this);
|
|
|
|
|
|
|
|
for (int index = 0; index < count(); index++) {
|
|
|
|
const bool selected = tabWidget->currentIndex() == index;
|
|
|
|
QRect tabrect = tabRect(index);
|
|
|
|
QRect selectionRect = tabrect;
|
|
|
|
if (selected) {
|
|
|
|
// Selection highlight
|
|
|
|
p.save();
|
|
|
|
QLinearGradient grad(selectionRect.topLeft(), selectionRect.topRight());
|
|
|
|
grad.setColorAt(0, QColor(255, 255, 255, 140));
|
|
|
|
grad.setColorAt(1, QColor(255, 255, 255, 210));
|
|
|
|
p.fillRect(selectionRect.adjusted(0,0,0,-1), grad);
|
|
|
|
p.restore();
|
|
|
|
|
|
|
|
// shadow lines
|
|
|
|
p.setPen(QColor(0, 0, 0, 110));
|
|
|
|
p.drawLine(selectionRect.topLeft() + QPoint(1, -1), selectionRect.topRight() - QPoint(0, 1));
|
|
|
|
p.drawLine(selectionRect.bottomLeft(), selectionRect.bottomRight());
|
|
|
|
p.setPen(QColor(0, 0, 0, 40));
|
|
|
|
p.drawLine(selectionRect.topLeft(), selectionRect.bottomLeft());
|
|
|
|
|
|
|
|
// highlights
|
|
|
|
p.setPen(QColor(255, 255, 255, 50));
|
|
|
|
p.drawLine(selectionRect.topLeft() + QPoint(0, -2), selectionRect.topRight() - QPoint(0, 2));
|
|
|
|
p.drawLine(selectionRect.bottomLeft() + QPoint(0, 1), selectionRect.bottomRight() + QPoint(0, 1));
|
|
|
|
p.setPen(QColor(255, 255, 255, 40));
|
|
|
|
p.drawLine(selectionRect.topLeft() + QPoint(0, 0), selectionRect.topRight());
|
|
|
|
p.drawLine(selectionRect.topRight() + QPoint(0, 1), selectionRect.bottomRight() - QPoint(0, 1));
|
|
|
|
p.drawLine(selectionRect.bottomLeft() + QPoint(0, -1), selectionRect.bottomRight() - QPoint(0, 1));
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Mouse hover effect
|
|
|
|
if (!selected && index == mouseHoverTabIndex && isTabEnabled(index)) {
|
|
|
|
p.save();
|
|
|
|
QLinearGradient grad(selectionRect.topLeft(), selectionRect.topRight());
|
|
|
|
grad.setColorAt(0, Qt::transparent);
|
|
|
|
grad.setColorAt(0.5, QColor(255, 255, 255, 40));
|
|
|
|
grad.setColorAt(1, Qt::transparent);
|
|
|
|
p.fillRect(selectionRect, grad);
|
|
|
|
p.setPen(QPen(grad, 1.0));
|
|
|
|
p.drawLine(selectionRect.topLeft(), selectionRect.topRight());
|
|
|
|
p.drawLine(selectionRect.bottomRight(), selectionRect.bottomLeft());
|
|
|
|
p.restore();
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Label (Icon and Text)
|
|
|
|
{
|
|
|
|
p.save();
|
|
|
|
QTransform m;
|
|
|
|
int textFlags;
|
|
|
|
Qt::Alignment iconFlags;
|
|
|
|
|
|
|
|
QRect tabrectText;
|
|
|
|
QRect tabrectLabel;
|
|
|
|
|
|
|
|
if (verticalTextTabs) {
|
|
|
|
m = QTransform::fromTranslate(tabrect.left(), tabrect.bottom());
|
|
|
|
m.rotate(-90);
|
|
|
|
textFlags = Qt::AlignLeft | Qt::AlignVCenter ;
|
|
|
|
iconFlags = Qt::AlignLeft | Qt::AlignVCenter;
|
|
|
|
|
|
|
|
tabrectLabel = QRect(QPoint(0, 0), m.mapRect(tabrect).size());
|
|
|
|
|
|
|
|
tabrectText = tabrectLabel;
|
|
|
|
tabrectText.translate(30,0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m = QTransform::fromTranslate(tabrect.left(), tabrect.top());
|
|
|
|
textFlags = Qt::AlignHCenter | Qt::AlignBottom ;
|
|
|
|
iconFlags = Qt::AlignHCenter | Qt::AlignTop;
|
|
|
|
|
|
|
|
tabrectLabel = QRect(QPoint(0, 0), m.mapRect(tabrect).size());
|
|
|
|
|
|
|
|
tabrectText = tabrectLabel;
|
|
|
|
tabrectText.translate(0,-5);
|
|
|
|
}
|
|
|
|
|
|
|
|
p.setTransform(m);
|
|
|
|
|
|
|
|
QFont boldFont(p.font());
|
|
|
|
boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
|
|
|
|
boldFont.setBold(true);
|
|
|
|
p.setFont(boldFont);
|
|
|
|
|
|
|
|
// Text drop shadow color
|
|
|
|
p.setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110) );
|
|
|
|
p.translate(0, 3);
|
|
|
|
p.drawText(tabrectText, textFlags, tabText(index));
|
|
|
|
|
|
|
|
// Text foreground color
|
|
|
|
p.translate(0, -1);
|
|
|
|
p.setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor());
|
|
|
|
p.drawText(tabrectText, textFlags, tabText(index));
|
|
|
|
|
|
|
|
|
|
|
|
// Draw the icon
|
|
|
|
QRect tabrectIcon;
|
|
|
|
const int PADDING = 5;
|
|
|
|
if (verticalTextTabs) {
|
|
|
|
tabrectIcon = tabrectLabel;
|
|
|
|
tabrectIcon.setSize(FancyTabWidget::IconSize_SmallSidebar);
|
|
|
|
tabrectIcon.translate(PADDING,PADDING);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tabrectIcon = tabrectLabel;
|
|
|
|
tabrectIcon.setSize(FancyTabWidget::IconSize_LargeSidebar);
|
|
|
|
// Center the icon
|
|
|
|
const int moveRight = (FancyTabWidget::TabSize_LargeSidebar.width() - FancyTabWidget::IconSize_LargeSidebar.width() -1)/2;
|
|
|
|
tabrectIcon.translate(moveRight,PADDING);
|
|
|
|
}
|
|
|
|
tabIcon(index).paint(&p, tabrectIcon, iconFlags);
|
|
|
|
p.restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
};
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Spacers are just disabled pages
|
|
|
|
void FancyTabWidget::addSpacer() {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-20 22:16:22 +02:00
|
|
|
QWidget *spacer = new QWidget(this);
|
2018-10-19 19:10:22 +02:00
|
|
|
const int index = addTab(spacer, QIcon(), QString());
|
|
|
|
setTabEnabled(index, false);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::setBackgroundPixmap(const QPixmap& pixmap) {
|
|
|
|
background_pixmap_ = pixmap;
|
|
|
|
update();
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::setCurrentIndex(int index) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
if (index >= count()) index = 0;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QWidget *currentPage = widget(index);
|
|
|
|
QLayout *layout = currentPage->layout();
|
|
|
|
if (bottom_widget_) layout->addWidget(bottom_widget_);
|
|
|
|
QTabWidget::setCurrentIndex(index);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::currentTabChanged(int index) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QWidget *currentPage = currentWidget();
|
|
|
|
QLayout *layout = currentPage->layout();
|
|
|
|
if (bottom_widget_) layout->addWidget(bottom_widget_);
|
|
|
|
emit CurrentChanged(index);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
FancyTabWidget::FancyTabWidget(QWidget* parent) : QTabWidget(parent),
|
|
|
|
menu_(nullptr),
|
|
|
|
mode_(Mode_None),
|
|
|
|
bottom_widget_(nullptr)
|
|
|
|
{
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
FancyTabBar *tabBar = new FancyTabBar(this);
|
|
|
|
setTabBar(tabBar);
|
|
|
|
setTabPosition(QTabWidget::West);
|
|
|
|
setMovable(true);
|
|
|
|
|
|
|
|
connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::loadSettings(const char *kSettingsGroup) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QSettings settings;
|
|
|
|
settings.beginGroup(kSettingsGroup);
|
|
|
|
|
|
|
|
for (int i = 0 ; i < count() ; i++) {
|
|
|
|
QString k = "tab_" + tabBar()->tabData(i).toString().toLower();
|
|
|
|
int index = settings.value(k, i).toInt();
|
2018-10-20 22:16:22 +02:00
|
|
|
if (index >= 0) {
|
2018-10-19 19:10:22 +02:00
|
|
|
tabBar()->moveTab(i, index);
|
2018-10-20 22:16:22 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
settings.endGroup();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::saveSettings(const char *kSettingsGroup) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QSettings settings;
|
|
|
|
settings.beginGroup(kSettingsGroup);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
for (int i = 0 ; i < count() ; i++) {
|
|
|
|
QString k = "tab_" + tabBar()->tabData(i).toString().toLower();
|
|
|
|
settings.setValue(k, i);
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
settings.endGroup();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-26 20:05:37 +02:00
|
|
|
void FancyTabWidget::addBottomWidget(QWidget* widget_view) {
|
|
|
|
bottom_widget_ = widget_view;
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-26 20:05:37 +02:00
|
|
|
int FancyTabWidget::addTab(QWidget *widget_view, const QIcon &icon, const QString &label) {
|
|
|
|
return insertTab(count(), widget_view, icon, label);
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-20 22:16:22 +02:00
|
|
|
int FancyTabWidget::insertTab(int index, QWidget *widget_view, const QIcon &icon, const QString &label) {
|
2018-08-29 21:42:24 +02:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QWidget *page(nullptr);
|
|
|
|
if (tabs_.contains(label)) page = tabs_.value(label);
|
|
|
|
else {
|
2018-10-20 22:16:22 +02:00
|
|
|
page = new QWidget(this);
|
2018-10-19 19:10:22 +02:00
|
|
|
// In order to achieve the same effect as the "Bottom Widget" of the old Nokia based FancyTabWidget a VBoxLayout is used on each page
|
2018-10-20 22:16:22 +02:00
|
|
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
2018-10-19 19:10:22 +02:00
|
|
|
layout->setSpacing(0);
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
2018-10-20 22:16:22 +02:00
|
|
|
layout->addWidget(widget_view);
|
2018-10-19 19:10:22 +02:00
|
|
|
page->setLayout(layout);
|
|
|
|
tabs_.insert(label, page);
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
for (int i = 0 ; i < count() ; i++) {
|
2018-10-20 22:16:22 +02:00
|
|
|
QString l = tabBar()->tabData(i).toString();
|
2018-10-19 19:10:22 +02:00
|
|
|
if (l == label) return i;
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
const int actualIndex = QTabWidget::insertTab(index, page, icon, label);
|
|
|
|
tabBar()->setTabData(actualIndex, QVariant(label));
|
|
|
|
return actualIndex;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::delTab(const QString &label) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
for (int i = 0 ; i < count() ; i++) {
|
2018-10-20 22:16:22 +02:00
|
|
|
QString l = tabBar()->tabData(i).toString();
|
|
|
|
if (l == label) {
|
|
|
|
removeTab(i);
|
|
|
|
break;
|
|
|
|
}
|
2018-08-29 21:42:24 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::paintEvent(QPaintEvent *pe) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
if (mode() != FancyTabWidget::Mode_LargeSidebar && mode() != FancyTabWidget::Mode_SmallSidebar) {
|
|
|
|
QTabWidget::paintEvent(pe);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QStylePainter p(this);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// The brown color (Ubuntu) you see on the background gradient
|
|
|
|
QColor baseColor = StyleHelper::baseColor();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
QRect backgroundRect = rect();
|
|
|
|
backgroundRect.setWidth(((FancyTabBar*)tabBar())->width());
|
|
|
|
p.fillRect(backgroundRect, baseColor);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Horizontal gradient over the sidebar from transparent to dark
|
2018-10-20 22:16:22 +02:00
|
|
|
Utils::StyleHelper::verticalGradient(&p, backgroundRect, backgroundRect, false);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Draw the translucent png graphics over the gradient fill
|
|
|
|
{
|
|
|
|
if (!background_pixmap_.isNull()) {
|
|
|
|
QRect pixmap_rect(background_pixmap_.rect());
|
|
|
|
pixmap_rect.moveTo(backgroundRect.topLeft());
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
while (pixmap_rect.top() < backgroundRect.bottom()) {
|
|
|
|
QRect source_rect(pixmap_rect.intersected(backgroundRect));
|
|
|
|
source_rect.moveTo(0, 0);
|
|
|
|
p.drawPixmap(pixmap_rect.topLeft(), background_pixmap_,source_rect);
|
|
|
|
pixmap_rect.moveTop(pixmap_rect.bottom() - 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
// Shadow effect of the background
|
|
|
|
{
|
|
|
|
QColor light(255, 255, 255, 80);
|
|
|
|
p.setPen(light);
|
|
|
|
p.drawLine(backgroundRect.topRight() - QPoint(1, 0), backgroundRect.bottomRight() - QPoint(1, 0));
|
|
|
|
QColor dark(0, 0, 0, 90);
|
|
|
|
p.setPen(dark);
|
|
|
|
p.drawLine(backgroundRect.topLeft(), backgroundRect.bottomLeft());
|
|
|
|
|
|
|
|
p.setPen(Utils::StyleHelper::borderColor());
|
|
|
|
p.drawLine(backgroundRect.topRight(), backgroundRect.bottomRight());
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::tabBarUpdateGeometry() {
|
|
|
|
tabBar()->updateGeometry();
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::SetMode(FancyTabWidget::Mode mode) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
mode_ = mode;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
if (mode == FancyTabWidget::Mode_Tabs || mode == FancyTabWidget::Mode_IconOnlyTabs) {
|
|
|
|
setTabPosition(QTabWidget::North);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setTabPosition(QTabWidget::West);
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
tabBar()->updateGeometry();
|
|
|
|
updateGeometry();
|
|
|
|
|
|
|
|
// There appears to be a bug in QTabBar which causes tabSizeHint to be ignored thus the need for this second shot repaint
|
|
|
|
QTimer::singleShot(1, this, SLOT(tabBarUpdateGeometry()));
|
|
|
|
|
|
|
|
emit ModeChanged(mode);
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::addMenuItem(QSignalMapper* mapper, QActionGroup* group, const QString& text, Mode mode) {
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
QAction* action = group->addAction(text);
|
|
|
|
action->setCheckable(true);
|
|
|
|
mapper->setMapping(action, mode);
|
|
|
|
connect(action, SIGNAL(triggered()), mapper, SLOT(map()));
|
|
|
|
|
|
|
|
if (mode == mode_) action->setChecked(true);
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
void FancyTabWidget::contextMenuEvent(QContextMenuEvent* e) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
if (!menu_) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
menu_ = new QMenu(this);
|
|
|
|
QSignalMapper* mapper = new QSignalMapper(this);
|
|
|
|
QActionGroup* group = new QActionGroup(this);
|
|
|
|
addMenuItem(mapper, group, tr("Large sidebar"), Mode_LargeSidebar);
|
|
|
|
addMenuItem(mapper, group, tr("Small sidebar"), Mode_SmallSidebar);
|
|
|
|
addMenuItem(mapper, group, tr("Plain sidebar"), Mode_PlainSidebar);
|
|
|
|
addMenuItem(mapper, group, tr("Tabs on top"), Mode_Tabs);
|
|
|
|
addMenuItem(mapper, group, tr("Icons on top"), Mode_IconOnlyTabs);
|
|
|
|
menu_->addActions(group->actions());
|
|
|
|
connect(mapper, SIGNAL(mapped(int)), SLOT(SetMode(int)));
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-19 19:10:22 +02:00
|
|
|
menu_->popup(e->globalPos());
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|