diff --git a/libtaskmanager/abstracttasksmodel.h b/libtaskmanager/abstracttasksmodel.h --- a/libtaskmanager/abstracttasksmodel.h +++ b/libtaskmanager/abstracttasksmodel.h @@ -115,6 +115,17 @@ virtual void requestNewInstance(const QModelIndex &index) override; /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * This base implementation does nothing. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + virtual void requestOpenUrls(const QModelIndex &index, const QList &urls); + + /** * Request the task at the given index be closed. * * This base implementation does nothing. diff --git a/libtaskmanager/abstracttasksmodel.cpp b/libtaskmanager/abstracttasksmodel.cpp --- a/libtaskmanager/abstracttasksmodel.cpp +++ b/libtaskmanager/abstracttasksmodel.cpp @@ -62,6 +62,12 @@ Q_UNUSED(index) } +void AbstractTasksModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + Q_UNUSED(index) + Q_UNUSED(urls) +} + void AbstractTasksModel::requestClose(const QModelIndex &index) { Q_UNUSED(index) diff --git a/libtaskmanager/abstracttasksmodeliface.h b/libtaskmanager/abstracttasksmodeliface.h --- a/libtaskmanager/abstracttasksmodeliface.h +++ b/libtaskmanager/abstracttasksmodeliface.h @@ -61,6 +61,15 @@ virtual void requestNewInstance(const QModelIndex &index) = 0; /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + virtual void requestOpenUrls(const QModelIndex &index, const QList &urls) = 0; + + /** * Request the task at the given index be closed. * * @param index An index in this tasks model. diff --git a/libtaskmanager/concatenatetasksproxymodel.h b/libtaskmanager/concatenatetasksproxymodel.h --- a/libtaskmanager/concatenatetasksproxymodel.h +++ b/libtaskmanager/concatenatetasksproxymodel.h @@ -66,6 +66,15 @@ void requestNewInstance(const QModelIndex &index); /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + virtual void requestOpenUrls(const QModelIndex &index, const QList &urls); + + /** * Request the task at the given index be closed. * * @param index An index in this tasks model. diff --git a/libtaskmanager/concatenatetasksproxymodel.cpp b/libtaskmanager/concatenatetasksproxymodel.cpp --- a/libtaskmanager/concatenatetasksproxymodel.cpp +++ b/libtaskmanager/concatenatetasksproxymodel.cpp @@ -64,6 +64,22 @@ } } +void ConcatenateTasksProxyModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (!index.isValid() || index.model() != this) { + return; + } + + const QModelIndex &sourceIndex = mapToSource(index); + const AbstractTasksModelIface *m = dynamic_cast(sourceIndex.model()); + + if (m) { + // NOTE: KConcatenateRowsProxyModel offers no way to get a non-const pointer + // to one of the source models, so we have to go through a mapped index. + const_cast(m)->requestOpenUrls(sourceIndex, urls); + } +} + void ConcatenateTasksProxyModel::requestClose(const QModelIndex &index) { if (!index.isValid() || index.model() != this) { diff --git a/libtaskmanager/flattentaskgroupsproxymodel.h b/libtaskmanager/flattentaskgroupsproxymodel.h --- a/libtaskmanager/flattentaskgroupsproxymodel.h +++ b/libtaskmanager/flattentaskgroupsproxymodel.h @@ -69,6 +69,15 @@ void requestNewInstance(const QModelIndex &index) override; /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + virtual void requestOpenUrls(const QModelIndex &index, const QList &urls); + + /** * Request the task at the given index be closed. * * @param index An index in this tasks model. diff --git a/libtaskmanager/flattentaskgroupsproxymodel.cpp b/libtaskmanager/flattentaskgroupsproxymodel.cpp --- a/libtaskmanager/flattentaskgroupsproxymodel.cpp +++ b/libtaskmanager/flattentaskgroupsproxymodel.cpp @@ -70,6 +70,13 @@ } } +void FlattenTaskGroupsProxyModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (d->sourceTasksModel && index.isValid() && index.model() == this) { + d->sourceTasksModel->requestOpenUrls(mapToSource(index), urls); + } +} + void FlattenTaskGroupsProxyModel::requestClose(const QModelIndex &index) { if (d->sourceTasksModel && index.isValid() && index.model() == this) { diff --git a/libtaskmanager/launchertasksmodel.h b/libtaskmanager/launchertasksmodel.h --- a/libtaskmanager/launchertasksmodel.h +++ b/libtaskmanager/launchertasksmodel.h @@ -132,6 +132,14 @@ */ void requestNewInstance(const QModelIndex &index) override; + /** + * Runs the application backing the launcher at the given index with the given URLs. + * + * @param index An index in this launcher tasks model + * @param urls The URLs to be passed to the application + */ + void requestOpenUrls(const QModelIndex &index, const QList &urls) override; + Q_SIGNALS: void launcherListChanged() const; diff --git a/libtaskmanager/launchertasksmodel.cpp b/libtaskmanager/launchertasksmodel.cpp --- a/libtaskmanager/launchertasksmodel.cpp +++ b/libtaskmanager/launchertasksmodel.cpp @@ -308,4 +308,37 @@ } } +void LauncherTasksModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (!index.isValid() || index.model() != this + || index.row() < 0 || index.row() >= d->launchers.count() + || urls.isEmpty()) { + return; + } + + const QUrl &url = d->launchers.at(index.row()); + + quint32 timeStamp = 0; + +#if HAVE_X11 + if (KWindowSystem::isPlatformX11()) { + timeStamp = QX11Info::appUserTime(); + } +#endif + + KService::Ptr service; + + if (url.scheme() == QLatin1String("preferred")) { + service = KService::serviceByStorageId(defaultApplication(url)); + } else { + service = KService::serviceByDesktopPath(url.toLocalFile()); + } + + if (!service) { + return; + } + + KRun::runApplication(*service, urls, nullptr, false, {}, KStartupInfo::createNewStartupIdForTimestamp(timeStamp)); +} + } diff --git a/libtaskmanager/taskfilterproxymodel.h b/libtaskmanager/taskfilterproxymodel.h --- a/libtaskmanager/taskfilterproxymodel.h +++ b/libtaskmanager/taskfilterproxymodel.h @@ -248,6 +248,15 @@ void requestNewInstance(const QModelIndex &index) override; /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + virtual void requestOpenUrls(const QModelIndex &index, const QList &urls); + + /** * Request the task at the given index be closed. * * @param index An index in this tasks model. diff --git a/libtaskmanager/taskfilterproxymodel.cpp b/libtaskmanager/taskfilterproxymodel.cpp --- a/libtaskmanager/taskfilterproxymodel.cpp +++ b/libtaskmanager/taskfilterproxymodel.cpp @@ -215,6 +215,14 @@ } } +void TaskFilterProxyModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (d->sourceTasksModel && index.isValid() && index.model() == this) { + d->sourceTasksModel->requestOpenUrls(mapToSource(index), urls); + } +} + + void TaskFilterProxyModel::requestClose(const QModelIndex &index) { if (d->sourceTasksModel && index.isValid() && index.model() == this) { diff --git a/libtaskmanager/taskgroupingproxymodel.h b/libtaskmanager/taskgroupingproxymodel.h --- a/libtaskmanager/taskgroupingproxymodel.h +++ b/libtaskmanager/taskgroupingproxymodel.h @@ -212,6 +212,15 @@ void requestNewInstance(const QModelIndex &index) override; /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + virtual void requestOpenUrls(const QModelIndex &index, const QList &urls); + + /** * Request the task at the given index be closed. * * @param index An index in this tasks model. diff --git a/libtaskmanager/taskgroupingproxymodel.cpp b/libtaskmanager/taskgroupingproxymodel.cpp --- a/libtaskmanager/taskgroupingproxymodel.cpp +++ b/libtaskmanager/taskgroupingproxymodel.cpp @@ -938,6 +938,15 @@ d->abstractTasksSourceModel->requestNewInstance(mapToSource(index)); } +void TaskGroupingProxyModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (!d->abstractTasksSourceModel || !index.isValid() || index.model() != this) { + return; + } + + d->abstractTasksSourceModel->requestOpenUrls(mapToSource(index), urls); +} + void TaskGroupingProxyModel::requestClose(const QModelIndex &index) { if (!d->abstractTasksSourceModel || !index.isValid() || index.model() != this) { diff --git a/libtaskmanager/tasksmodel.h b/libtaskmanager/tasksmodel.h --- a/libtaskmanager/tasksmodel.h +++ b/libtaskmanager/tasksmodel.h @@ -577,6 +577,15 @@ Q_INVOKABLE void requestNewInstance(const QModelIndex &index) override; /** + * Requests to open the given URLs with the application backing the task + * at the given index. + * + * @param index An index in this tasks model. + * @param urls The URLs to be passed to the application. + **/ + Q_INVOKABLE void requestOpenUrls(const QModelIndex &index, const QList &urls); + + /** * Request the task at the given index be closed. * * @param index An index in this tasks model. diff --git a/libtaskmanager/tasksmodel.cpp b/libtaskmanager/tasksmodel.cpp --- a/libtaskmanager/tasksmodel.cpp +++ b/libtaskmanager/tasksmodel.cpp @@ -1175,6 +1175,13 @@ } } +void TasksModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (index.isValid() && index.model() == this) { + d->abstractTasksSourceModel->requestOpenUrls(mapToSource(index), urls); + } +} + void TasksModel::requestClose(const QModelIndex &index) { if (index.isValid() && index.model() == this) { diff --git a/libtaskmanager/waylandtasksmodel.h b/libtaskmanager/waylandtasksmodel.h --- a/libtaskmanager/waylandtasksmodel.h +++ b/libtaskmanager/waylandtasksmodel.h @@ -81,6 +81,16 @@ void requestNewInstance(const QModelIndex &index) override; /** + * Runs the application backing the launcher at the given index with the given URLs. + * Success depends on whether a AbstractTasksModel::LauncherUrl could be + * derived from window metadata and a KService could be found from that. + * + * @param index An index in this launcher tasks model + * @param urls The URLs to be passed to the application + */ + void requestOpenUrls(const QModelIndex &index, const QList &urls) override; + + /** * Request the window at the given index be closed. * * @param index An index in this window tasks model. diff --git a/libtaskmanager/waylandtasksmodel.cpp b/libtaskmanager/waylandtasksmodel.cpp --- a/libtaskmanager/waylandtasksmodel.cpp +++ b/libtaskmanager/waylandtasksmodel.cpp @@ -375,6 +375,26 @@ } } +void WaylandTasksModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (!index.isValid() || index.model() != this || index.row() < 0 + || index.row() >= d->windows.count() + || urls.isEmpty()) { + return; + } + + KWayland::Client::PlasmaWindow *window = d->windows.at(index.row()); + + if (d->serviceCache.contains(window)) { + const KService::Ptr service = d->serviceCache.value(window); + + KRun::runApplication(*service, urls, nullptr, false); + + KActivities::ResourceInstance::notifyAccessed(QUrl("applications:" + service->storageId()), + "org.kde.libtaskmanager"); + } +} + void WaylandTasksModel::requestClose(const QModelIndex &index) { if (!index.isValid() || index.model() != this || index.row() < 0 || index.row() >= d->windows.count()) { diff --git a/libtaskmanager/windowtasksmodel.h b/libtaskmanager/windowtasksmodel.h --- a/libtaskmanager/windowtasksmodel.h +++ b/libtaskmanager/windowtasksmodel.h @@ -67,6 +67,16 @@ void requestNewInstance(const QModelIndex &index) override; /** + * Runs the application backing the launcher at the given index with the given URLs. + * Success depends on whether a AbstractTasksModel::LauncherUrl could be + * derived from window metadata and a KService could be found from that. + * + * @param index An index in this launcher tasks model + * @param urls The URLs to be passed to the application + */ + void requestOpenUrls(const QModelIndex &index, const QList &urls) override; + + /** * Request the window at the given index be closed. * * @param index An index in this window tasks model. diff --git a/libtaskmanager/windowtasksmodel.cpp b/libtaskmanager/windowtasksmodel.cpp --- a/libtaskmanager/windowtasksmodel.cpp +++ b/libtaskmanager/windowtasksmodel.cpp @@ -116,6 +116,13 @@ } } +void WindowTasksModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (d->sourceTasksModel && index.isValid() && index.model() == this) { + d->sourceTasksModel->requestOpenUrls(mapToSource(index), urls); + } +} + void WindowTasksModel::requestClose(const QModelIndex &index) { if (d->sourceTasksModel && index.isValid() && index.model() == this) { diff --git a/libtaskmanager/xwindowtasksmodel.h b/libtaskmanager/xwindowtasksmodel.h --- a/libtaskmanager/xwindowtasksmodel.h +++ b/libtaskmanager/xwindowtasksmodel.h @@ -80,6 +80,16 @@ void requestNewInstance(const QModelIndex &index) override; /** + * Runs the application backing the launcher at the given index with the given URLs. + * Success depends on whether a AbstractTasksModel::LauncherUrl could be + * derived from window metadata and a KService could be found from that. + * + * @param index An index in this launcher tasks model + * @param urls The URLs to be passed to the application + */ + void requestOpenUrls(const QModelIndex &index, const QList &urls) override; + + /** * Request the window at the given index be closed. * * @param index An index in this window tasks model. diff --git a/libtaskmanager/xwindowtasksmodel.cpp b/libtaskmanager/xwindowtasksmodel.cpp --- a/libtaskmanager/xwindowtasksmodel.cpp +++ b/libtaskmanager/xwindowtasksmodel.cpp @@ -943,6 +943,21 @@ } } +void XWindowTasksModel::requestOpenUrls(const QModelIndex &index, const QList &urls) +{ + if (!index.isValid() || index.model() != this || index.row() < 0 + || index.row() >= d->windows.count() + || urls.isEmpty()) { + return; + } + + const QUrl &url = d->appData(d->windows.at(index.row())).url; + const KService::Ptr service = KService::serviceByDesktopPath(url.toLocalFile()); + if (service) { + KRun::runApplication(*service, urls, nullptr, false, {}, KStartupInfo::createNewStartupIdForTimestamp(QX11Info::appUserTime())); + } +} + void XWindowTasksModel::requestClose(const QModelIndex &index) { if (!index.isValid() || index.model() != this || index.row() < 0 || index.row() >= d->windows.count()) {