I have a class that is a subclass of QObject that I would like to register as a meta-type. The QObject documentation states that the copy-constructor should be private, but the QMetaType documentation states that a type should have a public default constructor, a public copy constructor, and a public destructor.
I can override QObject's private copy constructor and declare a public copy constructor, but is this safe/ok/right?
class MyClass : public QObject {
Q_OBJECT
public:
MyClass();
MyClass(const MyClass &other);
~MyClass();
}
Q_DECLARE_METATYPE(MyClass);
It is not safe to make a QObject's copy constructor public. You can register a class pointer as the metatype, though. i.e.:
Q_DECLARE_METATYPE(MyClass*);
That's how Qt handles it with QObject and QWidget.
What you're asking for is perfectly ok. You can't use QObject
s copy constructor (it's private) in the implementation of your copy constructor, but then again, no-one forces you to:
class MyClass : public QObject {
Q_OBJECT
public:
// ...
MyClass( const MyClass & other )
: QObject(), i( other.i ) {} // NOTE: calling QObject default ctor
// ...
private:
int i;
};
Depending on what services you need from QObject
, you need to copy some properties over from other
, in both the copy ctor and the copy assignment operator. E.g., if you use QObject for it's dynamic properties feature, you'd need to copy those, too:
MyClass( const MyClass & other )
: QObject(), i( other.i )
{
Q_FOREACH( const QByteArray & prop, other.dynamicPropertyNames() )
setProperty( prop.constData(), other.property( prop.constData() ) );
}
Likewise, if you want to maintain signal/slot connections.
I use a separate copyValue(const MyClass & other)
function to copy the data members that define the "values" of the MyClass
instance. That ensures that I don't break the assumption of QObject
unique identity, while still being able to duplicate the parts of the class that are defined at compile time.
QTFruit fruit;
QScriptValue scriptedFruitObject = engine.newQObject(&fruit);
engine.globalObject().setProperty("fruit", scriptedFruitObject);
engine.setDefaultPrototype(qMetaTypeId<QTFruit>(),
scriptedFruitObject);
QScriptValue qsMetaObject =
engine.newQMetaObject(fruit.metaObject());
engine.globalObject().setProperty("eLedState",
qsMetaObject);
int t = engine.evaluate("eLedState.On").toInteger();
engine.evaluate("fruit.fromJScript(1)");
engine.evaluate("fruit.fromJScript(eLedState.On)");
engine.evaluate("fruit.fromJScript(eLedState.TriState)");
//Create the ctor funtion
QScriptValue qsFruitCtor =
engine.newFunction(QTFruitConstructor,
scriptedFruitObject);
//Expose ctor to javascript
engine.globalObject().setProperty("QTFruit", qsFruitCtor);
//Create the QTFruit object
engine.evaluate("var res = new QTFruit()");
engine.evaluate("res.fromJScript(eLedState.TriState)");
class QTFruit : public QObject
{
Q_OBJECT
public:
enum eLedState { Off, On , TriState};
Q_ENUMS( eLedState )
QTFruit();
~QTFruit();
QTFruit( const QTFruit & other );
//QTFruit(const QTFruit& other);
public slots:
void fromJScript(eLedState state);
//void on_inputSpinBox1_valueChanged(int value);
//void on_buttonClicked();
// void fromJScript();
//private:
};
Q_DECLARE_METATYPE(QTFruit*)
Q_DECLARE_METATYPE(QTFruit)
QScriptValue QTFruitConstructor(QScriptContext * /* context */,
QScriptEngine *interpreter);
And the cpp:
QScriptValue QTFruitConstructor(QScriptContext * /* context */,
QScriptEngine *interpreter)
{
//return interpreter->toScriptValue(new QTFruit());
//or
return interpreter->toScriptValue(QTFruit()); //but then you need the public copy contructor
}
QTFruit::QTFruit( const QTFruit & other )
: QObject()
{
}
QTFruit::~QTFruit()
{
}
QTFruit::QTFruit()
{
}
void QTFruit::fromJScript(eLedState state)
{
int t = 0;
}