Forum: PC-Programmierung Qt5 -> Qt6: QMetaType und QVariant, wie jetzt neu schreiben?


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich versuche gerade, qsstv auf Qt6 zu portieren, weil Qt5 an einer 
Stelle auf neueren MacOS seltsames Verhalten zeigt (QSlider) und 
beschrieben ist, dass dies in Qt6 korrigiert worden sei.

Ich stolpere über eine Konstellation aus QMetaType und QVariant, etwa ab 
hier:

https://github.com/dl8dtl/qsstv/blob/7b9697c9c748df9c2ea7245d5750dc6b61954686/xmlrpc/maiaXmlRpcServerConnection.cpp#L187
1
  int metatype = 0;
2
  QByteArray retTypeName = getReturnType(obj->metaObject(), method, argTypes);
3
  if(!retTypeName.isEmpty()  && retTypeName != "QVariant")
4
    {
5
      metatype = QMetaType::type(retTypeName.data());
6
      if(metatype == 0) // lookup failed
7
        return false;
8
    }
9
10
  QGenericArgument arg[10];
11
  for(int n = 0; n < args.count(); ++n)
12
    arg[n] = QGenericArgument(args[n].typeName(), args[n].constData());
13
14
  QGenericReturnArgument retarg;
15
  QVariant retval;
16
  QString test(QMetaType::typeName(metatype));
17
  if(metatype != 0)
18
    {
19
            if( test=="void")
20
              {
21
                retval=QVariant();
22
                  retTypeName="";
23
24
              }
25
            else
26
      {
27
        retval = QVariant(metatype, (const void *)0);

QMetaType::type() is laut Doku in Qt6 deprecated, gleichermaßen das 
::typeName etwas weiter unten. Würde aber zumindest noch compilieren, 
jedoch das Bilden einer QVariant aus diesem "metatype" (der ja hier ein 
"int" ist) ganz unten schlägt fehl, denn in Qt6 wird an dieser Stelle 
direkt ein QMetaType-Objekt erwartet.

Qt6:
1
QVariant(QMetaType type, const void *copy = nullptr)

Bis Qt5 dagegen hieß das an dieser Stelle:
1
QVariant(int typeId, const void *copy)

Irgendwie bekomme ich da gerade einen Knoten im Kopf, warum dieser 
Metatype einmal irgendwas numerisches sein soll und das andere Mal nun 
nicht mehr.

Lustig ist, dass die ganze Geschichte mit ::type trotzdem noch in der 
Qt6.3 Doku als Beispiel drin steht …

Ich vermute mal, dass man jetzt statt des "int metatype" direkt ein 
QMetaType-Objekt mittels
1
QMetaType   fromName(QByteArrayView typeName)
ableiten sollte und dieses dann für die QVariant verwenden. Passt das?

Gibt's hier jemanden, der damit schon mal was gemacht hat?

von Georg A. (georga)


Lesenswert?

Jörg W. schrieb:
> Gibt's hier jemanden, der damit schon mal was gemacht hat?

Nö, hab aber schon immer planlos Dinge in Qt zusammengesteckt, die laut 
Typ passen. War dafür C++ nicht da? ;)

Es gibt doch in Qt6 einen QMetaType(int typeId)-Konstruktor, damit 
solltest du doch vom metatype-int im Code auch wieder hinkommen, oder?

von Bernd B. (bbrand)


Lesenswert?

Ich habe zwar auch noch nicht mit QMetaType gearbeitet, aber wenn ich 
die Qt5 und Qt6 APIs vergleiche, denke ich, dass es so gehen könnte 
(ohne Gewähr :-):
1
  int metatypeId = 0;
2
  QByteArray retTypeName = getReturnType(obj->metaObject(), method, argTypes);
3
  if(!retTypeName.isEmpty()  && retTypeName != "QVariant")
4
    {
5
      metatypeId = QMetaType::fromName(retTypeName.data()).id();
6
      if(metatypeId == 0) // lookup failed
7
        return false;
8
    }
9
10
  QGenericArgument arg[10];
11
  for(int n = 0; n < args.count(); ++n)
12
    arg[n] = QGenericArgument(args[n].typeName(), args[n].constData());
13
14
  QGenericReturnArgument retarg;
15
  QVariant retval;
16
  QMetaType metatype(metatypeId);
17
  QString test(metatype.name());
18
  if(metatypeId != 0) // kann man sich eigentlich sparen, da weiter oben schon auf 0 geprüft wird
19
    {
20
            if( test=="void")
21
              {
22
                retval=QVariant();
23
                  retTypeName="";
24
              }
25
            else
26
      {
27
        retval = QVariant(metatype, (const void *)0);

Gruß,
Bernd

von Oliver S. (oliverso)


Lesenswert?

Da könntest du auch gleich im original
1
retval = QVariant(QMetaType(metatype), (const void *)0);

schreiben.
Wenn’s dem restlichen Codestil entsprechen soll, noch mit der alten 
Version per define für Qt<6.

Alles in allem ist das halt furchtbares rumdoktern an mehrfach durch die 
Versionsmangel gedrehtem Code. Das wurde wohl mal für eine 
(Früh-)Version von Qt4 geschrieben, dann notdürftig an Qt5 angepasst, 
und jetzt kommt Qt6. Vermutlich müsste man das ganze Metatyp-rumgemurkse 
auf einer Ebene weit oberhalb dieses Codes mal runderneuern. Allerdings 
kommt dann aber bestimmt jemand, und beschwert sich, daß das sich dann 
nicht mehr unter Qt4 kompilieren lässt.

Ich sag da nur: viel Spaß…

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Danke erstmal fürs Feedback, ich habe jetzt etwas ähnliches, allerdings 
#if QT_VERSION gespicktes, zusammengeknotet, was zumindest compiliert. 
Werde ich dann nochmal gegen eure Vorschläge vergleichen, vielleicht 
ergibt das ja weniger #ifdefs am Ende.

Oliver S. schrieb:
> Alles in allem ist das halt furchtbares rumdoktern an mehrfach durch die
> Versionsmangel gedrehtem Code. Das wurde wohl mal für eine
> (Früh-)Version von Qt4 geschrieben, dann notdürftig an Qt5 angepasst,
> und jetzt kommt Qt6.

Ja, den Eindruck habe ich auch. Gut, Qt5 ist aktuell eh 
Mindestvoraussetzung für qsstv, also 4 muss nicht mehr sein. Das Dumme 
ist, dass ich allerdings diesen XML-RPC-Server selbst noch nie benutzt 
habe und eigentlich auch keine Ambitionen dazu habe, insofern wüsste ich 
jetzt nicht, was ich da anschließend wie testen soll.

Der wichtigste Test ist jetzt für mich erstmal, ob die nervigen 
"Denkpausen", die ich mit Qt5 hatte, und bei denen der Code immer durch 
zig Stackebenen in QSlider herum drehte, anschließend weg sind.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bernd B. schrieb:
> denke ich, dass es so gehen könnte

Naja, dann doch nicht ganz. QMetaType::fromName() gibt's in Qt5 noch 
nicht, und auch der Konstruktor für QVariant() kann in Qt5 nur die 
typeId nehmen, in Qt6 nur den Metatype selbst. Damit geht es nicht 
ohne #ifdef an diesen Stellen ab.

Deine Idee aber, den originalen metatype in metatypeId umzubenennen und 
später noch einen echten Metatype draus zu machen, habe ich übernommen.

Wen's interessiert, das Resultat ist jetzt hier:

https://github.com/dl8dtl/qsstv/blob/9df87ea2c49c94c10495e26d68d48e4c49a4c174/xmlrpc/maiaXmlRpcServerConnection.cpp#L182

Leider hat es nur bedingt geholfen: die Macports haben noch Qt 6.2 
dabei, der Performance-Bug mit dem QSlider ist aber erst in 6.3 
repariert. Damit musste ich nun trotzdem noch den manuellen Würgaraund 
einbauen. Aber naja, zumindest ist das Projekt dann (bis auf noch ein 
paar Warnungen) allmählicht Qt6 ready, falls der Autor das gern mal 
übernehmen möchte. Für meinen Teil ist das Ziel zumindest erreicht, das 
alles auf dem M1 Macbook benutzen zu können.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.