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. tr() with binding: how to get the calling classname to a function,

tr() with binding: how to get the calling classname to a function,

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 3 Posters 600 Views
  • 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.
  • T Offline
    T Offline
    themts
    wrote on last edited by
    #1

    Hey guys,

    I want to be able to switch my application-language on runtime to another language.
    The QML part works out of the box via retranslate() but I have several c++ data-models which are not updating.

    To keep things clean, I would like to create a method like tr() which takes 3 parameters, which I could call like this:

    trExt("myText", &targetObject, &TargetClass::setName);
    

    So internally something like this should happen (Attention this is NOT a working function it is just a draft of an idea):

    template <typename Func>
    void trExt(const QString &text, typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func slot) {
      QMetaObject::invokeMethod(receiver, slot, Q_ARG(QString, text);
    
      connect(&languageChanger(), &LanguageChanger::languageChanged, [&]() {  
        QString newText = QCoreApplication::translate(char* NAME OF CALLING CLASS, text);
        QMetaObject::invokeMethod(receiver, slot, Q_ARG(QString, newText);
      }
    }
    

    To be able to use QCoreApplication::translate() correctly I have to forward the calling classname somehow as a context.
    I have no idea how this can be done. Somehow the default tr() function is able to do it but I don't know how (magic ? ).
    I would also like to avoid passing the calling context-name as an additional parameter.

    Any idea?
    THX

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      It's not QObject::tr() but <YourObjectWithQ_OBJECT_macro>::tr() and therefor the class name is known and can be passed to QCoreApplication::translate()

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      T 1 Reply Last reply
      2
      • Christian EhrlicherC Christian Ehrlicher

        It's not QObject::tr() but <YourObjectWithQ_OBJECT_macro>::tr() and therefor the class name is known and can be passed to QCoreApplication::translate()

        T Offline
        T Offline
        themts
        wrote on last edited by
        #3

        @Christian-Ehrlicher ahhh, ok. That makes sense.
        So the best approach would be to put it in a macro.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi,

          Out of curiosity, why do you want to translate a class name ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          Christian EhrlicherC 1 Reply Last reply
          0
          • T Offline
            T Offline
            themts
            wrote on last edited by
            #5

            I don’t want to translate the classname.
            I want to connect a translation to a slot.
            Normally I have situations like:
            object.setName(tr(„super english text“))

            Problem is that in this situations a retranslate wouldn’t trigger a new „setName“.

            So my idea is to have a function
            trExt("super english text", &object, &Class::setName);

            That way it would call setName and create a connection to a languageChanged event which resets the parameter to the new translation every time

            1 Reply Last reply
            0
            • SGaistS SGaist

              Hi,

              Out of curiosity, why do you want to translate a class name ?

              Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @SGaist said in tr() with binding: how to get the calling classname to a function,:

              why do you want to translate a class name ?

              No, he wants not translate the class name but mimic tr() which in fact calls QCoreApplication::translate() where the context is the class name.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              1 Reply Last reply
              0
              • T Offline
                T Offline
                themts
                wrote on last edited by
                #7

                one additional question:
                how do I invoke a methode without the name? Or how do I get the name

                I have this:

                #define N_TRANSLATE\
                template <typename Func>\
                void trExt(const QString &text, typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func slot) {\
                    QMetaObject::invokeMethod(receiver, "HERE I NEED A NAME", Q_ARG(QString, text));\
                

                To use "invokeMethod" I need the slotname.
                I would like to pass the slot as shown. Can I get the name somehow? Or is there another way of invoking this slot?

                1 Reply Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @themts said in tr() with binding: how to get the calling classname to a function,:

                  how do I invoke a methode without the name?

                  I don't understand what you mean - when you want to call a function you should know it's name, or?

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    themts
                    wrote on last edited by
                    #9

                    That is my function:

                        template <typename Func>
                            void trExt(const char *text, typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func slot) {   
                                const char* className = metaObject()->className();
                          
                                //A) CALL "Func slot" HERE AND PASS tr(text) as parameter to "Func slot"
                        
                                connect(&_langLoader(), &NLanguageLoader::languageChanged, [className, text, slot]() {  
                                    QString newText = QCoreApplication::translate(className, text);  
                                    //B) INVOKE METHOD "Func slot" HERE AND PASS newText as parameter to "Func slot" like QMetaObject::invokeMethod to be sure it is threadsafe  
                                });
                        
                            }
                    

                    I' missing two things now:
                    A) how do i call the slot (parameter 3) of the receiver? I would have exptected to use only slot(tr(text)) but compiler tells me "there is no function that takes 1 argument". Just from c++ side I would have expected that it works.

                    B) as the thread-context might be different I would like to use the QMetaObject::invokeMethod function as it will send it to the event loop if the target is in another context.

                    1 Reply Last reply
                    0
                    • T Offline
                      T Offline
                      themts
                      wrote on last edited by themts
                      #10

                      I just checked to code of QTimer::singleShot(), which does exactly what I need.
                      I just have to pass 0ms.

                      EDIT: not completely. A singleShot does not accept arguments. It's using QMetaObject::InvokeMethodImpl() which does not take arguments...

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        themts
                        wrote on last edited by
                        #11

                        ok, I will give up...

                        I will do it like this.
                        Instead of calling

                        trExt("super english text", &object, &Class::setName);"
                        

                        I will call

                        trExt("super english text", &object, "setName");
                        

                        I would have prefered the first way but I'm not that deep in the Qt internals.

                            void trExt(const char *text, QObject *receiver, const char *member) {
                                QMetaObject::invokeMethod(receiver, member, Q_ARG(QString, tr(text)));
                        
                                const char* className = metaObject()->className();
                                connect(&_langLoader(), &NLanguageLoader::languageChanged, [className, text, receiver, member]() {
                                    QString newText = QCoreApplication::translate(className, text);
                                    QMetaObject::invokeMethod(receiver, member, Q_ARG(QString, newText));
                                });
                            }
                        
                        1 Reply Last reply
                        1
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          What about implementing the changeEvent method to handle your object's translatable strings like shown in the dynamic translation part of the internationalization documentation ?

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          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