mirror of
https://invent.kde.org/network/kdeconnect-kde.git
synced 2025-12-12 20:35:55 +01:00
191 lines
7.1 KiB
C++
191 lines
7.1 KiB
C++
/*
|
||
* SPDX-FileCopyrightText: 2016 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||
*
|
||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||
*/
|
||
|
||
#include <QApplication>
|
||
#include <QIcon>
|
||
#include <QPointer>
|
||
#include <QProcess>
|
||
#include <QQuickStyle>
|
||
#include <QThread>
|
||
|
||
#ifdef Q_OS_WIN
|
||
#include <Windows.h>
|
||
#endif
|
||
|
||
#ifdef Q_OS_WIN
|
||
#include <QSystemTrayIcon>
|
||
#else
|
||
#include <KStatusNotifierItem>
|
||
#endif
|
||
|
||
#include <KAboutData>
|
||
#include <KColorSchemeManager>
|
||
#include <KCrash>
|
||
#include <KDBusService>
|
||
#include <KLocalizedString>
|
||
|
||
#include "deviceindicator.h"
|
||
#include "interfaces/dbusinterfaces.h"
|
||
#include "interfaces/devicesmodel.h"
|
||
#include "interfaces/devicessortproxymodel.h"
|
||
#include "kdeconnect-version.h"
|
||
|
||
#include <dbushelper.h>
|
||
|
||
#include "indicatorhelper.h"
|
||
#include "openconfig.h"
|
||
|
||
int main(int argc, char **argv)
|
||
{
|
||
#ifdef Q_OS_WIN
|
||
// If ran from a console, redirect the output there
|
||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||
freopen("CONOUT$", "w", stdout);
|
||
freopen("CONOUT$", "w", stderr);
|
||
}
|
||
#endif
|
||
|
||
QApplication app(argc, argv);
|
||
|
||
IndicatorHelper helper;
|
||
helper.startDaemon();
|
||
|
||
KAboutData aboutData(QStringLiteral("kdeconnect-indicator"),
|
||
i18n("KDE Connect Indicator"),
|
||
QStringLiteral(KDECONNECT_VERSION_STRING),
|
||
i18n("KDE Connect Indicator tool"),
|
||
KAboutLicense::GPL,
|
||
i18n("© 2016–2025 KDE Connect Team"));
|
||
aboutData.addAuthor(i18n("Aleix Pol Gonzalez"), {}, QStringLiteral("aleixpol@kde.org"));
|
||
aboutData.addAuthor(i18n("Albert Vaca Cintora"), {}, QStringLiteral("albertvaka@kde.org"));
|
||
aboutData.setProgramLogo(QIcon::fromTheme(QStringLiteral("kdeconnect")));
|
||
KAboutData::setApplicationData(aboutData);
|
||
|
||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||
// Ensure we have a suitable color theme set for light/dark mode. KColorSchemeManager implicitly applies
|
||
// a suitable default theme.
|
||
KColorSchemeManager::instance();
|
||
// Force breeze style to ensure coloring works consistently in dark mode. Specifically tab colors have
|
||
// troubles on windows.
|
||
QApplication::setStyle(QStringLiteral("breeze"));
|
||
// Force breeze icon theme to ensure we can correctly adapt icons to color changes WRT dark/light mode.
|
||
// Without this we may end up with hicolor and fail to support icon recoloring.
|
||
QIcon::setThemeName(QStringLiteral("breeze"));
|
||
#else
|
||
QIcon::setFallbackThemeName(QStringLiteral("breeze"));
|
||
#endif
|
||
|
||
// Default to org.kde.desktop style unless the user forces another style
|
||
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) {
|
||
QQuickStyle::setStyle(QStringLiteral("org.kde.desktop"));
|
||
}
|
||
|
||
KCrash::initialize();
|
||
|
||
KDBusService dbusService(KDBusService::Unique);
|
||
|
||
DevicesModel model;
|
||
model.setDisplayFilter(DevicesModel::Reachable | DevicesModel::Paired);
|
||
DevicesSortProxyModel proxyModel;
|
||
proxyModel.setSourceModel(&model);
|
||
QMenu *menu = new QMenu;
|
||
|
||
DaemonDbusInterface iface;
|
||
|
||
auto refreshMenu = [&iface, &proxyModel, &menu]() {
|
||
menu->clear();
|
||
// Note: This is needed on macOS since a single click on the icon doesn't open the app like on other platforms.
|
||
menu->addAction(i18n("Open app"), []() {
|
||
OpenConfig oc;
|
||
oc.openConfiguration();
|
||
});
|
||
for (int i = 0, count = proxyModel.rowCount(); i < count; ++i) {
|
||
QObject *deviceObject = proxyModel.data(proxyModel.index(i, 0), DevicesModel::DeviceRole).value<QObject *>();
|
||
DeviceDbusInterface *device = qobject_cast<DeviceDbusInterface *>(deviceObject);
|
||
if (device == nullptr)
|
||
continue;
|
||
|
||
auto indicator = new DeviceIndicator(device);
|
||
QObject::connect(device, &DeviceDbusInterface::destroyed, indicator, &QObject::deleteLater);
|
||
|
||
menu->addMenu(indicator);
|
||
}
|
||
const QStringList requests = iface.pairingRequests();
|
||
if (!requests.isEmpty()) {
|
||
menu->addSection(i18n("Pairing requests"));
|
||
|
||
for (const auto &req : requests) {
|
||
DeviceDbusInterface *dev = new DeviceDbusInterface(req, menu);
|
||
auto pairMenu = menu->addMenu(dev->name());
|
||
pairMenu->addAction(i18nc("Accept a pairing request", "Pair"), dev, &DeviceDbusInterface::acceptPairing);
|
||
pairMenu->addAction(i18n("Reject"), dev, &DeviceDbusInterface::cancelPairing);
|
||
}
|
||
}
|
||
// Add quit menu
|
||
#if defined(Q_OS_MAC)
|
||
menu->addAction(i18n("Quit"), []() {
|
||
auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect.daemon"),
|
||
QStringLiteral("/MainApplication"),
|
||
QStringLiteral("org.qtproject.Qt.QCoreApplication"),
|
||
QStringLiteral("quit"));
|
||
QDBusConnection::sessionBus().call(message, QDBus::NoBlock);
|
||
qApp->quit();
|
||
});
|
||
#elif defined(Q_OS_WIN)
|
||
menu->addAction(QIcon::fromTheme(QStringLiteral("application-exit")), i18n("Quit"), []() {
|
||
qApp->quit();
|
||
});
|
||
#endif
|
||
};
|
||
|
||
QObject::connect(&iface, &DaemonDbusInterface::pairingRequestsChanged, &model, refreshMenu);
|
||
QObject::connect(&model, &DevicesModel::rowsInserted, &model, refreshMenu);
|
||
QObject::connect(&model, &DevicesModel::rowsRemoved, &model, refreshMenu);
|
||
|
||
// Run icon to add icon path (if necessary)
|
||
helper.iconPathHook();
|
||
|
||
#ifdef Q_OS_WIN
|
||
QSystemTrayIcon systray;
|
||
helper.systrayIconHook(systray);
|
||
systray.setVisible(true);
|
||
systray.setToolTip(QStringLiteral("KDE Connect"));
|
||
QObject::connect(&model, &DevicesModel::rowsChanged, &model, [&systray, &model]() {
|
||
systray.setToolTip(i18np("%1 device connected", "%1 devices connected", model.rowCount()));
|
||
});
|
||
QObject::connect(&systray, &QSystemTrayIcon::activated, [](QSystemTrayIcon::ActivationReason reason) {
|
||
if (reason == QSystemTrayIcon::Trigger) {
|
||
OpenConfig oc;
|
||
oc.openConfiguration();
|
||
}
|
||
});
|
||
|
||
systray.setContextMenu(menu);
|
||
#else
|
||
KStatusNotifierItem systray;
|
||
helper.systrayIconHook(systray);
|
||
systray.setToolTip(QStringLiteral("kdeconnect"), QStringLiteral("KDE Connect"), QStringLiteral("KDE Connect"));
|
||
systray.setCategory(KStatusNotifierItem::Communications);
|
||
systray.setStatus(KStatusNotifierItem::Passive);
|
||
systray.setStandardActionsEnabled(false);
|
||
QObject::connect(&model, &DevicesModel::rowsChanged, &model, [&systray, &model]() {
|
||
const auto count = model.rowCount();
|
||
#ifndef Q_OS_MACOS // On MacOS, setting status to Active disables color theme syncing of the menu icon
|
||
systray.setStatus(count == 0 ? KStatusNotifierItem::Passive : KStatusNotifierItem::Active);
|
||
#endif
|
||
systray.setToolTip(QStringLiteral("kdeconnect"), QStringLiteral("KDE Connect"), i18np("%1 device connected", "%1 devices connected", count));
|
||
});
|
||
|
||
systray.setContextMenu(menu);
|
||
#endif
|
||
|
||
refreshMenu();
|
||
|
||
app.setQuitOnLastWindowClosed(false);
|
||
|
||
return app.exec();
|
||
}
|