Commit ee931882 authored by Méven Car's avatar Méven Car
Browse files

Add a Recent Files kcm to manage file history settings

BUG: 416271
parent a145c3de
......@@ -25,6 +25,7 @@ endif ()
add_subdirectory( desktoppaths )
add_subdirectory(activities)
add_subdirectory(recentFiles)
add_subdirectory(componentchooser)
add_subdirectory(kded)
add_subdirectory(runners)
......
/*
SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "BlacklistedApplicationsModel.h"
#include <QDebug>
#include <QList>
#include <QScopeGuard>
#include <QSet>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QVariant>
#include <KService>
#include "kactivitymanagerd_plugins_settings.h"
#include <utils/d_ptr_implementation.h>
#include "definitions.h"
class BlacklistedApplicationsModel::Private
{
public:
struct ApplicationData {
QString name;
QString title;
QString icon;
bool blocked;
};
QList<ApplicationData> applications;
KActivityManagerdPluginsSettings *pluginConfig;
bool enabled;
};
BlacklistedApplicationsModel::BlacklistedApplicationsModel(QObject *parent)
: QAbstractListModel(parent)
{
d->enabled = false;
d->pluginConfig = new KActivityManagerdPluginsSettings;
}
BlacklistedApplicationsModel::~BlacklistedApplicationsModel()
{
}
QHash<int, QByteArray> BlacklistedApplicationsModel::roleNames() const
{
return {{ApplicationIdRole, "name"}, {Qt::DecorationRole, "icon"}, {Qt::DisplayRole, "title"}, {BlockedApplicationRole, "blocked"}};
}
void BlacklistedApplicationsModel::load()
{
QSqlDatabase database;
const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kactivitymanagerd/resources/database");
database = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("plugins_sqlite_db_resources"));
database.setDatabaseName(path);
auto databaseRemove = qScopeGuard([&] {
QSqlDatabase::removeDatabase(database.connectionName());
});
// Loading plugin configuration
d->pluginConfig->load();
const auto defaultBlockedValue = d->pluginConfig->defaultBlockedByDefaultValue();
const auto &blockedAppList = d->pluginConfig->blockedApplications();
auto blockedApplications = QSet<QString>(blockedAppList.cbegin(), blockedAppList.cend());
const auto &allowedAppList = d->pluginConfig->allowedApplications();
auto allowedApplications = QSet<QString>(allowedAppList.cbegin(), allowedAppList.cend());
// Reading new applications from the database
if (!database.open()) {
// qDebug() << "Failed to open the database" << path << d->database.lastError();
return;
}
auto query = database.exec(QStringLiteral("SELECT DISTINCT(initiatingAgent) FROM ResourceScoreCache ORDER BY initiatingAgent"));
if (d->applications.length() > 0) {
beginRemoveRows(QModelIndex(), 0, d->applications.length() - 1);
d->applications.clear();
endRemoveRows();
}
while (query.next()) {
const auto name = query.value(0).toString();
if (defaultBlockedValue) {
if (!allowedApplications.contains(name)) {
blockedApplications << name;
}
} else {
if (!blockedApplications.contains(name)) {
allowedApplications << name;
}
}
}
QStringList applications = (blockedApplications + allowedApplications).values();
if (applications.length() > 0) {
std::sort(applications.begin(), applications.end());
beginInsertRows(QModelIndex(), 0, applications.length() - 1);
for (const auto &name : std::as_const(applications)) {
const auto service = KService::serviceByDesktopName(name);
const auto blocked = blockedApplications.contains(name);
if (service) {
d->applications << Private::ApplicationData{name, service->name(), service->icon(), blocked};
} else {
d->applications << Private::ApplicationData{name, name, QString(), blocked};
}
}
endInsertRows();
}
}
void BlacklistedApplicationsModel::save()
{
d->pluginConfig->save();
Q_EMIT changed(false);
}
void BlacklistedApplicationsModel::defaults()
{
for (int i = 0; i < rowCount(); i++) {
d->applications[i].blocked = false;
}
Q_EMIT dataChanged(QAbstractListModel::index(0), QAbstractListModel::index(rowCount() - 1));
Q_EMIT defaulted(true);
}
void BlacklistedApplicationsModel::toggleApplicationBlocked(int index)
{
if (index > rowCount()) {
return;
}
d->applications[index].blocked = !d->applications[index].blocked;
Q_EMIT dataChanged(QAbstractListModel::index(index), QAbstractListModel::index(index));
QStringList blockedApplications;
QStringList allowedApplications;
for (int i = 0; i < rowCount(); i++) {
const auto name = d->applications[i].name;
if (d->applications[i].blocked) {
blockedApplications << name;
} else {
allowedApplications << name;
}
}
d->pluginConfig->setBlockedApplications(blockedApplications);
d->pluginConfig->setAllowedApplications(allowedApplications);
const auto allowedApplicationsItem = d->pluginConfig->findItem("allowedApplications");
Q_ASSERT(allowedApplicationsItem);
const auto blockedApplicationsItem = d->pluginConfig->findItem("allowedApplications");
Q_ASSERT(blockedApplicationsItem);
Q_EMIT changed(blockedApplicationsItem->isSaveNeeded() && allowedApplicationsItem->isSaveNeeded());
Q_EMIT defaulted(blockedApplicationsItem->isDefault() && allowedApplicationsItem->isDefault());
}
QVariant BlacklistedApplicationsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_UNUSED(section)
Q_UNUSED(orientation)
Q_UNUSED(role)
return QVariant();
}
QVariant BlacklistedApplicationsModel::data(const QModelIndex &modelIndex, int role) const
{
const auto index = modelIndex.row();
if (index > rowCount()) {
return QVariant();
}
const auto &application = d->applications[index];
switch (role) {
default:
return QVariant();
case ApplicationIdRole:
return application.name;
case Qt::DisplayRole:
return application.title;
case Qt::DecorationRole:
return application.icon.isEmpty() ? QStringLiteral("application-x-executable") : application.icon;
case BlockedApplicationRole:
return application.blocked;
}
}
int BlacklistedApplicationsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return d->applications.size();
}
bool BlacklistedApplicationsModel::enabled() const
{
return d->enabled;
}
void BlacklistedApplicationsModel::setEnabled(bool enabled)
{
d->enabled = enabled;
Q_EMIT enabledChanged(enabled);
}
// #include <BlacklistedApplicationsModel.moc>
/*
SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef BLACKLISTED_APPLICATIONS_MODEL_H
#define BLACKLISTED_APPLICATIONS_MODEL_H
#include <QAbstractListModel>
#include <utils/d_ptr.h>
/**
* BlacklistedApplicationsModel
*/
class BlacklistedApplicationsModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
public:
explicit BlacklistedApplicationsModel(QObject *parent = nullptr);
~BlacklistedApplicationsModel() override;
enum Roles {
ApplicationIdRole = Qt::UserRole + 1,
BlockedApplicationRole,
};
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
Q_SIGNALS:
void changed(bool changed);
void defaulted(bool isDefault);
void enabledChanged(bool enabled);
public Q_SLOTS:
void toggleApplicationBlocked(int index);
void setEnabled(bool);
bool enabled() const;
void load();
void save();
void defaults();
private:
D_PTR;
};
#endif // BLACKLISTED_APPLICATIONS_MODEL_H
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
add_definitions(-DTRANSLATION_DOMAIN=\"kcm_recentFiles\")
find_package (Qt${QT_MAJOR_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Sql Qml DBus)
find_package (KF5KCMUtils ${KF5_DEP_VERSION} CONFIG REQUIRED)
find_package (KF5Declarative ${KF5_DEP_VERSION} CONFIG REQUIRED)
find_package (KF5XmlGui ${KF5_DEP_VERSION} CONFIG REQUIRED)
find_package (KF5GlobalAccel ${KF5_DEP_VERSION} CONFIG REQUIRED)
find_package (KF5Activities ${KF5_DEP_VERSION} CONFIG REQUIRED)
set (KAMD_KCM_DATADIR
${KDE_INSTALL_DATADIR_KF5}/kcm_recentFiles/workspace/settings/
)
if (NOT IS_ABSOLUTE "${KDE_INSTALL_DATADIR_KF5}")
set (KAMD_KCM_DATADIR "${CMAKE_INSTALL_PREFIX}/${KAMD_KCM_DATADIR}")
endif ()
configure_file (recentFiles-kcm-features.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/recentFiles-kcm-features.h)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set (KAMD_KCM_SRCS
kcm_recentFiles.cpp
BlacklistedApplicationsModel.cpp
)
ki18n_wrap_ui (
KAMD_KCM_SRCS
ui/RecentFiles.ui
)
qt_add_dbus_interface (
KAMD_KCM_SRCS
common/dbus/org.kde.ActivityManager.ResourceScoring.xml
resourcescoring_interface
)
kcmutils_generate_module_data(
KAMD_KCM_SRCS
MODULE_DATA_HEADER kactivitiesdata.h
MODULE_DATA_CLASS_NAME KActivitiesData
SETTINGS_HEADERS kactivitymanagerd_settings.h kactivitymanagerd_plugins_settings.h
SETTINGS_CLASSES KActivityManagerdSettings KActivityManagerdPluginsSettings
)
kconfig_add_kcfg_files(KAMD_KCM_SRCS kactivitymanagerd_settings.kcfgc GENERATE_MOC)
kconfig_add_kcfg_files(KAMD_KCM_SRCS kactivitymanagerd_plugins_settings.kcfgc GENERATE_MOC)
add_library (kcm_recentFiles MODULE ${KAMD_KCM_SRCS})
target_link_libraries (kcm_recentFiles
Qt::Quick
Qt::QuickWidgets
Qt::Core
Qt::Sql
Qt::Qml
Qt::DBus
KF5::KCMUtils
KF5::I18n
KF5::Service
KF5::Declarative
KF5::XmlGui
KF5::Activities
)
install (
TARGETS kcm_recentFiles
DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/kcms/systemsettings_qwidgets
)
install (
FILES kcm_recentFiles.desktop
DESTINATION ${KDE_INSTALL_APPDIR}
)
install (
DIRECTORY
qml/recentFiles
DESTINATION ${KAMD_KCM_DATADIR}/qml
)
install(FILES kactivitymanagerd_settings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
install(FILES kactivitymanagerd_plugins_settings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
#! /usr/bin/env bash
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
$XGETTEXT `find . -name \*.qml -o -name \*.h -o -name \*.js -o -name \*.cpp` -o $podir/kcm_recentFiles5.pot
rm -f rc.cpp
/*
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
// clang-format off
#ifndef DBUS_COMMON_H
#define DBUS_COMMON_H
#define KAMD_DBUS_SERVICE "org.kde.ActivityManager"
#define KAMD_DBUS_ACTIVITYMANAGER_PATH "/ActivityManager"
#define KAMD_DBUS_FEATURES_PATH KAMD_DBUS_ACTIVITYMANAGER_PATH"/Features"
#define KAMD_DBUS_RESOURCES_PATH KAMD_DBUS_ACTIVITYMANAGER_PATH"/Resources"
#define KAMD_DBUS_RESOURCES_SCORING_PATH KAMD_DBUS_RESOURCES_PATH"/Scoring"
#endif // DBUS_COMMON_H
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.ActivityManager.Features">
<method name="IsFeatureOperational">
<arg type="b" direction="out"/>
<arg name="feature" type="s" direction="in"/>
</method>
<method name="ListFeatures">
<arg type="as" direction="out"/>
<arg name="module" type="s" direction="in"/>
</method>
<method name="GetValue">
<arg type="v" direction="out"/>
<arg name="property" type="s" direction="in"/>
</method>
<method name="SetValue">
<arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method>
</interface>
</node>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.ActivityManager.ResourcesScoring">
<signal name="ResourceScoreUpdated">
<arg direction="out" type="s" name="activity"/>
<arg direction="out" type="s" name="client"/>
<arg direction="out" type="s" name="resource"/>
<arg direction="out" type="d" name="score"/>
<arg direction="out" type="u" name="lastUpdate"/>
<arg direction="out" type="u" name="firstUpdate"/>
</signal>
<signal name="ResourceScoreDeleted">
<arg direction="out" type="s" name="activity"/>
<arg direction="out" type="s" name="client"/>
<arg direction="out" type="s" name="resource"/>
</signal>
<signal name="RecentStatsDeleted">
<arg direction="out" type="s" name="activity"/>
<arg direction="out" type="i" name="count"/>
<arg direction="out" type="s" name="what"/>
</signal>
<signal name="EarlierStatsDeleted">
<arg direction="out" type="s" name="activity"/>
<arg direction="out" type="i" name="months"/>
</signal>
<method name="DeleteStatsForResource">
<arg direction="in" type="s" name="activity"/>
<arg direction="in" type="s" name="client"/>
<arg direction="in" type="s" name="resource"/>
</method>
<method name="DeleteRecentStats">
<arg direction="in" type="s" name="activity"/>
<arg direction="in" type="i" name="count"/>
<arg direction="in" type="s" name="what"/>
</method>
<method name="DeleteEarlierStats">
<arg direction="in" type="s" name="activity"/>
<arg direction="in" type="i" name="months"/>
</method>
</interface>
</node>
/*
SPDX-FileCopyrightText: 2015-2016 Ivan Cukic <ivan.cukic@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
#define SQLITE_PLUGIN_CONFIG_KEY "Plugin-org.kde.ActivityManager.Resources.Scoring"
#endif // DEFINITIONS_H
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="kactivitymanagerd-pluginsrc"/>
<group name="Plugin-org.kde.ActivityManager.Resources.Scoring">
<entry name="keepHistoryFor" key="keep-history-for" type="Int">
<label>How many months keep the activity history</label>
<default>0</default>
</entry>
<entry name="blockedByDefault" key="blocked-by-default" type="Bool">
<default>false</default>
</entry>
<entry name="whatToRemember" key="what-to-remember" type="Int">
<label>Which data to keep in activity history</label>
<default>0</default>
</entry>
<entry name="allowedApplications" key="allowed-applications" type="StringList">
<label>List of Applications whose activity history to save</label>
</entry>
<entry name="blockedApplications" key="blocked-applications" type="StringList">
<label>List of Applications whose activity history not to save</label>
</entry>
</group>
</kcfg>
File=kactivitymanagerd_plugins_settings.kcfg
ClassName=KActivityManagerdPluginsSettings
Mutators=true
DefaultValueGetters=true
ParentInConstructor=true
GlobalEnums=true
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="kactivitymanagerdrc"/>
<group name="Plugins">
<entry name="virtualDesktopSwitchEnabled" key="org.kde.ActivityManager.VirtualDesktopSwitchEnabled" type="Bool">
<default>false</default>
</entry>
<entry name="resourceScoringEnabled" key="org.kde.ActivityManager.ResourceScoringEnabled" type="Bool">
<default>true</default>
</entry>
</group>
</kcfg>
File=kactivitymanagerd_settings.kcfg
ClassName=KActivityManagerdSettings
Mutators=true
DefaultValueGetters=true
ParentInConstructor=true
/*
SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic@kde.org>
SPDX-FileCopyrightText: 2022 Méven Car <meven.car@kdenet.net>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "kcm_recentFiles.h"
#include "kactivitymanagerd_plugins_settings.h"
#include "kactivitymanagerd_settings.h"
#include "resourcescoring_interface.h"
#include <QDBusConnection>
#include <QDBusPendingCall>
#include <QMenu>
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickWidget>
#include <KConfigGroup>
#include <KMessageWidget>
#include <KSharedConfig>
#include "BlacklistedApplicationsModel.h"
#include "ui_RecentFiles.h"
#include <utils/d_ptr_implementation.h>
#include "recentFiles-kcm-features.h"
#include "common/dbus/common.h"
#include "kactivitiesdata.h"
K_PLUGIN_FACTORY_WITH_JSON(KActivityManagerKCMFactory, "kcm_recentFiles.json", registerPlugin<RecentFilesKcm>(); registerPlugin<KActivitiesData>();)
class RecentFilesKcm::Private : public Ui::RecentFiles
{
public:
KActivityManagerdSettings *mainConfig;
KActivityManagerdPluginsSettings *pluginConfig;
BlacklistedApplicationsModel *blacklistedApplicationsModel;