Mine-when-idle: - Auto-start/stop mining based on system idle time detection - Platform::getSystemIdleSeconds() via XScreenSaver (Linux) / GetLastInputInfo (Win) - Settings: mine_when_idle toggle + configurable delay (30s–10m) - Settings page UI with checkbox and delay combo Console tab: - Shell-like argument parsing with quote and JSON bracket support - Pass JSON objects/arrays directly as RPC params - Fix selection indices when lines are evicted from buffer Connection & status bar: - Reduce RPC connect timeout to 1s for localhost fast-fail - Fast retry timer on daemon startup and external daemon detection - Show pool mining hashrate in status bar; sidebar badge reflects pool state UI polish: - Add logo to About card in settings; expose logo dimensions on App - Header title offset-y support; adjust content-area margins - Fix banned peers row cursor position (rawRowPosB.x) Branding: - Update copyright to "DragonX Developers" in RC and About section - Replace logo/icon assets with updated versions Misc: - setup.sh: checkout dragonx branch before pulling - Remove stale prebuilt-binaries/xmrig/.gitkeep
313 lines
13 KiB
C++
313 lines
13 KiB
C++
// DragonX Wallet - ImGui Edition
|
||
// Copyright 2024-2026 The Hush Developers
|
||
// Released under the GPLv3
|
||
|
||
#pragma once
|
||
|
||
#include <algorithm>
|
||
#include <string>
|
||
#include <set>
|
||
#include <vector>
|
||
|
||
namespace dragonx {
|
||
namespace config {
|
||
|
||
/**
|
||
* @brief Application settings manager
|
||
*
|
||
* Handles loading and saving of user preferences.
|
||
*/
|
||
class Settings {
|
||
public:
|
||
Settings();
|
||
~Settings();
|
||
|
||
/**
|
||
* @brief Load settings from default location
|
||
* @return true if loaded successfully
|
||
*/
|
||
bool load();
|
||
|
||
/**
|
||
* @brief Load settings from specific path
|
||
* @param path Path to settings file
|
||
* @return true if loaded successfully
|
||
*/
|
||
bool load(const std::string& path);
|
||
|
||
/**
|
||
* @brief Save settings to default location
|
||
* @return true if saved successfully
|
||
*/
|
||
bool save();
|
||
|
||
/**
|
||
* @brief Save settings to specific path
|
||
* @param path Path to settings file
|
||
* @return true if saved successfully
|
||
*/
|
||
bool save(const std::string& path);
|
||
|
||
/**
|
||
* @brief Get default settings file path
|
||
*/
|
||
static std::string getDefaultPath();
|
||
|
||
// Theme
|
||
std::string getTheme() const { return theme_; }
|
||
void setTheme(const std::string& theme) { theme_ = theme; }
|
||
|
||
// Unified skin
|
||
std::string getSkinId() const { return skin_id_; }
|
||
void setSkinId(const std::string& id) { skin_id_ = id; }
|
||
|
||
// Privacy
|
||
bool getSaveZtxs() const { return save_ztxs_; }
|
||
void setSaveZtxs(bool save) { save_ztxs_ = save; }
|
||
|
||
bool getAutoShield() const { return auto_shield_; }
|
||
void setAutoShield(bool shield) { auto_shield_ = shield; }
|
||
|
||
bool getUseTor() const { return use_tor_; }
|
||
void setUseTor(bool tor) { use_tor_ = tor; }
|
||
|
||
// Fees
|
||
bool getAllowCustomFees() const { return allow_custom_fees_; }
|
||
void setAllowCustomFees(bool allow) { allow_custom_fees_ = allow; }
|
||
|
||
double getDefaultFee() const { return default_fee_; }
|
||
void setDefaultFee(double fee) { default_fee_ = fee; }
|
||
|
||
// Price
|
||
bool getFetchPrices() const { return fetch_prices_; }
|
||
void setFetchPrices(bool fetch) { fetch_prices_ = fetch; }
|
||
|
||
// Explorer URLs
|
||
std::string getTxExplorerUrl() const { return tx_explorer_url_; }
|
||
void setTxExplorerUrl(const std::string& url) { tx_explorer_url_ = url; }
|
||
|
||
std::string getAddressExplorerUrl() const { return address_explorer_url_; }
|
||
void setAddressExplorerUrl(const std::string& url) { address_explorer_url_ = url; }
|
||
|
||
// Language
|
||
std::string getLanguage() const { return language_; }
|
||
void setLanguage(const std::string& lang) { language_ = lang; }
|
||
|
||
// Visual effects
|
||
bool getAcrylicEnabled() const { return acrylic_enabled_; }
|
||
void setAcrylicEnabled(bool v) { acrylic_enabled_ = v; }
|
||
|
||
int getAcrylicQuality() const { return acrylic_quality_; }
|
||
void setAcrylicQuality(int v) { acrylic_quality_ = v; }
|
||
|
||
float getBlurMultiplier() const { return blur_multiplier_; }
|
||
void setBlurMultiplier(float v) { blur_multiplier_ = v; }
|
||
|
||
bool getReducedTransparency() const { return ui_opacity_ >= 0.99f; }
|
||
void setReducedTransparency(bool v) { if (v) ui_opacity_ = 1.0f; }
|
||
|
||
float getUIOpacity() const { return ui_opacity_; }
|
||
void setUIOpacity(float v) { ui_opacity_ = std::max(0.3f, std::min(1.0f, v)); }
|
||
|
||
float getWindowOpacity() const { return window_opacity_; }
|
||
void setWindowOpacity(float v) { window_opacity_ = std::max(0.3f, std::min(1.0f, v)); }
|
||
|
||
float getNoiseOpacity() const { return noise_opacity_; }
|
||
void setNoiseOpacity(float v) { noise_opacity_ = v; }
|
||
|
||
// Gradient background mode (use gradient variant of theme background)
|
||
bool getGradientBackground() const { return gradient_background_; }
|
||
void setGradientBackground(bool v) { gradient_background_ = v; }
|
||
|
||
// Balance layout (string ID, e.g. "classic", "donut")
|
||
std::string getBalanceLayout() const { return balance_layout_; }
|
||
void setBalanceLayout(const std::string& v) { balance_layout_ = v; }
|
||
|
||
// Console scanline effect
|
||
bool getScanlineEnabled() const { return scanline_enabled_; }
|
||
void setScanlineEnabled(bool v) { scanline_enabled_ = v; }
|
||
|
||
// Hidden addresses (addresses hidden from the UI by the user)
|
||
const std::set<std::string>& getHiddenAddresses() const { return hidden_addresses_; }
|
||
bool isAddressHidden(const std::string& addr) const { return hidden_addresses_.count(addr) > 0; }
|
||
void hideAddress(const std::string& addr) { hidden_addresses_.insert(addr); }
|
||
void unhideAddress(const std::string& addr) { hidden_addresses_.erase(addr); }
|
||
int getHiddenAddressCount() const { return (int)hidden_addresses_.size(); }
|
||
|
||
// Favorite addresses (pinned to top of address list)
|
||
const std::set<std::string>& getFavoriteAddresses() const { return favorite_addresses_; }
|
||
bool isAddressFavorite(const std::string& addr) const { return favorite_addresses_.count(addr) > 0; }
|
||
void favoriteAddress(const std::string& addr) { favorite_addresses_.insert(addr); }
|
||
void unfavoriteAddress(const std::string& addr) { favorite_addresses_.erase(addr); }
|
||
int getFavoriteAddressCount() const { return (int)favorite_addresses_.size(); }
|
||
|
||
// First-run wizard
|
||
bool getWizardCompleted() const { return wizard_completed_; }
|
||
void setWizardCompleted(bool v) { wizard_completed_ = v; }
|
||
|
||
// Security — auto-lock timeout (seconds; 0 = disabled)
|
||
int getAutoLockTimeout() const { return auto_lock_timeout_; }
|
||
void setAutoLockTimeout(int seconds) { auto_lock_timeout_ = seconds; }
|
||
|
||
// Security — unlock duration (seconds) for walletpassphrase
|
||
int getUnlockDuration() const { return unlock_duration_; }
|
||
void setUnlockDuration(int seconds) { unlock_duration_ = seconds; }
|
||
|
||
// Security — PIN unlock enabled
|
||
bool getPinEnabled() const { return pin_enabled_; }
|
||
void setPinEnabled(bool v) { pin_enabled_ = v; }
|
||
|
||
// Daemon — keep running in background when closing the app
|
||
bool getKeepDaemonRunning() const { return keep_daemon_running_; }
|
||
void setKeepDaemonRunning(bool v) { keep_daemon_running_ = v; }
|
||
|
||
// Daemon — stop externally-started daemons on exit (default: false)
|
||
bool getStopExternalDaemon() const { return stop_external_daemon_; }
|
||
void setStopExternalDaemon(bool v) { stop_external_daemon_ = v; }
|
||
|
||
// Verbose diagnostic logging (connection attempts, daemon state, port owner, etc.)
|
||
bool getVerboseLogging() const { return verbose_logging_; }
|
||
void setVerboseLogging(bool v) { verbose_logging_ = v; }
|
||
|
||
// Daemon — debug logging categories
|
||
const std::set<std::string>& getDebugCategories() const { return debug_categories_; }
|
||
void setDebugCategories(const std::set<std::string>& cats) { debug_categories_ = cats; }
|
||
bool hasDebugCategory(const std::string& cat) const { return debug_categories_.count(cat) > 0; }
|
||
void toggleDebugCategory(const std::string& cat) {
|
||
if (debug_categories_.count(cat)) debug_categories_.erase(cat);
|
||
else debug_categories_.insert(cat);
|
||
}
|
||
|
||
// Visual effects — animated theme effects (hue cycling, shimmer, glow, etc.)
|
||
bool getThemeEffectsEnabled() const { return theme_effects_enabled_; }
|
||
void setThemeEffectsEnabled(bool v) { theme_effects_enabled_ = v; }
|
||
|
||
// Low-spec mode — disables heavy visual effects for better performance
|
||
bool getLowSpecMode() const { return low_spec_mode_; }
|
||
void setLowSpecMode(bool v) { low_spec_mode_ = v; }
|
||
|
||
// Market — last selected exchange + pair
|
||
std::string getSelectedExchange() const { return selected_exchange_; }
|
||
void setSelectedExchange(const std::string& v) { selected_exchange_ = v; }
|
||
std::string getSelectedPair() const { return selected_pair_; }
|
||
void setSelectedPair(const std::string& v) { selected_pair_ = v; }
|
||
|
||
// Pool mining
|
||
std::string getPoolUrl() const { return pool_url_; }
|
||
void setPoolUrl(const std::string& v) { pool_url_ = v; }
|
||
std::string getPoolAlgo() const { return pool_algo_; }
|
||
void setPoolAlgo(const std::string& v) { pool_algo_ = v; }
|
||
std::string getPoolWorker() const { return pool_worker_; }
|
||
void setPoolWorker(const std::string& v) { pool_worker_ = v; }
|
||
int getPoolThreads() const { return pool_threads_; }
|
||
void setPoolThreads(int v) { pool_threads_ = v; }
|
||
bool getPoolTls() const { return pool_tls_; }
|
||
void setPoolTls(bool v) { pool_tls_ = v; }
|
||
bool getPoolHugepages() const { return pool_hugepages_; }
|
||
void setPoolHugepages(bool v) { pool_hugepages_ = v; }
|
||
bool getPoolMode() const { return pool_mode_; }
|
||
void setPoolMode(bool v) { pool_mode_ = v; }
|
||
|
||
// Mine when idle (auto-start mining when system is idle)
|
||
bool getMineWhenIdle() const { return mine_when_idle_; }
|
||
void setMineWhenIdle(bool v) { mine_when_idle_ = v; }
|
||
int getMineIdleDelay() const { return mine_idle_delay_; }
|
||
void setMineIdleDelay(int seconds) { mine_idle_delay_ = std::max(30, seconds); }
|
||
|
||
// Saved pool URLs (user-managed favorites dropdown)
|
||
const std::vector<std::string>& getSavedPoolUrls() const { return saved_pool_urls_; }
|
||
void addSavedPoolUrl(const std::string& url) {
|
||
// Don't add duplicates
|
||
for (const auto& u : saved_pool_urls_) if (u == url) return;
|
||
saved_pool_urls_.push_back(url);
|
||
}
|
||
void removeSavedPoolUrl(const std::string& url) {
|
||
saved_pool_urls_.erase(
|
||
std::remove(saved_pool_urls_.begin(), saved_pool_urls_.end(), url),
|
||
saved_pool_urls_.end());
|
||
}
|
||
|
||
// Saved pool worker addresses (user-managed favorites dropdown)
|
||
const std::vector<std::string>& getSavedPoolWorkers() const { return saved_pool_workers_; }
|
||
void addSavedPoolWorker(const std::string& addr) {
|
||
for (const auto& a : saved_pool_workers_) if (a == addr) return;
|
||
saved_pool_workers_.push_back(addr);
|
||
}
|
||
void removeSavedPoolWorker(const std::string& addr) {
|
||
saved_pool_workers_.erase(
|
||
std::remove(saved_pool_workers_.begin(), saved_pool_workers_.end(), addr),
|
||
saved_pool_workers_.end());
|
||
}
|
||
|
||
// Font scale (user accessibility setting, 1.0–1.5)
|
||
float getFontScale() const { return font_scale_; }
|
||
void setFontScale(float v) { font_scale_ = std::max(1.0f, std::min(1.5f, v)); }
|
||
|
||
// Window size persistence (logical pixels at 1x scale)
|
||
int getWindowWidth() const { return window_width_; }
|
||
int getWindowHeight() const { return window_height_; }
|
||
void setWindowSize(int w, int h) { window_width_ = w; window_height_ = h; }
|
||
|
||
private:
|
||
std::string settings_path_;
|
||
|
||
// Settings values
|
||
std::string theme_ = "dragonx";
|
||
std::string skin_id_ = "dragonx";
|
||
bool save_ztxs_ = true;
|
||
bool auto_shield_ = true;
|
||
bool use_tor_ = false;
|
||
bool allow_custom_fees_ = false;
|
||
double default_fee_ = 0.0001;
|
||
bool fetch_prices_ = true;
|
||
std::string tx_explorer_url_ = "https://explorer.dragonx.is/tx/";
|
||
std::string address_explorer_url_ = "https://explorer.dragonx.is/address/";
|
||
std::string language_ = "en";
|
||
bool acrylic_enabled_ = true;
|
||
int acrylic_quality_ = 2;
|
||
float blur_multiplier_ = 0.10f;
|
||
float noise_opacity_ = 0.5f;
|
||
bool gradient_background_ = false;
|
||
float ui_opacity_ = 0.50f; // Card/sidebar opacity (0.3–1.0, 1.0 = opaque)
|
||
float window_opacity_ = 0.75f; // Background alpha (0.3–1.0, <1 = desktop visible)
|
||
std::string balance_layout_ = "classic";
|
||
bool scanline_enabled_ = true;
|
||
std::set<std::string> hidden_addresses_;
|
||
std::set<std::string> favorite_addresses_;
|
||
bool wizard_completed_ = false;
|
||
int auto_lock_timeout_ = 900; // 15 minutes
|
||
int unlock_duration_ = 600; // 10 minutes
|
||
bool pin_enabled_ = false;
|
||
bool keep_daemon_running_ = false;
|
||
bool stop_external_daemon_ = false;
|
||
bool verbose_logging_ = false;
|
||
std::set<std::string> debug_categories_;
|
||
bool theme_effects_enabled_ = true;
|
||
bool low_spec_mode_ = false;
|
||
std::string selected_exchange_ = "TradeOgre";
|
||
std::string selected_pair_ = "DRGX/BTC";
|
||
|
||
// Pool mining
|
||
std::string pool_url_ = "pool.dragonx.is:3433";
|
||
std::string pool_algo_ = "rx/hush";
|
||
std::string pool_worker_ = "x";
|
||
int pool_threads_ = 0;
|
||
bool pool_tls_ = false;
|
||
bool pool_hugepages_ = true;
|
||
bool pool_mode_ = false; // false=solo, true=pool
|
||
bool mine_when_idle_ = false; // auto-start mining when system idle
|
||
int mine_idle_delay_= 120; // seconds of idle before mining starts
|
||
std::vector<std::string> saved_pool_urls_; // user-saved pool URL favorites
|
||
std::vector<std::string> saved_pool_workers_; // user-saved worker address favorites
|
||
|
||
// Font scale (user accessibility, 1.0–3.0; 1.0 = default)
|
||
float font_scale_ = 1.0f;
|
||
|
||
// Window size (logical pixels at 1x scale; 0 = use default 1200×775)
|
||
int window_width_ = 0;
|
||
int window_height_ = 0;
|
||
};
|
||
|
||
} // namespace config
|
||
} // namespace dragonx
|