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

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



  • 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)?



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



  • 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?



  • @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ę.



  • @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();


  • @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.



  • @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?



  • @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.



  • @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?



  • @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.



  • @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 .


Log in to reply