• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
kdesktopfileactions.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 * Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
3 * David Faure <faure@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License version 2 as published by the Free Software Foundation;
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 **/
19
20#include "kdesktopfileactions.h"
21
22#include "config-kio.h"
23
24#include "krun.h"
25#include "kautomount.h"
26#include <kmessageboxwrapper.h>
27#include <kdirnotify.h>
28#include <kmountpoint.h>
29
30#include <kstandarddirs.h>
31#include <kdesktopfile.h>
32#include <kconfiggroup.h>
33#include <klocale.h>
34#include <kservice.h>
35
36#ifndef KIO_NO_SOLID
37//Solid
38#include <solid/devicenotifier.h>
39#include <solid/device.h>
40#include <solid/deviceinterface.h>
41#include <solid/predicate.h>
42#include <solid/storageaccess.h>
43#include <solid/opticaldrive.h>
44#include <solid/opticaldisc.h>
45#include <solid/block.h>
46#endif
47
48enum BuiltinServiceType { ST_MOUNT = 0x0E1B05B0, ST_UNMOUNT = 0x0E1B05B1 }; // random numbers
49
50static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg );
51static bool runApplication( const KUrl& _url, const QString & _serviceFile );
52static bool runLink( const KUrl& _url, const KDesktopFile &cfg );
53
54bool KDesktopFileActions::run( const KUrl& u, bool _is_local )
55{
56 // It might be a security problem to run external untrusted desktop
57 // entry files
58 if ( !_is_local )
59 return false;
60
61 KDesktopFile cfg(u.toLocalFile());
62 if ( !cfg.desktopGroup().hasKey("Type") )
63 {
64 QString tmp = i18n("The desktop entry file %1 "
65 "has no Type=... entry.", u.toLocalFile() );
66 KMessageBoxWrapper::error( 0, tmp);
67 return false;
68 }
69
70 //kDebug(7000) << "TYPE = " << type.data();
71
72 if ( cfg.hasDeviceType() )
73 return runFSDevice( u, cfg );
74 else if ( cfg.hasApplicationType()
75 || (cfg.readType() == "Service" && !cfg.desktopGroup().readEntry("Exec").isEmpty())) // for kio_settings
76 return runApplication( u, u.toLocalFile() );
77 else if ( cfg.hasLinkType() )
78 return runLink( u, cfg );
79
80 QString tmp = i18n("The desktop entry of type\n%1\nis unknown.", cfg.readType() );
81 KMessageBoxWrapper::error( 0, tmp);
82
83 return false;
84}
85
86static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg )
87{
88 bool retval = false;
89
90 QString dev = cfg.readDevice();
91
92 if ( dev.isEmpty() )
93 {
94 QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.", _url.toLocalFile() );
95 KMessageBoxWrapper::error( 0, tmp);
96 return retval;
97 }
98
99 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
100 // Is the device already mounted ?
101 if (mp) {
102 KUrl mpURL(mp->mountPoint());
103 // Open a new window
104 retval = KRun::runUrl( mpURL, QLatin1String("inode/directory"), 0 /*TODO - window*/ );
105 } else {
106 KConfigGroup cg = cfg.desktopGroup();
107 bool ro = cg.readEntry("ReadOnly", false);
108 QString fstype = cg.readEntry( "FSType" );
109 if ( fstype == "Default" ) // KDE-1 thing
110 fstype.clear();
111 QString point = cg.readEntry( "MountPoint" );
112#ifndef Q_WS_WIN
113 (void) new KAutoMount( ro, fstype.toLatin1(), dev, point, _url.toLocalFile() );
114#endif
115 retval = false;
116 }
117
118 return retval;
119}
120
121static bool runApplication( const KUrl& , const QString & _serviceFile )
122{
123 KService s( _serviceFile );
124 if ( !s.isValid() )
125 // The error message was already displayed, so we can just quit here
126 // ### KDE4: is this still the case?
127 return false;
128
129 KUrl::List lst;
130 return KRun::run( s, lst, 0 /*TODO - window*/ );
131}
132
133static bool runLink( const KUrl& _url, const KDesktopFile &cfg )
134{
135 QString u = cfg.readUrl();
136 if ( u.isEmpty() )
137 {
138 QString tmp = i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.", _url.prettyUrl() );
139 KMessageBoxWrapper::error( 0, tmp );
140 return false;
141 }
142
143 KUrl url ( u );
144 KRun* run = new KRun(url,(QWidget*)0);
145
146 // X-KDE-LastOpenedWith holds the service desktop entry name that
147 // was should be preferred for opening this URL if possible.
148 // This is used by the Recent Documents menu for instance.
149 QString lastOpenedWidth = cfg.desktopGroup().readEntry( "X-KDE-LastOpenedWith" );
150 if ( !lastOpenedWidth.isEmpty() )
151 run->setPreferredService( lastOpenedWidth );
152
153 return false;
154}
155
156QList<KServiceAction> KDesktopFileActions::builtinServices( const KUrl& _url )
157{
158 QList<KServiceAction> result;
159
160 if ( !_url.isLocalFile() )
161 return result;
162
163 bool offerMount = false;
164 bool offerUnmount = false;
165
166 KDesktopFile cfg( _url.toLocalFile() );
167 if ( cfg.hasDeviceType() ) { // url to desktop file
168 const QString dev = cfg.readDevice();
169 if ( dev.isEmpty() ) {
170 QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.", _url.toLocalFile() );
171 KMessageBoxWrapper::error(0, tmp);
172 return result;
173 }
174
175 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
176 if (mp) {
177 offerUnmount = true;
178 }
179 else {
180 offerMount = true;
181 }
182 }
183#ifndef KIO_NO_SOLID
184 else { // url to device
185 Solid::Predicate predicate(Solid::DeviceInterface::Block, "device", _url.toLocalFile());
186 const QList<Solid::Device> devList = Solid::Device::listFromQuery(predicate, QString());
187 if (devList.empty()) {
188 kDebug(7000) << "Device" << _url.toLocalFile() << "not found";
189 return result;
190 }
191 Solid::Device device = devList[0];
192 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
193 Solid::StorageDrive *drive = device.parent().as<Solid::StorageDrive>();
194 bool mounted = access && access->isAccessible();
195
196 if ((mounted || device.is<Solid::OpticalDisc>()) && drive && drive->isRemovable()) {
197 offerUnmount = true;
198 }
199
200 if (!mounted && ((drive && drive->isHotpluggable()) || device.is<Solid::OpticalDisc>())) {
201 offerMount = true;
202 }
203 }
204#endif
205
206 if (offerMount) {
207 KServiceAction mount("mount", i18n("Mount"), QString(), QString(), false);
208 mount.setData(QVariant(ST_MOUNT));
209 result.append(mount);
210 }
211
212 if (offerUnmount) {
213 QString text;
214#ifdef HAVE_VOLMGT
215 /*
216 * Solaris' volume management can only umount+eject
217 */
218 text = i18n("Eject");
219#else
220 text = i18n("Unmount");
221#endif
222 KServiceAction unmount("unmount", text, QString(), QString(), false);
223 unmount.setData(QVariant(ST_UNMOUNT));
224 result.append(unmount);
225 }
226
227 return result;
228}
229
230QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, bool bLocalFiles )
231{
232 KDesktopFile cfg( path );
233 return userDefinedServices( path, cfg, bLocalFiles );
234}
235
236QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, const KDesktopFile& cfg, bool bLocalFiles, const KUrl::List & file_list )
237{
238 Q_UNUSED(path); // this was just for debugging; we use service.entryPath() now.
239 KService service(&cfg);
240 return userDefinedServices(service, bLocalFiles, file_list);
241}
242
243QList<KServiceAction> KDesktopFileActions::userDefinedServices( const KService& service, bool bLocalFiles, const KUrl::List & file_list )
244{
245 QList<KServiceAction> result;
246
247 if (!service.isValid()) // e.g. TryExec failed
248 return result;
249
250 QStringList keys;
251 const QString actionMenu = service.property("X-KDE-GetActionMenu", QVariant::String).toString();
252 if (!actionMenu.isEmpty()) {
253 const QStringList dbuscall = actionMenu.split(QChar(' '));
254 if (dbuscall.count() >= 4) {
255 const QString& app = dbuscall.at( 0 );
256 const QString& object = dbuscall.at( 1 );
257 const QString& interface = dbuscall.at( 2 );
258 const QString& function = dbuscall.at( 3 );
259
260 QDBusInterface remote( app, object, interface );
261 // Do NOT use QDBus::BlockWithGui here. It runs a nested event loop,
262 // in which timers can fire, leading to crashes like #149736.
263 QDBusReply<QStringList> reply = remote.call(function, file_list.toStringList());
264 keys = reply; // ensures that the reply was a QStringList
265 if (keys.isEmpty())
266 return result;
267 } else {
268 kWarning(7000) << "The desktop file" << service.entryPath()
269 << "has an invalid X-KDE-GetActionMenu entry."
270 << "Syntax is: app object interface function";
271 }
272 }
273
274 // Now, either keys is empty (all actions) or it's set to the actions we want
275
276 foreach(const KServiceAction& action, service.actions()) {
277 if (keys.isEmpty() || keys.contains(action.name())) {
278 const QString exec = action.exec();
279 if (bLocalFiles || exec.contains("%U") || exec.contains("%u")) {
280 result.append( action );
281 }
282 }
283 }
284
285 return result;
286}
287
288void KDesktopFileActions::executeService( const KUrl::List& urls, const KServiceAction& action )
289{
290 //kDebug(7000) << "EXECUTING Service " << action.name();
291
292 int actionData = action.data().toInt();
293 if ( actionData == ST_MOUNT || actionData == ST_UNMOUNT ) {
294 Q_ASSERT( urls.count() == 1 );
295 const QString path = urls.first().toLocalFile();
296 //kDebug(7000) << "MOUNT&UNMOUNT";
297
298 KDesktopFile cfg( path );
299 if (cfg.hasDeviceType()) { // path to desktop file
300 const QString dev = cfg.readDevice();
301 if ( dev.isEmpty() ) {
302 QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.", path );
303 KMessageBoxWrapper::error( 0, tmp );
304 return;
305 }
306 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
307
308 if ( actionData == ST_MOUNT ) {
309 // Already mounted? Strange, but who knows ...
310 if ( mp ) {
311 kDebug(7000) << "ALREADY Mounted";
312 return;
313 }
314
315 const KConfigGroup group = cfg.desktopGroup();
316 bool ro = group.readEntry("ReadOnly", false);
317 QString fstype = group.readEntry( "FSType" );
318 if ( fstype == "Default" ) // KDE-1 thing
319 fstype.clear();
320 QString point = group.readEntry( "MountPoint" );
321#ifndef Q_WS_WIN
322 (void)new KAutoMount( ro, fstype.toLatin1(), dev, point, path, false );
323#endif
324 } else if ( actionData == ST_UNMOUNT ) {
325 // Not mounted? Strange, but who knows ...
326 if ( !mp )
327 return;
328
329#ifndef Q_WS_WIN
330 (void)new KAutoUnmount( mp->mountPoint(), path );
331#endif
332 }
333 }
334#ifndef KIO_NO_SOLID
335 else { // path to device
336 Solid::Predicate predicate(Solid::DeviceInterface::Block, "device", path);
337 const QList<Solid::Device> devList = Solid::Device::listFromQuery(predicate, QString());
338 if (!devList.empty()) {
339 Solid::Device device = devList[0];
340 if ( actionData == ST_MOUNT ) {
341 if (device.is<Solid::StorageVolume>()) {
342 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
343 if (access) {
344 access->setup();
345 }
346 }
347 } else if ( actionData == ST_UNMOUNT ) {
348 if (device.is<Solid::OpticalDisc>()) {
349 Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
350 if (drive != 0) {
351 drive->eject();
352 }
353 } else if (device.is<Solid::StorageVolume>()) {
354 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
355 if (access && access->isAccessible()) {
356 access->teardown();
357 }
358 }
359 }
360 }
361 else {
362 kDebug(7000) << "Device" << path << "not found";
363 }
364 }
365#endif
366 } else {
367 kDebug() << action.name() << "first url's path=" << urls.first().toLocalFile() << "exec=" << action.exec();
368 KRun::run( action.exec(), urls, 0, action.text(), action.icon());
369 // The action may update the desktop file. Example: eject unmounts (#5129).
370 org::kde::KDirNotify::emitFilesChanged( urls.toStringList() );
371 }
372}
373
KAutoMount
This class implements synchronous mounting of devices, as well as showing a file-manager window after...
Definition: kautomount.h:46
KAutoUnmount
This class implements synchronous unmounting of devices, It is a wrapper around the asychronous KIO::...
Definition: kautomount.h:86
KConfigGroup
KConfigGroup::hasKey
bool hasKey(const char *key) const
KConfigGroup::readEntry
QString readEntry(const char *key, const char *aDefault=0) const
KDesktopFile
KDesktopFile::hasApplicationType
bool hasApplicationType() const
KDesktopFile::hasDeviceType
bool hasDeviceType() const
KDesktopFile::hasLinkType
bool hasLinkType() const
KDesktopFile::desktopGroup
KConfigGroup desktopGroup() const
KDesktopFile::readUrl
QString readUrl() const
KDesktopFile::readType
QString readType() const
KDesktopFile::readDevice
QString readDevice() const
KMessageBoxWrapper::error
static void error(QWidget *parent, const QString &text, const QString &caption=QString())
Definition: kmessageboxwrapper.h:33
KMountPoint::List::findByDevice
Ptr findByDevice(const QString &device) const
KMountPoint::currentMountPoints
static List currentMountPoints(DetailsNeededFlags infoNeeded=BasicInfoNeeded)
KRun
To open files with their associated applications in KDE, use KRun.
Definition: krun.h:60
KRun::runUrl
static bool runUrl(const KUrl &url, const QString &mimetype, QWidget *window, bool tempFile=false, bool runExecutables=true, const QString &suggestedFileName=QString(), const QByteArray &asn=QByteArray())
Open the given URL.
Definition: krun.cpp:122
KRun::run
static bool run(const KService &service, const KUrl::List &urls, QWidget *window, bool tempFiles=false, const QString &suggestedFileName=QString(), const QByteArray &asn=QByteArray())
Open a list of URLs with a certain service (application).
Definition: krun.cpp:984
KServiceAction
KServiceAction::text
QString text() const
KServiceAction::name
QString name() const
KServiceAction::exec
QString exec() const
KServiceAction::icon
QString icon() const
KServiceAction::data
QVariant data() const
KService
KService::actions
QList< KServiceAction > actions() const
KService::property
QVariant property(const QString &_name, QVariant::Type t) const
KSharedPtr
KSycocaEntry::isValid
bool isValid() const
KSycocaEntry::entryPath
QString entryPath() const
KUrl::List
KUrl::List::toStringList
QStringList toStringList() const
KUrl
KUrl::prettyUrl
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::isLocalFile
bool isLocalFile() const
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
OrgKdeKDirNotifyInterface::emitFilesChanged
static void emitFilesChanged(const QStringList &fileList)
Definition: kdirnotify.cpp:52
QList
QWidget
kDebug
#define kDebug
kWarning
#define kWarning
kautomount.h
kconfiggroup.h
kdesktopfile.h
runFSDevice
static bool runFSDevice(const KUrl &_url, const KDesktopFile &cfg)
Definition: kdesktopfileactions.cpp:86
runLink
static bool runLink(const KUrl &_url, const KDesktopFile &cfg)
Definition: kdesktopfileactions.cpp:133
BuiltinServiceType
BuiltinServiceType
Definition: kdesktopfileactions.cpp:48
ST_UNMOUNT
@ ST_UNMOUNT
Definition: kdesktopfileactions.cpp:48
ST_MOUNT
@ ST_MOUNT
Definition: kdesktopfileactions.cpp:48
runApplication
static bool runApplication(const KUrl &_url, const QString &_serviceFile)
Definition: kdesktopfileactions.cpp:121
kdesktopfileactions.h
kdirnotify.h
klocale.h
i18n
QString i18n(const char *text)
kmessageboxwrapper.h
kmountpoint.h
krun.h
kservice.h
kstandarddirs.h
access
int access(const QString &path, int mode)
KDesktopFileActions::executeService
void executeService(const KUrl::List &urls, const KServiceAction &service)
Execute service on the list of urls.
Definition: kdesktopfileactions.cpp:288
KDesktopFileActions::builtinServices
QList< KServiceAction > builtinServices(const KUrl &url)
Returns a list of services for the given .desktop file that are handled by kio itself.
Definition: kdesktopfileactions.cpp:156
KDesktopFileActions::userDefinedServices
QList< KServiceAction > userDefinedServices(const QString &path, bool bLocalFiles)
Returns a list of services defined by the user as possible actions on the given .desktop file.
Definition: kdesktopfileactions.cpp:230
KDesktopFileActions::run
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
Definition: kdesktopfileactions.cpp:54
group
group
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal