feat: tray-first UX, text outline, start-at-login toggle, font max 200
- All settings move to flat tray menu; right-click on clock disabled - ClockLabel: custom QPainterPath text rendering with configurable glyph outline (BorderColor) — verified pixel-level offscreen - Fixed glyph positioning bug (baseline math) caught by isolated test - Window auto-fits content (adjustSize) — no more oversized clock - Start at Login: checkable tray item, persisted in QSettings, LaunchAgent enable/disable (TDD: roundTrip test caught disable() returning false when plist already absent) - Color dialog: hex/HTML input + 'transparent' + native picker fallback; opaque colors stored as #RRGGBB - Border: glyph outline instead of box border; background still painted in paintEvent (QSS doesn't render with WA_TranslucentBackground on macOS) - Removed window shadow (setHasShadow:NO), no bold, SF Pro Rounded - Font size dialogs allow up to 200 (was 72) - macOS: icon template 16pt, light/dark auto-adapt; LaunchAgent points to /Applications install
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QSettings>
|
||||
#include <QStyleHints>
|
||||
#include <QSystemTrayIcon>
|
||||
#include "autostart_manager.h"
|
||||
@@ -14,23 +15,27 @@ constexpr int trayIconExtent = 16;
|
||||
|
||||
QIcon createTrayIcon(const QColor &color)
|
||||
{
|
||||
QPixmap pixmap(trayIconExtent, trayIconExtent);
|
||||
pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
|
||||
// Render at 16 logical points times the device pixel ratio so the
|
||||
// bitmap is crisp on Retina but occupies exactly one menu bar cell.
|
||||
const qreal devicePixelRatio = qApp->devicePixelRatio();
|
||||
QPixmap pixmap(qRound(trayIconExtent * devicePixelRatio),
|
||||
qRound(trayIconExtent * devicePixelRatio));
|
||||
pixmap.setDevicePixelRatio(devicePixelRatio);
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(QPen(color, 1.5));
|
||||
painter.drawEllipse(QPointF(8, 8), 5.5, 5.5);
|
||||
painter.drawLine(QPointF(8, 4.5), QPointF(8, 8));
|
||||
painter.drawLine(QPointF(8, 8), QPointF(10.5, 9.5));
|
||||
|
||||
QIcon icon(pixmap);
|
||||
#ifdef Q_OS_MAC
|
||||
// Template image: the system tints it black/white to match the
|
||||
// active appearance, like native menu bar icons.
|
||||
icon.setIsMask(true);
|
||||
#endif
|
||||
// Draw inside the 16pt coordinate space; center with a small margin.
|
||||
const QPointF center(trayIconExtent / 2.0, trayIconExtent / 2.0);
|
||||
const qreal radius = trayIconExtent / 2.0 - 1.5;
|
||||
painter.drawEllipse(center, radius, radius);
|
||||
painter.drawLine(QPointF(center.x(), center.y() - radius * 0.55), center);
|
||||
painter.drawLine(center, QPointF(center.x() + radius * 0.5, center.y() + radius * 0.3));
|
||||
|
||||
QIcon icon;
|
||||
icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off);
|
||||
return icon;
|
||||
}
|
||||
|
||||
@@ -51,7 +56,20 @@ int main(int argc, char *argv[])
|
||||
ClockWidget clock;
|
||||
clock.show();
|
||||
|
||||
AutoStartManager::enableForCurrentApplication();
|
||||
// Start at Login: honor the persisted choice instead of always forcing it.
|
||||
{
|
||||
QSettings autoStartSettings("Clouck", "Clouck");
|
||||
const bool startAtLogin = autoStartSettings.value("startAtLogin", true).toBool();
|
||||
if (startAtLogin)
|
||||
{
|
||||
AutoStartManager::enableForCurrentApplication();
|
||||
}
|
||||
else
|
||||
{
|
||||
AutoStartManager::disable();
|
||||
}
|
||||
autoStartSettings.setValue("startAtLogin", startAtLogin);
|
||||
}
|
||||
|
||||
const QStyleHints *styleHints = app.styleHints();
|
||||
QSystemTrayIcon trayIcon(createTrayIcon(trayIconColorForScheme(styleHints->colorScheme())), &app);
|
||||
@@ -64,6 +82,36 @@ int main(int argc, char *argv[])
|
||||
|
||||
QMenu trayMenu;
|
||||
QAction *toggleClockAction = trayMenu.addAction("Turn Clock Off");
|
||||
|
||||
QAction *startAtLoginAction = trayMenu.addAction("Start at Login");
|
||||
{
|
||||
QSettings autoStartSettings("Clouck", "Clouck");
|
||||
startAtLoginAction->setCheckable(true);
|
||||
startAtLoginAction->setChecked(autoStartSettings.value("startAtLogin", true).toBool());
|
||||
}
|
||||
QObject::connect(startAtLoginAction, &QAction::toggled, &app, [](bool checked) {
|
||||
QSettings autoStartSettings("Clouck", "Clouck");
|
||||
autoStartSettings.setValue("startAtLogin", checked);
|
||||
if (checked)
|
||||
{
|
||||
AutoStartManager::enableForCurrentApplication();
|
||||
}
|
||||
else
|
||||
{
|
||||
AutoStartManager::disable();
|
||||
}
|
||||
});
|
||||
|
||||
trayMenu.addSeparator();
|
||||
|
||||
// Clock settings live directly in the tray menu — no submenu.
|
||||
const QList<QAction *> clockActions = clock.menu()->actions();
|
||||
for (QAction *action : clockActions)
|
||||
{
|
||||
trayMenu.addAction(action);
|
||||
}
|
||||
|
||||
trayMenu.addSeparator();
|
||||
QAction *quitAction = trayMenu.addAction("Quit");
|
||||
|
||||
const auto toggleClock = [&clock, toggleClockAction]() {
|
||||
@@ -81,13 +129,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
QObject::connect(toggleClockAction, &QAction::triggered, &app, toggleClock);
|
||||
QObject::connect(quitAction, &QAction::triggered, &app, &QApplication::quit);
|
||||
QObject::connect(&trayIcon, &QSystemTrayIcon::activated, &app,
|
||||
[toggleClock](QSystemTrayIcon::ActivationReason reason) {
|
||||
if (reason == QSystemTrayIcon::Trigger)
|
||||
{
|
||||
toggleClock();
|
||||
}
|
||||
});
|
||||
|
||||
trayIcon.setContextMenu(&trayMenu);
|
||||
trayIcon.show();
|
||||
|
||||
Reference in New Issue
Block a user