File indexing completed on 2024-05-19 04:58:31

0001 /**************************************************************************
0002 **
0003 ** This file is part of Qt Creator
0004 **
0005 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
0006 **
0007 ** Contact: Nokia Corporation (qt-info@nokia.com)
0008 **
0009 ** Commercial Usage
0010 **
0011 ** Licensees holding valid Qt Commercial licenses may use this file in
0012 ** accordance with the Qt Commercial License Agreement provided with the
0013 ** Software or, alternatively, in accordance with the terms contained in
0014 ** a written agreement between you and Nokia.
0015 **
0016 ** GNU Lesser General Public License Usage
0017 **
0018 ** Alternatively, this file may be used under the terms of the GNU Lesser
0019 ** General Public License version 2.1 as published by the Free Software
0020 ** Foundation and appearing in the file LICENSE.LGPL included in the
0021 ** packaging of this file.  Please review the following information to
0022 ** ensure the GNU Lesser General Public License version 2.1 requirements
0023 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0024 **
0025 ** If you are unsure which license is appropriate for your use, please
0026 ** contact the sales department at http://qt.nokia.com/contact.
0027 **
0028 **************************************************************************/
0029 
0030 #include "fancytabwidget.h"
0031 #include "stylehelper.h"
0032 
0033 #include <QAnimationGroup>
0034 #include <QColorDialog>
0035 #include <QHBoxLayout>
0036 #include <QMenu>
0037 #include <QMouseEvent>
0038 #include <QPainter>
0039 #include <QSignalMapper>
0040 #include <QSplitter>
0041 #include <QStackedLayout>
0042 #include <QStyleOptionTab>
0043 #include <QToolButton>
0044 #include <QToolTip>
0045 #include <QVBoxLayout>
0046 #include <QActionGroup>
0047 //#include <QWindowsStyle>
0048 
0049 using namespace Core;
0050 using namespace Internal;
0051 
0052 const int FancyTabBar::m_rounding = 22;
0053 const int FancyTabBar::m_textPadding = 4;
0054 
0055 void FancyTabProxyStyle::drawControl(
0056     ControlElement element, const QStyleOption* option,
0057     QPainter* p, const QWidget* widget) const
0058 {
0059 
0060     const auto* v_opt = qstyleoption_cast<const QStyleOptionTab*>(option);
0061 
0062     if (element != CE_TabBarTab || !v_opt) {
0063         QProxyStyle::drawControl(element, option, p, widget);
0064         return;
0065     }
0066 
0067     const QRect rect = v_opt->rect;
0068     const bool selected = v_opt->state & State_Selected;
0069     const bool vertical_tabs = v_opt->shape == QTabBar::RoundedWest;
0070     const QString text = v_opt->text;
0071 
0072     if (selected) {
0073         //background
0074         p->save();
0075         QLinearGradient grad(rect.topLeft(), rect.topRight());
0076         grad.setColorAt(0, QColor(255, 255, 255, 140));
0077         grad.setColorAt(1, QColor(255, 255, 255, 210));
0078         p->fillRect(rect.adjusted(0, 0, 0, -1), grad);
0079         p->restore();
0080 
0081         //shadows
0082         p->setPen(QColor(0, 0, 0, 110));
0083         p->drawLine(rect.topLeft() + QPoint(1, -1), rect.topRight() - QPoint(0, 1));
0084         p->drawLine(rect.bottomLeft(), rect.bottomRight());
0085         p->setPen(QColor(0, 0, 0, 40));
0086         p->drawLine(rect.topLeft(), rect.bottomLeft());
0087 
0088         //highlights
0089         p->setPen(QColor(255, 255, 255, 50));
0090         p->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0, 2));
0091         p->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0, 1));
0092         p->setPen(QColor(255, 255, 255, 40));
0093         p->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight());
0094         p->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1));
0095         p->drawLine(rect.bottomLeft() + QPoint(0, -1), rect.bottomRight() - QPoint(0, 1));
0096     }
0097 
0098     QTransform m;
0099     if (vertical_tabs) {
0100         m = QTransform::fromTranslate(rect.left(), rect.bottom());
0101         m.rotate(-90);
0102     }
0103     else {
0104         m = QTransform::fromTranslate(rect.left(), rect.top());
0105     }
0106 
0107     const QRect draw_rect(QPoint(0, 0), m.mapRect(rect).size());
0108 
0109     p->save();
0110     p->setTransform(m);
0111 
0112     QRect icon_rect(QPoint(8, 0), v_opt->iconSize);
0113     QRect text_rect(icon_rect.topRight() + QPoint(4, 0), draw_rect.size());
0114     text_rect.setRight(draw_rect.width());
0115     icon_rect.translate(0, (draw_rect.height() - icon_rect.height()) / 2);
0116 
0117     QFont boldFont(p->font());
0118     boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
0119     boldFont.setBold(true);
0120     p->setFont(boldFont);
0121     p->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110));
0122     int textFlags = Qt::AlignHCenter | Qt::AlignVCenter;
0123     p->drawText(text_rect, textFlags, text);
0124     p->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor());
0125     if (widget) {
0126         const QString fader_key = QSL("tab_") + text + QSL("_fader");
0127         const QString animation_key = QSL("tab_") + text + QSL("_animation");
0128 
0129         const QString tab_hover = widget->property("tab_hover").toString();
0130         int fader = widget->property(fader_key.toUtf8().constData()).toInt();
0131         auto* animation = widget->property(animation_key.toUtf8().constData()).value<QPropertyAnimation*>();
0132 
0133         if (!animation) {
0134             auto* mut_widget = const_cast<QWidget*>(widget);
0135             fader = 0;
0136             mut_widget->setProperty(fader_key.toUtf8().constData(), fader);
0137             animation = new QPropertyAnimation(mut_widget, fader_key.toUtf8(), mut_widget);
0138             connect(animation, SIGNAL(valueChanged(QVariant)), mut_widget, SLOT(update()));
0139             mut_widget->setProperty(animation_key.toUtf8().constData(), QVariant::fromValue(animation));
0140         }
0141 
0142         if (text == tab_hover) {
0143             if (animation->state() != QAbstractAnimation::Running && fader != 40) {
0144                 animation->stop();
0145                 animation->setDuration(80);
0146                 animation->setEndValue(40);
0147                 animation->start();
0148             }
0149         }
0150         else {
0151             if (animation->state() != QAbstractAnimation::Running && fader != 0) {
0152                 animation->stop();
0153                 animation->setDuration(160);
0154                 animation->setEndValue(0);
0155                 animation->start();
0156             }
0157         }
0158 
0159         if (!selected) {
0160             p->save();
0161             p->fillRect(draw_rect, QColor(255, 255, 255, fader));
0162             p->setPen(QPen(QColor(255, 255, 255, fader), 1.0));
0163             p->drawLine(draw_rect.topLeft(), vertical_tabs ? draw_rect.bottomLeft() : draw_rect.topRight());
0164             p->drawLine(draw_rect.bottomRight(), vertical_tabs ? draw_rect.topRight() : draw_rect.bottomLeft());
0165             p->restore();
0166         }
0167     }
0168 
0169     Utils::StyleHelper::drawIconWithShadow(v_opt->icon, icon_rect, p, selected ? QIcon::Selected : QIcon::Normal);
0170 
0171     p->drawText(text_rect.translated(0, -1), textFlags, text);
0172 
0173     p->restore();
0174 }
0175 
0176 void FancyTabProxyStyle::polish(QWidget* widget)
0177 {
0178     if (QString::fromLatin1(widget->metaObject()->className()) == QLatin1String("QTabBar")) {
0179         widget->setMouseTracking(true);
0180         widget->installEventFilter(this);
0181     }
0182     QProxyStyle::polish(widget);
0183 }
0184 
0185 void FancyTabProxyStyle::polish(QApplication* app)
0186 {
0187     QProxyStyle::polish(app);
0188 }
0189 
0190 void FancyTabProxyStyle::polish(QPalette &palette)
0191 {
0192     QProxyStyle::polish(palette);
0193 }
0194 
0195 bool FancyTabProxyStyle::eventFilter(QObject* o, QEvent* e)
0196 {
0197     auto* bar = qobject_cast<QTabBar*>(o);
0198     if (bar && (e->type() == QEvent::MouseMove || e->type() == QEvent::Leave)) {
0199         auto* event = static_cast<QMouseEvent*>(e);
0200         const QString old_hovered_tab = bar->property("tab_hover").toString();
0201         const QString hovered_tab = e->type() == QEvent::Leave ? QString() : bar->tabText(bar->tabAt(event->pos()));
0202         bar->setProperty("tab_hover", hovered_tab);
0203 
0204         if (old_hovered_tab != hovered_tab) {
0205             bar->update();
0206         }
0207     }
0208 
0209     return false;
0210 }
0211 
0212 FancyTab::FancyTab(QWidget* tabbar)
0213     : QWidget(tabbar), tabbar(tabbar), m_fader(0)
0214 {
0215     animator.setPropertyName("fader");
0216     animator.setTargetObject(this);
0217     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
0218 }
0219 
0220 void FancyTab::fadeIn()
0221 {
0222     animator.stop();
0223     animator.setDuration(80);
0224     animator.setEndValue(40);
0225     animator.start();
0226 }
0227 
0228 void FancyTab::fadeOut()
0229 {
0230     animator.stop();
0231     animator.setDuration(160);
0232     animator.setEndValue(0);
0233     animator.start();
0234 }
0235 
0236 void FancyTab::setFader(float value)
0237 {
0238     m_fader = value;
0239     tabbar->update();
0240 }
0241 
0242 FancyTabBar::FancyTabBar(QWidget* parent)
0243     : QWidget(parent)
0244     , m_currentIndex(-1)
0245 {
0246     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
0247     //setStyle(new QWindowsStyle);
0248     setMinimumWidth(qMax(2 * m_rounding, 40));
0249     setAttribute(Qt::WA_Hover, true);
0250     setFocusPolicy(Qt::NoFocus);
0251     setMouseTracking(true); // Needed for hover events
0252     m_triggerTimer.setSingleShot(true);
0253 
0254     auto* layout = new QVBoxLayout;
0255     layout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding));
0256     layout->setSpacing(0);
0257     layout->setContentsMargins(0, 0, 0, 0);
0258     setLayout(layout);
0259 
0260     // We use a zerotimer to keep the sidebar responsive
0261     connect(&m_triggerTimer, &QTimer::timeout, this, &FancyTabBar::emitCurrentIndex);
0262 }
0263 
0264 FancyTabBar::~FancyTabBar()
0265 {
0266     delete style();
0267 }
0268 
0269 QSize FancyTab::sizeHint() const
0270 {
0271     QFont boldFont(font());
0272     boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
0273     boldFont.setBold(true);
0274     QFontMetrics fm(boldFont);
0275     int spacing = 8;
0276     int width = 60 + spacing + 2;
0277     int iconHeight = 32;
0278     QSize ret(width, iconHeight + spacing + fm.height());
0279     return ret;
0280 }
0281 
0282 QSize FancyTabBar::tabSizeHint(bool minimum) const
0283 {
0284     QFont boldFont(font());
0285     boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
0286     boldFont.setBold(true);
0287     QFontMetrics fm(boldFont);
0288     int spacing = 8;
0289     int width = 60 + spacing + 2;
0290     int iconHeight = minimum ? 0 : 32;
0291     return QSize(width, iconHeight + spacing + fm.height());
0292 }
0293 
0294 void FancyTabBar::paintEvent(QPaintEvent* event)
0295 {
0296     Q_UNUSED(event)
0297     QPainter p(this);
0298 
0299     for (int i = 0; i < count(); ++i)
0300         if (i != currentIndex()) {
0301             paintTab(&p, i);
0302         }
0303 
0304     // paint active tab last, since it overlaps the neighbors
0305     if (currentIndex() != -1) {
0306         paintTab(&p, currentIndex());
0307     }
0308 }
0309 
0310 void FancyTab::enterEvent(QEnterEvent*)
0311 {
0312     fadeIn();
0313 }
0314 
0315 void FancyTab::leaveEvent(QEvent*)
0316 {
0317     fadeOut();
0318 }
0319 
0320 QSize FancyTabBar::sizeHint() const
0321 {
0322     QSize sh = tabSizeHint();
0323     return QSize(sh.width(), sh.height() * m_tabs.count());
0324 }
0325 
0326 QSize FancyTabBar::minimumSizeHint() const
0327 {
0328     QSize sh = tabSizeHint(true);
0329     return QSize(sh.width(), sh.height() * m_tabs.count());
0330 }
0331 
0332 QRect FancyTabBar::tabRect(int index) const
0333 {
0334     return m_tabs[index]->geometry();
0335 }
0336 
0337 QString FancyTabBar::tabToolTip(int index) const
0338 {
0339     return m_tabs[index]->toolTip();
0340 }
0341 
0342 void FancyTabBar::setTabToolTip(int index, const QString &toolTip)
0343 {
0344     m_tabs[index]->setToolTip(toolTip);
0345 }
0346 
0347 // This keeps the sidebar responsive since
0348 // we get a repaint before loading the
0349 // mode itself
0350 void FancyTabBar::emitCurrentIndex()
0351 {
0352     Q_EMIT currentChanged(m_currentIndex);
0353 }
0354 
0355 void FancyTabBar::mousePressEvent(QMouseEvent* e)
0356 {
0357     e->accept();
0358     for (int index = 0; index < m_tabs.count(); ++index) {
0359         if (tabRect(index).contains(e->pos())) {
0360             m_currentIndex = index;
0361             update();
0362             m_triggerTimer.start(0);
0363             break;
0364         }
0365     }
0366 }
0367 
0368 void FancyTabBar::addTab(const QIcon &icon, const QString &label)
0369 {
0370     auto* tab = new FancyTab(this);
0371     tab->icon = icon;
0372     tab->text = label;
0373     m_tabs.append(tab);
0374     qobject_cast<QVBoxLayout*>(layout())->insertWidget(layout()->count() - 1, tab);
0375 }
0376 
0377 void FancyTabBar::addSpacer(int size)
0378 {
0379     qobject_cast<QVBoxLayout*>(layout())->insertSpacerItem(layout()->count() - 1,
0380             new QSpacerItem(0, size, QSizePolicy::Fixed, QSizePolicy::Maximum));
0381 }
0382 
0383 void FancyTabBar::paintTab(QPainter* painter, int tabIndex) const
0384 {
0385     if (!validIndex(tabIndex)) {
0386         qWarning("invalid index");
0387         return;
0388     }
0389     painter->save();
0390 
0391     QRect rect = tabRect(tabIndex);
0392     bool selected = (tabIndex == m_currentIndex);
0393 
0394     if (selected) {
0395         //background
0396         painter->save();
0397         QLinearGradient grad(rect.topLeft(), rect.topRight());
0398         grad.setColorAt(0, QColor(255, 255, 255, 140));
0399         grad.setColorAt(1, QColor(255, 255, 255, 210));
0400         painter->fillRect(rect.adjusted(0, 0, 0, -1), grad);
0401         painter->restore();
0402 
0403         //shadows
0404         painter->setPen(QColor(0, 0, 0, 110));
0405         painter->drawLine(rect.topLeft() + QPoint(1, -1), rect.topRight() - QPoint(0, 1));
0406         painter->drawLine(rect.bottomLeft(), rect.bottomRight());
0407         painter->setPen(QColor(0, 0, 0, 40));
0408         painter->drawLine(rect.topLeft(), rect.bottomLeft());
0409 
0410         //highlights
0411         painter->setPen(QColor(255, 255, 255, 50));
0412         painter->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0, 2));
0413         painter->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0, 1));
0414         painter->setPen(QColor(255, 255, 255, 40));
0415         painter->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight());
0416         painter->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1));
0417         painter->drawLine(rect.bottomLeft() + QPoint(0, -1), rect.bottomRight() - QPoint(0, 1));
0418     }
0419 
0420     // QString tabText(painter->fontMetrics().elidedText(this->tabText(tabIndex), Qt::ElideMiddle, width()));
0421     QRect tabTextRect(tabRect(tabIndex));
0422     QRect tabIconRect(tabTextRect);
0423     tabIconRect.adjust(+4, +4, -4, -4);
0424     tabTextRect.translate(0, -2);
0425     QFont boldFont(painter->font());
0426     boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize());
0427     boldFont.setBold(true);
0428     painter->setFont(boldFont);
0429     painter->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110));
0430     // int textFlags = Qt::AlignCenter | Qt::AlignBottom;
0431     // painter->drawText(tabTextRect, textFlags, tabText);
0432     painter->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor());
0433 #ifndef Q_OS_MACOS
0434     if (!selected) {
0435         painter->save();
0436         int fader = int(m_tabs[tabIndex]->fader());
0437         QLinearGradient grad(rect.topLeft(), rect.topRight());
0438         grad.setColorAt(0, Qt::transparent);
0439         grad.setColorAt(0.5, QColor(255, 255, 255, fader));
0440         grad.setColorAt(1, Qt::transparent);
0441 //        painter->fillRect(rect, grad);
0442 //        painter->setPen(QPen(grad, 1.0));
0443         painter->fillRect(rect, QColor(255, 255, 255, fader));
0444         painter->setPen(QPen(QColor(255, 255, 255, fader), 1.0));
0445         painter->drawLine(rect.topLeft(), rect.topRight());
0446         painter->drawLine(rect.bottomLeft(), rect.bottomRight());
0447         painter->restore();
0448     }
0449 #endif
0450 
0451     // const int textHeight = painter->fontMetrics().height();
0452     tabIconRect.adjust(0, 6, 0, -6);
0453     Utils::StyleHelper::drawIconWithShadow(tabIcon(tabIndex), tabIconRect, painter, selected ? QIcon::Selected : QIcon::Normal);
0454 
0455     painter->translate(0, -1);
0456     // painter->drawText(tabTextRect, textFlags, tabText);
0457     painter->restore();
0458 }
0459 
0460 void FancyTabBar::setCurrentIndex(int index)
0461 {
0462     m_currentIndex = index;
0463     update();
0464     Q_EMIT currentChanged(m_currentIndex);
0465 }
0466 
0467 
0468 //////
0469 // FancyColorButton
0470 //////
0471 
0472 class FALKON_EXPORT FancyColorButton : public QWidget
0473 {
0474 public:
0475     FancyColorButton(QWidget* parent)
0476         : m_parent(parent) {
0477         setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
0478     }
0479 
0480     void mousePressEvent(QMouseEvent* ev) override {
0481         if (ev->modifiers() & Qt::ShiftModifier) {
0482             Utils::StyleHelper::setBaseColor(QColorDialog::getColor(Utils::StyleHelper::requestedBaseColor(), m_parent));
0483         }
0484     }
0485 private:
0486     QWidget* m_parent;
0487 };
0488 
0489 //////
0490 // FancyTabWidget
0491 //////
0492 
0493 FancyTabWidget::FancyTabWidget(QWidget* parent)
0494     : QWidget(parent),
0495       mode_(Mode_None),
0496       tab_bar_(nullptr),
0497       stack_(new QStackedLayout),
0498       side_widget_(new QWidget),
0499       side_layout_(new QVBoxLayout),
0500       top_layout_(new QVBoxLayout),
0501       use_background_(false),
0502       menu_(nullptr),
0503       proxy_style_(new FancyTabProxyStyle)
0504 {
0505     side_layout_->setSpacing(0);
0506     side_layout_->setContentsMargins(0, 0, 0, 0);
0507     side_layout_->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding));
0508 
0509     side_widget_->setLayout(side_layout_);
0510     side_widget_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
0511 
0512     top_layout_->setContentsMargins(0, 0, 0, 0);
0513     top_layout_->setSpacing(0);
0514     top_layout_->addLayout(stack_);
0515 
0516     auto* main_layout = new QHBoxLayout;
0517     main_layout->setContentsMargins(0, 0, 0, 0);
0518     main_layout->setSpacing(1);
0519     main_layout->addWidget(side_widget_);
0520     main_layout->addLayout(top_layout_);
0521     setLayout(main_layout);
0522 }
0523 
0524 void FancyTabWidget::AddTab(QWidget* tab, const QIcon &icon, const QString &label)
0525 {
0526     stack_->addWidget(tab);
0527     items_ << Item(icon, label);
0528 }
0529 
0530 void FancyTabWidget::AddSpacer(int size)
0531 {
0532     items_ << Item(size);
0533 }
0534 
0535 void FancyTabWidget::SetBackgroundPixmap(const QPixmap &pixmap)
0536 {
0537     background_pixmap_ = pixmap;
0538     update();
0539 }
0540 
0541 void FancyTabWidget::paintEvent(QPaintEvent*)
0542 {
0543     if (!use_background_) {
0544         return;
0545     }
0546 
0547     QPainter painter(this);
0548 
0549     QRect rect = side_widget_->rect().adjusted(0, 0, 1, 0);
0550     rect = style()->visualRect(layoutDirection(), geometry(), rect);
0551     Utils::StyleHelper::verticalGradient(&painter, rect, rect);
0552 
0553     if (!background_pixmap_.isNull()) {
0554         QRect pixmap_rect(background_pixmap_.rect());
0555         pixmap_rect.moveTo(rect.topLeft());
0556 
0557         while (pixmap_rect.top() < rect.bottom()) {
0558             QRect source_rect(pixmap_rect.intersected(rect));
0559             source_rect.moveTo(0, 0);
0560             painter.drawPixmap(pixmap_rect.topLeft(), background_pixmap_, source_rect);
0561             pixmap_rect.moveTop(pixmap_rect.bottom() - 10);
0562         }
0563     }
0564 
0565     painter.setPen(Utils::StyleHelper::borderColor());
0566     painter.drawLine(rect.topRight(), rect.bottomRight());
0567 
0568     QColor light = Utils::StyleHelper::sidebarHighlight();
0569     painter.setPen(light);
0570     painter.drawLine(rect.bottomLeft(), rect.bottomRight());
0571 }
0572 
0573 int FancyTabWidget::current_index() const
0574 {
0575     return stack_->currentIndex();
0576 }
0577 
0578 void FancyTabWidget::SetCurrentIndex(int index)
0579 {
0580     if (auto* bar = qobject_cast<FancyTabBar*>(tab_bar_)) {
0581         bar->setCurrentIndex(index);
0582     }
0583     else if (auto* bar = qobject_cast<QTabBar*>(tab_bar_)) {
0584         bar->setCurrentIndex(index);
0585     }
0586     else {
0587         stack_->setCurrentIndex(index);
0588     }
0589 }
0590 
0591 void FancyTabWidget::ShowWidget(int index)
0592 {
0593     stack_->setCurrentIndex(index);
0594     Q_EMIT CurrentChanged(index);
0595 }
0596 
0597 void FancyTabWidget::AddBottomWidget(QWidget* widget)
0598 {
0599     top_layout_->addWidget(widget);
0600 }
0601 
0602 void FancyTabWidget::SetMode(FancyTabWidget::Mode mode)
0603 {
0604     // Remove previous tab bar
0605     delete tab_bar_;
0606     tab_bar_ = nullptr;
0607 
0608     use_background_ = false;
0609 
0610     // Create new tab bar
0611     switch (mode) {
0612     case Mode_None:
0613     default:
0614         qDebug() << "Unknown fancy tab mode" << mode;
0615         // fallthrough
0616 
0617     case Mode_LargeSidebar: {
0618         auto* bar = new FancyTabBar(this);
0619         side_layout_->insertWidget(0, bar);
0620         tab_bar_ = bar;
0621 
0622         for (const Item &item : std::as_const(items_)) {
0623             if (item.type_ == Item::Type_Spacer) {
0624                 bar->addSpacer(item.spacer_size_);
0625             }
0626             else {
0627                 bar->addTab(item.tab_icon_, item.tab_label_);
0628             }
0629         }
0630 
0631         bar->setCurrentIndex(stack_->currentIndex());
0632         connect(bar, &FancyTabBar::currentChanged, this, &FancyTabWidget::ShowWidget);
0633 
0634         use_background_ = true;
0635 
0636         break;
0637     }
0638 
0639     case Mode_Tabs:
0640         MakeTabBar(QTabBar::RoundedNorth, true, false, false);
0641         break;
0642 
0643     case Mode_IconOnlyTabs:
0644         MakeTabBar(QTabBar::RoundedNorth, false, true, false);
0645         break;
0646 
0647     case Mode_SmallSidebar:
0648         MakeTabBar(QTabBar::RoundedWest, true, true, true);
0649         use_background_ = true;
0650         break;
0651 
0652     case Mode_PlainSidebar:
0653         MakeTabBar(QTabBar::RoundedWest, true, true, false);
0654         break;
0655     }
0656 
0657     tab_bar_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
0658 
0659     mode_ = mode;
0660     Q_EMIT ModeChanged(mode);
0661     update();
0662 }
0663 
0664 void FancyTabWidget::contextMenuEvent(QContextMenuEvent* e)
0665 {
0666     Q_UNUSED(e)
0667 //  if (!menu_) {
0668 //    menu_ = new QMenu(this);
0669 
0670 //    QSignalMapper* mapper = new QSignalMapper(this);
0671 //    QActionGroup* group = new QActionGroup(this);
0672 //    AddMenuItem(mapper, group, tr("Large sidebar"), Mode_LargeSidebar);
0673 //    AddMenuItem(mapper, group, tr("Small sidebar"), Mode_SmallSidebar);
0674 //    AddMenuItem(mapper, group, tr("Plain sidebar"), Mode_PlainSidebar);
0675 //    AddMenuItem(mapper, group, tr("Tabs on top"), Mode_Tabs);
0676 //    AddMenuItem(mapper, group, tr("Icons on top"), Mode_IconOnlyTabs);
0677 //    menu_->addActions(group->actions());
0678 
0679 //    connect(mapper, SIGNAL(mapped(int)), SLOT(SetMode(int)));
0680 //  }
0681 
0682 //  menu_->popup(e->globalPos());
0683 }
0684 
0685 void FancyTabWidget::AddMenuItem(QSignalMapper* mapper, QActionGroup* group,
0686                                  const QString &text, Mode mode)
0687 {
0688     QAction* action = group->addAction(text);
0689     action->setCheckable(true);
0690     mapper->setMapping(action, mode);
0691     connect(action, SIGNAL(triggered()), mapper, SLOT(map()));
0692 
0693     if (mode == mode_) {
0694         action->setChecked(true);
0695     }
0696 }
0697 
0698 void FancyTabWidget::MakeTabBar(QTabBar::Shape shape, bool text, bool icons,
0699                                 bool fancy)
0700 {
0701     auto* bar = new QTabBar(this);
0702     bar->setShape(shape);
0703     bar->setDocumentMode(true);
0704     bar->setUsesScrollButtons(true);
0705 
0706     if (shape == QTabBar::RoundedWest) {
0707         bar->setIconSize(QSize(22, 22));
0708     }
0709 
0710     if (fancy) {
0711         bar->setStyle(proxy_style_);
0712     }
0713 
0714     if (shape == QTabBar::RoundedNorth) {
0715         top_layout_->insertWidget(0, bar);
0716     }
0717     else {
0718         side_layout_->insertWidget(0, bar);
0719     }
0720 
0721     for (const Item &item : std::as_const(items_)) {
0722         if (item.type_ != Item::Type_Tab) {
0723             continue;
0724         }
0725 
0726         QString label = item.tab_label_;
0727         if (shape == QTabBar::RoundedWest) {
0728             label = QFontMetrics(font()).elidedText(label, Qt::ElideMiddle, 100);
0729         }
0730 
0731         int tab_id = -1;
0732         if (icons && text) {
0733             tab_id = bar->addTab(item.tab_icon_, label);
0734         }
0735         else if (icons) {
0736             tab_id = bar->addTab(item.tab_icon_, QString());
0737         }
0738         else if (text) {
0739             tab_id = bar->addTab(label);
0740         }
0741 
0742         bar->setTabToolTip(tab_id, item.tab_label_);
0743     }
0744 
0745     bar->setCurrentIndex(stack_->currentIndex());
0746     connect(bar, &QTabBar::currentChanged, this, &FancyTabWidget::ShowWidget);
0747     tab_bar_ = bar;
0748 }