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"