[QTableView + QSqlTableModel] Sortowanie alfabetyczne nie uwzględnia polskich znaków
-
wrote on 26 May 2021, 08:11 last edited by
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)? -
wrote on 31 May 2021, 06:06 last edited by
Myślę, że powinieneś spojrzeć na QCollator z std::sort.
-
wrote on 2 Jun 2021, 08:02 last edited by
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?
-
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?
wrote on 2 Jun 2021, 08:50 last edited by@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ę.
-
@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ę.
wrote on 2 Jun 2021, 15:35 last edited by@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();
-
@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();
wrote on 2 Jun 2021, 15:42 last edited by artwaw 6 Feb 2021, 15:42@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. -
@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.wrote on 4 Jun 2021, 06:57 last edited by@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?
-
@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?
wrote on 4 Jun 2021, 09:48 last edited by@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;
, czymodel->deleteLater();
, czy nie usunę zbyt wcześnie, czy jakiś edge case nie wywali mi segfaulta. -
@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;
, czymodel->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?
wrote on 11 Jun 2021, 08:45 last edited by@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.
-
@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.
wrote on 11 Jun 2021, 09:01 last edited by@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 . -
@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ę.
wrote on 28 Jun 2021, 17:58 last edited by@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.
-
@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.
-
@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.
-
@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.wrote on 30 Jun 2021, 18:28 last edited by@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