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:
2026-08-19 22:41:33 +03:00
parent 6b9cb32534
commit d9008479c1
9 changed files with 402 additions and 61 deletions
+20 -6
View File
@@ -107,6 +107,14 @@ bool ConfigManager::loadSettings(const QString &filename)
{
m_secondaryTimeZoneId = text;
}
else if (name == "BorderColor")
{
m_borderColor = QColor(text);
}
else if (name == "LocationFontSize")
{
m_locationFontSize = text.toInt();
}
else
{
reader.skipCurrentElement();
@@ -153,14 +161,18 @@ bool ConfigManager::saveSettings(const QString &filename)
// Root element
writer.writeStartElement("ClouckConfig");
// Font color
writer.writeTextElement("FontColor", m_fontColor.name(QColor::HexArgb));
// Colors: store #RRGGBB when fully opaque, #AARRGGBB when translucent —
// the XML stays close to what the user typed.
const auto colorString = [](const QColor &color) {
return color.alpha() == 255 ? color.name(QColor::HexRgb) : color.name(QColor::HexArgb);
};
writer.writeTextElement("FontColor", colorString(m_fontColor));
writer.writeTextElement("BackgroundColor", colorString(m_backgroundColor));
writer.writeTextElement("BorderColor", colorString(m_borderColor));
// Background color
writer.writeTextElement("BackgroundColor", m_backgroundColor.name(QColor::HexArgb));
// Font size
// Font sizes
writer.writeTextElement("FontSize", QString::number(m_fontSize));
writer.writeTextElement("LocationFontSize", QString::number(m_locationFontSize));
// Always on top
writer.writeTextElement("AlwaysOnTop", m_alwaysOnTop ? "true" : "false");
@@ -214,4 +226,6 @@ void ConfigManager::setDefaultValues()
m_windowSize = QSize(240, 160); // Default clock size
m_primaryTimeZoneId = QString::fromUtf8(QTimeZone::systemTimeZoneId());
m_secondaryTimeZoneId = QStringLiteral("America/Los_Angeles");
m_borderColor = QColor(0, 0, 0, 0); // No border by default
m_locationFontSize = 12; // Smaller city label under the time
}