Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to get handle to QQmlApplicationEngine from inside c++ to call retranslate for QML

How to get handle to QQmlApplicationEngine from inside c++ to call retranslate for QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
8 Posts 4 Posters 791 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.
  • F Offline
    F Offline
    Flesh
    wrote on last edited by
    #1

    I have a QML app that has a Combobox I populate in c++, and what to retranslate the QML, currently I have to use setContextProperty, but I want to convert to qmlRegisterType or qmlRegisterUncreatableType after reading they might depreciate setContextProperty due to issues, but I cannot figure out a way to get a handle for QQmlApplicationEngine in main, and I cannot figure out how to initialize it in main so I can pass in the handle, making it work similar to setContextProperty, ideally I would initialize the class in main passing in the handle to QQmlApplicationEngine if I cannot get that handle internally, qApp seems to be the only gateway but I cannot find a function to call, and then pass in the initialize function, it seems that qmlRegisterUncreatableType should work for this, but I could not get it to work, nor can I find an example of doing this, and I have been searching the internet for a week now, and seem to be stuck here, I use the qApp->installTranslator which works for Widgets, but does not retranslate QML, I have to call retranslate() on the handle for QQmlApplicationEngine, it seems that you cannot ininalize a function and use either qmlRegisterType or qmlRegisterUncreatableType like you do setContextProperty, unless I am missing something, I have even search GitHub trying to find anyone doing this, but no luck so far.

    Thanks, Flesh

    Jeffrey Scott Flesher PhD
    http//LightWizzard.com/

    eyllanescE 1 Reply Last reply
    0
    • F Flesh

      I have a QML app that has a Combobox I populate in c++, and what to retranslate the QML, currently I have to use setContextProperty, but I want to convert to qmlRegisterType or qmlRegisterUncreatableType after reading they might depreciate setContextProperty due to issues, but I cannot figure out a way to get a handle for QQmlApplicationEngine in main, and I cannot figure out how to initialize it in main so I can pass in the handle, making it work similar to setContextProperty, ideally I would initialize the class in main passing in the handle to QQmlApplicationEngine if I cannot get that handle internally, qApp seems to be the only gateway but I cannot find a function to call, and then pass in the initialize function, it seems that qmlRegisterUncreatableType should work for this, but I could not get it to work, nor can I find an example of doing this, and I have been searching the internet for a week now, and seem to be stuck here, I use the qApp->installTranslator which works for Widgets, but does not retranslate QML, I have to call retranslate() on the handle for QQmlApplicationEngine, it seems that you cannot ininalize a function and use either qmlRegisterType or qmlRegisterUncreatableType like you do setContextProperty, unless I am missing something, I have even search GitHub trying to find anyone doing this, but no luck so far.

      Thanks, Flesh

      eyllanescE Offline
      eyllanescE Offline
      eyllanesc
      wrote on last edited by
      #2

      @Flesh Your question is confusing. Could you show a demo of what you have?

      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

      1 Reply Last reply
      0
      • F Offline
        F Offline
        Flesh
        wrote on last edited by
        #3

        The full source code is here:
        https://github.com/Light-Wizzard/QmlWidgetTranslator

        I will show you the main parts, this is how I do it now using setContextProperty, note that there has been talk about deprecating it if they have not already done so, but most people agree it is not the best way to do it do to performance issues

        This is my current way of doing this with setContextProperty

        class MyLanguageModel : public QAbstractListModel
        {
            Q_OBJECT
            ...
            void setQmlEngine(QQmlEngine &thisQmlEngine)
            {
                myEngine = thisQmlEngine;
            }
            Q_INVOKABLE bool setLanguage(const QString &thisLanguageName)
            {
                ...
                qApp->installTranslator(myTranslator);
                myEngine.retranslate();
            }    
            QQmlEngine &myEngine;
        };
        

        The QML does not matter in this case since there is no way of knowing QQmlEngine, so I am at a loss unless I missed something, how can I get assess to QQmlEngine inside a class if I do not use setContextProperty since I have to use it to call retranslate when I set the Language, I hope this made it clearer, unless one of the 3 ways of registering a class allows you to do this, I could not find a way to do that, it seems all these methods do not allow you to do this, unless I am missing something.

        int main(int argc, char *argv[])
        {
            ...
            QQmlApplicationEngine theEngine;
        
            MyLanguageModel *theLanguageModel = new MyLanguageModel(theEngine, qApp);
            theContext->setContextProperty("myLanguageModel", theLanguageModel);
        
            // setContextProperty allow me to set theEngine, but this method does not
            // Instantiable which does not allow me to pass in theEngine
            qmlRegisterType<MyLanguageModel>("Qt.LanguageModel", 1, 0, "MyLanguageModel");
            // Uncreatable which also does not allow me to pass theEngine
            qmlRegisterUncreatableType<Qt.LanguageModel>("myLanguageModel", 1, 0, "MyLanguageModel");
            // Anonymous which also does not allow me to pass theEngine
            qmlRegisterAnonymousType<Qt.LanguageModel>("myLanguageModel", 1, 0, "MyLanguageModel");
            // Singleton which has possiblities but I have not found a way to pass in theEngine
            qmlRegisterSingletonType("Qt.LanguageModel", 1, 0, "MyLanguageModel", myLanguageModelSingletontype_provider);
            ...
        }
        
        static QJSValue myLanguageModelSingletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
        {
            MyLanguageModel *theLanguageModel = new MyLanguageModel(engine, qApp);
            // This is where I get lost, this has to return a property, 
            // and I have many types of data and models, 
            // this is just an example I found online, 
            // I could not figure out how to use this method other than for properties
            QJSValue example = scriptEngine->newObject();
            example.setProperty("propertyInt", 80);
            example.setProperty("propertyString","testString");
            example.setProperty("propertyDate",QDateTime::currentDateTime().toString());
            return example;
        }
        

        The Singleton is the closes I can come to figuring out how to do this, but I am lost with how to set a data model using a property.

        I have a few things going on in this class that I can move to another class, I have a data model, and other data that I want to be translated in this class, so it needs to handle a List for a Combobox, and it does string translations in the c++ class, so I need a way for it to work like setContextProperty, so I need to find a way to get theEngine in main set in the class I register or find a way to pass it in, I hope that was clear, this is hard for me to explain for some reason.

        Thanks, Flesh

        Jeffrey Scott Flesher PhD
        http//LightWizzard.com/

        kshegunovK 1 Reply Last reply
        0
        • F Flesh

          The full source code is here:
          https://github.com/Light-Wizzard/QmlWidgetTranslator

          I will show you the main parts, this is how I do it now using setContextProperty, note that there has been talk about deprecating it if they have not already done so, but most people agree it is not the best way to do it do to performance issues

          This is my current way of doing this with setContextProperty

          class MyLanguageModel : public QAbstractListModel
          {
              Q_OBJECT
              ...
              void setQmlEngine(QQmlEngine &thisQmlEngine)
              {
                  myEngine = thisQmlEngine;
              }
              Q_INVOKABLE bool setLanguage(const QString &thisLanguageName)
              {
                  ...
                  qApp->installTranslator(myTranslator);
                  myEngine.retranslate();
              }    
              QQmlEngine &myEngine;
          };
          

          The QML does not matter in this case since there is no way of knowing QQmlEngine, so I am at a loss unless I missed something, how can I get assess to QQmlEngine inside a class if I do not use setContextProperty since I have to use it to call retranslate when I set the Language, I hope this made it clearer, unless one of the 3 ways of registering a class allows you to do this, I could not find a way to do that, it seems all these methods do not allow you to do this, unless I am missing something.

          int main(int argc, char *argv[])
          {
              ...
              QQmlApplicationEngine theEngine;
          
              MyLanguageModel *theLanguageModel = new MyLanguageModel(theEngine, qApp);
              theContext->setContextProperty("myLanguageModel", theLanguageModel);
          
              // setContextProperty allow me to set theEngine, but this method does not
              // Instantiable which does not allow me to pass in theEngine
              qmlRegisterType<MyLanguageModel>("Qt.LanguageModel", 1, 0, "MyLanguageModel");
              // Uncreatable which also does not allow me to pass theEngine
              qmlRegisterUncreatableType<Qt.LanguageModel>("myLanguageModel", 1, 0, "MyLanguageModel");
              // Anonymous which also does not allow me to pass theEngine
              qmlRegisterAnonymousType<Qt.LanguageModel>("myLanguageModel", 1, 0, "MyLanguageModel");
              // Singleton which has possiblities but I have not found a way to pass in theEngine
              qmlRegisterSingletonType("Qt.LanguageModel", 1, 0, "MyLanguageModel", myLanguageModelSingletontype_provider);
              ...
          }
          
          static QJSValue myLanguageModelSingletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
          {
              MyLanguageModel *theLanguageModel = new MyLanguageModel(engine, qApp);
              // This is where I get lost, this has to return a property, 
              // and I have many types of data and models, 
              // this is just an example I found online, 
              // I could not figure out how to use this method other than for properties
              QJSValue example = scriptEngine->newObject();
              example.setProperty("propertyInt", 80);
              example.setProperty("propertyString","testString");
              example.setProperty("propertyDate",QDateTime::currentDateTime().toString());
              return example;
          }
          

          The Singleton is the closes I can come to figuring out how to do this, but I am lost with how to set a data model using a property.

          I have a few things going on in this class that I can move to another class, I have a data model, and other data that I want to be translated in this class, so it needs to handle a List for a Combobox, and it does string translations in the c++ class, so I need a way for it to work like setContextProperty, so I need to find a way to get theEngine in main set in the class I register or find a way to pass it in, I hope that was clear, this is hard for me to explain for some reason.

          Thanks, Flesh

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by kshegunov
          #4
          MyLanguageModel *theLanguageModel = new MyLanguageModel(theEngine, qApp);
          

          with

          QQmlEngine &myEngine;
          

          is prone to dangling references. Instantiate the model with the QML engine as a parent. Don't pass the qApp instance, it's superfluous - you can get it from anywhere.

          This isn't valid C++, you can't assign references, they can only be initialized:

          void setQmlEngine(QQmlEngine &thisQmlEngine)
          {
              myEngine = thisQmlEngine;
          }
          

          Beside the obvious I still don't get what "to pass in theEngine" means exactly. Please explain that phrase, specifically. "Pass in" to what and for what purpose? On that note, there's the Qt.uiLanguage from QML (whenever QQmlApplicationEngine is the instantiated engine, why can't you use this one?

          Read and abide by the Qt Code of Conduct

          F 1 Reply Last reply
          1
          • kshegunovK kshegunov
            MyLanguageModel *theLanguageModel = new MyLanguageModel(theEngine, qApp);
            

            with

            QQmlEngine &myEngine;
            

            is prone to dangling references. Instantiate the model with the QML engine as a parent. Don't pass the qApp instance, it's superfluous - you can get it from anywhere.

            This isn't valid C++, you can't assign references, they can only be initialized:

            void setQmlEngine(QQmlEngine &thisQmlEngine)
            {
                myEngine = thisQmlEngine;
            }
            

            Beside the obvious I still don't get what "to pass in theEngine" means exactly. Please explain that phrase, specifically. "Pass in" to what and for what purpose? On that note, there's the Qt.uiLanguage from QML (whenever QQmlApplicationEngine is the instantiated engine, why can't you use this one?

            F Offline
            F Offline
            Flesh
            wrote on last edited by
            #5

            @kshegunov In the Language model, I initialize the Engine, I made it a separate function here to keep it short, but when you change languages, you have to have a reference to the Engine to trigger retranslate, by passing in the variable reference I can access that function in the Engine, the arguments to a function or a constructor initialization in this case.

            When the QML combobox changes, its the Language Model that gets notified of the change, the only problem I have is getting the reference to the QML Engine, and all of this is a hack as I said, this is what I am trying to get away from, this is the problem with using setContextProperty instead of registering it, but as I said, without the reference to the Engine in main, I cannot trigger the retranslate function, and all the examples I can find do not show another method of getting it, besides the qmlRegisterSingletonType, which might work, I will work with it today to see how to get a Property to take a QStringList.

            To clarify, I need a reference to the Qml Engine in main, "Pass in" means by reference, meaning & as a constructor, currently, I do this as such:

            MyLanguageModel::MyLanguageModel(QQmlEngine &thisQmlEngine, QObject *parent) : 
            QAbstractListModel(parent), myEngine(thisQmlEngine)
            
            

            Singletons seem to be my answer, but I have to find a way to make it work, maybe the QObject overload instead of QJSValue.

            Jeffrey Scott Flesher PhD
            http//LightWizzard.com/

            1 Reply Last reply
            0
            • jeremy_kJ Offline
              jeremy_kJ Offline
              jeremy_k
              wrote on last edited by jeremy_k
              #6

              For objects managed by the engine, there's the C++ function qmlEngine().

              Eg:

              class LanguageModel : public MyQmlInstantiatedListModel {
                  Q_INVOKABLE void changeLanguage() {
                      if (QQmlEngine *engine = qmlEngine(this)) {
                          engine->retranslate();
                      }
                  }
              };
              

              Asking a question about code? http://eel.is/iso-c++/testcase/

              F 1 Reply Last reply
              0
              • jeremy_kJ jeremy_k

                For objects managed by the engine, there's the C++ function qmlEngine().

                Eg:

                class LanguageModel : public MyQmlInstantiatedListModel {
                    Q_INVOKABLE void changeLanguage() {
                        if (QQmlEngine *engine = qmlEngine(this)) {
                            engine->retranslate();
                        }
                    }
                };
                
                F Offline
                F Offline
                Flesh
                wrote on last edited by
                #7

                @jeremy_k That is what I need, I will test it out as soon as possible, thanks.

                Jeffrey Scott Flesher PhD
                http//LightWizzard.com/

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  Flesh
                  wrote on last edited by
                  #8

                  @jeremy_k said in How to get handle to QQmlApplicationEngine from inside c++ to call retranslate for QML:

                  if (QQmlEngine *engine = qmlEngine(this)) {
                  engine->retranslate();
                  }

                  Just need to refactor now, thanks

                  Jeffrey Scott Flesher PhD
                  http//LightWizzard.com/

                  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