/******************************************************************************* ** Qt Advanced Docking System ** Copyright (C) 2017 Uwe Kindler ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; If not, see . ******************************************************************************/ //============================================================================ /// \file DockWidgetTab.h /// \author Syarif Fakhri /// \date 05.09.2022 /// \brief Implementation of CDockWidgetSideTab class //============================================================================ //============================================================================ // INCLUDES //============================================================================ #include #include "DockWidgetSideTab.h" #include "SideTabBar.h" #include #include "DockAreaWidget.h" #include "DockManager.h" #include "ElidingLabel.h" #include "DockWidget.h" namespace ads { using tTabLabel = CVerticalElidingLabel; /** * Private data class of CDockWidgetTab class (pimpl) */ struct DockWidgetSideTabPrivate { CDockWidgetSideTab* _this; CDockWidget* DockWidget; tTabLabel* TitleLabel; QBoxLayout* Layout; QBoxLayout* TitleLayout; // To have independent spacing from the icon CSideTabBar* SideTabBar; QSize IconSize; Qt::Orientation Orientation{Qt::Vertical}; SideTabIconLabel* IconLabel = nullptr; QIcon Icon; /** * Private data constructor */ DockWidgetSideTabPrivate(CDockWidgetSideTab* _public); /** * Creates the complete layout */ void createLayout(); /** * Update the icon in case the icon size changed */ void updateIcon() { if (!IconLabel || Icon.isNull()) { return; } if (IconSize.isValid()) { IconLabel->setPixmap(Icon.pixmap(IconSize)); } else { IconLabel->setPixmap(Icon.pixmap(_this->style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, _this))); } IconLabel->setVisible(true); } void updateContentsMargins() { QFontMetrics fm(TitleLabel->font()); int Spacing = qRound(fm.height() / 2.0); if (Orientation == Qt::Vertical) { TitleLayout->setContentsMargins(Spacing, Spacing, 0, Spacing); if (IconLabel) { IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing / 2, 0); } } else if (Orientation == Qt::Horizontal) { TitleLayout->setContentsMargins(Spacing / 2, Spacing, Spacing, Spacing); if (IconLabel) { IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, 0, Spacing / 2); } } } }; // struct DockWidgetTabPrivate //============================================================================ DockWidgetSideTabPrivate::DockWidgetSideTabPrivate(CDockWidgetSideTab* _public) : _this(_public) { } //============================================================================ void DockWidgetSideTabPrivate::createLayout() { TitleLabel = new tTabLabel(); TitleLabel->setElideMode(Qt::ElideRight); TitleLabel->setText(DockWidget->windowTitle()); TitleLabel->setObjectName("dockWidgetTabLabel"); _this->connect(TitleLabel, SIGNAL(elidedChanged(bool)), SIGNAL(elidedChanged(bool))); // Fill the layout // Purely for spacing on the text without messing up spacing on the icon TitleLayout = new QBoxLayout(QBoxLayout::TopToBottom); TitleLayout->setAlignment(Qt::AlignCenter); TitleLayout->addWidget(TitleLabel); TitleLayout->setSpacing(0); Layout = new QBoxLayout(QBoxLayout::TopToBottom); Layout->setAlignment(Qt::AlignCenter); Layout->setContentsMargins(0,0,0,0); Layout->setSpacing(0); _this->setLayout(Layout); Layout->addLayout(TitleLayout); updateContentsMargins(); TitleLabel->setVisible(true); } //============================================================================ void CDockWidgetSideTab::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { emit clicked(); } QFrame::mousePressEvent(event); } //============================================================================ void CDockWidgetSideTab::setSideTabBar(CSideTabBar* SideTabBar) { d->SideTabBar = SideTabBar; } //============================================================================ void CDockWidgetSideTab::removeFromSideTabBar() { if (d->SideTabBar == nullptr) { return; } d->SideTabBar->removeSideTab(this); setSideTabBar(nullptr); } //============================================================================ CDockWidgetSideTab::CDockWidgetSideTab(CDockWidget* DockWidget, QWidget* parent) : QFrame(parent), d(new DockWidgetSideTabPrivate(this)) { setAttribute(Qt::WA_NoMousePropagation); d->DockWidget = DockWidget; d->createLayout(); setFocusPolicy(Qt::NoFocus); } //============================================================================ CDockWidgetSideTab::~CDockWidgetSideTab() { delete d; } //============================================================================ void CDockWidgetSideTab::updateStyle() { internal::repolishStyle(this, internal::RepolishDirectChildren); } //============================================================================ CDockWidgetSideTab::SideTabBarArea CDockWidgetSideTab::sideTabBarArea() const { auto dockAreaWidget = d->DockWidget->dockAreaWidget(); if (dockAreaWidget && dockAreaWidget->isAutoHide()) { return dockAreaWidget->autoHideDockContainer()->sideTabBarArea(); } return Left; } //============================================================================ void CDockWidgetSideTab::setIcon(const QIcon& Icon) { QBoxLayout* Layout = qobject_cast(layout()); if (!d->IconLabel && Icon.isNull()) { return; } if (!d->IconLabel) { d->IconLabel = new SideTabIconLabel(); internal::setToolTip(d->IconLabel, d->TitleLabel->toolTip()); Layout->insertWidget(0, d->IconLabel, Qt::AlignHCenter); } else if (Icon.isNull()) { // Remove icon label Layout->removeWidget(d->IconLabel); delete d->IconLabel; d->IconLabel = nullptr; } d->Icon = Icon; d->updateIcon(); } //============================================================================ QSize CDockWidgetSideTab::iconSize() const { return d->IconSize; } //============================================================================ void CDockWidgetSideTab::setIconSize(const QSize& Size) { d->IconSize = Size; d->updateIcon(); } //============================================================================ void CDockWidgetSideTab::setOrientation(Qt::Orientation Orientation) { d->Orientation = Orientation; d->Layout->setDirection(Orientation == Qt::Vertical ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); d->TitleLabel->setOrientation(Orientation); updateStyle(); } //============================================================================ void CDockWidgetSideTab::updateOrientationAndSpacing(SideTabBarArea area) { setOrientation((area == Bottom || area == Top) ? Qt::Horizontal : Qt::Vertical); d->updateContentsMargins(); // Handle Icon changes if (d->Icon.isNull()) { return; } QFontMetrics fm(d->TitleLabel->font()); int Spacing = qRound(fm.height() / 2.0); if (CDockManager::testConfigFlag(CDockManager::LeftSideBarPrioritizeIconOnly) && area == Left) { d->TitleLabel->hide(); d->TitleLayout->setContentsMargins(0, 0, 0, 0); d->IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing / 2, Spacing / 2); return; } if (CDockManager::testConfigFlag(CDockManager::RightSideBarPrioritizeIconOnly) && area == Right) { d->TitleLabel->hide(); d->TitleLayout->setContentsMargins(0, 0, 0, 0); d->IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing, Spacing / 2); return; } if (CDockManager::testConfigFlag(CDockManager::BottomSideBarPrioritizeIconOnly) && area == Bottom) { d->TitleLabel->hide(); d->TitleLayout->setContentsMargins(0, 0, 0, 0); d->IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing / 2, Spacing); return; } if (CDockManager::testConfigFlag(CDockManager::TopSideBarPrioritizeIconOnly) && area == Top) { d->TitleLabel->hide(); d->TitleLayout->setContentsMargins(0, 0, 0, 0); d->IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing / 2, Spacing / 2); return; } d->TitleLabel->show(); } //============================================================================ bool CDockWidgetSideTab::isActiveTab() const { if (d->DockWidget->autoHideDockContainer()) { return d->DockWidget->autoHideDockContainer()->isVisible(); } return false; } //============================================================================ CDockWidget* CDockWidgetSideTab::dockWidget() const { return d->DockWidget; } /** * Private data class of SideTabIcon class (pimpl) */ struct SideTabIconLabelPrivate { SideTabIconLabel* _this; QLabel* IconLabel; QBoxLayout* Layout; SideTabIconLabelPrivate(SideTabIconLabel* _public); }; // struct SideTabIconLabelPrivate //============================================================================ SideTabIconLabelPrivate::SideTabIconLabelPrivate(SideTabIconLabel* _public) : _this(_public) { } //============================================================================ SideTabIconLabel::SideTabIconLabel(QWidget* parent) : QWidget(parent), d(new SideTabIconLabelPrivate(this)) { d->Layout = new QBoxLayout(QBoxLayout::TopToBottom); d->Layout->addWidget(d->IconLabel = new QLabel()); d->Layout->setAlignment(Qt::AlignCenter); d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); setLayout(d->Layout); } //============================================================================ SideTabIconLabel::~SideTabIconLabel() { delete d; } //============================================================================ void SideTabIconLabel::setPixmap(const QPixmap& pixmap) { d->IconLabel->setPixmap(pixmap); } //============================================================================ void SideTabIconLabel::setContentsMargins(int left, int top, int right, int bottom) { d->Layout->setContentsMargins(left, top, right, bottom); } }