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. How to use an Object of type QSqlTableModel in another function of the same class?
Forum Updated to NodeBB v4.3 + New Features

How to use an Object of type QSqlTableModel in another function of the same class?

Scheduled Pinned Locked Moved Unsolved General and Desktop
21 Posts 4 Posters 1.9k Views 4 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.
  • M Offline
    M Offline
    mooswitz
    wrote on last edited by mooswitz
    #1

    Hi People I'm new here and I formerly developed Software in RAD Studio. I started with QT Creator because I need to... Don't ask please...

    To my question: I am developing a database application and I need to use a model based TableView in a MainWindow-Class. For this to work, I decided to use the QSqlTableModel.
    I Use the following code to bring it to work - and as far as I can see - it works...

    The Database connection "DB_Connection" is already set as private "global " object in the class of MainWindow and gets the connection via a function called setDB like so:

    //mainwindow.h
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        QSqlTableModel getSQLTableModel();
        void setSQLTableModel(QSqlTableModel *model);
        void setDB(QSqlDatabase db);
        QSqlTableModel* getTableModel();
        void onOpenMainWindow();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
        QSqlTableModel *TableModel;
        QSqlDatabase DB_Connection;
    };
    
    //mainwindow.cpp
    void MainWindow::onOpenMainWindow()
    {
        QSqlTableModel *model = new QSqlTableModel;
        setSQLTableModel(model);
    
        model->setTable("mytable");
        model->setEditStrategy(QSqlTableModel::OnManualSubmit);
        model->select();
        model->setHeaderData(0, Qt::Horizontal, tr("oneOfManyColumns"));
        model->setHeader...
        .
        . -> and so on
    
        ui->view->setModel(model);
        ui->view->hideColumn(0);
    }
    
    //mainwindow.cpp
    void MainWindow::setSQLTableModel(QSqlTableModel *model)
    {
        this->TableModel = model;
    }
    
    //mainwindow.cpp
    void MainWindow::on_pushButton_clicked()
    {
        QSqlTableModel *model = TableModel;
        
        model->submitAll();    
    }
    

    It compiles without errors. Also it shows the DB-Data correctly in the tableView. I can also click it, edit, etc. BUT when i push the button it only saves the data once. After that I can still make changes in the tableView but I can't save it anymore. I don't get errors. It must have to do with the "model"-object. But I don't know how to fix that.

    So generally spoken: How can I use a button to save changes, that a user makes inside the tableView connected with the QSqlTableModel? I explicitly DON'T want it to be updated right with the change!

    Thanks in advance for your ideas and I hope someone can help me...

    EDIT: I don't usually instanciate objects with "new" but I had no other Idea how it would work...

    Greetz, mooswitz

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

      Hi and welcome to devnet,

      There are several issues with your code but one of the most important thing: you don't check that submitAll succeeds. That's the first thing you should add.

      Next thing: don't store QSqlDatabase member variables. That's not how the class shall be used and is explained in the documentation.

      Why are you creating the function local model pointer in your slot ? You can call submitAll directly on your member variable.

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

      JonBJ 1 Reply Last reply
      2
      • SGaistS SGaist

        Hi and welcome to devnet,

        There are several issues with your code but one of the most important thing: you don't check that submitAll succeeds. That's the first thing you should add.

        Next thing: don't store QSqlDatabase member variables. That's not how the class shall be used and is explained in the documentation.

        Why are you creating the function local model pointer in your slot ? You can call submitAll directly on your member variable.

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

        @SGaist said in How to use an Object of type QSqlTableModel in another function of the same class?:

        Why are you creating model in your slot ? You can call submitAll directly on your member variable.

        OP is not doing that. QSqlTableModel *model = TableModel;. So just getting a reference to the member variable.

        SGaistS 1 Reply Last reply
        0
        • JonBJ JonB

          @SGaist said in How to use an Object of type QSqlTableModel in another function of the same class?:

          Why are you creating model in your slot ? You can call submitAll directly on your member variable.

          OP is not doing that. QSqlTableModel *model = TableModel;. So just getting a reference to the member variable.

          SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by SGaist
          #4

          @JonB that's clear, I was asking why he is using that extra variable.

          Rephrased it

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

          M 1 Reply Last reply
          1
          • SGaistS SGaist

            @JonB that's clear, I was asking why he is using that extra variable.

            Rephrased it

            M Offline
            M Offline
            mooswitz
            wrote on last edited by mooswitz
            #5

            @SGaist
            First of all: thanks for your reply. So besides of that issue you mentioned, what else is wrong? - you mentioned several issues... I can only learn from it if I know what's wrong.

            To your Question: If I use the Variable

             TableModel 
            

            from inside the class I get an error that it can't be accessed. That is why I set the reference with

            model
            

            Next thing: don't store QSqlDatabase member variables. That's not how the class shall be used and is explained in the documentation.

            I understand that and I am aware of it. But I need the database connection in several Widgets. This is truly something new for me since in RAD Studio you had a very different concept of accessing the database. But apart of that I need an option to set the credentials for the database only once and still can access it in every window. I'd be indeed very happy if you'd show me a better option.

            Greetz, mooswitz

            artwawA JonBJ 2 Replies Last reply
            0
            • M mooswitz

              @SGaist
              First of all: thanks for your reply. So besides of that issue you mentioned, what else is wrong? - you mentioned several issues... I can only learn from it if I know what's wrong.

              To your Question: If I use the Variable

               TableModel 
              

              from inside the class I get an error that it can't be accessed. That is why I set the reference with

              model
              

              Next thing: don't store QSqlDatabase member variables. That's not how the class shall be used and is explained in the documentation.

              I understand that and I am aware of it. But I need the database connection in several Widgets. This is truly something new for me since in RAD Studio you had a very different concept of accessing the database. But apart of that I need an option to set the credentials for the database only once and still can access it in every window. I'd be indeed very happy if you'd show me a better option.

              Greetz, mooswitz

              artwawA Offline
              artwawA Offline
              artwaw
              wrote on last edited by artwaw
              #6

              @mooswitz

              @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

              I understand that and I am aware of it. But I need the database connection in several Widgets.

              That's why you have connection names.
              QSqlDatabase is a value class. Each time you need it just do auto db = QSqlDatabase::database() https://doc.qt.io/qt-6/qsqldatabase.html

              @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

              But apart of that I need an option to set the credentials for the database only once and still can access it in every window.

              That's how it works. You define connection with all the parameters, then can retrieve it in any part of your program with a call to database().

              For more information please re-read.

              Kind Regards,
              Artur

              M 1 Reply Last reply
              1
              • artwawA artwaw

                @mooswitz

                @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

                I understand that and I am aware of it. But I need the database connection in several Widgets.

                That's why you have connection names.
                QSqlDatabase is a value class. Each time you need it just do auto db = QSqlDatabase::database() https://doc.qt.io/qt-6/qsqldatabase.html

                @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

                But apart of that I need an option to set the credentials for the database only once and still can access it in every window.

                That's how it works. You define connection with all the parameters, then can retrieve it in any part of your program with a call to database().

                M Offline
                M Offline
                mooswitz
                wrote on last edited by mooswitz
                #7

                @artwaw
                Thanks for your answer. I read that document several times but now I understand the concept way better.

                I still have the problem, that I don't know how to securely trigger "submitAll()" from QSqlTableModel from inside another function like a button.

                The strange thing is, that it works with the code from my first post. - but only once. When I then close the window "MainWindow" while the application is still running, then I can retrigger "submitAll()" once again and for this one time it works again.

                I need a way that a user can trigger that button endless times to make as many changes as he wants...

                Also I will implement the following statement tomorrow to check if it actually worked:

                if(model.submitAll()){
                qDebug << "worked";
                }
                else{
                qDebug << "did'nt work";
                }
                

                I'll report back tomorrow.

                Greetz, mooswitz

                1 Reply Last reply
                0
                • M mooswitz

                  @SGaist
                  First of all: thanks for your reply. So besides of that issue you mentioned, what else is wrong? - you mentioned several issues... I can only learn from it if I know what's wrong.

                  To your Question: If I use the Variable

                   TableModel 
                  

                  from inside the class I get an error that it can't be accessed. That is why I set the reference with

                  model
                  

                  Next thing: don't store QSqlDatabase member variables. That's not how the class shall be used and is explained in the documentation.

                  I understand that and I am aware of it. But I need the database connection in several Widgets. This is truly something new for me since in RAD Studio you had a very different concept of accessing the database. But apart of that I need an option to set the credentials for the database only once and still can access it in every window. I'd be indeed very happy if you'd show me a better option.

                  Greetz, mooswitz

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

                  @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

                  from inside the class I get an error that it can't be accessed.

                  This does not make sense. Your code goes:

                  QSqlTableModel *model = TableModel;
                  model->submitAll();    
                  

                  So it is already "accessing member variable TableModel from within the class". So you can just go:

                  TableModel->submitAll();
                  

                  Let us know about the result of submitAll().

                  1 Reply Last reply
                  2
                  • M Offline
                    M Offline
                    mooswitz
                    wrote on last edited by mooswitz
                    #9

                    @artwaw @SGaist @JonB

                    I tried to reply here but akismet is constantly flagging my reply as spam. Therefore I posted my reply to Pastebin:
                    https://pastebin.com/e2SVXZVb

                    Here I made an error. It was meant so say:
                    "In any source-file where a database connection is needed I can now use the class DatabaseManager to call QSqlDatabase DB_Connection = DatabaseManager::instance();
                    So I can later check for isOpen(). That seems a lot better to me."

                    JonBJ SGaistS 2 Replies Last reply
                    0
                    • M mooswitz

                      @artwaw @SGaist @JonB

                      I tried to reply here but akismet is constantly flagging my reply as spam. Therefore I posted my reply to Pastebin:
                      https://pastebin.com/e2SVXZVb

                      Here I made an error. It was meant so say:
                      "In any source-file where a database connection is needed I can now use the class DatabaseManager to call QSqlDatabase DB_Connection = DatabaseManager::instance();
                      So I can later check for isOpen(). That seems a lot better to me."

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

                      @mooswitz
                      I don't know why you are getting "spam". I wouldn't normally look at pastebin or anything else external.

                      You now have

                      static QSqlDatabase db;
                      

                      as a member variable. Which goes against what the docs tell you (not) to do. Get rid of a member variable and use QSqlDatabase::database() static function per the docs.

                      M 1 Reply Last reply
                      2
                      • JonBJ JonB

                        @mooswitz
                        I don't know why you are getting "spam". I wouldn't normally look at pastebin or anything else external.

                        You now have

                        static QSqlDatabase db;
                        

                        as a member variable. Which goes against what the docs tell you (not) to do. Get rid of a member variable and use QSqlDatabase::database() static function per the docs.

                        M Offline
                        M Offline
                        mooswitz
                        wrote on last edited by
                        #11

                        @JonB

                        I got it now. I germany one would say "I was standing on the hose" I think it's best translated as: "I was drawing a blank" :D

                        I don't know what exactly was that hard for me to understand that but now I got it. So if i set the Database once in any source file by executing this:

                            QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
                            db.setHostName(DBHOSTNAME);
                            db.setDatabaseName(DBNAME);
                            db.setUserName(DBUSERNAME);
                            db.setPassword(DBPASSWORD);
                        

                        then I can get that connection always and everywhere inside my project with simply calling

                        QSqlDatabase db = QSqlDatabase::database();
                        

                        how can I make it work with several database connections? Let's say I have two different databases...

                        Would i then add them like so: ?

                            QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","MyDB1");
                            db.setHostName(DBHOSTNAME);
                            db.setDatabaseName(DBNAME);
                            db.setUserName(DBUSERNAME);
                            db.setPassword(DBPASSWORD);
                        
                            QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","MyDB2");
                            db.setHostName(DBHOSTNAME);
                            db.setDatabaseName(DBNAME);
                            db.setUserName(DBUSERNAME);
                            db.setPassword(DBPASSWORD);
                        
                        JonBJ artwawA 2 Replies Last reply
                        1
                        • M mooswitz

                          @JonB

                          I got it now. I germany one would say "I was standing on the hose" I think it's best translated as: "I was drawing a blank" :D

                          I don't know what exactly was that hard for me to understand that but now I got it. So if i set the Database once in any source file by executing this:

                              QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
                              db.setHostName(DBHOSTNAME);
                              db.setDatabaseName(DBNAME);
                              db.setUserName(DBUSERNAME);
                              db.setPassword(DBPASSWORD);
                          

                          then I can get that connection always and everywhere inside my project with simply calling

                          QSqlDatabase db = QSqlDatabase::database();
                          

                          how can I make it work with several database connections? Let's say I have two different databases...

                          Would i then add them like so: ?

                              QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","MyDB1");
                              db.setHostName(DBHOSTNAME);
                              db.setDatabaseName(DBNAME);
                              db.setUserName(DBUSERNAME);
                              db.setPassword(DBPASSWORD);
                          
                              QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","MyDB2");
                              db.setHostName(DBHOSTNAME);
                              db.setDatabaseName(DBNAME);
                              db.setUserName(DBUSERNAME);
                              db.setPassword(DBPASSWORD);
                          
                          JonBJ Online
                          JonBJ Online
                          JonB
                          wrote on last edited by JonB
                          #12

                          @mooswitz
                          Look at the docs!
                          QSqlDatabase QSqlDatabase::database(const QString &connectionName = QLatin1StringView(defaultConnection), bool open = true)

                          Returns the database connection called connectionName.

                          1 Reply Last reply
                          2
                          • M mooswitz

                            @JonB

                            I got it now. I germany one would say "I was standing on the hose" I think it's best translated as: "I was drawing a blank" :D

                            I don't know what exactly was that hard for me to understand that but now I got it. So if i set the Database once in any source file by executing this:

                                QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
                                db.setHostName(DBHOSTNAME);
                                db.setDatabaseName(DBNAME);
                                db.setUserName(DBUSERNAME);
                                db.setPassword(DBPASSWORD);
                            

                            then I can get that connection always and everywhere inside my project with simply calling

                            QSqlDatabase db = QSqlDatabase::database();
                            

                            how can I make it work with several database connections? Let's say I have two different databases...

                            Would i then add them like so: ?

                                QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","MyDB1");
                                db.setHostName(DBHOSTNAME);
                                db.setDatabaseName(DBNAME);
                                db.setUserName(DBUSERNAME);
                                db.setPassword(DBPASSWORD);
                            
                                QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","MyDB2");
                                db.setHostName(DBHOSTNAME);
                                db.setDatabaseName(DBNAME);
                                db.setUserName(DBUSERNAME);
                                db.setPassword(DBPASSWORD);
                            
                            artwawA Offline
                            artwawA Offline
                            artwaw
                            wrote on last edited by
                            #13

                            @mooswitz More or less yes. But try first with one connection and see how it works, don't be afraid to recall it everywhere you might need to. I'd wager it will work without a snag.

                            For more information please re-read.

                            Kind Regards,
                            Artur

                            1 Reply Last reply
                            0
                            • M mooswitz

                              @artwaw @SGaist @JonB

                              I tried to reply here but akismet is constantly flagging my reply as spam. Therefore I posted my reply to Pastebin:
                              https://pastebin.com/e2SVXZVb

                              Here I made an error. It was meant so say:
                              "In any source-file where a database connection is needed I can now use the class DatabaseManager to call QSqlDatabase DB_Connection = DatabaseManager::instance();
                              So I can later check for isOpen(). That seems a lot better to me."

                              SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              @mooswitz in addition to what my fellows wrote: the SQL related classes you use offer error methods that allow you to learn what went wrong. Using them will help you more than just printing "something wrong happened".

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

                              artwawA 1 Reply Last reply
                              1
                              • SGaistS SGaist

                                @mooswitz in addition to what my fellows wrote: the SQL related classes you use offer error methods that allow you to learn what went wrong. Using them will help you more than just printing "something wrong happened".

                                artwawA Offline
                                artwawA Offline
                                artwaw
                                wrote on last edited by
                                #15

                                @SGaist Great suggestion, I forgot to mention them.
                                You can #include <QSqlError> and then qDebug() << relevant db and QSqlQuery (and others) .error() or .lastError().text() and similar.

                                For more information please re-read.

                                Kind Regards,
                                Artur

                                1 Reply Last reply
                                0
                                • M Offline
                                  M Offline
                                  mooswitz
                                  wrote on last edited by mooswitz
                                  #16

                                  @SGaist @artwaw

                                  Thank you both for your advices but I indeed used the .lastError() and related functions already. I did'nt mention them in my first posts because initially QSqlDatabase was'nt my problem. Although I made mistakes that I now have corrected. It's working perfect now.

                                  My concern was: how can I use QSqlTableModel to trigger .submitAll(); via a button. But since I use a member variable it works.
                                  I wonder if there is a similar approach to it like with QSqlDatabase::database(); now that I know how to use that it's super nice.

                                  But I think that my initial problem got solved by correcting the database connection. So thanks. I consider this thread as solved.

                                  Greetz, mooswitz

                                  SGaistS 1 Reply Last reply
                                  0
                                  • M mooswitz

                                    @SGaist @artwaw

                                    Thank you both for your advices but I indeed used the .lastError() and related functions already. I did'nt mention them in my first posts because initially QSqlDatabase was'nt my problem. Although I made mistakes that I now have corrected. It's working perfect now.

                                    My concern was: how can I use QSqlTableModel to trigger .submitAll(); via a button. But since I use a member variable it works.
                                    I wonder if there is a similar approach to it like with QSqlDatabase::database(); now that I know how to use that it's super nice.

                                    But I think that my initial problem got solved by correcting the database connection. So thanks. I consider this thread as solved.

                                    Greetz, mooswitz

                                    SGaistS Offline
                                    SGaistS Offline
                                    SGaist
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #17

                                    @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

                                    My concern was: how can I use QSqlTableModel to trigger .submitAll(); via a button. But since I use a member variable it works.
                                    I wonder if there is a similar approach to it like with QSqlDatabase::database(); now that I know how to use that it's super nice.

                                    Don't, that would be unclean. It is not a design pattern that would fit that use case.

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

                                    M 1 Reply Last reply
                                    0
                                    • SGaistS SGaist

                                      @mooswitz said in How to use an Object of type QSqlTableModel in another function of the same class?:

                                      My concern was: how can I use QSqlTableModel to trigger .submitAll(); via a button. But since I use a member variable it works.
                                      I wonder if there is a similar approach to it like with QSqlDatabase::database(); now that I know how to use that it's super nice.

                                      Don't, that would be unclean. It is not a design pattern that would fit that use case.

                                      M Offline
                                      M Offline
                                      mooswitz
                                      wrote on last edited by
                                      #18

                                      @SGaist said in How to use an Object of type QSqlTableModel in another function of the same class?:

                                      Don't, that would be unclean. It is not a design pattern that would fit that use case.

                                      Okay. So What would be the better approach? I have taken the time now to figure out what would work better instead... so first: Why is there the "submitAll()" method, if I should'nt use it with a Button or sth. similar to trigger it? Or did you mean that I should not use the member variable for that?

                                      What I want to do is the following: You (as a user) get presented with a TableView, showing some Data from a mariadb. This Data (in my case userdata) can be edited here. I do not want it to update directly after change. So that's Why I want a button to trigger that. Regarding the option to use QSqlTableModel for that - what is then the better option to trigger an Insert to the db with the Data loaded with the TableModel?

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

                                        The unclean part was about trying to have a global QSqlTableModel in a similar fashion to QSqlDatabase.
                                        For the rest, you did thing correctly. You could even simplify a bit by connecting the button directly to the submitAll function. Bad suggestion, you'd lose error handling.

                                        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
                                        • M Offline
                                          M Offline
                                          mooswitz
                                          wrote on last edited by
                                          #20

                                          Okay. Thanks a lot!

                                          How would I do that? I mean: connecting the button directly to the function?

                                          SGaistS 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