Warning, file /network/kdeconnect-kde/indicator/main.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include <QApplication> 0008 #include <QPointer> 0009 #include <QProcess> 0010 #include <QThread> 0011 0012 #ifdef Q_OS_WIN 0013 #include <Windows.h> 0014 #endif 0015 0016 #ifdef Q_OS_WIN 0017 #include <QSystemTrayIcon> 0018 #else 0019 #include <KStatusNotifierItem> 0020 #endif 0021 0022 #include <KAboutData> 0023 #include <KCMultiDialog> 0024 #include <KColorSchemeManager> 0025 #include <KDBusService> 0026 #include <KLocalizedString> 0027 0028 #include "deviceindicator.h" 0029 #include "interfaces/dbusinterfaces.h" 0030 #include "interfaces/devicesmodel.h" 0031 #include "kdeconnect-version.h" 0032 0033 #include <dbushelper.h> 0034 0035 #include "indicatorhelper.h" 0036 0037 int main(int argc, char **argv) 0038 { 0039 #ifdef Q_OS_WIN 0040 // If ran from a console, redirect the output there 0041 if (AttachConsole(ATTACH_PARENT_PROCESS)) { 0042 freopen("CONOUT$", "w", stdout); 0043 freopen("CONOUT$", "w", stderr); 0044 } 0045 #endif 0046 0047 QIcon::setFallbackThemeName(QStringLiteral("breeze")); 0048 QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 0049 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 0050 0051 QApplication app(argc, argv); 0052 KAboutData about(QStringLiteral("kdeconnect-indicator"), 0053 i18n("KDE Connect Indicator"), 0054 QStringLiteral(KDECONNECT_VERSION_STRING), 0055 i18n("KDE Connect Indicator tool"), 0056 KAboutLicense::GPL, 0057 i18n("(C) 2016 Aleix Pol Gonzalez")); 0058 KAboutData::setApplicationData(about); 0059 0060 #ifdef Q_OS_WIN 0061 KColorSchemeManager manager; 0062 QApplication::setStyle(QStringLiteral("breeze")); 0063 IndicatorHelper helper(QUrl::fromLocalFile(qApp->applicationDirPath())); 0064 #else 0065 IndicatorHelper helper; 0066 #endif 0067 0068 helper.preInit(); 0069 0070 // Run Daemon initialization step 0071 // When run from macOS app bundle, D-Bus call should be later than kdeconnectd and D-Bus daemon 0072 QProcess kdeconnectd; 0073 if (helper.daemonHook(kdeconnectd)) { 0074 return -1; 0075 } 0076 0077 KDBusService dbusService(KDBusService::Unique); 0078 0079 // Trigger loading the KIconLoader plugin 0080 about.setProgramLogo(QIcon(QStringLiteral(":/icons/kdeconnect/kdeconnect.svg"))); 0081 0082 DevicesModel model; 0083 model.setDisplayFilter(DevicesModel::Reachable | DevicesModel::Paired); 0084 QMenu *menu = new QMenu; 0085 0086 QPointer<KCMultiDialog> dialog; 0087 0088 DaemonDbusInterface iface; 0089 0090 auto refreshMenu = [&iface, &model, &menu, &helper, &dialog]() { 0091 menu->clear(); 0092 auto configure = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure...")); 0093 QObject::connect(configure, &QAction::triggered, configure, [&dialog]() { 0094 if (dialog == nullptr) { 0095 dialog = new KCMultiDialog; 0096 dialog->addModule(KPluginMetaData(QStringLiteral("plasma/kcms/systemsettings_qwidgets/kcm_kdeconnect"))); 0097 dialog->setAttribute(Qt::WA_DeleteOnClose); 0098 dialog->show(); 0099 dialog->raise(); 0100 } else { 0101 dialog->raise(); 0102 dialog->activateWindow(); 0103 } 0104 }); 0105 for (int i = 0, count = model.rowCount(); i < count; ++i) { 0106 DeviceDbusInterface *device = model.getDevice(i); 0107 auto indicator = new DeviceIndicator(device); 0108 QObject::connect(device, &DeviceDbusInterface::destroyed, indicator, &QObject::deleteLater); 0109 0110 menu->addMenu(indicator); 0111 } 0112 const QStringList requests = iface.pairingRequests(); 0113 if (!requests.isEmpty()) { 0114 menu->addSection(i18n("Pairing requests")); 0115 0116 for (const auto &req : requests) { 0117 DeviceDbusInterface *dev = new DeviceDbusInterface(req, menu); 0118 auto pairMenu = menu->addMenu(dev->name()); 0119 pairMenu->addAction(i18nc("Accept a pairing request", "Pair"), dev, &DeviceDbusInterface::acceptPairing); 0120 pairMenu->addAction(i18n("Reject"), dev, &DeviceDbusInterface::cancelPairing); 0121 } 0122 } 0123 // Add quit menu 0124 #if defined Q_OS_MAC 0125 0126 menu->addAction(i18n("Quit"), []() { 0127 auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect.daemon"), 0128 QStringLiteral("/MainApplication"), 0129 QStringLiteral("org.qtproject.Qt.QCoreApplication"), 0130 QStringLiteral("quit")); 0131 QDBusConnection::sessionBus().call(message, QDBus::NoBlock); 0132 qApp->quit(); 0133 }); 0134 #elif defined Q_OS_WIN 0135 0136 menu->addAction(QIcon::fromTheme(QStringLiteral("application-exit")), i18n("Quit"), []() { 0137 qApp->quit(); 0138 }); 0139 #endif 0140 }; 0141 0142 QObject::connect(&iface, &DaemonDbusInterface::pairingRequestsChangedProxy, &model, refreshMenu); 0143 QObject::connect(&model, &DevicesModel::rowsInserted, &model, refreshMenu); 0144 QObject::connect(&model, &DevicesModel::rowsRemoved, &model, refreshMenu); 0145 0146 // Run icon to add icon path (if necessary) 0147 helper.iconPathHook(); 0148 0149 #ifdef Q_OS_WIN 0150 QSystemTrayIcon systray; 0151 helper.systrayIconHook(systray); 0152 systray.setVisible(true); 0153 systray.setToolTip(QStringLiteral("KDE Connect")); 0154 QObject::connect(&model, &DevicesModel::rowsChanged, &model, [&systray, &model]() { 0155 systray.setToolTip(i18np("%1 device connected", "%1 devices connected", model.rowCount())); 0156 }); 0157 QObject::connect(&systray, &QSystemTrayIcon::activated, [](QSystemTrayIcon::ActivationReason reason) { 0158 if (reason == QSystemTrayIcon::Trigger) { 0159 const QString kdeconnectAppExecutable = QStandardPaths::findExecutable(QStringLiteral("kdeconnect-app"), {QCoreApplication::applicationDirPath()}); 0160 if (!kdeconnectAppExecutable.isEmpty()) { 0161 QProcess::startDetached(kdeconnectAppExecutable, {}); 0162 } 0163 } 0164 }); 0165 0166 systray.setContextMenu(menu); 0167 #else 0168 KStatusNotifierItem systray; 0169 helper.systrayIconHook(systray); 0170 systray.setToolTip(QStringLiteral("kdeconnect"), QStringLiteral("KDE Connect"), QStringLiteral("KDE Connect")); 0171 systray.setCategory(KStatusNotifierItem::Communications); 0172 systray.setStatus(KStatusNotifierItem::Passive); 0173 systray.setStandardActionsEnabled(false); 0174 QObject::connect(&model, &DevicesModel::rowsChanged, &model, [&systray, &model]() { 0175 const auto count = model.rowCount(); 0176 #ifndef Q_OS_MACOS // On MacOS, setting status to Active disables color theme syncing of the menu icon 0177 systray.setStatus(count == 0 ? KStatusNotifierItem::Passive : KStatusNotifierItem::Active); 0178 #endif 0179 systray.setToolTip(QStringLiteral("kdeconnect"), QStringLiteral("KDE Connect"), i18np("%1 device connected", "%1 devices connected", count)); 0180 }); 0181 0182 systray.setContextMenu(menu); 0183 #endif 0184 0185 refreshMenu(); 0186 0187 app.setQuitOnLastWindowClosed(false); 0188 0189 // Finish init 0190 helper.postInit(); 0191 0192 return app.exec(); 0193 }