File indexing completed on 2024-03-24 04:59:55

0001 /*
0002  * SPDX-FileCopyrightText: 2017 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 <QAbstractButton>
0008 #include <QApplication>
0009 #include <QComboBox>
0010 #include <QCommandLineParser>
0011 #include <QDBusMessage>
0012 #include <QDialog>
0013 #include <QFileDialog>
0014 #include <QMessageBox>
0015 #include <QTextStream>
0016 #include <QUrl>
0017 
0018 #include <KAboutData>
0019 #include <KColorSchemeManager>
0020 #include <KDBusService>
0021 #include <KLocalizedString>
0022 #include <KUrlRequester>
0023 
0024 #include <dbushelper.h>
0025 
0026 #include "kdeconnect-version.h"
0027 #include "ui_dialog.h"
0028 #include <interfaces/dbushelpers.h>
0029 #include <interfaces/dbusinterfaces.h>
0030 #include <interfaces/devicesmodel.h>
0031 #include <interfaces/devicespluginfilterproxymodel.h>
0032 
0033 /**
0034  * Show only devices that can be shared to
0035  */
0036 
0037 int main(int argc, char **argv)
0038 {
0039     QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
0040     QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
0041     QApplication app(argc, argv);
0042     app.setWindowIcon(QIcon::fromTheme(QStringLiteral("kdeconnect")));
0043     const QString description = i18n("KDE Connect URL handler");
0044     KAboutData about(QStringLiteral("kdeconnect.handler"),
0045                      description,
0046                      QStringLiteral(KDECONNECT_VERSION_STRING),
0047                      description,
0048                      KAboutLicense::GPL,
0049                      i18n("(C) 2017 Aleix Pol Gonzalez"));
0050     about.addAuthor(QStringLiteral("Aleix Pol Gonzalez"), QString(), QStringLiteral("aleixpol@kde.org"));
0051     about.setProgramLogo(QIcon(QStringLiteral(":/icons/kdeconnect/kdeconnect.svg")));
0052     KAboutData::setApplicationData(about);
0053     KDBusService dbusService(KDBusService::Unique);
0054 
0055 #ifdef Q_OS_WIN
0056     KColorSchemeManager manager;
0057     QApplication::setStyle(QStringLiteral("breeze"));
0058 #endif
0059 
0060     QUrl urlToShare;
0061     bool open;
0062     QString deviceId;
0063     {
0064         QCommandLineParser parser;
0065         parser.addPositionalArgument(QStringLiteral("url"), i18n("URL to share"));
0066         parser.addOption(QCommandLineOption(QStringLiteral("device"), i18n("Select a device"), i18n("id")));
0067         parser.addOption(QCommandLineOption(QStringLiteral("open"), QStringLiteral("Open the file on the remote device")));
0068         about.setupCommandLine(&parser);
0069         parser.process(app);
0070         about.processCommandLine(&parser);
0071         if (parser.positionalArguments().count() == 1) {
0072             urlToShare = QUrl::fromUserInput(parser.positionalArguments().constFirst(), QDir::currentPath(), QUrl::AssumeLocalFile);
0073         }
0074         open = parser.isSet(QStringLiteral("open"));
0075         deviceId = parser.value(QStringLiteral("device"));
0076     }
0077 
0078     DevicesModel model;
0079     model.setDisplayFilter(DevicesModel::Paired | DevicesModel::Reachable);
0080     DevicesPluginFilterProxyModel proxyModel;
0081     proxyModel.setPluginFilter(QStringLiteral("kdeconnect_share"));
0082     proxyModel.setSourceModel(&model);
0083 
0084     QDialog dialog;
0085 
0086     Ui::Dialog uidialog;
0087     uidialog.setupUi(&dialog);
0088     uidialog.devicePicker->setModel(&proxyModel);
0089 
0090     if (!deviceId.isEmpty()) {
0091         uidialog.devicePicker->setCurrentIndex(model.rowForDevice(deviceId));
0092     }
0093 
0094     uidialog.openOnPeerCheckBox->setChecked(open);
0095 
0096     KUrlRequester *urlRequester = new KUrlRequester(&dialog);
0097     urlRequester->setStartDir(QUrl::fromLocalFile(QDir::homePath()));
0098     uidialog.urlHorizontalLayout->addWidget(urlRequester);
0099 
0100     QObject::connect(uidialog.sendUrlRadioButton, &QRadioButton::toggled, [&uidialog, urlRequester](const bool checked) {
0101         if (checked) {
0102             urlRequester->setPlaceholderText(i18n("Enter URL here"));
0103             urlRequester->button()->setVisible(false);
0104             uidialog.openOnPeerCheckBox->setVisible(false);
0105         }
0106     });
0107 
0108     QObject::connect(uidialog.sendFileRadioButton, &QAbstractButton::toggled, [&uidialog, urlRequester](const bool checked) {
0109         if (checked) {
0110             urlRequester->setPlaceholderText(i18n("Enter file location here"));
0111             urlRequester->button()->setVisible(true);
0112             uidialog.openOnPeerCheckBox->setVisible(true);
0113         }
0114     });
0115 
0116     QObject::connect(urlRequester, &KUrlRequester::textChanged, [&urlRequester, &uidialog]() {
0117         QUrl fileUrl(urlRequester->url());
0118         bool isLocalFileUrl = false;
0119         if (fileUrl.isLocalFile()) {
0120             QFileInfo fileInfo(fileUrl.toLocalFile());
0121             isLocalFileUrl = fileInfo.exists() && fileInfo.isFile(); // we don't support sending directories yet!
0122         }
0123         uidialog.sendFileRadioButton->setChecked(isLocalFileUrl);
0124         uidialog.sendUrlRadioButton->setChecked(!isLocalFileUrl);
0125     });
0126 
0127     if (!urlToShare.isEmpty()) {
0128         uidialog.sendUrlRadioButton->setVisible(false);
0129         uidialog.sendFileRadioButton->setVisible(false);
0130         urlRequester->setVisible(false);
0131 
0132         QString displayUrl;
0133         if (urlToShare.scheme() == QLatin1String("tel")) {
0134             displayUrl = urlToShare.toDisplayString(QUrl::RemoveScheme);
0135             uidialog.label->setText(i18n("Device to call %1 with:", displayUrl));
0136         } else if (urlToShare.isLocalFile() && open) {
0137             displayUrl = urlToShare.toDisplayString(QUrl::PreferLocalFile);
0138             uidialog.label->setText(i18n("Device to open %1 on:", displayUrl));
0139         } else if (urlToShare.scheme() == QLatin1String("sms")) {
0140             displayUrl = urlToShare.toDisplayString(QUrl::PreferLocalFile);
0141             uidialog.label->setText(i18n("Device to send a SMS with:"));
0142         } else {
0143             displayUrl = urlToShare.toDisplayString(QUrl::PreferLocalFile);
0144             uidialog.label->setText(i18n("Device to send %1 to:", displayUrl));
0145         }
0146     }
0147 
0148     if (open || urlToShare.isLocalFile()) {
0149         uidialog.sendFileRadioButton->setChecked(true);
0150         urlRequester->setUrl(QUrl(urlToShare.toLocalFile()));
0151 
0152     } else {
0153         uidialog.sendUrlRadioButton->setChecked(true);
0154         urlRequester->setUrl(urlToShare);
0155     }
0156 
0157     if (dialog.exec() == QDialog::Accepted) {
0158         const QUrl url = urlRequester->url();
0159         open = uidialog.openOnPeerCheckBox->isChecked();
0160         const int currentDeviceIndex = uidialog.devicePicker->currentIndex();
0161         if (!url.isEmpty() && currentDeviceIndex >= 0) {
0162             const QString device = proxyModel.index(currentDeviceIndex, 0).data(DevicesModel::IdModelRole).toString();
0163             const QString action = open && url.isLocalFile() ? QStringLiteral("openFile") : QStringLiteral("shareUrl");
0164 
0165             QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"),
0166                                                               QLatin1String("/modules/kdeconnect/devices/%1/share").arg(device),
0167                                                               QStringLiteral("org.kde.kdeconnect.device.share"),
0168                                                               action);
0169             msg.setArguments({url.toString()});
0170             blockOnReply(QDBusConnection::sessionBus().asyncCall(msg));
0171             return 0;
0172         } else {
0173             QMessageBox::critical(nullptr, description, i18n("Couldn't share %1", url.toString()));
0174             return 1;
0175         }
0176     } else {
0177         return 1;
0178     }
0179 }