Hello everyone,
i'm facing a problem for which i'm not finding any solution... i've tried pretty much everything, but i believe i may not understand something in the required logic here.
My project has reached a certain complexity point "code" speaking, and it's hard to provide all the relevant source code since everything depends on a lot of other stuff.
Basically, i have defined custom types:
// File is being Moc'ed.
namespace REA {
class IntList : public QList<qint32> {};
class UIntList : public QList<quint32> {};
class RgbList : public QList<QRgb> {};
class CharList : public QList<QChar> {};
class RgbToUIntHash : public QHash<QRgb,quint32> {};
class StringToStringHash : public QHash<QString,QString> {};
class StringToImageHash : public QHash<QString,QImage> {};
// And a lot more types...
// ------------------------------------- Rectangles ------------------------------------- //
// Rectangle.
class Rect
: public QRect { public:
// Members.
bool isRelative;
// Constructors.
: QRect(p, s
), isRelative
(r
) {};
// QDataStream friend serialization stuff.
friend QDataStream
& operator<<
(QDataStream
& s, Rect
const &r
) { return s <<
*(QRect*)&r << r.
isRelative;
};
friend QDataStream
& operator>>
(QDataStream
& s, Rect
&r
) { return s >>
*(QRect*)&r >> r.
isRelative;
};
};
// Float rectangle.
public:
// Members.
bool isRelative;
// Constructors.
: QRectF(p, s
), isRelative
(r
) {};
// QDataStream friend serialization stuff.
friend QDataStream
& operator<<
(QDataStream
& s, RectF
const &r
) { return s <<
*(QRectF*)&r << r.
isRelative;
};
friend QDataStream
& operator>>
(QDataStream
& s, RectF
&r
) { return s >>
*(QRectF*)&r >> r.
isRelative;
};
};
// And a lot more custom types...
};
Q_DECLARE_METATYPE(REA::IntList);
Q_DECLARE_METATYPE(REA::UIntList);
Q_DECLARE_METATYPE(REA::RgbList);
Q_DECLARE_METATYPE(REA::StringList);
Q_DECLARE_METATYPE(REA::CharList);
Q_DECLARE_METATYPE(REA::RgbToUIntHash);
Q_DECLARE_METATYPE(REA::StringToStringHash);
Q_DECLARE_METATYPE(REA::StringToImageHash);
Q_DECLARE_METATYPE(REA::Rect);
Q_DECLARE_METATYPE(REA::RectF);
// And the same for any other type...
// File is being Moc'ed.
namespace REA {
class IntList : public QList<qint32> {};
class UIntList : public QList<quint32> {};
class RgbList : public QList<QRgb> {};
class StringList : public QStringList {};
class CharList : public QList<QChar> {};
class RgbToUIntHash : public QHash<QRgb,quint32> {};
class StringToStringHash : public QHash<QString,QString> {};
class StringToImageHash : public QHash<QString,QImage> {};
// And a lot more types...
// ------------------------------------- Rectangles ------------------------------------- //
// Rectangle.
class Rect : public QRect {
public:
// Members.
bool isRelative;
// Constructors.
Rect (QPoint const &p=QPoint(0,0), QSize const &s=QSize(0,0), bool r=false)
: QRect(p, s), isRelative(r) {};
// QDataStream friend serialization stuff.
friend QDataStream& operator<< (QDataStream& s, Rect const &r) { return s << *(QRect*)&r << r.isRelative; };
friend QDataStream& operator>> (QDataStream& s, Rect &r) { return s >> *(QRect*)&r >> r.isRelative; };
};
// Float rectangle.
class RectF : public QRectF {
public:
// Members.
bool isRelative;
// Constructors.
RectF (QPointF const &p=QPointF(0,0), QSizeF const &s=QSizeF(0,0), bool r=false)
: QRectF(p, s), isRelative(r) {};
// QDataStream friend serialization stuff.
friend QDataStream& operator<< (QDataStream& s, RectF const &r) { return s << *(QRectF*)&r << r.isRelative; };
friend QDataStream& operator>> (QDataStream& s, RectF &r) { return s >> *(QRectF*)&r >> r.isRelative; };
};
// And a lot more custom types...
};
Q_DECLARE_METATYPE(REA::IntList);
Q_DECLARE_METATYPE(REA::UIntList);
Q_DECLARE_METATYPE(REA::RgbList);
Q_DECLARE_METATYPE(REA::StringList);
Q_DECLARE_METATYPE(REA::CharList);
Q_DECLARE_METATYPE(REA::RgbToUIntHash);
Q_DECLARE_METATYPE(REA::StringToStringHash);
Q_DECLARE_METATYPE(REA::StringToImageHash);
Q_DECLARE_METATYPE(REA::Rect);
Q_DECLARE_METATYPE(REA::RectF);
// And the same for any other type...
To copy to clipboard, switch view to plain text mode
Then at runtime, i register everything:
#define RegisterStreamOperators(name) qRegisterMetaTypeStreamOperators<name>(#name)
// Register lists / maps / hashes meta-types for streaming.
RegisterStreamOperators(REA::IntList);
RegisterStreamOperators(REA::UIntList);
RegisterStreamOperators(REA::RgbList);
RegisterStreamOperators(REA::StringList);
RegisterStreamOperators(REA::CharList);
RegisterStreamOperators(REA::RgbToUIntHash);
RegisterStreamOperators(REA::StringToStringHash);
RegisterStreamOperators(REA::StringToImageHash);
RegisterStreamOperators(REA::Rect);
RegisterStreamOperators(REA::RectF);
#undef RegisterStreamOperators
#define RegisterStreamOperators(name) qRegisterMetaTypeStreamOperators<name>(#name)
// Register lists / maps / hashes meta-types for streaming.
RegisterStreamOperators(REA::IntList);
RegisterStreamOperators(REA::UIntList);
RegisterStreamOperators(REA::RgbList);
RegisterStreamOperators(REA::StringList);
RegisterStreamOperators(REA::CharList);
RegisterStreamOperators(REA::RgbToUIntHash);
RegisterStreamOperators(REA::StringToStringHash);
RegisterStreamOperators(REA::StringToImageHash);
RegisterStreamOperators(REA::Rect);
RegisterStreamOperators(REA::RectF);
#undef RegisterStreamOperators
To copy to clipboard, switch view to plain text mode
Then, i have this very special class called "Variable", which acts a very similar way as QVariant does (It actually uses a QVariant internally). The Variable class allows me to define an i/o direction for a value, a name, and defines streaming operators to save / load lists of variables.
Then on my GUI project, i have subclassed QItemEditorFactory to allow me to dynamically instantiate editors based on the type of variable being edited:
#include "CustomItemEditorFactory.h"
// Editor classes.
#include "REATypes.h"
// Basic types.
#include <QLineEdit>
// Custom types.
#include "WgtBoolEditor.h"
#include "WgtPointEditor.h"
#include "WgtPointFEditor.h"
#include "WgtSizeEditor.h"
#include "WgtSizeFEditor.h"
#include "WgtRectEditor.h"
#include "WgtRectFEditor.h"
#include "WgtWFNodeUidEditor.h"
#include "WgtMemberPicker.h"
using namespace REA;
CustomItemEditorFactory
::CustomItemEditorFactory (const QItemEditorFactory* standardFactory
)}
switch (type) {
case QVariant::Bool: return new WgtBoolEditor
(parent
);
case QVariant::Point: return new WgtPointEditor
(parent
);
case QVariant::PointF: return new WgtPointFEditor
(parent
);
case QVariant::Size: return new WgtSizeEditor
(parent
);
case QVariant::SizeF: return new WgtSizeEditor
(parent
);
default:
if (type==qMetaTypeId<REA::Rect>()) return new WgtRectEditor(parent);
else if (type==qMetaTypeId<REA::RectF>()) return new WgtRectFEditor(parent);
else if (type==qMetaTypeId<REA::UniqueIdentifier>()) return new WgtWFNodeUidEditor(parent);
else if (type==qMetaTypeId<REA::MemberPath>()) return new WgtMemberPicker(parent);
else return _standardFactory->createEditor(type, parent);
};
}
// Any custom type...
return "value";
else
return _standardFactory->valuePropertyName(type);
}
void CustomItemEditorFactory::installAsStandardFactory () {
}
#include "CustomItemEditorFactory.h"
// Editor classes.
#include "REATypes.h"
// Basic types.
#include <QLineEdit>
// Custom types.
#include "WgtBoolEditor.h"
#include "WgtPointEditor.h"
#include "WgtPointFEditor.h"
#include "WgtSizeEditor.h"
#include "WgtSizeFEditor.h"
#include "WgtRectEditor.h"
#include "WgtRectFEditor.h"
#include "WgtWFNodeUidEditor.h"
#include "WgtMemberPicker.h"
using namespace REA;
CustomItemEditorFactory::CustomItemEditorFactory (const QItemEditorFactory* standardFactory)
: QItemEditorFactory(), _standardFactory(standardFactory) {
}
QWidget* CustomItemEditorFactory::createEditor (QVariant::Type type, QWidget* parent) const {
switch (type) {
case QVariant::String: return new QLineEdit(parent);
case QVariant::Bool: return new WgtBoolEditor(parent);
case QVariant::Point: return new WgtPointEditor(parent);
case QVariant::PointF: return new WgtPointFEditor(parent);
case QVariant::Size: return new WgtSizeEditor(parent);
case QVariant::SizeF: return new WgtSizeEditor(parent);
default:
if (type==qMetaTypeId<REA::Rect>()) return new WgtRectEditor(parent);
else if (type==qMetaTypeId<REA::RectF>()) return new WgtRectFEditor(parent);
else if (type==qMetaTypeId<REA::UniqueIdentifier>()) return new WgtWFNodeUidEditor(parent);
else if (type==qMetaTypeId<REA::MemberPath>()) return new WgtMemberPicker(parent);
else return _standardFactory->createEditor(type, parent);
};
}
QByteArray CustomItemEditorFactory::valuePropertyName (QVariant::Type type) const {
// Any custom type...
if ( type==QVariant::Bool ||
type==QVariant::Point || type==QVariant::PointF ||
type==QVariant::Size || type==QVariant::SizeF ||
type>=QVariant::UserType)
return "value";
else
return _standardFactory->valuePropertyName(type);
}
void CustomItemEditorFactory::installAsStandardFactory () {
QItemEditorFactory::setDefaultFactory(new CustomItemEditorFactory(QItemEditorFactory::defaultFactory()));
}
To copy to clipboard, switch view to plain text mode
All this works flawlessly, i have no problem doing something like:
WgtVariableEditor *wgt = new WgtVariableEditor(this, var);
WgtVariableEditor *wgt = new WgtVariableEditor(this, var);
To copy to clipboard, switch view to plain text mode
The Variable editor widget important part looks like that:
WgtVariableEditor
::WgtVariableEditor (QWidget *parent, Variable
const &var
): QWidget(parent,
0), _widget
(0), _variable
(var
) { // Create and set layout for this widget.
lyt->setSpacing(0);
lyt->setMargin(0);
setLayout(lyt);
// Retrieve editor widget object.
// Create the widget and store it's metaobject.
_widget
= f
->createEditor
((QVariant::Type)_variable.
value.
userType(),
this);
lyt->addWidget(_widget);
// Retrieve metaobject.
// Retrieve value property name.
// Set widget value.
_widget->setProperty(vpName, _variable.value);
// Get property index.
int pIndex = mo->indexOfProperty(vpName);
// Retrieve metamethod for notification signal.
QMetaMethod signal = mo
->property
(pIndex
).
notifySignal();
// Finally generate signal name.
connect(_widget, sName.toLatin1(), this, SLOT(onValueEdition()));
}
WgtVariableEditor::WgtVariableEditor (QWidget *parent, Variable const &var)
: QWidget(parent, 0), _widget(0), _variable(var) {
// Create and set layout for this widget.
QHBoxLayout *lyt = new QHBoxLayout(this);
lyt->setSpacing(0);
lyt->setMargin(0);
setLayout(lyt);
// Retrieve editor widget object.
QItemEditorFactory const *f = QItemEditorFactory::defaultFactory();
// Create the widget and store it's metaobject.
_widget = f->createEditor((QVariant::Type)_variable.value.userType(), this);
lyt->addWidget(_widget);
// Retrieve metaobject.
QMetaObject const *mo = _widget->metaObject();
// Retrieve value property name.
QByteArray vpName = f->valuePropertyName((QVariant::Type)_variable.value.userType());
// Set widget value.
_widget->setProperty(vpName, _variable.value);
// Get property index.
int pIndex = mo->indexOfProperty(vpName);
// Retrieve metamethod for notification signal.
QMetaMethod signal = mo->property(pIndex).notifySignal();
// Finally generate signal name.
QString sName = QString("2%1").arg(signal.signature());
connect(_widget, sName.toLatin1(), this, SLOT(onValueEdition()));
}
To copy to clipboard, switch view to plain text mode
Now, my problem is when it comes to editing lists and my QList-based custom types (REA::UIntList, REA::StringList, etc). i have no idea how to proceed. i first have created a template class (WgtListEditor), but Qt doesn't allow to subclass QObject (Nor QWidget, logic) in a template class...
i have tried then many and many other solutions... None of them works, and i got lost in the Qt editor logic.
Can someone please provide me with serious advices, and if possible with a diagram or some pseudo-code based on how my objects are made?
Thank you very much for your time, i appreciate any kind of help you could provide.
Pierre.
[EDIT]i notived my code was complettely messed up with the tabulations and everything... i recomend you switch to "plain" view of code, and copy paste into your favorite editor for a better anc clear view
[/EDIT]
Bookmarks