#include #include #include #include #include #include #include #include #include #include #include #include "nearby_tray_controller.h" namespace { QIcon BuildTintedSymbolicIcon(const QString& source, const QColor& color) { QIcon source_icon(source); if (source_icon.isNull()) { return QIcon(); } QIcon tinted_icon; for (int size : {16, 18, 20, 22, 24, 32}) { QPixmap pixmap = source_icon.pixmap(size, size); if (pixmap.isNull()) { continue; } QPixmap tinted(pixmap.size()); tinted.fill(Qt::transparent); QPainter painter(&tinted); painter.drawPixmap(0, 0, pixmap); painter.setCompositionMode(QPainter::CompositionMode_SourceIn); painter.fillRect(tinted.rect(), color); painter.end(); tinted_icon.addPixmap(tinted); } return tinted_icon; } } // namespace int main(int argc, char* argv[]) { QApplication app(argc, argv); app.setQuitOnLastWindowClosed(false); NearbyTrayController controller; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("nearbyController", &controller); engine.load(QUrl(QStringLiteral("qrc:/qml/Main.qml"))); if (engine.rootObjects().isEmpty()) { return 1; } auto* window = qobject_cast(engine.rootObjects().first()); if (window == nullptr) { return 1; } const auto resolve_tray_icon = [&app]() { // Render the bundled symbolic icon with palette text color so it adapts to light/dark themes. const QColor symbolic_color = app.palette().color(QPalette::WindowText); QIcon tray_icon = BuildTintedSymbolicIcon( QStringLiteral(":/icons/tray_icon-symbolic.svg"), symbolic_color); // Fallback to system themed icon. if (tray_icon.isNull()) { tray_icon = QIcon::fromTheme(QStringLiteral("network-wireless-symbolic")); } // Fallback to custom PNG icon. if (tray_icon.isNull()) { tray_icon = QIcon(QStringLiteral(":/icons/tray_icon.png")); } // Final fallback. if (tray_icon.isNull()) { tray_icon = app.windowIcon(); } return tray_icon; }; QIcon tray_icon = resolve_tray_icon(); QSystemTrayIcon tray(tray_icon); tray.setToolTip(QStringLiteral("Nearby QML Tray")); QMenu tray_menu; QAction* show_action = tray_menu.addAction(QStringLiteral("Show")); QAction* hide_action = tray_menu.addAction(QStringLiteral("Hide")); tray_menu.addSeparator(); QAction* quit_action = tray_menu.addAction(QStringLiteral("Quit")); QObject::connect(show_action, &QAction::triggered, window, [window]() { window->show(); window->raise(); window->requestActivate(); }); QObject::connect(hide_action, &QAction::triggered, window, [window]() { window->hide(); }); QObject::connect(quit_action, &QAction::triggered, &app, [&controller, &app]() { controller.stop(); app.quit(); }); QObject::connect(&tray, &QSystemTrayIcon::activated, window, [&tray, window](QSystemTrayIcon::ActivationReason reason) { if (reason != QSystemTrayIcon::Trigger && reason != QSystemTrayIcon::DoubleClick) { return; } if (window->isVisible()) { window->hide(); } else { window->show(); window->raise(); window->requestActivate(); } }); QObject::connect(&controller, &NearbyTrayController::requestTrayMessage, &tray, [&tray](const QString& title, const QString& body) { tray.showMessage(title, body, QSystemTrayIcon::Information, 3000); }); QObject::connect(&app, &QCoreApplication::aboutToQuit, &controller, [&controller]() { controller.stop(); }); QObject::connect(app.styleHints(), &QStyleHints::colorSchemeChanged, &tray, [&tray, &resolve_tray_icon](Qt::ColorScheme) { tray.setIcon(resolve_tray_icon()); }); tray.setContextMenu(&tray_menu); tray.show(); return app.exec(); }