mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-04-25 07:19:39 -05:00
Add process path check
This commit is contained in:
parent
ba38b8bf27
commit
99629e8c66
|
|
@ -211,8 +211,8 @@ AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft"
|
|||
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt"
|
||||
AdvSceneSwitcher.condition.process="Prozess"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}läuft{{focused}}und ist fokusiert"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}läuft{{focused}}und ist fokusiert"
|
||||
AdvSceneSwitcher.condition.process.layout.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.idle="Leerlauf"
|
||||
AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Plugin-Status"
|
||||
|
|
|
|||
|
|
@ -484,8 +484,9 @@ AdvSceneSwitcher.condition.record.state.stop="Recording stopped"
|
|||
AdvSceneSwitcher.condition.record.state.duration="Recording duration is longer than"
|
||||
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||
AdvSceneSwitcher.condition.process="Process"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}is running{{focused}}and is focused"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="Current foreground process:{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}is running{{focused}}and is focused"
|
||||
AdvSceneSwitcher.condition.process.layout.focus="Current foreground process:{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout.path="{{checkPath}}Match binary path:{{path}}{{pathRegex}}"
|
||||
AdvSceneSwitcher.condition.idle="Idle"
|
||||
AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for{{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Plugin state"
|
||||
|
|
@ -2312,6 +2313,7 @@ AdvSceneSwitcher.tempVar.macro.info.secondsSinceLastRun="Seconds since last run"
|
|||
AdvSceneSwitcher.tempVar.macro.info.secondsSinceLastRun.description="The number of seconds elapsed since the macro was last executed. Value is -1 if the macro has never been executed."
|
||||
|
||||
AdvSceneSwitcher.tempVar.process.name="Process name"
|
||||
AdvSceneSwitcher.tempVar.process.path="Process path"
|
||||
|
||||
AdvSceneSwitcher.tempVar.run.process.id="Process ID"
|
||||
AdvSceneSwitcher.tempVar.run.process.id.description="PID of the process assigned by the system."
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
|
|||
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Grabación detenida"
|
||||
AdvSceneSwitcher.condition.process="Proceso"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}se está ejecutando{{focused}}y está enfocado"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}se está ejecutando{{focused}}y está enfocado"
|
||||
AdvSceneSwitcher.condition.idle="Inactivo"
|
||||
AdvSceneSwitcher.condition.idle.entry="No hay entradas de teclado o ratón durante {{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Estado del complemento"
|
||||
|
|
|
|||
|
|
@ -279,8 +279,8 @@ AdvSceneSwitcher.condition.record.state.start="Enregistrement en cours"
|
|||
AdvSceneSwitcher.condition.record.state.pause="Enregistrement en pause"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Arrêt de l'enregistrement"
|
||||
AdvSceneSwitcher.condition.process="Processus"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}en cours d'exécution{{focused}}et est au premier plan"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="Processus au premier plan actuel :{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}en cours d'exécution{{focused}}et est au premier plan"
|
||||
AdvSceneSwitcher.condition.process.layout.focus="Processus au premier plan actuel :{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.idle="Inactif"
|
||||
AdvSceneSwitcher.condition.idle.entry="Aucune entrée de clavier ou de souris pendant{{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="État du plugin"
|
||||
|
|
|
|||
|
|
@ -445,8 +445,8 @@ AdvSceneSwitcher.condition.stream.service.tooltip="現在のサービス名: %1"
|
|||
AdvSceneSwitcher.condition.record.state.duration="録音時間が長くなっています。"
|
||||
; AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||
AdvSceneSwitcher.condition.process="プロセス"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}が実行中{{focused}}に集中しています"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="現在のフォアグラウンドプロセス:{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}が実行中{{focused}}に集中しています"
|
||||
AdvSceneSwitcher.condition.process.layout.focus="現在のフォアグラウンドプロセス:{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.idle="アイドル"
|
||||
AdvSceneSwitcher.condition.idle.entry="{{duration}}の間、キーボードまたはマウスの入力がありません"
|
||||
AdvSceneSwitcher.condition.pluginState="プラグインの状態"
|
||||
|
|
|
|||
|
|
@ -395,8 +395,8 @@ AdvSceneSwitcher.condition.record.state.stop="Gravação parada"
|
|||
AdvSceneSwitcher.condition.record.state.duration="Duração da gravação é maior que"
|
||||
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||
AdvSceneSwitcher.condition.process="Processo"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}está em execução{{focused}}e está em foco"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="Processo atual em primeiro plano:{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}está em execução{{focused}}e está em foco"
|
||||
AdvSceneSwitcher.condition.process.layout.focus="Processo atual em primeiro plano:{{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.idle="Inativo"
|
||||
AdvSceneSwitcher.condition.idle.entry="Sem entradas de teclado ou mouse por {{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Estado do plugin"
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ AdvSceneSwitcher.condition.record.state.start="Запись запущена"
|
|||
AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Запись остановлена"
|
||||
AdvSceneSwitcher.condition.process="Процесс"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}запущен{{focused}}и сфокусирован"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}запущен{{focused}}и сфокусирован"
|
||||
AdvSceneSwitcher.condition.idle="Простой"
|
||||
AdvSceneSwitcher.condition.idle.entry="Не было ни клавиатуры, ни мыши в течении{{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Состояние плагина"
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
|
|||
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Kayıt durdu"
|
||||
AdvSceneSwitcher.condition.process="İşlem"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}çalışıyor{{focused}}ve odaklandı"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}çalışıyor{{focused}}ve odaklandı"
|
||||
AdvSceneSwitcher.condition.idle="Boşta"
|
||||
AdvSceneSwitcher.condition.idle.entry="...için klavye veya fare girişi yok {{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Eklenti durumu"
|
||||
|
|
|
|||
|
|
@ -424,8 +424,8 @@ AdvSceneSwitcher.condition.record.state.stop="录制停止"
|
|||
AdvSceneSwitcher.condition.record.state.duration="录制时间长于"
|
||||
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||
AdvSceneSwitcher.condition.process="进程"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}为正在运行中{{focused}}且为焦点"
|
||||
AdvSceneSwitcher.condition.process.entry.focus="当前焦点进程: {{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}为正在运行中{{focused}}且为焦点"
|
||||
AdvSceneSwitcher.condition.process.layout.focus="当前焦点进程: {{focusProcess}}"
|
||||
AdvSceneSwitcher.condition.idle="闲置检测"
|
||||
AdvSceneSwitcher.condition.idle.entry="{{duration}}内没有键盘或鼠标输入"
|
||||
AdvSceneSwitcher.condition.pluginState="插件状态"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
#endif
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <climits>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include "kwin-helpers.h"
|
||||
|
||||
namespace advss {
|
||||
|
|
@ -483,6 +486,74 @@ void GetForegroundProcessName(std::string &proc)
|
|||
proc = getProcNameFromPid(pid);
|
||||
}
|
||||
|
||||
static std::string getProcessPathFromPid(long pid)
|
||||
{
|
||||
std::string linkPath = "/proc/" + std::to_string(pid) + "/exe";
|
||||
char buf[PATH_MAX];
|
||||
ssize_t len = readlink(linkPath.c_str(), buf, sizeof(buf) - 1);
|
||||
if (len <= 0) {
|
||||
return {};
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string GetForegroundProcessPath()
|
||||
{
|
||||
auto pid = getForegroundProcessPid();
|
||||
if (pid <= 0) {
|
||||
return {};
|
||||
}
|
||||
return getProcessPathFromPid(pid);
|
||||
}
|
||||
|
||||
QStringList GetProcessPathsFromName(const QString &name)
|
||||
{
|
||||
QStringList paths;
|
||||
const std::string nameStr = name.toStdString();
|
||||
DIR *procDir = opendir("/proc");
|
||||
if (!procDir) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(procDir)) != nullptr) {
|
||||
bool isPid = (entry->d_name[0] != '\0');
|
||||
for (const char *c = entry->d_name; *c; c++) {
|
||||
if (!isdigit(*c)) {
|
||||
isPid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isPid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string pid = entry->d_name;
|
||||
std::string commPath = "/proc/" + pid + "/comm";
|
||||
std::ifstream commFile(commPath);
|
||||
if (!commFile) {
|
||||
continue;
|
||||
}
|
||||
std::string comm;
|
||||
std::getline(commFile, comm);
|
||||
if (comm != nameStr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string path = getProcessPathFromPid(std::stol(pid));
|
||||
if (path.empty()) {
|
||||
continue;
|
||||
}
|
||||
QString qPath = QString::fromStdString(path);
|
||||
if (!paths.contains(qPath)) {
|
||||
paths.append(qPath);
|
||||
}
|
||||
}
|
||||
closedir(procDir);
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool IsInFocus(const QString &executable)
|
||||
{
|
||||
std::string current;
|
||||
|
|
|
|||
|
|
@ -321,6 +321,61 @@ void GetForegroundProcessName(QString &proc)
|
|||
proc = QString::fromStdString(temp);
|
||||
}
|
||||
|
||||
std::string GetForegroundProcessPath()
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||
for (NSRunningApplication *app in [ws runningApplications]) {
|
||||
if (!app.isActive) {
|
||||
continue;
|
||||
}
|
||||
NSURL *url = app.executableURL;
|
||||
if (!url) {
|
||||
break;
|
||||
}
|
||||
const char *str = url.path.UTF8String;
|
||||
if (str) {
|
||||
return str;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList GetProcessPathsFromName(const QString &name)
|
||||
{
|
||||
QStringList paths;
|
||||
@autoreleasepool {
|
||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||
for (NSRunningApplication *app in [ws runningApplications]) {
|
||||
NSString *appName = app.localizedName;
|
||||
if (!appName) {
|
||||
continue;
|
||||
}
|
||||
const char *nameStr = appName.UTF8String;
|
||||
if (!nameStr ||
|
||||
name != QString::fromUtf8(nameStr)) {
|
||||
continue;
|
||||
}
|
||||
NSURL *url = app.executableURL;
|
||||
if (!url) {
|
||||
continue;
|
||||
}
|
||||
const char *pathStr = url.path.UTF8String;
|
||||
if (!pathStr) {
|
||||
continue;
|
||||
}
|
||||
QString path = QString::fromUtf8(pathStr);
|
||||
if (!paths.contains(path)) {
|
||||
paths.append(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool IsInFocus(const QString &executable)
|
||||
{
|
||||
std::string current;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ EXPORT std::optional<std::string> GetTextInWindow(const std::string &window);
|
|||
EXPORT int SecondsSinceLastInput();
|
||||
EXPORT void GetProcessList(QStringList &processes);
|
||||
EXPORT void GetForegroundProcessName(std::string &name);
|
||||
EXPORT std::string GetForegroundProcessPath();
|
||||
EXPORT QStringList GetProcessPathsFromName(const QString &name);
|
||||
EXPORT bool IsInFocus(const QString &executable);
|
||||
void PlatformInit();
|
||||
void PlatformCleanup();
|
||||
|
|
|
|||
|
|
@ -415,6 +415,68 @@ void GetForegroundProcessName(std::string &proc)
|
|||
proc = temp.toStdString();
|
||||
}
|
||||
|
||||
std::string GetForegroundProcessPath()
|
||||
{
|
||||
HWND foregroundWindow = GetForegroundWindow();
|
||||
DWORD processId = 0;
|
||||
GetWindowThreadProcessId(foregroundWindow, &processId);
|
||||
|
||||
HANDLE process = OpenProcess(
|
||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
|
||||
if (process == NULL) {
|
||||
return {};
|
||||
}
|
||||
|
||||
WCHAR executablePath[600];
|
||||
GetModuleFileNameEx(process, 0, executablePath, 600);
|
||||
CloseHandle(process);
|
||||
|
||||
return QString::fromWCharArray(executablePath).toStdString();
|
||||
}
|
||||
|
||||
QStringList GetProcessPathsFromName(const QString &name)
|
||||
{
|
||||
QStringList paths;
|
||||
HANDLE procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (procSnapshot == INVALID_HANDLE_VALUE) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
PROCESSENTRY32 procEntry;
|
||||
procEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
if (!Process32First(procSnapshot, &procEntry)) {
|
||||
CloseHandle(procSnapshot);
|
||||
return paths;
|
||||
}
|
||||
|
||||
do {
|
||||
QString exeName = QString::fromWCharArray(procEntry.szExeFile);
|
||||
if (exeName != name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HANDLE process =
|
||||
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||||
FALSE, procEntry.th32ProcessID);
|
||||
if (process == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WCHAR executablePath[600];
|
||||
if (GetModuleFileNameEx(process, 0, executablePath, 600)) {
|
||||
QString path = QString::fromWCharArray(executablePath);
|
||||
if (!paths.contains(path)) {
|
||||
paths.append(path);
|
||||
}
|
||||
}
|
||||
CloseHandle(process);
|
||||
} while (Process32Next(procSnapshot, &procEntry));
|
||||
|
||||
CloseHandle(procSnapshot);
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool IsInFocus(const QString &executable)
|
||||
{
|
||||
// only checks if the current foreground window is from the same executable,
|
||||
|
|
|
|||
|
|
@ -16,54 +16,102 @@ bool MacroConditionProcess::_registered = MacroConditionFactory::Register(
|
|||
|
||||
bool MacroConditionProcess::CheckCondition()
|
||||
{
|
||||
QStringList runningProcesses;
|
||||
QString proc = QString::fromStdString(_process);
|
||||
GetProcessList(runningProcesses);
|
||||
std::string foregroundProcessName;
|
||||
GetForegroundProcessName(foregroundProcessName);
|
||||
|
||||
SetVariableValue(foregroundProcessName);
|
||||
|
||||
if (!_regex.Enabled()) {
|
||||
if (runningProcesses.contains(proc) &&
|
||||
(!_checkFocus || IsInFocus(proc))) {
|
||||
SetTempVarValue("name", proc.toStdString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const QString proc = QString::fromStdString(_process);
|
||||
|
||||
int matchIndex = -1;
|
||||
bool foundMatch = false;
|
||||
for (const auto &process : runningProcesses) {
|
||||
matchIndex++;
|
||||
if (_regex.Matches(process, proc)) {
|
||||
foundMatch = true;
|
||||
break;
|
||||
if (_checkFocus) {
|
||||
// Check name and path against the same foreground process
|
||||
// instance to avoid false positives when multiple processes
|
||||
// share the same name
|
||||
const auto foregroundPath = GetForegroundProcessPath();
|
||||
const QString foregroundName =
|
||||
QString::fromStdString(foregroundProcessName);
|
||||
|
||||
SetTempVarValue("name", foregroundProcessName);
|
||||
SetTempVarValue("path", foregroundPath);
|
||||
|
||||
bool nameMatches =
|
||||
_regex.Enabled() ? _regex.Matches(foregroundName, proc)
|
||||
: (foregroundName == proc);
|
||||
if (!nameMatches) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!foundMatch) {
|
||||
return false;
|
||||
}
|
||||
if (!_checkFocus) {
|
||||
SetTempVarValue("name",
|
||||
runningProcesses.at(matchIndex).toStdString());
|
||||
|
||||
if (_checkPath) {
|
||||
const QString pathPattern =
|
||||
QString::fromStdString(_processPath);
|
||||
const QString qForegroundPath =
|
||||
QString::fromStdString(foregroundPath);
|
||||
bool pathMatches =
|
||||
_pathRegex.Enabled()
|
||||
? _pathRegex.Matches(qForegroundPath,
|
||||
pathPattern)
|
||||
: qForegroundPath == pathPattern;
|
||||
if (!pathMatches) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
if (!IsInFocus(proc)) {
|
||||
return false;
|
||||
|
||||
QStringList runningProcesses;
|
||||
GetProcessList(runningProcesses);
|
||||
|
||||
for (const auto &process : runningProcesses) {
|
||||
bool nameMatches = _regex.Enabled()
|
||||
? _regex.Matches(process, proc)
|
||||
: (process == proc);
|
||||
if (!nameMatches) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_checkPath) {
|
||||
SetTempVarValue("name", process.toStdString());
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto paths = GetProcessPathsFromName(process);
|
||||
|
||||
const QString pathPattern =
|
||||
QString::fromStdString(_processPath);
|
||||
bool foundMatchingPath = false;
|
||||
for (const auto &path : paths) {
|
||||
bool pathMatches =
|
||||
_pathRegex.Enabled()
|
||||
? _pathRegex.Matches(path, pathPattern)
|
||||
: path == pathPattern;
|
||||
if (pathMatches) {
|
||||
SetTempVarValue("path", path.toStdString());
|
||||
foundMatchingPath = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatchingPath) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SetTempVarValue("name", process.toStdString());
|
||||
return true;
|
||||
}
|
||||
SetTempVarValue("name", foregroundProcessName);
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionProcess::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_process.Save(obj, "process");
|
||||
obs_data_set_bool(obj, "focus", _checkFocus);
|
||||
_regex.Save(obj);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
obs_data_set_bool(obj, "focus", _checkFocus);
|
||||
obs_data_set_bool(obj, "checkPath", _checkPath);
|
||||
_processPath.Save(obj, "processPath");
|
||||
_pathRegex.Save(obj, "pathRegex");
|
||||
obs_data_set_int(obj, "version", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -78,6 +126,9 @@ bool MacroConditionProcess::Load(obs_data_t *obj)
|
|||
} else {
|
||||
_regex.Load(obj);
|
||||
}
|
||||
_checkPath = obs_data_get_bool(obj, "checkPath");
|
||||
_processPath.Load(obj, "processPath");
|
||||
_pathRegex.Load(obj, "pathRegex");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +142,8 @@ void MacroConditionProcess::SetupTempVars()
|
|||
MacroCondition::SetupTempVars();
|
||||
AddTempvar("name",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.process.name"));
|
||||
AddTempvar("path",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.process.path"));
|
||||
}
|
||||
|
||||
MacroConditionProcessEdit::MacroConditionProcessEdit(
|
||||
|
|
@ -100,13 +153,20 @@ MacroConditionProcessEdit::MacroConditionProcessEdit(
|
|||
_regex(new RegexConfigWidget(this)),
|
||||
_focused(new QCheckBox()),
|
||||
_focusProcess(new QLabel()),
|
||||
_focusLayout(new QHBoxLayout())
|
||||
_focusLayout(new QHBoxLayout()),
|
||||
_checkPath(new QCheckBox()),
|
||||
_processPath(new VariableLineEdit(this)),
|
||||
_pathRegex(new RegexConfigWidget(this)),
|
||||
_pathLayout(new QHBoxLayout())
|
||||
{
|
||||
_processSelection->setEditable(true);
|
||||
_processSelection->setMaxVisibleItems(20);
|
||||
_processSelection->setToolTip(
|
||||
obs_module_text("AdvSceneSwitcher.tooltip.availableVariables"));
|
||||
|
||||
_processPath->setToolTip(
|
||||
obs_module_text("AdvSceneSwitcher.tooltip.availableVariables"));
|
||||
|
||||
QWidget::connect(_processSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(ProcessChanged(const QString &)));
|
||||
|
|
@ -115,6 +175,13 @@ MacroConditionProcessEdit::MacroConditionProcessEdit(
|
|||
SLOT(RegexChanged(const RegexConfig &)));
|
||||
QWidget::connect(_focused, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(FocusChanged(int)));
|
||||
QWidget::connect(_checkPath, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(CheckPathChanged(int)));
|
||||
QWidget::connect(_processPath, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(ProcessPathChanged(const QString &)));
|
||||
QWidget::connect(_pathRegex,
|
||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||
SLOT(PathRegexChanged(const RegexConfig &)));
|
||||
QWidget::connect(&_timer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateFocusProcess()));
|
||||
|
||||
|
|
@ -125,18 +192,25 @@ MacroConditionProcessEdit::MacroConditionProcessEdit(
|
|||
{"{{regex}}", _regex},
|
||||
{"{{focused}}", _focused},
|
||||
{"{{focusProcess}}", _focusProcess},
|
||||
{"{{checkPath}}", _checkPath},
|
||||
{"{{path}}", _processPath},
|
||||
{"{{pathRegex}}", _pathRegex},
|
||||
};
|
||||
|
||||
auto entryLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.process.entry"),
|
||||
obs_module_text("AdvSceneSwitcher.condition.process.layout"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.process.entry.focus"),
|
||||
"AdvSceneSwitcher.condition.process.layout.focus"),
|
||||
_focusLayout, widgetPlaceholders);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.process.layout.path"),
|
||||
_pathLayout, widgetPlaceholders);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addLayout(_focusLayout);
|
||||
mainLayout->addLayout(_pathLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
|
|
@ -178,6 +252,27 @@ void MacroConditionProcessEdit::FocusChanged(int state)
|
|||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionProcessEdit::CheckPathChanged(int state)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_checkPath = state;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionProcessEdit::ProcessPathChanged(const QString &text)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_processPath = text.toStdString();
|
||||
}
|
||||
|
||||
void MacroConditionProcessEdit::PathRegexChanged(const RegexConfig &conf)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_pathRegex = conf;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionProcessEdit::UpdateFocusProcess()
|
||||
{
|
||||
std::string name;
|
||||
|
|
@ -191,6 +286,13 @@ void MacroConditionProcessEdit::SetWidgetVisibility()
|
|||
return;
|
||||
}
|
||||
SetLayoutVisible(_focusLayout, _entryData->_checkFocus);
|
||||
_processPath->setVisible(_entryData->_checkPath);
|
||||
_pathRegex->setVisible(_entryData->_checkPath);
|
||||
if (_entryData->_checkPath) {
|
||||
RemoveStretchIfPresent(_pathLayout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_pathLayout);
|
||||
}
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
|
@ -205,6 +307,9 @@ void MacroConditionProcessEdit::UpdateEntryData()
|
|||
_entryData->_process.UnresolvedValue().c_str());
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
_focused->setChecked(_entryData->_checkFocus);
|
||||
_checkPath->setChecked(_entryData->_checkPath);
|
||||
_processPath->setText(_entryData->_processPath);
|
||||
_pathRegex->SetRegexConfig(_entryData->_pathRegex);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "variable-string.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
||||
|
|
@ -21,8 +21,11 @@ public:
|
|||
}
|
||||
|
||||
StringVariable _process;
|
||||
bool _checkFocus = true;
|
||||
RegexConfig _regex = RegexConfig::PartialMatchRegexConfig();
|
||||
bool _checkFocus = true;
|
||||
bool _checkPath = false;
|
||||
StringVariable _processPath;
|
||||
RegexConfig _pathRegex = RegexConfig::PartialMatchRegexConfig();
|
||||
|
||||
private:
|
||||
void SetupTempVars();
|
||||
|
|
@ -54,6 +57,9 @@ private slots:
|
|||
void ProcessChanged(const QString &text);
|
||||
void RegexChanged(const RegexConfig &);
|
||||
void FocusChanged(int state);
|
||||
void CheckPathChanged(int state);
|
||||
void ProcessPathChanged(const QString &text);
|
||||
void PathRegexChanged(const RegexConfig &);
|
||||
void UpdateFocusProcess();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
|
@ -66,6 +72,10 @@ private:
|
|||
QCheckBox *_focused;
|
||||
QLabel *_focusProcess;
|
||||
QHBoxLayout *_focusLayout;
|
||||
QCheckBox *_checkPath;
|
||||
VariableLineEdit *_processPath;
|
||||
RegexConfigWidget *_pathRegex;
|
||||
QHBoxLayout *_pathLayout;
|
||||
QTimer _timer;
|
||||
std::shared_ptr<MacroConditionProcess> _entryData;
|
||||
bool _loading = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user