2012-02-04 3 views
2

J'ajoute QScript à mon application Qt. J'ai déjà ajouté des métadonnées et utilisé certaines des fonctions de métadonnées pour interroger le code C++. Cela fonctionne bien - je peux naviguer dans la hiérarchie des objets et imprimer les valeurs (y compris les enums). Mais, je n'arrive pas à voir des enums travailler dans le script Qt.QtScript plus enums

J'ai ma classe ...

class HalPin : public QObject 
{ 
Q_OBJECT 
public: 
enum EHalPinType 
{ 
    Bit = HAL_BIT, 
    Float = HAL_FLOAT, 
    S32 = HAL_S32, 
    U32 = HAL_U32 
}; 

enum EHalPinDirection 
{ 
    In = HAL_IN, 
    Out = HAL_OUT, 
    IO = HAL_IO 
}; 
Q_ENUMS(EHalPinType) 
Q_ENUMS(EHalPinDirection) 

public: 
explicit HalPin(QObject *parent = 0); 

signals: 

public slots: 

}; 

Q_DECLARE_METATYPE(HalPin::EHalPinType) 
Q_DECLARE_METATYPE(HalPin::EHalPinDirection) 
Q_DECLARE_METATYPE(HalPin*) 

J'ai une autre classe qui a une méthode qui prend les énumérations comme arguments ...

class EmcHal : public QObject 
{ 
Q_OBJECT 
public: 
explicit EmcHal(QString moduleName, QObject *parent = 0); 

signals: 

public slots: 
QObject *createHalPin(HalPin::EHalPinType, HalPin::EHalPinDirection, QString name); 
}; 

Cette classe est exposée dans une autre classe - désolé, j'aurais dû simplifier l'exemple. Si j'écris le code JScript suivant,

var nextPagePin1 = Emc.hal.createHalPin(); 

je reçois une erreur je pense ...

SyntaxError: too few arguments in call to createHalPin(); candidates are createHalPin(HalPin::EHalPinType,HalPin::EHalPinDirection,QString) 

Ainsi, il semble que les types de ENUM sont connus pour QtScript.

Ce que j'ai du mal à faire est de définir les arguments enum de jscript. J'ai essayé beaucoup de combinaisons ...

Bit 
EHalPinType.Bit 
HalPin.EHalPinType.Bit 

et beaucoup plus.

Si je tente d'utiliser des entiers, je reçois ...

TypeError: cannot call createHalPin(): argument 1 has unknown type `HalPin::EHalPinType' (register the type with qScriptRegisterMetaType()) 

qui semble impliquer JScript ne connaît pas mes énumérations.

Des suggestions? Dois-je utiliser qRegisterMetaType ou qScriptRegisterMetaType pour accéder à mes énumérations? La documentation ne suggère pas que je doive faire cela. Ai-je besoin d'implémenter les fonctions de conversion pour la méthode qScriptRegisterMetaType.

Ou est ma syntaxe juste faux pour le jscript?

Est-ce que quelqu'un a un exemple de travail?

Merci, Frank

Répondre

2

Pour répondre à ma question ...

Eh bien, pas tant une réponse à pourquoi, mais un "meh, cela fonctionne" par exemple ...

Comme je l'ai mentionné ci-dessus, je n'ai pas pu obtenir les enums travaillant à la fois dans les métadonnées et jscript en même temps en utilisant les macros qt. Même si l'énumération est apparue dans qscript (j'ai vérifié dans le navigateur du débogueur de script), il n'a pas évalué à l'entier correct.

J'ai dû ajouter un QMetaObject pour l'énumération. Cela m'a donné les éléments enum, et corriger les valeurs entières.

Mais cela me donnait toujours l'erreur de type inconnu, donc je devais utiliser qScriptRegisterMetaType() pour enregistrer les fonctions de conversion pour les types.

C'est la classe que j'utilise pour 1 enum. C'est aussi minimal que je peux le faire. Je devrais être capable d'utiliser des macros pour les réduire un peu plus, mais il y a des limites à ce qui peut être macroisé, à cause des exigences qt-moc.

#include <QObject> 
#include <QMetaType> 
#include <QScriptEngine> 

#include "hal.h" 


class CEHalPinType : public QObject 
{ 
Q_OBJECT 
public: 
    explicit CEHalPinType(QObject *parent = 0) : QObject(parent) {} 
    explicit CEHalPinType(const CEHalPinType &other) : QObject(other.parent()) {} 
    virtual ~CEHalPinType() {} 

    enum EHalPinType 
    { 
     Bit = HAL_BIT, 
     Float = HAL_FLOAT, 
     S32 = HAL_S32, 
     U32 = HAL_U32 
    }; 
    Q_ENUMS(EHalPinType) 

private: 
    static QScriptValue toScriptValue(QScriptEngine *engine, const EHalPinType &s) 
    { 
     return engine->newVariant((int)s); 
    } 

    static void fromScriptValue(const QScriptValue &obj, EHalPinType &s) 
    { 
     s = (EHalPinType)obj.toInt32(); 
    } 
    static QScriptValue qscriptConstructor(QScriptContext *context, QScriptEngine *engine) 
    { 
     return engine->newQObject(new CEHalPinType(context->argument(0).toQObject()), QScriptEngine::ScriptOwnership); 
    } 
public: 
    static void Init(const char *name, QScriptEngine *engine) 
    { 
     qScriptRegisterMetaType(engine, toScriptValue, fromScriptValue); 
     QScriptValue metaObject = engine->newQMetaObject(&staticMetaObject, engine->newFunction(qscriptConstructor)); 
     engine->globalObject().setProperty(name, metaObject); 
    } 
}; 

Q_DECLARE_METATYPE(CEHalPinType::EHalPinType) 

Et mon JScript ressemble ...

var nextPagePin = Emc.hal.createHalPin(EHalPinType.Bit,EHalPinDirection.In,"nexis.NextPage"); 
0

Oops. J'ai sauté l'arme sur celui-ci. Bien que le script ait fonctionné, j'ai cassé la capacité de convertir des enums en chaînes en utilisant les données qmetaobject.

Et il ne semble pas y avoir une façon automatique de le faire.

Le problème est que j'ai déplacé les énumérations hors de la classe où les propriétés qui ont utilisé les énumérations ont été définies. Bien que la compilation Q_ENUMS et Q_PROPERTY, si j'utilise le QMetaProperty pour lire une énumération, cela ne fonctionne pas. Le QVariant qui est retourné affiche le type de données correct, "CEHalPinType :: EHalPinType", mais échoue le test isEnum() et canConvert (QVariant :: String) échoue aussi. En effet, lorsque le code qmetaobject recherche le type enum, il ne regarde que dans la classe en cours et ses classes dérivées. Il ne recherche pas d'autres classes. C'est pourquoi cela fonctionnait quand l'enum était un membre de la classe qui avait aussi les propriétés. Mon travail, comme suggéré ailleurs, consistait à créer mon propre QMap d'énumérations connues, en stockant le nom de la chaîne dans le mappage qmetaobject. J'ai utilisé une classe de base basée sur un modèle et utilisé T :: staticMetaObject pour obtenir l'objet Meta.