File indexing completed on 2024-04-28 03:59:11
0001 /* 0002 This file is part of the KDE Libraries 0003 SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kpagewidgetmodel.h" 0009 #include "kpagewidgetmodel_p.h" 0010 0011 #include "loggingcategory.h" 0012 0013 #include <QPointer> 0014 #include <QWidget> 0015 0016 #include <QIcon> 0017 0018 class KPageWidgetItemPrivate 0019 { 0020 public: 0021 KPageWidgetItemPrivate() 0022 : checkable(false) 0023 , checked(false) 0024 , enabled(true) 0025 , headerVisible(true) 0026 { 0027 } 0028 0029 ~KPageWidgetItemPrivate() 0030 { 0031 delete widget; 0032 widget = nullptr; 0033 } 0034 0035 QString name; 0036 QString header; 0037 QIcon icon; 0038 QPointer<QWidget> widget; 0039 bool checkable : 1; 0040 bool checked : 1; 0041 bool enabled : 1; 0042 bool headerVisible : 1; 0043 }; 0044 0045 KPageWidgetItem::KPageWidgetItem(QWidget *widget) 0046 : QObject(nullptr) 0047 , d(new KPageWidgetItemPrivate) 0048 { 0049 d->widget = widget; 0050 0051 // Hide the widget, otherwise when the widget has this KPageView as 0052 // parent the widget is shown outside the QStackedWidget if the page 0053 // was not selected ( and reparented ) yet. 0054 if (d->widget) { 0055 d->widget->hide(); 0056 } 0057 } 0058 0059 KPageWidgetItem::KPageWidgetItem(QWidget *widget, const QString &name) 0060 : QObject(nullptr) 0061 , d(new KPageWidgetItemPrivate) 0062 { 0063 d->widget = widget; 0064 d->name = name; 0065 0066 // Hide the widget, otherwise when the widget has this KPageView as 0067 // parent the widget is shown outside the QStackedWidget if the page 0068 // was not selected ( and reparented ) yet. 0069 if (d->widget) { 0070 d->widget->hide(); 0071 } 0072 } 0073 0074 KPageWidgetItem::~KPageWidgetItem() = default; 0075 0076 void KPageWidgetItem::setEnabled(bool enabled) 0077 { 0078 d->enabled = enabled; 0079 if (d->widget) { 0080 d->widget->setEnabled(enabled); 0081 } 0082 Q_EMIT changed(); 0083 } 0084 0085 bool KPageWidgetItem::isEnabled() const 0086 { 0087 return d->enabled; 0088 } 0089 0090 bool KPageWidgetItem::isHeaderVisible() const 0091 { 0092 return d->headerVisible; 0093 } 0094 0095 void KPageWidgetItem::setHeaderVisible(bool visible) 0096 { 0097 d->headerVisible = visible; 0098 0099 Q_EMIT changed(); 0100 } 0101 0102 QWidget *KPageWidgetItem::widget() const 0103 { 0104 return d->widget; 0105 } 0106 0107 void KPageWidgetItem::setName(const QString &name) 0108 { 0109 d->name = name; 0110 0111 Q_EMIT changed(); 0112 } 0113 0114 QString KPageWidgetItem::name() const 0115 { 0116 return d->name; 0117 } 0118 0119 void KPageWidgetItem::setHeader(const QString &header) 0120 { 0121 d->header = header; 0122 0123 Q_EMIT changed(); 0124 } 0125 0126 QString KPageWidgetItem::header() const 0127 { 0128 return d->header; 0129 } 0130 0131 void KPageWidgetItem::setIcon(const QIcon &icon) 0132 { 0133 d->icon = icon; 0134 0135 Q_EMIT changed(); 0136 } 0137 0138 QIcon KPageWidgetItem::icon() const 0139 { 0140 return d->icon; 0141 } 0142 0143 void KPageWidgetItem::setCheckable(bool checkable) 0144 { 0145 d->checkable = checkable; 0146 0147 Q_EMIT changed(); 0148 } 0149 0150 bool KPageWidgetItem::isCheckable() const 0151 { 0152 return d->checkable; 0153 } 0154 0155 void KPageWidgetItem::setChecked(bool checked) 0156 { 0157 d->checked = checked; 0158 0159 Q_EMIT toggled(checked); 0160 Q_EMIT changed(); 0161 } 0162 0163 bool KPageWidgetItem::isChecked() const 0164 { 0165 return d->checked; 0166 } 0167 0168 PageItem::PageItem(KPageWidgetItem *pageWidgetItem, PageItem *parent) 0169 : mPageWidgetItem(pageWidgetItem) 0170 , mParentItem(parent) 0171 { 0172 } 0173 0174 PageItem::~PageItem() 0175 { 0176 delete mPageWidgetItem; 0177 mPageWidgetItem = nullptr; 0178 0179 qDeleteAll(mChildItems); 0180 } 0181 0182 void PageItem::appendChild(PageItem *item) 0183 { 0184 mChildItems.append(item); 0185 } 0186 0187 void PageItem::insertChild(int row, PageItem *item) 0188 { 0189 mChildItems.insert(row, item); 0190 } 0191 0192 void PageItem::removeChild(int row) 0193 { 0194 mChildItems.removeAt(row); 0195 } 0196 0197 PageItem *PageItem::child(int row) 0198 { 0199 return mChildItems.value(row); 0200 } 0201 0202 int PageItem::childCount() const 0203 { 0204 return mChildItems.count(); 0205 } 0206 0207 int PageItem::columnCount() const 0208 { 0209 return 1; 0210 } 0211 0212 PageItem *PageItem::parent() 0213 { 0214 return mParentItem; 0215 } 0216 0217 int PageItem::row() const 0218 { 0219 if (mParentItem) { 0220 return mParentItem->mChildItems.indexOf(const_cast<PageItem *>(this)); 0221 } 0222 0223 return 0; 0224 } 0225 0226 KPageWidgetItem *PageItem::pageWidgetItem() const 0227 { 0228 return mPageWidgetItem; 0229 } 0230 0231 PageItem *PageItem::findChild(const KPageWidgetItem *item) 0232 { 0233 if (mPageWidgetItem == item) { 0234 return this; 0235 } 0236 0237 for (int i = 0; i < mChildItems.count(); ++i) { 0238 PageItem *pageItem = mChildItems[i]->findChild(item); 0239 if (pageItem) { 0240 return pageItem; 0241 } 0242 } 0243 0244 return nullptr; 0245 } 0246 0247 void PageItem::dump(int indent) 0248 { 0249 const QString indentation(indent, QLatin1Char(' ')); 0250 0251 const QString name = (mPageWidgetItem ? mPageWidgetItem->name() : QStringLiteral("root")); 0252 qCDebug(KWidgetsAddonsLog, "%s (%p)", qPrintable(QString(indentation + name)), (void *)this); 0253 for (int i = 0; i < mChildItems.count(); ++i) { 0254 mChildItems[i]->dump(indent + 2); 0255 } 0256 } 0257 0258 KPageWidgetModel::KPageWidgetModel(QObject *parent) 0259 : KPageModel(*new KPageWidgetModelPrivate, parent) 0260 { 0261 } 0262 0263 KPageWidgetModel::~KPageWidgetModel() 0264 { 0265 } 0266 0267 int KPageWidgetModel::columnCount(const QModelIndex &) const 0268 { 0269 return 1; 0270 } 0271 0272 QVariant KPageWidgetModel::data(const QModelIndex &index, int role) const 0273 { 0274 if (!index.isValid()) { 0275 return QVariant(); 0276 } 0277 0278 PageItem *item = static_cast<PageItem *>(index.internalPointer()); 0279 0280 if (role == Qt::DisplayRole) { 0281 return QVariant(item->pageWidgetItem()->name()); 0282 } else if (role == Qt::DecorationRole) { 0283 return QVariant(item->pageWidgetItem()->icon()); 0284 } else if (role == HeaderRole) { 0285 return QVariant(item->pageWidgetItem()->header()); 0286 } else if (role == HeaderVisibleRole) { 0287 return item->pageWidgetItem()->isHeaderVisible(); 0288 } else if (role == WidgetRole) { 0289 return QVariant::fromValue(item->pageWidgetItem()->widget()); 0290 } else if (role == Qt::CheckStateRole) { 0291 if (item->pageWidgetItem()->isCheckable()) { 0292 return (item->pageWidgetItem()->isChecked() ? Qt::Checked : Qt::Unchecked); 0293 } else { 0294 return QVariant(); 0295 } 0296 } else { 0297 return QVariant(); 0298 } 0299 } 0300 0301 bool KPageWidgetModel::setData(const QModelIndex &index, const QVariant &value, int role) 0302 { 0303 if (!index.isValid()) { 0304 return false; 0305 } 0306 0307 if (role != Qt::CheckStateRole) { 0308 return false; 0309 } 0310 0311 PageItem *item = static_cast<PageItem *>(index.internalPointer()); 0312 if (!item) { 0313 return false; 0314 } 0315 0316 if (!item->pageWidgetItem()->isCheckable()) { 0317 return false; 0318 } 0319 0320 if (value.toInt() == Qt::Checked) { 0321 item->pageWidgetItem()->setChecked(true); 0322 } else { 0323 item->pageWidgetItem()->setChecked(false); 0324 } 0325 0326 return true; 0327 } 0328 0329 Qt::ItemFlags KPageWidgetModel::flags(const QModelIndex &index) const 0330 { 0331 if (!index.isValid()) { 0332 return Qt::NoItemFlags; 0333 } 0334 0335 Qt::ItemFlags flags = Qt::ItemIsSelectable; 0336 0337 PageItem *item = static_cast<PageItem *>(index.internalPointer()); 0338 if (item->pageWidgetItem()->isCheckable()) { 0339 flags |= Qt::ItemIsUserCheckable; 0340 } 0341 if (item->pageWidgetItem()->isEnabled()) { 0342 flags |= Qt::ItemIsEnabled; 0343 } 0344 0345 return flags; 0346 } 0347 0348 QModelIndex KPageWidgetModel::index(int row, int column, const QModelIndex &parent) const 0349 { 0350 Q_D(const KPageWidgetModel); 0351 0352 PageItem *parentItem; 0353 0354 if (parent.isValid()) { 0355 parentItem = static_cast<PageItem *>(parent.internalPointer()); 0356 } else { 0357 parentItem = d->rootItem; 0358 } 0359 0360 PageItem *childItem = parentItem->child(row); 0361 if (childItem) { 0362 return createIndex(row, column, childItem); 0363 } else { 0364 return QModelIndex(); 0365 } 0366 } 0367 0368 QModelIndex KPageWidgetModel::parent(const QModelIndex &index) const 0369 { 0370 Q_D(const KPageWidgetModel); 0371 0372 if (!index.isValid()) { 0373 return QModelIndex(); 0374 } 0375 0376 PageItem *item = static_cast<PageItem *>(index.internalPointer()); 0377 PageItem *parentItem = item->parent(); 0378 0379 if (parentItem == d->rootItem) { 0380 return QModelIndex(); 0381 } else { 0382 return createIndex(parentItem->row(), 0, parentItem); 0383 } 0384 } 0385 0386 int KPageWidgetModel::rowCount(const QModelIndex &parent) const 0387 { 0388 Q_D(const KPageWidgetModel); 0389 0390 PageItem *parentItem; 0391 0392 if (!parent.isValid()) { 0393 parentItem = d->rootItem; 0394 } else { 0395 parentItem = static_cast<PageItem *>(parent.internalPointer()); 0396 } 0397 0398 return parentItem->childCount(); 0399 } 0400 0401 KPageWidgetItem *KPageWidgetModel::addPage(QWidget *widget, const QString &name) 0402 { 0403 KPageWidgetItem *item = new KPageWidgetItem(widget, name); 0404 0405 addPage(item); 0406 0407 return item; 0408 } 0409 0410 void KPageWidgetModel::addPage(KPageWidgetItem *item) 0411 { 0412 Q_EMIT layoutAboutToBeChanged(); 0413 0414 Q_D(KPageWidgetModel); 0415 connect(item, SIGNAL(changed()), this, SLOT(_k_itemChanged())); 0416 connect(item, SIGNAL(toggled(bool)), this, SLOT(_k_itemToggled(bool))); 0417 0418 // The row to be inserted 0419 int row = d->rootItem->childCount(); 0420 0421 beginInsertRows(QModelIndex(), row, row); 0422 0423 PageItem *pageItem = new PageItem(item, d->rootItem); 0424 d->rootItem->appendChild(pageItem); 0425 0426 endInsertRows(); 0427 0428 Q_EMIT layoutChanged(); 0429 } 0430 0431 KPageWidgetItem *KPageWidgetModel::insertPage(KPageWidgetItem *before, QWidget *widget, const QString &name) 0432 { 0433 KPageWidgetItem *item = new KPageWidgetItem(widget, name); 0434 0435 insertPage(before, item); 0436 0437 return item; 0438 } 0439 0440 void KPageWidgetModel::insertPage(KPageWidgetItem *before, KPageWidgetItem *item) 0441 { 0442 Q_D(KPageWidgetModel); 0443 0444 PageItem *beforePageItem = d->rootItem->findChild(before); 0445 if (!beforePageItem) { 0446 qCDebug(KWidgetsAddonsLog, "Invalid KPageWidgetItem passed!"); 0447 return; 0448 } 0449 0450 Q_EMIT layoutAboutToBeChanged(); 0451 0452 connect(item, SIGNAL(changed()), this, SLOT(_k_itemChanged())); 0453 connect(item, SIGNAL(toggled(bool)), this, SLOT(_k_itemToggled(bool))); 0454 0455 PageItem *parent = beforePageItem->parent(); 0456 // The row to be inserted 0457 int row = beforePageItem->row(); 0458 0459 QModelIndex index; 0460 if (parent != d->rootItem) { 0461 index = createIndex(parent->row(), 0, parent); 0462 } 0463 0464 beginInsertRows(index, row, row); 0465 0466 PageItem *newPageItem = new PageItem(item, parent); 0467 parent->insertChild(row, newPageItem); 0468 0469 endInsertRows(); 0470 0471 Q_EMIT layoutChanged(); 0472 } 0473 0474 KPageWidgetItem *KPageWidgetModel::addSubPage(KPageWidgetItem *parent, QWidget *widget, const QString &name) 0475 { 0476 KPageWidgetItem *item = new KPageWidgetItem(widget, name); 0477 0478 addSubPage(parent, item); 0479 0480 return item; 0481 } 0482 0483 void KPageWidgetModel::addSubPage(KPageWidgetItem *parent, KPageWidgetItem *item) 0484 { 0485 Q_D(KPageWidgetModel); 0486 0487 PageItem *parentPageItem = d->rootItem->findChild(parent); 0488 if (!parentPageItem) { 0489 qCDebug(KWidgetsAddonsLog, "Invalid KPageWidgetItem passed!"); 0490 return; 0491 } 0492 0493 Q_EMIT layoutAboutToBeChanged(); 0494 0495 connect(item, SIGNAL(changed()), this, SLOT(_k_itemChanged())); 0496 connect(item, SIGNAL(toggled(bool)), this, SLOT(_k_itemToggled(bool))); 0497 0498 // The row to be inserted 0499 int row = parentPageItem->childCount(); 0500 0501 QModelIndex index; 0502 if (parentPageItem != d->rootItem) { 0503 index = createIndex(parentPageItem->row(), 0, parentPageItem); 0504 } 0505 0506 beginInsertRows(index, row, row); 0507 0508 PageItem *newPageItem = new PageItem(item, parentPageItem); 0509 parentPageItem->appendChild(newPageItem); 0510 0511 endInsertRows(); 0512 0513 Q_EMIT layoutChanged(); 0514 } 0515 0516 void KPageWidgetModel::removePage(KPageWidgetItem *item) 0517 { 0518 if (!item) { 0519 return; 0520 } 0521 0522 Q_D(KPageWidgetModel); 0523 0524 PageItem *pageItem = d->rootItem->findChild(item); 0525 if (!pageItem) { 0526 qCDebug(KWidgetsAddonsLog, "Invalid KPageWidgetItem passed!"); 0527 return; 0528 } 0529 0530 Q_EMIT layoutAboutToBeChanged(); 0531 0532 disconnect(item, SIGNAL(changed()), this, SLOT(_k_itemChanged())); 0533 disconnect(item, SIGNAL(toggled(bool)), this, SLOT(_k_itemToggled(bool))); 0534 0535 PageItem *parentPageItem = pageItem->parent(); 0536 int row = parentPageItem->row(); 0537 0538 QModelIndex index; 0539 if (parentPageItem != d->rootItem) { 0540 index = createIndex(row, 0, parentPageItem); 0541 } 0542 0543 beginRemoveRows(index, pageItem->row(), pageItem->row()); 0544 0545 parentPageItem->removeChild(pageItem->row()); 0546 delete pageItem; 0547 0548 endRemoveRows(); 0549 0550 Q_EMIT layoutChanged(); 0551 } 0552 0553 KPageWidgetItem *KPageWidgetModel::item(const QModelIndex &index) const 0554 { 0555 if (!index.isValid()) { 0556 return nullptr; 0557 } 0558 0559 PageItem *item = static_cast<PageItem *>(index.internalPointer()); 0560 if (!item) { 0561 return nullptr; 0562 } 0563 0564 return item->pageWidgetItem(); 0565 } 0566 0567 QModelIndex KPageWidgetModel::index(const KPageWidgetItem *item) const 0568 { 0569 Q_D(const KPageWidgetModel); 0570 0571 if (!item) { 0572 return QModelIndex(); 0573 } 0574 0575 const PageItem *pageItem = d->rootItem->findChild(item); 0576 if (!pageItem) { 0577 return QModelIndex(); 0578 } 0579 0580 return createIndex(pageItem->row(), 0, (void *)pageItem); 0581 } 0582 0583 #include "moc_kpagewidgetmodel.cpp"