kdeconnect-kde/indicator/main.cpp
Albert Vaca Cintora bbcbec7709 Refactor macOS startup code
Moves all the stuff that is needed to start DBus on macOS (which for some reason it needs several steps, involving the use of `launchctl`) into a single `startDBusDaemon()` function. Before, it was spread into `kdeconnectconfig.cpp`, `indicatorhelper_mac.cpp` and `dbushelper.cpp`.

It also removes checking for an existing DBus daemon and always starts our own, since in most cases we couldn't connect to it anyway. This, together with removing the sleep in the retries when polling for the DBus daemon from 3s to 100ms, makes the startup much faster, so I removed the loading splash screen.
2024-09-21 09:27:24 +00:00

189 lines
6.8 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 <QPointer>
#include <QProcess>
#include <QThread>
#ifdef Q_OS_WIN
#include <Windows.h>
#endif
#ifdef Q_OS_WIN
#include <QSystemTrayIcon>
#else
#include <KStatusNotifierItem>
#endif
#include <KAboutData>
#include <KCMultiDialog>
#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"
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
QIcon::setFallbackThemeName(QStringLiteral("breeze"));
QApplication app(argc, argv);
IndicatorHelper helper;
helper.startDaemon();
KAboutData about(QStringLiteral("kdeconnect-indicator"),
i18n("KDE Connect Indicator"),
QStringLiteral(KDECONNECT_VERSION_STRING),
i18n("KDE Connect Indicator tool"),
KAboutLicense::GPL,
i18n("(C) 2016 Aleix Pol Gonzalez"));
KAboutData::setApplicationData(about);
KCrash::initialize();
#ifdef Q_OS_WIN
KColorSchemeManager manager;
QApplication::setStyle(QStringLiteral("breeze"));
#endif
KDBusService dbusService(KDBusService::Unique);
// Trigger loading the KIconLoader plugin
about.setProgramLogo(QIcon(QStringLiteral(":/icons/kdeconnect/kdeconnect.svg")));
DevicesModel model;
model.setDisplayFilter(DevicesModel::Reachable | DevicesModel::Paired);
DevicesSortProxyModel proxyModel;
proxyModel.setSourceModel(&model);
QMenu *menu = new QMenu;
QPointer<KCMultiDialog> dialog;
DaemonDbusInterface iface;
auto refreshMenu = [&iface, &proxyModel, &menu, &dialog]() {
menu->clear();
auto configure = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure..."));
QObject::connect(configure, &QAction::triggered, configure, [&dialog]() {
if (dialog == nullptr) {
dialog = new KCMultiDialog;
dialog->addModule(KPluginMetaData(QStringLiteral("plasma/kcms/systemsettings_qwidgets/kcm_kdeconnect")));
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
dialog->raise();
} else {
dialog->raise();
dialog->activateWindow();
}
});
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) {
const QString kdeconnectAppExecutable = QStandardPaths::findExecutable(QStringLiteral("kdeconnect-app"), {QCoreApplication::applicationDirPath()});
if (!kdeconnectAppExecutable.isEmpty()) {
QProcess::startDetached(kdeconnectAppExecutable, {});
}
}
});
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();
}