Index: autotests/krununittest.cpp =================================================================== --- autotests/krununittest.cpp +++ autotests/krununittest.cpp @@ -329,13 +329,17 @@ void KRunUnitTest::KRunRunService_data() { QTest::addColumn("tempFile"); + QTest::addColumn("useRunApplication"); - QTest::newRow("standard") << false; - QTest::newRow("tempfile") << true; + QTest::newRow("standard") << false << false; + QTest::newRow("tempfile") << true << false; + QTest::newRow("runApp") << false << true; + QTest::newRow("runApp_tempfile") << true << true; } void KRunUnitTest::KRunRunService() { QFETCH(bool, tempFile); + QFETCH(bool, useRunApplication); // Given a service desktop file and a source file const QString path = createTempService(); @@ -350,8 +354,10 @@ QList urls; urls.append(QUrl::fromLocalFile(srcFile)); - // When calling KRun::runService - qint64 pid = KRun::runService(service, urls, 0, tempFile); + // When calling KRun::runService or KRun::runApplication + qint64 pid = useRunApplication + ? KRun::runApplication(service, urls, 0, tempFile ? KRun::RunFlags(KRun::DeleteTemporaryFiles) : KRun::RunFlags()) + : KRun::runService(service, urls, 0, tempFile); // Then the service should be executed (which copies the source file to "dest") QVERIFY(pid != 0); Index: src/widgets/krun.h =================================================================== --- src/widgets/krun.h +++ src/widgets/krun.h @@ -211,6 +211,10 @@ /** * Open a list of URLs with a certain service (application). * + * Prefer runApplication(), unless you need to wait for the application + * to register to DBus before this method returns (but that should rather + * be done with DBus activation). + * * @param service the service to run * @param urls the list of URLs, can be empty (app launched * without argument) @@ -224,7 +228,32 @@ */ static qint64 runService(const KService &service, const QList &urls, QWidget *window, bool tempFiles = false, const QString &suggestedFileName = QString(), - const QByteArray &asn = QByteArray()); + const QByteArray &asn = QByteArray()); // TODO KF6: deprecate/remove + + enum RunFlag { + DeleteTemporaryFiles = 0x1 /// < the URLs passed to the service will be deleted when it exits (if the URLs are local files) + }; + Q_DECLARE_FLAGS(RunFlags, RunFlag) + + /** + * Run an application (known from its .desktop file, i.e. as a KService) + * + * Unlike runService, this does not wait for the application to register to DBus + * before returning. Such behavior is better done with DBus activation anyway. + * + * @param service the service to run + * @param urls the list of URLs, can be empty (app launched + * without argument) + * @param window The top-level widget of the app that invoked this object. + * @param runFlags various flags + * @param suggestedFileName see setSuggestedFileName + * @param asn Application startup notification id, if any (otherwise ""). + * @return 0 on error, the process ID on success + * @since 5.24 + */ + static qint64 runApplication(const KService &service, const QList &urls, QWidget *window, + RunFlags flags = RunFlags(), const QString &suggestedFileName = QString(), + const QByteArray &asn = QByteArray()); /** * Open a list of URLs with an executable. Index: src/widgets/krun.cpp =================================================================== --- src/widgets/krun.cpp +++ src/widgets/krun.cpp @@ -398,11 +398,9 @@ return true; } -static qint64 runTempService(const KService &_service, const QList &_urls, QWidget *window, - bool tempFiles, const QString &suggestedFileName, const QByteArray &asn) +static qint64 runApplicationImpl(const KService &_service, const QList &_urls, QWidget *window, + KRun::RunFlags flags, const QString &suggestedFileName, const QByteArray &asn) { - //qDebug() << "runTempService:" << _urls; - QList urlsToRun = _urls; if ((_urls.count() > 1) && !_service.allowMultipleFiles()) { // We need to launch the application N times. That sucks. @@ -414,13 +412,13 @@ while (++it != _urls.end()) { QList singleUrl; singleUrl.append(*it); - runTempService(_service, singleUrl, window, tempFiles, suggestedFileName, QByteArray()); + runApplicationImpl(_service, singleUrl, window, flags, suggestedFileName, QByteArray()); } urlsToRun.clear(); urlsToRun.append(_urls.first()); } KIO::DesktopExecParser execParser(_service, urlsToRun); - execParser.setUrlsAreTempFiles(tempFiles); + execParser.setUrlsAreTempFiles(flags & KRun::DeleteTemporaryFiles); execParser.setSuggestedFileName(suggestedFileName); const QStringList args = execParser.resultingArguments(); if (args.isEmpty()) { @@ -704,6 +702,27 @@ return runService(_service, _urls, window, tempFiles, suggestedFileName, asn) != 0; } +qint64 KRun::runApplication(const KService &service, const QList &urls, QWidget *window, + RunFlags flags, const QString &suggestedFileName, + const QByteArray &asn) +{ + if (!service.entryPath().isEmpty() && + !KDesktopFile::isAuthorizedDesktopFile(service.entryPath()) && + !::makeServiceExecutable(service, window)) { + return 0; + } + + + if ((flags & DeleteTemporaryFiles) == 0) { + // Remember we opened those urls, for the "recent documents" menu in kicker + for (const QUrl &url : urls) { + KRecentDocument::add(url, service.desktopEntryName()); + } + } + + return runApplicationImpl(service, urls, window, flags, suggestedFileName, asn); +} + qint64 KRun::runService(const KService &_service, const QList &_urls, QWidget *window, bool tempFiles, const QString &suggestedFileName, const QByteArray &asn) { @@ -715,10 +734,8 @@ if (!tempFiles) { // Remember we opened those urls, for the "recent documents" menu in kicker - QList::ConstIterator it = _urls.begin(); - for (; it != _urls.end(); ++it) { - //qDebug() << "KRecentDocument::adding " << (*it).url(); - KRecentDocument::add(*it, _service.desktopEntryName()); + for (const QUrl &url : _urls) { + KRecentDocument::add(url, _service.desktopEntryName()); } } @@ -738,7 +755,7 @@ } if (!useKToolInvocation) { - return runTempService(_service, _urls, window, tempFiles, suggestedFileName, asn); + return runApplicationImpl(_service, _urls, window, tempFiles ? RunFlags(DeleteTemporaryFiles) : RunFlags(), suggestedFileName, asn); } // Resolve urls if needed, depending on what the app supports