File indexing completed on 2024-05-12 17:07:26
0001 /* 0002 SPDX-FileCopyrightText: 2009 Ben Cooksley <ben@eclipse.endoftheinternet.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "SolidActions.h" 0008 #include "ActionItem.h" 0009 0010 #include <KAboutData> 0011 #include <KBuildSycocaProgressDialog> 0012 #include <KConfigGroup> 0013 #include <KDesktopFile> 0014 #include <KMessageBox> 0015 #include <KPluginFactory> 0016 #include <KStandardGuiItem> 0017 0018 #include <KIO/Global> 0019 0020 #include <QComboBox> 0021 #include <QDebug> 0022 #include <QPushButton> 0023 0024 #include <Solid/DeviceInterface> 0025 #include <Solid/Predicate> 0026 0027 K_PLUGIN_CLASS_WITH_JSON(SolidActions, "kcm_solid_actions.json") 0028 0029 SolidActions::SolidActions(QWidget *parent, const QVariantList &) 0030 : KCModule(parent) 0031 { 0032 KAboutData *about = new KAboutData(QStringLiteral("Device Actions"), 0033 i18n("Solid Device Actions Editor"), 0034 QStringLiteral("1.2"), 0035 i18n("Solid Device Actions Control Panel Module"), 0036 KAboutLicense::GPL, 0037 i18n("(c) 2009, 2014 Solid Device Actions team")); 0038 about->addAuthor(i18n("Ben Cooksley"), i18n("Maintainer"), QStringLiteral("ben@eclipse.endoftheinternet.org")); 0039 about->addCredit(QStringLiteral("Lukáš Tinkl"), i18n("Port to Plasma 5"), QStringLiteral("ltinkl@redhat.com")); 0040 setAboutData(about); 0041 setButtons(KCModule::Help); 0042 0043 // Prepare main display dialog 0044 actionModel = new ActionModel(this); 0045 mainUi.setupUi(this); 0046 mainUi.TvActions->setModel(actionModel); 0047 mainUi.TvActions->setHeaderHidden(true); 0048 mainUi.TvActions->setRootIsDecorated(false); 0049 mainUi.TvActions->setSelectionMode(QAbstractItemView::SingleSelection); 0050 KStandardGuiItem::assign(mainUi.PbAddAction, KStandardGuiItem::Add); 0051 mainUi.PbEditAction->setIcon(QIcon::fromTheme(QStringLiteral("document-edit"))); 0052 0053 connect(mainUi.PbAddAction, &QPushButton::clicked, this, &SolidActions::slotShowAddDialog); 0054 connect(mainUi.PbEditAction, &QPushButton::clicked, this, &SolidActions::editAction); 0055 connect(mainUi.PbDeleteAction, &QPushButton::clicked, this, &SolidActions::deleteAction); 0056 connect(mainUi.TvActions->selectionModel(), &QItemSelectionModel::currentChanged, this, &SolidActions::toggleEditDelete); 0057 connect(mainUi.TvActions, &QTreeView::doubleClicked, this, &SolidActions::editAction); 0058 0059 // Prepare + connect up with Edit dialog 0060 editUi = new ActionEditor(this); 0061 connect(editUi, &ActionEditor::accepted, this, &SolidActions::acceptActionChanges); 0062 0063 // Prepare + connect up add action dialog 0064 addDialog = new QDialog(this); 0065 addUi.setupUi(addDialog); 0066 addDialog->resize(QSize(300, 100)); // Set a sensible default size 0067 0068 slotTextChanged(addUi.LeActionName->text()); 0069 connect(addUi.LeActionName, &QLineEdit::textChanged, this, &SolidActions::slotTextChanged); 0070 connect(addUi.buttonBox, &QDialogButtonBox::accepted, this, &SolidActions::addAction); 0071 connect(addUi.buttonBox, &QDialogButtonBox::rejected, addDialog, &QDialog::reject); 0072 } 0073 0074 SolidActions::~SolidActions() 0075 { 0076 delete editUi; 0077 delete actionModel; 0078 } 0079 0080 void SolidActions::slotShowAddDialog() 0081 { 0082 addDialog->show(); 0083 addUi.LeActionName->setFocus(); 0084 addUi.LeActionName->clear(); 0085 } 0086 0087 void SolidActions::slotTextChanged(const QString &text) 0088 { 0089 addUi.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); 0090 } 0091 0092 void SolidActions::load() 0093 { 0094 fillActionsList(); 0095 } 0096 0097 void SolidActions::defaults() 0098 { 0099 } 0100 0101 void SolidActions::save() 0102 { 0103 } 0104 0105 void SolidActions::addAction() 0106 { 0107 const QString enteredName = addUi.LeActionName->text(); 0108 KDesktopFile templateDesktop(QStandardPaths::GenericDataLocation, QStringLiteral("kcmsolidactions/solid-action-template.desktop")); // Lets get the template 0109 0110 // Lets get a desktop file 0111 QString internalName = enteredName; // copy the name the user entered -> we will be making mods 0112 internalName.replace(QChar(' '), QChar('-'), Qt::CaseSensitive); // replace spaces with dashes 0113 internalName = KIO::encodeFileName(internalName); 0114 0115 QString filePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/solid/actions/"; // Get the location on disk for "data" 0116 if (!QDir().exists(filePath)) { 0117 QDir().mkpath(filePath); 0118 } 0119 filePath += internalName + ".desktop"; 0120 0121 // Fill in an initial template 0122 KDesktopFile *newDesktop = templateDesktop.copyTo(filePath); 0123 newDesktop->actionGroup(QStringLiteral("open")).writeEntry("Name", enteredName); // ditto 0124 delete newDesktop; // Force file to be written 0125 0126 // Prepare to open the editDialog 0127 fillActionsList(); 0128 const QList<ActionItem *> actionList = actionModel->actionList(); 0129 QModelIndex newAction; 0130 for (ActionItem *newItem : actionList) { // Lets find our new action 0131 if (newItem->desktopMasterPath == filePath) { 0132 const int position = actionList.indexOf(newItem); 0133 newAction = actionModel->index(position, 0); // Grab it 0134 break; 0135 } 0136 } 0137 0138 mainUi.TvActions->setCurrentIndex(newAction); // Set it as currently active 0139 addDialog->hide(); 0140 editAction(); // Open the edit dialog 0141 } 0142 0143 void SolidActions::editAction() 0144 { 0145 ActionItem *selectedItem = selectedAction(); 0146 if (!selectedItem) { 0147 return; 0148 } 0149 0150 // We should error out here if we have to 0151 if (!selectedItem->predicate().isValid()) { 0152 KMessageBox::error(this, i18n("It appears that the predicate for this action is not valid."), i18n("Error Parsing Device Conditions")); 0153 return; 0154 } 0155 0156 // Display us! 0157 editUi->setActionToEdit(selectedItem); 0158 editUi->setWindowIcon(windowIcon()); 0159 editUi->show(); 0160 } 0161 0162 void SolidActions::deleteAction() 0163 { 0164 ActionItem *action = selectedAction(); 0165 if (action->isUserSupplied()) { // Is the action user supplied? 0166 QFile::remove(action->desktopMasterPath); // Remove the main desktop file then 0167 } 0168 QFile::remove(action->desktopWritePath); // Remove the modified desktop file now 0169 fillActionsList(); // Update the list of actions 0170 } 0171 0172 ActionItem *SolidActions::selectedAction() const 0173 { 0174 QModelIndex action = mainUi.TvActions->currentIndex(); 0175 ActionItem *actionItem = actionModel->data(action, Qt::UserRole).value<ActionItem *>(); 0176 return actionItem; 0177 } 0178 0179 void SolidActions::fillActionsList() 0180 { 0181 mainUi.TvActions->clearSelection(); 0182 actionModel->buildActionList(); 0183 mainUi.TvActions->header()->setSectionResizeMode(0, QHeaderView::Stretch); 0184 mainUi.TvActions->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); 0185 toggleEditDelete(); 0186 } 0187 0188 void SolidActions::acceptActionChanges() 0189 { 0190 // Re-read the actions list to ensure changes are reflected 0191 KBuildSycocaProgressDialog::rebuildKSycoca(this); 0192 fillActionsList(); 0193 } 0194 0195 void SolidActions::toggleEditDelete() 0196 { 0197 bool toggle = true; 0198 0199 if (!mainUi.TvActions->currentIndex().isValid()) { // Is an action selected? 0200 mainUi.PbDeleteAction->setText(i18n("No Action Selected")); // Set a friendly disabled text 0201 mainUi.PbDeleteAction->setIcon(QIcon()); 0202 toggle = false; 0203 } 0204 0205 mainUi.PbEditAction->setEnabled(toggle); // Change them to the new state 0206 mainUi.PbDeleteAction->setEnabled(toggle); // Ditto 0207 0208 if (!toggle) { 0209 return; 0210 } 0211 0212 // What functionality do we need to change? 0213 if (selectedAction()->isUserSupplied()) { 0214 // We are able to directly delete it, enable full delete functionality 0215 KStandardGuiItem::assign(mainUi.PbDeleteAction, KStandardGuiItem::Remove); 0216 } else if (QFile::exists(selectedAction()->desktopWritePath)) { // Does the write file exist? 0217 // We are able to revert, lets show it 0218 KStandardGuiItem::assign(mainUi.PbDeleteAction, KStandardGuiItem::Discard); 0219 } else { 0220 // We cannot do anything then, disable delete functionality 0221 mainUi.PbDeleteAction->setText(i18n("Cannot be deleted")); 0222 mainUi.PbDeleteAction->setIcon(QIcon()); 0223 mainUi.PbDeleteAction->setEnabled(false); 0224 } 0225 } 0226 0227 #include "SolidActions.moc"