mirror of
https://invent.kde.org/plasma/plasma-desktop.git
synced 2026-11-03 14:49:44 -09:00
Due to changes in KDesktopFile, namely https://invent.kde.org/frameworks/kconfig/-/merge_requests/430 , we can end up in situation where we can't locate the template file, since we're searching for it from user files. Instead, locate the absolute filepath for the template in addAction and use it directly. BUG: 518317
216 lines
7.3 KiB
C++
216 lines
7.3 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2009 Ben Cooksley <ben@eclipse.endoftheinternet.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "SolidActions.h"
|
|
#include "ActionItem.h"
|
|
|
|
#include <KAboutData>
|
|
#include <KBuildSycocaProgressDialog>
|
|
#include <KConfigGroup>
|
|
#include <KDesktopFile>
|
|
#include <KMessageBox>
|
|
#include <KPluginFactory>
|
|
#include <KStandardGuiItem>
|
|
|
|
#include <KIO/Global>
|
|
|
|
#include <QComboBox>
|
|
#include <QDebug>
|
|
#include <QPushButton>
|
|
|
|
#include <Solid/DeviceInterface>
|
|
#include <Solid/Predicate>
|
|
|
|
K_PLUGIN_CLASS_WITH_JSON(SolidActions, "kcm_solid_actions.json")
|
|
|
|
SolidActions::SolidActions(QObject *parent, const KPluginMetaData &data)
|
|
: KCModule(parent, data)
|
|
{
|
|
setButtons(KCModule::Help);
|
|
|
|
// Prepare main display dialog
|
|
actionModel = new ActionModel(this);
|
|
mainUi.setupUi(widget());
|
|
mainUi.TvActions->setModel(actionModel);
|
|
mainUi.TvActions->setHeaderHidden(true);
|
|
mainUi.TvActions->setRootIsDecorated(false);
|
|
mainUi.TvActions->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
KStandardGuiItem::assign(mainUi.PbAddAction, KStandardGuiItem::Add);
|
|
mainUi.PbEditAction->setIcon(QIcon::fromTheme(QStringLiteral("document-edit")));
|
|
|
|
connect(mainUi.PbAddAction, &QPushButton::clicked, this, &SolidActions::slotShowAddDialog);
|
|
connect(mainUi.PbEditAction, &QPushButton::clicked, this, &SolidActions::editAction);
|
|
connect(mainUi.PbDeleteAction, &QPushButton::clicked, this, &SolidActions::deleteAction);
|
|
connect(mainUi.TvActions->selectionModel(), &QItemSelectionModel::currentChanged, this, &SolidActions::toggleEditDelete);
|
|
connect(mainUi.TvActions, &QTreeView::doubleClicked, this, &SolidActions::editAction);
|
|
|
|
// Prepare + connect up with Edit dialog
|
|
editUi = new ActionEditor(widget());
|
|
connect(editUi, &ActionEditor::accepted, this, &SolidActions::acceptActionChanges);
|
|
|
|
// Prepare + connect up add action dialog
|
|
addDialog = new QDialog(widget());
|
|
addUi.setupUi(addDialog);
|
|
addDialog->resize(QSize(300, 100)); // Set a sensible default size
|
|
|
|
slotTextChanged(addUi.LeActionName->text());
|
|
connect(addUi.LeActionName, &QLineEdit::textChanged, this, &SolidActions::slotTextChanged);
|
|
connect(addUi.buttonBox, &QDialogButtonBox::accepted, this, &SolidActions::addAction);
|
|
connect(addUi.buttonBox, &QDialogButtonBox::rejected, addDialog, &QDialog::reject);
|
|
}
|
|
|
|
void SolidActions::slotShowAddDialog()
|
|
{
|
|
addDialog->show();
|
|
addUi.LeActionName->setFocus();
|
|
addUi.LeActionName->clear();
|
|
}
|
|
|
|
void SolidActions::slotTextChanged(const QString &text)
|
|
{
|
|
addUi.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
|
|
}
|
|
|
|
void SolidActions::load()
|
|
{
|
|
fillActionsList();
|
|
}
|
|
|
|
void SolidActions::defaults()
|
|
{
|
|
}
|
|
|
|
void SolidActions::save()
|
|
{
|
|
}
|
|
|
|
void SolidActions::addAction()
|
|
{
|
|
const QString enteredName = addUi.LeActionName->text();
|
|
constexpr auto resourceType = QStandardPaths::GenericDataLocation;
|
|
const auto absolutePath = QStandardPaths::locate(resourceType, QStringLiteral("kcmsolidactions/solid-action-template.desktop"));
|
|
KDesktopFile templateDesktop(resourceType, absolutePath); // Lets get the template
|
|
|
|
// Lets get a desktop file
|
|
QString internalName = enteredName; // copy the name the user entered -> we will be making mods
|
|
internalName.replace(QChar(' '), QChar('-'), Qt::CaseSensitive); // replace spaces with dashes
|
|
internalName = KIO::encodeFileName(internalName);
|
|
|
|
QString filePath = QStandardPaths::writableLocation(resourceType) + "/solid/actions/"; // Get the location on disk for "data"
|
|
if (!QDir().exists(filePath)) {
|
|
QDir().mkpath(filePath);
|
|
}
|
|
filePath += internalName + ".desktop";
|
|
|
|
// Fill in an initial template
|
|
KDesktopFile *newDesktop = templateDesktop.copyTo(filePath);
|
|
newDesktop->actionGroup(QStringLiteral("open")).writeEntry("Name", enteredName); // ditto
|
|
delete newDesktop; // Force file to be written
|
|
|
|
// Prepare to open the editDialog
|
|
fillActionsList();
|
|
const QList<ActionItem *> actionList = actionModel->actionList();
|
|
QModelIndex newAction;
|
|
for (ActionItem *newItem : actionList) { // Lets find our new action
|
|
if (newItem->desktopMasterPath == filePath) {
|
|
const int position = actionList.indexOf(newItem);
|
|
newAction = actionModel->index(position, 0); // Grab it
|
|
break;
|
|
}
|
|
}
|
|
|
|
mainUi.TvActions->setCurrentIndex(newAction); // Set it as currently active
|
|
addDialog->hide();
|
|
editAction(); // Open the edit dialog
|
|
}
|
|
|
|
void SolidActions::editAction()
|
|
{
|
|
ActionItem *selectedItem = selectedAction();
|
|
if (!selectedItem) {
|
|
return;
|
|
}
|
|
|
|
// We should error out here if we have to
|
|
if (!selectedItem->predicate().isValid()) {
|
|
KMessageBox::error(widget(), i18n("It appears that the predicate for this action is not valid."), i18n("Error Parsing Device Conditions"));
|
|
return;
|
|
}
|
|
|
|
// Display us!
|
|
editUi->setActionToEdit(selectedItem);
|
|
editUi->setWindowIcon(widget()->windowIcon());
|
|
editUi->show();
|
|
}
|
|
|
|
void SolidActions::deleteAction()
|
|
{
|
|
ActionItem *action = selectedAction();
|
|
if (action->isUserSupplied()) { // Is the action user supplied?
|
|
QFile::remove(action->desktopMasterPath); // Remove the main desktop file then
|
|
}
|
|
QFile::remove(action->desktopWritePath); // Remove the modified desktop file now
|
|
fillActionsList(); // Update the list of actions
|
|
}
|
|
|
|
ActionItem *SolidActions::selectedAction() const
|
|
{
|
|
QModelIndex action = mainUi.TvActions->currentIndex();
|
|
ActionItem *actionItem = actionModel->data(action, Qt::UserRole).value<ActionItem *>();
|
|
return actionItem;
|
|
}
|
|
|
|
void SolidActions::fillActionsList()
|
|
{
|
|
mainUi.TvActions->clearSelection();
|
|
actionModel->buildActionList();
|
|
mainUi.TvActions->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
|
mainUi.TvActions->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
|
toggleEditDelete();
|
|
}
|
|
|
|
void SolidActions::acceptActionChanges()
|
|
{
|
|
// Re-read the actions list to ensure changes are reflected
|
|
KBuildSycocaProgressDialog::rebuildKSycoca(widget());
|
|
fillActionsList();
|
|
}
|
|
|
|
void SolidActions::toggleEditDelete()
|
|
{
|
|
bool toggle = true;
|
|
|
|
if (!mainUi.TvActions->currentIndex().isValid()) { // Is an action selected?
|
|
mainUi.PbDeleteAction->setText(i18n("No Action Selected")); // Set a friendly disabled text
|
|
mainUi.PbDeleteAction->setIcon(QIcon());
|
|
toggle = false;
|
|
}
|
|
|
|
mainUi.PbEditAction->setEnabled(toggle); // Change them to the new state
|
|
mainUi.PbDeleteAction->setEnabled(toggle); // Ditto
|
|
|
|
if (!toggle) {
|
|
return;
|
|
}
|
|
|
|
// What functionality do we need to change?
|
|
if (selectedAction()->isUserSupplied()) {
|
|
// We are able to directly delete it, enable full delete functionality
|
|
KStandardGuiItem::assign(mainUi.PbDeleteAction, KStandardGuiItem::Remove);
|
|
} else if (QFile::exists(selectedAction()->desktopWritePath)) { // Does the write file exist?
|
|
// We are able to revert, lets show it
|
|
KStandardGuiItem::assign(mainUi.PbDeleteAction, KStandardGuiItem::Discard);
|
|
} else {
|
|
// We cannot do anything then, disable delete functionality
|
|
mainUi.PbDeleteAction->setText(i18n("Cannot be deleted"));
|
|
mainUi.PbDeleteAction->setIcon(QIcon());
|
|
mainUi.PbDeleteAction->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
#include "SolidActions.moc"
|
|
|
|
#include "moc_SolidActions.cpp"
|