Seite 1 von 1

[signal] rowsInserted und rowsAboutToBeInserted

Verfasst: 24. März 2011 09:47
von forgoden
Die beiden Funktionen als Signale aus der QAbstractItemModel ergibt sich für mich keinen Sinn.

Warum wird rowsInserted auch vor dem Einfügen der Items aufgerufen? Also noch vor dem Auftauchen der Items im Model wird sie schon aufgerufen. Dadurch stürzt das Programm ab, wenn ich auf Items zugreife, die noch gar nicht existieren. Ich dachte das gehört eher zur Funktion rowsAboutToBeInserted, so wie das Dokument beschreibt?

Verfasst: 24. März 2011 09:58
von franzf
Wie kommst du darauf, dass rowsInserted VOR dem Einfügen emittiert wird? Nur weil dein Programm crasht?
Welches Model verwendest du? Wie fügst du die Items ein? Wie greifst du dann auf die neuen Item zu? Was sagt dein Debugger (->backtrace)?
Solche Fehler liegen fast nie an Qt, sondern am eigenen Programmcode (der verschwindend kleine Rest nennt sich "Bug" und taucht meist nur in recht wenig betretenen Ecken des Funktionsumfangs auf - rowsInserted etc. gehören nicht dazu.)

Also:
Bitte zeig uns deinen Code, an dem wir den Fehler nachvollziehen können. Am besten in Form eines minimalen, kompilierbaren Beispiels.

Verfasst: 24. März 2011 10:43
von forgoden
mainwindows.cpp

Code: Alles auswählen

	model = new QStandardItemModel;
	item = new QStandardItem("Objekte");
	model->setHorizontalHeaderItem(0, item); 

connect( model, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( rowsInserted( QModelIndex, int, int ) ));

Code: Alles auswählen

void MainWindow::rowsInserted( const QModelIndex & parent, int start, int end ) {

	qDebug() << "ctrl pressed" << treeWidget->ctrlkey;
	
	if ((parent.row() == -1) && treeWidget->ctrlkey) {
		for ( ; start <= end; ++start) {
			qDebug() << "[insert] " << model->item(start, 0); // hier stürzt es ab
		}
	}
}
geerbte treeview: (treeWidget ist in Wirklichkeit eine geerbte TreeView)

Code: Alles auswählen

void TreeView::dragMoveEvent(QDragMoveEvent *event) {

	QTreeView::dragMoveEvent(event);

	if ( event->keyboardModifiers() & Qt::ControlModifier)
		ctrlkey=true;
	else ctrlkey=false;

}
Vor kurzem habe ich herausgefunden dass rowsInserted nur funktioniert wenn ich Befehle wie model->appendRow(item); ausführe.

Nicht aber wenn ich MouseDrag die items klone oder verschiebe. In beiden Fällen reagiert rowsInserted spät

Wie ich darauf komme, erfahre ich durch
qDebug() << "[insert] " << model->item(0, 0);
wenn ich diesen Befehl einmal in rowsInserted implementiere und einmal manuell wenn ich Taste G drücke.
Habe ich 2 Items im Model, ziehe ich den ersten nach unten (so dass der 2. Item nach oben kommt) so sehe ich immer noch die Speicheradresse vom ersten item.


Was ist backtrace?

Verfasst: 24. März 2011 10:54
von forgoden
Abhilfe wäre wenn ich mit
void TreeView::dropEvent(QDropEvent *event);
ein Signal schicke? Ob es dann funkioniert weiss ich nicht. Muss ich noch ausprobieren.

Verfasst: 24. März 2011 10:54
von franzf
Du ignorierst die parents:
http://doc.qt.nokia.com/latest/model-vi ... s-of-items
Da in der Grafik die Angabe zu den rows anschauen!

Verfasst: 25. März 2011 08:44
von forgoden
Okay, wenn ich so schreibe

Code: Alles auswählen

model->index(start, 0, parent).data(ObjectRole);
oder so

Code: Alles auswählen

model->itemFromIndex( model->index(start, 0, parent) )->data(ObjectRole);
in der Funktion rowsInserted schreibe

stürzt es zwar nicht mehr ab, aber die Daten in QVariant bleiben leer. Erst wenn ein zweites Item eingefügt wird, werden die Daten vom ersten Item angezeigt. Das heisst, er greift immer zu früh darauf zu.

Verfasst: 25. März 2011 08:53
von forgoden
Ich gehe mal davon aus dass irgendwo die Funktion von Qt in DropEvent zuerst die items in Model kopieren lässt, dadurch wird die Funktion rowsInserted aufgerufen. Und dann erst werden die Daten geschrieben.

Verfasst: 25. März 2011 09:34
von franzf
Kannst du bitte deinen Code mal in ein .zip packen und hier anhängen (ALLE Binaries bitte löschen).
Ich bin mir ziemlich sicher, dass du irgendwo einen Fehler einbaust. Ohne dem kompletten für das Problem relevanten Code kann man nicht helfen.

Verfasst: 25. März 2011 13:56
von forgoden
okay hier ist es.

die Klasse object.h ist noch nicht fertig, deswegen einige Merkwürdigkeiten. Hat aber mit dem eigentlichen Problem nichts zu tun denk ich.

Also man fügt einfach Items hinzu mit der Taste "Einfg".
Man klickt auf die Items, um Informationen zu erhalten (debug)

Bei der Ausgabe in der Funktion "rowsInserted" soll int-value als Speicheradresse und den Namen des Items ausgeben. Beim Einfügen macht es keine Probleme damit.

Nur beim schieben und kopieren (mit strg-Taste) von Items zeigt value und Name leer.

Schleifen wie

Code: Alles auswählen

if ((parent.row() == -1) && treeWidget->ctrlkey) {
		for ( ; start <= end; ++start) {
sind natürlich nicht vernünftig - werde ich später weiter ausbauen, sobald das eigentliche Problem behoben ist.

Ich hoffe meine codes sind vollständig. Sind binaries mit exe-Dateien gemeint?

Verfasst: 26. März 2011 19:12
von forgoden
Konnte einer diesen Fehler reproduzieren?


Ich habe zwar mit dropEvent das Problem gelöst indem ich die Werte (parent, start und end) aus dem Signal rowsInserted zwischenspeichere, daraufhin sendet dropEvent ein Signal aus und eine extra Funktion fixed_rowsInserted wird ausgelöst und übernimmt diese Werte... aber schön ist das Ganze nicht

Verfasst: 27. März 2011 10:50
von franzf
Das schaut mir mittlerweile nach nem Bug her, evtl. in QStandardItemModel. Ich hab den Test etwas ausgeweitet, die Indizes passen nicht. Ich werd mal andere Models ausprobieren und in den Source schauen. Mal gucke...