File indexing completed on 2025-04-27 04:37:43
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 }