File indexing completed on 2024-04-21 04:58:39

0001 /*
0002     SPDX-FileCopyrightText: 2009 Tony Murray <murraytony@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "tabbedviewwidget.h"
0008 #include "krdc_debug.h"
0009 
0010 #include <QRegularExpression>
0011 #include <QTabBar>
0012 
0013 TabbedViewWidgetModel::TabbedViewWidgetModel(QTabWidget *modelTarget)
0014     : QAbstractItemModel(modelTarget)
0015     , m_tabWidget(modelTarget)
0016 {
0017 }
0018 
0019 QModelIndex TabbedViewWidgetModel::index(int row, int column, const QModelIndex &parent) const
0020 {
0021     if (!hasIndex(row, column, parent)) {
0022         return QModelIndex();
0023     }
0024     return createIndex(row, column, m_tabWidget->widget(row));
0025 }
0026 
0027 QModelIndex TabbedViewWidgetModel::parent(const QModelIndex &) const
0028 {
0029     return QModelIndex();
0030 }
0031 
0032 int TabbedViewWidgetModel::columnCount(const QModelIndex &) const
0033 {
0034     return 1;
0035 }
0036 
0037 int TabbedViewWidgetModel::rowCount(const QModelIndex &) const
0038 {
0039     return m_tabWidget->count();
0040 }
0041 
0042 Qt::ItemFlags TabbedViewWidgetModel::flags(const QModelIndex &index) const
0043 {
0044     if (!index.isValid()) {
0045         return Qt::ItemIsEnabled;
0046     }
0047     return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
0048 }
0049 
0050 bool TabbedViewWidgetModel::setData(const QModelIndex &index, const QVariant &value, int role)
0051 {
0052     if (index.isValid() && role == Qt::EditRole) {
0053         m_tabWidget->setTabText(index.row(), value.toString());
0054         Q_EMIT dataChanged(index, index);
0055         return true;
0056     }
0057     return false;
0058 }
0059 
0060 QVariant TabbedViewWidgetModel::data(const QModelIndex &index, int role) const
0061 {
0062     if (!index.isValid()) {
0063         return QVariant();
0064     }
0065 
0066     switch (role) {
0067     case Qt::EditRole:
0068     case Qt::DisplayRole: {
0069         static QRegularExpression reg(QStringLiteral("&(?!&)"));
0070         return m_tabWidget->tabText(index.row()).remove(reg); // remove accelerator string
0071     }
0072     case Qt::ToolTipRole:
0073         return m_tabWidget->tabToolTip(index.row());
0074     case Qt::DecorationRole:
0075         return m_tabWidget->tabIcon(index.row());
0076     default:
0077         return QVariant();
0078     }
0079 }
0080 
0081 void TabbedViewWidgetModel::emitLayoutAboutToBeChanged()
0082 {
0083     Q_EMIT layoutAboutToBeChanged();
0084 }
0085 
0086 void TabbedViewWidgetModel::emitLayoutChanged()
0087 {
0088     Q_EMIT layoutChanged();
0089 }
0090 
0091 void TabbedViewWidgetModel::emitDataChanged(int index)
0092 {
0093     QModelIndex modelIndex = createIndex(index, 1);
0094     Q_EMIT dataChanged(modelIndex, modelIndex);
0095 }
0096 
0097 TabbedViewWidget::TabbedViewWidget(QWidget *parent)
0098     : QTabWidget(parent)
0099     , m_model(new TabbedViewWidgetModel(this))
0100 {
0101 }
0102 
0103 TabbedViewWidget::~TabbedViewWidget()
0104 {
0105 }
0106 
0107 TabbedViewWidgetModel *TabbedViewWidget::getModel()
0108 {
0109     return m_model;
0110 }
0111 
0112 int TabbedViewWidget::addTab(QWidget *page, const QString &label)
0113 {
0114     int count = QTabWidget::count();
0115     m_model->beginInsertRows(QModelIndex(), count, count);
0116     int ret = QTabWidget::addTab(page, label);
0117     m_model->endInsertRows();
0118     return ret;
0119 }
0120 
0121 int TabbedViewWidget::addTab(QWidget *page, const QIcon &icon, const QString &label)
0122 {
0123     int count = QTabWidget::count();
0124     m_model->beginInsertRows(QModelIndex(), count, count);
0125     int ret = QTabWidget::addTab(page, icon, label);
0126     m_model->endInsertRows();
0127     return ret;
0128 }
0129 
0130 int TabbedViewWidget::insertTab(int index, QWidget *page, const QString &label)
0131 {
0132     m_model->beginInsertRows(QModelIndex(), index, index);
0133     int ret = QTabWidget::insertTab(index, page, label);
0134     m_model->endInsertRows();
0135     return ret;
0136 }
0137 
0138 int TabbedViewWidget::insertTab(int index, QWidget *page, const QIcon &icon, const QString &label)
0139 {
0140     m_model->beginInsertRows(QModelIndex(), index, index);
0141     int ret = QTabWidget::insertTab(index, page, icon, label);
0142     m_model->endInsertRows();
0143     return ret;
0144 }
0145 
0146 void TabbedViewWidget::removePage(QWidget *page)
0147 {
0148     int index = QTabWidget::indexOf(page);
0149     if (index == -1) {
0150         return;
0151     }
0152     m_model->beginRemoveRows(QModelIndex(), index, index);
0153     QTabWidget::removeTab(index);
0154     m_model->endRemoveRows();
0155 }
0156 
0157 void TabbedViewWidget::removeTab(int index)
0158 {
0159     m_model->beginRemoveRows(QModelIndex(), index, index);
0160     QTabWidget::removeTab(index);
0161     m_model->endRemoveRows();
0162 }
0163 
0164 void TabbedViewWidget::moveTab(int from, int to)
0165 {
0166     m_model->emitLayoutAboutToBeChanged();
0167     tabBar()->moveTab(from, to);
0168     m_model->emitLayoutChanged();
0169 }
0170 
0171 void TabbedViewWidget::setTabText(int index, const QString &label)
0172 {
0173     QTabWidget::setTabText(index, label);
0174     m_model->emitDataChanged(index);
0175 }
0176 
0177 // This functionality is taken from  KTabWidget for compatibility.
0178 // KTabWidget has been moved to KdeLibs4Support and QTabWidget::tabBarDoubleClicked does not
0179 // work on empty space after tabs,
0180 bool TabbedViewWidget::isEmptyTabbarSpace(const QPoint &point) const
0181 {
0182     if (count() == 0) {
0183         return true;
0184     }
0185     if (tabBar()->isHidden()) {
0186         return false;
0187     }
0188     QSize size(tabBar()->sizeHint());
0189     if ((tabPosition() == QTabWidget::North && point.y() < size.height()) || (tabPosition() == QTabWidget::South && point.y() > (height() - size.height()))) {
0190         QWidget *rightcorner = cornerWidget(Qt::TopRightCorner);
0191         if (rightcorner && rightcorner->isVisible()) {
0192             if (point.x() >= width() - rightcorner->width()) {
0193                 return false;
0194             }
0195         }
0196 
0197         QWidget *leftcorner = cornerWidget(Qt::TopLeftCorner);
0198         if (leftcorner && leftcorner->isVisible()) {
0199             if (point.x() <= leftcorner->width()) {
0200                 return false;
0201             }
0202         }
0203 
0204         for (int i = 0; i < count(); ++i)
0205             if (tabBar()->tabRect(i).contains(tabBar()->mapFromParent(point))) {
0206                 return false;
0207             }
0208 
0209         return true;
0210     }
0211 
0212     return false;
0213 }
0214 
0215 void TabbedViewWidget::mouseDoubleClickEvent(QMouseEvent *event)
0216 {
0217     if (event->button() != Qt::LeftButton) {
0218         return;
0219     }
0220 
0221     if (isEmptyTabbarSpace(event->pos())) {
0222         Q_EMIT tabBarDoubleClicked(-1);
0223         return;
0224     }
0225 
0226     QTabWidget::mouseDoubleClickEvent(event);
0227 }
0228 
0229 void TabbedViewWidget::mouseReleaseEvent(QMouseEvent *event)
0230 {
0231     if (event->button() == Qt::MiddleButton) {
0232         if (isEmptyTabbarSpace(event->pos())) {
0233             Q_EMIT mouseMiddleClick(-1);
0234             return;
0235         }
0236         int pos = tabBar()->tabAt(event->pos());
0237         if (pos != -1) {
0238             Q_EMIT mouseMiddleClick(pos);
0239             return;
0240         }
0241     }
0242 
0243     QTabWidget::mouseReleaseEvent(event);
0244 }