Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Update QTableView after hiding columns



  • Hello,
    I have a question about updating QTableView after hiding some columns. The code below is an extract from my whole code.
    Hopefully it shows what I am doing and help to understand my problem.

    There is a QSqlTableModel* myDataTableModel with the data to display in QTableView* myDataTableView.
    The user's selection of columns to hide is stored in table "tableFilter".
    If "bShowColumn" is 1 (One) the row should be shown. If "bShowColumn" is 0 (Zero) the row should be hidden.

    The tables with data representet "by strTableName could be different. They could have a different amount of columns and also different names of the columns. Nevertheless I want to show the data in the same view "myDataTableView".

    All is fine when I run the code the first time.
    Doing this a second time with a different table (strTableName changed) the QTableView is not updated properly and does not show all columns.

    What I am doing wrong?

    bool hide;
    int index;
    QString strTableName;  // This is just for the example.
                                         // The name of the table could change and is a parameter of the function
    
    QSqlTableModel* myDataTableModel;
    
    myDataTableModel->setTable(strTableName);--
    myDataTableModel->setEditStrategy(QSqlTableModel::OnFieldChange);
    myDataTableModel->setHeaderData(myDataTableModel->fieldIndex("run_number"),
                      Qt::Horizontal, "run");
    
    myDataTableModel->select();
    
    ui.mySimDataTableView->setModel(myDataTableModel);
    
    // Hide ID Column
    ui.mySimDataTableView->setColumnHidden(myDataTableModel->fieldIndex("idSimData"), true);
    
    QSqlDatabase db = QSqlDatabase::database("DEFAULT");
    QSqlQuery stuff(db);
    
    QString s = "SELECT tPropName, bShowColumn FROM tableFilter";
    
    if (stuff.exec(s));
    {
     while(stuff.next());
     {
      hide = stuff.value(1);.toInt() == 0;
      index = myDataTableModel()->fieldIndex(stuff.value(0).toString());
      if(index >= 0)
      {
       ui.mySimDataTableView->setColumnHidden(index, hide);
      }
     }
    }
    


  • First of all,m you hide columns, not rows :-)

    I think, the problem is that you explicitly hide columns, and the perhaps switch the model. You should remove the setColumnHidden and rehide all new hidden rows.

    I think, that could help.



  • Why not use a proxy model (based on "QSortFilterProxyModel":http://doc.qt.nokia.com/stable/qsortfilterproxymodel.html) like in this "wiki article":http://developer.qt.nokia.com/wiki/Filter_Columns_in_a_QFileSystemModel

    And don't forget to let the model emit signals (columnAdde/Remove etc.) afterwards to have the view catch up the changes.



  • you needn't emit signals if you just filter out rows. There are callback for hiding rows/columns in QSortFilterProxyModel: "filterAcceptsColumn":http://doc.qt.nokia.com/latest/qsortfilterproxymodel.html#filterAcceptsColumn and "filterAcceptsRow":http://doc.qt.nokia.com/latest/qsortfilterproxymodel.html#filterAcceptsRow

    Also see the "example in the description of QSortFilterProxyModel":http://doc.qt.nokia.com/latest/qsortfilterproxymodel.html#filtering



  • Yep. But if the filter rules change after the view has finished displaying items, you must inform the view of the change. Fortunately the Trolls have provided us with slot "invalidateFilter() ":http://doc.qt.nokia.com/latest/qsortfilterproxymodel.html#invalidateFilter for this :-)



  • Thanks so far.

    I will have a look at the proxy model next week and will also try to unhide the hidden columns before I hide them again.



  • Ok, if I do this

    // unhide all hidden columns
    int rows = myDataTableModel()->rowCount();
    for(int i=0; i<rows; i++)
    {
     ui.mySimDataTableView->setColumnHidden(i, false);
    }
    

    before

    ui.mySimDataTableView->setModel(myDataTableModel);

    everythink is fine.

    Thank you :-)



  • [quote author="js_dev" date="1296216104"]Thanks so far.

    I will have a look at the proxy model next week and will also try to unhide the hidden columns before I hide them again.[/quote]

    If you use the proxy model approach, the setColumnHidden of the view is not needed anymore.



  • Ok, if I do this

    // unhide all hidden columns
    int rows = myDataTableModel()->rowCount();
    for(int i=0; i<rows; i++)
    {
    ui.mySimDataTableView->setColumnHidden(i, false);
    }
    

    before

    ui.mySimDataTableView->setModel(myDataTableModel);

    everythink is fine.

    Thank you :-)[/quote]

    What is a bit strange:

    you iterate over rowCount and call setColumnHidden
    This does not fit!



  • Oh man - I mixed up rows and columns again :-(
    Sorry for the confuision.

    It must look like this:

    // unhide all hidden columns
    int cols = myDataTableModel()->columnCount();
    for(int i=0; i<cols; i++)
    {
     ui.mySimDataTableView->setColumnHidden(i, false);
    }
    
    ui.mySimDataTableView->setModel(myDataTableModel());
    


  • I found another (maybe easier) way to unhide all the previously hidden columns.

    If I resize the columns to content after hiding the columns I can get rid of the loop I posted above and the table view shows all the columns I want to see.

    Do it like this:

    if (stuff.exec(s))
    {
     while(stuff.next())
     {
      hide = stuff.value(1).toInt() == 0;
      index = myDataTableModel();->fieldIndex(stuff.value(0).toString());
      if(index >= 0)
      {
       ui.mySimDataTableView->setColumnHidden(index, hide);
      }
     }
    }
    // This will resize the columns to content and also unhide all previously hidden columns
    ui.mySimDataTableView->resizeColumnsToContents();
    


  • As this is not a described behavior, you should take care that it might change in future...


Log in to reply