00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kdesktopfileactions.h"
00021 #include "krun.h"
00022 #include "kautomount.h"
00023 #include <kmessageboxwrapper.h>
00024 #include <kdirnotify.h>
00025 #include <kmountpoint.h>
00026
00027 #include <kglobal.h>
00028 #include <kstandarddirs.h>
00029 #include <kdesktopfile.h>
00030 #include <kconfiggroup.h>
00031 #include <klocale.h>
00032 #include "kservice.h"
00033
00034 enum BuiltinServiceType { ST_MOUNT = 0x0E1B05B0, ST_UNMOUNT = 0x0E1B05B1 };
00035
00036 static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg );
00037 static bool runApplication( const KUrl& _url, const QString & _serviceFile );
00038 static bool runLink( const KUrl& _url, const KDesktopFile &cfg );
00039
00040 bool KDesktopFileActions::run( const KUrl& u, bool _is_local )
00041 {
00042
00043
00044 if ( !_is_local )
00045 return false;
00046
00047 KDesktopFile cfg( u.path() );
00048 if ( !cfg.desktopGroup().hasKey("Type") )
00049 {
00050 QString tmp = i18n("The desktop entry file %1 "
00051 "has no Type=... entry.", u.path() );
00052 KMessageBoxWrapper::error( 0, tmp);
00053 return false;
00054 }
00055
00056
00057
00058 if ( cfg.hasDeviceType() )
00059 return runFSDevice( u, cfg );
00060 else if ( cfg.hasApplicationType()
00061 || (cfg.readType() == "Service" && !cfg.desktopGroup().readEntry("Exec").isEmpty()))
00062 return runApplication( u, u.path() );
00063 else if ( cfg.hasLinkType() )
00064 return runLink( u, cfg );
00065
00066 QString tmp = i18n("The desktop entry of type\n%1\nis unknown.", cfg.readType() );
00067 KMessageBoxWrapper::error( 0, tmp);
00068
00069 return false;
00070 }
00071
00072 static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg )
00073 {
00074 bool retval = false;
00075
00076 QString dev = cfg.readDevice();
00077
00078 if ( dev.isEmpty() )
00079 {
00080 QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.", _url.path() );
00081 KMessageBoxWrapper::error( 0, tmp);
00082 return retval;
00083 }
00084
00085 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00086
00087 if (mp) {
00088 KUrl mpURL(mp->mountPoint());
00089
00090 retval = KRun::runUrl( mpURL, QLatin1String("inode/directory"), 0 );
00091 } else {
00092 KConfigGroup cg = cfg.desktopGroup();
00093 bool ro = cg.readEntry("ReadOnly", false);
00094 QString fstype = cg.readEntry( "FSType" );
00095 if ( fstype == "Default" )
00096 fstype.clear();
00097 QString point = cg.readEntry( "MountPoint" );
00098 #ifndef Q_WS_WIN
00099 (void) new KAutoMount( ro, fstype.toLatin1(), dev, point, _url.path() );
00100 #endif
00101 retval = false;
00102 }
00103
00104 return retval;
00105 }
00106
00107 static bool runApplication( const KUrl& , const QString & _serviceFile )
00108 {
00109 KService s( _serviceFile );
00110 if ( !s.isValid() )
00111
00112
00113 return false;
00114
00115 KUrl::List lst;
00116 return KRun::run( s, lst, 0 );
00117 }
00118
00119 static bool runLink( const KUrl& _url, const KDesktopFile &cfg )
00120 {
00121 QString u = cfg.readUrl();
00122 if ( u.isEmpty() )
00123 {
00124 QString tmp = i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.", _url.prettyUrl() );
00125 KMessageBoxWrapper::error( 0, tmp );
00126 return false;
00127 }
00128
00129 KUrl url ( u );
00130 KRun* run = new KRun(url,(QWidget*)0);
00131
00132
00133
00134
00135 QString lastOpenedWidth = cfg.desktopGroup().readEntry( "X-KDE-LastOpenedWith" );
00136 if ( !lastOpenedWidth.isEmpty() )
00137 run->setPreferredService( lastOpenedWidth );
00138
00139 return false;
00140 }
00141
00142 QList<KServiceAction> KDesktopFileActions::builtinServices( const KUrl& _url )
00143 {
00144 QList<KServiceAction> result;
00145
00146 if ( !_url.isLocalFile() )
00147 return result;
00148
00149 KDesktopFile cfg( _url.path() );
00150 QString type = cfg.readType();
00151
00152 if ( type.isEmpty() )
00153 return result;
00154
00155 if ( cfg.hasDeviceType() ) {
00156 const QString dev = cfg.readDevice();
00157 if ( dev.isEmpty() ) {
00158 QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.", _url.path() );
00159 KMessageBoxWrapper::error(0, tmp);
00160 } else {
00161 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00162
00163 if ( !mp ) {
00164 KServiceAction mount("mount", i18n("Mount"), QString(), QString(), false);
00165 mount.setData(QVariant(ST_MOUNT));
00166 result.append(mount);
00167 } else {
00168 QString text;
00169 #ifdef HAVE_VOLMGT
00170
00171
00172
00173 text = i18n("Eject");
00174 #else
00175 text = i18n("Unmount");
00176 #endif
00177 KServiceAction unmount("unmount", text, QString(), QString(), false);
00178 unmount.setData(QVariant(ST_UNMOUNT));
00179 result.append(unmount);
00180 }
00181 }
00182 }
00183
00184 return result;
00185 }
00186
00187 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, bool bLocalFiles )
00188 {
00189 KDesktopFile cfg( path );
00190 return userDefinedServices( path, cfg, bLocalFiles );
00191 }
00192
00193 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, const KDesktopFile& cfg, bool bLocalFiles, const KUrl::List & file_list )
00194 {
00195 Q_UNUSED(path);
00196 KService service(&cfg);
00197 return userDefinedServices(service, bLocalFiles, file_list);
00198 }
00199
00200 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const KService& service, bool bLocalFiles, const KUrl::List & file_list )
00201 {
00202 QList<KServiceAction> result;
00203
00204 if (!service.isValid())
00205 return result;
00206
00207 QStringList keys;
00208 const QString actionMenu = service.property("X-KDE-GetActionMenu", QVariant::String).toString();
00209 if (!actionMenu.isEmpty()) {
00210 const QStringList dbuscall = actionMenu.split(QChar(' '));
00211 if (dbuscall.count() >= 4) {
00212 const QString& app = dbuscall.at( 0 );
00213 const QString& object = dbuscall.at( 1 );
00214 const QString& interface = dbuscall.at( 2 );
00215 const QString& function = dbuscall.at( 3 );
00216
00217 QDBusInterface remote( app, object, interface );
00218
00219
00220 QDBusReply<QStringList> reply = remote.call(function, file_list.toStringList());
00221 keys = reply;
00222 if (keys.isEmpty())
00223 return result;
00224 } else {
00225 kWarning(7000) << "The desktop file" << service.entryPath()
00226 << "has an invalid X-KDE-GetActionMenu entry."
00227 << "Syntax is: app object interface function";
00228 }
00229 }
00230
00231
00232
00233 foreach(const KServiceAction& action, service.actions()) {
00234 if (keys.isEmpty() || keys.contains(action.name())) {
00235 const QString exec = action.exec();
00236 if (bLocalFiles || exec.contains("%U") || exec.contains("%u")) {
00237 result.append( action );
00238 }
00239 }
00240 }
00241
00242 return result;
00243 }
00244
00245 void KDesktopFileActions::executeService( const KUrl::List& urls, const KServiceAction& action )
00246 {
00247
00248
00249 int actionData = action.data().toInt();
00250 if ( actionData == ST_MOUNT || actionData == ST_UNMOUNT ) {
00251 Q_ASSERT( urls.count() == 1 );
00252 const QString path = urls.first().path();
00253
00254
00255 KDesktopFile cfg( path );
00256 const QString dev = cfg.readDevice();
00257 if ( dev.isEmpty() ) {
00258 QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.", path );
00259 KMessageBoxWrapper::error( 0, tmp );
00260 return;
00261 }
00262 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00263
00264 if ( actionData == ST_MOUNT ) {
00265
00266 if ( mp ) {
00267 kDebug(7000) << "ALREADY Mounted";
00268 return;
00269 }
00270
00271 const KConfigGroup group = cfg.desktopGroup();
00272 bool ro = group.readEntry("ReadOnly", false);
00273 QString fstype = group.readEntry( "FSType" );
00274 if ( fstype == "Default" )
00275 fstype.clear();
00276 QString point = group.readEntry( "MountPoint" );
00277 #ifndef Q_WS_WIN
00278 (void)new KAutoMount( ro, fstype.toLatin1(), dev, point, path, false );
00279 #endif
00280 } else if ( actionData == ST_UNMOUNT ) {
00281
00282 if ( !mp )
00283 return;
00284
00285 #ifndef Q_WS_WIN
00286 (void)new KAutoUnmount( mp->mountPoint(), path );
00287 #endif
00288 }
00289 } else {
00290 kDebug() << action.name() << "first url's path=" << urls.first().path() << "exec=" << action.exec();
00291 KRun::run( action.exec(), urls, 0, action.text(), action.icon(), "0" );
00292
00293 org::kde::KDirNotify::emitFilesChanged( urls.toStringList() );
00294 }
00295 }
00296