#include "config_manager.h" #include #include #include #include #include #include ConfigManager::ConfigManager(QObject *parent) : QObject(parent) { setDefaultValues(); } QString ConfigManager::defaultSettingsPath() { const QString configDirectory = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); if (configDirectory.isEmpty()) { qWarning() << "No application configuration directory is available"; return QString(); } return QDir(configDirectory).filePath("config.xml"); } bool ConfigManager::loadSettings(const QString &filename) { const QString settingsPath = filename.isEmpty() ? defaultSettingsPath() : filename; if (settingsPath.isEmpty()) { return false; } QFile file(settingsPath); if (!file.exists()) { qDebug() << "Config file does not exist, using defaults"; return false; } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Cannot open config file for reading:" << file.errorString(); return false; } QXmlStreamReader reader(&file); // Check if it's a valid XML file if (!reader.readNextStartElement() || reader.name() != QString("ClouckConfig")) { qDebug() << "Invalid config file format"; file.close(); return false; } // Read configuration values while (reader.readNextStartElement()) { QString name = reader.name().toString(); QString text = reader.readElementText(); if (name == "FontColor") { m_fontColor = QColor(text); } else if (name == "BackgroundColor") { m_backgroundColor = QColor(text); } else if (name == "FontSize") { m_fontSize = text.toInt(); } else if (name == "AlwaysOnTop") { m_alwaysOnTop = (text.toLower() == QString("true")); } else if (name == "WindowPosition") { // Parse position format: "x,y" QStringList coords = text.split(','); if (coords.size() == 2) { int x = coords[0].toInt(); int y = coords[1].toInt(); m_windowPosition = QPoint(x, y); } } else if (name == "WindowSize") { // Parse size format: "width,height" QStringList dims = text.split(','); if (dims.size() == 2) { int width = dims[0].toInt(); int height = dims[1].toInt(); m_windowSize = QSize(width, height); } } else if (name == "PrimaryTimeZone") { m_primaryTimeZoneId = text; } else if (name == "SecondaryTimeZone") { m_secondaryTimeZoneId = text; } else if (name == "BorderColor") { m_borderColor = QColor(text); } else if (name == "LocationFontSize") { m_locationFontSize = text.toInt(); } else { reader.skipCurrentElement(); } } file.close(); if (reader.hasError()) { qDebug() << "Error reading config file:" << reader.errorString(); return false; } return true; } bool ConfigManager::saveSettings(const QString &filename) { const QString settingsPath = filename.isEmpty() ? defaultSettingsPath() : filename; if (settingsPath.isEmpty()) { return false; } const QFileInfo fileInfo(settingsPath); if (!QDir().mkpath(fileInfo.absolutePath())) { qDebug() << "Cannot create configuration directory:" << fileInfo.absolutePath(); return false; } QFile file(settingsPath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "Cannot open config file for writing:" << file.errorString(); return false; } QXmlStreamWriter writer(&file); writer.setAutoFormatting(true); writer.writeStartDocument(); // Root element writer.writeStartElement("ClouckConfig"); // Colors: store #RRGGBB when fully opaque, #AARRGGBB when translucent — // the XML stays close to what the user typed. const auto colorString = [](const QColor &color) { return color.alpha() == 255 ? color.name(QColor::HexRgb) : color.name(QColor::HexArgb); }; writer.writeTextElement("FontColor", colorString(m_fontColor)); writer.writeTextElement("BackgroundColor", colorString(m_backgroundColor)); writer.writeTextElement("BorderColor", colorString(m_borderColor)); // Font sizes writer.writeTextElement("FontSize", QString::number(m_fontSize)); writer.writeTextElement("LocationFontSize", QString::number(m_locationFontSize)); // Always on top writer.writeTextElement("AlwaysOnTop", m_alwaysOnTop ? "true" : "false"); // Window position QString positionStr = QString("%1,%2") .arg(m_windowPosition.x()) .arg(m_windowPosition.y()); writer.writeTextElement("WindowPosition", positionStr); // Window size QString sizeStr = QString("%1,%2") .arg(m_windowSize.width()) .arg(m_windowSize.height()); writer.writeTextElement("WindowSize", sizeStr); writer.writeTextElement("PrimaryTimeZone", m_primaryTimeZoneId); writer.writeTextElement("SecondaryTimeZone", m_secondaryTimeZoneId); // Close root element writer.writeEndElement(); writer.writeEndDocument(); file.close(); return true; } void ConfigManager::resetToDefaults() { setDefaultValues(); } bool ConfigManager::configExists(const QString &filename) const { const QString settingsPath = filename.isEmpty() ? defaultSettingsPath() : filename; return !settingsPath.isEmpty() && QFile::exists(settingsPath); } void ConfigManager::setDefaultValues() { m_fontColor = QColor(0, 255, 0); m_backgroundColor = QColor(0, 0, 0, 0); m_fontSize = 24; m_alwaysOnTop = true; // Calculate initial position: bottom-right corner of primary screen // Position will be set properly when widget is shown for the first time m_windowPosition = QPoint(-1, -1); // Special value indicating "not set yet" m_windowSize = QSize(240, 160); // Default clock size m_primaryTimeZoneId = QString::fromUtf8(QTimeZone::systemTimeZoneId()); m_secondaryTimeZoneId = QStringLiteral("America/Los_Angeles"); m_borderColor = QColor(0, 0, 0, 0); // No border by default m_locationFontSize = 12; // Smaller city label under the time }