Skip to content

Commit f53aea9

Browse files
committed
core/desktopentry: expose exec command and use execDetached on call
1 parent ccdb136 commit f53aea9

File tree

4 files changed

+58
-26
lines changed

4 files changed

+58
-26
lines changed

src/core/common.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
#include "common.hpp"
22

33
#include <qdatetime.h>
4-
#include <qprocess.h>
54

65
namespace qs {
76

87
const QDateTime Common::LAUNCH_TIME = QDateTime::currentDateTime();
9-
QProcessEnvironment Common::INITIAL_ENVIRONMENT = {}; // NOLINT
108

119
} // namespace qs

src/core/common.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace qs {
77

88
struct Common {
99
static const QDateTime LAUNCH_TIME;
10-
static QProcessEnvironment INITIAL_ENVIRONMENT; // NOLINT
10+
static inline QProcessEnvironment INITIAL_ENVIRONMENT = {}; // NOLINT
1111
};
1212

1313
} // namespace qs

src/core/desktopentry.cpp

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
#include <qnamespace.h>
1212
#include <qobject.h>
1313
#include <qpair.h>
14-
#include <qprocess.h>
1514
#include <qstringview.h>
1615
#include <qtenvironmentvariables.h>
1716
#include <ranges>
1817

19-
#include "common.hpp"
18+
#include "../io/processcore.hpp"
2019
#include "logcat.hpp"
2120
#include "model.hpp"
21+
#include "qmlglobal.hpp"
2222

2323
namespace {
2424
QS_LOGGING_CATEGORY(logDesktopEntry, "quickshell.desktopentry", QtWarningMsg);
@@ -111,8 +111,10 @@ void DesktopEntry::parseEntry(const QString& text) {
111111
else if (key == "NoDisplay") this->mNoDisplay = value == "true";
112112
else if (key == "Comment") this->mComment = value;
113113
else if (key == "Icon") this->mIcon = value;
114-
else if (key == "Exec") this->mExecString = value;
115-
else if (key == "Path") this->mWorkingDirectory = value;
114+
else if (key == "Exec") {
115+
this->mExecString = value;
116+
this->mCommand = DesktopEntry::parseExecString(value);
117+
} else if (key == "Path") this->mWorkingDirectory = value;
116118
else if (key == "Terminal") this->mTerminal = value == "true";
117119
else if (key == "Categories") this->mCategories = value.split(u';', Qt::SkipEmptyParts);
118120
else if (key == "Keywords") this->mKeywords = value.split(u';', Qt::SkipEmptyParts);
@@ -127,7 +129,10 @@ void DesktopEntry::parseEntry(const QString& text) {
127129

128130
if (key == "Name") action->mName = value;
129131
else if (key == "Icon") action->mIcon = value;
130-
else if (key == "Exec") action->mExecString = value;
132+
else if (key == "Exec") {
133+
action->mExecString = value;
134+
action->mCommand = DesktopEntry::parseExecString(value);
135+
}
131136
}
132137

133138
this->mActions.insert(actionName, action);
@@ -179,7 +184,7 @@ void DesktopEntry::parseEntry(const QString& text) {
179184
}
180185

181186
void DesktopEntry::execute() const {
182-
DesktopEntry::doExec(this->mExecString, this->mWorkingDirectory);
187+
DesktopEntry::doExec(this->mCommand, this->mWorkingDirectory);
183188
}
184189

185190
bool DesktopEntry::isValid() const { return !this->mName.isEmpty(); }
@@ -251,23 +256,15 @@ QVector<QString> DesktopEntry::parseExecString(const QString& execString) {
251256
return arguments;
252257
}
253258

254-
void DesktopEntry::doExec(const QString& execString, const QString& workingDirectory) {
255-
auto args = DesktopEntry::parseExecString(execString);
256-
if (args.isEmpty()) {
257-
qCWarning(logDesktopEntry) << "Tried to exec string" << execString << "which parsed as empty.";
258-
return;
259-
}
260-
261-
auto process = QProcess();
262-
process.setProgram(args.at(0));
263-
process.setArguments(args.sliced(1));
264-
if (!workingDirectory.isEmpty()) process.setWorkingDirectory(workingDirectory);
265-
process.setProcessEnvironment(qs::Common::INITIAL_ENVIRONMENT);
266-
process.startDetached();
259+
void DesktopEntry::doExec(const QList<QString>& execString, const QString& workingDirectory) {
260+
qs::io::process::ProcessContext ctx;
261+
ctx.setCommand(execString);
262+
ctx.setWorkingDirectory(workingDirectory);
263+
QuickshellGlobal::execDetached(ctx);
267264
}
268265

269266
void DesktopAction::execute() const {
270-
DesktopEntry::doExec(this->mExecString, this->entry->mWorkingDirectory);
267+
DesktopEntry::doExec(this->mCommand, this->entry->mWorkingDirectory);
271268
}
272269

273270
DesktopEntryManager::DesktopEntryManager() {

src/core/desktopentry.hpp

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,19 @@ class DesktopEntry: public QObject {
2828
Q_PROPERTY(QString comment MEMBER mComment CONSTANT);
2929
/// Name of the icon associated with this application. May be empty.
3030
Q_PROPERTY(QString icon MEMBER mIcon CONSTANT);
31-
/// The raw `Exec` string from the desktop entry. You probably want @@execute().
31+
/// The raw `Exec` string from the desktop entry.
32+
///
33+
/// > [!WARNING] This cannot be reliably run as a command. See @@command for one you can run.
3234
Q_PROPERTY(QString execString MEMBER mExecString CONSTANT);
35+
/// The parsed `Exec` command in the desktop entry.
36+
///
37+
/// The entry can be run with @@execute(), or by using this command in
38+
/// @@Quickshell.Quickshell.execDetached() or @@Quickshell.Io.Process.
39+
/// If used in `execDetached` or a `Process`, @@workingDirectory should also be passed to
40+
/// the invoked process. See @@execute() for details.
41+
///
42+
/// > [!NOTE] The provided command does not invoke a terminal even if @@runInTerminal is true.
43+
Q_PROPERTY(QVector<QString> command MEMBER mCommand CONSTANT);
3344
/// The working directory to execute from.
3445
Q_PROPERTY(QString workingDirectory MEMBER mWorkingDirectory CONSTANT);
3546
/// If the application should run in a terminal.
@@ -46,6 +57,16 @@ class DesktopEntry: public QObject {
4657
void parseEntry(const QString& text);
4758

4859
/// Run the application. Currently ignores @@runInTerminal and field codes.
60+
///
61+
/// This is equivalent to calling @@Quickshell.Quickshell.execDetached() with @@command
62+
/// and @@DesktopEntry.workingDirectory as shown below:
63+
///
64+
/// ```qml
65+
/// Quickshell.execDetached({
66+
/// command: desktopEntry.command,
67+
/// workingDirectory: desktopEntry.workingDirectory,
68+
/// });
69+
/// ```
4970
Q_INVOKABLE void execute() const;
5071

5172
[[nodiscard]] bool isValid() const;
@@ -54,7 +75,7 @@ class DesktopEntry: public QObject {
5475

5576
// currently ignores all field codes.
5677
static QVector<QString> parseExecString(const QString& execString);
57-
static void doExec(const QString& execString, const QString& workingDirectory);
78+
static void doExec(const QList<QString>& execString, const QString& workingDirectory);
5879

5980
public:
6081
QString mId;
@@ -64,6 +85,7 @@ class DesktopEntry: public QObject {
6485
QString mComment;
6586
QString mIcon;
6687
QString mExecString;
88+
QVector<QString> mCommand;
6789
QString mWorkingDirectory;
6890
bool mTerminal = false;
6991
QVector<QString> mCategories;
@@ -82,8 +104,19 @@ class DesktopAction: public QObject {
82104
Q_PROPERTY(QString id MEMBER mId CONSTANT);
83105
Q_PROPERTY(QString name MEMBER mName CONSTANT);
84106
Q_PROPERTY(QString icon MEMBER mIcon CONSTANT);
85-
/// The raw `Exec` string from the desktop entry. You probably want @@execute().
107+
/// The raw `Exec` string from the action.
108+
///
109+
/// > [!WARNING] This cannot be reliably run as a command. See @@command for one you can run.
86110
Q_PROPERTY(QString execString MEMBER mExecString CONSTANT);
111+
/// The parsed `Exec` command in the action.
112+
///
113+
/// The entry can be run with @@execute(), or by using this command in
114+
/// @@Quickshell.Quickshell.execDetached() or @@Quickshell.Io.Process.
115+
/// If used in `execDetached` or a `Process`, @@DesktopEntry.workingDirectory should also be passed to
116+
/// the invoked process.
117+
///
118+
/// > [!NOTE] The provided command does not invoke a terminal even if @@runInTerminal is true.
119+
Q_PROPERTY(QVector<QString> command MEMBER mCommand CONSTANT);
87120
QML_ELEMENT;
88121
QML_UNCREATABLE("DesktopAction instances must be retrieved from a DesktopEntry");
89122

@@ -94,6 +127,9 @@ class DesktopAction: public QObject {
94127
, mId(std::move(id)) {}
95128

96129
/// Run the application. Currently ignores @@DesktopEntry.runInTerminal and field codes.
130+
///
131+
/// This is equivalent to calling @@Quickshell.Quickshell.execDetached() with @@command
132+
/// and @@DesktopEntry.workingDirectory.
97133
Q_INVOKABLE void execute() const;
98134

99135
private:
@@ -102,6 +138,7 @@ class DesktopAction: public QObject {
102138
QString mName;
103139
QString mIcon;
104140
QString mExecString;
141+
QVector<QString> mCommand;
105142
QHash<QString, QString> mEntries;
106143

107144
friend class DesktopEntry;

0 commit comments

Comments
 (0)