forked from quickshell/quickshell
feat: add support for getting and setting workdir
This commit is contained in:
parent
b5f50cd68f
commit
bbe64f42f3
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
#include <qcontainerfwd.h>
|
#include <qcontainerfwd.h>
|
||||||
#include <qcoreapplication.h>
|
#include <qcoreapplication.h>
|
||||||
|
#include <qdir.h>
|
||||||
#include <qguiapplication.h>
|
#include <qguiapplication.h>
|
||||||
|
#include <qjsengine.h>
|
||||||
#include <qlogging.h>
|
#include <qlogging.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qqmlcontext.h>
|
#include <qqmlcontext.h>
|
||||||
|
@ -83,3 +85,29 @@ QVariant QuickshellGlobal::env(const QString& variable) { // NOLINT
|
||||||
|
|
||||||
return qEnvironmentVariable(vstr.data());
|
return qEnvironmentVariable(vstr.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QuickshellGlobal::workingDirectory() const { // NOLINT
|
||||||
|
return QDir::current().absolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickshellGlobal::setWorkingDirectory(const QString& workingDirectory) { // NOLINT
|
||||||
|
QDir::setCurrent(workingDirectory);
|
||||||
|
emit this->workingDirectoryChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
static QuickshellGlobal* g_instance = nullptr; // NOLINT
|
||||||
|
|
||||||
|
QuickshellGlobal* QuickshellGlobal::create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/) {
|
||||||
|
return QuickshellGlobal::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
QuickshellGlobal* QuickshellGlobal::instance() {
|
||||||
|
if (g_instance == nullptr) g_instance = new QuickshellGlobal();
|
||||||
|
QJSEngine::setObjectOwnership(g_instance, QJSEngine::CppOwnership);
|
||||||
|
return g_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickshellGlobal::deleteInstance() {
|
||||||
|
delete g_instance;
|
||||||
|
g_instance = nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <qcontainerfwd.h>
|
#include <qcontainerfwd.h>
|
||||||
|
#include <qjsengine.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
|
#include <qqmlengine.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qqmllist.h>
|
#include <qqmllist.h>
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
|
@ -12,6 +14,7 @@
|
||||||
|
|
||||||
class QuickshellGlobal: public QObject {
|
class QuickshellGlobal: public QObject {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
// clang-format off
|
||||||
/// All currently connected screens.
|
/// All currently connected screens.
|
||||||
///
|
///
|
||||||
/// This property updates as connected screens change.
|
/// This property updates as connected screens change.
|
||||||
|
@ -33,6 +36,9 @@ class QuickshellGlobal: public QObject {
|
||||||
/// This creates an instance of your window once on every screen.
|
/// This creates an instance of your window once on every screen.
|
||||||
/// As screens are added or removed your window will be created or destroyed on those screens.
|
/// As screens are added or removed your window will be created or destroyed on those screens.
|
||||||
Q_PROPERTY(QQmlListProperty<QuickshellScreenInfo> screens READ screens NOTIFY screensChanged);
|
Q_PROPERTY(QQmlListProperty<QuickshellScreenInfo> screens READ screens NOTIFY screensChanged);
|
||||||
|
/// Quickshell's working directory. Defaults to whereever quickshell was launched from.
|
||||||
|
Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory NOTIFY workingDirectoryChanged);
|
||||||
|
// clang-format on
|
||||||
QML_SINGLETON;
|
QML_SINGLETON;
|
||||||
QML_NAMED_ELEMENT(Quickshell);
|
QML_NAMED_ELEMENT(Quickshell);
|
||||||
|
|
||||||
|
@ -54,8 +60,16 @@ public:
|
||||||
/// Returns the string value of an environment variable or null if it is not set.
|
/// Returns the string value of an environment variable or null if it is not set.
|
||||||
Q_INVOKABLE QVariant env(const QString& variable);
|
Q_INVOKABLE QVariant env(const QString& variable);
|
||||||
|
|
||||||
|
[[nodiscard]] QString workingDirectory() const;
|
||||||
|
void setWorkingDirectory(const QString& workingDirectory);
|
||||||
|
|
||||||
|
static QuickshellGlobal* create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/);
|
||||||
|
static QuickshellGlobal* instance();
|
||||||
|
static void deleteInstance();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void screensChanged();
|
void screensChanged();
|
||||||
|
void workingDirectoryChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateScreens();
|
void updateScreens();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <qdir.h>
|
||||||
#include <qfileinfo.h>
|
#include <qfileinfo.h>
|
||||||
#include <qlogging.h>
|
#include <qlogging.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
#include <qtimer.h>
|
#include <qtimer.h>
|
||||||
#include <qurl.h>
|
#include <qurl.h>
|
||||||
|
|
||||||
|
#include "qmlglobal.hpp"
|
||||||
#include "reload.hpp"
|
#include "reload.hpp"
|
||||||
#include "shell.hpp"
|
#include "shell.hpp"
|
||||||
#include "watcher.hpp"
|
#include "watcher.hpp"
|
||||||
|
@ -17,7 +19,8 @@
|
||||||
RootWrapper::RootWrapper(QString rootPath)
|
RootWrapper::RootWrapper(QString rootPath)
|
||||||
: QObject(nullptr)
|
: QObject(nullptr)
|
||||||
, rootPath(std::move(rootPath))
|
, rootPath(std::move(rootPath))
|
||||||
, engine(this) {
|
, engine(this)
|
||||||
|
, originalWorkingDirectory(QDir::current().absolutePath()) {
|
||||||
this->reloadGraph(true);
|
this->reloadGraph(true);
|
||||||
|
|
||||||
if (this->root == nullptr) {
|
if (this->root == nullptr) {
|
||||||
|
@ -28,14 +31,19 @@ RootWrapper::RootWrapper(QString rootPath)
|
||||||
|
|
||||||
RootWrapper::~RootWrapper() {
|
RootWrapper::~RootWrapper() {
|
||||||
// event loop may no longer be running so deleteLater is not an option
|
// event loop may no longer be running so deleteLater is not an option
|
||||||
|
QuickshellGlobal::deleteInstance();
|
||||||
delete this->root;
|
delete this->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWrapper::reloadGraph(bool hard) {
|
void RootWrapper::reloadGraph(bool hard) {
|
||||||
|
QuickshellGlobal::deleteInstance();
|
||||||
|
|
||||||
if (this->root != nullptr) {
|
if (this->root != nullptr) {
|
||||||
this->engine.clearComponentCache();
|
this->engine.clearComponentCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDir::setCurrent(this->originalWorkingDirectory);
|
||||||
|
|
||||||
auto component = QQmlComponent(&this->engine, QUrl::fromLocalFile(this->rootPath));
|
auto component = QQmlComponent(&this->engine, QUrl::fromLocalFile(this->rootPath));
|
||||||
|
|
||||||
auto* obj = component.beginCreate(this->engine.rootContext());
|
auto* obj = component.beginCreate(this->engine.rootContext());
|
||||||
|
|
|
@ -28,4 +28,5 @@ private:
|
||||||
QQmlEngine engine;
|
QQmlEngine engine;
|
||||||
ShellRoot* root = nullptr;
|
ShellRoot* root = nullptr;
|
||||||
FiletreeWatcher* configWatcher = nullptr;
|
FiletreeWatcher* configWatcher = nullptr;
|
||||||
|
QString originalWorkingDirectory;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "shell.hpp"
|
#include "shell.hpp"
|
||||||
|
|
||||||
|
#include <qdir.h>
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
void ShellRoot::setConfig(ShellConfig config) {
|
void ShellRoot::setConfig(ShellConfig config) {
|
||||||
|
@ -9,3 +10,7 @@ void ShellRoot::setConfig(ShellConfig config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShellConfig ShellRoot::config() const { return this->mConfig; }
|
ShellConfig ShellRoot::config() const { return this->mConfig; }
|
||||||
|
|
||||||
|
void ShellConfig::setWorkingDirectory(const QString& workingDirectory) { // NOLINT
|
||||||
|
QDir::setCurrent(workingDirectory);
|
||||||
|
}
|
||||||
|
|
|
@ -10,9 +10,12 @@
|
||||||
class ShellConfig {
|
class ShellConfig {
|
||||||
Q_GADGET;
|
Q_GADGET;
|
||||||
Q_PROPERTY(bool watchFiles MEMBER mWatchFiles);
|
Q_PROPERTY(bool watchFiles MEMBER mWatchFiles);
|
||||||
|
Q_PROPERTY(QString workingDirectory WRITE setWorkingDirectory);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool mWatchFiles = true;
|
bool mWatchFiles = true;
|
||||||
|
|
||||||
|
void setWorkingDirectory(const QString& workingDirectory);
|
||||||
};
|
};
|
||||||
|
|
||||||
///! Root config element
|
///! Root config element
|
||||||
|
@ -20,6 +23,8 @@ class ShellRoot: public ReloadPropagator {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
/// If `config.watchFiles` is true the configuration will be reloaded whenever it changes.
|
/// If `config.watchFiles` is true the configuration will be reloaded whenever it changes.
|
||||||
/// Defaults to true.
|
/// Defaults to true.
|
||||||
|
///
|
||||||
|
/// `config.workingDirectory` corrosponds to [Quickshell.workingDirectory](../quickshell#prop.workingDirectory).
|
||||||
Q_PROPERTY(ShellConfig config READ config WRITE setConfig);
|
Q_PROPERTY(ShellConfig config READ config WRITE setConfig);
|
||||||
QML_ELEMENT;
|
QML_ELEMENT;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <csignal> // NOLINT
|
#include <csignal> // NOLINT
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <qdir.h>
|
||||||
#include <qlist.h>
|
#include <qlist.h>
|
||||||
#include <qlogging.h>
|
#include <qlogging.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
|
@ -9,8 +10,18 @@
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
#include <qtypes.h>
|
#include <qtypes.h>
|
||||||
|
|
||||||
|
#include "../core/qmlglobal.hpp"
|
||||||
#include "datastream.hpp"
|
#include "datastream.hpp"
|
||||||
|
|
||||||
|
Process::Process(QObject* parent): QObject(parent) {
|
||||||
|
QObject::connect(
|
||||||
|
QuickshellGlobal::instance(),
|
||||||
|
&QuickshellGlobal::workingDirectoryChanged,
|
||||||
|
this,
|
||||||
|
&Process::onGlobalWorkingDirectoryChanged
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
bool Process::isRunning() const { return this->process != nullptr; }
|
bool Process::isRunning() const { return this->process != nullptr; }
|
||||||
|
|
||||||
void Process::setRunning(bool running) {
|
void Process::setRunning(bool running) {
|
||||||
|
@ -24,6 +35,25 @@ QVariant Process::pid() const {
|
||||||
return QVariant::fromValue(this->process->processId());
|
return QVariant::fromValue(this->process->processId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Process::workingDirectory() const {
|
||||||
|
if (this->mWorkingDirectory.isEmpty()) return QDir::current().absolutePath();
|
||||||
|
else return this->mWorkingDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::setWorkingDirectory(const QString& workingDirectory) {
|
||||||
|
auto absolute =
|
||||||
|
workingDirectory.isEmpty() ? workingDirectory : QDir(workingDirectory).absolutePath();
|
||||||
|
if (absolute == this->mWorkingDirectory) return;
|
||||||
|
this->mWorkingDirectory = absolute;
|
||||||
|
emit this->workingDirectoryChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::onGlobalWorkingDirectoryChanged() {
|
||||||
|
if (this->mWorkingDirectory.isEmpty()) {
|
||||||
|
emit this->workingDirectoryChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<QString> Process::command() const { return this->mCommand; }
|
QList<QString> Process::command() const { return this->mCommand; }
|
||||||
|
|
||||||
void Process::setCommand(QList<QString> command) {
|
void Process::setCommand(QList<QString> command) {
|
||||||
|
@ -137,6 +167,8 @@ void Process::startProcessIfReady() {
|
||||||
if (this->mStderrParser == nullptr) this->process->closeReadChannel(QProcess::StandardError);
|
if (this->mStderrParser == nullptr) this->process->closeReadChannel(QProcess::StandardError);
|
||||||
if (!this->mStdinEnabled) this->process->closeWriteChannel();
|
if (!this->mStdinEnabled) this->process->closeWriteChannel();
|
||||||
|
|
||||||
|
if (!this->mWorkingDirectory.isEmpty())
|
||||||
|
this->process->setWorkingDirectory(this->mWorkingDirectory);
|
||||||
this->process->start(cmd, args);
|
this->process->start(cmd, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,14 @@ class Process: public QObject {
|
||||||
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged);
|
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged);
|
||||||
/// The process ID of the running process or `null` if `running` is false.
|
/// The process ID of the running process or `null` if `running` is false.
|
||||||
Q_PROPERTY(QVariant pid READ pid NOTIFY pidChanged);
|
Q_PROPERTY(QVariant pid READ pid NOTIFY pidChanged);
|
||||||
|
/// The working directory of the process. Defaults to [quickshell's working directory].
|
||||||
|
///
|
||||||
|
/// If the process is already running changing this property will affect the next
|
||||||
|
/// started process. If the property has been changed after starting a process it will
|
||||||
|
/// return the new value, not the one for the currently running process.
|
||||||
|
///
|
||||||
|
/// [quickshell's working directory]: ../../quickshell/quickshell#prop.workingDirectory
|
||||||
|
Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory NOTIFY workingDirectoryChanged);
|
||||||
/// The command to execute.
|
/// The command to execute.
|
||||||
///
|
///
|
||||||
/// If the process is already running changing this property will affect the next
|
/// If the process is already running changing this property will affect the next
|
||||||
|
@ -64,7 +72,7 @@ class Process: public QObject {
|
||||||
QML_ELEMENT;
|
QML_ELEMENT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Process(QObject* parent = nullptr): QObject(parent) {}
|
explicit Process(QObject* parent = nullptr);
|
||||||
|
|
||||||
/// Sends a signal to the process if `running` is true, otherwise does nothing.
|
/// Sends a signal to the process if `running` is true, otherwise does nothing.
|
||||||
Q_INVOKABLE void signal(qint32 signal);
|
Q_INVOKABLE void signal(qint32 signal);
|
||||||
|
@ -77,6 +85,9 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] QVariant pid() const;
|
[[nodiscard]] QVariant pid() const;
|
||||||
|
|
||||||
|
[[nodiscard]] QString workingDirectory() const;
|
||||||
|
void setWorkingDirectory(const QString& workingDirectory);
|
||||||
|
|
||||||
[[nodiscard]] QList<QString> command() const;
|
[[nodiscard]] QList<QString> command() const;
|
||||||
void setCommand(QList<QString> command);
|
void setCommand(QList<QString> command);
|
||||||
|
|
||||||
|
@ -95,6 +106,7 @@ signals:
|
||||||
|
|
||||||
void runningChanged();
|
void runningChanged();
|
||||||
void pidChanged();
|
void pidChanged();
|
||||||
|
void workingDirectoryChanged();
|
||||||
void commandChanged();
|
void commandChanged();
|
||||||
void stdoutParserChanged();
|
void stdoutParserChanged();
|
||||||
void stderrParserChanged();
|
void stderrParserChanged();
|
||||||
|
@ -108,11 +120,13 @@ private slots:
|
||||||
void onStderrReadyRead();
|
void onStderrReadyRead();
|
||||||
void onStdoutParserDestroyed();
|
void onStdoutParserDestroyed();
|
||||||
void onStderrParserDestroyed();
|
void onStderrParserDestroyed();
|
||||||
|
void onGlobalWorkingDirectoryChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startProcessIfReady();
|
void startProcessIfReady();
|
||||||
|
|
||||||
QProcess* process = nullptr;
|
QProcess* process = nullptr;
|
||||||
|
QString mWorkingDirectory;
|
||||||
QList<QString> mCommand;
|
QList<QString> mCommand;
|
||||||
DataStreamParser* mStdoutParser = nullptr;
|
DataStreamParser* mStdoutParser = nullptr;
|
||||||
DataStreamParser* mStderrParser = nullptr;
|
DataStreamParser* mStderrParser = nullptr;
|
||||||
|
|
Loading…
Reference in a new issue