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. hide/unhide rows in QTableView: use QSqlTableModel or QSqlQuery?
Forum Update on Tuesday, May 27th 2025

hide/unhide rows in QTableView: use QSqlTableModel or QSqlQuery?

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 2 Posters 245 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 Offline
    S Offline
    sairun
    wrote on 4 Apr 2024, 17:34 last edited by sairun 4 Apr 2024, 17:35
    #1

    I have a QTableView (tableView) linked to a QSqlTableModel (tableModel) which fetches the data from a single sqlite table. The primary key is an unsigned long named 'id'. In tableView, selection is only possible by row(s) (selection behaviour is QAbstractItemView::SelectRows). I linked a small context menu to the tableView that allows a user to hide selected records or to unhide them all. The code to hide records is depicted below and is "working", meaning that it does what it is meant to do. However, I feel this is not the best way to implement the desired behavior.

    A user can select a few lines or many of them. In the latter case, I don't think the code is the best as it uses "filtering" on the tableModel on a per record basis to set a particular attribute ("hidden") to TRUE. The problem is that the rows on tableView do not have a direct correspondence to the rows in tableModel. Some rows on the view may be already hidden, so the row 10 in the view may not be the 10th row in the model (for example). Hence, it's necessary to fetch the sql 'id' of each row and use it with a filter to get the record and change the attribute "hidden". Tha's the approach coded below in hideRecords.

    void MainWindow::hideRecords()
    {
        QItemSelectionModel *select = tableView->selectionModel();
        if( select->hasSelection() )
        {
            // save the current filter
            QString currentFilter = tableModel->filter();
            QList<ulong> hidelist;
            // Get the list of selected rows
            QModelIndexList selection = select->selectedRows();
            for( const auto &sel: qAsConst( selection ) )
                hidelist.push_back( sel.data().value<ulong>() );
            //  Hide all selected rows by toggling the hidden attribute to TRUE (1)
            for( const auto &q: qAsConst( hidelist ) )
            {
                QString newFilter = "id=" + QString::number(q);
                tableModel->setFilter( newFilter );
                tableModel->select();
                if ( tableModel->rowCount() == 1)
                {
                    QSqlRecord record = tableModel->record( 0 );
                    record.setValue( "hidden", 1 );
                    tableModel->setRecord( 0, record );
                    tableModel->submitAll();
                }
            }
            // Reapply the current filtering if any
            tableModel->setFilter( currentFilter );
            tableModel->select();
        }
    }
    

    Wouldn't it be better to use a QSqlQuery with a "WHERE id IN (123,124,125,etc...)" clause which would hide all records at once? My problem is that after submitting the query, it's necessary to inform the model that something changed and it also should tell the view the same thing! Although there is a dataChanged() method in QAbstractItemModel, I think it does not apply here. I found no way to tell the model that the underlying sql database changed. As far as I can remember, doing a tableModel->select() didn't work either.

    The problem described above is even worst in the case of a unhide action. The list of hidden records can grow up to a considerable size. Changing each record one-by-one as is done in hideRecords() is surely not the best thing to do. However, implementing it through direct manipulation of the database may not be the best approach. I also wonder if it is OK to mix the model-view approach with direct access to the underlying database?

    C 1 Reply Last reply 4 Apr 2024, 17:47
    0
    • S sairun
      4 Apr 2024, 17:34

      I have a QTableView (tableView) linked to a QSqlTableModel (tableModel) which fetches the data from a single sqlite table. The primary key is an unsigned long named 'id'. In tableView, selection is only possible by row(s) (selection behaviour is QAbstractItemView::SelectRows). I linked a small context menu to the tableView that allows a user to hide selected records or to unhide them all. The code to hide records is depicted below and is "working", meaning that it does what it is meant to do. However, I feel this is not the best way to implement the desired behavior.

      A user can select a few lines or many of them. In the latter case, I don't think the code is the best as it uses "filtering" on the tableModel on a per record basis to set a particular attribute ("hidden") to TRUE. The problem is that the rows on tableView do not have a direct correspondence to the rows in tableModel. Some rows on the view may be already hidden, so the row 10 in the view may not be the 10th row in the model (for example). Hence, it's necessary to fetch the sql 'id' of each row and use it with a filter to get the record and change the attribute "hidden". Tha's the approach coded below in hideRecords.

      void MainWindow::hideRecords()
      {
          QItemSelectionModel *select = tableView->selectionModel();
          if( select->hasSelection() )
          {
              // save the current filter
              QString currentFilter = tableModel->filter();
              QList<ulong> hidelist;
              // Get the list of selected rows
              QModelIndexList selection = select->selectedRows();
              for( const auto &sel: qAsConst( selection ) )
                  hidelist.push_back( sel.data().value<ulong>() );
              //  Hide all selected rows by toggling the hidden attribute to TRUE (1)
              for( const auto &q: qAsConst( hidelist ) )
              {
                  QString newFilter = "id=" + QString::number(q);
                  tableModel->setFilter( newFilter );
                  tableModel->select();
                  if ( tableModel->rowCount() == 1)
                  {
                      QSqlRecord record = tableModel->record( 0 );
                      record.setValue( "hidden", 1 );
                      tableModel->setRecord( 0, record );
                      tableModel->submitAll();
                  }
              }
              // Reapply the current filtering if any
              tableModel->setFilter( currentFilter );
              tableModel->select();
          }
      }
      

      Wouldn't it be better to use a QSqlQuery with a "WHERE id IN (123,124,125,etc...)" clause which would hide all records at once? My problem is that after submitting the query, it's necessary to inform the model that something changed and it also should tell the view the same thing! Although there is a dataChanged() method in QAbstractItemModel, I think it does not apply here. I found no way to tell the model that the underlying sql database changed. As far as I can remember, doing a tableModel->select() didn't work either.

      The problem described above is even worst in the case of a unhide action. The list of hidden records can grow up to a considerable size. Changing each record one-by-one as is done in hideRecords() is surely not the best thing to do. However, implementing it through direct manipulation of the database may not be the best approach. I also wonder if it is OK to mix the model-view approach with direct access to the underlying database?

      C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 4 Apr 2024, 17:47 last edited by
      #2

      Or use a QSortFilterProxyModel

      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
      2

      1/2

      4 Apr 2024, 17:34

      • Login

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