mirror of
https://github.com/rgriebl/brickstore.git
synced 2026-01-28 20:38:33 -06:00
Better introspection via the dev console
This commit is contained in:
@@ -43,13 +43,160 @@ public:
|
||||
QmlException(const QList<QQmlError> &errors, const char *msg)
|
||||
: Exception(msg)
|
||||
{
|
||||
for (auto &error : errors) {
|
||||
m_message.append(u"\n"_qs);
|
||||
m_message.append(error.toString());
|
||||
}
|
||||
for (auto &error : errors)
|
||||
m_message = m_message % u'\n' % error.toString();
|
||||
}
|
||||
};
|
||||
|
||||
static QString stringifyType(QMetaType mt)
|
||||
{
|
||||
if (mt.metaObject()) {
|
||||
int qei = mt.metaObject()->indexOfClassInfo("QML.Element");
|
||||
if (qei >= 0) {
|
||||
const auto name = QString::fromLatin1(mt.metaObject()->classInfo(qei).value());
|
||||
if (name == u"auto")
|
||||
return QString::fromLatin1(mt.metaObject()->className()).section(u"::"_qs, -1);
|
||||
else
|
||||
return name;
|
||||
}
|
||||
}
|
||||
switch (mt.id()) {
|
||||
case QMetaType::QString : return u"string"_qs;
|
||||
case QMetaType::QStringList : return u"list<string>"_qs;
|
||||
case QMetaType::QVariant : return u"var"_qs;
|
||||
case QMetaType::QVariantList: return u"list"_qs;
|
||||
case QMetaType::QVariantMap : return u"object"_qs;
|
||||
case QMetaType::QSize : return u"size"_qs;
|
||||
case QMetaType::QColor : return u"color"_qs;
|
||||
case QMetaType::Float :
|
||||
case QMetaType::Double : return u"real"_qs;
|
||||
default : return QLatin1String(mt.name());
|
||||
}
|
||||
}
|
||||
|
||||
static QString stringify(const QVariant &value, int level = 0, bool indentFirstLine = false);
|
||||
|
||||
static QString stringifyQObject(const QObject *o, const QMetaObject *mo, int level, bool indentFirstLine)
|
||||
{
|
||||
QString str;
|
||||
QString indent = QString(level * 2, QLatin1Char(' '));
|
||||
QString nextIndent = QString((level + 1) * 2, QLatin1Char(' '));
|
||||
|
||||
bool isGadget = mo->metaType().flags().testFlag(QMetaType::IsGadget);
|
||||
|
||||
if (indentFirstLine)
|
||||
str.append(indent);
|
||||
|
||||
str = str % QLatin1String(mo->className()) % u" {\n";
|
||||
|
||||
if (!isGadget && mo->superClass()) {
|
||||
str = str % nextIndent % u"superclass: "
|
||||
% stringifyQObject(o, mo->superClass(), level + 1, false) % u'\n';
|
||||
}
|
||||
|
||||
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
|
||||
QMetaProperty p = mo->property(i);
|
||||
QVariant value = isGadget ? p.readOnGadget(o) : p.read(o);
|
||||
str = str % nextIndent % stringifyType(p.metaType()) % u' '
|
||||
% QLatin1String(p.name()) % u": " % stringify(value, level + 1, false) % u'\n';
|
||||
}
|
||||
|
||||
for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
|
||||
QMetaMethod m = mo->method(i);
|
||||
switch (m.methodType()) {
|
||||
case QMetaMethod::Slot: break;
|
||||
case QMetaMethod::Method: break;
|
||||
default: continue;
|
||||
}
|
||||
const auto pnames = m.parameterNames();
|
||||
QStringList params;
|
||||
for (int pi = 0; pi < m.parameterCount(); ++pi)
|
||||
params.append(stringifyType(m.parameterMetaType(pi)) % u' ' % QLatin1String(pnames.at(pi)));
|
||||
|
||||
str = str % nextIndent % stringifyType(m.returnMetaType()) % u' ' % QLatin1String(m.name())
|
||||
% u'(' % params.join(u", ") % u")\n";
|
||||
}
|
||||
|
||||
str = str % indent % u'}';
|
||||
return str;
|
||||
}
|
||||
|
||||
static QString stringifyQGadget(const void *g, const QMetaObject *mo, int level, bool indentFirstLine)
|
||||
{
|
||||
Q_ASSERT(g && mo && mo->metaType().flags().testFlag(QMetaType::IsGadget));
|
||||
return stringifyQObject(reinterpret_cast<const QObject *>(g), mo, level, indentFirstLine);
|
||||
}
|
||||
|
||||
static QString stringify(const QVariant &value, int level, bool indentFirstLine)
|
||||
{
|
||||
QString str;
|
||||
QString indent = QString(level * 2, QLatin1Char(' '));
|
||||
QString nextIndent = QString((level + 1) * 2, QLatin1Char(' '));
|
||||
|
||||
if (indentFirstLine)
|
||||
str.append(indent);
|
||||
|
||||
switch (int(value.typeId())) {
|
||||
case QMetaType::QVariantList: {
|
||||
QListIterator<QVariant> it(value.toList());
|
||||
if (!it.hasNext()) {
|
||||
str.append(u"[]");
|
||||
} else {
|
||||
str = str.append(u"[\n");
|
||||
|
||||
while (it.hasNext()) {
|
||||
str = str % stringify(it.next(), level + 1, true);
|
||||
if (it.hasNext())
|
||||
str.append(u',');
|
||||
str.append(u'\n');
|
||||
}
|
||||
str = str % indent % u']';
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QMetaType::QVariantMap: {
|
||||
QMapIterator<QString, QVariant> it(value.toMap());
|
||||
if (!it.hasNext()) {
|
||||
str.append(u"{}");
|
||||
} else {
|
||||
str.append(u"{\n");
|
||||
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
str = str % nextIndent % it.key() % u": " % stringify(it.value(), level + 1, false);
|
||||
if (it.hasNext())
|
||||
str.append(u',');
|
||||
str.append(u'\n');
|
||||
}
|
||||
str = str % indent % u'}';
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QMetaType::QString: {
|
||||
str = str % u'"' % value.toString().remove(u"\0"_qs) % u'"';
|
||||
break;
|
||||
}
|
||||
case QMetaType::QObjectStar: {
|
||||
QObject *o = qvariant_cast<QObject *>(value);
|
||||
if (!o) {
|
||||
str.append(u"<invalid QObject>");
|
||||
break;
|
||||
}
|
||||
str.append(stringifyQObject(o, o->metaObject(), level, false));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
QMetaType meta(value.typeId());
|
||||
if (meta.flags().testFlag(QMetaType::IsGadget))
|
||||
str.append(stringifyQGadget(value.data(), meta.metaObject(), level, false));
|
||||
else
|
||||
str.append(value.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
ScriptManager::ScriptManager(QQmlEngine *engine)
|
||||
: m_engine(engine)
|
||||
@@ -146,8 +293,9 @@ bool ScriptManager::executeString(const QString &s)
|
||||
Q_ASSERT(m_engine);
|
||||
|
||||
const char script[] =
|
||||
"import BrickStore 1.0\n"
|
||||
"import QtQml 2.12\n"
|
||||
"import BrickStore\n"
|
||||
"import BrickLink\n"
|
||||
"import QtQml\n"
|
||||
"QtObject {\n"
|
||||
" property var bl: BrickLink\n"
|
||||
" property var bs: BrickStore\n"
|
||||
@@ -161,15 +309,17 @@ bool ScriptManager::executeString(const QString &s)
|
||||
m_rootObject = component.create();
|
||||
|
||||
QQmlExpression e(m_engine->rootContext(), m_rootObject, s);
|
||||
qCDebug(LogScript).noquote() << "#" << s;
|
||||
auto result = e.evaluate();
|
||||
qCInfo(LogScript).noquote() << "#" << s;
|
||||
bool isUndefined = false;
|
||||
auto result = e.evaluate(&isUndefined);
|
||||
if (e.hasError()) {
|
||||
qCWarning(LogScript).noquote() << "> ERROR:" << e.error().toString();
|
||||
qCInfo(LogScript).noquote() << "> <error>:" << e.error().toString();
|
||||
return false;
|
||||
} else if (isUndefined) {
|
||||
qCInfo(LogScript, "> <undefined>");
|
||||
return true;
|
||||
} else {
|
||||
auto rs = result.toString();
|
||||
if (!rs.isEmpty())
|
||||
qCDebug(LogScript).noquote() << ">" << rs;
|
||||
qCInfo(LogScript).noquote() << ">" << stringify(result, 1, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user