Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. DBus reply data accessed via QString
Forum Updated to NodeBB v4.3 + New Features

DBus reply data accessed via QString

Scheduled Pinned Locked Moved Solved General and Desktop
dbusmethodqstringqvariantqlist
22 Posts 3 Posters 13.4k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    amonR2
    wrote on last edited by
    #13

    The output of qDebug << args.count(); gives me 1. There is something I have changed in my code's environment: previously it was in release mode and I have just thought to put it in Debug one's which gives more info. With this code:

    QString a1 = args.at(1).toString();
    qDebug() << a1;
    

    my app crashes and the IDE gives me this message: ASSERT failure in QList<T>::at: "index out of range", file /usr/include/qt4/QtCore/qlist.h, line 469. But when I use this one:

    QString a1 = args.at(0).toString();
    qDebug() << a1;
    

    my app doesn't crash and qDebug() gives me an empty string.

    miclandM 1 Reply Last reply
    0
    • A amonR2

      The output of qDebug << args.count(); gives me 1. There is something I have changed in my code's environment: previously it was in release mode and I have just thought to put it in Debug one's which gives more info. With this code:

      QString a1 = args.at(1).toString();
      qDebug() << a1;
      

      my app crashes and the IDE gives me this message: ASSERT failure in QList<T>::at: "index out of range", file /usr/include/qt4/QtCore/qlist.h, line 469. But when I use this one:

      QString a1 = args.at(0).toString();
      qDebug() << a1;
      

      my app doesn't crash and qDebug() gives me an empty string.

      miclandM Offline
      miclandM Offline
      micland
      wrote on last edited by
      #14

      @amonR2
      Ok, the argument list contains just one argument - that's why you get the "index out of range" error because you try to access the second argument. Please add the line qDebug() << args.at(0).typeName(); to see the type of the first argument. Maybe it's a list where you find all your expected data in...

      A 1 Reply Last reply
      0
      • miclandM micland

        @amonR2
        Ok, the argument list contains just one argument - that's why you get the "index out of range" error because you try to access the second argument. Please add the line qDebug() << args.at(0).typeName(); to see the type of the first argument. Maybe it's a list where you find all your expected data in...

        A Offline
        A Offline
        amonR2
        wrote on last edited by
        #15

        The reply from qDebug() << args.at(0).typeName(); gives me: QDBusArgument.

        miclandM 1 Reply Last reply
        0
        • A amonR2

          The reply from qDebug() << args.at(0).typeName(); gives me: QDBusArgument.

          miclandM Offline
          miclandM Offline
          micland
          wrote on last edited by
          #16

          @amonR2
          Huh, a nested QDBusArgument? Well check the inner argument if it serves the expected information:
          args.at(0).value<QDBusArgument>().args().
          (You should really try to inspect the reply using the debugger and iterate through the object tree to see what's encapsulated in the arguments. That's a lot easier than poking with qDebug() - perhaps this link will help you getting started? http://doc.qt.io/qtcreator/creator-debug-mode.html)

          1 Reply Last reply
          0
          • A Offline
            A Offline
            amonR2
            wrote on last edited by
            #17

            @micland said:

            Huh, a nested QDBusArgument?

            sorry I don't understand what you mean there but that's all qDebug displays.
            Then when I try to qDebug thisargs.at(0).value<QDBusArgument>().args();, the compiler says: 'class QDBusArgument' has no member named 'args'. So I tried with this: args.at(0).value<QDBusArgument>() and received the following from the compiler: no match for 'operator<<' in 'qDebug()() << QVariant::value() const [with T = QDBusArgument]()' [...] no known conversion for argument 1 from 'QDebug' to 'QDBusArgument&'.
            Finally, by puting a breakpoint (thank you for the link) at QList<QVariant> args = replyClementine.arguments(); in my code and launching the debug-mode, the compiler stops and shows me this through the "Locals and Expressions" window:

            	args                 	<inaccessible>	QList<QVariant>
            	this	 @0x83f87d8	FenetreNNS
            		QWidget		QWidget
            		Deviselabel	0x0	QLabel *
            		MainLabel	 @0x844d210	QLabel
            		Nextm	 @0x8451f28	QPushButton
            		NoTrackLabel	 @0x8454628	QLabel
            		Play	 @0x844f628	QPushButton
            		Previous	 @0x8451088	QPushButton
            		TemoinSousTitre	false	bool
            		Volume	 @0x8453a48	QSlider
            		VolumeLabel	 @0x844d160	QLabel
            		boutonDeviseBaht	 @0x8439978	QPushButton
            		boutonDeviseDenar	 @0x843cce0	QPushButton
            		boutonDeviseDollar	 @0x843f968	QPushButton
            		boutonDeviseEuro	 @0x8440418	QPushButton
            		boutonDeviseLira	 @0x843e608	QPushButton
            		boutonDevisePeso	 @0x8442098	QPushButton
            		boutonDevisePound	 @0x8444e58	QPushButton
            		boutonDeviseRuble	 @0x843b078	QPushButton
            		boutonDeviseRupee	 @0x844a4b0	QPushButton
            		boutonDeviseWon	 @0x844b2e0	QPushButton
            		boutonDeviseYen	 @0x8448a28	QPushButton
            		boutonDeviseYuan	 @0x8449e70	QPushButton
            		iface_Clementine	 @0x845e788	QDBusInterface
            		machine	 @0x8455420	QStateMachine
            		principalefen	 @0xbffff7b4	FenPrincipale
            		replyClementine		QDBusMessage
            			d_ptr	 @0x845d098	QDBusMessagePrivate
            		signMapper	 @0x8454ac0	QSignalMapper
            		signMapper2	 @0x84553e8	QSignalMapper
            		sliderSousTitre	 @0x844d998	QSlider
            		state1	 @0x8451f60	QState
            		state2	 @0x8451f70	QState
            		str1	"Currency"	QString
            		tempo	 @0x84505b0	QTimer
            
            

            Should I show the content of some other windows?

            miclandM 1 Reply Last reply
            0
            • A amonR2

              @micland said:

              Huh, a nested QDBusArgument?

              sorry I don't understand what you mean there but that's all qDebug displays.
              Then when I try to qDebug thisargs.at(0).value<QDBusArgument>().args();, the compiler says: 'class QDBusArgument' has no member named 'args'. So I tried with this: args.at(0).value<QDBusArgument>() and received the following from the compiler: no match for 'operator<<' in 'qDebug()() << QVariant::value() const [with T = QDBusArgument]()' [...] no known conversion for argument 1 from 'QDebug' to 'QDBusArgument&'.
              Finally, by puting a breakpoint (thank you for the link) at QList<QVariant> args = replyClementine.arguments(); in my code and launching the debug-mode, the compiler stops and shows me this through the "Locals and Expressions" window:

              	args                 	<inaccessible>	QList<QVariant>
              	this	 @0x83f87d8	FenetreNNS
              		QWidget		QWidget
              		Deviselabel	0x0	QLabel *
              		MainLabel	 @0x844d210	QLabel
              		Nextm	 @0x8451f28	QPushButton
              		NoTrackLabel	 @0x8454628	QLabel
              		Play	 @0x844f628	QPushButton
              		Previous	 @0x8451088	QPushButton
              		TemoinSousTitre	false	bool
              		Volume	 @0x8453a48	QSlider
              		VolumeLabel	 @0x844d160	QLabel
              		boutonDeviseBaht	 @0x8439978	QPushButton
              		boutonDeviseDenar	 @0x843cce0	QPushButton
              		boutonDeviseDollar	 @0x843f968	QPushButton
              		boutonDeviseEuro	 @0x8440418	QPushButton
              		boutonDeviseLira	 @0x843e608	QPushButton
              		boutonDevisePeso	 @0x8442098	QPushButton
              		boutonDevisePound	 @0x8444e58	QPushButton
              		boutonDeviseRuble	 @0x843b078	QPushButton
              		boutonDeviseRupee	 @0x844a4b0	QPushButton
              		boutonDeviseWon	 @0x844b2e0	QPushButton
              		boutonDeviseYen	 @0x8448a28	QPushButton
              		boutonDeviseYuan	 @0x8449e70	QPushButton
              		iface_Clementine	 @0x845e788	QDBusInterface
              		machine	 @0x8455420	QStateMachine
              		principalefen	 @0xbffff7b4	FenPrincipale
              		replyClementine		QDBusMessage
              			d_ptr	 @0x845d098	QDBusMessagePrivate
              		signMapper	 @0x8454ac0	QSignalMapper
              		signMapper2	 @0x84553e8	QSignalMapper
              		sliderSousTitre	 @0x844d998	QSlider
              		state1	 @0x8451f60	QState
              		state2	 @0x8451f70	QState
              		str1	"Currency"	QString
              		tempo	 @0x84505b0	QTimer
              
              

              Should I show the content of some other windows?

              miclandM Offline
              miclandM Offline
              micland
              wrote on last edited by
              #18

              @amonR2 said:

              Huh, a nested QDBusArgument?
              sorry I don't understand what you mean there but that's all qDebug displays.

              Aye, sorry - I was wrong, read your answer too fast and got confused...
              It's hard to find this error without reproducing it. If I find some time at the weekend I'll try to debug it. Can you tell me which software you installed? will say: what's that player your communicating with?

              A 1 Reply Last reply
              0
              • miclandM micland

                @amonR2 said:

                Huh, a nested QDBusArgument?
                sorry I don't understand what you mean there but that's all qDebug displays.

                Aye, sorry - I was wrong, read your answer too fast and got confused...
                It's hard to find this error without reproducing it. If I find some time at the weekend I'll try to debug it. Can you tell me which software you installed? will say: what's that player your communicating with?

                A Offline
                A Offline
                amonR2
                wrote on last edited by
                #19

                @micland
                The name of the player is "Clementine" and I am using Qt 4.8 . No worries, thank you a lot for your help anyway. I will keep looking for a solution. If I can't find anything I will use one of the other APIs. Cheers again.

                miclandM 2 Replies Last reply
                0
                • A amonR2

                  @micland
                  The name of the player is "Clementine" and I am using Qt 4.8 . No worries, thank you a lot for your help anyway. I will keep looking for a solution. If I can't find anything I will use one of the other APIs. Cheers again.

                  miclandM Offline
                  miclandM Offline
                  micland
                  wrote on last edited by
                  #20

                  @amonR2
                  I'm a little bit closer, but did non really succeed...
                  First: Qt 4.8 is some days older, I used 5.6 for my experiements. Inspecting the DBus interface using qdbusviewer (from Qt5.6) ended with the error message "Unable to find method GetMetadata on path /Player in interface org.freedesktop.MediaPlayer" (the method is listed but I can't call it) - but the cli client qdbus provided me the expected data. I can't say if that's a bug in Qt or a "conformity problem", but it shows that calling the clementine DBus interface from Qt works not straight forward.

                  I tried to access the interface using a simple Qt program (like the example code you posted) and got the same reply as you did. Inspecting the received QDBusArgument showed that its currentyType() is a MapType (4) which means that the arguments are organized as a key/value list (the same says the MPRIS spec: see "Metadata" is an array of dict entries in the form (string, variant) eg: {sv}., https://xmms2.org/wiki/MPRIS#.22Metadata.22)

                  I think you have to extract the values manually and play arround with beginMap(), beginMapEntry(), endMapEntry(), endMap() of QDBusArgument. (I spent just a little time but did not succeed ...)
                  But I'm interested if that's the right way so if you find a solution please share it here! (If I find some time I will try it again, too...)

                  1 Reply Last reply
                  1
                  • A amonR2

                    @micland
                    The name of the player is "Clementine" and I am using Qt 4.8 . No worries, thank you a lot for your help anyway. I will keep looking for a solution. If I can't find anything I will use one of the other APIs. Cheers again.

                    miclandM Offline
                    miclandM Offline
                    micland
                    wrote on last edited by
                    #21

                    @amonR2
                    out of curiousity I was looking for a solution (I didn't know before that maps and structs are supported by DBus). And I found a way - using Qt 5.6, but should work with Qt 4.8 as well:

                        // first the same code as you did already
                        QDBusInterface *iface_Clementine = new QDBusInterface("org.mpris.clementine", "/Player", "org.freedesktop.MediaPlayer", QDBusConnection::sessionBus());
                        if(iface_Clementine->isValid()) {
                            QDBusMessage replyClementine = iface_Clementine->call("GetMetadata");
                            qDebug() << replyClementine;
                            // there is just one argument and this argument is a map
                            QList<QVariant> args = replyClementine.arguments();
                            const QDBusArgument &arg = args[0].value<QDBusArgument>();
                            // the map has to be extracted entry by entry which is a tuple of key and value
                            // in this case, the key is a string but the type of the value depends on the key (string, int, ...)
                            arg.beginMap();
                            while (!arg.atEnd()) {
                                QString key;
                                QDBusVariant value;
                                arg.beginMapEntry();
                                arg >> key >> value;
                                arg.endMapEntry();
                                qDebug() << "Key:" << key << "\t\tValue:" << value.variant();
                            }
                            arg.endMap();
                        }
                    

                    You still have to inspect the type of the value (depends on what the entry represents: album or track number, or whatever). And the argument parsing can be wrapped in a stream operator, see http://doc.qt.io/qt-5/qdbusargument.html#beginMap-1

                    Some further helpul information can be found here: http://stackoverflow.com/questions/20206376/how-do-i-extract-the-returned-data-from-qdbusmessage-in-a-qt-dbus-call

                    I have no clue why the qdbusviewer of Qt 5.6 is unable to call the DBus method but the code snippet above is working fine.

                    A 1 Reply Last reply
                    1
                    • miclandM micland

                      @amonR2
                      out of curiousity I was looking for a solution (I didn't know before that maps and structs are supported by DBus). And I found a way - using Qt 5.6, but should work with Qt 4.8 as well:

                          // first the same code as you did already
                          QDBusInterface *iface_Clementine = new QDBusInterface("org.mpris.clementine", "/Player", "org.freedesktop.MediaPlayer", QDBusConnection::sessionBus());
                          if(iface_Clementine->isValid()) {
                              QDBusMessage replyClementine = iface_Clementine->call("GetMetadata");
                              qDebug() << replyClementine;
                              // there is just one argument and this argument is a map
                              QList<QVariant> args = replyClementine.arguments();
                              const QDBusArgument &arg = args[0].value<QDBusArgument>();
                              // the map has to be extracted entry by entry which is a tuple of key and value
                              // in this case, the key is a string but the type of the value depends on the key (string, int, ...)
                              arg.beginMap();
                              while (!arg.atEnd()) {
                                  QString key;
                                  QDBusVariant value;
                                  arg.beginMapEntry();
                                  arg >> key >> value;
                                  arg.endMapEntry();
                                  qDebug() << "Key:" << key << "\t\tValue:" << value.variant();
                              }
                              arg.endMap();
                          }
                      

                      You still have to inspect the type of the value (depends on what the entry represents: album or track number, or whatever). And the argument parsing can be wrapped in a stream operator, see http://doc.qt.io/qt-5/qdbusargument.html#beginMap-1

                      Some further helpul information can be found here: http://stackoverflow.com/questions/20206376/how-do-i-extract-the-returned-data-from-qdbusmessage-in-a-qt-dbus-call

                      I have no clue why the qdbusviewer of Qt 5.6 is unable to call the DBus method but the code snippet above is working fine.

                      A Offline
                      A Offline
                      amonR2
                      wrote on last edited by
                      #22

                      @micland

                      WOOW!!! Thank you sooo much micland!! It works!!!
                      I tried a code similar to yours but some data were missing. Just needed to do a very tiny modification on your code:

                      qDebug() << key << value.variant().toString();
                      

                      or directly

                      qDebug() << value.variant().toString();
                      

                      Except it, it is perfect! Thank you again.
                      @micland said:

                      I have no clue why the qdbusviewer of Qt 5.6 is unable to call the DBus method but the code snippet above is working fine.

                      I hope it is going to change as I intend to use it or the 5.7 version very soon.

                      Cheers again.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved