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. Emit signal from C++ to QML without any parameters
Forum Updated to NodeBB v4.3 + New Features

Emit signal from C++ to QML without any parameters

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlqt quickc++
4 Posts 2 Posters 963 Views 1 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.
  • B Offline
    B Offline
    bwylegly
    wrote on last edited by bwylegly
    #1

    Hi.

    Im trying to implement logging mechanism into my app.

    What I've done so far is created LoginView.qml file:

    // LoginView.qml
    
    Item {
    
        id: loginView
        signal loginClicked(string textField_usr, string textField_pwd);
    
        objectName: "loginView"
    // ATTEMPTS SO FAR
    //   Connections {
    //       target: MasterController.ui_loginController
    //       onLoginSuccessful: MasterView.contentFrame.replace("qrc:/views/DashboardView.qml")
    //        onLoginFailed: console.log("login failed")
    //    }
    
    //            LoginController {
    //                id: loginController
    //                onLoginSuccessful: MasterView.contentFrame.replace("qrc:/views/DashboardView.qml")
    //                onLoginFailed: console.log("login failed")
    //            }
    
        GroupBox {
           /* Some styling, including  TextFields etc*/
    
            Button {
                id: button
                objectName: "proceed_button"
            
                /*more styling*/
    
                onClicked: {
                    loginClicked(username_textField.text, password_textInput.text)
                }
            }
        }
    }
    
    

    LoginView.qml gets loaded by MasterView.qml onCompleted()

    Window {
        /*Some stuff - nothing related to login process*/
    
       StackView{
            id: contentFrame
            /*...*/
    
            initialItem: Qt.resolvedUrl("qrc:/views/SplashView.qml")
        }
    
    
        Component.onCompleted: {
           contentFrame.replace("qrc:/views/LoginView.qml")
    
        }
    }
    
    

    With that in place, I have created LoginViewController class:

    namespace cms{
    namespace controllers{
    
    class CMSLIBSHARED_EXPORT LoginViewController : public QObject{
        Q_OBJECT
    
    private:
    
        QObject* loginButton {nullptr};
    
    public:
    
    
        explicit LoginViewController(QObject* _parent = nullptr) : QObject(_parent) {}
    
        LoginViewController(QQmlApplicationEngine* engine){
            QObject* loginView = engine->rootObjects().first()->findChild<QObject*>("loginView");
        
            loginButton = loginView->findChild<QObject*>("proceed_button");
    
            QObject::connect(loginView, SIGNAL(loginClicked(QString, QString)), this, SLOT(loginButtonClicked(QString, QString)));
    
        }
    
    
    public slots:
        void loginButtonClicked(QString user, QString pwd);
    
    signals:
        void loginSuccessful();
        void loginFailed();
    };
    
    }
    }
    

    LoginViewController is a member of MasterController, which I export as MasterController's Q_PROPERTY:

    Q_OBJECT
    Q_PROPERTY(cms::controllers::LoginViewController* ui_loginController READ loginController CONSTANT)
    
    public:
    LoginViewController* loginController();
    

    Here's a part that im not really sure of.
    I registered my LoginViewController class as QML type inside main.cpp

    qmlRegisterType<cms::controllers::MasterController>("CMS", 1, 0, "MasterController");
    
    //newly added
    qmlRegisterType<cms::controllers::LoginViewController>("CMS", 1, 0, "LoginController");
    

    Everything works fine when I emit the signal from Qml into C++, login function works as intended, but I am getting stucked when i try to emit different signals depending on login method output.

    After signal from Qml button gets emitted, it triggers login function

    void LoginViewController::loginButtonClicked(QString user, QString pwd)
    {
            std::cerr << "loginButtonClicked " << std::endl;
            if(cms::administration::Clinic::login(user.toStdString(), pwd.toStdString())){
                loginSuccessful(); return;
            }
            loginFailed();
    }
    

    As you can see, here I'd like to emit signal into QML. I came by different posts, different documentation pages, and i feel like left with too many tools to work with.

    Could somebody guide me, on how should I emit and handle the signal inside QML?
    Moreover, if there's any "better" or more suitable solution for this mechanism, I'd be happy to hear about it.

    Best regards!

    1 Reply Last reply
    0
    • CharbyC Offline
      CharbyC Offline
      Charby
      wrote on last edited by
      #2

      I would do the following :

      • instead of registering your LoginViewController, I would simply create a context property for your controller instance. Something like :
      cms::controllers::LoginViewController controler;
      QQmlApplicationEngine engine;
      engine->rootContext()->setContextProperty("loginCtrl", this);
      
      
      • instead of retrieving the login button from c++ and create the connection etc...simply call loginButtonClicked on the controller property in the button onClicked handler.
      Button {
                  id: button
                  objectName: "proceed_button"
              
                  /*more styling*/
      
                  onClicked: loginCtrl.loginButtonClicked(username_textField.text, password_textInput.text)
              }
      
      • use a "Connection" item in QML with the controller property as target to react to loginSuccess/loginFailure
      Connection{
         target: loginCtrl
         onLoginSuccessful: {}
         onLoginFailed:{}
      }
      
      1 Reply Last reply
      0
      • B Offline
        B Offline
        bwylegly
        wrote on last edited by
        #3

        Hi @Charby, thanks for your feedback.
        Your idea works just fine, but im getting those errors, which I cannot get rid of.

        I have added Connection item you have mentioned about:

        • inside LoginView.qml
        Connections {
                target: loginController
                onLoginSuccessful : { masterView.contentFrame.replace("qrc:/views/DashboardView.qml") }
                onLoginFailed: {console.log("Failed") }
            }
        
        • inside main.cpp
            cms::controllers::MasterController masterController;
        
            QQmlApplicationEngine engine;
            engine.addImportPath("qrc:/");
        
            engine.rootContext()->setContextProperty("masterController", &masterController);
        
            engine.load(QUrl(QStringLiteral("qrc:/views/MasterView.qml")));
        
            cms::controllers::LoginViewController lvc(&engine);
            engine.rootContext()->setContextProperty("loginController", &lvc);
        

        But it produces following errors:

        qrc:/views/LoginView.qml:13:5: QML Connections: Cannot assign to non-existent property "onLoginFailed"
        qrc:/views/LoginView.qml:13:5: QML Connections: Cannot assign to non-existent property "onLoginSuccessful"
        qrc:/views/LoginView.qml:14: ReferenceError: loginController is not defined
        

        Any ideas?

        1 Reply Last reply
        0
        • CharbyC Offline
          CharbyC Offline
          Charby
          wrote on last edited by
          #4

          lvc needs to be defined as a context property before the qml engine call of load

          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