- NSApplicationActivationPolicyAccessory: app hidden from Dock and app switcher; lives only in the menu bar tray - resources/clouck.icns: programmatic icon (green gradient rounded square, white dial, 10:10 hands), all sizes 16-1024 incl @2x - CMake: MACOSX_BUNDLE_ICON_FILE wired, icns shipped in Resources/
144 lines
4.5 KiB
C++
144 lines
4.5 KiB
C++
#include <QApplication>
|
|
#include <QAction>
|
|
#include <QMenu>
|
|
#include <QPainter>
|
|
#include <QSettings>
|
|
#include <QStyleHints>
|
|
#include <QSystemTrayIcon>
|
|
#include "autostart_manager.h"
|
|
#include "clock_widget.h"
|
|
|
|
namespace
|
|
{
|
|
// Standard macOS menu bar icon extent (points). Matches surrounding icons.
|
|
constexpr int trayIconExtent = 16;
|
|
|
|
QIcon createTrayIcon(const QColor &color)
|
|
{
|
|
// 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));
|
|
|
|
// 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;
|
|
}
|
|
|
|
QColor trayIconColorForScheme(Qt::ColorScheme scheme)
|
|
{
|
|
return scheme == Qt::ColorScheme::Dark ? QColor(Qt::white) : QColor(Qt::black);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
QApplication app(argc, argv);
|
|
|
|
// Menu-bar-only app: no Dock icon, no app switcher entry.
|
|
#ifdef Q_OS_MAC
|
|
extern void clouck_setActivationPolicyAccessory(); // defined in window_helper_macos.mm
|
|
clouck_setActivationPolicyAccessory();
|
|
#endif
|
|
|
|
app.setApplicationName("Clouck");
|
|
app.setOrganizationName("Clouck");
|
|
app.setApplicationDisplayName("Clouck");
|
|
|
|
ClockWidget clock;
|
|
clock.show();
|
|
|
|
// 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);
|
|
trayIcon.setToolTip("Clouck");
|
|
|
|
QObject::connect(styleHints, &QStyleHints::colorSchemeChanged, &trayIcon,
|
|
[&trayIcon](Qt::ColorScheme scheme) {
|
|
trayIcon.setIcon(createTrayIcon(trayIconColorForScheme(scheme)));
|
|
});
|
|
|
|
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]() {
|
|
if (clock.isVisible())
|
|
{
|
|
clock.hide();
|
|
toggleClockAction->setText("Turn Clock On");
|
|
return;
|
|
}
|
|
|
|
clock.show();
|
|
clock.raise();
|
|
toggleClockAction->setText("Turn Clock Off");
|
|
};
|
|
|
|
QObject::connect(toggleClockAction, &QAction::triggered, &app, toggleClock);
|
|
QObject::connect(quitAction, &QAction::triggered, &app, &QApplication::quit);
|
|
|
|
trayIcon.setContextMenu(&trayMenu);
|
|
trayIcon.show();
|
|
|
|
return app.exec();
|
|
}
|