summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-03-25 13:17:07 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-03-27 16:42:34 +0100
commitf29b73d0026db64d7b2d1ca049461b784c98cecc (patch)
treeb01f3d5204060868371cb4e133bd4fbf58092465
parent927a76c9246109f14b51bd9a3cf224d6f987e10d (diff)
axviewer test: Add a metaobject dump
Task-number: QTBUG-82945 Change-Id: If9c84743779acdd199fd67ec2c2f4fc72f58129a Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--tests/manual/axviewer/main.cpp221
1 files changed, 220 insertions, 1 deletions
diff --git a/tests/manual/axviewer/main.cpp b/tests/manual/axviewer/main.cpp
index 6dd5f27..4828009 100644
--- a/tests/manual/axviewer/main.cpp
+++ b/tests/manual/axviewer/main.cpp
@@ -31,15 +31,25 @@
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
+#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
+#include <QtWidgets/QVBoxLayout>
+
+#include <QtGui/QFontDatabase>
+#include <QtGui/QScreen>
#include <QtCore/QCommandLineOption>
#include <QtCore/QCommandLineParser>
#include <QtCore/QDebug>
+#include <QtCore/QMetaMethod>
+#include <QtCore/QMetaObject>
+#include <QtCore/QPair>
#include <QtCore/QStringList>
#include <QtCore/QSysInfo>
@@ -61,6 +71,195 @@ static inline bool isOptionSet(int argc, char *argv[], const char *option)
[option] (const char *arg) { return !qstrcmp(arg, option); });
}
+using rightAlignNumber = QPair<int, int>; // Use as str << rightAlignNumber(value, width)
+
+QTextStream &operator<<(QTextStream &str, const rightAlignNumber &r)
+{
+ auto oldWidth = str.fieldWidth();
+ str.setFieldWidth(r.second);
+ auto oldAlignment = str.fieldAlignment();
+ str.setFieldAlignment(QTextStream::AlignRight);
+ str << r.first;
+ str.setFieldAlignment(oldAlignment);
+ str.setFieldWidth(oldWidth);
+ return str;
+}
+
+QTextStream &operator<<(QTextStream &str, const QMetaEnum &me)
+{
+ const int keyCount = me.keyCount();
+ str << me.name() << ' ' << keyCount << " keys";
+ if (me.isFlag())
+ str << " [flag]";
+ if (me.isScoped())
+ str << " [scoped]";
+ const int maxLogCount = std::min(6, keyCount);
+ str << " {";
+ for (int k = 0; k < maxLogCount; ++k) {
+ if (k)
+ str << ", ";
+ str << me.key(k) << " = " << me.value(k);
+ }
+ if (maxLogCount < keyCount)
+ str << ",...";
+ str << '}';
+ return str;
+}
+
+QTextStream &operator<<(QTextStream &str, const QMetaClassInfo &mc)
+{
+ str << '"' << mc.name() << "\": \"" << mc.value() << '"';
+ return str;
+}
+
+QTextStream &operator<<(QTextStream &str, const QMetaProperty &mp)
+{
+ str << mp.typeName() << ' ' << mp.name();
+ if (mp.isWritable())
+ str << " [writable]";
+ if (mp.isResettable())
+ str << " [resettable]";
+ if (mp.isDesignable())
+ str << " [designable]";
+ if (mp.isStored())
+ str << " [stored]";
+ if (mp.isUser())
+ str << " [user]";
+ if (mp.isConstant())
+ str << " [constant]";
+ if (mp.isFinal())
+ str << " [final]";
+ if (mp.isRequired())
+ str << " [required]";
+ if (mp.isFlagType())
+ str << " [flag]";
+ if (mp.isEnumType())
+ str << " [enum " << mp.enumerator().name() << ']';
+ if (mp.hasNotifySignal())
+ str << " [notify " << mp.notifySignal().name() << ']';
+ return str;
+}
+
+QTextStream &operator<<(QTextStream &str, const QMetaMethod &m)
+{
+ switch (m.access()) {
+ case QMetaMethod::Private:
+ str << "private ";
+ break;
+ case QMetaMethod::Protected:
+ str << "protected ";
+ break;
+ case QMetaMethod::Public:
+ break;
+ }
+ str << m.typeName() << ' ' << m.methodSignature();
+ switch (m.methodType()) {
+ case QMetaMethod::Method:
+ break;
+ case QMetaMethod::Signal:
+ str << " [signal]";
+ break;
+ case QMetaMethod::Slot:
+ str << " [slot]";
+ break;
+ case QMetaMethod::Constructor:
+ str << " [ct]";
+ break;
+ }
+ if (auto attributes = m.attributes()) {
+ str << " attributes: " << Qt::hex << Qt::showbase << attributes
+ << Qt::dec << Qt::noshowbase;
+ }
+ if (const int count = m.parameterCount()) {
+ str << " Parameters: ";
+ const auto parameterNames = m.parameterNames();
+ const auto parameterTypes = m.parameterTypes();
+ for (int p = 0; p < count; ++p) {
+ if (p)
+ str << ", ";
+ str << parameterTypes.at(p) << ' ' << parameterNames.at(p);
+ }
+ }
+ return str;
+}
+
+static void formatMetaObject(QTextStream &str, const QMetaObject *mo, const QByteArray &indent)
+{
+ str << indent << "--- " << mo->className() << " ---\n";
+
+ const int classInfoOffset = mo->classInfoOffset();
+ const int classInfoCount = mo->classInfoCount();
+ if (classInfoOffset < classInfoCount) {
+ str << indent << " Class Info of " << mo->className() << ": "
+ << classInfoOffset << ".." << classInfoCount << '\n';
+ for (int i = classInfoOffset; i < classInfoCount; ++i) {
+ str << indent << " " << rightAlignNumber(i, 3) << ' '
+ << mo->classInfo(i) << '\n';
+ }
+ }
+
+ const int enumOffset = mo->enumeratorOffset();
+ const int enumCount = mo->enumeratorCount();
+ if (enumOffset < enumCount) {
+ str << indent << " Enums of " << mo->className() << ": " << enumOffset
+ << ".." << enumCount << '\n';
+ for (int e = enumOffset; e < enumCount; ++e)
+ str << indent << " " << rightAlignNumber(e, 3) << ' ' << mo->enumerator(e) << '\n';
+ }
+
+ const int methodOffset = mo->methodOffset();
+ const int methodCount = mo->methodCount();
+ if (methodOffset < methodCount) {
+ str << indent << " Methods of " << mo->className() << ": " << methodOffset
+ << ".." << methodCount << '\n';
+ for (int m = methodOffset; m < methodCount; ++m)
+ str << indent << " " << rightAlignNumber(m, 3) << ' ' << mo->method(m) << '\n';
+ }
+
+ const int propertyOffset = mo->propertyOffset();
+ const int propertyCount = mo-> propertyCount();
+ if (propertyOffset < propertyCount) {
+ str << indent << " Properties of " << mo->className() << ": " << propertyOffset
+ << ".." << propertyCount << '\n';
+ for (int p = propertyOffset; p < propertyCount; ++p)
+ str << indent << " " << rightAlignNumber(p, 3) << ' ' << mo->property(p) << '\n';
+ }
+}
+
+QTextStream &operator<<(QTextStream &str, const QMetaObject &o)
+{
+ QVector<const QMetaObject *> klasses;
+ for (auto s = &o; s; s = s->superClass())
+ klasses.prepend(s);
+
+ QByteArray indent;
+ for (auto k : klasses) {
+ formatMetaObject(str, k, indent);
+ indent += " ";
+ }
+ return str;
+}
+
+class TextDialog : public QDialog
+{
+public:
+ explicit TextDialog(const QString &text, QWidget *parent = nullptr);
+};
+
+TextDialog::TextDialog(const QString &text, QWidget *parent) : QDialog(parent)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ auto layout = new QVBoxLayout(this);
+ auto pe = new QPlainTextEdit(text, this);
+ pe->setReadOnly(true);
+ pe->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
+ layout->addWidget(pe);
+
+ auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this);
+ layout->addWidget(buttonBox);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+}
+
class MainWindow : public QMainWindow
{
Q_OBJECT
@@ -68,6 +267,9 @@ public:
MainWindow();
bool setControl(const QString &clsid);
+public slots:
+ void showMetaObject();
+
private:
QAxWidget *m_axWidget;
};
@@ -91,7 +293,9 @@ MainWindow::MainWindow()
toolbar->setObjectName(QLatin1String("ToolBar"));
addToolBar(Qt::TopToolBarArea, toolbar);
- QAction *action;
+ QAction *action = fileMenu->addAction("Dump MetaObject",
+ this, &MainWindow::showMetaObject);
+ toolbar->addAction(action);
#ifdef QT_DIAG_LIB
action = fileMenu->addAction("Dump Widgets",
this, [] () { QtDiag::dumpAllWidgets(); });
@@ -117,6 +321,21 @@ bool MainWindow::setControl(const QString &clsid)
return result;
}
+void MainWindow::showMetaObject()
+{
+ auto mo = m_axWidget->metaObject();
+ QString dump;
+ {
+ QTextStream str(&dump);
+ str << *mo;
+ }
+ auto dialog = new TextDialog(dump, this);
+ dialog->setWindowTitle(QLatin1String("MetaObject of ") + QLatin1String(mo->className()));
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->resize(screen()->geometry().size() * 2 / 3);
+ dialog->show();
+}
+
int main(int argc, char* argv[])
{
if (isOptionSet(argc, argv, "-s"))