Qt - własny model po QAbstractItemModel

0

Chcesz koniecznie zrobić sposobem trudniejszym, cóż, kimże my z Markiem jesteśmy aby ci bronić? Proszę bardzo, reimplementuj QAbstractItemModel - w sumie, to nawet wskazane jest na pewnym etapie nauki Qt aby jakiś item model od zera napisać.
Jednak tutaj zacznij od implementacji metody index(), jak będziesz ją miał wtedy reszta będzie duużo prostsza.

0

no właśnie z tym indexem mam problem, pomożecie ? Bo jak nie zrobię indexu, to w sumie nie będę wiedział co jakich danych w której konkretnej komórce się odwołać, bo w sumie te funkcje wymagają indexu, no ale nie tylko indexu

2

Żeby było jasne
QSqlQueryModel dostarcza model "read only" z jednego powodu. Autorzy nie wiedzę jakie sql query QSqlQueryModel dostanie (może to być SELECT z wieloma join), ergo nie są w stanie stwierdzić jak obsłużyć modyfikację.
W przypadku QSqlTableModel masz tabelę i nie znając jej szczegółów można ją dość łatwo modyfikować UPDATE table_name SET field1 = ? WHERE Clause id=?.

Teraz ty znając swoje swoją bazę danych i query, które chcesz użyć do pobierania danych. Możesz więc dziedziczyć po QSqlQueryModel i zaimplementować modyfikację danych przez użytkownika.
Najprościej będzie w setData robić odpowiedni UPDATE i po sukcesie odświeżać cały model.
Optymalizacje typu: zmiana wartości w komórce, usuwanie dodawanie wierszy, bez pełnego refresh modelu są bardzo trudne w tym przypadku.

IMO masz dziedziczyć po QSqlQueryModel i nadpisać metody:

  • flags - żeby poinformować: co ma być edytowalne, a co nie
  • setData - żeby obsłużyć zapis nowych danych najpierw beginResetModel(), potem UPDATE ... na bazie danych, a na koniec endResetModel().

Wydaje mis się, że to powinno wystarczyć.

1

Generalnie po to używa się nieco bardziej zaawansowanych, bazowych klas modeli aby właśnie nie potrzebować się pałować z implementacją:

QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const

W tejże metodzie, przy pomocy createIndex() tworzysz QModelIndex dla podanych danych wejściowych. Prawdziwy dynks tkwi w zmapowaniu danych z QSqlQuery na 2-wymiarową strukturę jakiej używa QAbstractitemModel - a tutaj to już sam musisz sobie wymyślić jak odwzorować zapytanie dajmy na to "select count from table SomeTable where <some condition="condition">" na wiersz, kolumnę oraz rodzica.
Co jest oczywistym, to to, iż po każdej zmianie zapytania dotychczas potworzone QModelIndexy tracą cały sens, stąd wspomniałem o konieczności resetowania całego modelu w takim przypadku.

Suma sumarum, będziesz musiał na piechotę zrobić to, co już jest w QSqlQueryModelu.

0

w sumie dla mnie jakiejś filozofii nie ma aby zliczyć ile jest wierszy i kolumn w bazie, bo to jest to samo co macierz (algorytm macierzy umiem zrobić) ale bardziej mnie zastanawia to, że jak sobie pozliczam ile mam tych wierszy i kolumn to jak to "pokazać" QModelIndex-owi i przekazać tej funkcji ? Druga sprawa, to jak stworzyć tego parenta (root index) ? Bo tam też jest taka funkcja

Domyślam się następujących rzeczy:

  1. Zliczyć w macierzy (bazie) ile jest wierszy i przekazać do tej funkcji - tylko skąd tego parenta wziąć ?

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
  2. Zliczyć ile jest kolumn i przekazać to tej funkcji - analogicznie to co wyżej skąd tego parenta wziąć ?

    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
  3. Po zliczeniu wierszy i kolumn poniższa funkcja index pobierze sobie z automatu te dane, ponieważ rowCount i columnCount zwraca ile mają wierszy i kolumn - tylko znowu mam problem z tym parentem

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
  4. Tego parenta chyba robi się tu i ta funkcja go zwraca i powyższe funkcje sobie to pobierają, jak to w klasie

    QModelIndex parent(const QModelIndex &index) const override;

Z pozostałymi funkcjami zobaczymy czy sobie sam poradzę...

Czy mogę prosić @MasterBLB o dalsze wyjaśnienie ?

0

Inaczej, nim się weźmiesz za model [email protected] zastanowić się, jakie QSqlQuery chcesz obsługiwać, i dać kilka przykładowych z całego spektrum przewidywanych. Wyjaśnienie dokładnej budowy bazy danych na którym to ma operować także może być potrzebne.

0

zastanowić się, jakie QSqlQuery chcesz obsługiwać

czy masz na myśli to, czy moje zapytania będą zawierały "INNER JOIN" lub inne podobne skomplikowane zapytania ? Czy po prostu to będą zwykłe "SELECT" z jednej tabeli ?

dać kilka przykładowych z całego spektrum przewidywanych.

masz na myśli, że mam dać klika przykładowych zapytań ?

0

Tak i tak na oba pytania.

0

@zkubinski:
parent ma znaczenie tylko w przypadku modeli hierarchicznych, jak np. podział administracyjny państwa gdzie np. Polska jest 'rodzicem' dla województw, województwa są 'rodzicami' dla powiatów itd.
Dla list czy tabel parent nie jest istotny, dlatego w takich przypadkach powinno się dziedziczyć po QAbstractListModel czy QAbstractTableModel, żeby nie wynajdować koła na nowo.

0

Kilka dni myślałem nad przykładem, bo chciałbym zrozumieć te indexy, parenty i resztę no i chyba wymyśliłem:
Poniżej baza ma następującą strukturę, nie jest to jakiś konkretny mój problem ale starałem się pomyśleć przykład tak aby posłużył mi jako wzór do moich przyszłych rozwiązań.

Główna tabela to tWypozyczone

screenshot-20191111175734.png

Natomiast przykładowe zapytanie to:

SELECT 
`myDB`.`tWypozyczone`.`pIdWypozyczone`,
`myDB`.`tUzytkownicy`.`pImie`,
`myDB`.`tUzytkownicy`.`pNazwisko`,
`myDB`.`tUzytkownicy`.`pLogin`
FROM
`myDB`.`tWypozyczone`
INNER JOIN
`myDB`.`tUzytkownicy`
ON
`myDB`.`tUzytkownicy`.`pIdUzytkownicy` = `myDB`.`tWypozyczone`.`pIdUzytkownicy`
ORDER BY
`myDB`.`tWypozyczone`.`pIdWypozyczone`
ASC

Wiem, że w tym przypadku mógłbym skorzystać z klasy QSqlRelationalTableModel ale chciałbym wiedzieć jak tworzyć własne modele. Zależy mi na tym aby zrozumieć jak tworzyć index na dane we własnym modelu.

Mogę też dać przykład "zapytania w zapytaniu" ale to już byłby zbyt zaawansowany poziom.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0