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. Is this possible?
Forum Updated to NodeBB v4.3 + New Features

Is this possible?

Scheduled Pinned Locked Moved Unsolved General and Desktop
37 Posts 8 Posters 18.5k Views 6 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I purchased a new book “C++ Templates The Complete Guide SECOND EDITION”.

    ISBN-13: 978-0-321-71412-1
    ISBN-10: 0-321-71412-1

    I’m reading it and trying to digest everything. What I am ultimately aiming for is a way to create a generic and dynamic map capable of storing the information for any QT control or derived control and it’s signals. Where each single entry in the map would contain a pointer or reference to the control and the signal associated with the entry.

    Of course the signal prototypes can be very different and it’s this information I’m hoping to learn from this book. Is there anyone available that is very familiar with templates and QT signal prototypes that can tell me if this is possible?

    The aim is to use the maps with an iterator and create the connections in a signal generic way.

    Thank you for any help.

    Kind Regards,
    Sy

    JonBJ 1 Reply Last reply
    -1
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      You're using words like "templates", "map" and "dynamic" and I'm not sure I follow what you're trying to do. C++ is a statically typed language. Templates are static constructs with types evaluated at compile time. Same with maps. There's nothing dynamic about either one or the other.

      There are two types of syntax for connects in Qt - one uses function pointers and the other normalized string signatures generated at compile time in the meta objects. Both of those are also static constructs.

      Can you maybe provide an example or pseudo code of what you're trying to achieve?

      SPlattenS 1 Reply Last reply
      1
      • SPlattenS SPlatten

        I purchased a new book “C++ Templates The Complete Guide SECOND EDITION”.

        ISBN-13: 978-0-321-71412-1
        ISBN-10: 0-321-71412-1

        I’m reading it and trying to digest everything. What I am ultimately aiming for is a way to create a generic and dynamic map capable of storing the information for any QT control or derived control and it’s signals. Where each single entry in the map would contain a pointer or reference to the control and the signal associated with the entry.

        Of course the signal prototypes can be very different and it’s this information I’m hoping to learn from this book. Is there anyone available that is very familiar with templates and QT signal prototypes that can tell me if this is possible?

        The aim is to use the maps with an iterator and create the connections in a signal generic way.

        Thank you for any help.

        JonBJ Online
        JonBJ Online
        JonB
        wrote on last edited by
        #3

        @SPlatten said in Is this possible?:

        capable of storing the information for any QT control or derived control and it’s signals.

        Qt itself stores this, by definition. You might want to see what you can leverage out of Qt's own code....

        SPlattenS 1 Reply Last reply
        0
        • Chris KawaC Chris Kawa

          You're using words like "templates", "map" and "dynamic" and I'm not sure I follow what you're trying to do. C++ is a statically typed language. Templates are static constructs with types evaluated at compile time. Same with maps. There's nothing dynamic about either one or the other.

          There are two types of syntax for connects in Qt - one uses function pointers and the other normalized string signatures generated at compile time in the meta objects. Both of those are also static constructs.

          Can you maybe provide an example or pseudo code of what you're trying to achieve?

          SPlattenS Offline
          SPlattenS Offline
          SPlatten
          wrote on last edited by
          #4

          @Chris-Kawa the new features of C++ allow you to do far more than it was ever originally designed to do. Take a look at this book, search for the isbn number.

          Kind Regards,
          Sy

          1 Reply Last reply
          0
          • JonBJ JonB

            @SPlatten said in Is this possible?:

            capable of storing the information for any QT control or derived control and it’s signals.

            Qt itself stores this, by definition. You might want to see what you can leverage out of Qt's own code....

            SPlattenS Offline
            SPlattenS Offline
            SPlatten
            wrote on last edited by
            #5

            @JonB , thank you, I’m currently away from home and my system not returning until tomorrow. I know there is some very clever stuff going on in the QT library, particularly with the Lambda integration.

            Kind Regards,
            Sy

            1 Reply Last reply
            0
            • mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi
              @SPlatten since you got Chris interested, try to describe what you really want to do

              char* signal = "clicked(bool)";
              char* slot = "doSomething(bool)";
              connect(ui->someButton, SIGNAL(signal), this, SLOT(slot));
              

              But with lambdas/templates.

              https://forum.qt.io/topic/116696/connect-prototype-help

              SPlattenS 1 Reply Last reply
              0
              • mrjjM mrjj

                Hi
                @SPlatten since you got Chris interested, try to describe what you really want to do

                char* signal = "clicked(bool)";
                char* slot = "doSomething(bool)";
                connect(ui->someButton, SIGNAL(signal), this, SLOT(slot));
                

                But with lambdas/templates.

                https://forum.qt.io/topic/116696/connect-prototype-help

                SPlattenS Offline
                SPlattenS Offline
                SPlatten
                wrote on last edited by
                #7

                @mrjj thank you, I’ll be able to do this tomorrow, away at the moment and all my responses are from iPhone.

                Kind Regards,
                Sy

                Chris KawaC 1 Reply Last reply
                0
                • SPlattenS SPlatten

                  @mrjj thank you, I’ll be able to do this tomorrow, away at the moment and all my responses are from iPhone.

                  Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by Chris Kawa
                  #8

                  @SPlatten I'm obviously not gonna buy and read entire book before responding, but while I'm quite aware that there's a lot of clever trickery possible with C++ it's still a statically typed language and everything Qt does with connects is very much static as well.

                  Now that I've looked into the other thread @mrjj mentioned I feel like you're not seeing the problem. Again - C++ is statically typed. Every expression's type is evaluated at compile time and then results in a series of hardcoded instruction bytes in your executable. You can't make up connections between arbitrary functions at runtime. Their signature needs to be known at compile time so that an instantiation of the connect template exists for that specific signature. Connects are templates instantiated statically at compile time so in order to use them at runtime you have to instantiate them with concrete function pointer types as arguments or use the string based syntax. The string based syntax looks up the associated signal and slot function pointers and connects those but that also is based on a static types of those functions.

                  It seems like you think lambdas are somehow solving the dynamic aspect you're going after but they are not. They are too a static typed functors with signatures known at compile time. If all you want to do is connect a bunch of signals with different signatures to a single function then that's easy, but that doesn't give you much really:

                      struct SenderData { QObject* obj; const char* signal; };
                      std::vector<SenderData> sender_data;
                  
                      //Register stuff.
                      //You could read the object names and signal signatures from some file I guess, if you want to, and look up the objects by name
                      sender_data.push_back({ somePushButton, SIGNAL(clicked()) });
                      sender_data.push_back({ someCheckBox, SIGNAL(stateChanged(int)) });
                  
                      // connect everything to single common slot in some object
                      for (SenderData& sd : sender_data)
                          QObject::connect(sd.obj, sd.signal, someObject, SLOT(commonSlotInSomeObjectClass()));
                  

                  That's kinda pointless though as the single slot doesn't have any useful context (apart from the sender() method that's kinda useless here).

                  SPlattenS JKSHJ 2 Replies Last reply
                  6
                  • Chris KawaC Chris Kawa

                    @SPlatten I'm obviously not gonna buy and read entire book before responding, but while I'm quite aware that there's a lot of clever trickery possible with C++ it's still a statically typed language and everything Qt does with connects is very much static as well.

                    Now that I've looked into the other thread @mrjj mentioned I feel like you're not seeing the problem. Again - C++ is statically typed. Every expression's type is evaluated at compile time and then results in a series of hardcoded instruction bytes in your executable. You can't make up connections between arbitrary functions at runtime. Their signature needs to be known at compile time so that an instantiation of the connect template exists for that specific signature. Connects are templates instantiated statically at compile time so in order to use them at runtime you have to instantiate them with concrete function pointer types as arguments or use the string based syntax. The string based syntax looks up the associated signal and slot function pointers and connects those but that also is based on a static types of those functions.

                    It seems like you think lambdas are somehow solving the dynamic aspect you're going after but they are not. They are too a static typed functors with signatures known at compile time. If all you want to do is connect a bunch of signals with different signatures to a single function then that's easy, but that doesn't give you much really:

                        struct SenderData { QObject* obj; const char* signal; };
                        std::vector<SenderData> sender_data;
                    
                        //Register stuff.
                        //You could read the object names and signal signatures from some file I guess, if you want to, and look up the objects by name
                        sender_data.push_back({ somePushButton, SIGNAL(clicked()) });
                        sender_data.push_back({ someCheckBox, SIGNAL(stateChanged(int)) });
                    
                        // connect everything to single common slot in some object
                        for (SenderData& sd : sender_data)
                            QObject::connect(sd.obj, sd.signal, someObject, SLOT(commonSlotInSomeObjectClass()));
                    

                    That's kinda pointless though as the single slot doesn't have any useful context (apart from the sender() method that's kinda useless here).

                    SPlattenS Offline
                    SPlattenS Offline
                    SPlatten
                    wrote on last edited by
                    #9

                    @Chris-Kawa , thank you Chris I’ll respond properly tomorrow.

                    Kind Regards,
                    Sy

                    1 Reply Last reply
                    0
                    • Chris KawaC Chris Kawa

                      @SPlatten I'm obviously not gonna buy and read entire book before responding, but while I'm quite aware that there's a lot of clever trickery possible with C++ it's still a statically typed language and everything Qt does with connects is very much static as well.

                      Now that I've looked into the other thread @mrjj mentioned I feel like you're not seeing the problem. Again - C++ is statically typed. Every expression's type is evaluated at compile time and then results in a series of hardcoded instruction bytes in your executable. You can't make up connections between arbitrary functions at runtime. Their signature needs to be known at compile time so that an instantiation of the connect template exists for that specific signature. Connects are templates instantiated statically at compile time so in order to use them at runtime you have to instantiate them with concrete function pointer types as arguments or use the string based syntax. The string based syntax looks up the associated signal and slot function pointers and connects those but that also is based on a static types of those functions.

                      It seems like you think lambdas are somehow solving the dynamic aspect you're going after but they are not. They are too a static typed functors with signatures known at compile time. If all you want to do is connect a bunch of signals with different signatures to a single function then that's easy, but that doesn't give you much really:

                          struct SenderData { QObject* obj; const char* signal; };
                          std::vector<SenderData> sender_data;
                      
                          //Register stuff.
                          //You could read the object names and signal signatures from some file I guess, if you want to, and look up the objects by name
                          sender_data.push_back({ somePushButton, SIGNAL(clicked()) });
                          sender_data.push_back({ someCheckBox, SIGNAL(stateChanged(int)) });
                      
                          // connect everything to single common slot in some object
                          for (SenderData& sd : sender_data)
                              QObject::connect(sd.obj, sd.signal, someObject, SLOT(commonSlotInSomeObjectClass()));
                      

                      That's kinda pointless though as the single slot doesn't have any useful context (apart from the sender() method that's kinda useless here).

                      JKSHJ Offline
                      JKSHJ Offline
                      JKSH
                      Moderators
                      wrote on last edited by
                      #10

                      @Chris-Kawa said in Is this possible?:

                      You can't make up connections between arbitrary functions at runtime. Their signature needs to be known at compile time so that an instantiation of the connect template exists for that specific signature.

                      The older-style connect()s work by doing string comparisons, so the evaluation of the signature occurs at run-time. This allows connections to be made between C++ and QML (where the latter is not pre-compiled): https://doc.qt.io/qt-5/signalsandslots-syntaxes.html#connecting-c-objects-to-qml-objects

                      QMetaObjectBuilder even lets you create new signals/slots/properties at runtime. It is officially private API, but it shows what's possible: https://www.qtdeveloperdays.com/sites/default/files/QtDevDays2014US-DIY-moc.pdf

                      Still, I agree with you on your other comments about the "static"-ness of C++.

                      @SPlatten said in Is this possible?:

                      What I am ultimately aiming for is a way to create a generic and dynamic map capable of storing the information for any QT control or derived control and it’s signals. Where each single entry in the map would contain a pointer or reference to the control and the signal associated with the entry.

                      How do you plan to use this map?

                      Is there anyone available that is very familiar with templates and QT signal prototypes that can tell me if this is possible?

                      It is indeed possible to create a database of QObjects and signals, but templates can't contribute anything to it.

                      Start with QMetaObject::methodCount() and QMetaObject::method(): https://doc.qt.io/qt-5/qmetaobject.html#method

                      Code

                      QWidget w;
                      for (int i = 0; i < w.metaObject()->methodCount(); ++i)
                      {
                          auto met = w.metaObject()->method(i);
                          qDebug() << met.methodType() << met.methodSignature();
                      }
                      
                      

                      Output

                      1 "destroyed(QObject*)"
                      1 "destroyed()"
                      1 "objectNameChanged(QString)"
                      2 "deleteLater()"
                      2 "_q_reregisterTimers(void*)"
                      1 "windowTitleChanged(QString)"
                      1 "windowIconChanged(QIcon)"
                      1 "windowIconTextChanged(QString)"
                      1 "customContextMenuRequested(QPoint)"
                      2 "setEnabled(bool)"
                      2 "setDisabled(bool)"
                      2 "setWindowModified(bool)"
                      2 "setWindowTitle(QString)"
                      2 "setStyleSheet(QString)"
                      2 "setFocus()"
                      2 "update()"
                      2 "repaint()"
                      2 "setVisible(bool)"
                      2 "setHidden(bool)"
                      2 "show()"
                      2 "hide()"
                      2 "showMinimized()"
                      2 "showMaximized()"
                      2 "showFullScreen()"
                      2 "showNormal()"
                      2 "close()"
                      2 "raise()"
                      2 "lower()"
                      2 "updateMicroFocus()"
                      2 "_q_showIfNotHidden()"
                      0 "grab(QRect)"
                      0 "grab()"
                      

                      See also QMetaMethod::methodType(): https://doc.qt.io/qt-5/qmetamethod.html#MethodType-enum

                      0 = QMetaMethod::Method
                      1 = QMetaMethod::Signal
                      2 = QMetaMethod::Slot

                      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                      1 Reply Last reply
                      5
                      • Chris KawaC Offline
                        Chris KawaC Offline
                        Chris Kawa
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        @JKSH said:

                        QMetaObjectBuilder even lets you create new signals/slots/properties at runtime. It is officially private API, but it shows what's possible:

                        I think you misunderstood what I was trying to convey. You can create connections at runtime. You can enumerate methods etc. but those are all operations on pre-existing, pre-compiled static data embedded in the executable (meta objects or otherwise). You can't create a new type at runtime. You can't dynamically invent a function/lambda. You can only work with what's already there and was known statically.
                        So yeah, you can pre-register a set of types, expose them to whatever system you're creating and operate on that data at runtime. But you can't create new types or function signatures at runtime. There's no "eval()" in C++ like in javascript (unless you actually add a compiler to your program and create and load shared libraries, which would probably spook all existing antivirus software out there).

                        1 Reply Last reply
                        2
                        • SPlattenS Offline
                          SPlattenS Offline
                          SPlatten
                          wrote on last edited by
                          #12

                          @JKSH said in Is this possible?:

                          QWidget w;
                          for (int i = 0; i < w.metaObject()->methodCount(); ++i)
                          {
                          auto met = w.metaObject()->method(i);
                          qDebug() << met.methodType() << met.methodSignature();
                          }

                          Ok, my application is intended to be as generic as possible. The application will be an engine that will read the application configuration in from XML. The XML specifies what widgets are to be included and signals from a widget can be subscribed to by anything in the XML, sockets are in JavaScript. I already have a framework working where signals in the C++ engine are connected to the slots in JavaScript. My intention is to reduce and simplify the current code that currently connects signals to slots where I have a single connect for each signal and slot.

                          What I want to do is almost exactly what has been posted here, produce a map of available signals then connect all these signals to a single slot in C++ which will package up the signal content and parameters into an object which is then emitted in a generic signal that all JavaScript slots can subscribe to.

                          If there is any clarification or if I have been vague please ask.

                          Kind Regards,
                          Sy

                          jsulmJ 1 Reply Last reply
                          0
                          • SPlattenS SPlatten

                            @JKSH said in Is this possible?:

                            QWidget w;
                            for (int i = 0; i < w.metaObject()->methodCount(); ++i)
                            {
                            auto met = w.metaObject()->method(i);
                            qDebug() << met.methodType() << met.methodSignature();
                            }

                            Ok, my application is intended to be as generic as possible. The application will be an engine that will read the application configuration in from XML. The XML specifies what widgets are to be included and signals from a widget can be subscribed to by anything in the XML, sockets are in JavaScript. I already have a framework working where signals in the C++ engine are connected to the slots in JavaScript. My intention is to reduce and simplify the current code that currently connects signals to slots where I have a single connect for each signal and slot.

                            What I want to do is almost exactly what has been posted here, produce a map of available signals then connect all these signals to a single slot in C++ which will package up the signal content and parameters into an object which is then emitted in a generic signal that all JavaScript slots can subscribe to.

                            If there is any clarification or if I have been vague please ask.

                            jsulmJ Offline
                            jsulmJ Offline
                            jsulm
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            @SPlatten said in Is this possible?:

                            produce a map of available signals then connect all these signals to a single slot in C++

                            How are you going to handle different parameters of all these different signals with just one slot?

                            https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            2
                            • SPlattenS Offline
                              SPlattenS Offline
                              SPlatten
                              wrote on last edited by
                              #14

                              @jsulm , I don't think this is an issued when connecting a C++ signal to a Lambda slot.

                              Kind Regards,
                              Sy

                              JonBJ 1 Reply Last reply
                              0
                              • SPlattenS SPlatten

                                @jsulm , I don't think this is an issued when connecting a C++ signal to a Lambda slot.

                                JonBJ Online
                                JonBJ Online
                                JonB
                                wrote on last edited by
                                #15

                                @SPlatten
                                But we have said before (read above): using a lambda is not relevant to solving the issue of parameters & types. You seem to think lambdas will avoid the issue which would be present if you have signal/slot functions, and we are saying that is not the case, the issue remains....

                                1 Reply Last reply
                                0
                                • SPlattenS Offline
                                  SPlattenS Offline
                                  SPlatten
                                  wrote on last edited by
                                  #16

                                  I've already connected a C++ signal to a Lambda slot and whilst there are rules about slots having to match the signal parameters in C++, this is not the case when connecting a C++ signal to a Lambda slot. I've already done this and it works, which is why my request was for a way of creating a generic map of signals that I can iterate through and connect them all up to a single Lambda slot.

                                  Kind Regards,
                                  Sy

                                  JonBJ 1 Reply Last reply
                                  0
                                  • SPlattenS SPlatten

                                    I've already connected a C++ signal to a Lambda slot and whilst there are rules about slots having to match the signal parameters in C++, this is not the case when connecting a C++ signal to a Lambda slot. I've already done this and it works, which is why my request was for a way of creating a generic map of signals that I can iterate through and connect them all up to a single Lambda slot.

                                    JonBJ Online
                                    JonBJ Online
                                    JonB
                                    wrote on last edited by
                                    #17

                                    @SPlatten said in Is this possible?:

                                    whilst there are rules about slots having to match the signal parameters in C++, this is not the case when connecting a C++ signal to a Lambda slot.

                                    That's not what I find. I guess we'll have to beg to differ.

                                    1 Reply Last reply
                                    0
                                    • SPlattenS Offline
                                      SPlattenS Offline
                                      SPlatten
                                      wrote on last edited by
                                      #18

                                      @JonB, actually, sorry I forgot, what I actually did was add an additional signal. The control signals are connected to a slot that has matching parameters this is all in C++, that slot then creates an object that has everything in it required to identify the originating slot, finally a generic signal is emitted with the new object and its this that is connected to Lambda.

                                      So going back, what I really need to (if possible) dynamically create the repeater slot for each signal, which means I wouldn't have to code up and think of every possibly signal up front.

                                      Kind Regards,
                                      Sy

                                      JonBJ 1 Reply Last reply
                                      0
                                      • SPlattenS SPlatten

                                        @JonB, actually, sorry I forgot, what I actually did was add an additional signal. The control signals are connected to a slot that has matching parameters this is all in C++, that slot then creates an object that has everything in it required to identify the originating slot, finally a generic signal is emitted with the new object and its this that is connected to Lambda.

                                        So going back, what I really need to (if possible) dynamically create the repeater slot for each signal, which means I wouldn't have to code up and think of every possibly signal up front.

                                        JonBJ Online
                                        JonBJ Online
                                        JonB
                                        wrote on last edited by JonB
                                        #19

                                        @SPlatten said in Is this possible?:

                                        , which means I wouldn't have to code up and think of every possibly signal up front.

                                        But I think that's precisely what the discussion here is all about! C++ is statically typed, and you cannot think of every possible signal which is what you need at compile-time, and that is the issue! And I/others do not see how using lambdas would obviate that, lambdas are still subject to compile-type type checking, for both their parameters and the methods they might call....

                                        Perhaps we should leave it at that and you see how you get on, because we're not getting very far with a "You say, I say" ... :)

                                        1 Reply Last reply
                                        0
                                        • SPlattenS Offline
                                          SPlattenS Offline
                                          SPlatten
                                          wrote on last edited by
                                          #20

                                          @JonB , the reason for Lambda is purely to provide an interface between the C++ and the JavaScript. Using a repeater signal allows me to use the same signal out of the repeater with parameters that will never change, the receiving signal which fires the repeater is the one that will have the differences.

                                          Please don't get me wrong, I'm not arguing with you, I was under the impression that what I'm trying to achieve is actually possible.

                                          Kind Regards,
                                          Sy

                                          jsulmJ 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