Fügt Einstellungsfenster und Lua-Skriptausführung hinzu

Implementiert ein Einstellungsfenster zur Konfiguration von Lua-Skript-Timeouts und anderen Einstellungen.
Ermöglicht die Ausführung von Lua-Skripten in einem separaten Thread mit Abbruchfunktion und Timeout-Mechanismus.
Verbessert die Benutzererfahrung durch Hinzufügen der Möglichkeit, das Toolbox-Verzeichnis im Dateisystem zu öffnen.
Behebt Fokusprobleme und verbessert die Fensterpositionierung und -größe.
This commit is contained in:
2026-01-27 22:26:36 +01:00
parent 5c32949535
commit 0ce126fbfc
5 changed files with 461 additions and 29 deletions

View File

@@ -6,7 +6,7 @@
class toolboxTray : public tray {
public:
// Konstruktor mit optionalen Parametern für Icon und Tooltip
toolboxTray(const char* icon = nullptr, const char* tooltip = nullptr) {
explicit toolboxTray(const char* icon = nullptr, const char* tooltip = nullptr) : tray() {
this->icon = icon;
this->tooltip = const_cast<char*>(tooltip);
this->menu = nullptr; // Initialisiere ohne Menü (kann später gesetzt werden)

View File

@@ -5,6 +5,10 @@
#include <saucer/embedded/all.hpp>
#include <sol/sol.hpp>
#include <saucer/webview.hpp>
#include <unordered_map>
#include <mutex>
#include "optionWindow.h"
#include "toolConfig.h"
class ToolboxWindow {
public:
@@ -21,6 +25,7 @@ public:
void initialize();
void setupToolboxWindow();
void toggleDevTools();
std::atomic_bool isIndex = true;
@@ -40,12 +45,13 @@ public:
std::vector<ToolboxItem> m_toolboxItems;
saucer::smartview<saucer::default_serializer> m_webview;
saucer::smartview m_webview;
private:
std::unique_ptr<hwnd_module> m_hwnd_module;
HWND m_hwnd{};
std::shared_ptr<saucer::application> m_app;
std::unique_ptr<optionWindow> m_optionWindow;
std::thread m_threadMonitor;
std::atomic<bool> m_runningMonitor = true;
@@ -77,6 +83,7 @@ private:
void debug_print();
void run_lua(int id);
void cancel_lua(int id);
void monitor_focus();
@@ -85,10 +92,31 @@ private:
void SetJsonItems();
void openEinst();
void openEinst(int id);
void centerWindow();
void resizeWindow(int width, int height);
void resizeWindow(double widthPercent, double heightPercent);
void openIndex();
void getNewContent();
int getLuaTimeoutSeconds();
void setLuaTimeoutSeconds(int seconds);
std::string getActiveToolName();
struct LuaTask {
std::shared_ptr<std::atomic_bool> cancel;
};
std::mutex m_luaTasksMutex;
std::unordered_map<int, LuaTask> m_luaTasks;
int m_activeToolId = -1;
ToolConfigStore m_configStore;
std::filesystem::path getToolConfigPath(int id) const;
void ensureConfigExists(int id) const;
int getLuaTimeoutSecondsForId(int id) const;
std::string getToolConfigIni() const;
void setToolConfigIni(const std::string &content);
};

View File

@@ -4,7 +4,6 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Toolbox</title>
<link rel="stylesheet" href="../highlight/styles/dark.css" media="all" title="dark">
<style>
body {
font-family: Arial, sans-serif;
@@ -129,7 +128,7 @@
flex: 1;
background: #1e1e2e;
padding: 15px;
display: none; /* Standardmäßig ausgeblendet */
display: flex; /* Standardmäßig sichtbar */
flex-direction: column;
align-items: center;
justify-content: center;
@@ -170,18 +169,32 @@
<div class="editor" id="editor">
<label for="code-editor"></label>
<textarea id="code-editor" placeholder="Write Lua code here..."></textarea>
<pre><code id="highlightedOutput" class="language-lua"></code></pre>
<pre><code id="highlightedOutput" class="language-lua"></code></pre>
</div>
<div class="general" id="general"></div>
<div class="general" id="general">
<div style="width: 80%; max-width: 520px;">
<h3 style="margin: 0 0 10px 0;">Tool</h3>
<div id="tool-name" style="margin-bottom: 20px; color: #ff79c6;">-</div>
<label for="lua-timeout">Lua Timeout (Sekunden)</label>
<input id="lua-timeout" type="number" min="0" step="1" value="30"
style="width: 100%; margin-top: 6px; padding: 8px; border-radius: 4px; border: 1px solid #32334a; background: #2b2c3b; color: #fff;">
<div style="margin-top: 6px; font-size: 12px; color: #aaa;">
0 = kein Timeout
</div>
<button id="save-settings" class="back-button" style="margin-top: 16px;">Speichern</button>
<div id="save-status" style="margin-top: 8px; font-size: 12px; color: #aaa;"></div>
</div>
</div>
<!-- Footer -->
<div class="footer">
<!--Schmidti.Digital &copy; 2024-->
</div>
</div>
<script src="../highlight/highlight.min.js"></script>
<script src="../highlight/languages/lua.min.js"></script>
<script>
function goBack() {
saucer.exposed.openIndex();
@@ -206,13 +219,40 @@
document.addEventListener('DOMContentLoaded', () => {
const editor = document.getElementById('code-editor');
const output = document.getElementById('highlightedOutput');
showContent('general');
// Synchronisiere den Inhalt von textarea mit dem Codeblock
editor.addEventListener('input', () => {
output.innerHTML = ''; // Vorheriges Highlighting entfernen
output.textContent = editor.value; // Aktuellen Text setzen
hljs.highlightAll();
if (window.hljs && typeof hljs.highlightAll === 'function') {
hljs.highlightAll();
}
});
const toolName = document.getElementById('tool-name');
const timeoutInput = document.getElementById('lua-timeout');
const saveBtn = document.getElementById('save-settings');
const saveStatus = document.getElementById('save-status');
saucer.exposed.getActiveToolName().then(name => {
toolName.textContent = name || '-';
});
saucer.exposed.getLuaTimeoutSeconds().then(value => {
timeoutInput.value = value;
});
saveBtn.addEventListener('click', () => {
const seconds = parseInt(timeoutInput.value, 10);
saucer.exposed.setLuaTimeoutSeconds(Number.isFinite(seconds) ? seconds : 0);
saveStatus.textContent = 'Gespeichert';
setTimeout(() => {
saveStatus.textContent = '';
}, 1500);
});
});
</script>

View File

@@ -2,29 +2,103 @@
#include <iostream>
#include <windows.h>
#include <saucer/embedded/all.hpp>
#include <saucer/navigation.hpp>
#include <saucer/app.hpp>
#include <unordered_map>
optionWindow::optionWindow(std::shared_ptr<saucer::application>& app)
namespace {
std::unordered_map<HWND, WNDPROC> g_option_prev_procs;
LRESULT CALLBACK option_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if (msg == WM_KEYDOWN && wparam == VK_F12) {
auto *self = reinterpret_cast<optionWindow *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (self) {
self->toggleDevTools();
return 0;
}
}
const auto it = g_option_prev_procs.find(hwnd);
if (it != g_option_prev_procs.end()) {
return CallWindowProc(it->second, hwnd, msg, wparam, lparam);
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void install_option_f12_toggle(HWND hwnd, optionWindow *self) {
if (!hwnd || !self) {
return;
}
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
auto prev = reinterpret_cast<WNDPROC>(
SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(option_wndproc))
);
if (prev) {
g_option_prev_procs[hwnd] = prev;
}
}
}
optionWindow::optionWindow(std::shared_ptr<saucer::application>& app,
std::function<int()> getLuaTimeoutSeconds,
std::function<void(int)> setLuaTimeoutSeconds,
std::function<std::string()> getActiveToolName,
std::function<std::string()> getToolConfigIni,
std::function<void(const std::string &)> setToolConfigIni,
std::function<void()> openIndex)
: m_app(app)
, m_webview([&]() -> saucer::smartview<> {
, m_webview([&]() -> saucer::smartview {
auto window_res = saucer::window::create(app.get());
if (!window_res.has_value()) {
throw std::runtime_error("optionWindow: failed to create saucer::window");
}
saucer::webview::options opts{window_res.value()};
auto sv_res = saucer::smartview<>::create(opts);
opts.browser_flags.insert("--disable-gpu");
auto sv_res = saucer::smartview::create(opts);
if (!sv_res.has_value()) {
throw std::runtime_error("optionWindow: failed to create saucer::smartview");
}
return std::move(sv_res.value());
}())
, m_hwnd()
, m_getLuaTimeoutSeconds(std::move(getLuaTimeoutSeconds))
, m_setLuaTimeoutSeconds(std::move(setLuaTimeoutSeconds))
, m_getActiveToolName(std::move(getActiveToolName))
, m_getToolConfigIni(std::move(getToolConfigIni))
, m_setToolConfigIni(std::move(setToolConfigIni))
, m_openIndex(std::move(openIndex))
{
}
void optionWindow::initialize() {
// Modul hinzufügen
m_hwnd_module = std::make_unique<hwnd_module>(&m_webview);
m_hwnd = m_hwnd_module->get_hwnd();
install_option_f12_toggle(m_hwnd, this);
configureWindow();
exposeToJs();
loadResources();
#ifdef _DEBUG
m_webview.set_dev_tools(false);
#endif
m_webview.on<saucer::webview::event::navigate>([](const saucer::navigation& nav) {
const auto scheme = nav.url().scheme();
const auto host = nav.url().host();
if (scheme == "saucer" && host && *host == "embedded") {
return saucer::policy::allow;
}
if (scheme == "about") {
return saucer::policy::allow;
}
return saucer::policy::block;
});
m_webview.parent().on<saucer::window::event::close>([this]() -> saucer::policy {
if (m_openIndex) {
m_openIndex();
}
m_webview.parent().hide();
return saucer::policy::block;
});
}
void optionWindow::setHWND(HWND hwnd)
@@ -40,10 +114,12 @@ void optionWindow::configureWindow() {
int windowHeight = static_cast<int>(screenHeight * (700.0 / 1080.0));
m_webview.parent().set_size({windowWidth, windowHeight});
m_webview.set_force_dark(true);
const saucer::color bg{0x1e, 0x1e, 0x2e, 0xFF};
m_webview.set_background(bg);
m_webview.parent().set_background(bg);
int xPos = screenWidth - windowWidth;
int yPos = screenHeight - 42 - windowHeight;
int xPos = (screenWidth - windowWidth) / 2;
int yPos = (screenHeight - windowHeight) / 2;
// HWND über das Modul abrufen
if (HWND hwnd = m_hwnd) {
@@ -59,13 +135,14 @@ void optionWindow::loadResources() {
return;
}
auto it = resources.find("/html/index.html");
auto it = resources.find("/html/einstellungen.html");
if (it == resources.end()) {
std::cerr << "Fehler: 'index.html' wurde nicht gefunden!" << std::endl;
std::cerr << "Fehler: 'einstellungen.html' wurde nicht gefunden!" << std::endl;
return;
}
m_webview.embed(resources);
m_webview.serve("/html/index.html");
// Explicit URL to avoid accidental fallback to main index
m_webview.set_url("saucer://embedded/html/einstellungen.html");
m_webview.set_context_menu(false);
if (!resources.contains("/ico/toolbox.png")) {
@@ -88,4 +165,51 @@ void optionWindow::runLuaScript() {
void optionWindow::show() {
m_webview.parent().show();
runLuaScript();
configureWindow();
}
void optionWindow::exposeToJs() {
m_webview.expose("openIndex", [&]() {
if (m_openIndex) {
m_openIndex();
}
m_webview.parent().hide();
});
m_webview.expose("getLuaTimeoutSeconds", [&]() -> int {
if (m_getLuaTimeoutSeconds) {
return m_getLuaTimeoutSeconds();
}
return 30;
});
m_webview.expose("setLuaTimeoutSeconds", [&](int seconds) {
if (m_setLuaTimeoutSeconds) {
m_setLuaTimeoutSeconds(seconds);
}
});
m_webview.expose("getActiveToolName", [&]() -> std::string {
if (m_getActiveToolName) {
return m_getActiveToolName();
}
return {};
});
m_webview.expose("getToolConfigIni", [&]() -> std::string {
if (m_getToolConfigIni) {
return m_getToolConfigIni();
}
return {};
});
m_webview.expose("setToolConfigIni", [&](const std::string &content) {
if (m_setToolConfigIni) {
m_setToolConfigIni(content);
}
});
}
void optionWindow::toggleDevTools() {
m_webview.set_dev_tools(!m_webview.dev_tools());
}

View File

@@ -1,21 +1,73 @@
#include "toolboxWindow.h"
#include <iostream>
#include <stdexcept>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#include <algorithm>
#include <nlohmann/json.hpp>
#include <cppcodec/base64_rfc4648.hpp>
#include <saucer/embedded/all.hpp>
#include <saucer/navigation.hpp>
#include <saucer/app.hpp>
#include <format>
#include <chrono>
extern "C" {
#include <lua.h>
#include <lauxlib.h>
}
#include <fstream>
#include <sstream>
#include <unordered_map>
namespace {
std::unordered_map<HWND, WNDPROC> g_toolbox_prev_procs;
LRESULT CALLBACK toolbox_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if (msg == WM_KEYDOWN && wparam == VK_F12) {
auto *self = reinterpret_cast<ToolboxWindow *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (self) {
self->toggleDevTools();
return 0;
}
}
const auto it = g_toolbox_prev_procs.find(hwnd);
if (it != g_toolbox_prev_procs.end()) {
return CallWindowProc(it->second, hwnd, msg, wparam, lparam);
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void install_toolbox_f12_toggle(HWND hwnd, ToolboxWindow *self) {
if (!hwnd || !self) {
return;
}
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
auto prev = reinterpret_cast<WNDPROC>(
SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(toolbox_wndproc))
);
if (prev) {
g_toolbox_prev_procs[hwnd] = prev;
}
}
}
ToolboxWindow::ToolboxWindow(std::shared_ptr<saucer::application>& app)
: m_webview([&]() -> saucer::smartview<> {
: m_webview([&]() -> saucer::smartview {
auto window_res = saucer::window::create(app.get());
if (!window_res.has_value()) {
throw std::runtime_error("ToolboxWindow: failed to create saucer::window");
}
saucer::webview::options opts{window_res.value()};
auto sv_res = saucer::smartview<>::create(opts);
opts.browser_flags.insert("--disable-gpu");
auto sv_res = saucer::smartview::create(opts);
if (!sv_res.has_value()) {
throw std::runtime_error("ToolboxWindow: failed to create saucer::smartview");
}
@@ -27,6 +79,7 @@ ToolboxWindow::ToolboxWindow(std::shared_ptr<saucer::application>& app)
void ToolboxWindow::initialize() {
m_hwnd_module = std::make_unique<hwnd_module>(&m_webview);
m_hwnd = m_hwnd_module->get_hwnd();
install_toolbox_f12_toggle(m_hwnd, this);
ensureToolboxInUserPath();
fillToolboxMenu();
configureWindow();
@@ -37,6 +90,17 @@ void ToolboxWindow::initialize() {
void ToolboxWindow::setupToolboxWindow() {
SetJsonItems();
ExposeToJs();
m_webview.on<saucer::webview::event::navigate>([](const saucer::navigation& nav) {
const auto scheme = nav.url().scheme();
const auto host = nav.url().host();
if (scheme == "saucer" && host && *host == "embedded") {
return saucer::policy::allow;
}
if (scheme == "about") {
return saucer::policy::allow;
}
return saucer::policy::block;
});
m_webview.parent().set_always_on_top(true);
m_webview.parent().set_decorations(saucer::window::decoration::none);
@@ -95,7 +159,9 @@ void ToolboxWindow::configureWindow() {
const int windowHeight = 600;
m_webview.parent().set_size({windowWidth, windowHeight});
m_webview.set_force_dark(true);
const saucer::color bg{0x1e, 0x1e, 0x2e, 0xFF};
m_webview.set_background(bg);
m_webview.parent().set_background(bg);
// Arbeitsbereich mit DPI-Skalierung berücksichtigen
RECT workArea;
@@ -142,7 +208,7 @@ void ToolboxWindow::loadResources() {
return;
}
m_webview.embed(resources);
m_webview.serve("/html/index.html");
m_webview.set_url("saucer://embedded/html/index.html");
//m_webview.set_url("https://nindo.de");
m_webview.set_context_menu(false);
@@ -200,6 +266,10 @@ void ToolboxWindow::ExposeToJs() {
run_lua(id);
});
m_webview.expose("cancel_lua", [&](int id) {
cancel_lua(id);
});
m_webview.expose("debug_print", [&]() {
debug_print();
});
@@ -208,8 +278,8 @@ void ToolboxWindow::ExposeToJs() {
open_file_system();
});
m_webview.expose("openEinst", [&]() {
openEinst();
m_webview.expose("openEinst", [&](int id) {
openEinst(id);
});
m_webview.expose("openIndex", [&]() {
@@ -220,6 +290,26 @@ void ToolboxWindow::ExposeToJs() {
{
getNewContent();
});
m_webview.expose("getLuaTimeoutSeconds", [&]() -> int {
return getLuaTimeoutSeconds();
});
m_webview.expose("setLuaTimeoutSeconds", [&](int seconds) {
setLuaTimeoutSeconds(seconds);
});
m_webview.expose("getActiveToolName", [&]() -> std::string {
return getActiveToolName();
});
m_webview.expose("getToolConfigIni", [&]() -> std::string {
return getToolConfigIni();
});
m_webview.expose("setToolConfigIni", [&](const std::string &content) {
setToolConfigIni(content);
});
}
void ToolboxWindow::SetJsonItems() {// Konvertierung des Vektors in JSON
@@ -349,8 +439,20 @@ void ToolboxWindow::run_lua(int id) {
console_opened = true;
}*/
constexpr int kHookInstructionCount = 10000;
const int timeoutSeconds = getLuaTimeoutSecondsForId(id);
const auto deadline = (timeoutSeconds > 0)
? (std::chrono::steady_clock::now() + std::chrono::seconds(timeoutSeconds))
: (std::chrono::steady_clock::time_point::max)();
auto cancelFlag = std::make_shared<std::atomic_bool>(false);
{
std::lock_guard<std::mutex> lock(m_luaTasksMutex);
m_luaTasks[id] = LuaTask{cancelFlag};
}
// Lambda-Funktion, um das Lua-Skript auszuführen
auto lua_task = [this, id]() {
auto lua_task = [this, id, cancelFlag, deadline]() {
sol::state lua;
lua.open_libraries(sol::lib::base,
sol::lib::os,
@@ -362,6 +464,37 @@ void ToolboxWindow::run_lua(int id) {
sol::lib::utf8,
sol::lib::io);
struct LuaHookContext {
std::shared_ptr<std::atomic_bool> cancel;
std::chrono::steady_clock::time_point deadline;
};
LuaHookContext ctx{
cancelFlag,
deadline
};
lua_State* L = lua.lua_state();
*reinterpret_cast<LuaHookContext**>(lua_getextraspace(L)) = &ctx;
lua_sethook(
L,
[](lua_State* hookState, lua_Debug*) {
auto* hookCtx = *reinterpret_cast<LuaHookContext**>(lua_getextraspace(hookState));
if (!hookCtx) {
return;
}
if (hookCtx->cancel->load(std::memory_order_relaxed)) {
luaL_error(hookState, "Lua script cancelled");
}
if (hookCtx->deadline != (std::chrono::steady_clock::time_point::max)() &&
std::chrono::steady_clock::now() > hookCtx->deadline) {
luaL_error(hookState, "Lua script cancelled or timed out");
}
},
LUA_MASKCOUNT,
kHookInstructionCount
);
try {
std::string scriptPath = m_toolboxItems[id].lua_script_path_string;
std::cout << "Running Lua script: " << scriptPath << std::endl;
@@ -380,6 +513,11 @@ void ToolboxWindow::run_lua(int id) {
m_webview.saucer::webview::execute(std::format("enableButtonByToolId({})", id));
m_webview.reload();
}
{
std::lock_guard<std::mutex> lock(m_luaTasksMutex);
m_luaTasks.erase(id);
}
};
// Erstellen und starten des Threads
@@ -391,6 +529,14 @@ void ToolboxWindow::run_lua(int id) {
std::cout << "Lua-Skript wurde gestartet." << std::endl;
}
void ToolboxWindow::cancel_lua(int id) {
std::lock_guard<std::mutex> lock(m_luaTasksMutex);
auto it = m_luaTasks.find(id);
if (it != m_luaTasks.end() && it->second.cancel) {
it->second.cancel->store(true, std::memory_order_relaxed);
}
}
void ToolboxWindow::debug_print() {
std::cout << "ToolboxWindow::debug_print()" << std::endl;
}
@@ -442,12 +588,29 @@ void ToolboxWindow::open_file_system() {
// Beispielhafte Nutzung:
void ToolboxWindow::openEinst() {
if (!serveHtmlFile("html/einstellungen.html", true)) {
if (!m_optionWindow) {
m_optionWindow = std::make_unique<optionWindow>(
m_app,
[this]() { return getLuaTimeoutSeconds(); },
[this](int seconds) { setLuaTimeoutSeconds(seconds); },
[this]() { return getActiveToolName(); },
[this]() { return getToolConfigIni(); },
[this](const std::string &content) { setToolConfigIni(content); },
[this]() { openIndex(); }
);
m_optionWindow->initialize();
}
m_optionWindow->show();
}
void ToolboxWindow::openEinst(int id) {
if (id < 0 || id >= static_cast<int>(m_toolboxItems.size())) {
std::cerr << "openEinst: invalid tool id " << id << std::endl;
return;
}
isIndex = false;
resizeWindow(60.0, 70.0);
centerWindow();
m_activeToolId = id;
ensureConfigExists(id);
openEinst();
}
void ToolboxWindow::centerWindow() {
@@ -494,6 +657,9 @@ void ToolboxWindow::resizeWindow(double widthPercent, double heightPercent)
}
void ToolboxWindow::openIndex() {
if (!m_bShow) {
show();
}
if (!serveHtmlFile("html/index.html", false)) {
return;
}
@@ -509,3 +675,77 @@ void ToolboxWindow::getNewContent()
isIndex = true;
}
void ToolboxWindow::toggleDevTools() {
m_webview.set_dev_tools(!m_webview.dev_tools());
}
std::filesystem::path ToolboxWindow::getToolConfigPath(int id) const {
if (id < 0 || id >= static_cast<int>(m_toolboxItems.size())) {
return {};
}
return std::filesystem::path(m_toolboxItems[id].path) / "config.ini";
}
void ToolboxWindow::ensureConfigExists(int id) const {
const auto configPath = getToolConfigPath(id);
if (configPath.empty()) {
return;
}
m_configStore.ensureExists(configPath);
}
int ToolboxWindow::getLuaTimeoutSecondsForId(int id) const {
const auto configPath = getToolConfigPath(id);
if (configPath.empty()) {
return 30;
}
return m_configStore.getInt(configPath, "lua_timeout_seconds", 30);
}
int ToolboxWindow::getLuaTimeoutSeconds() {
if (m_activeToolId < 0) {
return 30;
}
return getLuaTimeoutSecondsForId(m_activeToolId);
}
void ToolboxWindow::setLuaTimeoutSeconds(int seconds) {
if (m_activeToolId < 0) {
return;
}
const auto configPath = getToolConfigPath(m_activeToolId);
if (configPath.empty()) {
return;
}
m_configStore.setInt(configPath, "lua_timeout_seconds", seconds);
}
std::string ToolboxWindow::getToolConfigIni() const {
if (m_activeToolId < 0) {
return {};
}
const auto configPath = getToolConfigPath(m_activeToolId);
if (configPath.empty()) {
return {};
}
return m_configStore.readAll(configPath);
}
void ToolboxWindow::setToolConfigIni(const std::string &content) {
if (m_activeToolId < 0) {
return;
}
const auto configPath = getToolConfigPath(m_activeToolId);
if (configPath.empty()) {
return;
}
m_configStore.writeAll(configPath, content);
}
std::string ToolboxWindow::getActiveToolName() {
if (m_activeToolId < 0 || m_activeToolId >= static_cast<int>(m_toolboxItems.size())) {
return {};
}
return m_toolboxItems[m_activeToolId].name;
}