File indexing completed on 2024-06-16 04:50:36

0001 /*
0002     SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "collectionpropertiesdialog.h"
0008 
0009 #include "cachepolicy.h"
0010 #include "cachepolicypage.h"
0011 #include "collection.h"
0012 #include "collectiongeneralpropertiespage_p.h"
0013 #include "collectionmodifyjob.h"
0014 
0015 #include "akonadiwidgets_debug.h"
0016 
0017 #include <KConfigGroup>
0018 #include <KSharedConfig>
0019 #include <QTabWidget>
0020 
0021 #include <QDialogButtonBox>
0022 
0023 using namespace Akonadi;
0024 
0025 /**
0026  * @internal
0027  */
0028 class Akonadi::CollectionPropertiesDialogPrivate
0029 {
0030 public:
0031     CollectionPropertiesDialogPrivate(CollectionPropertiesDialog *parent, const Akonadi::Collection &collection, const QStringList &pageNames);
0032 
0033     void init();
0034 
0035     static void registerBuiltinPages();
0036 
0037     void save()
0038     {
0039         const int numberOfTab(mTabWidget->count());
0040         for (int i = 0; i < numberOfTab; ++i) {
0041             auto page = static_cast<CollectionPropertiesPage *>(mTabWidget->widget(i));
0042             page->save(mCollection);
0043         }
0044 
0045         // We use WA_DeleteOnClose => Don't use dialog as parent otherwise we can't save modified collection.
0046         auto job = new CollectionModifyJob(mCollection);
0047         QObject::connect(job, &CollectionModifyJob::result, q, [this](KJob *job) {
0048             saveResult(job);
0049         });
0050         Q_EMIT q->settingsSaved();
0051     }
0052 
0053     void saveResult(KJob *job)
0054     {
0055         if (job->error()) {
0056             // TODO
0057             qCWarning(AKONADIWIDGETS_LOG) << job->errorString();
0058         }
0059     }
0060 
0061     void setCurrentPage(const QString &name)
0062     {
0063         const int numberOfTab(mTabWidget->count());
0064         for (int i = 0; i < numberOfTab; ++i) {
0065             QWidget *w = mTabWidget->widget(i);
0066             if (w->objectName() == name) {
0067                 mTabWidget->setCurrentIndex(i);
0068                 break;
0069             }
0070         }
0071     }
0072 
0073     CollectionPropertiesDialog *const q;
0074     Collection mCollection;
0075     QStringList mPageNames;
0076     QTabWidget *mTabWidget = nullptr;
0077 };
0078 
0079 class CollectionPropertiesPageFactoryList : public QList<CollectionPropertiesPageFactory *>
0080 {
0081 public:
0082     explicit CollectionPropertiesPageFactoryList() = default;
0083     CollectionPropertiesPageFactoryList(const CollectionPropertiesPageFactoryList &) = delete;
0084     CollectionPropertiesPageFactoryList &operator=(const CollectionPropertiesPageFactoryList &) = delete;
0085     ~CollectionPropertiesPageFactoryList()
0086     {
0087         qDeleteAll(*this);
0088     }
0089 };
0090 
0091 Q_GLOBAL_STATIC(CollectionPropertiesPageFactoryList, s_pages) // NOLINT(readability-redundant-member-init)
0092 
0093 static bool s_defaultPage = true;
0094 
0095 CollectionPropertiesDialogPrivate::CollectionPropertiesDialogPrivate(CollectionPropertiesDialog *qq,
0096                                                                      const Akonadi::Collection &collection,
0097                                                                      const QStringList &pageNames)
0098     : q(qq)
0099     , mCollection(collection)
0100     , mPageNames(pageNames)
0101 {
0102     if (s_defaultPage) {
0103         registerBuiltinPages();
0104     }
0105 }
0106 
0107 void CollectionPropertiesDialogPrivate::registerBuiltinPages()
0108 {
0109     static bool registered = false;
0110 
0111     if (registered) {
0112         return;
0113     }
0114 
0115     s_pages->append(new CollectionGeneralPropertiesPageFactory());
0116     s_pages->append(new CachePolicyPageFactory());
0117 
0118     registered = true;
0119 }
0120 
0121 void CollectionPropertiesDialogPrivate::init()
0122 {
0123     auto mainLayout = new QVBoxLayout(q);
0124     q->setAttribute(Qt::WA_DeleteOnClose);
0125     mTabWidget = new QTabWidget(q);
0126     mainLayout->addWidget(mTabWidget);
0127 
0128     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, q);
0129     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0130     okButton->setDefault(true);
0131     okButton->setShortcut(Qt::CTRL | Qt::Key_Return); // NOLINT(bugprone-suspicious-enum-usage)
0132     q->connect(buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept);
0133     q->connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
0134     mainLayout->addWidget(buttonBox);
0135 
0136     if (mPageNames.isEmpty()) { // default loading
0137         for (CollectionPropertiesPageFactory *factory : std::as_const(*s_pages)) {
0138             CollectionPropertiesPage *page = factory->createWidget(mTabWidget);
0139             if (page->canHandle(mCollection)) {
0140                 mTabWidget->addTab(page, page->pageTitle());
0141                 page->load(mCollection);
0142             } else {
0143                 delete page;
0144             }
0145         }
0146     } else { // custom loading
0147         QHash<QString, CollectionPropertiesPage *> pages;
0148 
0149         for (CollectionPropertiesPageFactory *factory : std::as_const(*s_pages)) {
0150             CollectionPropertiesPage *page = factory->createWidget(mTabWidget);
0151             const QString pageName = page->objectName();
0152 
0153             if (page->canHandle(mCollection) && mPageNames.contains(pageName) && !pages.contains(pageName)) {
0154                 pages.insert(page->objectName(), page);
0155             } else {
0156                 delete page;
0157             }
0158         }
0159 
0160         for (const QString &pageName : std::as_const(mPageNames)) {
0161             CollectionPropertiesPage *page = pages.value(pageName);
0162             if (page) {
0163                 mTabWidget->addTab(page, page->pageTitle());
0164                 page->load(mCollection);
0165             }
0166         }
0167     }
0168 
0169     q->connect(buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, q, [this]() {
0170         save();
0171     });
0172     q->connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, q, &QObject::deleteLater);
0173 
0174     KConfigGroup group(KSharedConfig::openStateConfig(), QStringLiteral("CollectionPropertiesDialog"));
0175     const QSize size = group.readEntry("Size", QSize());
0176     if (size.isValid()) {
0177         q->resize(size);
0178     } else {
0179         q->resize(q->sizeHint().width(), q->sizeHint().height());
0180     }
0181 }
0182 
0183 CollectionPropertiesDialog::CollectionPropertiesDialog(const Collection &collection, QWidget *parent)
0184     : QDialog(parent)
0185     , d(new CollectionPropertiesDialogPrivate(this, collection, QStringList()))
0186 {
0187     d->init();
0188 }
0189 
0190 CollectionPropertiesDialog::CollectionPropertiesDialog(const Collection &collection, const QStringList &pages, QWidget *parent)
0191     : QDialog(parent)
0192     , d(new CollectionPropertiesDialogPrivate(this, collection, pages))
0193 {
0194     d->init();
0195 }
0196 
0197 CollectionPropertiesDialog::~CollectionPropertiesDialog()
0198 {
0199     KConfigGroup group(KSharedConfig::openStateConfig(), QStringLiteral("CollectionPropertiesDialog"));
0200     group.writeEntry("Size", size());
0201 }
0202 
0203 void CollectionPropertiesDialog::registerPage(CollectionPropertiesPageFactory *factory)
0204 {
0205     if (s_pages->isEmpty() && s_defaultPage) {
0206         CollectionPropertiesDialogPrivate::registerBuiltinPages();
0207     }
0208     s_pages->append(factory);
0209 }
0210 
0211 void CollectionPropertiesDialog::useDefaultPage(bool defaultPage)
0212 {
0213     s_defaultPage = defaultPage;
0214 }
0215 
0216 QString CollectionPropertiesDialog::defaultPageObjectName(DefaultPage page)
0217 {
0218     switch (page) {
0219     case GeneralPage:
0220         return QStringLiteral("Akonadi::CollectionGeneralPropertiesPage");
0221     case CachePage:
0222         return QStringLiteral("Akonadi::CachePolicyPage");
0223     }
0224 
0225     return QString();
0226 }
0227 
0228 void CollectionPropertiesDialog::setCurrentPage(const QString &name)
0229 {
0230     d->setCurrentPage(name);
0231 }
0232 
0233 #include "moc_collectionpropertiesdialog.cpp"