File indexing completed on 2024-11-17 04:49:14

0001 /*
0002   This file is part of KOrganizer.
0003 
0004   SPDX-FileCopyrightText: 2000, 2001, 2002, 2003 Cornelius Schumacher <schumacher@kde.org>
0005   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
0006 
0007   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0008 */
0009 
0010 #include "koprefsdialogplugins.h"
0011 #include "kocore.h"
0012 #include "koprefs.h"
0013 #include <CalendarSupport/KCalPrefs>
0014 #include <KLocalizedString>
0015 #include <KMessageBox>
0016 #include <KPluginFactory>
0017 #include <QAction>
0018 #include <QGroupBox>
0019 #include <QHeaderView>
0020 #include <QLabel>
0021 #include <QRadioButton>
0022 #include <QToolButton>
0023 #include <QTreeWidget>
0024 #include <QVBoxLayout>
0025 
0026 class PluginItem : public QTreeWidgetItem
0027 {
0028 public:
0029     PluginItem(QTreeWidget *parent, const KPluginMetaData &service)
0030         : QTreeWidgetItem(parent, {service.name()})
0031         , mService(service)
0032     {
0033     }
0034 
0035     PluginItem(QTreeWidgetItem *parent, const KPluginMetaData &service)
0036         : QTreeWidgetItem(parent, {service.name()})
0037         , mService(service)
0038     {
0039     }
0040 
0041     KPluginMetaData service()
0042     {
0043         return mService;
0044     }
0045 
0046 private:
0047     const KPluginMetaData mService;
0048 };
0049 
0050 Q_DECLARE_METATYPE(PluginItem *)
0051 
0052 K_PLUGIN_CLASS_WITH_JSON(KOPrefsDialogPlugins, "korganizer_configplugins.json")
0053 
0054 /**
0055   Dialog for selecting and configuring KOrganizer plugins
0056 */
0057 KOPrefsDialogPlugins::KOPrefsDialogPlugins(QObject *parent, const KPluginMetaData &data)
0058     : KPrefsModule(KOPrefs::instance(), parent, data)
0059     , mTreeWidget(new QTreeWidget(widget()))
0060     , mDescription(new QLabel(widget()))
0061     , mPositioningGroupBox(new QGroupBox(i18nc("@title:group", "Position"), widget()))
0062 {
0063     auto topTopLayout = new QVBoxLayout(widget());
0064     topTopLayout->setContentsMargins({});
0065     topTopLayout->setSpacing(0);
0066     mTreeWidget->setColumnCount(2);
0067     mTreeWidget->setHeaderHidden(true);
0068     mTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
0069     mTreeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0070     mTreeWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
0071     mTreeWidget->header()->setStretchLastSection(false);
0072     topTopLayout->addWidget(mTreeWidget);
0073 
0074     mDescription->setAlignment(Qt::AlignVCenter);
0075     mDescription->setWordWrap(true);
0076     mDescription->setFrameShape(QLabel::Panel);
0077     mDescription->setFrameShadow(QLabel::Sunken);
0078     mDescription->setMinimumSize(QSize(0, 55));
0079     QSizePolicy policy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
0080     policy.setHorizontalStretch(0);
0081     policy.setVerticalStretch(0);
0082     policy.setHeightForWidth(mDescription->sizePolicy().hasHeightForWidth());
0083     mDescription->setSizePolicy(policy);
0084     topTopLayout->addWidget(mDescription);
0085 
0086     // mPositionMonthTop = new QCheckBox(
0087     // i18nc( "@option:check", "Show in the month view" ), mPositioningGroupBox );
0088     mPositionAgendaTop = new QRadioButton(i18nc("@option:check", "Show at the top of the agenda views"), mPositioningGroupBox);
0089     mPositionAgendaBottom = new QRadioButton(i18nc("@option:check", "Show at the bottom of the agenda views"), mPositioningGroupBox);
0090     auto positioningLayout = new QVBoxLayout(mPositioningGroupBox);
0091     // positioningLayout->addWidget( mPositionMonthTop );
0092     positioningLayout->addWidget(mPositionAgendaTop);
0093     positioningLayout->addWidget(mPositionAgendaBottom);
0094     positioningLayout->addStretch(1);
0095     topTopLayout->addWidget(mPositioningGroupBox);
0096 
0097     connect(mPositionAgendaTop, &QRadioButton::clicked, this, &KOPrefsDialogPlugins::positioningChanged);
0098     connect(mPositionAgendaBottom, &QRadioButton::clicked, this, &KOPrefsDialogPlugins::positioningChanged);
0099 
0100     connect(mTreeWidget, &QTreeWidget::itemSelectionChanged, this, &KOPrefsDialogPlugins::selectionChanged);
0101     connect(mTreeWidget, &QTreeWidget::itemChanged, this, &KOPrefsDialogPlugins::selectionChanged);
0102     connect(mTreeWidget, &QTreeWidget::itemClicked, this, &KOPrefsDialogPlugins::slotWidChanged);
0103 
0104     load();
0105 
0106     selectionChanged();
0107 }
0108 
0109 KOPrefsDialogPlugins::~KOPrefsDialogPlugins()
0110 {
0111     delete mDecorations;
0112 }
0113 
0114 void KOPrefsDialogPlugins::usrReadConfig()
0115 {
0116     mTreeWidget->clear();
0117     auto plugins = KOCore::self()->availableCalendarDecorations();
0118 
0119     EventViews::PrefsPtr viewPrefs = KOPrefs::instance()->eventViewsPreferences();
0120 
0121     QStringList selectedPlugins = viewPrefs->selectedPlugins();
0122 
0123     mDecorations = new QTreeWidgetItem(mTreeWidget, QStringList(i18nc("@title:group", "Calendar Decorations")));
0124 
0125     for (const KPluginMetaData &plugin : plugins) {
0126         PluginItem *item = new PluginItem(mDecorations, plugin);
0127 
0128         if (selectedPlugins.contains(plugin.pluginId())) {
0129             item->setCheckState(0, Qt::Checked);
0130         } else {
0131             item->setCheckState(0, Qt::Unchecked);
0132         }
0133         const QVariant variant = plugin.value(QStringLiteral("X-KDE-KOrganizer-HasSettings"), false);
0134         const bool hasSettings = (variant.isValid() && variant.toBool());
0135         if (hasSettings) {
0136             auto but = new QToolButton(mTreeWidget);
0137             auto act = new QAction(but);
0138             const QString decoration = plugin.pluginId();
0139             act->setData(QVariant::fromValue<PluginItem *>(item));
0140             but->setDefaultAction(act);
0141             but->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
0142             but->setFixedWidth(28);
0143             but->setToolTip(i18nc("@action", "Configure"));
0144             but->setAutoFillBackground(true);
0145             but->setEnabled(true);
0146             mTreeWidget->setItemWidget(item, 1, but);
0147             connect(but, &QToolButton::triggered, this, &KOPrefsDialogPlugins::configureClicked);
0148         }
0149     }
0150 
0151     mDecorations->setExpanded(true);
0152 
0153     const auto monthViewTop = KOPrefs::instance()->decorationsAtMonthViewTop();
0154     mDecorationsAtMonthViewTop = QSet<QString>(monthViewTop.begin(), monthViewTop.end());
0155     const auto agendaViewTop = viewPrefs->decorationsAtAgendaViewTop();
0156     mDecorationsAtAgendaViewTop = QSet<QString>(agendaViewTop.begin(), agendaViewTop.end());
0157     const auto agendaViewBottom = viewPrefs->decorationsAtAgendaViewBottom();
0158     mDecorationsAtAgendaViewBottom = QSet<QString>(agendaViewBottom.begin(), agendaViewBottom.end());
0159 }
0160 
0161 void KOPrefsDialogPlugins::usrWriteConfig()
0162 {
0163     QStringList selectedPlugins;
0164 
0165     for (int i = 0; i < mTreeWidget->topLevelItemCount(); ++i) {
0166         QTreeWidgetItem *serviceTypeGroup = mTreeWidget->topLevelItem(i);
0167         for (int j = 0; j < serviceTypeGroup->childCount(); ++j) {
0168             auto item = static_cast<PluginItem *>(serviceTypeGroup->child(j));
0169             if (item->checkState(0) == Qt::Checked) {
0170                 selectedPlugins.append(item->service().pluginId());
0171             }
0172         }
0173     }
0174     EventViews::PrefsPtr viewPrefs = KOPrefs::instance()->eventViewsPreferences();
0175     viewPrefs->setSelectedPlugins(selectedPlugins);
0176 
0177     KOPrefs::instance()->setDecorationsAtMonthViewTop(mDecorationsAtMonthViewTop.values());
0178     viewPrefs->setDecorationsAtAgendaViewTop(mDecorationsAtAgendaViewTop.values());
0179     viewPrefs->setDecorationsAtAgendaViewBottom(mDecorationsAtAgendaViewBottom.values());
0180 }
0181 
0182 void KOPrefsDialogPlugins::configureClicked(QAction *action)
0183 {
0184     if (!action) {
0185         return;
0186     }
0187 
0188     auto item = action->data().value<PluginItem *>();
0189 
0190     if (!item) {
0191         return;
0192     }
0193 
0194     EventViews::CalendarDecoration::Decoration *plugin = KOCore::self()->loadCalendarDecoration(item->service());
0195 
0196     if (plugin) {
0197         plugin->configure(widget());
0198         delete plugin;
0199 
0200         slotWidChanged();
0201     } else {
0202         KMessageBox::error(widget(), i18nc("@info", "Unable to configure this plugin"), QStringLiteral("PluginConfigUnable"));
0203     }
0204 }
0205 
0206 void KOPrefsDialogPlugins::positioningChanged()
0207 {
0208     if (mTreeWidget->selectedItems().count() != 1) {
0209         return;
0210     }
0211 
0212     PluginItem *item = dynamic_cast<PluginItem *>(mTreeWidget->selectedItems().last());
0213     if (!item) {
0214         return;
0215     }
0216 
0217     QString decoration = item->service().pluginId();
0218 
0219     /*if ( mPositionMonthTop->checkState() == Qt::Checked ) {
0220       if ( !mDecorationsAtMonthViewTop.contains( decoration ) ) {
0221         mDecorationsAtMonthViewTop.insert( decoration );
0222       }
0223     } else {
0224       mDecorationsAtMonthViewTop.remove( decoration );
0225     }*/
0226 
0227     if (mPositionAgendaTop->isChecked()) {
0228         if (!mDecorationsAtAgendaViewTop.contains(decoration)) {
0229             mDecorationsAtAgendaViewTop.insert(decoration);
0230         }
0231     } else {
0232         mDecorationsAtAgendaViewTop.remove(decoration);
0233     }
0234 
0235     if (mPositionAgendaBottom->isChecked()) {
0236         if (!mDecorationsAtAgendaViewBottom.contains(decoration)) {
0237             mDecorationsAtAgendaViewBottom.insert(decoration);
0238         }
0239     } else {
0240         mDecorationsAtAgendaViewBottom.remove(decoration);
0241     }
0242 
0243     slotWidChanged();
0244 }
0245 
0246 void KOPrefsDialogPlugins::selectionChanged()
0247 {
0248     mPositioningGroupBox->hide();
0249     // mPositionMonthTop->setChecked( false );
0250     mPositionAgendaTop->setChecked(false);
0251     mPositionAgendaBottom->setChecked(false);
0252 
0253     if (mTreeWidget->selectedItems().count() != 1) {
0254         mDescription->setText(QString());
0255         return;
0256     }
0257 
0258     PluginItem *item = dynamic_cast<PluginItem *>(mTreeWidget->selectedItems().last());
0259     if (!item) {
0260         mDescription->setText(QString());
0261         return;
0262     }
0263 
0264     mDescription->setText(item->service().description());
0265 
0266     bool hasPosition = false;
0267     QString decoration = item->service().pluginId();
0268     /*if ( mDecorationsAtMonthViewTop.contains( decoration ) ) {
0269       mPositionMonthTop->setChecked( true );
0270       hasPosition = true;
0271     }*/
0272     if (mDecorationsAtAgendaViewTop.contains(decoration)) {
0273         mPositionAgendaTop->setChecked(true);
0274         hasPosition = true;
0275     }
0276     if (mDecorationsAtAgendaViewBottom.contains(decoration)) {
0277         mPositionAgendaBottom->setChecked(true);
0278         hasPosition = true;
0279     }
0280 
0281     if (!hasPosition) {
0282         // no position has been selected, so default to Agenda Top
0283         mDecorationsAtAgendaViewTop << decoration;
0284         mPositionAgendaTop->setChecked(true);
0285     }
0286 
0287     mPositioningGroupBox->setEnabled(item->checkState(0) == Qt::Checked);
0288     mPositioningGroupBox->show();
0289 
0290     slotWidChanged();
0291 }
0292 
0293 #include "koprefsdialogplugins.moc"
0294 
0295 #include "moc_koprefsdialogplugins.cpp"