SVN commit 420946 by ervin: Introduce a new property for desktop files : X-KDE-Protocols Allow to declare which protocols are really supported for special cases (in particular applications needing to seek in files). The behavior is the following: 1) If X-KDE-Protocols is not specified or X-KDE-Protocols=KIO, %U works as expected 2) If X-KDE-Protocols=protocol1,protocol2,... %U works as expected for protocol1, protocol2, ... Other URLs are rewritten using NetAccess::mostLocalURL() before being passed to the application (to ensure having file:/ URLs when using media:/ or system:/ for example) As a result it's not necessary to resolve URLs having UDS_LOCAL_PATH in KFileItem::run(), everything is processed in KRun. Thanks a lot to dfaure for helping with KRun itself. M +4 -0 application.desktop M +2 -2 kio/kfileitem.cpp M +42 -2 kio/krun.cpp --- trunk/KDE/kdelibs/kio/application.desktop #420945:420946 @@ -110,3 +110,7 @@ [PropertyDef::X-KDE-HasTempFileOption] Type=bool + +[PropertyDef::X-KDE-Protocols] +Type=QStringList + --- trunk/KDE/kdelibs/kio/kio/kfileitem.cpp #420945:420946 @@ -757,8 +757,8 @@ void KFileItem::run() { - bool is_local; - KURL url = mostLocalURL(is_local); + bool is_local = m_bIsLocalURL; + KURL url = m_url; // When clicking on a link to e.g. $HOME from the desktop, we want to open $HOME // But when following a link on the FTP site, the target be an absolute path // that doesn't work in the URL. So we resolve links only on the local filesystem. --- trunk/KDE/kdelibs/kio/kio/krun.cpp #420945:420946 @@ -34,6 +34,7 @@ #include "kio/job.h" #include "kio/global.h" #include "kio/scheduler.h" +#include "kio/netaccess.h" #include "kfile/kopenwith.h" #include "kfile/krecentdocument.h" @@ -197,7 +198,7 @@ if ( !!service ) return KRun::run( *service, lst, tempFiles ); - kdDebug(250) << "No service set, running " << l.text() << endl; + kdDebug(7010) << "No service set, running " << l.text() << endl; return KRun::run( l.text(), lst ); // TODO handle tempFiles } return false; @@ -647,6 +648,42 @@ _service.name(), _service.icon() ); } +// WARNING: don't call this from processDesktopExec, since klauncher uses that too... +static KURL::List resolveURLs( const KURL::List& _urls, const KService& _service ) +{ + // Check which protocols the application supports. + // This can be a list of actual protocol names, or just KIO for KDE apps. + QStringList supportedProtocols = _service.property("X-KDE-Protocols").toStringList(); + KRunMX1 mx1( _service ); + QString exec = _service.exec(); + if ( mx1.expandMacrosShellQuote( exec ) && !mx1.hasUrls ) { + Q_ASSERT( supportedProtocols.isEmpty() ); // huh? If you support protocols you need %u or %U... + } else { + if ( supportedProtocols.isEmpty() ) // compat: assume KIO if not set + supportedProtocols.append( "KIO" ); + } + kdDebug(7010) << "supportedProtocols:" << supportedProtocols << endl; + + KURL::List urls( _urls ); + if ( supportedProtocols.find( "KIO" ) == supportedProtocols.end() ) { + for( KURL::List::Iterator it = urls.begin(); it != urls.end(); ++it ) { + const KURL url = *it; + bool supported = url.isLocalFile() || supportedProtocols.find( url.protocol().lower() ) != supportedProtocols.end(); + kdDebug(7010) << "Looking at url=" << url << " supported=" << supported << endl; + if ( !supported && KProtocolInfo::protocolClass(url.protocol()) == ":local" ) + { + // Maybe we can resolve to a local URL? + KURL localURL = KIO::NetAccess::mostLocalURL( url, 0 ); + if ( localURL != url ) { + *it = localURL; + kdDebug(7010) << "Changed to " << localURL << endl; + } + } + } + } + return urls; +} + // BIC merge with method below pid_t KRun::run( const KService& _service, const KURL::List& _urls ) { @@ -684,11 +721,14 @@ kdDebug(7010) << "First url " << _urls.first().url() << endl; } + // Resolve urls if needed, depending on what the app supports + KURL::List urls = resolveURLs( _urls, _service ); + QString error; int pid = 0; int i = KApplication::startServiceByDesktopPath( - _service.desktopEntryPath(), _urls.toStringList(), &error, 0L, &pid + _service.desktopEntryPath(), urls.toStringList(), &error, 0L, &pid ); if (i != 0)