File indexing completed on 2024-05-12 04:42:03

0001 /*
0002     SPDX-FileCopyrightText: 2015 Gregor Mi <codestruct@posteo.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "kmoretoolspresets.h"
0008 #include "kmoretools_debug.h"
0009 #include "kmoretoolspresets_p.h"
0010 #include <QFile>
0011 #include <QHash>
0012 
0013 #include "kmoretools.h"
0014 
0015 #define _ QStringLiteral
0016 
0017 class KmtServiceInfo
0018 {
0019 public:
0020     KmtServiceInfo(const QString &desktopEntryName, const QString &homepageUrl, int maxUrlArgCount, const QString &appstreamId)
0021         : desktopEntryName(desktopEntryName)
0022         , homepageUrl(homepageUrl)
0023         , maxUrlArgCount(maxUrlArgCount)
0024         , appstreamId(appstreamId)
0025     {
0026     }
0027 
0028 public:
0029     QString desktopEntryName;
0030     QString homepageUrl;
0031     int maxUrlArgCount;
0032     QString appstreamId;
0033 };
0034 
0035 namespace KMoreToolsNamespace
0036 {
0037 class OSDetection
0038 {
0039 public:
0040     static bool is_LinuxOSFamily_Debian()
0041     {
0042         return QFile::exists(QLatin1String("/etc/debian_version"));
0043     }
0044 };
0045 }
0046 
0047 //
0048 // todo later: add a property "maturity" with values "stable" > "new" > "incubating" or similar
0049 //
0050 KMoreToolsService *KMoreToolsPresets::registerServiceByDesktopEntryName(KMoreTools *kmt, const QString &desktopEntryName)
0051 {
0052     static QHash<QString, KmtServiceInfo> dict;
0053     // clang-format off
0054 #define ADD_ENTRY(desktopEntryName, maxUrlArgCount, homepageUrl, appstreamUrl) dict.insert(desktopEntryName, KmtServiceInfo(desktopEntryName, homepageUrl, maxUrlArgCount, appstreamUrl));
0055 
0056     //
0057     // definitions begin (sorted alphabetically):
0058     //                                              .------ If one gives more URL arguments as
0059     //                                              |       specified here the program will not work.
0060     //                                              |       Note, that there are some desktop files where _too few_
0061     //                                              |       arguments also lead to errors. Watch the console
0062     //                                              v       output for messages from the program.
0063     //
0064     ADD_ENTRY(QStringLiteral("angrysearch"),                        0, QStringLiteral("https://github.com/DoTheEvo/ANGRYsearch"), QString());
0065     ADD_ENTRY(QStringLiteral("com.uploadedlobster.peek"),           0, QStringLiteral("https://github.com/phw/peek"), QStringLiteral("com.uploadedlobster.peek.desktop")); // easy to use screen recorder, creates gif
0066     ADD_ENTRY(QStringLiteral("catfish"),                            1, QStringLiteral("http://www.twotoasts.de/index.php/catfish/"), QStringLiteral("catfish"));
0067     ADD_ENTRY(QStringLiteral("ding"),                               0, QStringLiteral("https://www-user.tu-chemnitz.de/~fri/ding/"), QString()); // Offline dict, Online: https://dict.tu-chemnitz.de/dings.cgi
0068     ADD_ENTRY(QStringLiteral("disk"),                               0, QStringLiteral("https://en.opensuse.org/YaST_Disk_Controller"), QString());
0069     ADD_ENTRY(QStringLiteral("fontinst"),                           0, QStringLiteral("https://docs.kde.org/?application=kcontrol/fontinst&branch=trunk5"), QString()); // good for previewing many fonts at once
0070     ADD_ENTRY(QStringLiteral("fontmatrix"),                         0, QStringLiteral("https://github.com/fontmatrix/fontmatrix"), QString());
0071     ADD_ENTRY(QStringLiteral("fsearch"),                            0, QStringLiteral("https://github.com/cboxdoerfer/fsearch"), QString());
0072     ADD_ENTRY(QStringLiteral("giggle"),                             1, QStringLiteral("https://wiki.gnome.org/Apps/giggle/"), QStringLiteral("giggle.desktop")); // good for searching in history
0073     ADD_ENTRY(QStringLiteral("git-cola-folder-handler"),            1, QStringLiteral("https://git-cola.github.io"), QStringLiteral("git-cola.desktop"));
0074     ADD_ENTRY(QStringLiteral("git-cola-view-history.kmt-edition"),  1, QStringLiteral("https://git-cola.github.io"), QStringLiteral("git-cola.desktop"));
0075     ADD_ENTRY(QStringLiteral("gitk.kmt-edition"),                   1, QStringLiteral("https://git-scm.com/docs/gitk"), QString());
0076     ADD_ENTRY(QStringLiteral("qgit.kmt-edition"),                   1, QStringLiteral("https://github.com/tibirna/qgit"), QString());
0077     ADD_ENTRY(QStringLiteral("gitg"),                               1, QStringLiteral("https://wiki.gnome.org/action/show/Apps/Gitg?action=show&redirect=Gitg"), QStringLiteral("gitg.desktop"));
0078     ADD_ENTRY(QStringLiteral("gnome-search-tool"),                  0, QStringLiteral("https://help.gnome.org/users/gnome-search-tool/"), QStringLiteral("gnome-search-tool.desktop")); // has good filtering options
0079     ADD_ENTRY(QStringLiteral("gucharmap"),                          0, QStringLiteral("https://wiki.gnome.org/action/show/Apps/Gucharmap"), QStringLiteral("gucharmap.desktop"));
0080     ADD_ENTRY(QStringLiteral("gparted"),                            0, QStringLiteral("https://gparted.org"), QStringLiteral("gparted.desktop"));
0081     ADD_ENTRY(QStringLiteral("htop"),                               0, QStringLiteral("https://hisham.hm/htop/"), QStringLiteral("htop.desktop"));
0082     ADD_ENTRY(QStringLiteral("hotshots"),                           1, QStringLiteral("https://sourceforge.net/projects/hotshots/"), QString());
0083     ADD_ENTRY(QStringLiteral("kaption"),                            0, QStringLiteral("https://www.linux-apps.com/content/show.php/?content=139302"), QString());
0084     ADD_ENTRY(QStringLiteral("kding"),                              0, QString(), QString()); // Offline dict; unmaintained?
0085     ADD_ENTRY(QStringLiteral("org.kde.kmousetool"),                 0, QStringLiteral("https://kde.org/applications/utilities/org.kde.kmousetool/"), QStringLiteral("org.kde.kmousetool"));
0086     ADD_ENTRY(QStringLiteral("org.gnome.clocks"),                   0, QStringLiteral("https://wiki.gnome.org/Apps/Clocks"), QStringLiteral("org.gnome.clocks.desktop"));
0087     ADD_ENTRY(QStringLiteral("org.kde.filelight"),                  1, QStringLiteral("https://kde.org/applications/utilities/org.kde.filelight/"), QStringLiteral("org.kde.filelight.desktop"));
0088     ADD_ENTRY(QStringLiteral("org.kde.kcharselect"),                0, QStringLiteral("https://kde.org/applications/utilities/org.kde.kcharselect/"), QStringLiteral("org.kde.kcharselect"));
0089     ADD_ENTRY(QStringLiteral("org.kde.kdf"),                        0, QStringLiteral("https://kde.org/applications/system/org.kde.kdf/"), QStringLiteral("org.kde.kdf"));
0090     ADD_ENTRY(QStringLiteral("org.kde.kfind"),                      1, QStringLiteral("https://kde.org/applications/utilities/org.kde.kfind/"), QStringLiteral("org.kde.kfind.desktop")); // has good filtering options
0091     ADD_ENTRY(QStringLiteral("org.kde.partitionmanager"),           0, QStringLiteral("https://kde.org/applications/system/org.kde.partitionmanager"), QStringLiteral("org.kde.partitionmanager.desktop"));
0092     ADD_ENTRY(QStringLiteral("org.kde.plasma.cuttlefish.kmt-edition"), 0, QStringLiteral("https://vizzzion.org/blog/2015/02/say-hi-to-cuttlefish/"), QStringLiteral("org.kde.plasma.cuttlefish"));
0093     ADD_ENTRY(QStringLiteral("org.kde.ksysguard"),                  0, QStringLiteral("https://userbase.kde.org/KSysGuard"), QStringLiteral("org.kde.ksysguard"));
0094     ADD_ENTRY(QStringLiteral("org.kde.ksystemlog"),                 0, QStringLiteral("https://kde.org/applications/system/org.kde.ksystemlog/"), QStringLiteral("org.kde.ksystemlog"));
0095     ADD_ENTRY(QStringLiteral("org.kde.ktimer"),                     0, QStringLiteral("https://kde.org/applications/utilities/org.kde.ktimer/"), QStringLiteral("org.kde.ktimer"));
0096     ADD_ENTRY(QStringLiteral("org.kde.spectacle"),                  0, QStringLiteral("https://kde.org/applications/utilities/org.kde.spectacle"), QStringLiteral("org.kde.spectacle.desktop"));
0097     ADD_ENTRY(QStringLiteral("simplescreenrecorder"),               0, QStringLiteral("https://www.maartenbaert.be/simplescreenrecorder/"), QStringLiteral("simplescreenrecorder.desktop"));
0098     ADD_ENTRY(QStringLiteral("com.obsproject.Studio"),              0, QStringLiteral("https://obsproject.com/"), QStringLiteral("com.obsproject.Studio"));
0099     ADD_ENTRY(QStringLiteral("vokoscreenNG"),                       0, QStringLiteral("https://github.com/vkohaupt/vokoscreenNG"), KMoreToolsNamespace::OSDetection::is_LinuxOSFamily_Debian() ? QLatin1String("de.volkoh.linuxecke.vokoscreen_ng") : QStringLiteral("com.github.vkohaupt.vokoscreenNG")); // feature-rich screen recorder
0100     ADD_ENTRY(QStringLiteral("xfce4-taskmanager"),                  0, QStringLiteral("https://goodies.xfce.org/projects/applications/xfce4-taskmanager"), QStringLiteral("xfce4-taskmanager.desktop"));
0101     //
0102     // ...definitions end
0103     //
0104 
0105 #undef ADD_ENTRY
0106     // clang-format on
0107 
0108     auto iter = dict.constFind(desktopEntryName);
0109     if (iter != dict.constEnd()) {
0110         auto kmtServiceInfo = *iter;
0111         const QString subdir = QStringLiteral("presets-kmoretools");
0112         auto serviceLocatingMode = desktopEntryName.endsWith(QLatin1String(".kmt-edition")) ? KMoreTools::ServiceLocatingMode_ByProvidedExecLine
0113                                                                                             : KMoreTools::ServiceLocatingMode_Default;
0114         auto service = kmt->registerServiceByDesktopEntryName(desktopEntryName, subdir, serviceLocatingMode);
0115         if (service) { // We might get nullptr in case of missing or broken .desktop files
0116             service->setHomepageUrl(QUrl(kmtServiceInfo.homepageUrl));
0117             service->setMaxUrlArgCount(kmtServiceInfo.maxUrlArgCount);
0118             service->setAppstreamId(kmtServiceInfo.appstreamId);
0119         }
0120         return service;
0121     } else {
0122         qCDebug(KMORETOOLS) << "KMoreToolsPresets::registerServiceByDesktopEntryName: " << desktopEntryName << "was not found. Return nullptr.";
0123         return nullptr;
0124     }
0125 }
0126 
0127 QList<KMoreToolsService *> KMoreToolsPresets::registerServicesByGroupingNames(KMoreTools *kmt, const QStringList &groupingNames)
0128 {
0129     QString firstMoreSectionDesktopEntryName;
0130     return KMoreToolsPresetsPrivate::registerServicesByGroupingNames(&firstMoreSectionDesktopEntryName, kmt, groupingNames);
0131 }
0132 
0133 QList<KMoreToolsService *>
0134 KMoreToolsPresetsPrivate::registerServicesByGroupingNames(QString *firstMoreSectionDesktopEntryName, KMoreTools *kmt, const QStringList &groupingNames)
0135 {
0136     static QHash<QString, QList<QString>> dict;
0137 
0138     // The corresponding desktop files are located here:
0139     // 'knewstuff/data/kmoretools-desktopfiles/'
0140 
0141     // Use KMoreToolsTest2::testDialogForGroupingNames to see if the settings
0142     // here are correct.
0143 
0144     // NOTE that the desktopentry names must be registered in
0145     // registerServiceByDesktopEntryName above.
0146 
0147     // For special handlings about naming in the menu etc. see kmoretoolsmenufactory.cpp/addItemsForGroupingNameWithSpecialHandling
0148 
0149     //
0150     // grouping definitions begin (sorted alphabetically):
0151     //
0152     // clang-format off
0153     dict.insert(_("disk-usage"), { _("org.kde.kdf"), _("org.kde.filelight") });
0154     dict.insert(_("disk-partitions"), { _("gparted"), _("org.kde.partitionmanager"), _("disk") });
0155     dict.insert(_("files-find"), { _("org.kde.kfind"), _("fsearch"), _("more:"), _("gnome-search-tool"), _("catfish"), _("angrysearch") });
0156     dict.insert(_("font-tools"), { _("fontinst"), _("gucharmap"), _("more:"), _("org.kde.kcharselect"), _("fontmatrix") });
0157     dict.insert(_("git-clients-for-folder"), { _("git-cola-folder-handler"), _("gitk.kmt-edition"),
0158                 _("giggle"), _("qgit.kmt-edition"), _("gitg") });
0159     dict.insert(_("git-clients-and-actions"), { _("git-cola-folder-handler"), _("git-cola-view-history.kmt-edition"),
0160                 _("giggle"), _("gitk.kmt-edition"), _("qgit.kmt-edition"), _("gitg") });
0161     dict.insert(_("icon-browser"), { _("org.kde.plasma.cuttlefish.kmt-edition") });
0162     dict.insert(_("language-dictionary"), { _("ding"), _("kding") });
0163     dict.insert(_("mouse-tools"), { _("org.kde.kmousetool") }); // todo: add program "xbanish" to remove mouse cursor while typing
0164     dict.insert(_("screenrecorder"), { _("com.uploadedlobster.peek"), _("simplescreenrecorder"), _("vokoscreenNG"), _("com.obsproject.Studio") });
0165     dict.insert(_("screenshot-take"), { _("org.kde.spectacle"), _("shutter"), _("kaption"), _("hotshots") });
0166     dict.insert(_("system-monitor-processes"), { _("org.kde.ksysguard"), _("more:"), _("htop"), _("xfce4-taskmanager") });
0167     dict.insert(_("system-monitor-logs"), { _("org.kde.ksystemlog") });
0168     dict.insert(_("time-countdown"), { _("org.gnome.clocks"), _("org.kde.ktimer") });
0169     //
0170     // ...grouping definitions end
0171     //
0172     // clang-format on
0173 
0174     QList<KMoreToolsService *> resultList;
0175     QSet<QString> alreadyUsedDesktopEntryNames; // including the "more:" keyword
0176     bool nextIsMore = false;
0177 
0178     for (const QString &groupingName : groupingNames) {
0179         auto iter = dict.constFind(groupingName);
0180         if (iter != dict.constEnd()) {
0181             for (const QString &desktopEntryName : std::as_const(*iter)) {
0182                 if (!alreadyUsedDesktopEntryNames.contains(desktopEntryName)) {
0183                     if (desktopEntryName == _("more:")) {
0184                         nextIsMore = true;
0185                     } else {
0186                         if (nextIsMore) { // this will be only set once
0187                             *firstMoreSectionDesktopEntryName = desktopEntryName;
0188                             nextIsMore = false;
0189                         }
0190                         KMoreToolsService *kmtService = KMoreToolsPresets::registerServiceByDesktopEntryName(kmt, desktopEntryName);
0191                         if (kmtService) { // Do not add null pointers caused by missing or broken .desktop files
0192                             resultList << kmtService;
0193                         }
0194                     }
0195                 } else {
0196                     alreadyUsedDesktopEntryNames.insert(desktopEntryName);
0197                 }
0198             }
0199         } else {
0200             qCWarning(KMORETOOLS) << "KMoreToolsPresets::registerServicesByGroupingName: groupingName not found: " << groupingName;
0201         }
0202     }
0203 
0204     if (resultList.isEmpty()) {
0205         qCWarning(KMORETOOLS) << "KMoreToolsPresets::registerServicesByGroupingName: " << groupingNames
0206                               << ". Nothing found in this groupings. HINT: check for invalid grouping names.";
0207     }
0208 
0209     return resultList;
0210 }