Fixed architecture

This commit is contained in:
Sigismund Dijkstra 2025-07-27 20:10:29 -05:00
parent 328600b777
commit af6ef391f4
5 changed files with 386 additions and 0 deletions

124
PomodoroConfig.cpp Normal file
View File

@ -0,0 +1,124 @@
#include "PomodoroConfig.h"
#include <QStandardPaths>
#include <QDir>
PomodoroConfig& PomodoroConfig::instance()
{
static PomodoroConfig config;
return config;
}
PomodoroConfig::PomodoroConfig()
{
const QString configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
const QString appConfigDir = configPath + "/PomodoroTimer";
QDir().mkpath(appConfigDir);
m_settings = std::make_unique<QSettings>(
appConfigDir + "/config.ini",
QSettings::IniFormat
);
loadSettings();
}
void PomodoroConfig::setWorkDuration(int seconds)
{
if (seconds > 0 && seconds != m_workDuration) {
m_workDuration = seconds;
saveSettings();
}
}
void PomodoroConfig::setShortBreakDuration(int seconds)
{
if (seconds > 0 && seconds != m_shortBreakDuration) {
m_shortBreakDuration = seconds;
saveSettings();
}
}
void PomodoroConfig::setLongBreakDuration(int seconds)
{
if (seconds > 0 && seconds != m_longBreakDuration) {
m_longBreakDuration = seconds;
saveSettings();
}
}
void PomodoroConfig::setShowNotifications(bool enabled)
{
if (enabled != m_showNotifications) {
m_showNotifications = enabled;
saveSettings();
}
}
void PomodoroConfig::setAutoStartBreaks(bool enabled)
{
if (enabled != m_autoStartBreaks) {
m_autoStartBreaks = enabled;
saveSettings();
}
}
void PomodoroConfig::setWorkEndSound(const QString& soundPath)
{
if (soundPath != m_workEndSound) {
m_workEndSound = soundPath;
saveSettings();
}
}
void PomodoroConfig::setBreakEndSound(const QString& soundPath)
{
if (soundPath != m_breakEndSound) {
m_breakEndSound = soundPath;
saveSettings();
}
}
void PomodoroConfig::saveSettings()
{
if (!m_settings) return;
m_settings->beginGroup("Timer");
m_settings->setValue("workDuration", m_workDuration);
m_settings->setValue("shortBreakDuration", m_shortBreakDuration);
m_settings->setValue("longBreakDuration", m_longBreakDuration);
m_settings->endGroup();
m_settings->beginGroup("UI");
m_settings->setValue("showNotifications", m_showNotifications);
m_settings->setValue("autoStartBreaks", m_autoStartBreaks);
m_settings->endGroup();
m_settings->beginGroup("Sound");
m_settings->setValue("workEndSound", m_workEndSound);
m_settings->setValue("breakEndSound", m_breakEndSound);
m_settings->endGroup();
m_settings->sync();
}
void PomodoroConfig::loadSettings()
{
if (!m_settings) return;
m_settings->beginGroup("Timer");
m_workDuration = m_settings->value("workDuration", DEFAULT_WORK_DURATION).toInt();
m_shortBreakDuration = m_settings->value("shortBreakDuration", DEFAULT_SHORT_BREAK).toInt();
m_longBreakDuration = m_settings->value("longBreakDuration", DEFAULT_LONG_BREAK).toInt();
m_settings->endGroup();
m_settings->beginGroup("UI");
m_showNotifications = m_settings->value("showNotifications", true).toBool();
m_autoStartBreaks = m_settings->value("autoStartBreaks", false).toBool();
m_settings->endGroup();
m_settings->beginGroup("Sound");
m_workEndSound = m_settings->value("workEndSound", QString()).toString();
m_breakEndSound = m_settings->value("breakEndSound", QString()).toString();
m_settings->endGroup();
}

70
PomodoroConfig.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef POMODOROCONFIG_H
#define POMODOROCONFIG_H
#include <QSettings>
#include <QString>
#include <memory>
class PomodoroConfig
{
public:
static PomodoroConfig& instance();
// Timer durations (in seconds)
int workDuration() const { return m_workDuration; }
int shortBreakDuration() const { return m_shortBreakDuration; }
int longBreakDuration() const { return m_longBreakDuration; }
void setWorkDuration(int seconds);
void setShortBreakDuration(int seconds);
void setLongBreakDuration(int seconds);
// UI settings
bool showNotifications() const { return m_showNotifications; }
void setShowNotifications(bool enabled);
bool autoStartBreaks() const { return m_autoStartBreaks; }
void setAutoStartBreaks(bool enabled);
// Sound settings
QString workEndSound() const { return m_workEndSound; }
QString breakEndSound() const { return m_breakEndSound; }
void setWorkEndSound(const QString& soundPath);
void setBreakEndSound(const QString& soundPath);
// Constants
static constexpr int DEFAULT_WORK_DURATION = 1500; // 25 minutes
static constexpr int DEFAULT_SHORT_BREAK = 300; // 5 minutes
static constexpr int DEFAULT_LONG_BREAK = 900; // 15 minutes
static constexpr int SESSIONS_BEFORE_LONG_BREAK = 4;
void saveSettings();
void loadSettings();
private:
PomodoroConfig();
~PomodoroConfig() = default;
// Disable copy/move
PomodoroConfig(const PomodoroConfig&) = delete;
PomodoroConfig& operator=(const PomodoroConfig&) = delete;
PomodoroConfig(PomodoroConfig&&) = delete;
PomodoroConfig& operator=(PomodoroConfig&&) = delete;
std::unique_ptr<QSettings> m_settings;
// Timer settings
int m_workDuration = DEFAULT_WORK_DURATION;
int m_shortBreakDuration = DEFAULT_SHORT_BREAK;
int m_longBreakDuration = DEFAULT_LONG_BREAK;
// UI settings
bool m_showNotifications = true;
bool m_autoStartBreaks = false;
// Sound settings
QString m_workEndSound;
QString m_breakEndSound;
};
#endif // POMODOROCONFIG_H

111
TimerController.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "TimerController.h"
#include <QDebug>
TimerController::TimerController(QObject *parent)
: QObject(parent)
, m_timer(std::make_unique<QTimer>(this))
{
connect(m_timer.get(), &QTimer::timeout, this, &TimerController::onTimerTick);
m_timer->setInterval(1000); // 1 second
reset();
}
void TimerController::start()
{
if (m_state == TimerState::Stopped) {
updateTotalSeconds();
m_remainingSeconds = m_totalSeconds;
}
m_state = TimerState::Running;
m_timer->start();
emit stateChanged(m_state);
}
void TimerController::pause()
{
if (m_state == TimerState::Running) {
m_state = TimerState::Paused;
m_timer->stop();
emit stateChanged(m_state);
}
}
void TimerController::reset()
{
m_timer->stop();
m_state = TimerState::Stopped;
m_currentSessionType = SessionType::Work;
updateTotalSeconds();
m_remainingSeconds = m_totalSeconds;
emit stateChanged(m_state);
emit sessionChanged(m_currentSessionType);
emit timeChanged(m_remainingSeconds);
}
void TimerController::skip()
{
m_timer->stop();
startNextSession();
}
double TimerController::progressPercentage() const
{
if (m_totalSeconds == 0) return 0.0;
return (static_cast<double>(m_totalSeconds - m_remainingSeconds) / m_totalSeconds) * 100.0;
}
void TimerController::onTimerTick()
{
if (m_remainingSeconds > 0) {
--m_remainingSeconds;
emit timeChanged(m_remainingSeconds);
} else {
m_timer->stop();
emit timerFinished();
startNextSession();
}
}
void TimerController::startNextSession()
{
switch (m_currentSessionType) {
case SessionType::Work:
++m_completedSessions;
if (m_completedSessions % SESSIONS_BEFORE_LONG_BREAK == 0) {
m_currentSessionType = SessionType::LongBreak;
} else {
m_currentSessionType = SessionType::ShortBreak;
}
break;
case SessionType::ShortBreak:
case SessionType::LongBreak:
m_currentSessionType = SessionType::Work;
break;
}
m_state = TimerState::Stopped;
updateTotalSeconds();
m_remainingSeconds = m_totalSeconds;
emit sessionChanged(m_currentSessionType);
emit stateChanged(m_state);
emit timeChanged(m_remainingSeconds);
}
void TimerController::updateTotalSeconds()
{
switch (m_currentSessionType) {
case SessionType::Work:
m_totalSeconds = m_workDuration;
break;
case SessionType::ShortBreak:
m_totalSeconds = m_shortBreakDuration;
break;
case SessionType::LongBreak:
m_totalSeconds = m_longBreakDuration;
break;
}
}

81
TimerController.h Normal file
View File

@ -0,0 +1,81 @@
#ifndef TIMERCONTROLLER_H
#define TIMERCONTROLLER_H
#include <QObject>
#include <QTimer>
#include <QDateTime>
#include <memory>
enum class SessionType {
Work,
ShortBreak,
LongBreak
};
enum class TimerState {
Stopped,
Running,
Paused
};
class TimerController : public QObject
{
Q_OBJECT
public:
explicit TimerController(QObject *parent = nullptr);
~TimerController() override = default;
// Timer control
void start();
void pause();
void reset();
void skip();
// Getters
[[nodiscard]] int remainingSeconds() const { return m_remainingSeconds; }
[[nodiscard]] int totalSeconds() const { return m_totalSeconds; }
[[nodiscard]] SessionType currentSessionType() const { return m_currentSessionType; }
[[nodiscard]] TimerState state() const { return m_state; }
[[nodiscard]] int completedSessions() const { return m_completedSessions; }
[[nodiscard]] double progressPercentage() const;
// Configuration
void setWorkDuration(int seconds) { m_workDuration = seconds; }
void setShortBreakDuration(int seconds) { m_shortBreakDuration = seconds; }
void setLongBreakDuration(int seconds) { m_longBreakDuration = seconds; }
signals:
void timeChanged(int remainingSeconds);
void sessionChanged(SessionType type);
void timerFinished();
void stateChanged(TimerState state);
private slots:
void onTimerTick();
private:
void startNextSession();
void updateTotalSeconds();
// Timer objects
std::unique_ptr<QTimer> m_timer;
// State
TimerState m_state = TimerState::Stopped;
SessionType m_currentSessionType = SessionType::Work;
// Time tracking
int m_remainingSeconds = 0;
int m_totalSeconds = 0;
int m_completedSessions = 0;
// Configuration
int m_workDuration = 1500; // 25 minutes
int m_shortBreakDuration = 300; // 5 minutes
int m_longBreakDuration = 900; // 15 minutes
static constexpr int SESSIONS_BEFORE_LONG_BREAK = 4;
};
#endif // TIMERCONTROLLER_H

BIN
logoTimer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB