2022-04-02 18:24:21 +05:00

282 lines
11 KiB
C++

/*
SPDX-FileCopyrightText: 2015-2016 Ivan Cukic <ivan.cukic@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "dialog.h"
#include <QAction>
#include <QDialogButtonBox>
#include <QGuiApplication>
#include <QPushButton>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickView>
#include <QQuickWidget>
#include <QString>
#include <QTabWidget>
#include <QTimer>
#include <QVBoxLayout>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <KMessageWidget>
#include "../kactivities-kcm-features.h"
#include "features_interface.h"
#include "kactivities/controller.h"
#include "kactivities/info.h"
#include "common/dbus/common.h"
#include "utils/continue_with.h"
#include "utils/d_ptr_implementation.h"
class Dialog::Private
{
public:
Private(Dialog *parent)
: q(parent)
, activityName(QStringLiteral("activityName"))
, activityDescription(QStringLiteral("activityDescription"))
, activityIcon(QStringLiteral("activityIcon"))
, activityWallpaper(QStringLiteral("activityWallpaper"))
, activityIsPrivate(true)
, activityShortcut(QStringLiteral("activityShortcut"))
, features(new org::kde::ActivityManager::Features(QStringLiteral(KAMD_DBUS_SERVICE),
QStringLiteral(KAMD_DBUS_FEATURES_PATH),
QDBusConnection::sessionBus(),
q))
{
}
Dialog *const q;
QVBoxLayout *layout;
QTabWidget *tabs;
QQuickWidget *tabGeneral;
KMessageWidget *message;
QDialogButtonBox *buttons;
QString defaultOKText;
QQuickWidget *createTab(const QString &title, const QString &file)
{
auto view = new QQuickWidget();
view->setResizeMode(QQuickWidget::SizeRootObjectToView);
view->setClearColor(QGuiApplication::palette().window().color());
view->rootContext()->setContextProperty(QStringLiteral("dialog"), q);
view->rootContext()->setContextObject(new KLocalizedContext(view));
const QString sourceFile = QStringLiteral(KAMD_KCM_DATADIR) + "qml/activityDialog/" + file;
if (QFile::exists(sourceFile)) {
view->setSource(QUrl::fromLocalFile(sourceFile));
tabs->addTab(view, title);
} else {
message->setText(i18n("Error loading the QML files. Check your installation.\nMissing %1", sourceFile));
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::Controller activities;
org::kde::ActivityManager::Features *features;
};
void Dialog::showDialog(const QString &id)
{
static Dialog *dialog = nullptr;
// If we use the regular singleton here (static value instead of static ptr),
// we will crash on exit because of Qt...
if (!dialog) {
dialog = new Dialog();
}
dialog->init(id);
dialog->show();
}
Dialog::Dialog(QObject *parent)
: QDialog()
, d(this)
{
resize(550, 400);
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->message->setWordWrap(true);
d->layout->addWidget(d->message);
// Tabs
d->tabs = new QTabWidget(this);
d->layout->addWidget(d->tabs);
d->tabGeneral = d->createTab(i18n("General"), QStringLiteral("GeneralTab.qml"));
// Buttons
d->buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
d->layout->QLayout::addWidget(d->buttons);
connect(d->buttons->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &Dialog::save);
connect(d->buttons, &QDialogButtonBox::rejected, this, &Dialog::close);
d->defaultOKText = d->buttons->button(QDialogButtonBox::Ok)->text();
}
void Dialog::init(const QString &activityId)
{
setWindowTitle(activityId.isEmpty() ? i18nc("@title:window", "Create a New Activity") //
: i18nc("@title:window", "Activity Settings"));
d->buttons->button(QDialogButtonBox::Ok)->setText(activityId.isEmpty() ? i18nc("@action:button", "Create") : d->defaultOKText);
d->tabs->setCurrentIndex(0);
setActivityId(activityId);
setActivityName(QString());
setActivityDescription(QString());
setActivityIcon(QStringLiteral("activities"));
setActivityIsPrivate(false);
setActivityShortcut(QKeySequence());
if (!activityId.isEmpty()) {
KActivities::Info activityInfo(activityId);
setActivityName(activityInfo.name());
setActivityDescription(activityInfo.description());
setActivityIcon(activityInfo.icon());
// finding the key shortcut
const auto shortcuts = KGlobalAccel::self()->globalShortcut(QStringLiteral("ActivityManager"), QStringLiteral("switch-to-activity-") + activityId);
setActivityShortcut(shortcuts.isEmpty() ? QKeySequence() : shortcuts.first());
// is private?
auto result = d->features->GetValue(QStringLiteral("org.kde.ActivityManager.Resources.Scoring/isOTR/") + activityId);
auto watcher = new QDBusPendingCallWatcher(result, this);
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [&](QDBusPendingCallWatcher *watcher) mutable {
QDBusPendingReply<QDBusVariant> reply = *watcher;
setActivityIsPrivate(reply.value().variant().toBool());
watcher->deleteLater();
});
}
}
Dialog::~Dialog()
{
}
void Dialog::showEvent(QShowEvent *event)
{
Q_UNUSED(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<Type>(); \
} \
\
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(General, QKeySequence, const QKeySequence &, Shortcut)
IMPLEMENT_PROPERTY(General, 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<QString> &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(nullptr);
action.setProperty("isConfigurationAction", true);
action.setProperty("componentName", QStringLiteral("ActivityManager"));
action.setObjectName(QStringLiteral("switch-to-activity-") + activityId);
KGlobalAccel::self()->setShortcut(&action, {activityShortcut()}, KGlobalAccel::NoAutoloading);
// is private?
d->features->SetValue(QStringLiteral("org.kde.ActivityManager.Resources.Scoring/isOTR/") + activityId, QDBusVariant(activityIsPrivate()));
close();
}