forked from quickshell/quickshell
		
	core/qmlglobal: add execDetached functions for spawning processes
This commit is contained in:
		
							parent
							
								
									0140356d99
								
							
						
					
					
						commit
						0499518143
					
				
					 10 changed files with 167 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
qt_add_library(quickshell-io STATIC
 | 
			
		||||
	datastream.cpp
 | 
			
		||||
	processcore.cpp
 | 
			
		||||
	process.cpp
 | 
			
		||||
	fileview.cpp
 | 
			
		||||
	jsonadapter.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,9 @@
 | 
			
		|||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include <qdir.h>
 | 
			
		||||
#include <qhash.h>
 | 
			
		||||
#include <qlist.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qmap.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qprocess.h>
 | 
			
		||||
#include <qqmlinfo.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -13,10 +13,10 @@
 | 
			
		|||
#include <qtypes.h>
 | 
			
		||||
#include <qvariant.h>
 | 
			
		||||
 | 
			
		||||
#include "../core/common.hpp"
 | 
			
		||||
#include "../core/generation.hpp"
 | 
			
		||||
#include "../core/qmlglobal.hpp"
 | 
			
		||||
#include "datastream.hpp"
 | 
			
		||||
#include "processcore.hpp"
 | 
			
		||||
 | 
			
		||||
Process::Process(QObject* parent): QObject(parent) {
 | 
			
		||||
	QObject::connect(
 | 
			
		||||
| 
						 | 
				
			
			@ -79,9 +79,10 @@ void Process::onGlobalWorkingDirectoryChanged() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QMap<QString, QVariant> Process::environment() const { return this->mEnvironment; }
 | 
			
		||||
QHash<QString, QVariant> Process::environment() const { return this->mEnvironment; }
 | 
			
		||||
 | 
			
		||||
void Process::setEnvironment(QMap<QString, QVariant> environment) {
 | 
			
		||||
void Process::setEnvironment(QHash<QString, QVariant> environment) {
 | 
			
		||||
	qDebug() << "setEnv" << environment;
 | 
			
		||||
	if (environment == this->mEnvironment) return;
 | 
			
		||||
	this->mEnvironment = std::move(environment);
 | 
			
		||||
	emit this->environmentChanged();
 | 
			
		||||
| 
						 | 
				
			
			@ -224,24 +225,7 @@ void Process::setupEnvironment(QProcess* process) {
 | 
			
		|||
		process->setWorkingDirectory(this->mWorkingDirectory);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const auto& sysenv = qs::Common::INITIAL_ENVIRONMENT;
 | 
			
		||||
	auto env = this->mClearEnvironment ? QProcessEnvironment() : sysenv;
 | 
			
		||||
 | 
			
		||||
	for (auto& name: this->mEnvironment.keys()) {
 | 
			
		||||
		auto value = this->mEnvironment.value(name);
 | 
			
		||||
		if (!value.isValid()) continue;
 | 
			
		||||
 | 
			
		||||
		if (this->mClearEnvironment) {
 | 
			
		||||
			if (value.isNull()) {
 | 
			
		||||
				if (sysenv.contains(name)) env.insert(name, sysenv.value(name));
 | 
			
		||||
			} else env.insert(name, value.toString());
 | 
			
		||||
		} else {
 | 
			
		||||
			if (value.isNull()) env.remove(name);
 | 
			
		||||
			else env.insert(name, value.toString());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	process->setProcessEnvironment(env);
 | 
			
		||||
	qs::core::process::setupProcessEnvironment(process, this->mClearEnvironment, this->mEnvironment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Process::onStarted() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qhash.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qprocess.h>
 | 
			
		||||
#include <qqmlintegration.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +99,7 @@ class Process: public QObject {
 | 
			
		|||
	/// 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.
 | 
			
		||||
	Q_PROPERTY(QMap<QString, QVariant> environment READ environment WRITE setEnvironment NOTIFY environmentChanged);
 | 
			
		||||
	Q_PROPERTY(QHash<QString, QVariant> environment READ environment WRITE setEnvironment NOTIFY environmentChanged);
 | 
			
		||||
	/// If the process's environment should be cleared prior to applying @@environment.
 | 
			
		||||
	/// Defaults to false.
 | 
			
		||||
	///
 | 
			
		||||
| 
						 | 
				
			
			@ -140,10 +141,12 @@ public:
 | 
			
		|||
	/// Writes to the process's stdin. Does nothing if @@running is false.
 | 
			
		||||
	Q_INVOKABLE void write(const QString& data);
 | 
			
		||||
 | 
			
		||||
	/// Launches an instance of the process detached from quickshell.
 | 
			
		||||
	/// Launches an instance of the process detached from Quickshell.
 | 
			
		||||
	///
 | 
			
		||||
	/// The subprocess will not be tracked, @@running will be false,
 | 
			
		||||
	/// and the subprocess will not be killed by Quickshell.
 | 
			
		||||
	///
 | 
			
		||||
	/// This function is equivalent to @@Quickshell.Quickshell.execDetached().
 | 
			
		||||
	Q_INVOKABLE void startDetached();
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] bool isRunning() const;
 | 
			
		||||
| 
						 | 
				
			
			@ -157,8 +160,8 @@ public:
 | 
			
		|||
	[[nodiscard]] QString workingDirectory() const;
 | 
			
		||||
	void setWorkingDirectory(const QString& workingDirectory);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] QMap<QString, QVariant> environment() const;
 | 
			
		||||
	void setEnvironment(QMap<QString, QVariant> environment);
 | 
			
		||||
	[[nodiscard]] QHash<QString, QVariant> environment() const;
 | 
			
		||||
	void setEnvironment(QHash<QString, QVariant> environment);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] bool environmentCleared() const;
 | 
			
		||||
	void setEnvironmentCleared(bool cleared);
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +206,7 @@ private:
 | 
			
		|||
	QProcess* process = nullptr;
 | 
			
		||||
	QList<QString> mCommand;
 | 
			
		||||
	QString mWorkingDirectory;
 | 
			
		||||
	QMap<QString, QVariant> mEnvironment;
 | 
			
		||||
	QHash<QString, QVariant> mEnvironment;
 | 
			
		||||
	DataStreamParser* mStdoutParser = nullptr;
 | 
			
		||||
	DataStreamParser* mStderrParser = nullptr;
 | 
			
		||||
	QByteArray stdoutBuffer;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										37
									
								
								src/io/processcore.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/io/processcore.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
#include "processcore.hpp"
 | 
			
		||||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qhash.h>
 | 
			
		||||
#include <qprocess.h>
 | 
			
		||||
#include <qvariant.h>
 | 
			
		||||
 | 
			
		||||
#include "../core/common.hpp"
 | 
			
		||||
 | 
			
		||||
namespace qs::core::process {
 | 
			
		||||
 | 
			
		||||
void setupProcessEnvironment(
 | 
			
		||||
    QProcess* process,
 | 
			
		||||
    bool clear,
 | 
			
		||||
    const QHash<QString, QVariant>& envChanges
 | 
			
		||||
) {
 | 
			
		||||
	const auto& sysenv = qs::Common::INITIAL_ENVIRONMENT;
 | 
			
		||||
	auto env = clear ? QProcessEnvironment() : sysenv;
 | 
			
		||||
 | 
			
		||||
	for (auto& name: envChanges.keys()) {
 | 
			
		||||
		auto value = envChanges.value(name);
 | 
			
		||||
		if (!value.isValid()) continue;
 | 
			
		||||
 | 
			
		||||
		if (clear) {
 | 
			
		||||
			if (value.isNull()) {
 | 
			
		||||
				if (sysenv.contains(name)) env.insert(name, sysenv.value(name));
 | 
			
		||||
			} else env.insert(name, value.toString());
 | 
			
		||||
		} else {
 | 
			
		||||
			if (value.isNull()) env.remove(name);
 | 
			
		||||
			else env.insert(name, value.toString());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	process->setProcessEnvironment(env);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace qs::core::process
 | 
			
		||||
							
								
								
									
										16
									
								
								src/io/processcore.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/io/processcore.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qhash.h>
 | 
			
		||||
#include <qprocess.h>
 | 
			
		||||
#include <qvariant.h>
 | 
			
		||||
 | 
			
		||||
namespace qs::core::process {
 | 
			
		||||
 | 
			
		||||
void setupProcessEnvironment(
 | 
			
		||||
    QProcess* process,
 | 
			
		||||
    bool clear,
 | 
			
		||||
    const QHash<QString, QVariant>& envChanges
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
function (qs_test name)
 | 
			
		||||
	add_executable(${name} ${ARGN})
 | 
			
		||||
	target_link_libraries(${name} PRIVATE Qt::Quick Qt::Network Qt::Test)
 | 
			
		||||
	target_link_libraries(${name} PRIVATE Qt::Quick Qt::Network Qt::Test quickshell-io)
 | 
			
		||||
	add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue