Telepathy integration
This sends recieved text messages to any Telepathy client and allows the user to respond from there. This should work with both our clients and Empathy. An account on telepathy is created on activation. As Telepathy clients expect backends to be always running, this is started by the daemon to suppress client errors. The plugin system then talks to the same CM via use of a singleton accessor. Based on work by Alexandr Akulich then tidied up and rebased.
This commit is contained in:
parent
501e5431ec
commit
e4cbf22519
18 changed files with 924 additions and 8 deletions
|
@ -13,6 +13,11 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DI
|
||||||
find_package(Qt5 5.2 REQUIRED COMPONENTS Quick)
|
find_package(Qt5 5.2 REQUIRED COMPONENTS Quick)
|
||||||
find_package(KF5 REQUIRED COMPONENTS I18n ConfigWidgets DBusAddons IconThemes)
|
find_package(KF5 REQUIRED COMPONENTS I18n ConfigWidgets DBusAddons IconThemes)
|
||||||
find_package(Qca-qt5 2.1.0 REQUIRED)
|
find_package(Qca-qt5 2.1.0 REQUIRED)
|
||||||
|
find_package(TelepathyQt5 0.9.5)
|
||||||
|
find_package(TelepathyQt5Service 0.9.5)
|
||||||
|
if (TelepathyQt5_FOUND)
|
||||||
|
add_definitions(-DHAVE_TELEPATHY)
|
||||||
|
endif()
|
||||||
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR})
|
include_directories(${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
|
@ -49,6 +54,11 @@ add_subdirectory(plugins)
|
||||||
add_subdirectory(plasmoid)
|
add_subdirectory(plasmoid)
|
||||||
add_subdirectory(cli)
|
add_subdirectory(cli)
|
||||||
add_subdirectory(fileitemactionplugin)
|
add_subdirectory(fileitemactionplugin)
|
||||||
|
|
||||||
|
if (TelepathyQt5_FOUND)
|
||||||
|
add_subdirectory(telepathy-cm)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -8,6 +8,9 @@ add_executable(kdeconnectd kdeconnectd.cpp)
|
||||||
target_link_libraries(kdeconnectd kdeconnectcore KF5::KIOWidgets KF5::DBusAddons KF5::Notifications KF5::I18n Qt5::Widgets)
|
target_link_libraries(kdeconnectd kdeconnectcore KF5::KIOWidgets KF5::DBusAddons KF5::Notifications KF5::I18n Qt5::Widgets)
|
||||||
|
|
||||||
ecm_mark_nongui_executable(kdeconnectd)
|
ecm_mark_nongui_executable(kdeconnectd)
|
||||||
|
if(TelepathyQt5_FOUND)
|
||||||
|
target_link_libraries(kdeconnectd connectcm)
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file(kdeconnectd.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectd.desktop)
|
configure_file(kdeconnectd.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectd.desktop)
|
||||||
configure_file(org.kde.kdeconnect.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.service)
|
configure_file(org.kde.kdeconnect.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.service)
|
||||||
|
@ -15,3 +18,4 @@ configure_file(org.kde.kdeconnect.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectd.desktop DESTINATION ${AUTOSTART_INSTALL_DIR})
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectd.desktop DESTINATION ${AUTOSTART_INSTALL_DIR})
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.service DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.service DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
|
||||||
install(TARGETS kdeconnectd DESTINATION ${LIBEXEC_INSTALL_DIR})
|
install(TARGETS kdeconnectd DESTINATION ${LIBEXEC_INSTALL_DIR})
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
#include "kdeconnect-version.h"
|
#include "kdeconnect-version.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_TELEPATHY
|
||||||
|
#include "kdeconnecttelepathyprotocolfactory.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -128,6 +132,11 @@ int main(int argc, char* argv[])
|
||||||
QObject::connect(daemon, SIGNAL(destroyed(QObject*)), &app, SLOT(quit()));
|
QObject::connect(daemon, SIGNAL(destroyed(QObject*)), &app, SLOT(quit()));
|
||||||
initializeTermHandlers(&app, daemon);
|
initializeTermHandlers(&app, daemon);
|
||||||
|
|
||||||
|
#ifdef HAVE_TELEPATHY
|
||||||
|
//keep a reference to the KTP CM so that we can register on DBus
|
||||||
|
auto telepathyPlugin = KDEConnectTelepathyProtocolFactory::interface();
|
||||||
|
#endif
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,9 @@ target_link_libraries(kdeconnect_telephony
|
||||||
KF5::I18n
|
KF5::I18n
|
||||||
KF5::Notifications
|
KF5::Notifications
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (TelepathyQt5_FOUND)
|
||||||
|
target_link_libraries(kdeconnect_telephony
|
||||||
|
connectcm
|
||||||
|
)
|
||||||
|
endif()
|
|
@ -35,7 +35,11 @@ Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY, "kdeconnect.plugin.telephony")
|
||||||
TelephonyPlugin::TelephonyPlugin(QObject *parent, const QVariantList &args)
|
TelephonyPlugin::TelephonyPlugin(QObject *parent, const QVariantList &args)
|
||||||
: KdeConnectPlugin(parent, args)
|
: KdeConnectPlugin(parent, args)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_TELEPATHY
|
||||||
|
//keep a reference to the KTP CM so that we can register on DBus
|
||||||
|
m_telepathyInterface = KDEConnectTelepathyProtocolFactory::interface();
|
||||||
|
connect(m_telepathyInterface.constData(), SIGNAL(messageReceived(QString,QString)), SLOT(sendSms(QString,QString)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
KNotification* TelephonyPlugin::createNotification(const NetworkPackage& np)
|
KNotification* TelephonyPlugin::createNotification(const NetworkPackage& np)
|
||||||
|
@ -88,10 +92,11 @@ KNotification* TelephonyPlugin::createNotification(const NetworkPackage& np)
|
||||||
notification->setActions( QStringList(i18n("Mute Call")) );
|
notification->setActions( QStringList(i18n("Mute Call")) );
|
||||||
connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::sendMutePackage);
|
connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::sendMutePackage);
|
||||||
} else if (event == QLatin1String("sms")) {
|
} else if (event == QLatin1String("sms")) {
|
||||||
|
const QString messageBody = np.get<QString>("messageBody","");
|
||||||
notification->setActions( QStringList(i18n("Reply")) );
|
notification->setActions( QStringList(i18n("Reply")) );
|
||||||
notification->setProperty("phoneNumber", phoneNumber);
|
notification->setProperty("phoneNumber", phoneNumber);
|
||||||
notification->setProperty("contactName", contactName);
|
notification->setProperty("contactName", contactName);
|
||||||
notification->setProperty("originalMessage", np.get<QString>("messageBody",""));
|
notification->setProperty("originalMessage", messageBody);
|
||||||
connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::showSendSmsDialog);
|
connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::showSendSmsDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,15 +109,23 @@ bool TelephonyPlugin::receivePackage(const NetworkPackage& np)
|
||||||
if (np.get<bool>("isCancel")) {
|
if (np.get<bool>("isCancel")) {
|
||||||
|
|
||||||
//TODO: Clear the old notification
|
//TODO: Clear the old notification
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_TELEPATHY
|
||||||
|
if (np.get<QString>("event") == QLatin1String("sms")) {
|
||||||
|
const QString messageBody = np.get<QString>("messageBody","");
|
||||||
|
const QString phoneNumber = np.get<QString>("phoneNumber", i18n("unknown number"));
|
||||||
|
const QString contactName = np.get<QString>("contactName", phoneNumber);
|
||||||
|
if (m_telepathyInterface->sendMessage(contactName, messageBody)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} else {
|
|
||||||
KNotification* n = createNotification(np);
|
KNotification* n = createNotification(np);
|
||||||
if (n != nullptr) n->sendEvent();
|
if (n != nullptr) n->sendEvent();
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelephonyPlugin::sendMutePackage()
|
void TelephonyPlugin::sendMutePackage()
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
|
|
||||||
#include <core/kdeconnectplugin.h>
|
#include <core/kdeconnectplugin.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_TELEPATHY
|
||||||
|
#include "kdeconnecttelepathyprotocolfactory.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PACKAGE_TYPE_TELEPHONY QLatin1String("kdeconnect.telephony")
|
#define PACKAGE_TYPE_TELEPHONY QLatin1String("kdeconnect.telephony")
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY)
|
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY)
|
||||||
|
@ -51,6 +55,11 @@ private Q_SLOTS:
|
||||||
private:
|
private:
|
||||||
KNotification* createNotification(const NetworkPackage& np);
|
KNotification* createNotification(const NetworkPackage& np);
|
||||||
|
|
||||||
|
#ifdef HAVE_TELEPATHY
|
||||||
|
ConnectProtocolPtr m_telepathyInterface;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
24
telepathy-cm/CMakeLists.txt
Normal file
24
telepathy-cm/CMakeLists.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
project(connectcm)
|
||||||
|
|
||||||
|
add_definitions(-DCONNECTCM_LIBRARY)
|
||||||
|
|
||||||
|
set(connectcm_SOURCES
|
||||||
|
connection.cpp
|
||||||
|
protocol.cpp
|
||||||
|
textchannel.cpp
|
||||||
|
kdeconnecttelepathyprotocolfactory.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(connectcm SHARED ${connectcm_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(connectcm
|
||||||
|
PUBLIC
|
||||||
|
Qt5::Core
|
||||||
|
${TELEPATHY_QT5_LIBRARIES}
|
||||||
|
${TELEPATHY_QT5_SERVICE_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
install (TARGETS connectcm
|
||||||
|
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||||
|
)
|
||||||
|
|
1
telepathy-cm/README
Normal file
1
telepathy-cm/README
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Connect TelepathyQt-based Connection Manager.
|
12
telepathy-cm/connectcm_export.h
Normal file
12
telepathy-cm/connectcm_export.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef CONNECTCM_EXPORT_H
|
||||||
|
#define CONNECTCM_EXPORT_H
|
||||||
|
|
||||||
|
#include <QtCore/QtGlobal>
|
||||||
|
|
||||||
|
#if defined(CONNECTCM_LIBRARY)
|
||||||
|
#define CONNECTCM_EXPORT Q_DECL_EXPORT
|
||||||
|
#else
|
||||||
|
#define CONNECTCM_EXPORT Q_DECL_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
362
telepathy-cm/connection.cpp
Normal file
362
telepathy-cm/connection.cpp
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 Alexandr Akulich <akulichalexander@gmail.com>
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
#include "textchannel.h"
|
||||||
|
|
||||||
|
#include <TelepathyQt/Constants>
|
||||||
|
#include <TelepathyQt/BaseChannel>
|
||||||
|
#include <TelepathyQt/Presence>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
Tp::SimpleStatusSpecMap ConnectConnection::getSimpleStatusSpecMap()
|
||||||
|
{
|
||||||
|
//Presence
|
||||||
|
Tp::SimpleStatusSpec spAvailable;
|
||||||
|
spAvailable.type = Tp::ConnectionPresenceTypeAvailable;
|
||||||
|
spAvailable.maySetOnSelf = false;
|
||||||
|
spAvailable.canHaveMessage = true;
|
||||||
|
|
||||||
|
Tp::SimpleStatusSpec spOffline;
|
||||||
|
spOffline.type = Tp::ConnectionPresenceTypeOffline;
|
||||||
|
spOffline.maySetOnSelf = false;
|
||||||
|
spOffline.canHaveMessage = false;
|
||||||
|
|
||||||
|
Tp::SimpleStatusSpecMap specs;
|
||||||
|
specs.insert(QLatin1String("available"), spAvailable);
|
||||||
|
specs.insert(QLatin1String("offline"), spOffline);
|
||||||
|
return specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectConnection::ConnectConnection(const QDBusConnection &dbusConnection, const QString &cmName, const QString &protocolName, const QVariantMap ¶meters) :
|
||||||
|
Tp::BaseConnection(dbusConnection, cmName, protocolName, parameters)
|
||||||
|
{
|
||||||
|
qDebug() << "making new connection";
|
||||||
|
|
||||||
|
/* Connection.Interface.Contacts */
|
||||||
|
contactsIface = Tp::BaseConnectionContactsInterface::create();
|
||||||
|
contactsIface->setGetContactAttributesCallback(Tp::memFun(this, &ConnectConnection::getContactAttributes));
|
||||||
|
contactsIface->setContactAttributeInterfaces(QStringList()
|
||||||
|
<< TP_QT_IFACE_CONNECTION
|
||||||
|
<< TP_QT_IFACE_CONNECTION_INTERFACE_CONTACT_LIST
|
||||||
|
<< TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE);
|
||||||
|
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(contactsIface));
|
||||||
|
|
||||||
|
/* Connection.Interface.SimplePresence */
|
||||||
|
simplePresenceIface = Tp::BaseConnectionSimplePresenceInterface::create();
|
||||||
|
simplePresenceIface->setSetPresenceCallback(Tp::memFun(this,&ConnectConnection::setPresence));
|
||||||
|
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(simplePresenceIface));
|
||||||
|
|
||||||
|
/* Connection.Interface.ContactList */
|
||||||
|
contactListIface = Tp::BaseConnectionContactListInterface::create();
|
||||||
|
contactListIface->setGetContactListAttributesCallback(Tp::memFun(this, &ConnectConnection::getContactListAttributes));
|
||||||
|
// contactListIface->setRequestSubscriptionCallback(Tp::memFun(this, &ConnectConnection::requestSubscription));
|
||||||
|
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(contactListIface));
|
||||||
|
|
||||||
|
/* Connection.Interface.Requests */
|
||||||
|
requestsIface = Tp::BaseConnectionRequestsInterface::create(this);
|
||||||
|
/* Fill requestableChannelClasses */
|
||||||
|
Tp::RequestableChannelClass text;
|
||||||
|
text.fixedProperties[TP_QT_IFACE_CHANNEL+".ChannelType"] = TP_QT_IFACE_CHANNEL_TYPE_TEXT;
|
||||||
|
text.fixedProperties[TP_QT_IFACE_CHANNEL+".TargetHandleType"] = Tp::HandleTypeContact;
|
||||||
|
text.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetHandle");
|
||||||
|
text.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetID");
|
||||||
|
requestsIface->requestableChannelClasses << text;
|
||||||
|
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(requestsIface));
|
||||||
|
|
||||||
|
QString selfName = QLatin1String("SelfContact");
|
||||||
|
|
||||||
|
if (parameters.contains("self_name")) {
|
||||||
|
selfName = parameters.value("self_name").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters.contains("device_id")) {
|
||||||
|
m_deviceId = parameters.value("device_id").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelfHandle(addContact(selfName + "@kdeconnect_" + m_deviceId));
|
||||||
|
|
||||||
|
setConnectCallback(Tp::memFun(this, &ConnectConnection::connect));
|
||||||
|
setInspectHandlesCallback(Tp::memFun(this, &ConnectConnection::inspectHandles));
|
||||||
|
setCreateChannelCallback(Tp::memFun(this, &ConnectConnection::createChannelCB));
|
||||||
|
setRequestHandlesCallback(Tp::memFun(this, &ConnectConnection::requestHandles));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectConnection::~ConnectConnection()
|
||||||
|
{
|
||||||
|
qDebug() << "goodbye connection";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectConnection::connect(Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
setStatus(Tp::ConnectionStatusConnecting, Tp::ConnectionStatusReasonRequested);
|
||||||
|
|
||||||
|
simplePresenceIface->setStatuses(getSimpleStatusSpecMap());
|
||||||
|
|
||||||
|
Tp::SimpleContactPresences presences;
|
||||||
|
Tp::SimplePresence presence;
|
||||||
|
presence.status = "available";
|
||||||
|
presence.statusMessage = "";
|
||||||
|
presence.type = Tp::ConnectionPresenceTypeAvailable;
|
||||||
|
presences[selfHandle()] = presence;
|
||||||
|
simplePresenceIface->setPresences(presences);
|
||||||
|
|
||||||
|
setStatus(Tp::ConnectionStatusConnected, Tp::ConnectionStatusReasonRequested);
|
||||||
|
|
||||||
|
/* Set ContactList status */
|
||||||
|
contactListIface->setContactListState(Tp::ContactListStateSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ConnectConnection::inspectHandles(uint handleType, const Tp::UIntList &handles, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
if (handleType != Tp::HandleTypeContact) {
|
||||||
|
error->set(TP_QT_ERROR_INVALID_ARGUMENT, "Unsupported handle type");
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList result;
|
||||||
|
|
||||||
|
foreach (uint handle, handles) {
|
||||||
|
if (!m_handles.contains(handle)) {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(m_handles.value(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::BaseChannelPtr ConnectConnection::createChannelCB(const QVariantMap &request, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
const uint targetHandleType = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")).toUInt();
|
||||||
|
const QString channelType = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")).toString();
|
||||||
|
|
||||||
|
//note if we ever have this invoked from external clients we need to look for TargetID too and look it up
|
||||||
|
const uint targetHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")).toUInt();
|
||||||
|
|
||||||
|
qDebug() << "ConnectConnection::createChannel " << channelType
|
||||||
|
<< " " << targetHandleType
|
||||||
|
<< " " << targetHandle;
|
||||||
|
|
||||||
|
if ((targetHandleType != Tp::HandleTypeContact) || (targetHandle == 0)) {
|
||||||
|
error->set(TP_QT_ERROR_INVALID_HANDLE, "createChannel error");
|
||||||
|
return Tp::BaseChannelPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::BaseChannelPtr baseChannel = Tp::BaseChannel::create(this, channelType, Tp::HandleType(targetHandleType), targetHandle);
|
||||||
|
|
||||||
|
QString identifier = m_handles.value(targetHandle);
|
||||||
|
|
||||||
|
if (channelType == TP_QT_IFACE_CHANNEL_TYPE_TEXT) {
|
||||||
|
ConnectTextChannelPtr textType = ConnectTextChannel::create(this, baseChannel.data(), targetHandle, identifier);
|
||||||
|
qDebug() << "Text interface is called " << textType->interfaceName();
|
||||||
|
baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(textType));
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::UIntList ConnectConnection::requestHandles(uint handleType, const QStringList &identifiers, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << identifiers;
|
||||||
|
|
||||||
|
Tp::UIntList result;
|
||||||
|
|
||||||
|
if (handleType != Tp::HandleTypeContact) {
|
||||||
|
error->set(TP_QT_ERROR_INVALID_ARGUMENT, "ConnectConnection::requestHandles - Handle Type unknown");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(const QString &identify, identifiers) {
|
||||||
|
uint handle = m_handles.key(identify, 0);
|
||||||
|
if (handle) {
|
||||||
|
result.append(handle);
|
||||||
|
} else {
|
||||||
|
result.append(addContact(identify));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::ContactAttributesMap ConnectConnection::getContactListAttributes(const QStringList &interfaces, bool hold, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
Tp::ContactAttributesMap contactAttributes;
|
||||||
|
|
||||||
|
foreach (const uint handle, m_handles.keys()) {
|
||||||
|
if (handle == selfHandle()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QVariantMap attributes;
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection/contact-id"] = m_handles.value(handle);
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection.Interface.ContactList/subscribe"] = Tp::SubscriptionStateYes;
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection.Interface.ContactList/publish"] = Tp::SubscriptionStateYes;
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection.Interface.ConnectPresence/presence"] = QVariant::fromValue(getPresence(handle));
|
||||||
|
contactAttributes[handle] = attributes;
|
||||||
|
}
|
||||||
|
return contactAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::ContactAttributesMap ConnectConnection::getContactAttributes(const Tp::UIntList &handles, const QStringList &interfaces, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
// Connection.Interface.Contacts
|
||||||
|
// http://telepathy.freedesktop.org/spec/Connection_Interface_Contacts.html#Method:GetContactAttributes
|
||||||
|
qDebug() << Q_FUNC_INFO << handles;
|
||||||
|
|
||||||
|
Tp::ContactAttributesMap contactAttributes;
|
||||||
|
|
||||||
|
foreach (const uint handle, handles) {
|
||||||
|
if (m_handles.contains(handle)){
|
||||||
|
QVariantMap attributes;
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection/contact-id"] = m_handles.value(handle);
|
||||||
|
|
||||||
|
if (handle != selfHandle() && interfaces.contains("org.freedesktop.Telepathy.Connection.Interface.ContactList")) {
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection.Interface.ContactList/subscribe"] = Tp::SubscriptionStateYes;
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection.Interface.ContactList/publish"] = Tp::SubscriptionStateYes;
|
||||||
|
attributes["org.freedesktop.Telepathy.Connection.Interface.SimplePresence/presence"] = QVariant::fromValue(getPresence(handle));
|
||||||
|
}
|
||||||
|
contactAttributes[handle] = attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return contactAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::SimplePresence ConnectConnection::getPresence(uint handle)
|
||||||
|
{
|
||||||
|
return Tp::Presence::offline().barePresence();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ConnectConnection::setPresence(const QString &status, const QString &message, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "not implemented";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ConnectConnection::ensureContact(const QString &identifier)
|
||||||
|
{
|
||||||
|
uint handle = getHandle(identifier);
|
||||||
|
if (!handle) {
|
||||||
|
handle = addContact(identifier);
|
||||||
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ConnectConnection::addContacts(const QStringList &identifiers)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
uint handle = 0;
|
||||||
|
|
||||||
|
if (!m_handles.isEmpty()) {
|
||||||
|
handle = m_handles.keys().last();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<uint> newHandles;
|
||||||
|
foreach(const QString &identifier, identifiers) {
|
||||||
|
++handle;
|
||||||
|
m_handles.insert(handle, identifier);
|
||||||
|
newHandles << handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ConnectConnection::addContact(const QString &identifier)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
return addContacts(QStringList() << identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive message from someone to ourself */
|
||||||
|
bool ConnectConnection::receiveMessage(const QString &sender, const QString &message)
|
||||||
|
{
|
||||||
|
uint senderHandle, targetHandle;
|
||||||
|
|
||||||
|
Tp::HandleType handleType = Tp::HandleTypeContact;
|
||||||
|
senderHandle = targetHandle = ensureContact(sender);
|
||||||
|
|
||||||
|
Tp::DBusError error;
|
||||||
|
bool yours;
|
||||||
|
|
||||||
|
QVariantMap request;
|
||||||
|
request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")] = TP_QT_IFACE_CHANNEL_TYPE_TEXT;
|
||||||
|
request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")] = targetHandle;
|
||||||
|
request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] = Tp::HandleTypeContact;
|
||||||
|
request[TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")] = targetHandle; //they texted you, so they started it
|
||||||
|
Tp::BaseChannelPtr channel = ensureChannel(request, yours, false, &error);
|
||||||
|
if (error.isValid()) {
|
||||||
|
qWarning() << "ensureChannel failed:" << error.name() << " " << error.message();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::BaseChannelTextTypePtr textChannel = Tp::BaseChannelTextTypePtr::dynamicCast(channel->interface(TP_QT_IFACE_CHANNEL_TYPE_TEXT));
|
||||||
|
if (!textChannel) {
|
||||||
|
qDebug() << "Error, channel is not a textChannel??";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint timestamp = QDateTime::currentMSecsSinceEpoch() / 1000;
|
||||||
|
|
||||||
|
Tp::MessagePartList body;
|
||||||
|
Tp::MessagePart text;
|
||||||
|
text["content-type"] = QDBusVariant("text/plain");
|
||||||
|
text["content"] = QDBusVariant(message);
|
||||||
|
body << text;
|
||||||
|
|
||||||
|
Tp::MessagePartList partList;
|
||||||
|
Tp::MessagePart header;
|
||||||
|
header["message-received"] = QDBusVariant(timestamp);
|
||||||
|
header["message-sender"] = QDBusVariant(senderHandle);
|
||||||
|
header["message-sender-id"] = QDBusVariant(sender);
|
||||||
|
//header["sender-nickname"] = QDBusVariant(pushName);
|
||||||
|
header["message-type"] = QDBusVariant(Tp::ChannelTextMessageTypeNormal);
|
||||||
|
|
||||||
|
partList << header << body;
|
||||||
|
textChannel->addReceivedMessage(partList);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectConnection::setContactList(const QStringList &identifiers)
|
||||||
|
{
|
||||||
|
// Actually it don't clear previous list (not implemented yet)
|
||||||
|
addContacts(identifiers);
|
||||||
|
|
||||||
|
// Tp::ContactSubscriptionMap changes;
|
||||||
|
// Tp::HandleIdentifierMap identifiers;
|
||||||
|
// Tp::HandleIdentifierMap removals;
|
||||||
|
|
||||||
|
QList<uint> handles;
|
||||||
|
|
||||||
|
for (int i = 0; i < identifiers.count(); ++i) {
|
||||||
|
handles.append(ensureContact(identifiers.at(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ConnectConnection::getHandle(const QString &identifier) const
|
||||||
|
{
|
||||||
|
foreach (uint key, m_handles.keys()) {
|
||||||
|
if (m_handles.value(key) == identifier) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
71
telepathy-cm/connection.h
Normal file
71
telepathy-cm/connection.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 Alexandr Akulich <akulichalexander@gmail.com>
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONNECTCM_CONNECTION_H
|
||||||
|
#define CONNECTCM_CONNECTION_H
|
||||||
|
|
||||||
|
#include "connectcm_export.h"
|
||||||
|
|
||||||
|
#include <TelepathyQt/BaseConnection>
|
||||||
|
#include <TelepathyQt/BaseChannel>
|
||||||
|
|
||||||
|
class CONNECTCM_EXPORT ConnectConnection : public Tp::BaseConnection
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ConnectConnection(const QDBusConnection &dbusConnection,
|
||||||
|
const QString &cmName, const QString &protocolName,
|
||||||
|
const QVariantMap ¶meters);
|
||||||
|
~ConnectConnection();
|
||||||
|
|
||||||
|
static Tp::SimpleStatusSpecMap getSimpleStatusSpecMap();
|
||||||
|
|
||||||
|
void connect(Tp::DBusError *error);
|
||||||
|
QStringList inspectHandles(uint handleType, const Tp::UIntList &handles, Tp::DBusError *error);
|
||||||
|
Tp::BaseChannelPtr createChannelCB(const QVariantMap &request, Tp::DBusError *error);
|
||||||
|
|
||||||
|
Tp::UIntList requestHandles(uint handleType, const QStringList &identifiers, Tp::DBusError *error);
|
||||||
|
|
||||||
|
Tp::ContactAttributesMap getContactListAttributes(const QStringList &interfaces, bool hold, Tp::DBusError *error);
|
||||||
|
Tp::ContactAttributesMap getContactAttributes(const Tp::UIntList &handles, const QStringList &interfaces, Tp::DBusError *error);
|
||||||
|
|
||||||
|
Tp::SimplePresence getPresence(uint handle);
|
||||||
|
uint setPresence(const QString &status, const QString &message, Tp::DBusError *error);
|
||||||
|
|
||||||
|
uint ensureContact(const QString &identifier);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool receiveMessage(const QString &sender, const QString &message);
|
||||||
|
void setContactList(const QStringList &identifiers);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void messageReceived(const QString &sender, const QString &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint getHandle(const QString &identifier) const;
|
||||||
|
uint addContact(const QString &identifier);
|
||||||
|
uint addContacts(const QStringList &identifiers);
|
||||||
|
|
||||||
|
Tp::BaseConnectionContactsInterfacePtr contactsIface;
|
||||||
|
Tp::BaseConnectionSimplePresenceInterfacePtr simplePresenceIface;
|
||||||
|
Tp::BaseConnectionContactListInterfacePtr contactListIface;
|
||||||
|
Tp::BaseConnectionAddressingInterfacePtr addressingIface;
|
||||||
|
Tp::BaseConnectionRequestsInterfacePtr requestsIface;
|
||||||
|
|
||||||
|
QMap<uint, QString> m_handles;
|
||||||
|
/* Maps a contact handle to its subscription state */
|
||||||
|
|
||||||
|
QString m_deviceId;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONNECTCM_CONNECTION_H
|
6
telepathy-cm/kdeconnect.manager
Normal file
6
telepathy-cm/kdeconnect.manager
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[ConnectionManager]
|
||||||
|
BusName=org.freedesktop.Telepathy.ConnectionManager.kdeconnect
|
||||||
|
ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/kdeconnect
|
||||||
|
Interfaces=
|
||||||
|
|
||||||
|
[Protocol kdeconnect]
|
68
telepathy-cm/kdeconnecttelepathyprotocolfactory.cpp
Normal file
68
telepathy-cm/kdeconnecttelepathyprotocolfactory.cpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#include <TelepathyQt/Types>
|
||||||
|
#include <TelepathyQt/BaseConnectionManager>
|
||||||
|
#include <TelepathyQt/Constants>
|
||||||
|
#include <TelepathyQt/Debug>
|
||||||
|
#include <TelepathyQt/Types>
|
||||||
|
#include <TelepathyQt/ConnectionManager>
|
||||||
|
|
||||||
|
#include <TelepathyQt/AccountManager>
|
||||||
|
#include <TelepathyQt/Account>
|
||||||
|
#include <TelepathyQt/PendingReady>
|
||||||
|
#include <TelepathyQt/PendingAccount>
|
||||||
|
#include <TelepathyQt/AccountSet>
|
||||||
|
|
||||||
|
#include <QtDBus/QDBusConnection>
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
|
#include "kdeconnecttelepathyprotocolfactory.h"
|
||||||
|
|
||||||
|
Tp::WeakPtr<KDEConnectTelepathyProtocol> KDEConnectTelepathyProtocolFactory::s_interface;
|
||||||
|
|
||||||
|
ConnectProtocolPtr KDEConnectTelepathyProtocolFactory::interface() {
|
||||||
|
if (s_interface.isNull()) {
|
||||||
|
Tp::registerTypes();
|
||||||
|
Tp::enableDebug(true);
|
||||||
|
Tp::enableWarnings(true);
|
||||||
|
|
||||||
|
ConnectProtocolPtr protocol = Tp::BaseProtocol::create<KDEConnectTelepathyProtocol>(
|
||||||
|
QDBusConnection::sessionBus(),
|
||||||
|
QLatin1String("kdeconnect"));
|
||||||
|
s_interface = protocol;
|
||||||
|
|
||||||
|
static Tp::BaseConnectionManagerPtr cm = Tp::BaseConnectionManager::create(
|
||||||
|
QDBusConnection::sessionBus(), QLatin1String("kdeconnect"));
|
||||||
|
|
||||||
|
protocol->setConnectionManagerName(cm->name());
|
||||||
|
protocol->setEnglishName(QLatin1String("KDE Connect"));
|
||||||
|
protocol->setIconName(QLatin1String("kdeconnect"));
|
||||||
|
protocol->setVCardField(QLatin1String("phone_number"));
|
||||||
|
|
||||||
|
cm->addProtocol(protocol);
|
||||||
|
cm->registerObject();
|
||||||
|
|
||||||
|
//fake being a client and create an account to use this connection
|
||||||
|
//maybe this should be per device.. with a device ID as a parameter, but lets keep it connect for now
|
||||||
|
|
||||||
|
Tp::AccountManagerPtr am = Tp::AccountManager::create(QDBusConnection::sessionBus());
|
||||||
|
QObject::connect(am->becomeReady(), &Tp::PendingOperation::finished, [am]() {
|
||||||
|
Tp::AccountSetPtr accounts = am->accountsByProtocol("kdeconnect");
|
||||||
|
if (!accounts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (accounts->accounts().isEmpty()) {
|
||||||
|
Tp::PendingAccount* pa = am->createAccount("kdeconnect", "kdeconnect", "kdeconnect", QVariantMap(), QVariantMap());
|
||||||
|
QObject::connect(pa, &Tp::PendingOperation::finished, pa, [pa](){
|
||||||
|
if (!pa->account()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pa->account()->setEnabled(true);
|
||||||
|
pa->account()->setRequestedPresence(Tp::Presence::available());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Tp::AccountPtr account = accounts->accounts().first();
|
||||||
|
account->setRequestedPresence(Tp::Presence::available());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return s_interface.toStrongRef();
|
||||||
|
}
|
18
telepathy-cm/kdeconnecttelepathyprotocolfactory.h
Normal file
18
telepathy-cm/kdeconnecttelepathyprotocolfactory.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
|
#include "connectcm_export.h"
|
||||||
|
|
||||||
|
typedef Tp::SharedPtr<KDEConnectTelepathyProtocol> ConnectProtocolPtr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SingletonFactory for plugins to get access to the Telepathy connection manager
|
||||||
|
* Whilst the main process also holds a reference.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CONNECTCM_EXPORT KDEConnectTelepathyProtocolFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ConnectProtocolPtr interface();
|
||||||
|
private:
|
||||||
|
static Tp::WeakPtr<KDEConnectTelepathyProtocol> s_interface;
|
||||||
|
};
|
116
telepathy-cm/protocol.cpp
Normal file
116
telepathy-cm/protocol.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 Alexandr Akulich <akulichalexander@gmail.com>
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "protocol.h"
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
#include <TelepathyQt/BaseConnection>
|
||||||
|
#include <TelepathyQt/Constants>
|
||||||
|
#include <TelepathyQt/RequestableChannelClassSpec>
|
||||||
|
#include <TelepathyQt/RequestableChannelClassSpecList>
|
||||||
|
#include <TelepathyQt/Types>
|
||||||
|
|
||||||
|
#include <QLatin1String>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
KDEConnectTelepathyProtocol::KDEConnectTelepathyProtocol(const QDBusConnection &dbusConnection, const QString &name)
|
||||||
|
: BaseProtocol(dbusConnection, name)
|
||||||
|
{
|
||||||
|
// setParameters(Tp::ProtocolParameterList()
|
||||||
|
// << Tp::ProtocolParameter(QLatin1String("device_id"), QLatin1String("s"), Tp::ConnMgrParamFlagRequired)
|
||||||
|
// << Tp::ProtocolParameter(QLatin1String("self_name"), QLatin1String("s"), 0));
|
||||||
|
|
||||||
|
setRequestableChannelClasses(Tp::RequestableChannelClassSpecList() << Tp::RequestableChannelClassSpec::textChat());
|
||||||
|
|
||||||
|
// callbacks
|
||||||
|
setCreateConnectionCallback(memFun(this, &KDEConnectTelepathyProtocol::createConnection));
|
||||||
|
setIdentifyAccountCallback(memFun(this, &KDEConnectTelepathyProtocol::identifyAccount));
|
||||||
|
setNormalizeContactCallback(memFun(this, &KDEConnectTelepathyProtocol::normalizeContact));
|
||||||
|
|
||||||
|
addrIface = Tp::BaseProtocolAddressingInterface::create();
|
||||||
|
addrIface->setAddressableVCardFields(QStringList() << QLatin1String("x-example-vcard-field"));
|
||||||
|
addrIface->setAddressableUriSchemes(QStringList() << QLatin1String("example-uri-scheme"));
|
||||||
|
addrIface->setNormalizeVCardAddressCallback(memFun(this, &KDEConnectTelepathyProtocol::normalizeVCardAddress));
|
||||||
|
addrIface->setNormalizeContactUriCallback(memFun(this, &KDEConnectTelepathyProtocol::normalizeContactUri));
|
||||||
|
plugInterface(Tp::AbstractProtocolInterfacePtr::dynamicCast(addrIface));
|
||||||
|
/*
|
||||||
|
presenceIface = Tp::BaseProtocolPresenceInterface::create();
|
||||||
|
presenceIface->setStatuses(Tp::PresenceSpecList(ConnectConnection::getConnectStatusSpecMap()));
|
||||||
|
plugInterface(Tp::AbstractProtocolInterfacePtr::dynamicCast(presenceIface));*/
|
||||||
|
|
||||||
|
Tp::DBusError err;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDEConnectTelepathyProtocol::~KDEConnectTelepathyProtocol()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDEConnectTelepathyProtocol::setConnectionManagerName(const QString &newName)
|
||||||
|
{
|
||||||
|
m_connectionManagerName = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDEConnectTelepathyProtocol::sendMessage(QString sender, QString message)
|
||||||
|
{
|
||||||
|
if (m_connection) {
|
||||||
|
return m_connection->receiveMessage(sender, message);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDEConnectTelepathyProtocol::setContactList(QStringList list)
|
||||||
|
{
|
||||||
|
if (m_connection) {
|
||||||
|
m_connection->setContactList(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tp::BaseConnectionPtr KDEConnectTelepathyProtocol::createConnection(const QVariantMap ¶meters, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
Q_UNUSED(error)
|
||||||
|
|
||||||
|
auto newConnection = Tp::BaseConnection::create<ConnectConnection>(m_connectionManagerName, this->name(), parameters);
|
||||||
|
connect(newConnection.constData(), SIGNAL(messageReceived(QString,QString)), SIGNAL(messageReceived(QString,QString)));
|
||||||
|
m_connection = newConnection;
|
||||||
|
|
||||||
|
return newConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KDEConnectTelepathyProtocol::identifyAccount(const QVariantMap ¶meters, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << parameters;
|
||||||
|
error->set(QLatin1String("IdentifyAccount.Error.NotImplemented"), QLatin1String(""));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KDEConnectTelepathyProtocol::normalizeContact(const QString &contactId, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << contactId;
|
||||||
|
error->set(QLatin1String("NormalizeContact.Error.NotImplemented"), QLatin1String(""));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KDEConnectTelepathyProtocol::normalizeVCardAddress(const QString &vcardField, const QString vcardAddress,
|
||||||
|
Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << vcardField << vcardAddress;
|
||||||
|
error->set(QLatin1String("NormalizeVCardAddress.Error.NotImplemented"), QLatin1String(""));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KDEConnectTelepathyProtocol::normalizeContactUri(const QString &uri, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << uri;
|
||||||
|
error->set(QLatin1String("NormalizeContactUri.Error.NotImplemented"), QLatin1String(""));
|
||||||
|
return QString();
|
||||||
|
}
|
68
telepathy-cm/protocol.h
Normal file
68
telepathy-cm/protocol.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 Alexandr Akulich <akulichalexander@gmail.com>
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONNECTCM_PROTOCOL_H
|
||||||
|
#define CONNECTCM_PROTOCOL_H
|
||||||
|
|
||||||
|
#include "connectcm_export.h"
|
||||||
|
|
||||||
|
#include <TelepathyQt/BaseProtocol>
|
||||||
|
|
||||||
|
class ConnectConnection;
|
||||||
|
|
||||||
|
class CONNECTCM_EXPORT KDEConnectTelepathyProtocol : public Tp::BaseProtocol
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(KDEConnectTelepathyProtocol)
|
||||||
|
|
||||||
|
public:
|
||||||
|
KDEConnectTelepathyProtocol(const QDBusConnection &dbusConnection, const QString &name);
|
||||||
|
virtual ~KDEConnectTelepathyProtocol();
|
||||||
|
|
||||||
|
QString connectionManagerName() const;
|
||||||
|
void setConnectionManagerName(const QString &newName);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool sendMessage(QString sender, QString message);
|
||||||
|
void setContactList(QStringList list);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void contactsListChanged(QStringList);
|
||||||
|
void messageReceived(QString sender, QString message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tp::BaseConnectionPtr createConnection(const QVariantMap ¶meters, Tp::DBusError *error);
|
||||||
|
QString identifyAccount(const QVariantMap ¶meters, Tp::DBusError *error);
|
||||||
|
QString normalizeContact(const QString &contactId, Tp::DBusError *error);
|
||||||
|
|
||||||
|
// Proto.I.Addressing
|
||||||
|
QString normalizeVCardAddress(const QString &vCardField, const QString vCardAddress,
|
||||||
|
Tp::DBusError *error);
|
||||||
|
QString normalizeContactUri(const QString &uri, Tp::DBusError *error);
|
||||||
|
|
||||||
|
Tp::BaseProtocolAddressingInterfacePtr addrIface;
|
||||||
|
Tp::BaseProtocolAvatarsInterfacePtr avatarsIface;
|
||||||
|
|
||||||
|
QString m_connectionManagerName;
|
||||||
|
|
||||||
|
//normally keeping the connection in the protocol would be really weird
|
||||||
|
//however we want to proxy the messages to the active connection and want a single entry point
|
||||||
|
Tp::SharedPtr<ConnectConnection> m_connection;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QString KDEConnectTelepathyProtocol::connectionManagerName() const
|
||||||
|
{
|
||||||
|
return m_connectionManagerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONNECTCM_PROTOCOL_H
|
73
telepathy-cm/textchannel.cpp
Normal file
73
telepathy-cm/textchannel.cpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 Alexandr Akulich <akulichalexander@gmail.com>
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "textchannel.h"
|
||||||
|
|
||||||
|
#include <TelepathyQt/Constants>
|
||||||
|
#include <TelepathyQt/RequestableChannelClassSpec>
|
||||||
|
#include <TelepathyQt/RequestableChannelClassSpecList>
|
||||||
|
#include <TelepathyQt/Types>
|
||||||
|
|
||||||
|
#include <QLatin1String>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
ConnectTextChannel::ConnectTextChannel(QObject *connection, Tp::BaseChannel *baseChannel, uint targetHandle, const QString &identifier)
|
||||||
|
: Tp::BaseChannelTextType(baseChannel),
|
||||||
|
m_connection(connection),
|
||||||
|
m_identifier(identifier)
|
||||||
|
{
|
||||||
|
QStringList supportedContentTypes = QStringList() << "text/plain";
|
||||||
|
Tp::UIntList messageTypes = Tp::UIntList() << Tp::ChannelTextMessageTypeNormal;
|
||||||
|
|
||||||
|
uint messagePartSupportFlags = 0;
|
||||||
|
uint deliveryReportingSupport = 0;
|
||||||
|
|
||||||
|
m_messagesIface = Tp::BaseChannelMessagesInterface::create(this,
|
||||||
|
supportedContentTypes,
|
||||||
|
messageTypes,
|
||||||
|
messagePartSupportFlags,
|
||||||
|
deliveryReportingSupport);
|
||||||
|
|
||||||
|
baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(m_messagesIface));
|
||||||
|
|
||||||
|
m_messagesIface->setSendMessageCallback(Tp::memFun(this, &ConnectTextChannel::sendMessageCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectTextChannelPtr ConnectTextChannel::create(QObject *connection, Tp::BaseChannel *baseChannel, uint targetHandle, const QString &identifier)
|
||||||
|
{
|
||||||
|
return ConnectTextChannelPtr(new ConnectTextChannel(connection, baseChannel, targetHandle, identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectTextChannel::~ConnectTextChannel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ConnectTextChannel::sendMessageCallback(const Tp::MessagePartList &messageParts, uint flags, Tp::DBusError *error)
|
||||||
|
{
|
||||||
|
QString content;
|
||||||
|
for (Tp::MessagePartList::const_iterator i = messageParts.begin()+1; i != messageParts.end(); ++i) {
|
||||||
|
if(i->count(QLatin1String("content-type"))
|
||||||
|
&& i->value(QLatin1String("content-type")).variant().toString() == QLatin1String("text/plain")
|
||||||
|
&& i->count(QLatin1String("content")))
|
||||||
|
{
|
||||||
|
content = i->value(QLatin1String("content")).variant().toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(m_connection, "messageReceived", Q_ARG(QString, m_identifier), Q_ARG(QString, content));
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
46
telepathy-cm/textchannel.h
Normal file
46
telepathy-cm/textchannel.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 Alexandr Akulich <akulichalexander@gmail.com>
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONNECTCM_TEXTCHANNEL_H
|
||||||
|
#define CONNECTCM_TEXTCHANNEL_H
|
||||||
|
|
||||||
|
#include "connectcm_export.h"
|
||||||
|
|
||||||
|
#include <TelepathyQt/BaseChannel>
|
||||||
|
|
||||||
|
class ConnectTextChannel;
|
||||||
|
|
||||||
|
typedef Tp::SharedPtr<ConnectTextChannel> ConnectTextChannelPtr;
|
||||||
|
|
||||||
|
class CONNECTCM_EXPORT ConnectTextChannel : public Tp::BaseChannelTextType
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static ConnectTextChannelPtr create(QObject *connection, Tp::BaseChannel *baseChannel, uint targetHandle, const QString &identifier);
|
||||||
|
virtual ~ConnectTextChannel();
|
||||||
|
|
||||||
|
QString sendMessageCallback(const Tp::MessagePartList &messageParts, uint flags, Tp::DBusError *error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ConnectTextChannel(QObject *connection, Tp::BaseChannel *baseChannel, uint targetHandle, const QString &identifier);
|
||||||
|
|
||||||
|
QObject *m_connection;
|
||||||
|
|
||||||
|
QString m_identifier;
|
||||||
|
|
||||||
|
Tp::BaseChannelTextTypePtr m_channelTextType;
|
||||||
|
Tp::BaseChannelMessagesInterfacePtr m_messagesIface;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONNECTCM_TEXTCHANNEL_H
|
Loading…
Reference in a new issue