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. QTableView alter data and sorting

QTableView alter data and sorting

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 2.6k 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
    Slawomir_Piernikowski
    wrote on last edited by
    #1

    Hi
    In my software data is loaded from files to QTableView.
    Sorting is enabled:
    tableView.setSortingEnabled(true);

    In another function I alter data from the level of the tableView
    (not by clicking on the choosen cell of the tableView but programmatically, see hereunder):

    tableView.model()->setData(indeks,
    QVariant(newCategory), Qt::EditRole);
    Before tableView.model()->setData...... I set sorting of the tableView : tableView.setSortingEnabled(false);
    and after changing data(using the function tableView.model()->setData......) again I set sotring
    of the tableView : tableView.setSortingEnabled(true);
    I changed data in the loop looking for the data I want to alter and after the loop has just been finished I set sorting: tableView.setSortingEnabled(true);

    If I have sorting set to false the function which change data works fine. But if the sorting is set to false and after changing data set to true the result of changing data are not correct.
    For exemple if I want to alter strings "AAA" to "BBB" only some
    part of them will change fexp 3 out of 4.
    Any sugestions please.

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

      Hi,

      What version of Qt are you using ?
      On what OS ?

      Can you provide a minimal compilable example that shows that behaviour ?

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

      S 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        What version of Qt are you using ?
        On what OS ?

        Can you provide a minimal compilable example that shows that behaviour ?

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

        @SGaist
        Hi
        Qt Creator 4.7.1
        Based on Qt 5.11.2 (MSVC 2015, 32 bitowy)
        Version from Sep 18 2018 14:54:17
        From version fa50153fc8
        Os Windows 10 proffessional 64bit
        Example: not compilable but shows the matter.

        NowyMagazyn class derived from QAbstractItemModel.
        Virtual methods are overrided.
        The key issue here is why sorting makes problem when changin data.

        void NowyMagazyn::LoadMagazins()//Geting data from files to model and bring it to The View
        {
        //Getting names of the magazins
        QStringList nazwyMagazynow;
        nazwyMagazynow = cModel->GetMagazynNames();

        for(int i = 0; i < nazwyMagazynow.size(); i++)
        {     
          //Creating instance of the Magazin and pushBack to vectMagazin
          cMagazyn->CreateMagazynInstancesPushBackToVectMagazyn();
        
          ui->tabWidget->addTab(cMagazyn->GetVectMagazyn().at(i), nazwyMagazynow.at(i));
         
          //Creating Models for each Magazin
          cModel->CreateMagazynModelPushBackToVector();
          cModel->GetVectMagazynModel().at(i)->SetModelName(nazwyMagazynow.at(i));      
          cModel->GetVectMagazynModel().at(i)->InsertInvoker();
        
          //Creating FilterProxysModels
          cFilterProxyModel->CreateMagazynFilterProxyModelPushBackToVectFilterProxyModel();
          cFilterProxyModel->GetVectMagazynFilterProxyModel().at(i)->setSourceModel(cModel->GetVectMagazynModel().at(i));
         
          //Combine The View with The Model
          if(cMagazyn->GetVectMagazyn().size() > 0)
          {
              cMagazyn->GetVectMagazyn()[i]->GetTabView().setModel(cFilterProxyModel->GetVectMagazynFilterProxyModel().at(i));
              cMagazyn->GetVectMagazyn()[i]->GetTabView().setSortingEnabled(true);
              cMagazyn->GetVectMagazyn()[i]->GetTabView().horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
              cMagazyn->GetVectMagazyn()[i]->GetTabView().setSelectionBehavior(QAbstractItemView::SelectRows);
        
        
          }
        

        Now the function which change data in the View:

        void NowyMagazyn::UpdateViewAfterCategoryAlter(QString oldCategory, QString newCategory)
        {

        for(int i = 0; i < ui->tabWidget->count(); i++)
        {
            if(ui->tabWidget->tabText(i) == ui->CboxMagazyn->currentText())
            {            
                ui->tabWidget->setCurrentIndex(i); //The view has to be active before further actions           
                break;
            }
        }
        
        //before changing data in from the level of the view setting sorting to false
        cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().setSortingEnabled(false);
        
        //Getting rowCount 
        int rowCount = cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model()->rowCount(QModelIndex());
        
        for(int i = 0; i <  rowCount; i++)
        {
            //Getting indekses one  by one for column 0
            QModelIndex indeks = cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model()->index(i, 0);
        
            //Getting data from the view to compare
            QString categoryToCompare = cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model() ->data(indeks).toString();
           
            
            //changing data in the view if comparission is true
            if(oldCategory == categoryToCompare)
             {
               cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model()->setData(indeks,QVariant(newCategory), Qt::EditRole);                                       
               
             }
        }
        
        //after changing data  setting sorting to true;    
        cMagazyn->GetVectMagazyn()[ui->tabWidget->currentIndex() - 2]->GetTabView().setSortingEnabled(true);
        

        }

        See pictures before and after changing the data:0_1540703870144_Data befor changing.png 0_1540703888282_Data after changing.png

        I suspect that when changing data in the loop something goes wrong with indexes.
        See row 6 before changing data. The row moved to position 5 after changing the data.
        One of the solution to get rid of the problem is to break the loop in the if statement
        and call UpdateViewAfterCategoryAlter(ui->CboxKategoria->currentText(), nowaNazwaKategorii); function so many times how many we have rows with data to change:
        exp:
        for(int i = 0; i < number of rows to change; i++)
        UpdateViewAfterCategoryAlter(ui->CboxKategoria->currentText(), nowaNazwaKategorii);

        and breaking the loop in the if statement in UpdateViewAfterCategoryAlter:

            //changing data in the view if comparission is true
            if(oldCategory == categoryToCompare)
             {
               cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model()->setData(indeks,QVariant(newCategory), Qt::EditRole);
               break;
             }
        
        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by Christian Ehrlicher
          #4

          Your code is very hard to read. Why to you call "cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model()" every time instead using an intermediate variable?

          auto model = cMagazyn->GetVectMagazyn().at(ui->tabWidget->currentIndex() - 2)->GetTabView().model();
          for (int i = 0; i < model->rowCount(); ++i) {
            const auto idx = model->index(i, 0);
            const QString categoryToCompare  = model->data(idx, Qt::EditRole).toString();
            if (oldCategory == categoryToCompare)
              model->setData(idx, newCategory), Qt::EditRole);
          }
          

          And notw to your problem - since you've enabled sorting the sorting will occur as soon as you call setData() which also means that your row indexes will change.

          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
          • S Offline
            S Offline
            Slawomir_Piernikowski
            wrote on last edited by
            #5

            Yes indeed it is a little hard to read. Good idea with intermmediate variable.
            You write: "And not to your problem - since you've enabled sorting the sorting will occur as soon as you call setData() which also means that your row indexes will change."
            I agree.
            Before changing the data sorting is disabled and only after changing them sotring is enabled. I add that if sorting is disabled at all the function works fine.
            It is quite odd.

            1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @Slawomir_Piernikowski said in QTableView alter data and sorting:

              cFilterProxyModel

              Since you've a custom QSortFilterProxyModel inbetween you can't simply disable sorting this way - this property is only usefull to enable/disable sorting by the user. I first was under the impression that you're using a QTableWidget

              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
              • S Offline
                S Offline
                Slawomir_Piernikowski
                wrote on last edited by Slawomir_Piernikowski
                #7

                So how can it be done???. I add that I have not overrided sort function in MagazynModel which derived from QAbstractItemModel and not overrided sort function in MagazynFilterProxyModel which derived from QSortFilterProxyModel. I use only QSortFilterProxyModel for filtring data.
                I say again that when tabView->SetSortingEnabled(bool) is never set true in my soft
                the UpdateViewAfterCategoryAlter works fine (data after changing are correct) and there is no any sorting.

                1 Reply Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  You can e.g. iterate over the base model. There the rows won't change it's order.

                  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
                  1
                  • S Offline
                    S Offline
                    Slawomir_Piernikowski
                    wrote on last edited by
                    #9

                    Yes it can be done like this.
                    In Model View Control you can change data by clicking on the selected data in a cell and change data - this works ok.

                    I have tried to do the same but changing data in many cell one by one using loop - this only works when setSortingEnabled is never set true in the soft.

                    So I jumpet to a conclusion to break the loop just after changing the data in one cell
                    and again call the function UpdateViewAfterCategoryAlter again and again up to the number data in cell(rows) I wanted to change - this works ok even SetSortingEnabled(true).

                    I was googling for information and found out that just before changing data sorting should be set false an just after should be set to true but in my case it is not working. I submited the post here because maybe somebody had the same issue.

                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @Slawomir_Piernikowski said in QTableView alter data and sorting:

                      I was googling for information and found out that just before changing data sorting should be set false an just after should be set to true but in my case it is not working

                      This is true for the convenience QTableWidget but not when you have a custom QSortFilterProxyModel inbetween. Then you can do it like I suggested - directly change the values in the source model.

                      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
                      1
                      • S Offline
                        S Offline
                        Slawomir_Piernikowski
                        wrote on last edited by Slawomir_Piernikowski
                        #11

                        Ok I got it. Thanks
                        I have decided to change data using the View instead of the model. Simply it is easyer to do.

                        "So I jumpet to a conclusion to break the loop just after changing the data in one cell
                        and again call the function UpdateViewAfterCategoryAlter again and again up to the number data in cell(rows) I wanted to change - this works ok even SetSortingEnabled(true)."

                        ...but after testing this solution with 1000 strings(located in one column) to change I have noticed that it takes much time to do this and soft crashes itself.

                        So I come back to do the same with the source model and this approach apeard to be better one.
                        That means works faster and more stable.

                        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