diff --git a/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.h b/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.h --- a/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.h +++ b/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.h @@ -44,6 +44,7 @@ void showCalendar(const QDate &date) const; void addToCalendar(SemanticMemento *memento) const; void openInApp(MimeTreeParser::Interface::BodyPart *part) const; + void openWithKDEConnect(MimeTreeParser::Interface::BodyPart *part, const QString &deviceId) const; QString m_appPath; }; diff --git a/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp b/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp --- a/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp +++ b/plugins/messageviewer/bodypartformatter/semantic/semanticurlhandler.cpp @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include #include @@ -275,6 +277,29 @@ }); } + QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), QStringLiteral("/modules/kdeconnect"), QStringLiteral("org.kde.kdeconnect.daemon"), QStringLiteral("devices")); + msg.setArguments({true, true}); + QDBusPendingReply reply = QDBusConnection::sessionBus().asyncCall(msg); + reply.waitForFinished(); + + if(reply.isValid()) { + for (const QString &deviceId : reply.value()) { + + QDBusInterface deviceIface(QStringLiteral("org.kde.kdeconnect"), QStringLiteral("/modules/kdeconnect/devices/") + deviceId, QStringLiteral("org.kde.kdeconnect.device")); + + QDBusReply pluginReply = deviceIface.call(QLatin1String("hasPlugin"), QLatin1String("kdeconnect_share")); + + if (pluginReply.value()) { + + action = menu.addAction(QIcon::fromTheme(QStringLiteral("kdeconnect")), i18n("Send to %1", deviceIface.property("name").toString())); + + QObject::connect(action, &QAction::triggered, this, [this, part, deviceId]() { + openWithKDEConnect(part, deviceId); + }); + } + } + } + menu.exec(p); return true; } @@ -423,10 +448,62 @@ return; } f.write(b); + f.close(); part->nodeHelper()->addTempFile(f.fileName()); f.setAutoRemove(false); args.push_back(f.fileName()); } QProcess::startDetached(m_appPath, args); } + +void SemanticUrlHandler::openWithKDEConnect(MimeTreeParser::Interface::BodyPart *part, const QString &deviceId) const +{ + QTemporaryFile f(QStringLiteral("itinerary.XXXXXX.jsonld")); + if (!f.open()) { + qCWarning(SEMANTIC_LOG) << "Failed to open temporary file:" << f.errorString(); + return; + } + + const auto m = memento(part); + const auto extractedData = m->data(); + QVector data; + data.reserve(extractedData.size()); + for (const auto &d : m->data()) { + data += d.reservations; + } + f.write(QJsonDocument(JsonLdDocument::toJson(data)).toJson()); + f.close(); + part->nodeHelper()->addTempFile(f.fileName()); + f.setAutoRemove(false); + + QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), QStringLiteral("/modules/kdeconnect/devices/") + deviceId + QStringLiteral("/share"), QStringLiteral("org.kde.kdeconnect.device.share"), QStringLiteral("openFile")); + msg.setArguments({QUrl::fromLocalFile(f.fileName()).toString()}); + + QDBusConnection::sessionBus().send(msg); + + // add pkpass attachments + for (const auto &elem : data) { + if (!JsonLd::canConvert(elem)) { + continue; + } + const auto res = JsonLd::convert(elem); + const auto b = m->rawPassData(res.pkpassPassTypeIdentifier(), res.pkpassSerialNumber()); + if (b.isEmpty()) { + continue; + } + + QTemporaryFile f(QStringLiteral("itinerary.XXXXXX.pkpass")); + if (!f.open()) { + qCWarning(SEMANTIC_LOG) << "Failed to open temporary file:" << f.errorString(); + return; + } + f.write(b); + f.close(); + part->nodeHelper()->addTempFile(f.fileName()); + f.setAutoRemove(false); + msg.setArguments({QUrl::fromLocalFile(f.fileName()).toString()}); + + QDBusConnection::sessionBus().send(msg); + } +}