QSqlQueryModel + benutzerdefinierte Rollen

Alles rund um die Programmierung mit Qt
Antworten
NoRulez
Beiträge: 208
Registriert: 19. Juni 2007 15:43

QSqlQueryModel + benutzerdefinierte Rollen

Beitrag von NoRulez »

Hallo,

wie kann ich in einem QSqlQueryModel benutzerdefinierte Rollen setzen?
Solll heißen das ich beispielsweise für Spalte 1 und 2 Qt::DisplayRole und für Spalte 3 und 4 Qt::UserRole habe wo meine Werte drin stehen?

LG NoRulez
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das was drin steht ist immer Qt::DisplayRole.
Deine Möglichkeit ist, von QSqlQueryModel abzuleiten und die data() Methode überschreiben und falls der übergebene index.column() == 3 oder 4, gibst du bei Qt::DIsplayRole deine Werte zurück.

Allerdings wird es komplizierter, wenn deine View Editierbar ist, und der User in der Spalte, wo deine UserRole-Werte angezeigt werden, denkt er editiert die Zelle, die auch im Header steht.
Also auch noch setData() überschreiben und dir eine intelligente map ausdenken, die bei einem editierten Wert in Spalte 3 oder 4 einen Wert ins Model schreibt, der dann bei ernueter Anzeige den korrekten Wert wieder in der View anzeigt...
NoRulez
Beiträge: 208
Registriert: 19. Juni 2007 15:43

Beitrag von NoRulez »

ich habe das überladen der data() funktion schon probiert, jedoch wenn alle Qt:DisplayRole sind, wie liefere ich da ein Qt::UserRole zurück?

Code: Alles auswählen

switch(index.column()) {
  case Column3:
      // Dieser Wert soll statt Qt::DisplayRole ein Qt::UserRole sein
    break;
  case Column4:
      // Dieser Wert soll statt Qt::DisplayRole ein Qt::UserRole sein
    break;
}
LG NoRulez
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Schon mal ein einfaches if auf den Parameter role probiert?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Wenn du die View "austricksen" willst hast du natürlich ein Problem.
Ich habe halt angenommen, dass dein Model selber weiß, welche UserRole-Daten anzuzeigen sind.
Aber so wie es scheint hast du verschwiegen, dass du die Daten anzeigen willst, die vorher mit setData als UserRole eingefügt wurden ;)

Dann musst du die vorgegebene Schnittstelle erweitern und eine eigene Methode "setUserRole" und das übergebene index auf ein QVariant mappen.

Oder (einfacher) du verwendest einen Delegate in deiner View.

Aber warum sollen dem User eigentlich Fake-Daten angezeigt werden?

// edit
Upsala hat theoretisch Recht.
Nur ist dann das Problem, dass deine eigentlichen Daten für immer verborgen bleiben, denn die Daten hält das Model, und wenn ein data() auf die DisplayRole immer die UserRole zurückgibt - oops ;)
Desweiteren hab ich keine Schimmer, wie die SqlModels ihre Daten in die DB schreiben, aber wahrscheinlich wird hier auch die DisplayRole abgefragt, und dann stehen auf einmal die falschen Daten in der DB :P
NoRulez
Beiträge: 208
Registriert: 19. Juni 2007 15:43

Beitrag von NoRulez »

OK, anscheinend habe ich zu wenig Informationen mitgeteilt.

@upsala: Klar habe ich schon mit if und switch herumprobiert.

Mir geht es eigentlich um folgendes, das ich Spalte 1 und 2 anzeigen will, und Spalte 3 und 4 nur zum internen Rechnen benötige.

Als zum Rechnen mit den internen Werten würde ich folgendes verwenden, wobei internal1 und internal2 eben nicht für den User sichtbar sein soll:

Code: Alles auswählen

qint32 userVar1 = model->data(model->index(0, 0), Qt::DisplayRole).toInt();
qint32 userVar2 = model->data(model->index(0, 1), Qt::DisplayRole).toInt();

qint32 internal1 = model->data(model->index(0, 2), Qt::UserRole).toInt();
qint32 internal2 = model->data(model->index(0, 3), Qt::UserRole).toInt();
Da wie Du (@franf) schon gesagt hast, Qt::DisplayRole standard ist bei QSqlQueryModel.
Wie kann ich diese faken?
Also das ich Qt::DisplayRole für die entsprechenden Spalten auf Qt::UserRole abändern kann?

LG NoRulez
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Hab ich doch schon ausführlich beschrieben.
Am einfachsten nimmst du dir ein Delegate!
Spicken darfst du bei QSqlRelationalDelegate
NoRulez
Beiträge: 208
Registriert: 19. Juni 2007 15:43

Beitrag von NoRulez »

Das Problem ist nur das ich kein Delegate verwenden kann.
Und zurückschreiben will ich bei diesem Model auch nichts.

Ich will quasi nur die 4 Columns haben, wobei die letzen 2 halt intern verwendet werden.

Wenn ich KD Chart das Model übergebe, versucht dieses nun von 4 Spalten ein DIagramm zu zeichnen, was natürlich falsch ist, da nur in den ersten 2 Spalten die Daten dafür da sind, und die anderen um die X und Y achsen zu zeichnen
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Also interessiert dich Spalte 3 und 4 gar nicht?
Der KD Chart greift nur lesend auf dein Model zu?

Super.
Gaukel ihm doch anstatt falscher Daten ne falsche Spaltenzahl vor...
Also von QSqlTableModel ableiten und nur columnCount() implementieren -> 2 zurückgeben.
Das sollte dein Problem hoffentlich lösen.

Wenn du aber noch anderswo auf das Model zugreifst und veränderst - keine Ahnung ob KD Chart auf Änderungen regieren kann - geht das natürlich auch nicht.
Dann brauchst du nur für KD Chart ein Wrapper-Model, welches in allen nötigen Methoden einfach die vom QSqlTableModel (->als Member deklarieren und im Konstruktor übergeben) zurückgibt. Bis auf columnCount, da sollte nur 2 returned werden.
NoRulez
Beiträge: 208
Registriert: 19. Juni 2007 15:43

Beitrag von NoRulez »

franzf hat geschrieben:Also interessiert dich Spalte 3 und 4 gar nicht?
Doch, dies Spalte 2 beispielsweise wird aus spalte 3 und 4 berechnet. Somit ist zwar Spalte 2 im Diagramm sichtbar, 3 und 4 haben jedoch dann nichts da drin verloren.
franzf hat geschrieben:Gaukel ihm doch anstatt falscher Daten ne falsche Spaltenzahl vor...
So einfach ist das leider nicht, den wenn ich nur eine 2 zurückliefere, dann bekomme ich auch die anderen Werte nicht mehr aus dem Model.

LG NoRulez
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Also eine neue Voraussetzung...
Und wie du das anstellst weiß ich nicht. Du berechnest Spalte 2 aus 3 und 4. Geschieht das schon "dynmisch"? Oder findet die Berechnung im SqlQuery statt?
Denn du verlangst jetzt soviel nachträgliche Magie, die so gar nicht vorgesehen ist.
Ein Model verwaltet Daten. Wenn du Auswählen willst machst du dies am besten mit einem vorgelagerten Proxy-Model. Reicht dir das nicht bleibt nur noch eins: Ein eigenes Model schreiben. Und wieder der Tip: Schau dich bei QSqlTableModel schlau, wie die das machen.

// Nachtrag:
Zeig doch einfach mal, was du gerade schon hast. Auch die Sql-Tabelle und wie Daten berechnet werden. Bisher hast du kaum konkrete Info herausgerückt.
NoRulez
Beiträge: 208
Registriert: 19. Juni 2007 15:43

Beitrag von NoRulez »

Es ist eine sehr flache Tabelle, die Abfrage sieht in etwa wie folgt aus:

Code: Alles auswählen

SELECT '' as total, '' as subtotal, a, b FROM mytable
total und subtotal wird hier beispielsweise im Model berechnet.
Mir ist sehr wohl klar das dies vermutlich mit Stored Procedures und/oder mit Berechnungen im Statement eleganter gelöst werden kann, aber:
1.) Gibt es in dieser DB keine Stored Procedures
2.) Die Berechnung kann hier nicht durchgeführt werden, da ich hier ein QTime in eine Gleitkommazahl umwandeln muss, und daraus die Summe berechne
Wenn mir jedoch jemand sagen könnte wie ich aus einer Uhrzeit in eine Gleitkommazahl in SQLite konvertiere, wäre natürlich so gut wie alles gelöst.

LG NoRulez
Antworten