File indexing completed on 2025-05-04 04:51:07

0001 /*
0002    SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "viewerpluginexternalconfigurewidget.h"
0008 #include "externalscriptplugin_debug.h"
0009 #include "viewerpluginexternaleditdialog.h"
0010 #include <KConfigGroup>
0011 #include <KDesktopFile>
0012 #include <KLocalizedString>
0013 #include <KMessageBox>
0014 #include <QFile>
0015 #include <QFileInfo>
0016 #include <QLabel>
0017 #include <QListWidget>
0018 #include <QPointer>
0019 #include <QPushButton>
0020 #include <QStandardPaths>
0021 #include <QVBoxLayout>
0022 
0023 class ViewerPluginExternalScriptItem : public QListWidgetItem
0024 {
0025 public:
0026     ViewerPluginExternalScriptItem(QListWidget *parent);
0027 
0028     void setScriptInfo(const ViewerPluginExternalScriptInfo &scriptInfo);
0029     [[nodiscard]] ViewerPluginExternalScriptInfo scriptInfo() const;
0030 
0031 private:
0032     ViewerPluginExternalScriptInfo mScriptInfo;
0033 };
0034 
0035 ViewerPluginExternalScriptItem::ViewerPluginExternalScriptItem(QListWidget *parent)
0036     : QListWidgetItem(parent)
0037 {
0038 }
0039 
0040 void ViewerPluginExternalScriptItem::setScriptInfo(const ViewerPluginExternalScriptInfo &scriptInfo)
0041 {
0042     mScriptInfo = scriptInfo;
0043     setText(mScriptInfo.name());
0044     QString commandLine = mScriptInfo.executable();
0045     if (!mScriptInfo.commandLine().isEmpty()) {
0046         commandLine += QLatin1Char(' ') + mScriptInfo.commandLine();
0047     }
0048     setToolTip(mScriptInfo.description() + QStringLiteral(" (%1)").arg(commandLine));
0049 }
0050 
0051 ViewerPluginExternalScriptInfo ViewerPluginExternalScriptItem::scriptInfo() const
0052 {
0053     return mScriptInfo;
0054 }
0055 
0056 ViewerPluginExternalConfigureWidget::ViewerPluginExternalConfigureWidget(QWidget *parent)
0057     : QWidget(parent)
0058     , mListExternal(new QListWidget(this))
0059     , mAddScript(new QPushButton(i18n("Add Script..."), this))
0060     , mRemoveScript(new QPushButton(i18n("Remove Script"), this))
0061     , mModifyScript(new QPushButton(i18n("Modify Script..."), this))
0062 {
0063     auto mainLayout = new QVBoxLayout(this);
0064     mainLayout->setObjectName(QLatin1StringView("layout"));
0065     mainLayout->setContentsMargins({});
0066 
0067     auto lab = new QLabel(i18n("External Script:"), this);
0068     lab->setObjectName(QLatin1StringView("lab"));
0069     mainLayout->addWidget(lab);
0070 
0071     auto listLayout = new QHBoxLayout;
0072     mainLayout->addLayout(listLayout);
0073 
0074     mListExternal->setObjectName(QLatin1StringView("listexternal"));
0075     mListExternal->setSelectionMode(QAbstractItemView::SingleSelection);
0076     mListExternal->setAlternatingRowColors(true);
0077     listLayout->addWidget(mListExternal);
0078     connect(mListExternal, &QListWidget::itemSelectionChanged, this, &ViewerPluginExternalConfigureWidget::updateButtons);
0079     connect(mListExternal, &QListWidget::itemDoubleClicked, this, &ViewerPluginExternalConfigureWidget::slotDoubleClicked);
0080 
0081     auto buttonLayout = new QVBoxLayout;
0082     listLayout->addLayout(buttonLayout);
0083 
0084     connect(mAddScript, &QPushButton::clicked, this, &ViewerPluginExternalConfigureWidget::slotAddScript);
0085     mAddScript->setObjectName(QLatin1StringView("addscript"));
0086     buttonLayout->addWidget(mAddScript);
0087 
0088     connect(mModifyScript, &QPushButton::clicked, this, &ViewerPluginExternalConfigureWidget::slotModifyScript);
0089     mModifyScript->setObjectName(QLatin1StringView("modifyscript"));
0090     buttonLayout->addWidget(mModifyScript);
0091 
0092     connect(mRemoveScript, &QPushButton::clicked, this, &ViewerPluginExternalConfigureWidget::slotRemoveScript);
0093     mRemoveScript->setObjectName(QLatin1StringView("removescript"));
0094     buttonLayout->addWidget(mRemoveScript);
0095     buttonLayout->addStretch(1);
0096     updateButtons();
0097 }
0098 
0099 ViewerPluginExternalConfigureWidget::~ViewerPluginExternalConfigureWidget() = default;
0100 
0101 void ViewerPluginExternalConfigureWidget::slotRemoveScript()
0102 {
0103     QListWidgetItem *item = mListExternal->currentItem();
0104     if (item) {
0105         const int answer = KMessageBox::warningTwoActions(this,
0106                                                           i18n("Do you want to remove this script \"%1\"?", item->text()),
0107                                                           i18n("Remove External Script"),
0108                                                           KStandardGuiItem::remove(),
0109                                                           KStandardGuiItem::cancel());
0110         if (answer == KMessageBox::ButtonCode::PrimaryAction) {
0111             auto scriptItem = static_cast<ViewerPluginExternalScriptItem *>(item);
0112             mFilesToRemove.append(scriptItem->scriptInfo().fileName());
0113             delete mListExternal->takeItem(mListExternal->currentRow());
0114         }
0115     }
0116 }
0117 
0118 void ViewerPluginExternalConfigureWidget::slotModifyScript()
0119 {
0120     QListWidgetItem *item = mListExternal->currentItem();
0121     if (item) {
0122         modifyScript(item);
0123     }
0124 }
0125 
0126 void ViewerPluginExternalConfigureWidget::slotAddScript()
0127 {
0128     QStringList existingNames;
0129     const int numberOfElement(mListExternal->count());
0130     for (int i = 0; i < numberOfElement; ++i) {
0131         auto item = static_cast<ViewerPluginExternalScriptItem *>(mListExternal->item(i));
0132         existingNames << item->text();
0133     }
0134     QPointer<ViewerPluginExternalEditDialog> dlg = new ViewerPluginExternalEditDialog(this);
0135     dlg->setExistingsNames(existingNames);
0136     if (dlg->exec()) {
0137         auto item = new ViewerPluginExternalScriptItem(mListExternal);
0138         item->setScriptInfo(dlg->scriptInfo());
0139     }
0140     delete dlg;
0141 }
0142 
0143 void ViewerPluginExternalConfigureWidget::load()
0144 {
0145     ViewerPluginExternalScriptsLoadJob job;
0146     const QStringList lst =
0147         QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("messageviewerplugins/"), QStandardPaths::LocateDirectory);
0148     job.setExternalScriptsDirectories(lst);
0149     job.start();
0150     const QList<ViewerPluginExternalScriptInfo> scriptInfos = job.scriptInfos();
0151     fillScriptInfo(scriptInfos);
0152 }
0153 
0154 void ViewerPluginExternalConfigureWidget::fillScriptInfo(const QList<ViewerPluginExternalScriptInfo> &scriptInfos)
0155 {
0156     for (const ViewerPluginExternalScriptInfo &script : scriptInfos) {
0157         auto item = new ViewerPluginExternalScriptItem(mListExternal);
0158         item->setScriptInfo(script);
0159     }
0160 }
0161 
0162 void ViewerPluginExternalConfigureWidget::save()
0163 {
0164     for (const QString &path : std::as_const(mFilesToRemove)) {
0165         QFile f(path);
0166         if (!f.remove()) {
0167             qCWarning(EXTERNALSCRIPTPLUGIN_LOG) << " Impossible to delete " << path;
0168         }
0169     }
0170     const QString writablePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/messageviewerplugins/");
0171     const int numberOfElement(mListExternal->count());
0172     for (int i = 0; i < numberOfElement; ++i) {
0173         auto item = static_cast<ViewerPluginExternalScriptItem *>(mListExternal->item(i));
0174         const ViewerPluginExternalScriptInfo &scriptInfo = item->scriptInfo();
0175         QString filenamepath = scriptInfo.fileName();
0176         if (filenamepath.isEmpty()) {
0177             filenamepath = writablePath + QStringLiteral("%1.desktop").arg(scriptInfo.name());
0178             int fileIndex = 1;
0179             while (QFileInfo::exists(filenamepath)) {
0180                 filenamepath = writablePath + QStringLiteral("%1-%2.desktop").arg(scriptInfo.name()).arg(fileIndex);
0181                 fileIndex++;
0182             }
0183         }
0184         KDesktopFile desktopFile(filenamepath);
0185         desktopFile.desktopGroup().writeEntry(QStringLiteral("Name"), scriptInfo.name());
0186         desktopFile.desktopGroup().writeEntry(QStringLiteral("Description"), scriptInfo.description());
0187         desktopFile.desktopGroup().writeEntry(QStringLiteral("Executable"), scriptInfo.executable());
0188         desktopFile.desktopGroup().writeEntry(QStringLiteral("CommandLine"), scriptInfo.commandLine());
0189         desktopFile.desktopGroup().sync();
0190     }
0191 }
0192 
0193 void ViewerPluginExternalConfigureWidget::updateButtons()
0194 {
0195     QListWidgetItem *item = mListExternal->currentItem();
0196     if (item) {
0197         auto scriptItem = static_cast<ViewerPluginExternalScriptItem *>(item);
0198         const bool isReadOnly = scriptItem->scriptInfo().isReadOnly();
0199         mRemoveScript->setEnabled(!isReadOnly);
0200         mModifyScript->setEnabled(!isReadOnly);
0201     } else {
0202         mRemoveScript->setEnabled(false);
0203         mModifyScript->setEnabled(false);
0204     }
0205 }
0206 
0207 void ViewerPluginExternalConfigureWidget::slotDoubleClicked(QListWidgetItem *item)
0208 {
0209     if (item) {
0210         modifyScript(item);
0211     }
0212 }
0213 
0214 void ViewerPluginExternalConfigureWidget::modifyScript(QListWidgetItem *item)
0215 {
0216     auto scriptItem = static_cast<ViewerPluginExternalScriptItem *>(item);
0217     if (!scriptItem->scriptInfo().isReadOnly()) {
0218         QPointer<ViewerPluginExternalEditDialog> dlg = new ViewerPluginExternalEditDialog(this);
0219         dlg->setScriptInfo(scriptItem->scriptInfo());
0220         if (dlg->exec()) {
0221             scriptItem->setScriptInfo(dlg->scriptInfo());
0222         }
0223         delete dlg;
0224     }
0225 }
0226 
0227 #include "moc_viewerpluginexternalconfigurewidget.cpp"