Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. Polish
  4. [QTableView + QSqlTableModel] Sortowanie alfabetyczne nie uwzględnia polskich znaków
QtWS25 Last Chance

[QTableView + QSqlTableModel] Sortowanie alfabetyczne nie uwzględnia polskich znaków

Scheduled Pinned Locked Moved Solved Polish
15 Posts 4 Posters 1.7k 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.
  • K Offline
    K Offline
    karlowic
    wrote on last edited by
    #1

    Dzień dobry
    Program tworzy SqlTableModel i wyświetla go w QTableView. Niestety rekordy sortowane alfabetycznie np. po nazwisku zaczynające się na Ś, Ł wyświetlane są na końcu listy (w przypadku Ż nie ma problemu :-) ). Czy istnieje jakiś sposób, żeby wyświetlały się w prawidłowym miejscu (Ś po S, Ł po L)?

    1 Reply Last reply
    0
    • S Offline
      S Offline
      sowas
      wrote on last edited by
      #2

      Myślę, że powinieneś spojrzeć na QCollator z std::sort.

      1 Reply Last reply
      0
      • K Offline
        K Offline
        karlowic
        wrote on last edited by
        #3

        Udało mi się dojść do czegoś takiego:
        int main()
        {
        QStringList myStringList = (QStringList() << "Kabaciński" << "Świątek" << "Kąkolewski" <<
        "Kłaczek" << "Krzaczek" << "Babiak" << "Żuk" << "Lubański" << "Strzelecka" <<
        "Szulc"<< "Łapacz" << "Czykiel" << "Cabaj" << "Ćwiek" << "100" << "99");
        QCollator sorter;
        sorter.setNumericMode( true );
        sorter.setCaseSensitivity( Qt::CaseInsensitive );
        std::sort(myStringList.begin(), myStringList.end(), sorter);
        qDebug() << myStringList;
        }
        Ładnie sortuje listę myStringList:
        ("99", "100", "Babiak", "Cabaj", "Czykiel", "Ćwiek", "Kabaciński", "Kąkolewski", "Kłaczek", "Krzaczek", "Lubański", "Łapacz", "Strzelecka", "Szulc", "Świątek", "Żuk")

        ale jak to zastosować do QSqlTableModel?

        artwawA 1 Reply Last reply
        0
        • K karlowic

          Udało mi się dojść do czegoś takiego:
          int main()
          {
          QStringList myStringList = (QStringList() << "Kabaciński" << "Świątek" << "Kąkolewski" <<
          "Kłaczek" << "Krzaczek" << "Babiak" << "Żuk" << "Lubański" << "Strzelecka" <<
          "Szulc"<< "Łapacz" << "Czykiel" << "Cabaj" << "Ćwiek" << "100" << "99");
          QCollator sorter;
          sorter.setNumericMode( true );
          sorter.setCaseSensitivity( Qt::CaseInsensitive );
          std::sort(myStringList.begin(), myStringList.end(), sorter);
          qDebug() << myStringList;
          }
          Ładnie sortuje listę myStringList:
          ("99", "100", "Babiak", "Cabaj", "Czykiel", "Ćwiek", "Kabaciński", "Kąkolewski", "Kłaczek", "Krzaczek", "Lubański", "Łapacz", "Strzelecka", "Szulc", "Świątek", "Żuk")

          ale jak to zastosować do QSqlTableModel?

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

          @karlowic Nie stosować.
          Wstaw QSortFilterProxyModel pomiędzy QSqlTableModel a widok, ten model służy do stosowania filtrów i właściwego sortowania.

          Pamiętaj też żeby włączyć setSortLocaleAware(), to powinno załatwić sprawę.

          For more information please re-read.

          Kind Regards,
          Artur

          K R 2 Replies Last reply
          1
          • artwawA artwaw

            @karlowic Nie stosować.
            Wstaw QSortFilterProxyModel pomiędzy QSqlTableModel a widok, ten model służy do stosowania filtrów i właściwego sortowania.

            Pamiętaj też żeby włączyć setSortLocaleAware(), to powinno załatwić sprawę.

            K Offline
            K Offline
            karlowic
            wrote on last edited by
            #5

            @artwaw Jesteś the best. :)
            Oczywiście działa.

            int column = 2;
            switch (ui->comboBox->currentIndex())
            {
            case 0:              //Nazwisko
                column = 2;
                break;
            case 1:             //telefon
                column = 3;
                break;
            case 2:            //Imię
                column= 1;
                break;
            }
            
            QSqlTableModel *model = new QSqlTableModel;
            model->setTable("pacjenci");
            model->select();
            
            model->setHeaderData(0, Qt::Horizontal, tr("id"));
            model->setHeaderData(1, Qt::Horizontal, tr("Imię"));
            model->setHeaderData(2, Qt::Horizontal, tr("Nazwisko"));
            model->setHeaderData(3, Qt::Horizontal, tr("nr telefonu"));
            
            QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
            proxyModel->setSourceModel(model);
            proxyModel->setSortLocaleAware(true);
            proxyModel->sort(column, Qt::AscendingOrder);
            
            ui->tableView->setModel(proxyModel);
            ui->tableView->setColumnWidth(0,40);
            ui->tableView->show();
            
            artwawA 1 Reply Last reply
            0
            • K karlowic

              @artwaw Jesteś the best. :)
              Oczywiście działa.

              int column = 2;
              switch (ui->comboBox->currentIndex())
              {
              case 0:              //Nazwisko
                  column = 2;
                  break;
              case 1:             //telefon
                  column = 3;
                  break;
              case 2:            //Imię
                  column= 1;
                  break;
              }
              
              QSqlTableModel *model = new QSqlTableModel;
              model->setTable("pacjenci");
              model->select();
              
              model->setHeaderData(0, Qt::Horizontal, tr("id"));
              model->setHeaderData(1, Qt::Horizontal, tr("Imię"));
              model->setHeaderData(2, Qt::Horizontal, tr("Nazwisko"));
              model->setHeaderData(3, Qt::Horizontal, tr("nr telefonu"));
              
              QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
              proxyModel->setSourceModel(model);
              proxyModel->setSortLocaleAware(true);
              proxyModel->sort(column, Qt::AscendingOrder);
              
              ui->tableView->setModel(proxyModel);
              ui->tableView->setColumnWidth(0,40);
              ui->tableView->show();
              
              artwawA Offline
              artwawA Offline
              artwaw
              wrote on last edited by artwaw
              #6

              @karlowic Jeszcze uwaga: jeśli nie kasujesz model i proxyModel to masz memory leak dopóki nie ustawisz im rodzica przy new.

              To drugie znakomicie automatyzuje proces, więc np. new QSqlTableModel(this); byłoby wskazane.

              For more information please re-read.

              Kind Regards,
              Artur

              K 1 Reply Last reply
              1
              • artwawA artwaw

                @karlowic Jeszcze uwaga: jeśli nie kasujesz model i proxyModel to masz memory leak dopóki nie ustawisz im rodzica przy new.

                To drugie znakomicie automatyzuje proces, więc np. new QSqlTableModel(this); byłoby wskazane.

                K Offline
                K Offline
                karlowic
                wrote on last edited by
                #7

                @artwaw Do tej pory ustawiałem rodzica przy new tylko dla podrzędnego okna w programie.

                A w takim przypadku też warto wpisywać pisać QLabel(this):

                if(!mydb.open())
                {
                    no_redy = new QLabel(this);
                    no_redy->setText("No ready");
                    ui->statusBar->addWidget(no_redy);
                
                }
                  else
                {
                    redy = new QLabel(this);
                    redy->setText("Ready");
                    ui->statusBar->addWidget(redy);
                    refresh();
                }
                

                bo tego nie robiłem wcześniej?

                artwawA 1 Reply Last reply
                0
                • K karlowic

                  @artwaw Do tej pory ustawiałem rodzica przy new tylko dla podrzędnego okna w programie.

                  A w takim przypadku też warto wpisywać pisać QLabel(this):

                  if(!mydb.open())
                  {
                      no_redy = new QLabel(this);
                      no_redy->setText("No ready");
                      ui->statusBar->addWidget(no_redy);
                  
                  }
                    else
                  {
                      redy = new QLabel(this);
                      redy->setText("Ready");
                      ui->statusBar->addWidget(redy);
                      refresh();
                  }
                  

                  bo tego nie robiłem wcześniej?

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

                  @karlowic To zależy. Popatrz tutaj: https://doc.qt.io/qt-5/objecttrees.html

                  Generalnie jeśli obiekt ma rodzica to zostanie prawidłowo usunięty kiedy zostanie usunięty rodzic. Jeśli dodajesz obiekt to UI najprawdopodobniej zachodzi reparenting, więc nie mam problemu - ale warto sprawdzić dokumentację gdyż są wyjątki.

                  W przypadku obiektów niewidokowych sprawa jest nieco bardziej skomplikowana, bo reparenting zdarza się siłą rzeczy rzadziej. Ja dodaję instancję której członkiem jest model (this) jako parent, bo nie muszę się wtedy martwić czy delete model;, czy model->deleteLater();, czy nie usunę zbyt wcześnie, czy jakiś edge case nie wywali mi segfaulta.

                  For more information please re-read.

                  Kind Regards,
                  Artur

                  K 1 Reply Last reply
                  0
                  • artwawA artwaw

                    @karlowic To zależy. Popatrz tutaj: https://doc.qt.io/qt-5/objecttrees.html

                    Generalnie jeśli obiekt ma rodzica to zostanie prawidłowo usunięty kiedy zostanie usunięty rodzic. Jeśli dodajesz obiekt to UI najprawdopodobniej zachodzi reparenting, więc nie mam problemu - ale warto sprawdzić dokumentację gdyż są wyjątki.

                    W przypadku obiektów niewidokowych sprawa jest nieco bardziej skomplikowana, bo reparenting zdarza się siłą rzeczy rzadziej. Ja dodaję instancję której członkiem jest model (this) jako parent, bo nie muszę się wtedy martwić czy delete model;, czy model->deleteLater();, czy nie usunę zbyt wcześnie, czy jakiś edge case nie wywali mi segfaulta.

                    K Offline
                    K Offline
                    karlowic
                    wrote on last edited by
                    #9

                    @artwaw Widgety w UI dziedziczą się automatycznie - to rozumiem, :) ale kiedy dodaję QLabel dodatkowo (czyli nie jest to ui->label), czy też ma ustalonego rodzica czy muszę go ustalić jak w/w przykładzie?

                    artwawA 1 Reply Last reply
                    0
                    • K karlowic

                      @artwaw Widgety w UI dziedziczą się automatycznie - to rozumiem, :) ale kiedy dodaję QLabel dodatkowo (czyli nie jest to ui->label), czy też ma ustalonego rodzica czy muszę go ustalić jak w/w przykładzie?

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

                      @karlowic
                      void QStatusBar::addWidget(QWidget *widget, int stretch = 0)
                      Adds the given widget to this status bar, reparenting the widget if it isn't already a child of this QStatusBar object.

                      W tym wypadku nie musisz, bo zachodzi reparenting. Ale nie zawsze zachodzi, szczególnie poza UI.

                      Moją uwagę na początku przykuło że konstruujesz modele bez rodzica.

                      For more information please re-read.

                      Kind Regards,
                      Artur

                      K 1 Reply Last reply
                      0
                      • artwawA artwaw

                        @karlowic
                        void QStatusBar::addWidget(QWidget *widget, int stretch = 0)
                        Adds the given widget to this status bar, reparenting the widget if it isn't already a child of this QStatusBar object.

                        W tym wypadku nie musisz, bo zachodzi reparenting. Ale nie zawsze zachodzi, szczególnie poza UI.

                        Moją uwagę na początku przykuło że konstruujesz modele bez rodzica.

                        K Offline
                        K Offline
                        karlowic
                        wrote on last edited by
                        #11

                        @artwaw
                        *"void QStatusBar::addWidget(QWidget widget, int stretch = 0)
                        Adds the given widget to this status bar, reparenting the widget if it isn't already a child of this QStatusBar object."

                        Zawsze warto zaglądać do dokumentacji :)
                        Dziekuję za pomoc .

                        1 Reply Last reply
                        0
                        • artwawA artwaw

                          @karlowic Nie stosować.
                          Wstaw QSortFilterProxyModel pomiędzy QSqlTableModel a widok, ten model służy do stosowania filtrów i właściwego sortowania.

                          Pamiętaj też żeby włączyć setSortLocaleAware(), to powinno załatwić sprawę.

                          R Offline
                          R Offline
                          rykomick
                          wrote on last edited by
                          #12

                          @artwaw @karlowic Sposób sortowania musi być ustawiony w źródłowej bazie danych i tam musi być dokonane sortowanie, ani nie w kliencie, modelu czy też używając QSortFilterProxyModel . Powód: Aby dokonać sortowania klient musi załadować wszystkie rekordy z bazy danych. Przy kilku to nie problem, ale przy kilku milionach to problem wielki.

                          K artwawA 2 Replies Last reply
                          0
                          • R rykomick

                            @artwaw @karlowic Sposób sortowania musi być ustawiony w źródłowej bazie danych i tam musi być dokonane sortowanie, ani nie w kliencie, modelu czy też używając QSortFilterProxyModel . Powód: Aby dokonać sortowania klient musi załadować wszystkie rekordy z bazy danych. Przy kilku to nie problem, ale przy kilku milionach to problem wielki.

                            K Offline
                            K Offline
                            karlowic
                            wrote on last edited by
                            #13

                            @rykomick "Sposób sortowania musi być ustawiony w źródłowej bazie danych i tam musi być dokonane sortowanie"
                            Baza danych to Sqlite. Proszę podać sposób sortowania znaków diakrytycznych w tej bazie, jeśli to możliwe.

                            R 1 Reply Last reply
                            0
                            • R rykomick

                              @artwaw @karlowic Sposób sortowania musi być ustawiony w źródłowej bazie danych i tam musi być dokonane sortowanie, ani nie w kliencie, modelu czy też używając QSortFilterProxyModel . Powód: Aby dokonać sortowania klient musi załadować wszystkie rekordy z bazy danych. Przy kilku to nie problem, ale przy kilku milionach to problem wielki.

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

                              @rykomick ale próbowałeś czy tak tylko piszesz?

                              For more information please re-read.

                              Kind Regards,
                              Artur

                              1 Reply Last reply
                              0
                              • K karlowic

                                @rykomick "Sposób sortowania musi być ustawiony w źródłowej bazie danych i tam musi być dokonane sortowanie"
                                Baza danych to Sqlite. Proszę podać sposób sortowania znaków diakrytycznych w tej bazie, jeśli to możliwe.

                                R Offline
                                R Offline
                                rykomick
                                wrote on last edited by
                                #15

                                @karlowic Sqllite ma niestety bardzo ograniczoną funkcjonalność, jeżeli o takie problemy chodzi. Najlepiej napisać samemu funkcję sortującą: https://stackoverflow.com/questions/35371168/locale-aware-collation-in-sqlite-using-qt

                                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