maemo.org - Talk

maemo.org - Talk (https://talk.maemo.org/index.php)
-   Development (https://talk.maemo.org/forumdisplay.php?f=13)
-   -   [SFOS+M6] QDBusConnection: receive/send message (https://talk.maemo.org/showthread.php?t=95876)

chrm 2015-08-26 09:04

QDBusConnection: receive/send message
 
Hi!

I'm working on OTR integration for Harmattans conversations UI.
It should be fine by using D-Bus but I have a problem with D-Bus objects converting to Qt-Classes.

But let me explain.

I would like to connect to the interface "org.freedesktop.Telepathy.Channel.Interface.Messa ges" and method "MessageReceived".

dbus-monitor shows this structure:

Code:

signal sender=:1.606 -> dest=(null destination) serial=333 path=/org/freedesktop/Telepathy/Connection/gabble/jabber/XXX_2fnokiaN9/ImChannel33; interface=org.freedesktop.Telepathy.Channel.Interface.Messages; member=MessageReceived
  array [
      array [
        dict entry(            string "pending-message-id"
            variant                uint32 0
        )
        dict entry(
            string "message-sender-id"           
            variant                string "XXX@jabberes.org"
        )
        dict entry(
            string "message-received"
            variant                int64 1440523701   
        )
        dict entry(
            string "message-sender"
            variant                uint32 33
        )      ]
      array [
        dict entry(
            string "content"
            variant                string "Message content"
          )
        dict entry(
            string "content-type"
            variant                string "text/plain"
        )      ]
  ]

So I wrote the following Qt-Code to connect to this event:

Code:

QDBusConnection::sessionBus().connect(QString(),
    QString(),
    "org.freedesktop.Telepathy.Channel.Interface.Messages",
    "MessageReceived", this,
    SLOT(telepathyMessageReceived(QList<QVariant>)));

It works fine and my SLOT will be called on incoming messages:

Code:

void ImControlThread::telepathyMessageReceived(QList<QVariant> _content)
{
    qDebug() << "ImControlThread::telepathyMessageReceived(): size=" << _content.size() << ". Variant=" << _content.at(0).typeName();
}

I have there a QList<QVariant>. The QVariant-Objects must be a QList again with some QVariantMap entries.
But now, I'm out of idea. I'm just not able to parse the D-Bus structure from QList<QVariant>.
The debug output in my SLOT shows for _content.size() == 2. But for _content.at(0).typeName() == "void*".

No chance to cast it in something I can extract the data from.

Do you have an idea? Thank you very much for any hint!

marxian 2015-08-26 12:08

Re: QDBusConnection: receive message
 
I think you will need to use QDBusMessage and QDBusArgument in order to convert the reply arguments:

Code:

void ImControlThread::telepathyMessageReceived(const QDBusMessage &reply) {
    foreach (QVariant arg, reply.arguments()) {
        if (arg.canConvert<QDBusArgument>()) {
            qDebug() << dbusArgumentToVariant(arg.value<QDBusArgument>());
        }
        else {
            qDebug() << arg;
        }
    }
}

QVariant dbusArgumentToVariant(const QDBusArgument &arg) {
    switch (arg.currentType()) {
    case QDBusArgument::BasicType:
    case QDBusArgument::VariantType:
        return basicTypeToVariant(arg);
    case QDBusArgument::ArrayType:
        return arrayTypeToVariant(arg);
    case QDBusArgument::MapType:
        return mapTypeToVariant(arg);
    default:
        return QVariant();
    }
}

QVariant basicTypeToVariant(const QDBusArgument &arg) {
    return arg.asVariant();
}

QVariant arrayTypeToVariant(const QDBusArgument &arg) {
    QVariantList list;
    arg.beginArray();

    while (!arg.atEnd()) {
        list << dbusArgumentToVariant(arg);
    }

    arg.endArray();
    return list;
}

QVariant mapTypeToVariant(const QDBusArgument &arg) {
    QVariantMap map;
    arg.beginMap();

    while (!arg.atEnd()) {
        arg.beginMapEntry();
        map[basicTypeToVariant(arg).toString()] = dbusArgumentToVariant(arg);
        arg.endMapEntry();
    }

    arg.endMap();
    return map;
}


chrm 2015-08-26 13:05

Re: QDBusConnection: receive message
 
Perfect! Thank you very much!

chrm 2015-08-27 08:19

Re: QDBusConnection: receive message
 
Dear marxian,

it works well expect for mapTypeToVariant().
Im able to extract the key name, but value is always empty.
QDBusMessage &reply includes all the data (qDebug() shows everything), but

Code:

map[basicTypeToVariant(arg).toString()] = busArgumentToVariant(arg);
gives a valid map with keys but empty values.

Any idea?

marxian 2015-08-27 11:07

Re: QDBusConnection: receive message
 
It could be that the QDBusArgument::currentType() of the map values is not handled in dbusArgumentToVariant(), therfore an null QVariant is returned. Try adding a qDebug() statement in that function to check the reported type:

Code:

QVariant dbusArgumentToVariant(const QDBusArgument &arg) {
    qDebug() << "dbusArgumentToVariant. Current type is" << arg.currentType();
    switch (arg.currentType()) {
    case QDBusArgument::BasicType:
    case QDBusArgument::VariantType:
        return basicTypeToVariant(arg);
    case QDBusArgument::ArrayType:
        return arrayTypeToVariant(arg);
    case QDBusArgument::MapType:
        return mapTypeToVariant(arg);
    default:
        qDebug() << "dbusArgumentToVariant. Type not handled.";
        return QVariant();
    }
}

I would expect the map values to be basic/variant type, so perhaps QDBusArgument::asVariant() is returning a null QVariant.

chrm 2015-08-28 08:42

Re: QDBusConnection: receive message
 
Hi!

Thank you a lot!
Handling for QDBusArgument::MapEntryType is needed. But now it works fine.

The next step is to insert the decrypted message back in tracker so it appears in the conversations UI.

Do you have any experience with the Tracker on N9? I thing, using tracker-sparql to modify the message is the right way.

Thank you for any hint.

chrm 2015-08-28 13:49

Re: QDBusConnection: receive message
 
Ok, got it. I'm able to remove messages from tracker.

The next step is to insert a new message, the decrypted one.

chrm 2015-09-05 19:07

Re: QDBusConnection: receive/send message
 
Dear Marxian,

Reading received messages and changing them in tracker works fine. But I spent the last week trying to send a DBus message to Telepathy - without success :(

I have to implement this method:
http://telepathy.freedesktop.org/spe...Messages1.html

So this is my code:

Code:

    QList<QVariant> args;

    QDBusObjectPath path("/org/freedesktop/Telepathy/Connection/gabble/jabber/XXX");
    QString targetID = "XXX@jabberes.org";
    args << qVariantFromValue(path);
    args << targetID;

    QMap<QString, QVariant> message;

    message["content"] = QVariant(qVariantFromValue("Message Content"));
    message["content-type"] = QVariant(qVariantFromValue(QString("text/plain")));

    QList<QVariant> msgList;
    msgList << qVariantFromValue(message);

    args << msgList;

    uint flags = 0;
    args << flags;

    m.setArguments(args);
  QDBusMessage retVal = QDBusConnection::sessionBus().call(m);

The retVal error code is:
Code:

QDBusMessage(type=Error, service="", error name="org.freedesktop.DBus.Error.UnknownMethod", error message="Method "SendMessage" with signature "osa{sv}u" on interface "org.freedesktop.Telepathy.ChannelDispatcher.Interface.Messages1" doesn't exist"
So my question is, how to create a message with this signature: "osaa{sv}u", especially this aa{sv}?

I know, there are heavy libs like TelepathyQt, but i want just to send only one message and hope, this could be done with a simple code...

Thank you for any hint.

chrm 2015-09-09 11:56

Re: QDBusConnection: receive/send message
 
Finally, it works!

If someone wants to know, how to send an XMMP-Message using Qt and DBus on Harmattan, here it is:

First declare needed typedefs

Code:

typedef QMap<QString, QVariant> KeyVarPair;
typedef QList<KeyVarPair> KeyVarPairList;
Q_DECLARE_METATYPE(KeyVarPair)
Q_DECLARE_METATYPE(KeyVarPairList)

And register them as DBus types:

Code:

qDBusRegisterMetaType<KeyVarPair>();
qDBusRegisterMetaType<KeyVarPairList>();

Now create a sendMessage function:

Code:

bool MyClass::telepathySendDBusMessage(QString _receiver, QString _account, QString _content)
{
    QString dbus_service = "org.freedesktop.Telepathy.ChannelDispatcher";
    QString dbus_path = "/org/freedesktop/Telepathy/ChannelDispatcher";
    QString dbus_interface = "org.freedesktop.Telepathy.ChannelDispatcher.Interface.Messages.DRAFT";
 
    QDBusMessage m = QDBusMessage::createMethodCall(
                                      dbus_service,
                                      dbus_path,
                                      dbus_interface,
                                      "SendMessage");
   

    QList<QVariant> args;

    // Path and targetID
    QDBusObjectPath path(_account);
    QString targetID = _receiver;
    args << qVariantFromValue(path);
    args << targetID;

    // Message Parts
    KeyVarPair message1;

    int type = 0;
    message1["message-type"] = qVariantFromValue(type);

    KeyVarPair message2;

    message2["content"] = qVariantFromValue(_content);
    message2["content-type"] = qVariantFromValue(QString("text/plain"));

    KeyVarPairList messageData;
    messageData << message1;
    messageData << message2;

    args << qVariantFromValue(messageData);

    // Flags
    uint flags = 0;
    args << flags;

    m.setArguments(args);
 
    QDBusMessage retVal = QDBusConnection::sessionBus().call(m);

    return true;
}

Call the message:

Code:

myClassObj->telepathySendDBusMessage(
  "to.jabber.account@jabber.server.tld",
  "/org/freedesktop/Telepathy/Account/gabble/jabber/ACCOUNT_NAME",
  "It works!");

Finally I have everything to start with the OTR implementation!

Halftux 2015-09-09 13:52

Re: QDBusConnection: receive/send message
 
Quote:

Originally Posted by chrm (Post 1481747)
Finally I have everything to start with the OTR implementation!

Wow that is amazing thanks to you and marxian I learned a lot in this thread.

Will be your final project opensource? Wish you success!


All times are GMT. The time now is 22:22.

vBulletin® Version 3.8.8