Zpět na domů

C++20 správce tapet: D-Bus a RAII

Článek rozebírá architekturu CLI-nástroje Rwal pro správu tapet v různých DE. Používá se vzor Adapter, skriptování D-Bus pro KDE, GSettings pro GNOME, RAII obalka libcurl a std::jthread C++20. Uvedeny příklady kódu a CMake.

Rwal: C++20 nástroj pro tapety v KDE a GNOME
Advertisement 728x90

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.

Google AdInline article slot
// 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.

Google AdInline article slot

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.

Google AdInline article slot
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.
  • QtNetwork nebo boost::asio pro 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

Advertisement 728x90

Číst dál