cast-Verächter - Handhabung QVariant bei Model-View-Programm

Alles rund um die Programmierung mit Qt
Antworten
stimpy
Beiträge: 64
Registriert: 7. März 2006 17:05

cast-Verächter - Handhabung QVariant bei Model-View-Programm

Beitrag von stimpy »

Hallo,

ich habe mich von dem QT-Beispiel "simpletreemodel" inspirieren lassen und habe eine Baumansicht programmiert. Mein Baum besteht aus verketteten Objekten, die von TreeNode abgeleitet sind. Die Funktion getTreeNode() soll mir einen Zeiger auf so einen Knoten liefern. Dazu muß data() bemüht werden.
So richtig leuchtet mir die Verwendung von QVariant nicht ein. Am Ende lande ich doch bei typlosen Zeigern.
Beispielsweise liefert ein Klick auf ein Baumelement dessen Index. Aus diesem Index muß ich einen Zeiger auf das tatsächliche Objekt basteln.
Ohne wilde "Castereien" komme ich da nicht hin, obwohl folgendes Programm funktioniert:

Code: Alles auswählen

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
	if(!index.isValid()) return QVariant();

	if(role == Qt::UserRole)
		return qVariantFromValue(index.internalPointer());

	return QVariant();
}


TreeNode *TreeModel::getNode(const QModelIndex &index)
{
	void  *qobj;
	QVariant variant = data(index, Qt::UserRole);

	if(qVariantCanConvert<void *>(variant))
		qobj = qVariantValue<void *>(variant);

	return static_cast<TreeNode *>(qobj);
};
Geht das nicht schöner, sicherer und eleganter. Ich könnte evtl. statt void-Zeigern QObject-Zeiger nehmen, aber viel besser wäre das auch nicht. Überhaupt ist mir QVariant etwas suspekt...

Danke für jeden sachdienlichen Hinweis!
Volker
Beiträge: 343
Registriert: 30. Juni 2005 05:27

Beitrag von Volker »

Also ich weiss nicht ob das Deiner Definition von schön entspricht, aber ich mach's folgendermaßen:

Code: Alles auswählen

QVariant data = m_fileModel->data(index, FileInfoModel::FileInfoRole);	
if (data.canConvert<QFileInfo>())
	list.push_back(data.value<QFileInfo>());
Damit das funktioniert musst Du allerdings die Klasse die Du in QVariant stecken willst per Makro erst mal für QVariant bekannt machen:
Dazu einfach in den Header deiner Klasse folgendes hinzufügen:

Code: Alles auswählen

Q_DECLARE_METATYPE(QFileInfo)
stimpy
Beiträge: 64
Registriert: 7. März 2006 17:05

Beitrag von stimpy »

Also ich weiss nicht ob das Deiner Definition von schön entspricht...
Ja das finde ich sehr schön, jetzt wird mir auch der Sinn von QVariant langsam klar.

Ich habe mal ein wenig rumprobiert. Ich möchte ja nur die Zeiger auf die Objekte weitergeben und nicht alles rumkopieren. Da werde ich meine Lösung mehr oder weniger behalten. Das Casten an sich werde ich kaum vermeiden können, da ich ja maximal Zeiger auf eine Basisklasse (also TreeNode *) erhalte.

Vielen Dank!
stimpy
Beiträge: 64
Registriert: 7. März 2006 17:05

Auch gefährlich...

Beitrag von stimpy »

Mir ist auch noch afgefallen, daß qobject_cast Blödsinn liefert, wenn nicht
Q_OBJECT in allen Klassendefinitionen (auch in allen Ableitungen) steht.
Er kann dann vermeintlich Dinge zurechtkonvertieren, die eher NULL sein
sollten. :?
skydave
Beiträge: 3
Registriert: 18. Juni 2009 00:48

automatisches dynamic_cast von pointern in QVariants

Beitrag von skydave »

Hi Leute,

ich bin per Forumsuche über diesen thread gestolpert der thematisch sehr nah an meiner folgenden Frage liegt:

Ich speichere pointer auf verschiedene Klassen meines frameworks in QVariants und möchte QVariants vom typ eines Baisklassen pointers als pointer einer abgeleiteten Klasse auslesen. Dabei müsste also von qt intern ein dynamic_cast ausgeführt werden.

Kurz: Ist folgendes irgendwie machbar?

Code: Alles auswählen

class A;
class B; // B erbt von A

qRegisterMetaType<A *>();
qRegisterMetaType<B *>();

B *bPtr = new B;
A *aPtr = bPtr;

QVariant qv = QVariant::fromValue( aPtr ); // QVariant ist nun vom typ A *

// jetzt möchte ich aber den variant als B * auslesen
bool res = qv.canConvert<B *>(); // Problem: liefert false zurück
B *p = qv.value<B *>();               // Problem: liefert 0 zurück

Sieht so aus als ginge das nicht. Ich möchte aber gerne mal die Meinung von Experten dazu hören. Gibts vielleicht elegante Lösungen?

Danke schonmal,
David
Antworten