Add tool configuration management and enhance UI functionality

Introduce `ToolConfigStore` for managing tool configuration files, enabling retrieval and updates. Refactor window handling to support Lua timeout settings and dynamic tool-specific configurations. Improve HTML UI with Lua timeout adjustments and centralized styling updates.
This commit is contained in:
2026-01-27 22:26:05 +01:00
parent 0f66263f63
commit 5c32949535
8 changed files with 175 additions and 22 deletions

View File

@@ -42,7 +42,8 @@ elseif (UNIX)
set(LIBS ${APPINDICATOR_LIBRARIES})
endif ()
file(GLOB_RECURSE SOURCES "src/*.cpp" "inc/*.h") # Nur für .cpp und .h
file(GLOB_RECURSE SOURCES "src/*.cpp" "inc/*.h")
list(APPEND SOURCES "src/toolConfig.cpp") # Nur für .cpp und .h
file(GLOB_RECURSE MODULE_SOURCES "module/*.ixx") # Separates GLOB für Module
add_executable(Toolbox main.cpp
@@ -72,7 +73,7 @@ if (WIN32)
endif ()
endif ()
saucer_embed("res")
saucer_embed("res" TARGET ${PROJECT_NAME})
CPMFindPackage(
NAME saucer-desktop
@@ -85,7 +86,7 @@ target_link_libraries(
PRIVATE
saucer::saucer
sol2::sol2
lua
lua::lib
tray
nlohmann_json
cppcodec
@@ -96,4 +97,4 @@ target_link_libraries(
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel"))
set_target_properties(Toolbox PROPERTIES WIN32_EXECUTABLE TRUE)
endif ()
endif ()

View File

@@ -5,12 +5,20 @@
#include <saucer/embedded/all.hpp>
#include <sol/sol.hpp>
#include <saucer/webview.hpp>
#include <functional>
#include <memory>
class optionWindow {
public:
// Konstruktor erhält das Application-Objekt als Parameter
explicit optionWindow(std::shared_ptr<saucer::application>& app);
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);
// Methode zum Anzeigen des Fensters
void show();
@@ -18,13 +26,22 @@ public:
// Für die Fensterinitialisierung
void initialize();
void setHWND(HWND hwnd);
void toggleDevTools();
private:
std::shared_ptr<saucer::application> m_app;
saucer::smartview<saucer::default_serializer> m_webview;
saucer::smartview m_webview;
std::unique_ptr<hwnd_module> m_hwnd_module;
HWND m_hwnd;
std::function<int()> m_getLuaTimeoutSeconds;
std::function<void(int)> m_setLuaTimeoutSeconds;
std::function<std::string()> m_getActiveToolName;
std::function<std::string()> m_getToolConfigIni;
std::function<void(const std::string &)> m_setToolConfigIni;
std::function<void()> m_openIndex;
void configureWindow();
void loadResources();
void runLuaScript();
void exposeToJs();
};

13
inc/toolConfig.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include <filesystem>
#include <string>
class ToolConfigStore {
public:
bool ensureExists(const std::filesystem::path &path) const;
int getInt(const std::filesystem::path &path, const std::string &key, int fallback) const;
void setInt(const std::filesystem::path &path, const std::string &key, int value) const;
std::string readAll(const std::filesystem::path &path) const;
void writeAll(const std::filesystem::path &path, const std::string &content) const;
};

View File

@@ -32,9 +32,9 @@ coco::stray start(saucer::application *app){
// Tray-Menü definieren
tray_menu tray_menu_items[] = {
{reinterpret_cast<const char*>(u8"Öffnen"), 0, 0, 0, on_click, nullptr},
{"Oeffnen", 0, 0, 0, on_click, nullptr},
{"-", 0, 0, 0, nullptr, nullptr}, // Separator
{reinterpret_cast<const char*>(u8"Beenden"), 0, 0, 0, on_quit, nullptr},
{"Beenden", 0, 0, 0, on_quit, nullptr},
{nullptr, 0, 0, 0, nullptr, nullptr} // Ende des Menüs
};

View File

@@ -1,8 +1,10 @@
export module toolboxTray;
module;
#include <functional>
#include "tray.h"
export module toolboxTray;
export
class toolboxTray : public tray {
@@ -49,4 +51,4 @@ private:
tray_update(this); // Update des Trays mit dem Menü
}
}
};
};

View File

@@ -167,7 +167,7 @@
<body>
<div class="header">
<button onclick="getNewContent()" class="button" id="reload-button"></button>
<button onclick="openEinst()" class="button" id="option-button">⚙️</button>
<button onclick="openEinstFirst()" class="button" id="option-button" style="display: none;">⚙️</button>
<h1>Toolbox</h1>
<button onclick="openFileSystem()" id="file-system-button" class="button">📁</button>
</div>
@@ -183,6 +183,7 @@
}
function runLuaWithId(event) {
event.preventDefault();
if (event.target.tagName === 'BUTTON') {
// Falls der Button gedrückt wurde, brich die Funktion ab
return false;
@@ -234,7 +235,7 @@
: `data:image/png;base64,${item.icon}`;
const toolCardHTML = `
<a href="${item.url}" class="tool-card"
<div class="tool-card" data-url="${item.url}"
data-tool-id="${item.id}"
onclick="runLuaWithId(event)">
<img src="${iconSrc}" alt="${item.name}">
@@ -243,9 +244,9 @@
<p>${item.description}</p>
</div>
<div class="tool-action">
<button>Einst</button>
<button onclick="openEinst(event, ${item.id})">Einst</button>
</div>
</div>
</a>
`;
toolbox.innerHTML += toolCardHTML;
@@ -279,13 +280,32 @@
}
}
function openEinst(){
event.stopPropagation();
function openEinst(event, toolId){
if (event) {
event.stopPropagation();
event.preventDefault();
}
console.log('Einst Button geklickt!');
saucer.exposed.openEinst();
saucer.exposed.openEinst(toolId);
}
function openEinstFirst(){
const firstCard = document.querySelector('.tool-card');
if (!firstCard) {
return;
}
const toolId = firstCard.getAttribute('data-tool-id');
saucer.exposed.openEinst(parseInt(toolId));
}
document.addEventListener('DOMContentLoaded', () => {
document.addEventListener('click', (e) => {
const link = e.target.closest('a');
if (link) {
e.preventDefault();
}
}, true);
const toolbox = document.getElementById('toolbox');
saucer.exposed.getToolboxItems().then(jsonString => {
@@ -297,7 +317,7 @@
: `data:image/png;base64,${item.icon}`;
const toolCardHTML = `
<a href="${item.url}" class="tool-card"
<div class="tool-card" data-url="${item.url}"
data-tool-id="${item.id}"
onclick="runLuaWithId(event)">
<img src="${iconSrc}" alt="${item.name}">
@@ -306,9 +326,9 @@
<p>${item.description}</p>
</div>
<div class="tool-action">
<button onclick="openEinst(event)">Einst</button>
<button onclick="openEinst(event, ${item.id})">Einst</button>
</div>
</a>
</div>
`;
toolbox.innerHTML += toolCardHTML;
@@ -328,4 +348,4 @@
});
</script>
</body>
</html>
</html>

100
src/toolConfig.cpp Normal file
View File

@@ -0,0 +1,100 @@
#include "toolConfig.h"
#include <fstream>
#include <sstream>
#include <vector>
bool ToolConfigStore::ensureExists(const std::filesystem::path &path) const {
if (path.empty()) {
return false;
}
if (std::filesystem::exists(path)) {
return true;
}
std::ofstream out(path);
if (!out) {
return false;
}
out << "lua_timeout_seconds=30\n";
return true;
}
static bool parse_key_value(const std::string &line, std::string &key, std::string &value) {
const auto pos = line.find('=');
if (pos == std::string::npos) {
return false;
}
key = line.substr(0, pos);
value = line.substr(pos + 1);
return true;
}
int ToolConfigStore::getInt(const std::filesystem::path &path, const std::string &key, int fallback) const {
if (!std::filesystem::exists(path)) {
return fallback;
}
std::ifstream in(path);
std::string line;
while (std::getline(in, line)) {
std::string k, v;
if (!parse_key_value(line, k, v)) {
continue;
}
if (k == key) {
try {
return std::max(0, std::stoi(v));
} catch (...) {
return fallback;
}
}
}
return fallback;
}
void ToolConfigStore::setInt(const std::filesystem::path &path, const std::string &key, int value) const {
std::vector<std::string> lines;
if (std::filesystem::exists(path)) {
std::ifstream in(path);
std::string line;
while (std::getline(in, line)) {
lines.push_back(line);
}
}
bool updated = false;
for (auto &line : lines) {
std::string k, v;
if (parse_key_value(line, k, v) && k == key) {
line = k + "=" + std::to_string(std::max(0, value));
updated = true;
break;
}
}
if (!updated) {
lines.push_back(key + "=" + std::to_string(std::max(0, value)));
}
std::ofstream out(path);
for (const auto &line : lines) {
out << line << "\n";
}
}
std::string ToolConfigStore::readAll(const std::filesystem::path &path) const {
if (path.empty() || !std::filesystem::exists(path)) {
return {};
}
std::ifstream in(path);
std::ostringstream ss;
ss << in.rdbuf();
return ss.str();
}
void ToolConfigStore::writeAll(const std::filesystem::path &path, const std::string &content) const {
if (path.empty()) {
return;
}
std::ofstream out(path);
out << content;
}