CopperSpice Overview
MetaObject Macros

The following table details the "Q_" macros which have been maintained or modified for CopperSpice. These changes expand functionality, provide more flexibility, and leverage new capabilities added in new versions of C++. The second column shows examples of how the macro or define might appear in your source code.

Define Replacement Description
Q_ARG   — Unchanged in CS
Q_CLASSINFO CS_CLASSINFO("project", "KitchenSink")
Q_DECLARE_EXTENSION_INTERFACE Remove, no replacement is required Used internally with CsDesigner
Q_DECLARE_FLAGS Replacement Code ➜  Example shown below
Q_DECLARE_INTERFACE CS_DECLARE_INTERFACE(ShapeInterface, "id")
Q_DECLARE_METATYPE CS_DECLARE_METATYPE(TYPE)
Q_DECLARE_OPERATORS_FOR_FLAGS   — Unchanged in CS
Q_DECLARE_TR_FUNCTIONS   — Unchanged in CS
Q_DECLARE_TYPEINFO Remove, no replacement is required
Q_DISABLE_COPY   — Unchanged in CS
Q_ENUMS CS_ENUM(Spices)
[ Added macro ] CS_REGISTER_ENUM( enum Spices {mint, basil}; ) Enums must be registered when used as the value of a Property
Q_EMIT Not required Signal & Slot declarations need to appear in the appropriate "public", "protected", or "private" specifier
Q_FLAGS CS_FLAG(Food_Enum, Food_Flag)
Q_GADGET CS_GADGET(Ginger) Class name must be passed
Q_INTERFACES CS_INTERFACES() ➜  Example shown below
Q_INVOKABLE CS_INVOKABLE() ➜  Example shown below
Q_OBJECT CS_OBJECT(Ginger) Class name must be passed
[ Added macro ] CS_OBJECT_MULTIPLE(Ginger, QWidget) Class name is passed as the first parameter

For multiple inheritance the second parameter is the first parent class
Q_OUTOFLINE_TEMPLATES Removed since compilers after C++11 understand templates
Q_PROPERTY CS_PROPERTY() ➜  Example shown below
Q_RETURN_ARG   — Unchanged in CS
Q_SCRIPT_DECLARE_QMETAOBJECT   — Unchanged in CS
Q_SIGNAL CS_SIGNAL() ➜  Example shown below
Q_SIGNALS Remove, place signal macros in a public section All signals are registered individually
Q_SLOT CS_SLOT() ➜  Example shown below
Q_SLOTS Remove, no replacement is required All slots are registered individually or declared as a method
[ Added macro ] Overloaded Signals & Slots ➜  Example shown below
[ Added macro ] CS_TAG("myTag", myMethod()) Associates a tag with a method, refer to QMetaMethod::tag()

Replacement for Q_DECLARE_FLAGS

class testFlags
{
CS_OBJECT(testFlags)
public:
// Q_DECLARE_FLAGS(enumName, flagName)
using flagName = QFlags<enumName>;
// Q_DECLARE_FLAGS(Option, OptionFlags)
using OptionFlags = QFlags<Option>;
}

CS_INTERFACES Example

class testInterfaces
{
CS_OBJECT(testInterfaces)
CS_INTERFACES(QSqlDriverFactoryInterface, QFactoryInterface)
CS_INTERFACES(QTextCodecFactoryInterface, QFactoryInterface)
}

CS_INVOKABLE Example

class testInvokable
{
CS_OBJECT(testInvokable)
public:
CS_INVOKABLE_CONSTRUCTOR_1(Public, explicit QObject(QObject *parent = nullptr))
CS_INVOKABLE_CONSTRUCTOR_2(QObject, QObject *)
CS_INVOKABLE_METHOD_1(Public, bool callable_Method(QString data))
CS_INVOKABLE_METHOD_2(callable_Method)
private:
CS_INVOKABLE_CONSTRUCTOR_1(Private, MyClass(QObject * = nullptr))
CS_INVOKABLE_CONSTRUCTOR_2(MyClass, QObject *)
}

CS_PROPERTY Example

Each property is declared using a separate macro. Any data type can be used for the property, including template data types like QMap<int, QString>.

class testProperty
{
CS_OBJECT(testProperty)
CS_PROPERTY_READ(title, getTitle)
CS_PROPERTY_WRITE(title, setTitle)
CS_PROPERTY_RESET(title, resetTitle)
CS_PROPERTY_NOTIFY(title, titleChanged)
CS_PROPERTY_REVISION(title, 31415)
CS_PROPERTY_DESIGNABLE(title, true)
CS_PROPERTY_DESIGNABLE_NONSTATIC(title, true)
CS_PROPERTY_SCRIPTABLE(title, false)
CS_PROPERTY_SCRIPTABLE_NONSTATIC(title, isScriptTitle())
CS_PROPERTY_STORED(title, true)
CS_PROPERTY_STORED_NONSTATIC(title, m_title.isEmpty())
CS_PROPERTY_USER(title, true )
CS_PROPERTY_USER_NONSTATIC(title, (m_title.size() > 5))
CS_PROPERTY_CONSTANT(title)
CS_PROPERTY_FINAL(title)
CS_PROPERTY_READ(map, getMapData)
CS_PROPERTY_WRITE(map, setMapData)
public:
void setTitle(const QString &newTitle);
QString getTitle() const;
void setMapData(const QMap<int, QString> &newMap);
QMap<int, QString> getMapData() const;
}

CS_SIGNAL Declaration Example

class testSignal
{
CS_OBJECT(testSignal)
public:
CS_SIGNAL_1(Public, void clicked(bool checked = false))
CS_SIGNAL_2(clicked, checked)
// overload 1
CS_SIGNAL_1(Public, void released())
CS_SIGNAL_OVERLOAD(released, ())
// overload 2
CS_SIGNAL_1(Public, void released(int leftbutton, int rightbutton))
CS_SIGNAL_OVERLOAD(released, (int, int), leftbutton, rightbutton)
protected:
CS_SIGNAL_1(Protected, void mySignal(void(*someVar)(int, bool)))
CS_SIGNAL_2(mySignal, someVar)
private:
CS_SIGNAL_1(Private, void mapMethod(QList<QMap<double, int>> data))
CS_SIGNAL_2(mapMethod, data)
}

CS_SLOT Declaration Example

A slot method only needs to be registered using the CS_SLOT macro when it is passed to connect() by name. If your code is only using method pointers in calls to connect(), simply declare your slots as you would declare any other method.

class testSlot
{
CS_OBJECT(testSlot)
public:
CS_SLOT_1(Public, void closePB(QObject *SomeObject = nullptr))
CS_SLOT_2(closePB)
CS_SLOT_1(Public, bool closePB_clicked())
CS_SLOT_2(closePB_clicked)
// overload 1
CS_SLOT_1(Public, void released())
CS_SLOT_OVERLOAD(released, ())
// overload 2
CS_SLOT_1(Public, void released(bool isDone))
CS_SLOT_OVERLOAD(released, (bool))
protected:
CS_SLOT_1(Protected, int mySlotName(int count))
CS_SLOT_2(mySlotName)
private:
CS_SLOT_1(Private, void refresh(QString data))
CS_SLOT_2(refresh)
}

Declaring and Using Overloaded Signals & Slots

The valueChanged() signal for QSpinBox has two overloads. The following code shows how they are declared in CopperSpice.

// overload 1 from QSpinBox
CS_SIGNAL_1(Public, void valueChanged(const QString &text))
CS_SIGNAL_OVERLOAD(valueChanged, text)
// overload 2 from QSpinBox
CS_SIGNAL_1(Public, void valueChanged(int newValue))
CS_SIGNAL_OVERLOAD(valueChanged, newValue)

When calling connect() using method pointers, the second parameter is a pointer to the signal and the fourth parameter is a pointer to the slot. If either the signal or the slot is overloaded additional syntax will be required so the compiler knows which overload to use. By adding the cs_mp_cast<int> syntax the compiler now has enough information to select the correct overload. In this example the overload which accepts an int data type will be used.

QSpinBox *spinBox = new QSpinBox;
QProgressBar *progressBar = new QProgressBar;
connect(spinBox, cs_mp_cast<int>(&QSpinBox::valueChanged), progressBar, &QProgressBar::setValue);