2016-04-04 16 views
0

Ich beabsichtige, ein eigenes Elementmodell zu erstellen, das von QAbstractItemModel abgeleitet ist. Das Modell enthält keine Daten, sondern ein Datenrepository. Dieses Repository gibt Signale aus, nachdem Elemente eingefügt, entfernt, umbenannt usw. wurden.So leiten Sie Signale in einem QAbstractItemModel-Wrappermodell weiter

Wenn sich etwas im Repository ändert, muss das Objektmodell diese Signale weiterleiten.

jedoch das Repository eigenständige Signale wie void itemRemoved(int index); hat, während QAbstractItemModel beginnen hat/Endpaare von Schutzfunktionen (und Signalen) wie beginInsertRows() und endInsertRows().

Wie soll ich damit umgehen? Z.B. Ich könnte einen Schlitz wie die folgenden zu dem itemRemoved() Signal Repository verbinden:

void RepositoryItemRemoved(int i) 
{ 
    beginInsertRows(QModelIndex(), i, i); 
    endInsertRows(); 
} 

auf dem obigen Beispiel Basierend: Ist es gültig beginInsertRows()/endInsertRows() sequently nach rufe eine Zeile im Repository eingesetzt wurde?

+0

Haben Sie eine Vorstellung davon, welche Nebenwirkungen auftreten können, wenn Sie den vorgesehenen Verwendungszweck nicht einhalten? – Silicomancer

+1

Um ehrlich zu sein, macht dieses Design für mich keinen Sinn. Ein einzelnes Signal nach dem Einfügen oder Entfernen der Daten sollte ausreichen, um die Aufgabe zu erledigen. Es ist vielleicht nur in einem Kontext mit mehreren Threads problematisch, aber dann würde ein einfacher Mutex den Trick machen. Ich könnte etwas vermissen, aber ich hatte viele Fälle, in denen Qt Internals suboptimal entworfen sind. – dtech

Antwort

1

Ich hatte ein ähnliches Szenario, wo die Daten in einem anderen Objekt sind, und das Modell ist nur ein Wrapper und nur erstellt, wenn dieser Datensatz in einer Ansicht angezeigt wird. Ich habe einen Zeiger auf das Modellobjekt im Datenobjekt verwendet und überprüft, ob es bei Einfügeoperationen null ist, und falls nicht, rufe beginInsertRows() und endInsertRows() durch. Da diese Daten geschützt sind, müsste die Datenklasse natürlich als Freund der Modellklasse deklariert werden.

Die Dokumentation betont, dass es wichtig ist, beginInsertRows() zu nennen, bevor alle Daten eingefügt:

Wenn insertRows Neuimplementierung() in einer Unterklasse, können Sie diese Funktion aufrufen müssen, bevor die Daten in das Modell der zugrunde liegenden Datenspeicher Einfügen ...

... Andernfalls können sich die Ansichten in einem ungültigen Zustand befinden.

Sie sollten mit einer Ansicht testen oder alternativ die tatsächliche Implementierung in der Quelle untersuchen.

0

Ich hatte auch etwas ähnliches Szenario, nur in meinem Fall wickelte das Qt-Modell das zugrundeliegende Modell etwas wörtlicher: Das zugrundeliegende Modell enthielt ausreichend mehr Daten, als die Ansicht wissen musste. Daher lasse ich das Qt-Modell eine eigene Liste von kleinen Teilen des Datenelements eines jeden zugrunde liegenden Modells enthalten, damit die Ansicht/der Delegierte damit umgehen kann. So sind die Schlitze, die Updates aus dem zugrunde liegenden Modell Verarbeitung sah wie folgt aus:

void RepositoryItemRemoved(int i) 
{ 
    beginRemoveRows(QModelIndex(), i, i); 
    removeModelItem(i); 
    endRemoveRows(); 
} 

Eine solche Konstruktion löste das Problem der ungültigen Zustand Sicht, obwohl es für die Anwendungsfälle, in denen unpraktisch sein kann, lassen die Qt-Modell seine eigene Artikel Liste enthalten würde bedeuten, die ausreichende Menge an Daten zu duplizieren, mit denen gearbeitet wird.