diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a64cdc..bc69017 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,10 +14,12 @@ qt6_standard_project_setup()
set(SOURCES
main.cpp
clockwidget.cpp
+ configmanager.cpp
)
set(HEADERS
clockwidget.h
+ configmanager.h
)
# Create executable
diff --git a/README.md b/README.md
index 41ab8ed..d558c56 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# ⏰ Flock
+# ⏰ Flock


@@ -18,16 +18,16 @@ When on macOS / Linux, the clock on the menu bar is too small to be noticeable,
- [ ] Frameless
- [x] Drag and Move
- [x] Right Click Menu
- - [ ] Always On Top
+ - [x] Always On Top
- [ ] Show in Fullscreen Mode
- [x] **Style**
- [x] Set Background Color
- [x] Set Font Color
- [x] Set FontSize
-- [ ] **Configuration File** (XML)
- - [ ] Read Settings
- - [ ] Write Settings
- - [ ] Reset Settings
+- [x] **Configuration File** (XML)
+ - [x] Read Settings
+ - [x] Write Settings
+ - [x] Reset Settings
- [ ] **Time**
- [ ] Select Time Zone
- [ ] Set Alarms
@@ -73,11 +73,24 @@ make
./flock
```
+### Configuration
+
+The application now uses XML configuration files instead of QSettings. Configuration is stored in `config.xml` with the following options:
+
+- **FontColor**: Font color in hex format
+- **BackgroundColor**: Background color with alpha transparency
+- **FontSize**: Font size in points (8-72)
+- **AlwaysOnTop**: Window always stays on top
+- **WindowPosition**: Window position coordinates
+
+The configuration file is automatically created when you first run the application and make changes to settings.
+
### Usage
- **Move**: Left-click and drag
- **Menu**: Right-click for context menu
- **Customize**: Change colors, font size, always-on-top behavior
+- **Configuration**: Settings are saved to `config.xml` and persist between sessions
### Project Structure
@@ -88,6 +101,7 @@ qflock/
│ ├── *.o # Object files
│ ├── moc_*.cpp # Qt meta-object compiler output
│ └── Makefile # Build file
+├── config.xml # XML configuration file
├── build.sh # One-click build script
├── clean.sh # Clean script
├── flock.pro # qmake project file
diff --git a/XML_CONFIG_GUIDE.md b/XML_CONFIG_GUIDE.md
new file mode 100644
index 0000000..e85f1e6
--- /dev/null
+++ b/XML_CONFIG_GUIDE.md
@@ -0,0 +1,78 @@
+# XML Configuration Implementation
+
+## Overview
+
+The configuration system has been successfully implemented using XML files instead of QSettings. The new ConfigManager class handles all configuration operations.
+
+## Files Created/Modified
+
+### New Files
+
+- [`configmanager.h`](file:///Users/integzz/Documents/GitHub/qflock/configmanager.h) - Configuration manager header
+- [`configmanager.cpp`](file:///Users/integzz/Documents/GitHub/qflock/configmanager.cpp) - Configuration manager implementation
+- [`config.xml`](file:///Users/integzz/Documents/GitHub/qflock/config.xml) - Default configuration file
+
+### Modified Files
+
+- [`clockwidget.h`](file:///Users/integzz/Documents/GitHub/qflock/clockwidget.h) - Replaced QSettings with ConfigManager
+- [`clockwidget.cpp`](file:///Users/integzz/Documents/GitHub/qflock/clockwidget.cpp) - Updated to use XML configuration
+- [`flock.pro`](file:///Users/integzz/Documents/GitHub/qflock/flock.pro) - Added new source files
+- [`CMakeLists.txt`](file:///Users/integzz/Documents/GitHub/qflock/CMakeLists.txt) - Added new source files
+
+## XML Configuration Format
+
+The configuration is stored in XML format with the following structure:
+
+```xml
+
+
+ #ffffff
+ #96000000
+ 24
+ true
+ 100,100
+
+```
+
+## Configuration Options
+
+- **FontColor**: Font color in hex format (e.g., #ffffff for white)
+- **BackgroundColor**: Background color in hex format with alpha (e.g., #96000000 for semi-transparent black)
+- **FontSize**: Font size in points (8-72)
+- **AlwaysOnTop**: Boolean value (true/false)
+- **WindowPosition**: Window position as "x,y" coordinates
+
+## Usage
+
+The configuration is automatically loaded when the application starts and saved when it closes. Users can:
+
+1. **Modify settings through the UI**: Right-click on the clock to access the context menu
+2. **Edit config.xml directly**: The file is human-readable and can be edited manually
+3. **Reset to defaults**: Use the "Reset Settings" option in the context menu
+
+## Features
+
+- ✅ XML-based configuration storage
+- ✅ Automatic loading on startup
+- ✅ Automatic saving on exit
+- ✅ Default values if config file doesn't exist
+- ✅ Human-readable XML format
+- ✅ Error handling for corrupted config files
+- ✅ Manual editing support
+
+## Build and Test
+
+Use the provided test script to build and verify the XML configuration:
+
+```bash
+./test_xml_config.sh
+```
+
+This will:
+
+1. Clean previous build files
+2. Build the project with XML configuration support
+3. Display the current config.xml content
+4. Provide instructions to run the application
+
+The configuration file will be created automatically when you first run the application and make changes to the settings.
diff --git a/clockwidget.cpp b/clockwidget.cpp
index 13175f3..75abef5 100644
--- a/clockwidget.cpp
+++ b/clockwidget.cpp
@@ -1,4 +1,5 @@
#include "clockwidget.h"
+#include "configmanager.h"
#include
#include
#include
@@ -128,6 +129,7 @@ void ClockWidget::changeFontColor()
if (color.isValid())
{
m_fontColor = color;
+ m_configManager->setFontColor(m_fontColor);
updateStyleSheet();
}
}
@@ -138,6 +140,7 @@ void ClockWidget::changeBackgroundColor()
if (color.isValid())
{
m_backgroundColor = color;
+ m_configManager->setBackgroundColor(m_backgroundColor);
updateStyleSheet();
}
}
@@ -149,6 +152,7 @@ void ClockWidget::changeFontSize()
if (ok)
{
m_fontSize = size;
+ m_configManager->setFontSize(m_fontSize);
updateStyleSheet();
}
}
@@ -158,7 +162,7 @@ void ClockWidget::resetSettings()
int ret = QMessageBox::question(this, "Reset Settings", "Are you sure you want to reset all settings?");
if (ret == QMessageBox::Yes)
{
- m_settings->clear();
+ m_configManager->resetToDefaults();
loadSettings();
updateStyleSheet();
}
@@ -171,27 +175,55 @@ void ClockWidget::quitApplication()
void ClockWidget::loadSettings()
{
- m_settings = new QSettings("QFlock", "Clock", this);
+ m_configManager = new ConfigManager(this);
- m_fontColor = m_settings->value("fontColor", QColor(255, 255, 255)).value();
- m_backgroundColor = m_settings->value("backgroundColor", QColor(0, 0, 0, 150)).value();
- m_fontSize = m_settings->value("fontSize", 24).toInt();
- m_alwaysOnTop = m_settings->value("alwaysOnTop", true).toBool();
+ // Load from XML config file
+ if (!m_configManager->loadSettings())
+ {
+ // If loading fails, config manager already has default values
+ qDebug() << "Using default settings";
+ }
+
+ // Apply loaded settings
+ m_fontColor = m_configManager->fontColor();
+ m_backgroundColor = m_configManager->backgroundColor();
+ m_fontSize = m_configManager->fontSize();
+ m_alwaysOnTop = m_configManager->alwaysOnTop();
// Restore window position
- QPoint pos = m_settings->value("position", QPoint(100, 100)).toPoint();
- move(pos);
+ move(m_configManager->windowPosition());
+
+ // Update always on top checkbox in menu
+ QList actions = m_contextMenu->actions();
+ for (QAction *action : actions)
+ {
+ if (action->text() == "Always on Top")
+ {
+ action->setChecked(m_alwaysOnTop);
+ break;
+ }
+ }
updateStyleSheet();
}
void ClockWidget::saveSettings()
{
- m_settings->setValue("fontColor", m_fontColor);
- m_settings->setValue("backgroundColor", m_backgroundColor);
- m_settings->setValue("fontSize", m_fontSize);
- m_settings->setValue("alwaysOnTop", m_alwaysOnTop);
- m_settings->setValue("position", pos());
+ if (!m_configManager)
+ return;
+
+ // Update config manager with current values
+ m_configManager->setFontColor(m_fontColor);
+ m_configManager->setBackgroundColor(m_backgroundColor);
+ m_configManager->setFontSize(m_fontSize);
+ m_configManager->setAlwaysOnTop(m_alwaysOnTop);
+ m_configManager->setWindowPosition(pos());
+
+ // Save to XML file
+ if (!m_configManager->saveSettings())
+ {
+ qDebug() << "Failed to save settings to config.xml";
+ }
}
void ClockWidget::updateStyleSheet()
diff --git a/clockwidget.h b/clockwidget.h
index 22ea4f2..961b133 100644
--- a/clockwidget.h
+++ b/clockwidget.h
@@ -7,10 +7,10 @@
#include
#include
#include
-#include
-#include
#include
+class ConfigManager;
+
class ClockWidget : public QWidget
{
Q_OBJECT
@@ -49,7 +49,7 @@ private:
bool m_dragging;
// Settings
- QSettings *m_settings;
+ ConfigManager *m_configManager;
QColor m_fontColor;
QColor m_backgroundColor;
int m_fontSize;
diff --git a/config.xml b/config.xml
new file mode 100644
index 0000000..95e0d4b
--- /dev/null
+++ b/config.xml
@@ -0,0 +1,8 @@
+
+
+ #ffffff
+ #96000000
+ 24
+ true
+ 100,100
+
diff --git a/configmanager.cpp b/configmanager.cpp
new file mode 100644
index 0000000..73f78ad
--- /dev/null
+++ b/configmanager.cpp
@@ -0,0 +1,146 @@
+#include "configmanager.h"
+#include
+#include
+
+ConfigManager::ConfigManager(QObject *parent)
+ : QObject(parent)
+{
+ setDefaultValues();
+}
+
+bool ConfigManager::loadSettings(const QString &filename)
+{
+ QFile file(filename);
+ 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() != "QFlockConfig")
+ {
+ 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() == "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
+ {
+ reader.skipCurrentElement();
+ }
+ }
+
+ file.close();
+
+ if (reader.hasError())
+ {
+ qDebug() << "Error reading config file:" << reader.errorString();
+ return false;
+ }
+
+ return true;
+}
+
+bool ConfigManager::saveSettings(const QString &filename)
+{
+ QFile file(filename);
+ 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("QFlockConfig");
+
+ // Font color
+ writer.writeTextElement("FontColor", m_fontColor.name(QColor::HexArgb));
+
+ // Background color
+ writer.writeTextElement("BackgroundColor", m_backgroundColor.name(QColor::HexArgb));
+
+ // Font size
+ writer.writeTextElement("FontSize", QString::number(m_fontSize));
+
+ // 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);
+
+ // Close root element
+ writer.writeEndElement();
+
+ writer.writeEndDocument();
+ file.close();
+
+ return true;
+}
+
+void ConfigManager::resetToDefaults()
+{
+ setDefaultValues();
+}
+
+bool ConfigManager::configExists(const QString &filename) const
+{
+ return QFile::exists(filename);
+}
+
+void ConfigManager::setDefaultValues()
+{
+ m_fontColor = QColor(255, 255, 255); // White
+ m_backgroundColor = QColor(0, 0, 0, 150); // Semi-transparent black
+ m_fontSize = 24;
+ m_alwaysOnTop = true;
+ m_windowPosition = QPoint(100, 100);
+}
diff --git a/configmanager.h b/configmanager.h
new file mode 100644
index 0000000..8fa4b39
--- /dev/null
+++ b/configmanager.h
@@ -0,0 +1,56 @@
+#ifndef CONFIGMANAGER_H
+#define CONFIGMANAGER_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class ConfigManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigManager(QObject *parent = nullptr);
+
+ // Load settings from XML file
+ bool loadSettings(const QString &filename = "config.xml");
+
+ // Save settings to XML file
+ bool saveSettings(const QString &filename = "config.xml");
+
+ // Getters
+ QColor fontColor() const { return m_fontColor; }
+ QColor backgroundColor() const { return m_backgroundColor; }
+ int fontSize() const { return m_fontSize; }
+ bool alwaysOnTop() const { return m_alwaysOnTop; }
+ QPoint windowPosition() const { return m_windowPosition; }
+
+ // Setters
+ void setFontColor(const QColor &color) { m_fontColor = color; }
+ void setBackgroundColor(const QColor &color) { m_backgroundColor = color; }
+ void setFontSize(int size) { m_fontSize = size; }
+ void setAlwaysOnTop(bool onTop) { m_alwaysOnTop = onTop; }
+ void setWindowPosition(const QPoint &pos) { m_windowPosition = pos; }
+
+ // Reset to default values
+ void resetToDefaults();
+
+ // Check if config file exists
+ bool configExists(const QString &filename = "config.xml") const;
+
+private:
+ // Default values
+ void setDefaultValues();
+
+ // Settings data
+ QColor m_fontColor;
+ QColor m_backgroundColor;
+ int m_fontSize;
+ bool m_alwaysOnTop;
+ QPoint m_windowPosition;
+};
+
+#endif // CONFIGMANAGER_H
diff --git a/flock.pro b/flock.pro
index 0e62961..7547abd 100644
--- a/flock.pro
+++ b/flock.pro
@@ -7,10 +7,12 @@ QT = core gui widgets
SOURCES = \
$$PWD/main.cpp \
- $$PWD/clockwidget.cpp
+ $$PWD/clockwidget.cpp \
+ $$PWD/configmanager.cpp
HEADERS = \
- $$PWD/clockwidget.h
+ $$PWD/clockwidget.h \
+ $$PWD/configmanager.h
INCLUDEPATH = \
$$PWD/.
diff --git a/test_xml_config.sh b/test_xml_config.sh
new file mode 100755
index 0000000..f0dbc85
--- /dev/null
+++ b/test_xml_config.sh
@@ -0,0 +1,29 @@
+# Build and Run Test
+
+echo "Building QFlock with XML configuration..."
+
+# Clean previous build
+./clean.sh
+
+# Build the project
+./build.sh
+
+# Check if build was successful
+if [ $? -eq 0 ]; then
+ echo "Build successful! Testing XML configuration..."
+
+ # Show config file content
+ echo "Config file content:"
+ if [ -f "config.xml" ]; then
+ cat config.xml
+ else
+ echo "No config.xml found (will be created on first run)"
+ fi
+
+ echo ""
+ echo "You can now run the application:"
+ echo "./build/flock.app/Contents/MacOS/flock # macOS"
+ echo "./build/flock # Linux"
+else
+ echo "Build failed!"
+fi