diff --git a/kcms/CMakeLists.txt b/kcms/CMakeLists.txt --- a/kcms/CMakeLists.txt +++ b/kcms/CMakeLists.txt @@ -36,6 +36,7 @@ add_subdirectory( hardware ) add_subdirectory( desktoppaths ) +add_subdirectory(activities) add_subdirectory(componentchooser) add_subdirectory(emoticons) add_subdirectory(icons) diff --git a/kcms/activities/ActivitiesTab.h b/kcms/activities/ActivitiesTab.h new file mode 100644 --- /dev/null +++ b/kcms/activities/ActivitiesTab.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ACTIVITIES_TAB_H +#define ACTIVITIES_TAB_H + +#include + +#include + +/** + * ActivitiesTab + */ +class ActivitiesTab : public QWidget { + Q_OBJECT +public: + ActivitiesTab(QWidget *parent); + ~ActivitiesTab(); + +public Q_SLOTS: + void defaults(); + void load(); + void save(); + +Q_SIGNALS: + void changed(); + +private: + D_PTR; +}; + +#endif // ACTIVITIES_TAB_H diff --git a/kcms/activities/ActivitiesTab.cpp b/kcms/activities/ActivitiesTab.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/ActivitiesTab.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ActivitiesTab.h" + +#include +#include +#include + +#include +#include +#include + +#include "ExtraActivitiesInterface.h" +#include "definitions.h" + +#include + +#include "kactivities-kcm-features.h" + +#include "utils.h" + +class ActivitiesTab::Private { +public: + std::unique_ptr viewActivities; + ExtraActivitiesInterface *extraActivitiesInterface; +}; + +ActivitiesTab::ActivitiesTab(QWidget *parent) + : QWidget(parent) + , d() +{ + new QVBoxLayout(this); + + d->extraActivitiesInterface = new ExtraActivitiesInterface(this); + + d->viewActivities = createView(this); + d->viewActivities->rootContext()->setContextProperty( + "kactivitiesExtras", d->extraActivitiesInterface); + setViewSource(d->viewActivities, "/qml/activitiesTab/main.qml"); +} + +ActivitiesTab::~ActivitiesTab() +{ +} + +void ActivitiesTab::defaults() +{ +} + +void ActivitiesTab::load() +{ +} + +void ActivitiesTab::save() +{ +} + +#include "ActivitiesTab.moc" diff --git a/kcms/activities/BlacklistedApplicationsModel.h b/kcms/activities/BlacklistedApplicationsModel.h new file mode 100644 --- /dev/null +++ b/kcms/activities/BlacklistedApplicationsModel.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLACKLISTED_APPLICATIONS_MODEL_H +#define BLACKLISTED_APPLICATIONS_MODEL_H + +#include + +#include + +/** + * BlacklistedApplicationsModel + */ +class BlacklistedApplicationsModel : public QAbstractListModel { + Q_OBJECT + + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + +public: + BlacklistedApplicationsModel(QObject *parent = Q_NULLPTR); + ~BlacklistedApplicationsModel(); + + enum Roles { + ApplicationIdRole = Qt::UserRole + 1, + BlockedApplicationRole + }; + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + + QHash roleNames() const Q_DECL_OVERRIDE; + +Q_SIGNALS: + void changed(); + 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 diff --git a/kcms/activities/BlacklistedApplicationsModel.cpp b/kcms/activities/BlacklistedApplicationsModel.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/BlacklistedApplicationsModel.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "BlacklistedApplicationsModel.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "definitions.h" + +class BlacklistedApplicationsModel::Private { +public: + struct ApplicationData { + QString name; + QString title; + QString icon; + bool blocked; + }; + + QList applications; + QSqlDatabase database; + + KSharedConfig::Ptr pluginConfig; + bool enabled; +}; + +BlacklistedApplicationsModel::BlacklistedApplicationsModel(QObject *parent) + : QAbstractListModel(parent) +{ + d->enabled = false; + d->pluginConfig = KSharedConfig::openConfig("kactivitymanagerd-pluginsrc"); +} + +BlacklistedApplicationsModel::~BlacklistedApplicationsModel() +{ +} + +QHash BlacklistedApplicationsModel::roleNames() const +{ + return { + { ApplicationIdRole, "name"}, + { Qt::DecorationRole, "icon"}, + { Qt::DisplayRole, "title"}, + { BlockedApplicationRole, "blocked" } + }; +} + +void BlacklistedApplicationsModel::load() +{ + // Loading plugin configuration + + const auto config = d->pluginConfig->group(SQLITE_PLUGIN_CONFIG_KEY); + + const auto defaultBlockedValue = config.readEntry("blocked-by-default", false); + auto blockedApplications = QSet::fromList(config.readEntry("blocked-applications", QStringList())); + auto allowedApplications = QSet::fromList(config.readEntry("allowed-applications", QStringList())); + + // Reading new applications from the database + + const QString path + = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + + QStringLiteral("/kactivitymanagerd/resources/database"); + + d->database = QSqlDatabase::addDatabase("QSQLITE", "plugins_sqlite_db_resources"); + d->database.setDatabaseName(path); + + if (!d->database.open()) { + // qDebug() << "Failed to open the database" << path << d->database.lastError(); + return; + } + + auto query = d->database.exec("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; + } + } + } + + auto applications = (blockedApplications + allowedApplications).toList(); + + if (applications.length() > 0) { + qSort(applications); + + beginInsertRows(QModelIndex(), 0, applications.length() - 1); + + foreach(const auto & name, 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() +{ + auto config = d->pluginConfig->group(SQLITE_PLUGIN_CONFIG_KEY); + QStringList blockedApplications; + QStringList allowedApplications; + + for (int i = 0; i < rowCount(); i++) { + (d->applications[i].blocked ? blockedApplications : allowedApplications) + << d->applications[i].name; + } + + config.writeEntry("allowed-applications", allowedApplications); + config.writeEntry("blocked-applications", blockedApplications); +} + +void BlacklistedApplicationsModel::defaults() +{ + for (int i = 0; i < rowCount(); i++) { + d->applications[i].blocked = false; + } + + dataChanged(QAbstractListModel::index(0), + QAbstractListModel::index(rowCount() - 1)); +} + +void BlacklistedApplicationsModel::toggleApplicationBlocked(int index) +{ + if (index > rowCount()) { + return; + } + + d->applications[index].blocked = !d->applications[index].blocked; + dataChanged(QAbstractListModel::index(index), + QAbstractListModel::index(index)); + + emit changed(); +} + +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() ? "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; + emit enabledChanged(enabled); +} + +// #include diff --git a/kcms/activities/CMakeLists.txt b/kcms/activities/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/activities/CMakeLists.txt @@ -0,0 +1,88 @@ +# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab: +project (KCMActivities) + +find_package (Qt5 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}/kactivitymanagerd/workspace/settings/ + ) + +if (NOT IS_ABSOLUTE "${KDE_INSTALL_DATADIR_KF5}") + set (KAMD_KCM_DATADIR "${CMAKE_INSTALL_PREFIX}/${KAMD_KCM_DATADIR}") +endif () + +configure_file (kactivities-kcm-features.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kactivities-kcm-features.h) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +add_subdirectory(imports) + +set (KAMD_KCM_SRCS + kcm_activities.cpp + + MainConfigurationWidget.cpp + ActivitiesTab.cpp + SwitchingTab.cpp + PrivacyTab.cpp + + BlacklistedApplicationsModel.cpp + ExtraActivitiesInterface.cpp + + utils/dbusfuture_p.cpp + ) + +ki18n_wrap_ui ( + KAMD_KCM_SRCS + ui/MainConfigurationWidgetBase.ui + ui/PrivacyTabBase.ui + ui/SwitchingTabBase.ui + ) + +qt5_add_dbus_interface ( + KAMD_KCM_SRCS + + common/dbus/org.kde.ActivityManager.Features.xml + features_interface + ) + +add_library (kcm_activities MODULE ${KAMD_KCM_SRCS}) + +target_link_libraries (kcm_activities + Qt5::Quick + Qt5::Core + Qt5::Sql + Qt5::Qml + Qt5::DBus + KF5::KCMUtils + KF5::I18n + KF5::Service + KF5::Declarative + KF5::XmlGui + KF5::GlobalAccel + KF5::Activities + ) + +install ( + TARGETS kcm_activities + DESTINATION ${KDE_INSTALL_PLUGINDIR} + ) + +install ( + FILES kcm_activities.desktop + DESTINATION ${KDE_INSTALL_KSERVICES5DIR} + ) + +install ( + DIRECTORY + + qml/activitiesTab + qml/privacyTab + + DESTINATION ${KAMD_KCM_DATADIR}/qml + ) + diff --git a/kcms/activities/ExtraActivitiesInterface.h b/kcms/activities/ExtraActivitiesInterface.h new file mode 100644 --- /dev/null +++ b/kcms/activities/ExtraActivitiesInterface.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef EXTRA_ACTIVITES_INTERFACE_H +#define EXTRA_ACTIVITES_INTERFACE_H + +#include + +#include + +#include +#include + +class ExtraActivitiesInterface : public QObject { + Q_OBJECT + +public: + ExtraActivitiesInterface(QObject *parent = Q_NULLPTR); + ~ExtraActivitiesInterface(); + +public Q_SLOTS: + void setIsPrivate(const QString &activity, bool isPrivate, + QJSValue callback); + void getIsPrivate(const QString &activity, QJSValue callback); + + void setShortcut(const QString &activity, const QKeySequence &keySequence); + QKeySequence shortcut(const QString &activity); + +private: + D_PTR; +}; + +#endif // EXTRA_ACTIVITES_INTERFACE_H diff --git a/kcms/activities/ExtraActivitiesInterface.cpp b/kcms/activities/ExtraActivitiesInterface.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/ExtraActivitiesInterface.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ExtraActivitiesInterface.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include "utils/dbusfuture_p.h" +#include "features_interface.h" +#include "definitions.h" +#include "common/dbus/common.h" + +#define ENABLE_QJSVALUE_CONTINUATION +#include "utils/continue_with.h" + +class ExtraActivitiesInterface::Private { +public: + Private(ExtraActivitiesInterface *q) + : features(new KAMD_DBUS_CLASS_INTERFACE(Features, Features, q)) + , activitiesActionCollection(new KActionCollection(q, QStringLiteral("ActivityManager"))) + { + activitiesActionCollection->setComponentDisplayName(i18n("Activities")); + activitiesActionCollection->setConfigGlobal(true); + } + + ~Private() + { + } + + QAction *actionForActivity(const QString &activity) + { + if (!activityActions.contains(activity)) { + auto action = activitiesActionCollection->addAction( + "switch-to-activity-" + activity); + + activityActions[activity] = action; + action->setProperty("isConfigurationAction", true); + + KGlobalAccel::self()->setShortcut(action, {}); + } + + return activityActions[activity]; + } + + + std::unique_ptr features; + std::unique_ptr activitiesActionCollection; + QHash activityActions; +}; + +ExtraActivitiesInterface::ExtraActivitiesInterface(QObject *parent) + : QObject(parent) + , d(this) +{ +} + +ExtraActivitiesInterface::~ExtraActivitiesInterface() +{ +} + +void ExtraActivitiesInterface::setIsPrivate(const QString &activity, + bool isPrivate, QJSValue callback) +{ + auto result = d->features->SetValue( + "org.kde.ActivityManager.Resources.Scoring/isOTR/" + activity, + QDBusVariant(isPrivate)); + + auto *watcher = new QDBusPendingCallWatcher(result, this); + + QObject::connect( + watcher, &QDBusPendingCallWatcher::finished, + this, [callback] (QDBusPendingCallWatcher* watcher) mutable { + callback.call(); + watcher->deleteLater(); + } + ); +} + +void ExtraActivitiesInterface::getIsPrivate(const QString &activity, + QJSValue callback) +{ + auto result = d->features->GetValue( + "org.kde.ActivityManager.Resources.Scoring/isOTR/" + activity); + + auto *watcher = new QDBusPendingCallWatcher(result, this); + + QObject::connect( + watcher, &QDBusPendingCallWatcher::finished, + this, [callback,result] (QDBusPendingCallWatcher* watcher) mutable { + QDBusPendingReply reply = *watcher; + callback.call({reply.value().variant().toBool()}); + watcher->deleteLater(); + } + ); +} + +void ExtraActivitiesInterface::setShortcut(const QString &activity, + const QKeySequence &keySequence) +{ + auto action = d->actionForActivity(activity); + + KGlobalAccel::self()->setShortcut(action, { keySequence }, + KGlobalAccel::NoAutoloading); +} + +QKeySequence ExtraActivitiesInterface::shortcut(const QString &activity) +{ + auto action = d->actionForActivity(activity); + + const auto shortcuts = KGlobalAccel::self()->shortcut(action); + return (shortcuts.isEmpty()) ? QKeySequence() : shortcuts.first(); +} + diff --git a/kcms/activities/MainConfigurationWidget.h b/kcms/activities/MainConfigurationWidget.h new file mode 100644 --- /dev/null +++ b/kcms/activities/MainConfigurationWidget.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MAIN_CONFIGURATION_WIDGET_H +#define MAIN_CONFIGURATION_WIDGET_H + +#include +#include +#include +#include + +#include + +/** + * MainConfigurationWidget + */ +class MainConfigurationWidget : public KCModule { + Q_OBJECT +public: + MainConfigurationWidget(QWidget *parent, QVariantList args); + ~MainConfigurationWidget(); + +public Q_SLOTS: + void defaults() Q_DECL_OVERRIDE; + void load() Q_DECL_OVERRIDE; + void save() Q_DECL_OVERRIDE; + +private: + D_PTR; +}; + +#endif // MAIN_CONFIGURATION_WIDGET_H diff --git a/kcms/activities/MainConfigurationWidget.cpp b/kcms/activities/MainConfigurationWidget.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/MainConfigurationWidget.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "MainConfigurationWidget.h" + +#include + +#include "ui_MainConfigurationWidgetBase.h" + +#include "ActivitiesTab.h" +#include "SwitchingTab.h" +#include "PrivacyTab.h" + +K_PLUGIN_FACTORY(ActivitiesKCMFactory, registerPlugin();) + +class MainConfigurationWidget::Private : public Ui::MainConfigurationWidgetBase { +public: + ActivitiesTab * tabActivities; + SwitchingTab * tabSwitching; + PrivacyTab * tabPrivacy; +}; + +MainConfigurationWidget::MainConfigurationWidget(QWidget *parent, QVariantList args) + : KCModule(parent, args) + , d() +{ + d->setupUi(this); + + d->tabs->insertTab(0, d->tabActivities = new ActivitiesTab(d->tabs), i18n("Activities")); + d->tabs->insertTab(1, d->tabSwitching = new SwitchingTab(d->tabs), i18n("Switching")); + d->tabs->insertTab(2, d->tabPrivacy = new PrivacyTab(d->tabs), i18n("Privacy")); + + connect(d->tabActivities, SIGNAL(changed()), this, SLOT(changed())); + connect(d->tabSwitching, SIGNAL(changed()), this, SLOT(changed())); + connect(d->tabPrivacy, SIGNAL(changed()), this, SLOT(changed())); +} + +MainConfigurationWidget::~MainConfigurationWidget() +{ +} + +void MainConfigurationWidget::defaults() +{ + d->tabActivities->defaults(); + d->tabPrivacy->defaults(); + d->tabSwitching->defaults(); +} + +void MainConfigurationWidget::load() +{ + d->tabActivities->load(); + d->tabPrivacy->load(); + d->tabSwitching->load(); +} + +void MainConfigurationWidget::save() +{ + d->tabActivities->save(); + d->tabPrivacy->save(); + d->tabSwitching->save(); +} + +#include "MainConfigurationWidget.moc" diff --git a/kcms/activities/PrivacyTab.h b/kcms/activities/PrivacyTab.h new file mode 100644 --- /dev/null +++ b/kcms/activities/PrivacyTab.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PRIVACY_TAB_H +#define PRIVACY_TAB_H + +#include + +#include + +/** + * PrivacyTab + */ +class PrivacyTab : public QWidget { + Q_OBJECT +public: + PrivacyTab(QWidget *parent); + ~PrivacyTab(); + +public Q_SLOTS: + void defaults(); + void load(); + void save(); + +private Q_SLOTS: + void forget(int count, const QString &what); + void forgetLastHour(); + void forgetTwoHours(); + void forgetDay(); + void forgetAll(); + + void spinKeepHistoryValueChanged(int value); + +Q_SIGNALS: + void changed(); + +private: + enum WhatToRemember { + AllApplications = 0, + SpecificApplications = 1, + NoApplications = 2 + }; + + D_PTR; +}; + +#endif // PRIVACY_TAB_H diff --git a/kcms/activities/PrivacyTab.cpp b/kcms/activities/PrivacyTab.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/PrivacyTab.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "PrivacyTab.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "ui_PrivacyTabBase.h" +#include "BlacklistedApplicationsModel.h" +#include "definitions.h" + +#include + +#include "kactivities-kcm-features.h" + +#include "common/dbus/common.h" + +#include "utils.h" + +class PrivacyTab::Private : public Ui::PrivacyTabBase { +public: + KSharedConfig::Ptr mainConfig; + KSharedConfig::Ptr pluginConfig; + + BlacklistedApplicationsModel *blacklistedApplicationsModel; + QObject *viewBlacklistedApplicationsRoot; + std::unique_ptr viewBlacklistedApplications; + + Private() + : viewBlacklistedApplicationsRoot(Q_NULLPTR) + , viewBlacklistedApplications(Q_NULLPTR) + { + } +}; + +PrivacyTab::PrivacyTab(QWidget *parent) + : QWidget(parent) + , d() +{ + d->setupUi(this); + + d->mainConfig = KSharedConfig::openConfig("kactivitymanagerdrc"); + d->pluginConfig = KSharedConfig::openConfig("kactivitymanagerd-pluginsrc"); + + // Keep history initialization + + d->spinKeepHistory->setRange(0, INT_MAX); + d->spinKeepHistory->setSpecialValueText(i18nc("unlimited number of months", "forever")); + + connect(d->spinKeepHistory, SIGNAL(valueChanged(int)), + this, SLOT(spinKeepHistoryValueChanged(int))); + spinKeepHistoryValueChanged(0); + + // Clear recent history button + + auto menu = new QMenu(this); + + connect(menu->addAction(i18n("Forget the last hour")), &QAction::triggered, + this, &PrivacyTab::forgetLastHour); + connect(menu->addAction(i18n("Forget the last two hours")), &QAction::triggered, + this, &PrivacyTab::forgetTwoHours); + connect(menu->addAction(i18n("Forget a day")), &QAction::triggered, + this, &PrivacyTab::forgetDay); + connect(menu->addAction(i18n("Forget everything")), &QAction::triggered, + this, &PrivacyTab::forgetAll); + + d->buttonClearRecentHistory->setMenu(menu); + + // Blacklist applications + + d->blacklistedApplicationsModel = new BlacklistedApplicationsModel(this); + + new QGridLayout(d->viewBlacklistedApplicationsContainer); + + d->viewBlacklistedApplications + = createView(d->viewBlacklistedApplicationsContainer); + d->viewBlacklistedApplications->rootContext()->setContextProperty( + "applicationModel", d->blacklistedApplicationsModel); + setViewSource(d->viewBlacklistedApplications, + "/qml/privacyTab/BlacklistApplicationView.qml"); + + // React to changes + + connect(d->radioRememberAllApplications, SIGNAL(toggled(bool)), this, SIGNAL(changed())); + connect(d->radioDontRememberApplications, SIGNAL(toggled(bool)), this, SIGNAL(changed())); + connect(d->spinKeepHistory, SIGNAL(valueChanged(int)), this, SIGNAL(changed())); + connect(d->blacklistedApplicationsModel, SIGNAL(changed()), this, SIGNAL(changed())); + + connect(d->radioRememberSpecificApplications, SIGNAL(toggled(bool)), + d->blacklistedApplicationsModel, SLOT(setEnabled(bool))); + + connect(d->radioRememberSpecificApplications, SIGNAL(toggled(bool)), + d->viewBlacklistedApplicationsContainer, SLOT(setEnabled(bool))); + + connect(d->radioRememberSpecificApplications, SIGNAL(toggled(bool)), + d->checkBlacklistAllNotOnList, SLOT(setEnabled(bool))); + + defaults(); + + d->checkBlacklistAllNotOnList->setEnabled(false); + d->blacklistedApplicationsModel->setEnabled(false); + d->viewBlacklistedApplicationsContainer->setEnabled(false); +} + +PrivacyTab::~PrivacyTab() +{ +} + +void PrivacyTab::defaults() +{ + d->radioRememberAllApplications->click(); + d->spinKeepHistory->setValue(0); + d->blacklistedApplicationsModel->defaults(); +} + +void PrivacyTab::load() +{ + d->blacklistedApplicationsModel->load(); + + const auto statisticsConfig + = d->pluginConfig->group(SQLITE_PLUGIN_CONFIG_KEY); + + const auto whatToRemember = (WhatToRemember)statisticsConfig.readEntry( + "what-to-remember", (int)AllApplications); + + d->radioRememberAllApplications->setChecked(whatToRemember == AllApplications); + d->radioRememberSpecificApplications->setChecked(whatToRemember == SpecificApplications); + d->radioDontRememberApplications->setChecked(whatToRemember == NoApplications); + + d->spinKeepHistory->setValue( + statisticsConfig.readEntry("keep-history-for", 0)); + d->checkBlacklistAllNotOnList->setChecked( + statisticsConfig.readEntry("blocked-by-default", false)); +} + +void PrivacyTab::save() +{ + d->blacklistedApplicationsModel->save(); + + auto statisticsConfig = d->pluginConfig->group(SQLITE_PLUGIN_CONFIG_KEY); + + const auto whatToRemember = + d->radioRememberSpecificApplications->isChecked() ? SpecificApplications : + d->radioDontRememberApplications->isChecked() ? NoApplications : + /* otherwise */ AllApplications; + + statisticsConfig.writeEntry("what-to-remember", (int)whatToRemember); + statisticsConfig.writeEntry("keep-history-for", d->spinKeepHistory->value()); + statisticsConfig.writeEntry("blocked-by-default", d->checkBlacklistAllNotOnList->isChecked()); + + statisticsConfig.sync(); + + auto pluginListConfig = d->mainConfig->group("Plugins"); + + pluginListConfig.writeEntry("org.kde.ActivityManager.ResourceScoringEnabled", + whatToRemember != NoApplications); + + pluginListConfig.sync(); +} + +void PrivacyTab::forget(int count, const QString &what) +{ + KAMD_DBUS_DECL_INTERFACE(rankingsservice, Resources/Scoring, + ResourcesScoring); + + rankingsservice.asyncCall("DeleteRecentStats", QString(), count, what); +} + +void PrivacyTab::forgetLastHour() +{ + forget(1, "h"); +} + +void PrivacyTab::forgetTwoHours() +{ + forget(2, "h"); +} + +void PrivacyTab::forgetDay() +{ + forget(1, "d"); +} + +void PrivacyTab::forgetAll() +{ + forget(0, "everything"); +} + +void PrivacyTab::spinKeepHistoryValueChanged(int value) +{ + static auto months = ki18ncp("unit of time. months to keep the history", + " month", " months"); + + if (value) { + d->spinKeepHistory->setPrefix( + i18nc("for in 'keep history for 5 months'", "for ")); + d->spinKeepHistory->setSuffix(months.subs(value).toString()); + } +} + +#include "PrivacyTab.moc" diff --git a/kcms/activities/SwitchingTab.h b/kcms/activities/SwitchingTab.h new file mode 100644 --- /dev/null +++ b/kcms/activities/SwitchingTab.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SWITCHING_TAB_H +#define SWITCHING_TAB_H + +#include + +#include + +class QKeySequence; + +/** + * SwitchingTab + */ +class SwitchingTab : public QWidget { + Q_OBJECT +public: + SwitchingTab(QWidget *parent); + ~SwitchingTab(); + +public Q_SLOTS: + void defaults(); + void load(); + void save(); + +private Q_SLOTS: + void shortcutChanged(const QKeySequence &sequence); + +Q_SIGNALS: + void changed(); + +private: + D_PTR; +}; + +#endif // SWITCHING_TAB_H diff --git a/kcms/activities/SwitchingTab.cpp b/kcms/activities/SwitchingTab.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/SwitchingTab.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "SwitchingTab.h" + +#include +#include +#include +#include + +#include "ui_SwitchingTabBase.h" + +#include +#include + +class SwitchingTab::Private : public Ui::SwitchingTabBase { +public: + KSharedConfig::Ptr mainConfig; + + KActionCollection *mainActionCollection; + KActivities::Consumer activities; + + void createAction(const QString &actionName, const QString &actionText, + const QList &sequence) + { + auto action = mainActionCollection->addAction(actionName); + action->setProperty("isConfigurationAction", true); + action->setText(actionText); + KGlobalAccel::self()->setShortcut(action, sequence); + } + + Private() + : mainActionCollection(Q_NULLPTR) + { + } +}; + +SwitchingTab::SwitchingTab(QWidget *parent) + : QWidget(parent) + , d() +{ + d->setupUi(this); + + d->mainConfig = KSharedConfig::openConfig("kactivitymanagerdrc"); + + // Shortcut config. The shortcut belongs to the component "plasmashell"! + d->mainActionCollection = new KActionCollection(this, QStringLiteral("plasmashell")); + d->mainActionCollection->setComponentDisplayName(i18n("Activity switching")); + d->mainActionCollection->setConfigGlobal(true); + + d->createAction("next activity", + i18nc("@action", "Walk through activities"), + { Qt::META + Qt::Key_Tab }); + d->createAction("previous activity", + i18nc("@action", "Walk through activities (Reverse)"), + { Qt::META + Qt::SHIFT + Qt::Key_Tab } ); + + d->scActivities->setActionTypes(KShortcutsEditor::GlobalAction); + d->scActivities->addCollection(d->mainActionCollection); + + connect(d->scActivities, &KShortcutsEditor::keyChange, + this, [this] { changed(); }); + connect(d->checkRememberVirtualDesktop, SIGNAL(toggled(bool)), + this, SIGNAL(changed())); + + defaults(); +} + +SwitchingTab::~SwitchingTab() +{ +} + +void SwitchingTab::shortcutChanged(const QKeySequence &sequence) +{ + QString actionName = sender() + ? sender()->property("shortcutAction").toString() + : QString(); + + if (actionName.isEmpty()) return; + + auto action = d->mainActionCollection->action(actionName); + + KGlobalAccel::self()->setShortcut(action, { sequence }, + KGlobalAccel::NoAutoloading); + d->mainActionCollection->writeSettings(); + + emit changed(); +} + +void SwitchingTab::defaults() +{ + d->checkRememberVirtualDesktop->setChecked(false); +} + +void SwitchingTab::load() +{ + auto pluginListConfig = d->mainConfig->group("Plugins"); + + d->checkRememberVirtualDesktop->setChecked(pluginListConfig.readEntry( + "org.kde.ActivityManager.VirtualDesktopSwitchEnabled", false)); +} + +void SwitchingTab::save() +{ + auto pluginListConfig = d->mainConfig->group("Plugins"); + + pluginListConfig.writeEntry( + "org.kde.ActivityManager.VirtualDesktopSwitchEnabled", + d->checkRememberVirtualDesktop->isChecked()); + + pluginListConfig.sync(); +} + +#include "SwitchingTab.moc" diff --git a/kcms/activities/common/dbus/common.h b/kcms/activities/common/dbus/common.h new file mode 100644 --- /dev/null +++ b/kcms/activities/common/dbus/common.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DBUS_COMMON_H +#define DBUS_COMMON_H + +#include +#include + +#define KAMD_DBUS_SERVICE \ + QStringLiteral("org.kde.ActivityManager") + +#define KAMD_DBUS_OBJECT_PATH(A) \ + (sizeof(#A) > 2 ? QLatin1String("/ActivityManager/" #A) \ + : QLatin1String("/ActivityManager")) + +#define KAMD_DBUS_OBJECT(A) \ + QLatin1String("org.kde.ActivityManager." #A) + +#define KAMD_DBUS_INTERFACE(OBJECT_PATH, OBJECT, PARENT) \ + QDBusInterface(KAMD_DBUS_SERVICE, \ + KAMD_DBUS_OBJECT_PATH(OBJECT_PATH), \ + KAMD_DBUS_OBJECT(OBJECT), \ + QDBusConnection::sessionBus(), \ + PARENT) + +#define KAMD_DBUS_DECL_INTERFACE(VAR, OBJECT_PATH, OBJECT) \ + QDBusInterface VAR(KAMD_DBUS_SERVICE, \ + KAMD_DBUS_OBJECT_PATH(OBJECT_PATH), \ + KAMD_DBUS_OBJECT(OBJECT), \ + QDBusConnection::sessionBus(), \ + Q_NULLPTR) + +#define KAMD_DBUS_CLASS_INTERFACE(OBJECT_PATH, OBJECT, PARENT) \ + org::kde::ActivityManager::OBJECT( \ + KAMD_DBUS_SERVICE, \ + KAMD_DBUS_OBJECT_PATH(OBJECT_PATH), \ + QDBusConnection::sessionBus(), \ + PARENT) + +#endif // DBUS_COMMON_H + diff --git a/kcms/activities/common/dbus/org.kde.ActivityManager.Features.xml b/kcms/activities/common/dbus/org.kde.ActivityManager.Features.xml new file mode 100644 --- /dev/null +++ b/kcms/activities/common/dbus/org.kde.ActivityManager.Features.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/kcms/activities/definitions.h b/kcms/activities/definitions.h new file mode 100644 --- /dev/null +++ b/kcms/activities/definitions.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#define SQLITE_PLUGIN_CONFIG_KEY "Plugin-org.kde.ActivityManager.Resources.Scoring" + +#endif // DEFINITIONS_H + diff --git a/kcms/activities/imports/CMakeLists.txt b/kcms/activities/imports/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/CMakeLists.txt @@ -0,0 +1,58 @@ +# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab: + +project (kactivities-settings) +find_package (ECM 0.0.8 REQUIRED NO_MODULE) +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) + +find_package (Qt5 REQUIRED NO_MODULE COMPONENTS Sql Gui Widgets Qml Quick Sql QuickWidgets) +find_package (KF5GlobalAccel ${KF5_DEP_VERSION} CONFIG REQUIRED) +# find_package (KF5DBusAddons ${KF5_DEP_VERSION} CONFIG REQUIRED) +find_package (KF5I18n ${KF5_DEP_VERSION} CONFIG REQUIRED) +find_package (KF5WidgetsAddons ${KF5_DEP_VERSION} CONFIG REQUIRED) +# find_package (KF5Config ${KF5_DEP_VERSION} CONFIG REQUIRED) +# find_package (KF5CoreAddons ${KF5_DEP_VERSION} CONFIG REQUIRED) +# find_package (KF5KIO ${KF5_DEP_VERSION} CONFIG REQUIRED) + +set ( + kactivities_KCM_imports_LIB_SRCS + plugin.cpp + activitysettings.cpp + dialog.cpp + ) + +qt5_add_dbus_interface ( + kactivities_KCM_imports_LIB_SRCS + + ../common/dbus/org.kde.ActivityManager.Features.xml + features_interface + ) + +add_library (kactivitiessettingsplugin SHARED ${kactivities_KCM_imports_LIB_SRCS}) + +target_link_libraries ( + kactivitiessettingsplugin + Qt5::Core + Qt5::DBus + Qt5::Gui + Qt5::Qml + Qt5::Quick + Qt5::Widgets + Qt5::QuickWidgets + KF5::I18n + KF5::Activities + KF5::GlobalAccel + KF5::WidgetsAddons + ) + +## install + +install ( + DIRECTORY + qml/activityDialog + + DESTINATION ${KAMD_KCM_DATADIR}/qml + ) + +install (TARGETS kactivitiessettingsplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/activities/settings) +install (FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/activities/settings) + diff --git a/kcms/activities/imports/activitysettings.h b/kcms/activities/imports/activitysettings.h new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/activitysettings.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ACTIVITYSETTINGS_H +#define ACTIVITYSETTINGS_H + +#include + +class ActivitySettings: public QObject { + Q_OBJECT + +public: + ActivitySettings(QObject *parent = Q_NULLPTR); + ~ActivitySettings(); + +public Q_SLOTS: + Q_INVOKABLE void configureActivities(); + Q_INVOKABLE void configureActivity(const QString &id); + Q_INVOKABLE void newActivity(); + Q_INVOKABLE void deleteActivity(const QString &id); +}; + +#endif // ACTIVITYSETTINGS_H + + diff --git a/kcms/activities/imports/activitysettings.cpp b/kcms/activities/imports/activitysettings.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/activitysettings.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "activitysettings.h" + +#include +#include + +#include + +#include "dialog.h" + +#include +#include + +ActivitySettings::ActivitySettings(QObject *parent) + : QObject(parent) +{ +} + +ActivitySettings::~ActivitySettings() +{ +} + +void ActivitySettings::configureActivity(const QString &id) +{ + auto dialog = new Dialog(id); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); +} + +void ActivitySettings::newActivity() +{ + auto dialog = new Dialog(); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); +} + +void ActivitySettings::deleteActivity(const QString &id) +{ + KActivities::Info info(id); + + if (QMessageBox::question(Q_NULLPTR, i18n("Delete activity"), + i18n("Are you sure you want to delete '%1'?", + info.name())) == QMessageBox::Yes) { + KActivities::Controller().removeActivity(id); + } +} + +void ActivitySettings::configureActivities() +{ + QProcess::startDetached("kcmshell5", { "activities" }); +} + + +#include "activitysettings.moc" + + diff --git a/kcms/activities/imports/dialog.h b/kcms/activities/imports/dialog.h new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/dialog.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DIALOG_H +#define DIALOG_H + +#include +#include + +#include "utils/d_ptr.h" + +class Dialog: public QDialog { + Q_OBJECT + +public: + Dialog(QObject *parent = Q_NULLPTR); + Dialog(const QString &activityId, QObject *parent = Q_NULLPTR); + + ~Dialog(); + + void initUi(const QString &activityId = QString()); + + QString activityId() const; + void setActivityId(const QString &activityId); + + QString activityName() const; + void setActivityName(const QString &activityName); + + QString activityDescription() const; + void setActivityDescription(const QString &activityDescription); + + QString activityIcon() const; + void setActivityIcon(const QString &activityIcon); + + QString activityWallpaper() const; + void setActivityWallpaper(const QString &activityWallpaper); + + bool activityIsPrivate() const; + void setActivityIsPrivate(bool activityIsPrivate); + + QKeySequence activityShortcut() const; + void setActivityShortcut(const QKeySequence &activityShortcut); + +public Q_SLOTS: + void save(); + void create(); + void saveChanges(const QString &activityId); + +protected: + void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; + +private: + D_PTR; + +}; + +#endif // DIALOG_H + diff --git a/kcms/activities/imports/dialog.cpp b/kcms/activities/imports/dialog.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/dialog.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "dialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../kactivities-kcm-features.h" + +#include "kactivities/info.h" +#include "kactivities/controller.h" +#include "features_interface.h" + +#include "common/dbus/common.h" +#include "utils/continue_with.h" +#include "utils/d_ptr_implementation.h" +#include "../utils.h" + +class Dialog::Private { +public: + Private(Dialog *parent) + : q(parent) + , activityName("activityName") + , activityDescription("activityDescription") + , activityIcon("activityIcon") + , activityWallpaper("activityWallpaper") + , activityIsPrivate(true) + , activityShortcut("activityShortcut") + , features(new KAMD_DBUS_CLASS_INTERFACE(Features, Features, q)) + { + } + + Dialog *const q; + QVBoxLayout *layout; + QTabWidget *tabs; + + QQuickWidget *tabGeneral; + QQuickWidget *tabOther; + KMessageWidget *message; + + QQuickWidget *createTab(const QString &title, const QString &file) + { + auto view = new QQuickWidget(); + + view->setResizeMode(QQuickWidget::SizeRootObjectToView); + +// TODO: Remove this once we start requiring Qt 5.4 +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) + #warning "The activity configuration dialogue will not fully follow the system colours. Update to Qt 5.5." +#else + view->setClearColor(QGuiApplication::palette().window().color()); +#endif + + view->rootContext()->setContextProperty("dialog", q); + + if (setViewSource(view, "/qml/activityDialog/" + file)) { + tabs->addTab(view, title); + + auto root = view->rootObject(); + Q_ASSERT(root); + QMetaObject::invokeMethod(root, "load", Qt::DirectConnection); + + } else { + message->setText(i18n("Error loading the QML files. Check your installation.\nMissing %1", + QStringLiteral(KAMD_KCM_DATADIR) + "/qml/activityDialog/" + file)); + message->setVisible(true); + } + + return view; + } + + void setFocus(QQuickWidget *widget) + { + // TODO: does not work... + widget->setFocus(); + auto root = widget->rootObject(); + + if (!root) return; + + QMetaObject::invokeMethod(widget->rootObject(), "setFocus", + Qt::DirectConnection); + } + + QString activityId; + + QString activityName; + QString activityDescription; + QString activityIcon; + QString activityWallpaper; + bool activityIsPrivate; + QString activityShortcut; + + KActivities::Info *activityInfo; + KActivities::Controller activities; + org::kde::ActivityManager::Features *features; +}; + +Dialog::Dialog(QObject *parent) + : QDialog() + , d(this) +{ + setWindowTitle(i18n("Create a new activity")); + initUi(); +} + +Dialog::Dialog(const QString &activityId, QObject *parent) + : QDialog() + , d(this) +{ + setWindowTitle(i18n("Activity settings")); + initUi(activityId); + + setActivityId(activityId); + + d->activityInfo = new KActivities::Info(activityId, this); + + setActivityName(d->activityInfo->name()); + setActivityDescription(d->activityInfo->description()); + setActivityIcon(d->activityInfo->icon()); + + // finding the key shortcut + const auto shortcuts = KGlobalAccel::self()->globalShortcut( + QStringLiteral("ActivityManager"), "switch-to-activity-" + activityId); + setActivityShortcut(shortcuts.isEmpty() ? QKeySequence() : shortcuts.first()); + + // is private? + auto result = d->features->GetValue( + "org.kde.ActivityManager.Resources.Scoring/isOTR/" + activityId); + + auto watcher = new QDBusPendingCallWatcher(result, this); + + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, + [&](QDBusPendingCallWatcher *watcher) mutable { + QDBusPendingReply reply = *watcher; + setActivityIsPrivate(reply.value().variant().toBool()); + }); + + +} + +void Dialog::initUi(const QString &activityId) +{ + resize(600, 500); + + d->layout = new QVBoxLayout(this); + + // Message widget for showing errors + d->message = new KMessageWidget(this); + d->message->setMessageType(KMessageWidget::Error); + d->message->setVisible(false); + d->layout->addWidget(d->message); + + // Tabs + d->tabs = new QTabWidget(this); + d->layout->addWidget(d->tabs); + d->tabGeneral = d->createTab(i18n("General"), "GeneralTab.qml"); + d->tabOther = d->createTab(i18n("Other"), "OtherTab.qml"); + + // Buttons + auto buttons = new QDialogButtonBox( + QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + d->layout->QLayout::addWidget(buttons); + + if (activityId.isEmpty()) { + buttons->button(QDialogButtonBox::Ok)->setText(i18n("Create")); + } + + connect(buttons->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, + this, &Dialog::save); + connect(buttons, &QDialogButtonBox::rejected, + this, &Dialog::close); + + setActivityName(QString()); + setActivityDescription(QString()); + setActivityIcon(QString()); + setActivityIsPrivate(false); + + setActivityShortcut(QKeySequence()); +} + +Dialog::~Dialog() +{ +} + +void Dialog::showEvent(QShowEvent *event) +{ + // Setting the focus + d->setFocus(d->tabGeneral); +} + +#define IMPLEMENT_PROPERTY(Scope, Type, PType, PropName) \ + Type Dialog::activity##PropName() const \ + { \ + auto root = d->tab##Scope->rootObject(); \ + \ + if (!root) { \ + qDebug() << "Root does not exist"; \ + return Type(); \ + } \ + \ + return root->property("activity" #PropName).value(); \ + } \ + \ + void Dialog::setActivity##PropName(PType value) \ + { \ + auto root = d->tab##Scope->rootObject(); \ + \ + if (!root) { \ + qDebug() << "Root does not exist"; \ + return; \ + } \ + \ + root->setProperty("activity" #PropName, value); \ + } + +IMPLEMENT_PROPERTY(General, QString, const QString &, Id) +IMPLEMENT_PROPERTY(General, QString, const QString &, Name) +IMPLEMENT_PROPERTY(General, QString, const QString &, Description) +IMPLEMENT_PROPERTY(General, QString, const QString &, Icon) +IMPLEMENT_PROPERTY(General, QString, const QString &, Wallpaper) +IMPLEMENT_PROPERTY(Other, QKeySequence, const QKeySequence &, Shortcut) +IMPLEMENT_PROPERTY(Other, bool, bool, IsPrivate) +#undef IMPLEMENT_PROPERTY + +void Dialog::save() +{ + if (activityId().isEmpty()) { + create(); + + } else { + saveChanges(activityId()); + + } +} + +void Dialog::create() +{ + using namespace kamd::utils; + continue_with( + d->activities.addActivity(activityName()), + [this](const optional_view &activityId) { + if (activityId.is_initialized()) { + saveChanges(activityId.get()); + } + }); +} + +void Dialog::saveChanges(const QString &activityId) +{ + d->activities.setActivityName(activityId, activityName()); + d->activities.setActivityDescription(activityId, activityDescription()); + d->activities.setActivityIcon(activityId, activityIcon()); + + // setting the key shortcut + QAction action(Q_NULLPTR); + action.setProperty("isConfigurationAction", true); + action.setProperty("componentName", "ActivityManager"); + action.setObjectName("switch-to-activity-" + activityId); + KGlobalAccel::self()->removeAllShortcuts(&action); + KGlobalAccel::self()->setGlobalShortcut(&action, activityShortcut()); + + // is private? + d->features->SetValue("org.kde.ActivityManager.Resources.Scoring/isOTR/" + + activityId, + QDBusVariant(activityIsPrivate())); + + close(); +} + +#include "dialog.moc" + + diff --git a/kcms/activities/imports/plugin.h b/kcms/activities/imports/plugin.h new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/plugin.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KACTIVITIES_IMPORTS_PLUGIN_H +#define KACTIVITIES_IMPORTS_PLUGIN_H + +#include + +class ActivitiesSettingsPlugin : public QQmlExtensionPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.kde.activities.settings") + +public: + ActivitiesSettingsPlugin(QObject *parent = Q_NULLPTR); + void registerTypes(const char *uri) Q_DECL_OVERRIDE; +}; + +#endif // KACTIVITIES_IMPORTS_PLUGIN_H + diff --git a/kcms/activities/imports/plugin.cpp b/kcms/activities/imports/plugin.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/plugin.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "plugin.h" + +#include + +#include "activitysettings.h" + +#include + +ActivitiesSettingsPlugin::ActivitiesSettingsPlugin(QObject *parent) + : QQmlExtensionPlugin(parent) +{ +} + +static QJSValue settingsSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + + auto result = new ActivitySettings(); + return scriptEngine->newQObject(result); +} + +void ActivitiesSettingsPlugin::registerTypes(const char *uri) +{ + Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.activities.settings")); + + qmlRegisterSingletonType("org.kde.activities.settings", 0, 1, + "ActivitySettings", + settingsSingleton); +} + diff --git a/kcms/activities/imports/qml/activityDialog/GeneralTab.qml b/kcms/activities/imports/qml/activityDialog/GeneralTab.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qml/activityDialog/GeneralTab.qml @@ -0,0 +1,164 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.2 +import QtQuick.Controls 1.0 as QtControls + +import org.kde.plasma.core 2.0 as PlasmaCore + +import "./components" as Local + +Item { + id: root + + function setFocus() { + activityName.forceActiveFocus(); + console.log("GeneralTab: Set focus called"); + } + + property string activityId: "" + + property alias activityName : activityName.text + property alias activityDescription : activityDescription.text + property alias activityIcon : buttonIcon.iconName + property alias activityWallpaper : imageWallpaper.source + + height : content.childrenRect.height + 4 * units.smallSpacing + width : content.childrenRect.width + 4 * units.smallSpacing + + Column { + id: content + + anchors { + fill: parent + margins: 2 * units.smallSpacing + } + + spacing: units.smallSpacing + + QtControls.Label { + font.bold: true + text: i18n("Activity information") + } + + property int labelWidth : 2 * units.largeSpacing + + Math.max(activityName.desiredLabelWidth, activityDescription.desiredLabelWidth) + + Local.LabeledTextField { + id: activityName + label: i18n("Name") + + labelWidth: content.labelWidth + } + + Local.LabeledTextField { + id: activityDescription + label: i18n("Description") + + labelWidth: content.labelWidth + } + + Item { + width: parent.width + height: units.smallSpacing + } + + Row { + height : units.iconSizes.large * 3 + width : childrenRect.width + spacing : units.largeSpacing + + Item { + id: panelWallpaper + + visible: false + + height: parent.height + width: buttonChangeWallpaper.width + imageWallpaper.width + units.smallSpacing + + QtControls.Label { + id: labelWallpaper + font.bold: true + text: i18n("Wallpaper") + } + + QtControls.Button { + id: buttonChangeWallpaper + width: content.labelWidth + text: i18n("Change...") + + anchors { + verticalCenter: imageWallpaper.verticalCenter + } + } + + Image { + id: imageWallpaper + source: "" + + width: height / 3 * 4 + + anchors { + top: labelWallpaper.bottom + bottom: parent.bottom + left: buttonChangeWallpaper.right + + leftMargin: units.smallSpacing + } + + } + } + + Item { + id: panelIcon + + height : parent.height + width : parent.height + + QtControls.Label { + id: labelIcon + font.bold: true + text: i18n("Icon") + } + + Item { + anchors { + top: labelIcon.bottom + bottom: parent.bottom + left: parent.left + right: parent.right + } + + Local.IconChooser { + id: buttonIcon + + width: height + height: 2 * units.iconSizes.large + + anchors { + centerIn: parent + } + } + } + } + } + } +} + diff --git a/kcms/activities/imports/qml/activityDialog/OtherTab.qml b/kcms/activities/imports/qml/activityDialog/OtherTab.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qml/activityDialog/OtherTab.qml @@ -0,0 +1,55 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.2 +import QtQuick.Controls 1.0 as QtControls + +import "./components" as Local + +Item { + id: root + + property alias activityIsPrivate : checkPrivate.checked + property alias activityShortcut : panelShortcut.keySequence + + height : content.childrenRect.height + 4 * units.smallSpacing + width : content.childrenRect.width + 4 * units.smallSpacing + + Column { + anchors { + fill: parent + margins: 2 * units.smallSpacing + } + + QtControls.CheckBox { + id: checkPrivate + + text: "Private - do not track usage for this activity" + + width: parent.width + } + + Local.ShortcutChooser { + id: panelShortcut + + width: parent.width + } + } +} diff --git a/kcms/activities/imports/qml/activityDialog/components/DialogButtons.qml b/kcms/activities/imports/qml/activityDialog/components/DialogButtons.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qml/activityDialog/components/DialogButtons.qml @@ -0,0 +1,58 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls + +Row { + id: root + + property alias acceptText: buttonAccept.text + property alias acceptIcon: buttonAccept.iconName + + property alias cancelText: buttonCancel.text + property alias cancelIcon: buttonCancel.iconName + + signal accepted() + signal canceled() + + spacing: units.smallSpacing + + height : buttonAccept.height //childrenRect.height + width : buttonAccept.width + spacing + buttonCancel.width + + QtControls.Button { + id: buttonAccept + + text: i18n("Apply") + iconName: "list-add" + + onClicked: root.accepted() + } + + QtControls.Button { + id: buttonCancel + + text: i18n("Cancel") + iconName: "dialog-cancel" + + onClicked: root.canceled() + } +} diff --git a/kcms/activities/imports/qml/activityDialog/components/IconChooser.qml b/kcms/activities/imports/qml/activityDialog/components/IconChooser.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qml/activityDialog/components/IconChooser.qml @@ -0,0 +1,42 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import org.kde.kquickcontrols 2.0 as KQuickControls +import org.kde.kquickcontrolsaddons 2.0 as KQuickControls + +QtControls.Button { + id: root + + width: height + height: units.iconSizes.medium + + iconName: "preferences-activities" + + KQuickControls.IconDialog { + id: iconDialog + onIconNameChanged: root.iconName = iconName + } + + onClicked: { + iconDialog.open(); + } +} diff --git a/kcms/activities/imports/qml/activityDialog/components/LabeledTextField.qml b/kcms/activities/imports/qml/activityDialog/components/LabeledTextField.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qml/activityDialog/components/LabeledTextField.qml @@ -0,0 +1,57 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.2 +import QtQuick.Controls 1.0 as QtControls + +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + property alias text : textField.text + property alias label : label.text + + property alias labelWidth : label.width + property alias desiredLabelWidth : label.contentWidth + + height : textField.height + width : parent.width + + QtControls.Label { + id: label + + horizontalAlignment: Text.AlignRight + + anchors { + left: parent.left + verticalCenter: textField.verticalCenter + } + } + + QtControls.TextField { + id: textField + + anchors { + left : label.right + right : parent.right + + leftMargin : units.smallSpacing + } + } +} diff --git a/kcms/activities/imports/qml/activityDialog/components/ShortcutChooser.qml b/kcms/activities/imports/qml/activityDialog/components/ShortcutChooser.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qml/activityDialog/components/ShortcutChooser.qml @@ -0,0 +1,42 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.2 +import QtQuick.Controls 1.0 as QtControls + +import org.kde.plasma.core 2.0 as PlasmaCore + +import org.kde.kquickcontrols 2.0 as KQuickControls +import org.kde.kquickcontrolsaddons 2.0 as KQuickControls + +Row { + spacing: units.smallSpacing + + property alias keySequence: buttonKeyShorcut.keySequence + + QtControls.Label { + anchors.verticalCenter: parent.verticalCenter + text: i18n("Shortcut for switching to this activity:") + } + + KQuickControls.KeySequenceItem { + id: buttonKeyShorcut + } +} diff --git a/kcms/activities/imports/qmldir b/kcms/activities/imports/qmldir new file mode 100644 --- /dev/null +++ b/kcms/activities/imports/qmldir @@ -0,0 +1,3 @@ +module org.kde.activities.settings +plugin kactivitiessettingsplugin + diff --git a/kcms/activities/kactivities-kcm-features.h.cmake b/kcms/activities/kactivities-kcm-features.h.cmake new file mode 100644 --- /dev/null +++ b/kcms/activities/kactivities-kcm-features.h.cmake @@ -0,0 +1,6 @@ +#ifndef KCM_CONFIG_FEATURES_H_ +#define KCM_CONFIG_FEATURES_H_ + +#cmakedefine KAMD_KCM_DATADIR "@KAMD_KCM_DATADIR@" + +#endif diff --git a/kcms/activities/kcm_activities.cpp b/kcms/activities/kcm_activities.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/kcm_activities.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "MainConfigurationWidget.h" diff --git a/kcms/activities/kcm_activities.desktop b/kcms/activities/kcm_activities.desktop new file mode 100644 --- /dev/null +++ b/kcms/activities/kcm_activities.desktop @@ -0,0 +1,94 @@ +[Desktop Entry] +Icon=preferences-activities +Type=Service +ServiceTypes=KCModule + +X-KDE-ModuleType=Library +X-KDE-Library=kcm_activities +X-KDE-FactoryName=kcm_activities +X-KDE-ParentApp=kcontrol +X-KDE-System-Settings-Parent-Category=desktopbehavior +X-KDE-Weight=80 + +Name=Activities +Name[ar]=الأنشطة +Name[ast]=Actividaes +Name[bs]=Aktivnosti +Name[ca]=Activitats +Name[ca@valencia]=Activitats +Name[cs]=Aktivity +Name[da]=Aktiviteter +Name[de]=Aktivitäten +Name[el]=Δραστηριότητες +Name[en_GB]=Activities +Name[es]=Actividades +Name[et]=Tegevused +Name[fi]=Aktiviteetit +Name[fr]=Activités +Name[ga]=Gníomhaíochtaí +Name[gd]=Gnìomhachdan +Name[gl]=Actividades +Name[he]=פעילויות +Name[hu]=Aktivitások +Name[ia]=Activitates +Name[is]=Virkni +Name[it]=Attività +Name[kk]=Белсенділіктер +Name[km]=​សកម្មភាព +Name[ko]=활동 +Name[lt]=Veiklos +Name[mr]=कार्यपध्दती +Name[nb]=Aktiviteter +Name[nds]=Aktiviteten +Name[nl]=Activiteiten +Name[nn]=Aktivitetar +Name[pa]=ਐਕਟਵਿਟੀ +Name[pl]=Działania +Name[pt]=Actividades +Name[pt_BR]=Atividades +Name[ro]=Activități +Name[ru]=Комнаты +Name[sk]=Aktivity +Name[sl]=Dejavnosti +Name[sr]=Активности +Name[sr@ijekavian]=Активности +Name[sr@ijekavianlatin]=Aktivnosti +Name[sr@latin]=Aktivnosti +Name[sv]=Aktiviteter +Name[tg]=Фаъолият +Name[tr]=Etkinlikler +Name[ug]=پائالىيەتلەر +Name[uk]=Простори дій +Name[x-test]=xxActivitiesxx +Name[zh_CN]=活动 +Name[zh_TW]=活動 +Comment=Activities help you to focus on a specific task +Comment[ast]=Actividaes que t'ayuden a enfocate nuna xera específica +Comment[ca]=Les activitats ajuden a centrar-vos en una tasca específica +Comment[ca@valencia]=Les activitats ajuden a centrar-vos en una tasca específica +Comment[da]=Aktiviteter hjælper dig med at fokusere på en specifik opgave +Comment[de]=Aktivitäten helfen Ihnen dabei, sich auf eine Aufgabe zu konzentrieren +Comment[el]=Οι δραστηριότητες σας βοηθούν να εστιάσετε σε μια συγκεκριμένη εργασία +Comment[en_GB]=Activities help you to focus on a specific task +Comment[es]=Las actividades le ayudan a concentrarse en una tarea específica +Comment[fi]=Aktiviteetit auttavat sinua keskittymään yhteen asiaan +Comment[fr]=Les activités vous aident à vous concentrer sur une tâche spécifique +Comment[gl]=As actividades axudan a centrarse en tarefas concretas. +Comment[it]=Le attività ti aiutano a concentrarti su un compito particolare +Comment[ko]=활동을 사용하면 개별 작업에 집중할 수 있습니다 +Comment[nl]=Activiteiten helpen u te focussen op een specifieke taak +Comment[nn]=Aktivitetar hjelper deg å fokusera på oppgåver +Comment[pl]=Działania umożliwiają ci skupienie się na danym zadaniu +Comment[pt]=As actividades ajudam-no a focar-se numa tarefa específica +Comment[pt_BR]=Ajuda-o a se concentrar em uma tarefa específica +Comment[sk]=Aktivity vám pomôžu sústrediť sa na určitú úlohu +Comment[sl]=Dejavnosti vam pomagajo, da se osredotočite na določeno opravilo +Comment[sr]=Активности вам помажу да се усредсредите на одређени задатак +Comment[sr@ijekavian]=Активности вам помажу да се усредсредите на одређени задатак +Comment[sr@ijekavianlatin]=Aktivnosti vam pomažu da se usredsredite na određeni zadatak +Comment[sr@latin]=Aktivnosti vam pomažu da se usredsredite na određeni zadatak +Comment[sv]=Aktiviteter hjälper dig att fokusera på en viss uppgift +Comment[uk]=Простори дій допоможуть вам сконцентруватися на виконанні певного завдання +Comment[x-test]=xxActivities help you to focus on a specific taskxx +Comment[zh_CN]=活动可以帮助您专注于单一任务 + diff --git a/kcms/activities/qml/activitiesTab/ActivitiesView.qml b/kcms/activities/qml/activitiesTab/ActivitiesView.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/qml/activitiesTab/ActivitiesView.qml @@ -0,0 +1,195 @@ +/* vim:set foldenable foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.kquickcontrolsaddons 2.0 +import QtQuick.Controls 1.0 as QtControls + +import org.kde.activities 0.1 as Activities +import org.kde.activities.settings 0.1 +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + id: root + + anchors.fill: parent + + QtControls.Button { + id: buttonCreateActivity + + text: i18n("Create activity...") + iconName: "list-add" + + anchors { + top: parent.top + left: parent.left + } + + onClicked: ActivitySettings.newActivity(); + + enabled: !dialogCreateActivityLoader.itemVisible + } + + Loader { + id: dialogCreateActivityLoader + + property bool itemVisible: status == Loader.Ready && item.visible + + z: 1 + + anchors { + top: buttonCreateActivity.bottom + left: buttonCreateActivity.left + } + } + + QtControls.ScrollView { + anchors { + top: buttonCreateActivity.bottom + topMargin: units.smallSpacing + left: parent.left + right: parent.right + bottom: parent.bottom + } + + enabled: !dialogCreateActivityLoader.itemVisible + + ListView { + width: parent.width + // anchors.fill: parent + + model: Activities.ActivityModel { + id: kactivities + } + + SystemPalette { + id: palette + colorGroup: SystemPalette.Active + } + + /////////////////////////////////////////////////////////////////// + delegate: Rectangle { + width: parent.width + + Behavior on height { PropertyAnimation { duration: units.shortDuration } } + height: icon.height + units.smallSpacing * 2 + + (dialogConfigureLoader.itemVisible ? dialogConfigureLoader.height : 0) + + (dialogDeleteLoader.itemVisible ? dialogDeleteLoader.height : 0) + + color: (model.index % 2 == 0) ? palette.base : palette.alternateBase + + Item { + id: header + + height: units.iconSizes.medium + + anchors { + left: parent.left + right: parent.right + top: parent.top + } + + QIconItem { + id: icon + icon: model.icon + + width: height + height: parent.height + + anchors { + left: parent.left + top: parent.top + + topMargin: units.smallSpacing + bottomMargin: units.smallSpacing + } + } + + QtControls.Label { + text: model.name + + anchors { + left: icon.right + right: buttons.left + leftMargin: units.largeSpacing + verticalCenter: icon.verticalCenter + } + } + + Row { + id: buttons + + spacing: units.smallSpacing + + anchors { + right: parent.right + + rightMargin: units.smallSpacing + verticalCenter: parent.verticalCenter + } + + QtControls.Button { + id: buttonConfigure + + iconName: "configure" + + onClicked: ActivitySettings.configureActivity(model.id); + } + + QtControls.Button { + id: buttonDelete + + iconName: "edit-delete" + + onClicked: ActivitySettings.deleteActivity(model.id); + } + + visible: !dialogDeleteLoader.itemVisible + } + + visible: !dialogConfigureLoader.itemVisible + } + + Loader { + id: dialogConfigureLoader + + property bool itemVisible: status == Loader.Ready && item.visible + + anchors { + left: parent.left + top: parent.top + } + } + + Loader { + id: dialogDeleteLoader + + property bool itemVisible: status == Loader.Ready && item.visible + + anchors { + left: parent.left + top: header.bottom + } + } + } + /////////////////////////////////////////////////////////////////// + } + } +} diff --git a/kcms/activities/qml/activitiesTab/main.qml b/kcms/activities/qml/activitiesTab/main.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/qml/activitiesTab/main.qml @@ -0,0 +1,27 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2015 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.2 + +ActivitiesView { + anchors.fill: parent + +} + diff --git a/kcms/activities/qml/privacyTab/BlacklistApplicationView.qml b/kcms/activities/qml/privacyTab/BlacklistApplicationView.qml new file mode 100644 --- /dev/null +++ b/kcms/activities/qml/privacyTab/BlacklistApplicationView.qml @@ -0,0 +1,107 @@ +/* vim:set foldenable foldmethod=marker: + * + * Copyright (C) 2012 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.kquickcontrolsaddons 2.0 +import QtQuick.Controls 1.0 as QtControls + +QtControls.ScrollView { + anchors.fill: parent + + Flow { + id: main + + SystemPalette { + id: colors + } + + width: parent.parent.width + + property int minimumHeight: 100 + + spacing: 16 + + height: Math.max(childrenRect.height, minimumHeight) + + opacity: applicationModel.enabled ? 1 : .3 + Behavior on opacity { NumberAnimation { duration: 150 } } + + Repeater { + model: applicationModel + Column { + id: item + + property bool blocked: model.blocked + + Item { + id: mainIcon + + width : 64 + 20 + height : 64 + 20 + + QIconItem { + id: icon + icon: model.icon + + anchors.fill : parent + anchors.margins : 10 + + opacity: item.blocked ? 0.5 : 1.0 + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + QIconItem { + id: iconNo + icon: "dialog-cancel" + + anchors { + right : parent.right + bottom : parent.bottom + } + + width : 48 + height : 48 + opacity : (1 - icon.opacity) * 2 + } + + MouseArea { + onClicked: applicationModel.toggleApplicationBlocked(model.index) + anchors.fill: parent + } + } + + Text { + elide : Text.ElideRight + width : mainIcon.width + + text : model.title + opacity : icon.opacity + color : colors.windowText + + anchors.margins : 10 + anchors.horizontalCenter : parent.horizontalCenter + horizontalAlignment : Text.AlignHCenter + } + } + } + } + +} + diff --git a/kcms/activities/ui/MainConfigurationWidgetBase.ui b/kcms/activities/ui/MainConfigurationWidgetBase.ui new file mode 100644 --- /dev/null +++ b/kcms/activities/ui/MainConfigurationWidgetBase.ui @@ -0,0 +1,28 @@ + + + MainConfigurationWidgetBase + + + + 0 + 0 + 760 + 613 + + + + + + + -1 + + + + + + + + + changed() + + diff --git a/kcms/activities/ui/PrivacyTabBase.ui b/kcms/activities/ui/PrivacyTabBase.ui new file mode 100644 --- /dev/null +++ b/kcms/activities/ui/PrivacyTabBase.ui @@ -0,0 +1,123 @@ + + + PrivacyTabBase + + + + 0 + 0 + 631 + 479 + + + + Form + + + + + + Remember opened documents: + + + + + + + + + + + For a&ll applications + + + true + + + + + + + &Do not remember + + + + + + + O&nly for specific applications + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Keep history + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + Clear recent history + + + + + + + + + + 0 + 0 + + + + + + + + Blacklist all applications not on this list + + + + + + + + diff --git a/kcms/activities/ui/SwitchingTabBase.ui b/kcms/activities/ui/SwitchingTabBase.ui new file mode 100644 --- /dev/null +++ b/kcms/activities/ui/SwitchingTabBase.ui @@ -0,0 +1,69 @@ + + + SwitchingTabBase + + + + 0 + 0 + 666 + 558 + + + + Form + + + + + + General + + + + + + Remember the current virtual desktop for each activity (needs restart) + + + + + + + + + + Shortcuts + + + + + + + + + + + + Qt::Vertical + + + + 20 + 195 + + + + + + + + + KShortcutsEditor + QWidget +
kshortcutseditor.h
+
+
+ + +
diff --git a/kcms/activities/utils.h b/kcms/activities/utils.h new file mode 100644 --- /dev/null +++ b/kcms/activities/utils.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_H +#define UTILS_H + +#include + +inline std::unique_ptr createView(QWidget *parent) +{ + auto view = new QQuickView(); + view->setColor(QGuiApplication::palette().window().color()); + view->setResizeMode(QQuickView::SizeRootObjectToView); + + auto container = QWidget::createWindowContainer(view, parent); + container->setFocusPolicy(Qt::TabFocus); + + parent->layout()->addWidget(container); + + return std::unique_ptr(view); +} + +template +inline bool setViewSource(View &view, const QString &file) +{ + QString sourceFile = QStringLiteral(KAMD_KCM_DATADIR) + file; + + if (QFile::exists(sourceFile)) { + view->setSource(sourceFile); + + return true; + + } else { + return false; + } + +} + +#endif // UTILS_H + diff --git a/kcms/activities/utils/continue_with.h b/kcms/activities/utils/continue_with.h new file mode 100644 --- /dev/null +++ b/kcms/activities/utils/continue_with.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_CONTINUE_WITH_H +#define UTILS_CONTINUE_WITH_H + +#include +#include +#include + +#include "utils/optional_view.h" +// #include + +#ifdef ENABLE_QJSVALUE_CONTINUATION +#include +#endif + +namespace kamd { +namespace utils { + +namespace detail { //_ +#ifdef ENABLE_QJSVALUE_CONTINUATION + inline void test_continuation(const QJSValue &continuation) + { + if (!continuation.isCallable()) { + qWarning() << "Passed handler is not callable: " << continuation.toString(); + } + } + + template + inline void pass_value(const QFuture<_ReturnType> &future, + QJSValue continuation) + { + auto result = continuation.call({ future.result() }); + if (result.isError()) { + qWarning() << "Handler returned this error: " << result.toString(); + } + } + + inline void pass_value(const QFuture &future, QJSValue continuation) + { + Q_UNUSED(future); + auto result = continuation.call({}); + if (result.isError()) { + qWarning() << "Handler returned this error: " << result.toString(); + } + } +#endif + + template + inline void test_continuation(_Continuation &&continuation) + { + Q_UNUSED(continuation); + } + + template + inline void pass_value(const QFuture<_ReturnType> &future, + _Continuation &&continuation) + { + using namespace kamd::utils; + continuation(future.resultCount() > 0 + ? make_optional_view(future.result()) + : none()); + } + + template + inline void pass_value(_Continuation &&continuation) + { + continuation(); + } + +} //^ namespace detail + +template +inline void continue_with(const QFuture<_ReturnType> &future, + _Continuation &&continuation) +{ + detail::test_continuation(continuation); + + auto watcher = new QFutureWatcher<_ReturnType>(); + QObject::connect(watcher, &QFutureWatcherBase::finished, [=]() mutable { + detail::pass_value(future, continuation); + }); + + watcher->setFuture(future); +} + +} // namespace utils +} // namespace kamd + +#endif /* !UTILS_CONTINUE_WITH_H */ + + diff --git a/kcms/activities/utils/d_ptr.h b/kcms/activities/utils/d_ptr.h new file mode 100644 --- /dev/null +++ b/kcms/activities/utils/d_ptr.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef D_PTR_H +#define D_PTR_H + +#include + +namespace kamd { +namespace utils { + +template +class d_ptr { +private: + std::unique_ptr d; + +public: + d_ptr(); + + template + d_ptr(Args &&...); + + ~d_ptr(); + + T *operator->() const; +}; + +#define D_PTR \ + class Private; \ + friend class Private; \ + const ::kamd::utils::d_ptr d + +} // namespace utils +} // namespace kamd + +#endif diff --git a/kcms/activities/utils/d_ptr_implementation.h b/kcms/activities/utils/d_ptr_implementation.h new file mode 100644 --- /dev/null +++ b/kcms/activities/utils/d_ptr_implementation.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef D_PTR_IMPLEMENTATION_H +#define D_PTR_IMPLEMENTATION_H + +#include + +namespace kamd { +namespace utils { + +template +d_ptr::d_ptr() + : d(new T()) +{ +} + +template +template +d_ptr::d_ptr(Args &&... args) + : d(new T(std::forward(args)...)) +{ +} + +template +d_ptr::~d_ptr() +{ +} + +template +T *d_ptr::operator->() const +{ + return d.get(); +} + +} // namespace utils +} // namespace kamd + +#endif diff --git a/kcms/activities/utils/dbusfuture_p.h b/kcms/activities/utils/dbusfuture_p.h new file mode 100644 --- /dev/null +++ b/kcms/activities/utils/dbusfuture_p.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2013 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ACTIVITIES_DBUSFUTURE_P_H +#define ACTIVITIES_DBUSFUTURE_P_H + +#include +#include +#include +#include +#include +#include +#include + +namespace DBusFuture { + +namespace detail { //_ + +template +class DBusCallFutureInterface : public QObject, + public QFutureInterface<_Result> { +public: + DBusCallFutureInterface(QDBusPendingReply<_Result> reply) + : reply(reply), + replyWatcher(Q_NULLPTR) + { + } + + ~DBusCallFutureInterface() + { + delete replyWatcher; + } + + void callFinished(); + + QFuture<_Result> start() + { + replyWatcher = new QDBusPendingCallWatcher(reply); + + QObject::connect(replyWatcher, + &QDBusPendingCallWatcher::finished, + [this] () { callFinished(); }); + + this->reportStarted(); + + if (reply.isFinished()) { + this->callFinished(); + } + + return this->future(); + } + +private: + QDBusPendingReply<_Result> reply; + QDBusPendingCallWatcher * replyWatcher; +}; + +template +void DBusCallFutureInterface<_Result>::callFinished() +{ + deleteLater(); + + if (!reply.isError()) { + this->reportResult(reply.value()); + } + + this->reportFinished(); +} + +template <> +void DBusCallFutureInterface::callFinished(); + +template +class ValueFutureInterface : public QObject, QFutureInterface<_Result> { +public: + ValueFutureInterface(const _Result & value) + : value(value) + { + } + + QFuture<_Result> start() + { + auto future = this->future(); + + this->reportResult(value); + this->reportFinished(); + + deleteLater(); + + return future; + } + +private: + _Result value; + +}; + +template <> +class ValueFutureInterface : public QObject, QFutureInterface { +public: + ValueFutureInterface(); + + QFuture start(); + // { + // auto future = this->future(); + // this->reportFinished(); + // deleteLater(); + // return future; + // } +}; + +} //^ namespace detail + +template +QFuture<_Result> +asyncCall(QDBusAbstractInterface *interface, const QString &method, + const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), + const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), + const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), + const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant()) +{ + using namespace detail; + + auto callFutureInterface = new DBusCallFutureInterface + <_Result>(interface->asyncCall(method, arg1, arg2, arg3, arg4, arg5, + arg6, arg7, arg8)); + + return callFutureInterface->start(); +} + +template +QFuture<_Result> +fromValue(const _Result & value) +{ + using namespace detail; + + auto valueFutureInterface = new ValueFutureInterface<_Result>(value); + + return valueFutureInterface->start(); +} + +template +QFuture<_Result> +fromReply(const QDBusPendingReply<_Result> &reply) +{ + using namespace detail; + + auto callFutureInterface = new DBusCallFutureInterface<_Result>(reply); + + return callFutureInterface->start(); +} + +QFuture fromVoid(); + +} // namespace DBusFuture + +#endif /* DBUSFUTURE_P_H */ + diff --git a/kcms/activities/utils/dbusfuture_p.cpp b/kcms/activities/utils/dbusfuture_p.cpp new file mode 100644 --- /dev/null +++ b/kcms/activities/utils/dbusfuture_p.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "dbusfuture_p.h" + +namespace DBusFuture { + +namespace detail { //_ + +template <> +void DBusCallFutureInterface::callFinished() +{ + deleteLater(); + + // qDebug() << "This is call end"; + + this->reportFinished(); +} + +ValueFutureInterface::ValueFutureInterface() +{ +} + +QFuture ValueFutureInterface::start() +{ + auto future = this->future(); + + this->reportFinished(); + + deleteLater(); + + return future; +} + +} //^ namespace detail + +QFuture fromVoid() +{ + using namespace detail; + + auto valueFutureInterface = new ValueFutureInterface(); + + return valueFutureInterface->start(); +} + +} // namespace DBusFuture + diff --git a/kcms/activities/utils/optional_view.h b/kcms/activities/utils/optional_view.h new file mode 100644 --- /dev/null +++ b/kcms/activities/utils/optional_view.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 - 2016 by Ivan Cukic + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_OPTIONAL_H +#define UTILS_OPTIONAL_H + +namespace kamd { +namespace utils { + +struct none_t {}; +inline const none_t none() { return none_t(); } + +// A simple implementation of the optional class +// until we can rely on std::optional. +// It is not going to come close in the supported +// features to the std one. +// (we need it in the core library, so we don't +// want to use boost.optional) +template +class optional_view { +public: + explicit optional_view(const T &value) + : m_value(&value) + { + } + + optional_view(const none_t &) + : m_value(Q_NULLPTR) + { + } + + bool is_initialized() const + { + return m_value != Q_NULLPTR; + } + + const T &get() const + { + return *m_value; + } + + const T *operator->() const + { + return m_value; + } + +private: + const T *const m_value; +}; + +template +optional_view make_optional_view(const T &value) +{ + return optional_view(value); +} + +} // namespace utils +} // namespace kamd + + +#endif // UTILS_OPTIONAL_H +