File indexing completed on 2024-11-24 04:34:22

0001 /***************************************************************************
0002  *   SPDX-License-Identifier: GPL-2.0-or-later
0003  *                                                                         *
0004  *   SPDX-FileCopyrightText: 2004-2023 Thomas Fischer <fischer@unix-ag.uni-kl.de>
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  *   This program is distributed in the hope that it will be useful,       *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0014  *   GNU General Public License for more details.                          *
0015  *                                                                         *
0016  *   You should have received a copy of the GNU General Public License     *
0017  *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
0018  ***************************************************************************/
0019 
0020 #include "hidingtabwidget.h"
0021 
0022 #include <QSet>
0023 
0024 typedef struct {
0025     /// the hidden widget
0026     QWidget *widget;
0027     /// the hidden widget's neighboring widgets,
0028     /// used to find a place where to insert the tab when it will be shown again.
0029     QWidget *leftNeighborWidget, *rightNeighborWidget;
0030     /// tab properties
0031     QIcon icon;
0032     QString label;
0033     bool enabled;
0034     QString toolTip;
0035     QString whatsThis;
0036 } HiddenTabInfo;
0037 
0038 class HidingTabWidget::Private {
0039 private:
0040     HidingTabWidget *parent;
0041     QTabWidget *parentAsQTabWidget;
0042 
0043 public:
0044     QSet<HiddenTabInfo> hiddenTabInfo;
0045 
0046     Private(HidingTabWidget *_parent)
0047             : parent(_parent), parentAsQTabWidget(qobject_cast<QTabWidget *>(_parent))
0048     {
0049         /// nothing
0050     }
0051 
0052     int showTab(const HiddenTabInfo &hti, int index = InvalidTabPosition)
0053     {
0054         if (index <0) {
0055             /// No position to insert tab given, so make an educated guess
0056             index = parent->count(); ///< Append at end of tab row by default
0057             int i = InvalidTabPosition;
0058             if ((i = parent->indexOf(hti.leftNeighborWidget)) >= 0)
0059                 index = i + 1; ///< Right of left neighbor
0060             else if ((i = parent->indexOf(hti.rightNeighborWidget)) >= 0)
0061                 index = i; ///< Left of right neighbor
0062         }
0063 
0064         /// Insert tab using QTabWidget's original function
0065         index = parentAsQTabWidget->insertTab(index, hti.widget, hti.icon, hti.label);
0066         /// Restore tab's properties
0067         parent->setTabToolTip(index, hti.toolTip);
0068         parent->setTabWhatsThis(index, hti.whatsThis);
0069         parent->setTabEnabled(index, hti.enabled);
0070 
0071         return index;
0072     }
0073 };
0074 
0075 
0076 /// required to for QSet<HiddenTabInfo>
0077 uint qHash(const HiddenTabInfo &hti)
0078 {
0079     return qHash(hti.widget);
0080 }
0081 
0082 /// required to for QSet<HiddenTabInfo>
0083 bool operator==(const HiddenTabInfo &a, const HiddenTabInfo &b)
0084 {
0085     return a.widget == b.widget;
0086 }
0087 
0088 const int HidingTabWidget::InvalidTabPosition = -1;
0089 
0090 HidingTabWidget::HidingTabWidget(QWidget *parent)
0091         : QTabWidget(parent), d(new Private(this))
0092 {
0093     /// nothing to see here
0094 }
0095 
0096 HidingTabWidget::~HidingTabWidget()
0097 {
0098     delete d;
0099 }
0100 
0101 QWidget *HidingTabWidget::hideTab(int index)
0102 {
0103     if (index < 0 || index >= count()) return nullptr;
0104 
0105     HiddenTabInfo hti;
0106     hti.widget = widget(index);
0107     hti.leftNeighborWidget = index > 0 ? widget(index - 1) : nullptr;
0108     hti.rightNeighborWidget = index < count() - 1 ? widget(index + 1) : nullptr;
0109     hti.label = tabText(index);
0110     hti.icon = tabIcon(index);
0111     hti.enabled = isTabEnabled(index);
0112     hti.toolTip = tabToolTip(index);
0113     hti.whatsThis = tabWhatsThis(index);
0114     d->hiddenTabInfo.insert(hti);
0115 
0116     QTabWidget::removeTab(index);
0117 
0118     return hti.widget;
0119 }
0120 
0121 int HidingTabWidget::showTab(QWidget *page)
0122 {
0123     for (const HiddenTabInfo &hti : const_cast<const QSet<HiddenTabInfo> &>(d->hiddenTabInfo)) {
0124         if (hti.widget == page)
0125             return d->showTab(hti);
0126     }
0127 
0128     return InvalidTabPosition;
0129 }
0130 
0131 void HidingTabWidget::removeTab(int index)
0132 {
0133     if (index >= 0 && index < count()) {
0134         QWidget *page = widget(index);
0135         for (const HiddenTabInfo &hti : const_cast<const QSet<HiddenTabInfo> &>(d->hiddenTabInfo)) {
0136             if (hti.widget == page) {
0137                 d->hiddenTabInfo.remove(hti);
0138                 break;
0139             }
0140         }
0141         QTabWidget::removeTab(index);
0142     }
0143 }
0144 
0145 int HidingTabWidget::addTab(QWidget *page, const QString &label)
0146 {
0147     for (const HiddenTabInfo &hti : const_cast<const QSet<HiddenTabInfo> &>(d->hiddenTabInfo)) {
0148         if (hti.widget == page) {
0149             int pos = d->showTab(hti);
0150             setTabText(pos, label);
0151             return pos;
0152         }
0153     }
0154 
0155     return QTabWidget::addTab(page, label);
0156 }
0157 
0158 int HidingTabWidget::addTab(QWidget *page, const QIcon &icon, const QString &label)
0159 {
0160     for (const HiddenTabInfo &hti : const_cast<const QSet<HiddenTabInfo> &>(d->hiddenTabInfo)) {
0161         if (hti.widget == page) {
0162             int pos = d->showTab(hti);
0163             setTabIcon(pos, icon);
0164             setTabText(pos, label);
0165             return pos;
0166         }
0167     }
0168 
0169     return QTabWidget::addTab(page, icon, label);
0170 }
0171 
0172 int HidingTabWidget::insertTab(int index, QWidget *page, const QString &label)
0173 {
0174     for (const HiddenTabInfo &hti : const_cast<const QSet<HiddenTabInfo> &>(d->hiddenTabInfo)) {
0175         if (hti.widget == page) {
0176             int pos = d->showTab(hti, index);
0177             setTabText(pos, label);
0178             return pos;
0179         }
0180     }
0181 
0182     return QTabWidget::insertTab(index, page, label);
0183 }
0184 
0185 int HidingTabWidget::insertTab(int index, QWidget *page, const QIcon &icon, const QString &label)
0186 {
0187     for (const HiddenTabInfo &hti : const_cast<const QSet<HiddenTabInfo> &>(d->hiddenTabInfo)) {
0188         if (hti.widget == page) {
0189             index = d->showTab(hti, index);
0190             setTabIcon(index, icon);
0191             setTabText(index, label);
0192             return index;
0193         }
0194     }
0195 
0196     return QTabWidget::insertTab(index, page, icon, label);
0197 }
0198 
0199 bool HidingTabWidget::tabIsShown(QWidget *page) const
0200 {
0201     for (int i = 0; i < count(); ++i)
0202         if (widget(i) == page)
0203             return true;
0204     return false;
0205 }