Fixed architecture
This commit is contained in:
parent
328600b777
commit
af6ef391f4
124
PomodoroConfig.cpp
Normal file
124
PomodoroConfig.cpp
Normal 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
70
PomodoroConfig.h
Normal 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
111
TimerController.cpp
Normal 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
81
TimerController.h
Normal 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
BIN
logoTimer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Loading…
Reference in New Issue
Block a user