File indexing completed on 2024-04-28 08:51:04

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), m_tabWidget(modelTarget)
0015 {
0016 }
0017 
0018 QModelIndex TabbedViewWidgetModel::index(int row, int column, const QModelIndex &parent) const
0019 {
0020     if (!hasIndex(row, column, parent)) {
0021         return QModelIndex();
0022     }
0023     return createIndex(row, column, m_tabWidget->widget(row));
0024 }
0025 
0026 QModelIndex TabbedViewWidgetModel::parent(const QModelIndex &) const
0027 {
0028     return QModelIndex();
0029 }
0030 
0031 int TabbedViewWidgetModel::columnCount(const QModelIndex &) const
0032 {
0033     return 1;
0034 }
0035 
0036 int TabbedViewWidgetModel::rowCount(const QModelIndex &) const
0037 {
0038     return m_tabWidget->count();
0039 }
0040 
0041 Qt::ItemFlags TabbedViewWidgetModel::flags(const QModelIndex &index) const
0042 {
0043     if (!index.isValid()) {
0044         return Qt::ItemIsEnabled;
0045     }
0046     return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
0047 }
0048 
0049 bool TabbedViewWidgetModel::setData(const QModelIndex &index, const QVariant &value, int role)
0050 {
0051     if (index.isValid() && role == Qt::EditRole) {
0052         m_tabWidget->setTabText(index.row(), value.toString());
0053         Q_EMIT dataChanged(index, index);
0054         return true;
0055     }
0056     return false;
0057 }
0058 
0059 QVariant TabbedViewWidgetModel::data(const QModelIndex &index, int role) const
0060 {
0061     if (!index.isValid()) {
0062         return QVariant();
0063     }
0064 
0065     switch (role) {
0066     case Qt::EditRole:
0067     case Qt::DisplayRole: {
0068         static QRegularExpression reg(QStringLiteral("&(?!&)"));
0069         return m_tabWidget->tabText(index.row()).remove(reg); //remove accelerator string
0070     }
0071     case Qt::ToolTipRole:
0072         return m_tabWidget->tabToolTip(index.row());
0073     case Qt::DecorationRole:
0074         return m_tabWidget->tabIcon(index.row());
0075     default:
0076         return QVariant();
0077     }
0078 }
0079 
0080 void TabbedViewWidgetModel::emitLayoutAboutToBeChanged()
0081 {
0082     Q_EMIT layoutAboutToBeChanged();
0083 }
0084 
0085 void TabbedViewWidgetModel::emitLayoutChanged()
0086 {
0087     Q_EMIT layoutChanged();
0088 }
0089 
0090 void TabbedViewWidgetModel::emitDataChanged(int index)
0091 {
0092     QModelIndex modelIndex = createIndex(index, 1);
0093     Q_EMIT dataChanged(modelIndex, modelIndex);
0094 }
0095 
0096 TabbedViewWidget::TabbedViewWidget(QWidget *parent)
0097         : QTabWidget(parent), m_model(new TabbedViewWidgetModel(this))
0098 {
0099 }
0100 
0101 TabbedViewWidget::~TabbedViewWidget()
0102 {
0103 }
0104 
0105 TabbedViewWidgetModel* TabbedViewWidget::getModel()
0106 {
0107     return m_model;
0108 }
0109 
0110 int TabbedViewWidget::addTab(QWidget *page, const QString &label)
0111 {
0112     int count = QTabWidget::count();
0113     m_model->beginInsertRows(QModelIndex(), count, count);
0114     int ret = QTabWidget::addTab(page, label);
0115     m_model->endInsertRows();
0116     return ret;
0117 }
0118 
0119 int TabbedViewWidget::addTab(QWidget *page, const QIcon &icon, const QString &label)
0120 {
0121     int count = QTabWidget::count();
0122     m_model->beginInsertRows(QModelIndex(), count, count);
0123     int ret = QTabWidget::addTab(page, icon, label);
0124     m_model->endInsertRows();
0125     return ret;
0126 }
0127 
0128 int TabbedViewWidget::insertTab(int index, QWidget *page, const QString &label)
0129 {
0130     m_model->beginInsertRows(QModelIndex(), index, index);
0131     int ret = QTabWidget::insertTab(index, page, label);
0132     m_model->endInsertRows();
0133     return ret;
0134 }
0135 
0136 int TabbedViewWidget::insertTab(int index, QWidget *page, const QIcon &icon, const QString &label)
0137 {
0138     m_model->beginInsertRows(QModelIndex(), index, index);
0139     int ret = QTabWidget::insertTab(index, page, icon, label);
0140     m_model->endInsertRows();
0141     return ret;
0142 }
0143 
0144 void TabbedViewWidget::removePage(QWidget *page)
0145 {
0146     int index = QTabWidget::indexOf(page);
0147     if (index == -1) {
0148         return;
0149     }
0150     m_model->beginRemoveRows(QModelIndex(), index, index);
0151     QTabWidget::removeTab(index);
0152     m_model->endRemoveRows();
0153 }
0154 
0155 void TabbedViewWidget::removeTab(int index)
0156 {
0157     m_model->beginRemoveRows(QModelIndex(), index, index);
0158     QTabWidget::removeTab(index);
0159     m_model->endRemoveRows();
0160 }
0161 
0162 void TabbedViewWidget::moveTab(int from, int to)
0163 {
0164     m_model->emitLayoutAboutToBeChanged();
0165     tabBar()->moveTab(from, to);
0166     m_model->emitLayoutChanged();
0167 }
0168 
0169 void TabbedViewWidget::setTabText(int index, const QString &label)
0170 {
0171     QTabWidget::setTabText(index, label);
0172     m_model->emitDataChanged(index);
0173 }
0174 
0175 //This functionality is taken from  KTabWidget for compatibility.
0176 //KTabWidget has been moved to KdeLibs4Support and QTabWidget::tabBarDoubleClicked does not
0177 //work on empty space after tabs,
0178 bool TabbedViewWidget::isEmptyTabbarSpace(const QPoint &point) const
0179 {
0180     if (count() == 0) {
0181         return true;
0182     }
0183     if (tabBar()->isHidden()) {
0184         return false;
0185     }
0186     QSize size(tabBar()->sizeHint());
0187     if ((tabPosition() == QTabWidget::North && point.y() < size.height()) ||
0188             (tabPosition() == QTabWidget::South && point.y() > (height() - size.height()))) {
0189 
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 }
0245