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