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 }