Plasma5Support

deviceserviceaction.cpp
1/*
2 SPDX-FileCopyrightText: 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
3 SPDX-FileCopyrightText: 2005-2007 Kevin Ottens <ervin@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#include "deviceserviceaction.h"
9
10#include <QDebug>
11
12#include <KApplicationTrader>
13#include <KConfigGroup>
14#include <KDesktopFile>
15#include <KIO/CommandLauncherJob>
16#include <KLocalizedString>
17#include <KNotificationJobUiDelegate>
18#include <KService>
19#include <kmacroexpander.h>
20#include <solid/block.h>
21#include <solid/device.h>
22#include <solid/storageaccess.h>
23
24class MacroExpander : public KMacroExpanderBase
25{
26public:
27 MacroExpander(const Solid::Device &device)
29 , m_device(device)
30 {
31 }
32
33protected:
34 int expandEscapedMacro(const QString &str, int pos, QStringList &ret) override;
35
36private:
37 Solid::Device m_device;
38};
39
40class DelayedExecutor : public QObject
41{
43public:
44 DelayedExecutor(const KServiceAction &service, Solid::Device &device);
45
46private Q_SLOTS:
47 void _k_storageSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
48
49private:
50 void delayedExecute(const QString &udi);
51
52 KServiceAction m_service;
53};
54
55void DeviceServiceAction::execute(Solid::Device &device)
56{
57 new DelayedExecutor(m_service, device);
58}
59
60void DelayedExecutor::_k_storageSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
61{
62 Q_UNUSED(errorData);
63
64 if (!error) {
65 delayedExecute(udi);
66 }
67}
68
69void DeviceServiceAction::setService(const KServiceAction &service)
70{
71 m_service = service;
72}
73
74KServiceAction DeviceServiceAction::service() const
75{
76 return m_service;
77}
78
79int MacroExpander::expandEscapedMacro(const QString &str, int pos, QStringList &ret)
80{
81 ushort option = str[pos + 1].unicode();
82
83 switch (option) {
84 case 'f': // Filepath
85 case 'F': // case insensitive
86 if (m_device.is<Solid::StorageAccess>()) {
87 ret << m_device.as<Solid::StorageAccess>()->filePath();
88 } else {
89 qWarning() << "DeviceServiceAction::execute: " << m_device.udi() << " is not a StorageAccess device";
90 }
91 break;
92 case 'd': // Device node
93 case 'D': // case insensitive
94 if (m_device.is<Solid::Block>()) {
95 ret << m_device.as<Solid::Block>()->device();
96 } else {
97 qWarning() << "DeviceServiceAction::execute: " << m_device.udi() << " is not a Block device";
98 }
99 break;
100 case 'i': // UDI
101 case 'I': // case insensitive
102 ret << m_device.udi();
103 break;
104 case 'j': // Last section of UDI
105 case 'J': // case insensitive
106 ret << m_device.udi().section(QLatin1Char('/'), -1);
107 break;
108 case '%':
109 ret = QStringList(QLatin1String("%"));
110 break;
111 default:
112 return -2; // subst with same and skip
113 }
114 return 2;
115}
116
117DelayedExecutor::DelayedExecutor(const KServiceAction &service, Solid::Device &device)
118 : m_service(service)
119{
120 if (device.is<Solid::StorageAccess>() && !device.as<Solid::StorageAccess>()->isAccessible()) {
121 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
122
123 connect(access, &Solid::StorageAccess::setupDone, this, &DelayedExecutor::_k_storageSetupDone);
124
125 access->setup();
126 } else {
127 delayedExecute(device.udi());
128 }
129}
130
131void DelayedExecutor::delayedExecute(const QString &udi)
132{
133 Solid::Device device(udi);
134
135 QString exec = m_service.exec();
136 MacroExpander mx(device);
137 mx.expandMacrosShellQuote(exec);
138
141
142 // To make xdg-activation and startup feedback work we need to pass the desktop file name of what we are launching
143 if (m_service.service()->storageId().endsWith(QLatin1String("openWithFileManager.desktop"))) {
144 // We know that we are going to launch the default file manager, so query the desktop file name of that
145 const KService::Ptr defaultFileManager = KApplicationTrader::preferredService(QStringLiteral("inode/directory"));
146 if (defaultFileManager) {
147 job->setDesktopName(defaultFileManager->desktopEntryName());
148 }
149 } else {
150 // Read the app that will be launched from the desktop file
151 KDesktopFile desktopFile(m_service.service()->storageId());
152 job->setDesktopName(desktopFile.desktopGroup().readEntry("X-KDE-AliasFor"));
153 }
154
155 job->start();
156
157 deleteLater();
158}
159
160#include "deviceserviceaction.moc"
void setDesktopName(const QString &desktopName)
void start() override
void setUiDelegate(KJobUiDelegate *delegate)
QString exec() const
KServicePtr service() const
QString udi() const
bool is() const
DevIface * as()
bool isAccessible() const
KSERVICE_EXPORT KService::Ptr preferredService(const QString &mimeType)
Q_OBJECTQ_OBJECT
Q_SLOTSQ_SLOTS
void deleteLater()
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
const QChar * unicode() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:57 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.