File indexing completed on 2024-05-12 05:35:49

0001 /*
0002     SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic@kde.org>
0003     SPDX-FileCopyrightText: 2022 Méven Car <meven.car@kdenet.net>
0004 
0005     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 #include "kcm_recentFiles.h"
0008 #include "kactivitymanagerd_plugins_settings.h"
0009 #include "kactivitymanagerd_settings.h"
0010 #include "resourcescoring_interface.h"
0011 
0012 #include <QDBusConnection>
0013 #include <QDBusPendingCall>
0014 
0015 #include <QMenu>
0016 #include <QQmlComponent>
0017 #include <QQmlContext>
0018 #include <QQmlEngine>
0019 
0020 #include <QQuickWidget>
0021 
0022 #include <KConfigDialogManager>
0023 #include <KConfigGroup>
0024 #include <KMessageWidget>
0025 #include <KSharedConfig>
0026 
0027 #include "BlacklistedApplicationsModel.h"
0028 #include "ui_RecentFiles.h"
0029 
0030 #include <utils/d_ptr_implementation.h>
0031 
0032 #include "recentFiles-kcm-features.h"
0033 
0034 #include "common/dbus/common.h"
0035 #include "kactivitiesdata.h"
0036 #include "kcms-recentfiles-debug.h"
0037 
0038 K_PLUGIN_FACTORY_WITH_JSON(KActivityManagerKCMFactory, "kcm_recentFiles.json", registerPlugin<RecentFilesKcm>(); registerPlugin<KActivitiesData>();)
0039 
0040 class RecentFilesKcm::Private : public Ui::RecentFiles
0041 {
0042 public:
0043     KActivityManagerdSettings *mainConfig;
0044     KActivityManagerdPluginsSettings *pluginConfig;
0045 
0046     BlacklistedApplicationsModel *blacklistedApplicationsModel;
0047 
0048     explicit Private(QObject *parent)
0049         : mainConfig(new KActivityManagerdSettings(parent))
0050         , pluginConfig(new KActivityManagerdPluginsSettings(parent))
0051         , blacklistedApplicationsModel(new BlacklistedApplicationsModel(parent))
0052     {
0053     }
0054 
0055     void setDefaultIndicatorVisible(QWidget *widget, bool visible)
0056     {
0057         widget->setProperty("_kde_highlight_neutral", visible);
0058         widget->update();
0059     }
0060 
0061     void updateUiDefaultIndicator(bool visible)
0062     {
0063         setDefaultIndicatorVisible(radioDontRememberApplications, visible && radioDontRememberApplications->isChecked());
0064         setDefaultIndicatorVisible(radioRememberSpecificApplications, visible && radioRememberSpecificApplications->isChecked());
0065     }
0066 };
0067 
0068 RecentFilesKcm::RecentFilesKcm(QObject *parent, const KPluginMetaData &data)
0069     : KCModule(parent, data)
0070     , d(this)
0071 {
0072     d->setupUi(widget());
0073 
0074     // Keep history initialization
0075 
0076     d->kcfg_keepHistoryFor->setRange(0, INT_MAX);
0077     d->kcfg_keepHistoryFor->setSpecialValueText(i18nc("unlimited number of months", "Forever"));
0078 
0079     connect(d->kcfg_keepHistoryFor, SIGNAL(valueChanged(int)), this, SLOT(spinKeepHistoryValueChanged(int)));
0080     spinKeepHistoryValueChanged(0);
0081 
0082     // Clear recent history button
0083 
0084     auto menu = new QMenu(widget());
0085 
0086     connect(menu->addAction(i18n("Forget the last hour")), &QAction::triggered, this, &RecentFilesKcm::forgetLastHour);
0087     connect(menu->addAction(i18n("Forget the last two hours")), &QAction::triggered, this, &RecentFilesKcm::forgetTwoHours);
0088     connect(menu->addAction(i18n("Forget a day")), &QAction::triggered, this, &RecentFilesKcm::forgetDay);
0089     connect(menu->addAction(i18n("Forget everything")), &QAction::triggered, this, &RecentFilesKcm::forgetAll);
0090 
0091     d->buttonClearRecentHistory->setMenu(menu);
0092 
0093     // Blacklist applications
0094 
0095     d->blacklistedApplicationsModel = new BlacklistedApplicationsModel(this);
0096     connect(d->blacklistedApplicationsModel, &BlacklistedApplicationsModel::changed, this, &RecentFilesKcm::unmanagedWidgetChangeState);
0097     connect(d->blacklistedApplicationsModel, &BlacklistedApplicationsModel::defaulted, this, &RecentFilesKcm::unmanagedWidgetDefaultState);
0098 
0099     d->viewBlacklistedApplications->setClearColor(QGuiApplication::palette().window().color());
0100     d->viewBlacklistedApplications->rootContext()->setContextProperty(QStringLiteral("applicationModel"), d->blacklistedApplicationsModel);
0101     d->viewBlacklistedApplications->setSource(QUrl::fromLocalFile(KAMD_KCM_DATADIR + QStringLiteral("/qml/recentFiles/BlacklistApplicationView.qml")));
0102 
0103     // React to changes
0104 
0105     connect(d->radioRememberSpecificApplications, &QAbstractButton::toggled, d->blacklistedApplicationsModel, &BlacklistedApplicationsModel::setEnabled);
0106     connect(d->radioRememberSpecificApplications, &QAbstractButton::toggled, d->kcfg_blockedByDefault, &QCheckBox::setEnabled);
0107 
0108     // By default the KCModule (and eventually the kconfigdialogmanager) use
0109     // the index of checked radio button as the value of the setting. In this
0110     // case however we have a mismatch, the radio button "Do not remember"
0111     // (radioDontRememberApplications) has index 1 but in the WhatToRemember
0112     // enum has the value 2! So...
0113     // 1. Let kconfigwidgets know that this QGroupBox will be using a custom
0114     //    property to indicate the setting's value ("kcfg_value")
0115     d->kcfg_whatToRemember->setProperty("kcfg_property", QByteArray("kcfg_value"));
0116     // 2. Every time any radio button is clicked, we need to reset the
0117     //    kcfg_value and potentially set the dialog to "needs saving" state
0118     //    NOTE: Do not use "toggled" since it fires for two buttons each time!
0119     connect(d->radioRememberSpecificApplications, &QAbstractButton::clicked, this, &RecentFilesKcm::whatToRememberWidgetChanged);
0120     connect(d->radioRememberAllApplications, &QAbstractButton::clicked, this, &RecentFilesKcm::whatToRememberWidgetChanged);
0121     connect(d->radioDontRememberApplications, &QAbstractButton::clicked, this, &RecentFilesKcm::whatToRememberWidgetChanged);
0122 
0123     // Initial state
0124 
0125     d->blacklistedApplicationsModel->setEnabled(false);
0126     d->messageWidget->setVisible(false);
0127 
0128     connect(this, &RecentFilesKcm::defaultsIndicatorsVisibleChanged, this, [this]() {
0129         d->updateUiDefaultIndicator(defaultsIndicatorsVisible());
0130         for (KConfigDialogManager *config : configs()) {
0131             config->setDefaultsIndicatorsVisible(defaultsIndicatorsVisible());
0132         }
0133     });
0134 
0135     addConfig(d->pluginConfig, widget());
0136     addConfig(d->mainConfig, widget());
0137 }
0138 
0139 RecentFilesKcm::~RecentFilesKcm()
0140 {
0141 }
0142 
0143 void RecentFilesKcm::defaults()
0144 {
0145     d->blacklistedApplicationsModel->defaults();
0146     // Click and not setChecked to trigger whatToRememberWidgetChanged()
0147     d->radioRememberAllApplications->click();
0148 
0149     KCModule::defaults();
0150 }
0151 
0152 void RecentFilesKcm::load()
0153 {
0154     d->blacklistedApplicationsModel->load();
0155 
0156     KCModule::load();
0157 
0158     auto wtr = d->pluginConfig->whatToRemember();
0159     d->radioRememberSpecificApplications->setChecked(wtr == SpecificApplications);
0160     d->radioDontRememberApplications->setChecked(wtr == NoApplications);
0161     d->radioRememberAllApplications->setChecked(wtr == AllApplications);
0162 
0163     d->blacklistedApplicationsModel->setEnabled(d->radioRememberSpecificApplications->isChecked());
0164 
0165     d->updateUiDefaultIndicator(defaultsIndicatorsVisible());
0166 }
0167 
0168 void RecentFilesKcm::whatToRememberWidgetChanged(bool)
0169 {
0170     // See ctor for details: tl;dr: reset the what-to-rememeber value
0171     // and set the dialog to "changed" (if save is needed)
0172     // clang-format off
0173     const auto whatToRemember =
0174         d->radioRememberSpecificApplications->isChecked() ? SpecificApplications :
0175         d->radioDontRememberApplications->isChecked()     ? NoApplications :
0176         /* otherwise */                                     AllApplications;
0177     // clang-format on
0178     qCDebug(LOG_KCMS_RECENTFILES) << "whatToRememberWidgetChangeState: " << whatToRemember;
0179     d->kcfg_whatToRemember->setProperty("kcfg_value", whatToRemember);
0180     setNeedsSave(whatToRemember != d->pluginConfig->whatToRemember());
0181 
0182     d->updateUiDefaultIndicator(defaultsIndicatorsVisible());
0183 }
0184 
0185 void RecentFilesKcm::save()
0186 {
0187     d->blacklistedApplicationsModel->save();
0188     // clang-format off
0189     const auto whatToRemember =
0190         d->radioRememberSpecificApplications->isChecked() ? SpecificApplications :
0191         d->radioDontRememberApplications->isChecked()     ? NoApplications :
0192         /* otherwise */                                     AllApplications;
0193     // clang-format on
0194     d->mainConfig->setResourceScoringEnabled(whatToRemember != NoApplications);
0195     d->mainConfig->save();
0196 
0197     KCModule::save();
0198 }
0199 
0200 void RecentFilesKcm::forget(int count, const QString &what)
0201 {
0202     org::kde::ActivityManager::ResourcesScoring rankingsservice(QStringLiteral(KAMD_DBUS_SERVICE),
0203                                                                 QStringLiteral(KAMD_DBUS_RESOURCES_SCORING_PATH),
0204                                                                 QDBusConnection::sessionBus());
0205     rankingsservice.DeleteRecentStats(QString(), count, what);
0206 
0207     d->messageWidget->animatedShow();
0208 }
0209 
0210 void RecentFilesKcm::forgetLastHour()
0211 {
0212     forget(1, QStringLiteral("h"));
0213 }
0214 
0215 void RecentFilesKcm::forgetTwoHours()
0216 {
0217     forget(2, QStringLiteral("h"));
0218 }
0219 
0220 void RecentFilesKcm::forgetDay()
0221 {
0222     forget(1, QStringLiteral("d"));
0223 }
0224 
0225 void RecentFilesKcm::forgetAll()
0226 {
0227     forget(0, QStringLiteral("everything"));
0228 }
0229 
0230 void RecentFilesKcm::spinKeepHistoryValueChanged(int value)
0231 {
0232     static auto months = ki18ncp("unit of time. months to keep the history", " month", " months");
0233 
0234     if (value) {
0235         d->kcfg_keepHistoryFor->setPrefix(i18nc("for in 'keep history for 5 months'", "For "));
0236         d->kcfg_keepHistoryFor->setSuffix(months.subs(value).toString());
0237     }
0238 }
0239 
0240 #include "kcm_recentFiles.moc"