feat: dual time zones, autostart, tray icon, config relocation, tests
- Dual clock (primary/secondary time zone) with IANA picker, persisted in XML - AutoStartManager: macOS LaunchAgent (com.clouck.clock, RunAtLoad) - Tray icon: template image, light/dark adaptation, toggle + quit menu - ConfigManager: default path moved to QStandardPaths::AppConfigLocation - Qt Test suite (ConfigManager, AutoStartManager) wired into CTest - GitHub origin renamed to upstream; private Gitea repo as origin
This commit is contained in:
+94
-7
@@ -2,13 +2,14 @@
|
||||
#include "config_manager.h"
|
||||
#include "window_helper.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QTime>
|
||||
#include <QDateTime>
|
||||
#include <QColorDialog>
|
||||
#include <QFontDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
#include <QTimeZone>
|
||||
|
||||
ClockWidget::ClockWidget(QWidget *parent)
|
||||
: QWidget(parent), m_dragging(false), m_resizing(false), m_resizeBorder(5)
|
||||
@@ -48,11 +49,14 @@ ClockWidget::~ClockWidget()
|
||||
|
||||
void ClockWidget::setupUI()
|
||||
{
|
||||
m_timeLabel = new QLabel(this);
|
||||
m_timeLabel->setAlignment(Qt::AlignCenter);
|
||||
m_primaryTimeLabel = new QLabel(this);
|
||||
m_secondaryTimeLabel = new QLabel(this);
|
||||
m_primaryTimeLabel->setAlignment(Qt::AlignCenter);
|
||||
m_secondaryTimeLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_timeLabel);
|
||||
layout->addWidget(m_primaryTimeLabel);
|
||||
layout->addWidget(m_secondaryTimeLabel);
|
||||
layout->setContentsMargins(10, 10, 10, 10);
|
||||
}
|
||||
|
||||
@@ -74,6 +78,12 @@ void ClockWidget::createMenu()
|
||||
QAction *fontSizeAction = new QAction("Set Font Size", this);
|
||||
connect(fontSizeAction, &QAction::triggered, this, &ClockWidget::changeFontSize);
|
||||
|
||||
QAction *primaryTimeZoneAction = new QAction("Set First Time Zone", this);
|
||||
connect(primaryTimeZoneAction, &QAction::triggered, this, &ClockWidget::changePrimaryTimeZone);
|
||||
|
||||
QAction *secondaryTimeZoneAction = new QAction("Set Second Time Zone", this);
|
||||
connect(secondaryTimeZoneAction, &QAction::triggered, this, &ClockWidget::changeSecondaryTimeZone);
|
||||
|
||||
QAction *resetAction = new QAction("Reset Settings", this);
|
||||
connect(resetAction, &QAction::triggered, this, &ClockWidget::resetSettings);
|
||||
|
||||
@@ -86,6 +96,9 @@ void ClockWidget::createMenu()
|
||||
m_contextMenu->addAction(bgColorAction);
|
||||
m_contextMenu->addAction(fontSizeAction);
|
||||
m_contextMenu->addSeparator();
|
||||
m_contextMenu->addAction(primaryTimeZoneAction);
|
||||
m_contextMenu->addAction(secondaryTimeZoneAction);
|
||||
m_contextMenu->addSeparator();
|
||||
m_contextMenu->addAction(resetAction);
|
||||
m_contextMenu->addAction(quitAction);
|
||||
}
|
||||
@@ -179,8 +192,8 @@ void ClockWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
|
||||
void ClockWidget::updateTime()
|
||||
{
|
||||
QString currentTime = QTime::currentTime().toString("HH:mm:ss");
|
||||
m_timeLabel->setText(currentTime);
|
||||
m_primaryTimeLabel->setText(formattedTime(m_primaryTimeZoneId));
|
||||
m_secondaryTimeLabel->setText(formattedTime(m_secondaryTimeZoneId));
|
||||
}
|
||||
|
||||
void ClockWidget::toggleAlwaysOnTop()
|
||||
@@ -240,6 +253,16 @@ void ClockWidget::changeFontSize()
|
||||
}
|
||||
}
|
||||
|
||||
void ClockWidget::changePrimaryTimeZone()
|
||||
{
|
||||
changeTimeZone(true);
|
||||
}
|
||||
|
||||
void ClockWidget::changeSecondaryTimeZone()
|
||||
{
|
||||
changeTimeZone(false);
|
||||
}
|
||||
|
||||
void ClockWidget::resetSettings()
|
||||
{
|
||||
int ret = QMessageBox::question(this, "Reset Settings", "Are you sure you want to reset all settings?");
|
||||
@@ -304,6 +327,8 @@ void ClockWidget::loadSettings()
|
||||
m_backgroundColor = m_configManager->backgroundColor();
|
||||
m_fontSize = m_configManager->fontSize();
|
||||
m_alwaysOnTop = m_configManager->alwaysOnTop();
|
||||
m_primaryTimeZoneId = m_configManager->primaryTimeZoneId();
|
||||
m_secondaryTimeZoneId = m_configManager->secondaryTimeZoneId();
|
||||
|
||||
// Restore window position and size
|
||||
QPoint windowPos = m_configManager->windowPosition();
|
||||
@@ -344,6 +369,8 @@ void ClockWidget::saveSettings()
|
||||
m_configManager->setAlwaysOnTop(m_alwaysOnTop);
|
||||
m_configManager->setWindowPosition(pos());
|
||||
m_configManager->setWindowSize(size());
|
||||
m_configManager->setPrimaryTimeZoneId(m_primaryTimeZoneId);
|
||||
m_configManager->setSecondaryTimeZoneId(m_secondaryTimeZoneId);
|
||||
|
||||
// Save to XML file
|
||||
if (!m_configManager->saveSettings())
|
||||
@@ -357,6 +384,7 @@ void ClockWidget::updateStyleSheet()
|
||||
QString styleSheet = QString(
|
||||
"QLabel { "
|
||||
"color: %1; "
|
||||
"font-family: 'SF Pro Rounded'; "
|
||||
"font-size: %2pt; "
|
||||
"font-weight: bold; "
|
||||
"background-color: %3; "
|
||||
@@ -367,6 +395,65 @@ void ClockWidget::updateStyleSheet()
|
||||
QString::number(m_fontSize),
|
||||
m_backgroundColor.name(QColor::HexArgb));
|
||||
|
||||
m_timeLabel->setStyleSheet(styleSheet);
|
||||
m_primaryTimeLabel->setStyleSheet(styleSheet);
|
||||
m_secondaryTimeLabel->setStyleSheet(styleSheet);
|
||||
setStyleSheet(QString("background-color: transparent;"));
|
||||
}
|
||||
|
||||
void ClockWidget::changeTimeZone(bool primaryClock)
|
||||
{
|
||||
QStringList timeZoneIds;
|
||||
for (const QByteArray &timeZoneId : QTimeZone::availableTimeZoneIds())
|
||||
{
|
||||
timeZoneIds.append(QString::fromUtf8(timeZoneId));
|
||||
}
|
||||
|
||||
const QString currentTimeZoneId = primaryClock ? m_primaryTimeZoneId : m_secondaryTimeZoneId;
|
||||
const int currentIndex = timeZoneIds.indexOf(currentTimeZoneId);
|
||||
bool accepted = false;
|
||||
const QString selectedTimeZoneId = QInputDialog::getItem(
|
||||
this,
|
||||
primaryClock ? "Set First Time Zone" : "Set Second Time Zone",
|
||||
"Time Zone:",
|
||||
timeZoneIds,
|
||||
currentIndex < 0 ? 0 : currentIndex,
|
||||
false,
|
||||
&accepted);
|
||||
|
||||
if (!accepted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (primaryClock)
|
||||
{
|
||||
m_primaryTimeZoneId = selectedTimeZoneId;
|
||||
m_configManager->setPrimaryTimeZoneId(selectedTimeZoneId);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_secondaryTimeZoneId = selectedTimeZoneId;
|
||||
m_configManager->setSecondaryTimeZoneId(selectedTimeZoneId);
|
||||
}
|
||||
|
||||
if (!m_configManager->saveSettings())
|
||||
{
|
||||
qDebug() << "Failed to save time zone settings to config.xml";
|
||||
}
|
||||
updateTime();
|
||||
}
|
||||
|
||||
QString ClockWidget::formattedTime(const QString &timeZoneId) const
|
||||
{
|
||||
const QTimeZone timeZone(timeZoneId.toUtf8());
|
||||
if (!timeZone.isValid())
|
||||
{
|
||||
qWarning() << "Invalid time zone configured:" << timeZoneId;
|
||||
return QString("Invalid time zone\n%1").arg(timeZoneId);
|
||||
}
|
||||
|
||||
const QDateTime timeInZone = QDateTime::currentDateTimeUtc().toTimeZone(timeZone);
|
||||
const QString cityName = QString::fromUtf8(timeZone.id()).section('/', -1).replace('_', ' ');
|
||||
return QString("%1\n%2")
|
||||
.arg(timeInZone.time().toString("HH:mm"), cityName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user