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. QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program
Qt 6.11 is out! See what's new in the release blog

QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 3 Posters 618 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.
  • S sairun

    I'm developing an application to query an external web server given some user preferences. The retrieved data is stored in a local SQLite3 database. I've managed to code a functional prototype based on the Qt model/view framework, using a QTableView instance to which a model TableModel (derived from QSqlTableModel) is associated. The database to be used is passed to the model during its construction (it can be empty or partially populated with previous queries):

        _TableView = new QTableView( this );
        _TableModel = new TableModel( this, database );
        _TableModel->select();
        _TableView->setModel( _TableModel );
    

    However, during the program execution it should allow the user to change to a different database as many times as he/she likes. For that, the current database should be closed and a new one created or opened. From the documentation it's not clear what to do with the current model and the view. Before closing the database, should the model be destroyed (deleted) and a new one created? Should the model be reset (with clear()) and then associated to the new database? What about the view?

    While reading QAbstractItemView documentation I found the following comments for setModel():

    This function will create and set a new selection model, replacing any model
    that was previously set with setSelectionModel(). However, the old selection
    model will not be deleted as it may be shared between several views. We
    recommend that you delete the old selection model if it is no longer required.
    This is done with the following code:

       QItemSelectionModel *m = view->selectionModel();
       view->setModel(new model);
       delete m;
    

    The above code is not clear because it does not refer the model! The pointer *m is pointing to a QItemSelectionModel which is not the same thing. With this example I assume that one should not destroy the view when changing models, but the underlying current model should be disposed either using delete or model->deleteLater() . I'm not sure if setModel() passes the owneship of the model to the view. Apparently it does not. But one can create a model passing the view as its parent.

    I found an interesting example in github which partially answers my questions but also raises new ones. It reuses the view and destroys the model each time the users selects/creates a different database. The new models are always created with the view as their parent. It also has an odd (for me) method of destroying the model: it creates a unique_ptr pointing to the current model, which then goes out of scope when that method returns! It also nullifies the view's model, since there is no method in the view to do so.

    void MainWindow::removeCurrentModel()
    {
        std::unique_ptr<QAbstractItemModel> currentModel{ui_->tableView->model()};
        ui_->tableView->setModel(nullptr);
    }
    

    But what about SelectionModel associated with the view (as implied in the documentation of QAbstractItemView)? Does it get destroyed automatically? The documentation says

    It is up to the application to delete the old selection model if it is no
    longer needed; i.e., if it is not being used by other views. This will happen
    automatically when its parent object is deleted. However, if it does not have
    a parent, or if the parent is a long-lived object, it may be preferable to
    call its deleteLater() function to explicitly delete it.

    So, to summarize, wouldn't it be better to do

       QItemSelectionModel *oldselmod = view->selectionModel();
       QSqlTableModel *oldmodel = view->model();
       
       view->setModel(new model);
       
       oldselmod->deleteLater();
       oldmodel->deleteLater();
    
    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #2

    @sairun
    Your final boxed code looks fine. (You might check for nullptr since they are pointers, just in case: delete nullptr is fine but nullptr->deleteLater() is not.)

    S 1 Reply Last reply
    0
    • JonBJ JonB

      @sairun
      Your final boxed code looks fine. (You might check for nullptr since they are pointers, just in case: delete nullptr is fine but nullptr->deleteLater() is not.)

      S Offline
      S Offline
      sairun
      wrote on last edited by
      #3

      Thanks @JonB for noticing the unchecked deleteLater() but at this stage of the program I can at least be sure that the olmodel pointer is pointing to something because it was being used. Still, it's better to make sure the pointer is not null! The old selection model olselmod is another thing. In fact, the code in github that I've linked previously doesn't mention the selectionModel() anywhere in the sources. But valgrind didn't show any major leak, so I'm not sure if it is being dealt aitomatically.

      JonBJ 1 Reply Last reply
      0
      • S sairun

        Thanks @JonB for noticing the unchecked deleteLater() but at this stage of the program I can at least be sure that the olmodel pointer is pointing to something because it was being used. Still, it's better to make sure the pointer is not null! The old selection model olselmod is another thing. In fact, the code in github that I've linked previously doesn't mention the selectionModel() anywhere in the sources. But valgrind didn't show any major leak, so I'm not sure if it is being dealt aitomatically.

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #4

        @sairun
        I wasn't sure whether selectionModel() could potentially be nullptr if, say, you never do a selection. Probably not. But better safe than sorry.

        I rely on valgrind for checking Qt/C++ memory is being disposed correctly. If it passes you should be good. You could try not doing the disposals and verify it then complains.

        S 1 Reply Last reply
        0
        • JonBJ JonB

          @sairun
          I wasn't sure whether selectionModel() could potentially be nullptr if, say, you never do a selection. Probably not. But better safe than sorry.

          I rely on valgrind for checking Qt/C++ memory is being disposed correctly. If it passes you should be good. You could try not doing the disposals and verify it then complains.

          S Offline
          S Offline
          sairun
          wrote on last edited by
          #5

          Don't get me wrong @JonB. I prefer to do the checking. The issue is whether I care about selectionModel or not. I've never had the need to directly intercat with it, although I know it is being used in my program. I rely on the selection of rows in a view to export some data.

          JonBJ 1 Reply Last reply
          0
          • S sairun

            Don't get me wrong @JonB. I prefer to do the checking. The issue is whether I care about selectionModel or not. I've never had the need to directly intercat with it, although I know it is being used in my program. I rely on the selection of rows in a view to export some data.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #6

            @sairun
            Yes, if you use selection then the QItemSelectionModel will come into play. You should indeed delete or deleteLater() it as you are doing, else I think it may leak. I only meant that I do not know whether view->selectionModel() is always guaranteed to be allocated and non-nullptr, if it can be nullptr then your original unprotected code would crash, so it's worth putting in the check. I think we are on the same page :)

            Christian EhrlicherC 1 Reply Last reply
            0
            • JonBJ JonB

              @sairun
              Yes, if you use selection then the QItemSelectionModel will come into play. You should indeed delete or deleteLater() it as you are doing, else I think it may leak. I only meant that I do not know whether view->selectionModel() is always guaranteed to be allocated and non-nullptr, if it can be nullptr then your original unprotected code would crash, so it's worth putting in the check. I think we are on the same page :)

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

              @JonB said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

              You should indeed delete or deleteLater() it as you are doing, else I think it may leak.

              No, it does not.

              https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/itemviews/qabstractitemview.cpp#n797

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

              JonBJ S 2 Replies Last reply
              0
              • Christian EhrlicherC Christian Ehrlicher

                @JonB said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                You should indeed delete or deleteLater() it as you are doing, else I think it may leak.

                No, it does not.

                https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/itemviews/qabstractitemview.cpp#n797

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

                @Christian-Ehrlicher
                QAbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel)

                Note: It is up to the application to delete the old selection model if it is no longer needed; i.e., if it is not being used by other views. This will happen automatically when its parent object is deleted. However, if it does not have a parent, or if the parent is a long-lived object, it may be preferable to call its deleteLater() function to explicitly delete it.

                That is what the OP is trying to follow. I do not know what his parent is. At least this is what I was thinking of, and the examples OP has found on the web.

                1 Reply Last reply
                0
                • Christian EhrlicherC Christian Ehrlicher

                  @JonB said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                  You should indeed delete or deleteLater() it as you are doing, else I think it may leak.

                  No, it does not.

                  https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/itemviews/qabstractitemview.cpp#n797

                  S Offline
                  S Offline
                  sairun
                  wrote on last edited by
                  #9

                  @Christian-Ehrlicher, what you mean is that per source code the QItemSelectionModel is set as a child of QAbstractItemModel and will be deleted when the latter is deleted? So I only have to deal with the model and not the selection model?

                  Christian EhrlicherC 1 Reply Last reply
                  0
                  • S sairun

                    @Christian-Ehrlicher, what you mean is that per source code the QItemSelectionModel is set as a child of QAbstractItemModel and will be deleted when the latter is deleted? So I only have to deal with the model and not the selection model?

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

                    @sairun said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                    So I only have to deal with the model and not the selection model?

                    Yes

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

                    S 1 Reply Last reply
                    0
                    • Christian EhrlicherC Christian Ehrlicher

                      @sairun said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                      So I only have to deal with the model and not the selection model?

                      Yes

                      S Offline
                      S Offline
                      sairun
                      wrote on last edited by
                      #11

                      @Christian-Ehrlicher said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                      Yes

                      I see. So the documentation isn't correct in the code snippet I showed above... I should mention that I implemented the deletion of the QTableModel without referencing the QItemSelectionModel` as suggested, and so far everything is working as expected. I'll mark this as solved.

                      Christian EhrlicherC 1 Reply Last reply
                      0
                      • S sairun has marked this topic as solved on
                      • S sairun

                        @Christian-Ehrlicher said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                        Yes

                        I see. So the documentation isn't correct in the code snippet I showed above... I should mention that I implemented the deletion of the QTableModel without referencing the QItemSelectionModel` as suggested, and so far everything is working as expected. I'll mark this as solved.

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

                        @sairun said in QSqlTableModel, QTableView and sqlite databases: how to use/reuse them in the same program:

                        isn't correct in the code snippet I showed above..

                        I don't see a problem here:

                        It is up to the application to delete the old selection model if it is no
                        longer needed; i.e., if it is not being used by other views. This will happen
                        automatically when its parent object is deleted.

                        The parent is QAbstractItemView so the QISM is deleted when the itemview gets deleted.

                        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

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved