File indexing completed on 2024-05-12 05:37:18
0001 /* 0002 SPDX-FileCopyrightText: 2005 Jean-Remy Falleri <jr.falleri@laposte.net> 0003 SPDX-FileCopyrightText: 2005-2007 Kevin Ottens <ervin@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "deviceserviceaction.h" 0009 0010 #include <QDebug> 0011 0012 #include <KApplicationTrader> 0013 #include <KConfigGroup> 0014 #include <KDesktopFile> 0015 #include <KIO/CommandLauncherJob> 0016 #include <KLocalizedString> 0017 #include <KNotificationJobUiDelegate> 0018 #include <KService> 0019 #include <kmacroexpander.h> 0020 #include <solid/block.h> 0021 #include <solid/device.h> 0022 #include <solid/storageaccess.h> 0023 0024 class MacroExpander : public KMacroExpanderBase 0025 { 0026 public: 0027 MacroExpander(const Solid::Device &device) 0028 : KMacroExpanderBase('%') 0029 , m_device(device) 0030 { 0031 } 0032 0033 protected: 0034 int expandEscapedMacro(const QString &str, int pos, QStringList &ret) override; 0035 0036 private: 0037 Solid::Device m_device; 0038 }; 0039 0040 class DelayedExecutor : public QObject 0041 { 0042 Q_OBJECT 0043 public: 0044 DelayedExecutor(const KServiceAction &service, Solid::Device &device); 0045 0046 private Q_SLOTS: 0047 void _k_storageSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi); 0048 0049 private: 0050 void delayedExecute(const QString &udi); 0051 0052 KServiceAction m_service; 0053 }; 0054 0055 void DeviceServiceAction::execute(Solid::Device &device) 0056 { 0057 new DelayedExecutor(m_service, device); 0058 } 0059 0060 void DelayedExecutor::_k_storageSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi) 0061 { 0062 Q_UNUSED(errorData); 0063 0064 if (!error) { 0065 delayedExecute(udi); 0066 } 0067 } 0068 0069 void DeviceServiceAction::setService(const KServiceAction &service) 0070 { 0071 m_service = service; 0072 } 0073 0074 KServiceAction DeviceServiceAction::service() const 0075 { 0076 return m_service; 0077 } 0078 0079 int MacroExpander::expandEscapedMacro(const QString &str, int pos, QStringList &ret) 0080 { 0081 ushort option = str[pos + 1].unicode(); 0082 0083 switch (option) { 0084 case 'f': // Filepath 0085 case 'F': // case insensitive 0086 if (m_device.is<Solid::StorageAccess>()) { 0087 ret << m_device.as<Solid::StorageAccess>()->filePath(); 0088 } else { 0089 qWarning() << "DeviceServiceAction::execute: " << m_device.udi() << " is not a StorageAccess device"; 0090 } 0091 break; 0092 case 'd': // Device node 0093 case 'D': // case insensitive 0094 if (m_device.is<Solid::Block>()) { 0095 ret << m_device.as<Solid::Block>()->device(); 0096 } else { 0097 qWarning() << "DeviceServiceAction::execute: " << m_device.udi() << " is not a Block device"; 0098 } 0099 break; 0100 case 'i': // UDI 0101 case 'I': // case insensitive 0102 ret << m_device.udi(); 0103 break; 0104 case '%': 0105 ret = QStringList(QLatin1String("%")); 0106 break; 0107 default: 0108 return -2; // subst with same and skip 0109 } 0110 return 2; 0111 } 0112 0113 DelayedExecutor::DelayedExecutor(const KServiceAction &service, Solid::Device &device) 0114 : m_service(service) 0115 { 0116 if (device.is<Solid::StorageAccess>() && !device.as<Solid::StorageAccess>()->isAccessible()) { 0117 Solid::StorageAccess *access = device.as<Solid::StorageAccess>(); 0118 0119 connect(access, &Solid::StorageAccess::setupDone, this, &DelayedExecutor::_k_storageSetupDone); 0120 0121 access->setup(); 0122 } else { 0123 delayedExecute(device.udi()); 0124 } 0125 } 0126 0127 void DelayedExecutor::delayedExecute(const QString &udi) 0128 { 0129 Solid::Device device(udi); 0130 0131 qWarning() << "About the execute the service..."; 0132 QString exec = m_service.exec(); 0133 qWarning() << "Executed the service!!!"; 0134 MacroExpander mx(device); 0135 mx.expandMacrosShellQuote(exec); 0136 0137 KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(exec); 0138 job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled)); 0139 0140 // To make xdg-activation and startup feedback work we need to pass the desktop file name of what we are launching 0141 if (m_service.service()->storageId().endsWith(QLatin1String("openWithFileManager.desktop"))) { 0142 // We know that we are going to launch the default file manager, so query the desktop file name of that 0143 const KService::Ptr defaultFileManager = KApplicationTrader::preferredService(QStringLiteral("inode/directory")); 0144 job->setDesktopName(defaultFileManager->desktopEntryName()); 0145 } else { 0146 // Read the app that will be launched from the desktop file 0147 KDesktopFile desktopFile(m_service.service()->storageId()); 0148 job->setDesktopName(desktopFile.desktopGroup().readEntry("X-KDE-AliasFor")); 0149 } 0150 0151 job->start(); 0152 0153 deleteLater(); 0154 } 0155 0156 #include "deviceserviceaction.moc"