diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d5d0229..a8fd43e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,71 +1,77 @@ cmake_minimum_required(VERSION 3.0) project(kdeconnect) set(KDECONNECT_VERSION_MAJOR 1) set(KDECONNECT_VERSION_MINOR 2) set(KDECONNECT_VERSION_PATCH 1) set(KDECONNECT_VERSION "${KDECONNECT_VERSION_MAJOR}.${KDECONNECT_VERSION_MINOR}.${KDECONNECT_VERSION_PATCH}") set(QT_MIN_VERSION "5.7.0") set(KF5_MIN_VERSION "5.42.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Quick) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils) find_package(KF5 ${KF5_MIN_VERSION} COMPONENTS DocTools) find_package(Qca-qt5 2.1.0 REQUIRED) include_directories(${CMAKE_SOURCE_DIR}) configure_file(kdeconnect-version.h.in ${CMAKE_CURRENT_BINARY_DIR}/kdeconnect-version.h) include(KDEInstallDirs) include(KDECompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(ECMAddTests) include(ECMSetupVersion) include(ECMInstallIcons) include(FeatureSummary) include(KDEConnectMacros.cmake) add_definitions(-DQT_NO_URL_CAST_FROM_STRING -DQT_NO_KEYWORDS) include(GenerateExportHeader) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(core) add_subdirectory(kcm) add_subdirectory(kcmplugin) if(NOT WIN32) add_subdirectory(kio) add_subdirectory(plasmoid) endif() add_subdirectory(icon) add_subdirectory(interfaces) option(EXPERIMENTALAPP_ENABLED OFF) if(EXPERIMENTALAPP_ENABLED) add_subdirectory(app) endif() add_subdirectory(daemon) add_subdirectory(plugins) add_subdirectory(cli) add_subdirectory(indicator) add_subdirectory(fileitemactionplugin) add_subdirectory(urlhandler) add_subdirectory(nautilus-extension) + +option(SMSAPP_ENABLED OFF) +if(SMSAPP_ENABLED) + find_package(KF5People REQUIRED) + add_subdirectory(smsapp) +endif() if(KF5DocTools_FOUND) add_subdirectory(doc) endif() if(BUILD_TESTING) add_subdirectory(tests) endif() install(FILES org.kde.kdeconnect.kcm.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/interfaces/CMakeLists.txt b/interfaces/CMakeLists.txt index 806ff36e..db8a12e0 100644 --- a/interfaces/CMakeLists.txt +++ b/interfaces/CMakeLists.txt @@ -1,81 +1,82 @@ project(KDEConnectInterfaces) function(geninterface source_h output_h) set(xml_file ${CMAKE_CURRENT_BINARY_DIR}/${output_h}.xml) qt5_generate_dbus_interface( ${source_h} ${xml_file}) list(APPEND libkdeconnect_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${output_h}) set_source_files_properties(${xml_file} PROPERTIES NO_NAMESPACE true) qt5_add_dbus_interface(libkdeconnect_SRC ${xml_file} ${output_h}) set(libkdeconnect_SRC ${libkdeconnect_SRC} PARENT_SCOPE) set(libkdeconnect_HEADERS ${libkdeconnect_HEADERS} PARENT_SCOPE) endfunction() set(libkdeconnect_SRC dbusinterfaces.cpp devicesmodel.cpp notificationsmodel.cpp devicessortproxymodel.cpp # modeltest.cpp ) set(libkdeconnect_public_HEADERS KDEConnect/DevicesModel KDEConnect/NotificationsModel ) set(libkdeconnect_HEADERS devicesmodel.h notificationsmodel.h dbusinterfaces.h ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectinterfaces_export.h ) geninterface(${CMAKE_SOURCE_DIR}/core/daemon.h daemoninterface) geninterface(${CMAKE_SOURCE_DIR}/core/device.h deviceinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/battery/batterydbusinterface.h devicebatteryinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/sftp/sftpplugin.h devicesftpinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/notifications/notificationsdbusinterface.h devicenotificationsinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/findmyphone/findmyphoneplugin.h devicefindmyphoneinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/notifications/notification.h notificationinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/mprisremote/mprisremoteplugin.h mprisremoteinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/remotecontrol/remotecontrolplugin.h remotecontrolinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/lockdevice/lockdeviceplugin.h lockdeviceinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/remotecommands/remotecommandsplugin.h remotecommandsinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/remotekeyboard/remotekeyboardplugin.h remotekeyboardinterface) +geninterface(${CMAKE_SOURCE_DIR}/plugins/telephony/telephonyplugin.h telephonyinterface) add_library(kdeconnectinterfaces SHARED ${libkdeconnect_SRC}) set_target_properties(kdeconnectinterfaces PROPERTIES VERSION ${KDECONNECT_VERSION} SOVERSION ${KDECONNECT_VERSION_MAJOR} ) generate_export_header(kdeconnectinterfaces EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectinterfaces_export.h BASE_NAME KDEConnectInterfaces) target_link_libraries(kdeconnectinterfaces LINK_PUBLIC Qt5::Gui Qt5::DBus LINK_PRIVATE KF5::ConfigCore KF5::I18n ) configure_file(KDEConnectConfig.cmake.in ${CMAKE_BINARY_DIR}/interfaces/KDEConnectConfig.cmake @ONLY) ecm_setup_version( "${KDECONNECT_VERSION_MAJOR}.${KDECONNECT_VERSION_MINOR}.${KDECONNECT_VERSION_PATCH}" VARIABLE_PREFIX KDECONNECTINTERFACES VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdeconnectinterfaces_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDEConnectConfigVersion.cmake" SOVERSION ${KDECONNECT_VERSION_MAJOR}) install(TARGETS kdeconnectinterfaces EXPORT kdeconnectLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) ## Don't install header files until API/ABI policy is defined # # install(FILES ${libkdeconnect_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/kdeconnect COMPONENT Devel) # install(FILES ${libkdeconnect_public_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/KDEConnect COMPONENT Devel) # install(FILES ${CMAKE_BINARY_DIR}/interfaces/KDEConnectConfig.cmake # ${CMAKE_BINARY_DIR}/interfaces/KDEConnectConfigVersion.cmake # DESTINATION ${LIB_INSTALL_DIR}/cmake/KDEConnect) diff --git a/interfaces/dbusinterfaces.cpp b/interfaces/dbusinterfaces.cpp index fbe93cac..53b17537 100644 --- a/interfaces/dbusinterfaces.cpp +++ b/interfaces/dbusinterfaces.cpp @@ -1,166 +1,173 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dbusinterfaces.h" QString DaemonDbusInterface::activatedService() { static const QString service = QStringLiteral("org.kde.kdeconnect"); auto reply = QDBusConnection::sessionBus().interface()->startService(service); if (!reply.isValid()) { qWarning() << "error activating kdeconnectd:" << QDBusConnection::sessionBus().interface()->lastError(); } return service; } DaemonDbusInterface::DaemonDbusInterface(QObject* parent) : OrgKdeKdeconnectDaemonInterface(DaemonDbusInterface::activatedService(), QStringLiteral("/modules/kdeconnect"), QDBusConnection::sessionBus(), parent) { connect(this, &OrgKdeKdeconnectDaemonInterface::pairingRequestsChanged, this, &DaemonDbusInterface::pairingRequestsChangedProxy); } DaemonDbusInterface::~DaemonDbusInterface() { } DeviceDbusInterface::DeviceDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/"+id, QDBusConnection::sessionBus(), parent) , m_id(id) { connect(this, &OrgKdeKdeconnectDeviceInterface::trustedChanged, this, &DeviceDbusInterface::trustedChangedProxy); connect(this, &OrgKdeKdeconnectDeviceInterface::reachableChanged, this, &DeviceDbusInterface::reachableChangedProxy); connect(this, &OrgKdeKdeconnectDeviceInterface::nameChanged, this, &DeviceDbusInterface::nameChangedProxy); connect(this, &OrgKdeKdeconnectDeviceInterface::hasPairingRequestsChanged, this, &DeviceDbusInterface::hasPairingRequestsChangedProxy); } DeviceDbusInterface::~DeviceDbusInterface() { } QString DeviceDbusInterface::id() const { return m_id; } void DeviceDbusInterface::pluginCall(const QString& plugin, const QString& method) { QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+id()+'/'+plugin, "org.kde.kdeconnect.device."+plugin, method); QDBusConnection::sessionBus().asyncCall(msg); } DeviceBatteryDbusInterface::DeviceBatteryDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceBatteryInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/"+id, QDBusConnection::sessionBus(), parent) { } DeviceBatteryDbusInterface::~DeviceBatteryDbusInterface() { } DeviceNotificationsDbusInterface::DeviceNotificationsDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceNotificationsInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/"+id, QDBusConnection::sessionBus(), parent) { } DeviceNotificationsDbusInterface::~DeviceNotificationsDbusInterface() { } NotificationDbusInterface::NotificationDbusInterface(const QString& deviceId, const QString& notificationId, QObject* parent) : OrgKdeKdeconnectDeviceNotificationsNotificationInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/"+deviceId+"/notifications/"+notificationId, QDBusConnection::sessionBus(), parent) , id(notificationId) { } NotificationDbusInterface::~NotificationDbusInterface() { } SftpDbusInterface::SftpDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceSftpInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + id + "/sftp", QDBusConnection::sessionBus(), parent) { } SftpDbusInterface::~SftpDbusInterface() { } MprisDbusInterface::MprisDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceMprisremoteInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + id + "/mprisremote", QDBusConnection::sessionBus(), parent) { connect(this, &OrgKdeKdeconnectDeviceMprisremoteInterface::propertiesChanged, this, &MprisDbusInterface::propertiesChangedProxy); } MprisDbusInterface::~MprisDbusInterface() { } RemoteControlDbusInterface::RemoteControlDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceRemotecontrolInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + id + "/remotecontrol", QDBusConnection::sessionBus(), parent) { } RemoteControlDbusInterface::~RemoteControlDbusInterface() { } LockDeviceDbusInterface::LockDeviceDbusInterface(const QString& id, QObject* parent) : OrgKdeKdeconnectDeviceLockdeviceInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + id + "/lockdevice", QDBusConnection::sessionBus(), parent) { connect(this, &OrgKdeKdeconnectDeviceLockdeviceInterface::lockedChanged, this, &LockDeviceDbusInterface::lockedChangedProxy); Q_ASSERT(isValid()); } LockDeviceDbusInterface::~LockDeviceDbusInterface() { } FindMyPhoneDeviceDbusInterface::FindMyPhoneDeviceDbusInterface(const QString& deviceId, QObject* parent): OrgKdeKdeconnectDeviceFindmyphoneInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + deviceId + "/findmyphone", QDBusConnection::sessionBus(), parent) { } FindMyPhoneDeviceDbusInterface::~FindMyPhoneDeviceDbusInterface() { } RemoteCommandsDbusInterface::RemoteCommandsDbusInterface(const QString& deviceId, QObject* parent): OrgKdeKdeconnectDeviceRemotecommandsInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + deviceId + "/remotecommands", QDBusConnection::sessionBus(), parent) { } RemoteCommandsDbusInterface::~RemoteCommandsDbusInterface() = default; RemoteKeyboardDbusInterface::RemoteKeyboardDbusInterface(const QString& deviceId, QObject* parent): OrgKdeKdeconnectDeviceRemotekeyboardInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + deviceId + "/remotekeyboard", QDBusConnection::sessionBus(), parent) { connect(this, &OrgKdeKdeconnectDeviceRemotekeyboardInterface::remoteStateChanged, this, &RemoteKeyboardDbusInterface::remoteStateChanged); } RemoteKeyboardDbusInterface::~RemoteKeyboardDbusInterface() = default; + +TelephonyDbusInterface::TelephonyDbusInterface(const QString& deviceId, QObject* parent): + OrgKdeKdeconnectDeviceTelephonyInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + deviceId + "/telephony", QDBusConnection::sessionBus(), parent) +{ +} + +TelephonyDbusInterface::~TelephonyDbusInterface() = default; diff --git a/interfaces/dbusinterfaces.h b/interfaces/dbusinterfaces.h index 4b2029d0..fbf2395f 100644 --- a/interfaces/dbusinterfaces.h +++ b/interfaces/dbusinterfaces.h @@ -1,211 +1,221 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DBUSINTERFACES_H #define DBUSINTERFACES_H #include "interfaces/kdeconnectinterfaces_export.h" #include "interfaces/daemoninterface.h" #include "interfaces/deviceinterface.h" #include "interfaces/devicebatteryinterface.h" #include "interfaces/devicesftpinterface.h" #include "interfaces/devicefindmyphoneinterface.h" #include "interfaces/devicenotificationsinterface.h" #include "interfaces/notificationinterface.h" #include "interfaces/mprisremoteinterface.h" #include "interfaces/remotecontrolinterface.h" #include "interfaces/lockdeviceinterface.h" #include "interfaces/remotecommandsinterface.h" #include "interfaces/remotekeyboardinterface.h" +#include "interfaces/telephonyinterface.h" /** * Using these "proxy" classes just in case we need to rename the * interface, so we can change the class name in a single place. */ class KDECONNECTINTERFACES_EXPORT DaemonDbusInterface : public OrgKdeKdeconnectDaemonInterface { Q_OBJECT public: explicit DaemonDbusInterface(QObject* parent = nullptr); ~DaemonDbusInterface() override; static QString activatedService(); Q_SIGNALS: void deviceAdded(const QString& id); void pairingRequestsChangedProxy(); }; class KDECONNECTINTERFACES_EXPORT DeviceDbusInterface : public OrgKdeKdeconnectDeviceInterface { Q_OBJECT // TODO: Workaround because OrgKdeKdeconnectDeviceInterface is not generating // the signals for the properties Q_PROPERTY(bool isReachable READ isReachable NOTIFY reachableChangedProxy) Q_PROPERTY(bool isTrusted READ isTrusted NOTIFY trustedChangedProxy) Q_PROPERTY(QString name READ name NOTIFY nameChangedProxy) Q_PROPERTY(bool hasPairingRequests READ hasPairingRequests NOTIFY hasPairingRequestsChangedProxy) public: explicit DeviceDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~DeviceDbusInterface() override; Q_SCRIPTABLE QString id() const; Q_SCRIPTABLE void pluginCall(const QString& plugin, const QString& method); Q_SIGNALS: void nameChangedProxy(const QString& name); void trustedChangedProxy(bool paired); void reachableChangedProxy(bool reachable); void hasPairingRequestsChangedProxy(bool); private: const QString m_id; }; class KDECONNECTINTERFACES_EXPORT DeviceBatteryDbusInterface : public OrgKdeKdeconnectDeviceBatteryInterface { Q_OBJECT public: explicit DeviceBatteryDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~DeviceBatteryDbusInterface() override; }; class KDECONNECTINTERFACES_EXPORT DeviceNotificationsDbusInterface : public OrgKdeKdeconnectDeviceNotificationsInterface { Q_OBJECT public: explicit DeviceNotificationsDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~DeviceNotificationsDbusInterface() override; }; class KDECONNECTINTERFACES_EXPORT NotificationDbusInterface : public OrgKdeKdeconnectDeviceNotificationsNotificationInterface { Q_OBJECT public: NotificationDbusInterface(const QString& deviceId, const QString& notificationId, QObject* parent = nullptr); ~NotificationDbusInterface() override; QString notificationId() { return id; } private: const QString id; }; class KDECONNECTINTERFACES_EXPORT SftpDbusInterface : public OrgKdeKdeconnectDeviceSftpInterface { Q_OBJECT public: explicit SftpDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~SftpDbusInterface() override; }; class KDECONNECTINTERFACES_EXPORT MprisDbusInterface : public OrgKdeKdeconnectDeviceMprisremoteInterface { Q_OBJECT // TODO: Workaround because qdbusxml2cpp is not generating // the signals for the properties Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY propertiesChangedProxy) Q_PROPERTY(int length READ length NOTIFY propertiesChangedProxy) Q_PROPERTY(QString nowPlaying READ nowPlaying NOTIFY propertiesChangedProxy) Q_PROPERTY(QStringList playerList READ playerList NOTIFY propertiesChangedProxy) Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY propertiesChangedProxy) Q_PROPERTY(int position READ position WRITE setPosition NOTIFY propertiesChangedProxy) public: explicit MprisDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~MprisDbusInterface() override; Q_SIGNALS: void propertiesChangedProxy(); }; class KDECONNECTINTERFACES_EXPORT RemoteControlDbusInterface : public OrgKdeKdeconnectDeviceRemotecontrolInterface { Q_OBJECT public: explicit RemoteControlDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~RemoteControlDbusInterface() override; }; class KDECONNECTINTERFACES_EXPORT LockDeviceDbusInterface : public OrgKdeKdeconnectDeviceLockdeviceInterface { Q_OBJECT Q_PROPERTY(bool isLocked READ isLocked WRITE setIsLocked NOTIFY lockedChangedProxy) public: explicit LockDeviceDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~LockDeviceDbusInterface() override; Q_SIGNALS: void lockedChangedProxy(bool isLocked); }; class KDECONNECTINTERFACES_EXPORT FindMyPhoneDeviceDbusInterface : public OrgKdeKdeconnectDeviceFindmyphoneInterface { Q_OBJECT public: explicit FindMyPhoneDeviceDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~FindMyPhoneDeviceDbusInterface() override; }; class KDECONNECTINTERFACES_EXPORT RemoteCommandsDbusInterface : public OrgKdeKdeconnectDeviceRemotecommandsInterface { Q_OBJECT public: explicit RemoteCommandsDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~RemoteCommandsDbusInterface() override; }; class KDECONNECTINTERFACES_EXPORT RemoteKeyboardDbusInterface : public OrgKdeKdeconnectDeviceRemotekeyboardInterface { Q_OBJECT Q_PROPERTY(bool remoteState READ remoteState NOTIFY remoteStateChanged) public: explicit RemoteKeyboardDbusInterface(const QString& deviceId, QObject* parent = nullptr); ~RemoteKeyboardDbusInterface() override; Q_SIGNALS: void remoteStateChanged(bool state); }; +class KDECONNECTINTERFACES_EXPORT TelephonyDbusInterface + : public OrgKdeKdeconnectDeviceTelephonyInterface +{ + Q_OBJECT +public: + explicit TelephonyDbusInterface(const QString& deviceId, QObject* parent = nullptr); + ~TelephonyDbusInterface() override; +}; + template static void setWhenAvailable(const QDBusPendingReply& pending, W func, QObject* parent) { QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(pending, parent); QObject::connect(watcher, &QDBusPendingCallWatcher::finished, parent, [func](QDBusPendingCallWatcher* watcher) { watcher->deleteLater(); QDBusPendingReply reply = *watcher; func(reply.value()); }); } #endif diff --git a/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp b/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp index f53b050b..dd9f2fc3 100644 --- a/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp +++ b/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp @@ -1,133 +1,141 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "kdeconnectdeclarativeplugin.h" #include #include #include #include #include #include "objectfactory.h" #include "responsewaiter.h" #include "interfaces/devicessortproxymodel.h" #include "interfaces/devicesmodel.h" #include "interfaces/notificationsmodel.h" QObject* createDeviceDbusInterface(const QVariant& deviceId) { return new DeviceDbusInterface(deviceId.toString()); } QObject* createDeviceBatteryDbusInterface(const QVariant& deviceId) { return new DeviceBatteryDbusInterface(deviceId.toString()); } QObject* createFindMyPhoneInterface(const QVariant& deviceId) { return new FindMyPhoneDeviceDbusInterface(deviceId.toString()); } QObject* createRemoteKeyboardInterface(const QVariant& deviceId) { return new RemoteKeyboardDbusInterface(deviceId.toString()); } QObject* createSftpInterface(const QVariant& deviceId) { return new SftpDbusInterface(deviceId.toString()); } QObject* createRemoteControlInterface(const QVariant& deviceId) { return new RemoteControlDbusInterface(deviceId.toString()); } QObject* createMprisInterface(const QVariant& deviceId) { return new MprisDbusInterface(deviceId.toString()); } QObject* createDeviceLockInterface(const QVariant& deviceId) { Q_ASSERT(!deviceId.toString().isEmpty()); return new LockDeviceDbusInterface(deviceId.toString()); } +QObject* createTelephonyInterface(const QVariant& deviceId) +{ + return new TelephonyDbusInterface(deviceId.toString()); +} + QObject* createDBusResponse() { return new DBusAsyncResponse(); } void KdeConnectDeclarativePlugin::registerTypes(const char* uri) { qmlRegisterType(uri, 1, 0, "DevicesModel"); qmlRegisterType(uri, 1, 0, "NotificationsModel"); qmlRegisterType(uri, 1, 0, "DBusAsyncResponse"); qmlRegisterType(uri, 1, 0, "DevicesSortProxyModel"); qmlRegisterUncreatableType(uri, 1, 0, "MprisDbusInterface", QStringLiteral("You're not supposed to instantiate interfacess")); qmlRegisterUncreatableType(uri, 1, 0, "LockDeviceDbusInterface", QStringLiteral("You're not supposed to instantiate interfacess")); qmlRegisterUncreatableType(uri, 1, 0, "FindMyPhoneDbusInterface", QStringLiteral("You're not supposed to instantiate interfacess")); qmlRegisterUncreatableType(uri, 1, 0, "RemoteKeyboardDbusInterface", QStringLiteral("You're not supposed to instantiate interfacess")); qmlRegisterUncreatableType(uri, 1, 0, "DeviceDbusInterface", QStringLiteral("You're not supposed to instantiate interfacess")); qmlRegisterSingletonType(uri, 1, 0, "DaemonDbusInterface", [](QQmlEngine*, QJSEngine*) -> QObject* { return new DaemonDbusInterface; } ); } void KdeConnectDeclarativePlugin::initializeEngine(QQmlEngine* engine, const char* uri) { QQmlExtensionPlugin::initializeEngine(engine, uri); engine->rootContext()->setContextProperty(QStringLiteral("DeviceDbusInterfaceFactory") , new ObjectFactory(engine, createDeviceDbusInterface)); engine->rootContext()->setContextProperty(QStringLiteral("DeviceBatteryDbusInterfaceFactory") , new ObjectFactory(engine, createDeviceBatteryDbusInterface)); engine->rootContext()->setContextProperty(QStringLiteral("FindMyPhoneDbusInterfaceFactory") , new ObjectFactory(engine, createFindMyPhoneInterface)); engine->rootContext()->setContextProperty(QStringLiteral("SftpDbusInterfaceFactory") , new ObjectFactory(engine, createSftpInterface)); engine->rootContext()->setContextProperty(QStringLiteral("RemoteKeyboardDbusInterfaceFactory") , new ObjectFactory(engine, createRemoteKeyboardInterface)); engine->rootContext()->setContextProperty(QStringLiteral("MprisDbusInterfaceFactory") , new ObjectFactory(engine, createMprisInterface)); engine->rootContext()->setContextProperty(QStringLiteral("RemoteControlDbusInterfaceFactory") , new ObjectFactory(engine, createRemoteControlInterface)); engine->rootContext()->setContextProperty(QStringLiteral("LockDeviceDbusInterfaceFactory") , new ObjectFactory(engine, createDeviceLockInterface)); + + engine->rootContext()->setContextProperty(QStringLiteral("TelephonyDbusInterfaceFactory") + , new ObjectFactory(engine, createTelephonyInterface)); engine->rootContext()->setContextProperty(QStringLiteral("DBusResponseFactory") , new ObjectFactory(engine, createDBusResponse)); engine->rootContext()->setContextProperty(QStringLiteral("DBusResponseWaiter") , DBusResponseWaiter::instance()); } diff --git a/plugins/telephony/telephonyplugin.cpp b/plugins/telephony/telephonyplugin.cpp index 91ea2a8c..5c50efa2 100644 --- a/plugins/telephony/telephonyplugin.cpp +++ b/plugins/telephony/telephonyplugin.cpp @@ -1,170 +1,171 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "telephonyplugin.h" #include "sendreplydialog.h" #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_telephony.json", registerPlugin< TelephonyPlugin >(); ) Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY, "kdeconnect.plugin.telephony") TelephonyPlugin::TelephonyPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_telepathyInterface(QStringLiteral("org.freedesktop.Telepathy.ConnectionManager.kdeconnect"), QStringLiteral("/kdeconnect")) { } KNotification* TelephonyPlugin::createNotification(const NetworkPacket& np) { const QString event = np.get(QStringLiteral("event")); const QString phoneNumber = np.get(QStringLiteral("phoneNumber"), i18n("unknown number")); const QString contactName = np.get(QStringLiteral("contactName"), phoneNumber); const QByteArray phoneThumbnail = QByteArray::fromBase64(np.get(QStringLiteral("phoneThumbnail"), "")); // In case telepathy can handle the message, don't do anything else if (event == QLatin1String("sms") && m_telepathyInterface.isValid()) { qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Passing a text message to the telepathy interface"; connect(&m_telepathyInterface, SIGNAL(messageReceived(QString,QString)), SLOT(sendSms(QString,QString)), Qt::UniqueConnection); const QString messageBody = np.get(QStringLiteral("messageBody"),QLatin1String("")); QDBusReply reply = m_telepathyInterface.call(QStringLiteral("sendMessage"), phoneNumber, contactName, messageBody); if (reply) { return nullptr; } else { qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Telepathy failed, falling back to the default handling"; } } QString content, type, icon; KNotification::NotificationFlags flags = KNotification::CloseOnTimeout; const QString title = device()->name(); if (event == QLatin1String("ringing")) { type = QStringLiteral("callReceived"); icon = QStringLiteral("call-start"); content = i18n("Incoming call from %1", contactName); } else if (event == QLatin1String("missedCall")) { type = QStringLiteral("missedCall"); icon = QStringLiteral("call-start"); content = i18n("Missed call from %1", contactName); flags |= KNotification::Persistent; //Note that in Unity this generates a message box! } else if (event == QLatin1String("sms")) { type = QStringLiteral("smsReceived"); icon = QStringLiteral("mail-receive"); QString messageBody = np.get(QStringLiteral("messageBody"), QLatin1String("")); content = i18n("SMS from %1
%2", contactName, messageBody); flags |= KNotification::Persistent; //Note that in Unity this generates a message box! } else if (event == QLatin1String("talking")) { return nullptr; } else { #ifndef NDEBUG return nullptr; #else type = QStringLiteral("callReceived"); icon = QStringLiteral("phone"); content = i18n("Unknown telephony event: %1", event); #endif } qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Creating notification with type:" << type; KNotification* notification = new KNotification(type, flags, this); if (!phoneThumbnail.isEmpty()) { QPixmap photo; photo.loadFromData(phoneThumbnail, "JPEG"); notification->setPixmap(photo); } else { notification->setIconName(icon); } notification->setComponentName(QStringLiteral("kdeconnect")); notification->setTitle(title); notification->setText(content); if (event == QLatin1String("ringing")) { notification->setActions( QStringList(i18n("Mute Call")) ); connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::sendMutePacket); } else if (event == QLatin1String("sms")) { const QString messageBody = np.get(QStringLiteral("messageBody"),QLatin1String("")); notification->setActions( QStringList(i18n("Reply")) ); notification->setProperty("phoneNumber", phoneNumber); notification->setProperty("contactName", contactName); notification->setProperty("originalMessage", messageBody); connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::showSendSmsDialog); } return notification; } bool TelephonyPlugin::receivePacket(const NetworkPacket& np) { if (np.get(QStringLiteral("isCancel"))) { //TODO: Clear the old notification return true; } KNotification* n = createNotification(np); if (n != nullptr) n->sendEvent(); return true; } void TelephonyPlugin::sendMutePacket() { NetworkPacket packet(PACKET_TYPE_TELEPHONY_REQUEST, {{"action", "mute"}}); sendPacket(packet); } void TelephonyPlugin::sendSms(const QString& phoneNumber, const QString& messageBody) { NetworkPacket np(PACKET_TYPE_SMS_REQUEST, { {"sendSms", true}, {"phoneNumber", phoneNumber}, {"messageBody", messageBody} }); + qDebug() << "sending sms!"; sendPacket(np); } void TelephonyPlugin::showSendSmsDialog() { QString phoneNumber = sender()->property("phoneNumber").toString(); QString contactName = sender()->property("contactName").toString(); QString originalMessage = sender()->property("originalMessage").toString(); SendReplyDialog* dialog = new SendReplyDialog(originalMessage, phoneNumber, contactName); connect(dialog, &SendReplyDialog::sendReply, this, &TelephonyPlugin::sendSms); dialog->show(); dialog->raise(); } QString TelephonyPlugin::dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/telephony"; } #include "telephonyplugin.moc" diff --git a/smsapp/CMakeLists.txt b/smsapp/CMakeLists.txt new file mode 100644 index 00000000..8aadde5d --- /dev/null +++ b/smsapp/CMakeLists.txt @@ -0,0 +1,7 @@ +qt5_add_resources(KCSMS_SRCS resources.qrc) + +add_executable(kdeconnect-sms main.cpp ${KCSMS_SRCS}) +target_link_libraries(kdeconnect-sms Qt5::Quick Qt5::Widgets KF5::DBusAddons KF5::CoreAddons KF5::I18n) + +install(TARGETS kdeconnect-sms ${INSTALL_TARGETS_DEFAULT_ARGS}) +install(PROGRAMS org.kde.kdeconnect.sms.desktop DESTINATION ${KDE_INSTALL_APPDIR}) diff --git a/smsapp/main.cpp b/smsapp/main.cpp new file mode 100644 index 00000000..58c6dc64 --- /dev/null +++ b/smsapp/main.cpp @@ -0,0 +1,54 @@ +/* + * This file is part of KDE Telepathy Chat + * + * Copyright (C) 2015 Aleix Pol Gonzalez + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "kdeconnect-version.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + KAboutData aboutData("org.kde.kdeconnect.sms", i18n("SMS Instant Messaging"), QStringLiteral(KDECONNECT_VERSION_STRING), i18n("KDE Connect SMS"), KAboutLicense::GPL, i18n("(c) 2018, Aleix Pol Gonzalez")); + aboutData.addAuthor(i18n("Aleix Pol Gonzalez"), {}, "aleixpol@kde.org"); + KAboutData::setApplicationData(aboutData); + + { + QCommandLineParser parser; + aboutData.setupCommandLine(&parser); + parser.addVersionOption(); + parser.addHelpOption(); + parser.process(app); + aboutData.processCommandLine(&parser); + } + + KDBusService service(KDBusService::Unique); + + QQmlApplicationEngine engine; + engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); + engine.load(QUrl("qrc:/qml/main.qml")); + + return app.exec(); +} diff --git a/smsapp/org.kde.kdeconnect.sms.desktop b/smsapp/org.kde.kdeconnect.sms.desktop new file mode 100644 index 00000000..addeaf37 --- /dev/null +++ b/smsapp/org.kde.kdeconnect.sms.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Name=KDE Connect SMS +GenericName=SMS +Comment=Text Messaging +Exec=kdeconnect-sms +Icon=kdeconnect +Type=Application +Terminal=false +Categories=Qt;KDE;Network;InstantMessaging + +X-DBUS-StartupType=Unique +X-DBUS-ServiceName=org.kde.kdeconnect.sms diff --git a/smsapp/qml/ContactList.qml b/smsapp/qml/ContactList.qml new file mode 100644 index 00000000..babf418a --- /dev/null +++ b/smsapp/qml/ContactList.qml @@ -0,0 +1,96 @@ +/* + * This file is part of KDE Telepathy Chat + * + * Copyright (C) 2015 Aleix Pol Gonzalez + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import QtQuick 2.5 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.1 +import org.kde.people 1.0 +import org.kde.plasma.core 2.0 as Core +import org.kde.kirigami 2.3 as Kirigami +import org.kde.kdeconnect 1.0 + +Kirigami.ScrollablePage +{ + Component { + id: chatView + ConversationDisplay {} + } + + ListView { + id: view + spacing: 3 + currentIndex: 0 + + model: PersonsSortFilterProxyModel { + requiredProperties: ["phoneNumber"] + sortRole: Qt.DisplayRole + sortCaseSensitivity: Qt.CaseInsensitive + sourceModel: PersonsModel { + id: people + } + } + + header: TextField { + id: filter + placeholderText: i18n("Filter...") + Layout.fillWidth: true + onTextChanged: { + view.model.filterRegExp = new RegExp(filter.text) + view.currentIndex = 0 + } + Keys.onUpPressed: view.currentIndex = Math.max(view.currentIndex-1, 0) + Keys.onDownPressed: view.currentIndex = Math.min(view.currentIndex+1, view.count-1) + onAccepted: { + view.currentItem.startChat() + } + Shortcut { + sequence: "Ctrl+F" + onActivated: filter.forceActiveFocus() + } + } + + delegate: Kirigami.BasicListItem + { + id: mouse + hoverEnabled: true + + readonly property var person: PersonData { + personUri: model.personUri + } + + label: display + icon: decoration + function startChat() { + applicationWindow().pageStack.push(chatView, { person: person.person, device: Qt.binding(function() {return devicesCombo.device })}) + } + onClicked: { startChat(); } + } + + } + footer: ComboBox { + id: devicesCombo + readonly property QtObject device: model.data(model.index(currentIndex, 0), DevicesModel.DeviceRole) + model: DevicesSortProxyModel { + //TODO: make it possible to sort only if they can do sms + sourceModel: DevicesModel { displayFilter: DevicesModel.Paired | DevicesModel.Reachable } + } + textRole: "display" + } +} diff --git a/smsapp/qml/ConversationDisplay.qml b/smsapp/qml/ConversationDisplay.qml new file mode 100644 index 00000000..edd7bb09 --- /dev/null +++ b/smsapp/qml/ConversationDisplay.qml @@ -0,0 +1,65 @@ +/* + * This file is part of KDE Telepathy Chat + * + * Copyright (C) 2015 Aleix Pol Gonzalez + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import QtQuick 2.1 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.1 +import org.kde.kirigami 2.4 as Kirigami + +Kirigami.ScrollablePage +{ + id: page + title: i18n("%1: %2", person.name, person.phone) + property QtObject person + property QtObject device + + readonly property QtObject telephony: TelephonyDbusInterfaceFactory.create(device.id()) + + Kirigami.CardsListView { + model: ListModel { + ListElement { display: "aaa"; fromMe: true } + ListElement { display: "aaa" } + ListElement { display: "aaa"; fromMe: true } + ListElement { display: "aaa" } + ListElement { display: "aaa" } + ListElement { display: "aaa" } + } + delegate: Kirigami.AbstractCard { + readonly property real margin: 100 + x: fromMe ? Kirigami.Units.gridUnit : margin + width: parent.width - margin - Kirigami.Units.gridUnit + contentItem: Label { text: model.display } + } + } + footer: RowLayout { + TextField { + id: message + Layout.fillWidth: true + placeholderText: i18n("Say hi...") + } + Button { + text: "Send" + onClicked: { + console.log("sending sms", page.person.phone) + page.telephony.sendSms(page.person.phone, message.text) + } + } + } +} diff --git a/smsapp/qml/main.qml b/smsapp/qml/main.qml new file mode 100644 index 00000000..f7bdf446 --- /dev/null +++ b/smsapp/qml/main.qml @@ -0,0 +1,37 @@ +/* + * This file is part of KDE Telepathy Chat + * + * Copyright (C) 2014 Aleix Pol Gonzalez + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import QtQuick 2.1 +import QtQuick.Controls 2.3 +import org.kde.kirigami 2.3 as Kirigami + +Kirigami.ApplicationWindow +{ + id: root + visible: true + width: 800 + height: 600 + + header: Kirigami.ToolBarApplicationHeader {} + + pageStack.initialPage: ContactList { + title: i18n("KDE Connect SMS") + } +} diff --git a/smsapp/resources.qrc b/smsapp/resources.qrc new file mode 100644 index 00000000..a53e8c51 --- /dev/null +++ b/smsapp/resources.qrc @@ -0,0 +1,7 @@ + + + qml/main.qml + qml/ContactList.qml + qml/ConversationDisplay.qml + +