Křížově platformní správce tapet v C++20: Architektura a systémová integrace
CLI utilita Rwal spravuje tapety v KDE, GNOME a plánuje se pro Windows. Klíčovým prvkem je rozhraní IWallpaperSetter, které implementuje vzor Adapter. Tím se izoluje obchodní logika od specifik desktopového prostředí, což minimalizuje #ifdef.
// src/wallpaper/IWallpaperSetter.hpp
class IWallpaperSetter {
public:
virtual ~IWallpaperSetter() = default;
virtual bool setWallpaper(const std::string& path) = 0;
};
Fábrika v runtime určuje prostředí a vrací vhodnou implementaci. Podpora nového desktopového prostředí vyžaduje pouze novou odvozenou třídu.
Integrace s KDE Plasma přes D-Bus
KDE vyžaduje interakci s org.kde.plasmashell. Implementace KdeSetter odesílá JavaScriptový skript pro aplikaci tapet na všechny pracovní plochy.
// Zjednodušený fragment ze src/wallpaper/KdeSetter.cpp
QDBusInterface remoteApp("org.kde.plasmashell", "/PlasmaShell", "org.kde.PlasmaShell");
QString script = QString(
"var allDesktops = desktops();"
"for (var i = 0; i < allDesktops.length; i++) {"
" var d = allDesktops[i];"
" d.wallpaperPlugin = 'org.kde.image';"
" d.currentConfigGroup = Array('Wallpapers', 'org.kde.image', 'General');"
" d.writeConfig('Image', 'file://%1');"
"}"
).arg(QString::fromStdString(path));
remoteApp.call("evaluateScript", script);
Skript dynamicky nastavuje wallpaperPlugin a Image v konfiguraci každé pracovní plochy. Zpracování chyb D-Bus je implementováno přes QDBusError.
GNOME: GSettings a tematické režimy
Pro GNOME se používá gsettings přes QProcess. Berou se v úvahu picture-uri-dark a picture-uri pro tmavé/světlé motivy.
// Ze src/wallpaper/GnomeSetter.cpp
QProcess::execute("gsettings", {
"set", "org.gnome.desktop.background", "picture-uri-dark",
QString("file://%1").arg(QString::fromStdString(path))
});
Kód kontroluje přítomnost gsettings a fallback na přímé kopírování do ~/.config. Tím je zajištěna stabilita v kontejnerech.
Síťová vrstva: RAII obálka pro libcurl
Stahování obrázků je implementováno přes CurlWrapper s RAII. std::unique_ptr s vlastním deleterem zaručuje cleanup.
// src/net/CurlWrapper.hpp
using CurlPtr = std::unique_ptr<CURL, void(*)(CURL*)>;
// Implementace
CurlWrapper::CurlWrapper() : curl_(curl_easy_init(), curl_easy_cleanup) {
if (!curl_) throw std::runtime_error("Failed to initialize CURL");
}
Třída zapouzdřuje CURLOPT_USERAGENT, CURLOPT_TIMEOUT a progress callbacky. Stahování do paměti využívá CURLOPT_WRITEFUNCTION.
CMake: Modulární sestavení C++20
Projekt vyžaduje C++20 pro std::jthread a plánovaný std::format. CMake najde Qt5 DBus, CURL, nlohmann_json.
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 REQUIRED COMPONENTS Core DBus Widgets)
find_package(CURL REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
add_subdirectory(src/wallpaper)
target_link_libraries(${PROJECT_NAME} PRIVATE wallpaper_lib Qt5::DBus CURL::libcurl nlohmann_json::nlohmann_json)
Odmítnutí Dockeru zjednodušilo přístup k D-Bus hostitele. Statické linkování CURL minimalizuje závislosti.
Asynchronita s std::jthread
Stahování 4K obrázků blokovalo UI. Řešením je std::jthread C++20:
- Automatické join při opuštění scope.
- stop_token pro zrušení operací.
- Kompatibilita s coroutines pomocí
co_await.
std::jthread loader(& {
// Stahování s kontrolou stoken.stop_requested()
});
Křížová kompatibilita kompilátorů: GCC 11+ a Clang 14+ s -fcoroutines.
Co je důležité
- Vzor Adapter umožňuje přidat desktopové prostředí za 15 minut bez refaktoringu jádra.
- RAII pro libcurl vylučuje úniky paměti v cestách výjimek.
std::jthreadřeší zamrznutí UI při síťových operacích.- Modulární CMake zajišťuje přenosné sestavení.
- D-Bus skriptování je jediný spolehlivý způsob pro Plasma.
Architektonická rozhodnutí a analýza
Statická analýza clang-tidy odhalila Qt signály s potenciálním use-after-free. ADR dokumentují volbu D-Bus nad přímou editací konfigurace.
Plány rozvoje:
- Windows WinAPI
SystemParametersInfoW. QtNetworkneboboost::asiopro asynchronní operace.- Optimalizace parsování JSON pro odpovědi nad 100MB+.
Projekt demonstruje systémové programování v C++20 pro středně pokročilé vývojáře: od rozhraní po coroutines.
— Editorial Team
Zatím žádné komentáře.