Full-node GUI wallet for DragonX cryptocurrency. Built with Dear ImGui, SDL3, and OpenGL3/DX11. Features: - Send/receive shielded and transparent transactions - Autoshield with merged transaction display - Built-in CPU mining (xmrig) - Peer management and network monitoring - Wallet encryption with PIN lock - QR code generation for receive addresses - Transaction history with pagination - Console for direct RPC commands - Cross-platform (Linux, Windows)
193 lines
6.5 KiB
C++
193 lines
6.5 KiB
C++
// DragonX Wallet - ImGui Edition
|
|
// Copyright 2024-2026 The Hush Developers
|
|
// Released under the GPLv3
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <filesystem>
|
|
|
|
namespace dragonx {
|
|
namespace ui {
|
|
namespace schema {
|
|
|
|
/**
|
|
* @brief Manages bundled and user-installed skins (unified TOML files)
|
|
*
|
|
* Responsibilities:
|
|
* - Enumerate bundled skins from res/themes/ directory (any .toml except ui.toml)
|
|
* - Enumerate user themes from ~/.config/ObsidianDragon/themes/<folder>/theme.toml
|
|
* - Import / remove user skins
|
|
* - Validate skin TOML structure before import
|
|
* - Track active skin ID in settings
|
|
*/
|
|
class SkinManager {
|
|
public:
|
|
/**
|
|
* @brief Metadata about an available skin
|
|
*/
|
|
struct SkinInfo {
|
|
std::string id; ///< Unique identifier (folder name or filename stem)
|
|
std::string name; ///< Display name from theme.name
|
|
std::string author; ///< Author from theme.author
|
|
std::string path; ///< Full filesystem path to the TOML file
|
|
std::string directory; ///< Folder containing theme.toml (empty for bundled flat files)
|
|
std::string backgroundImagePath; ///< Resolved path to background image override (empty = use default)
|
|
std::string logoPath; ///< Resolved path to logo image override (empty = use default)
|
|
bool dark = true; ///< Dark mode flag from theme.dark
|
|
bool bundled = true; ///< true = shipped with app, false = user-installed
|
|
bool valid = true; ///< true if theme.toml passed validation
|
|
std::string validationError; ///< Error message if !valid
|
|
};
|
|
|
|
/**
|
|
* @brief Result of a skin validation
|
|
*/
|
|
struct ValidationResult {
|
|
bool valid = false;
|
|
std::string error; ///< Error message if !valid
|
|
};
|
|
|
|
/**
|
|
* @brief Get the singleton instance
|
|
*/
|
|
static SkinManager& instance();
|
|
|
|
/**
|
|
* @brief Scan for available skins (bundled + user)
|
|
*
|
|
* Re-scans both the bundled res/ directory and the user skins directory.
|
|
* Call this on startup and after import/remove operations.
|
|
*/
|
|
void refresh();
|
|
|
|
/**
|
|
* @brief Get the list of available skins
|
|
* @return Sorted list: bundled skins first (with "dragonx" at top), then user skins
|
|
*/
|
|
const std::vector<SkinInfo>& available() const { return skins_; }
|
|
|
|
/**
|
|
* @brief Find a skin by ID
|
|
* @return Pointer to SkinInfo, or nullptr if not found
|
|
*/
|
|
const SkinInfo* findById(const std::string& id) const;
|
|
|
|
/**
|
|
* @brief Validate a skin TOML file
|
|
* @param path Path to the TOML file
|
|
* @return Validation result with error message if invalid
|
|
*
|
|
* Validation rules:
|
|
* 1. File must be valid TOML
|
|
* 2. Must contain [theme] table
|
|
* 3. theme.name must be a non-empty string
|
|
* 4. theme.palette must be a table with at least --primary and --background
|
|
* 5. If [globals] exists, it must be a table
|
|
*/
|
|
static ValidationResult validateSkinFile(const std::string& path);
|
|
|
|
/**
|
|
* @brief Import a skin file into the user skins directory
|
|
* @param sourcePath Path to the source TOML file
|
|
* @return true if imported successfully
|
|
*
|
|
* Validates the file first. Copies to user skins directory.
|
|
* Calls refresh() on success.
|
|
*/
|
|
bool importSkin(const std::string& sourcePath);
|
|
|
|
/**
|
|
* @brief Remove a user-installed skin
|
|
* @param id Skin ID to remove
|
|
* @return true if removed successfully
|
|
*
|
|
* Cannot remove bundled skins. Calls refresh() on success.
|
|
*/
|
|
bool removeSkin(const std::string& id);
|
|
|
|
/**
|
|
* @brief Apply a skin by ID
|
|
* @param id Skin ID to activate
|
|
* @return true if skin was found and loaded
|
|
*
|
|
* Loads the skin file into UISchema and applies ImGui colors.
|
|
*/
|
|
bool setActiveSkin(const std::string& id);
|
|
|
|
/**
|
|
* @brief Get the currently active skin ID
|
|
*/
|
|
const std::string& activeSkinId() const { return activeSkinId_; }
|
|
|
|
/**
|
|
* @brief Get the bundled skins directory path
|
|
*/
|
|
static std::string getBundledSkinsDirectory();
|
|
|
|
/**
|
|
* @brief Get the user skins directory path
|
|
*/
|
|
static std::string getUserSkinsDirectory();
|
|
|
|
/**
|
|
* @brief Set callback invoked after skin changes (for image reloading)
|
|
* @param cb Callback receiving backgroundImagePath and logoPath (empty = use default)
|
|
*/
|
|
void setImageReloadCallback(std::function<void(const std::string& bgPath, const std::string& logoPath)> cb) {
|
|
imageReloadCb_ = std::move(cb);
|
|
}
|
|
|
|
/**
|
|
* @brief Re-resolve image paths from UISchema and trigger reload callback
|
|
*
|
|
* Called by UISchema hot-reload when [theme.images] values change.
|
|
* Updates the active SkinInfo's image paths and fires imageReloadCb_.
|
|
*
|
|
* @param skinId Active skin ID to update
|
|
* @param tomlPath Path to the TOML file whose images section changed
|
|
*/
|
|
void resolveAndReloadImages(const std::string& skinId, const std::string& tomlPath);
|
|
|
|
/**
|
|
* @brief Enable/disable gradient background mode
|
|
*
|
|
* When enabled, theme backgrounds are replaced with their gradient
|
|
* variants (e.g. "gradient_drgx_bg.png" instead of "drgx_bg.png").
|
|
* Falls back to dark_gradient.png or light_gradient.png when no
|
|
* theme-specific gradient exists.
|
|
*/
|
|
void setGradientMode(bool enabled);
|
|
bool isGradientMode() const { return gradientMode_; }
|
|
|
|
private:
|
|
SkinManager() = default;
|
|
~SkinManager() = default;
|
|
SkinManager(const SkinManager&) = delete;
|
|
SkinManager& operator=(const SkinManager&) = delete;
|
|
|
|
void scanDirectory(const std::string& dir, bool bundled);
|
|
|
|
/// Resolve the image directory for a given skin
|
|
std::filesystem::path resolveImgDir(const SkinInfo* skin) const;
|
|
|
|
/// Given an original bg relative path and img dir, resolve the gradient variant
|
|
std::string resolveGradientBg(const std::string& bgFilename,
|
|
const std::filesystem::path& imgDir,
|
|
bool isDark) const;
|
|
|
|
/// Common helper: resolve bg (optionally gradient) and logo, fire callback
|
|
void resolveAndFireCallback(SkinInfo* skin, const std::filesystem::path& imgDir);
|
|
|
|
std::vector<SkinInfo> skins_;
|
|
std::string activeSkinId_ = "dragonx";
|
|
bool gradientMode_ = false;
|
|
std::function<void(const std::string&, const std::string&)> imageReloadCb_;
|
|
};
|
|
|
|
} // namespace schema
|
|
} // namespace ui
|
|
} // namespace dragonx
|