Added global JS property tree to allow exploring of engine data.

This commit is contained in:
harry 2024-01-16 21:48:13 -05:00
parent 9a9f9541d6
commit dc2d3c26aa
2 changed files with 163 additions and 7 deletions

View File

@ -32,6 +32,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
#include <QHeaderView>
#include <QJSValueIterator> #include <QJSValueIterator>
#ifdef __QT_UI_TOOLS__ #ifdef __QT_UI_TOOLS__
@ -435,10 +436,6 @@ int QtScriptInstance::call(const QString& funcName, const QJSValueList& args)
//printf("Script Call Success!\n"); //printf("Script Call Success!\n");
} }
QJSValue global = engine->globalObject();
printSymbols( global );
return 0; return 0;
} }
//---------------------------------------------------- //----------------------------------------------------
@ -665,9 +662,29 @@ QScriptDialog_t::QScriptDialog_t(QWidget *parent)
mainLayout->addLayout(hbox); mainLayout->addLayout(hbox);
lbl = new QLabel(tr("Output Console:")); tabWidget = new QTabWidget();
mainLayout->addWidget(lbl); mainLayout->addWidget(tabWidget);
mainLayout->addWidget(jsOutput);
tabWidget->addTab(jsOutput, tr("Output Console"));
propTree = new QTreeWidget();
propTree->setColumnCount(3);
propTree->setSelectionMode( QAbstractItemView::SingleSelection );
propTree->setAlternatingRowColors(true);
auto* item = new QTreeWidgetItem();
item->setText(0, QString::fromStdString("Name"));
item->setText(1, QString::fromStdString("Type"));
item->setText(2, QString::fromStdString("Value"));
item->setTextAlignment(0, Qt::AlignLeft);
item->setTextAlignment(1, Qt::AlignLeft);
item->setTextAlignment(2, Qt::AlignLeft);
propTree->setHeaderItem(item);
propTree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
tabWidget->addTab(propTree, tr("Global Properties"));
closeButton = new QPushButton( tr("Close") ); closeButton = new QPushButton( tr("Close") );
closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
@ -725,13 +742,131 @@ void QScriptDialog_t::closeWindow(void)
deleteLater(); deleteLater();
} }
//---------------------------------------------------- //----------------------------------------------------
void QScriptDialog_t::loadPropertyTree(QJSValue& object, QTreeWidgetItem* parentItem)
{
QJSValueIterator it(object);
while (it.hasNext())
{
it.next();
QJSValue child = it.value();
bool isPrototype = it.name() == "prototype";
if (!isPrototype)
{
QTreeWidgetItem* item = new QTreeWidgetItem();
QString value;
const char *type = "unknown";
if (child.isArray())
{
type = "array";
}
else if (child.isBool())
{
type = "bool";
value = QVariant(child.toBool()).toString();
}
else if (child.isCallable())
{
type = "function";
value = "";
}
else if (child.isDate())
{
type = "date";
value = child.toDateTime().toString();
}
else if (child.isError())
{
type = "error";
value = child.toString();
}
else if (child.isNull())
{
type = "null";
value = "null";
}
else if (child.isNumber())
{
type = "number";
value = QVariant(child.toNumber()).toString();
}
else if (child.isRegExp())
{
type = "RegExp";
value.clear();
}
else if (child.isQMetaObject())
{
type = "meta";
value.clear();
auto* meta = child.toQMetaObject();
if (meta != nullptr)
{
value = meta->className();
}
}
else if (child.isObject())
{
type = "object";
value.clear();
auto* obj = child.toQObject();
if (obj != nullptr)
{
auto* meta = obj->metaObject();
if (meta != nullptr)
{
value = meta->className();
}
}
}
else if (child.isString())
{
type = "string";
value = child.toString();
}
item->setText(0, it.name());
item->setText(1, type);
item->setText(2, value);
if (parentItem == nullptr)
{
propTree->addTopLevelItem(item);
}
else
{
parentItem->addChild(item);
}
if (child.isObject())
{
loadPropertyTree(child, item);
}
}
}
}
//----------------------------------------------------
void QScriptDialog_t::updatePeriodic(void) void QScriptDialog_t::updatePeriodic(void)
{ {
//printf("Update JS\n"); //printf("Update JS\n");
FCEU_WRAPPER_LOCK(); FCEU_WRAPPER_LOCK();
if (!emuThreadText.isEmpty()) if (!emuThreadText.isEmpty())
{ {
auto* vbar = jsOutput->verticalScrollBar();
int vbarValue = vbar->value();
bool vbarAtMax = vbarValue >= vbar->maximum();
jsOutput->insertPlainText(emuThreadText); jsOutput->insertPlainText(emuThreadText);
if (vbarAtMax)
{
vbar->setValue( vbar->maximum() );
}
emuThreadText.clear(); emuThreadText.clear();
} }
refreshState(); refreshState();
@ -918,6 +1053,10 @@ void QScriptDialog_t::startScript(void)
refreshState(); refreshState();
QJSValue globals = scriptInstance->getEngine()->globalObject();
loadPropertyTree(globals);
FCEU_WRAPPER_UNLOCK(); FCEU_WRAPPER_UNLOCK();
} }
//---------------------------------------------------- //----------------------------------------------------
@ -951,7 +1090,16 @@ void QScriptDialog_t::logOutput(const QString& text)
} }
else else
{ {
auto* vbar = jsOutput->verticalScrollBar();
int vbarValue = vbar->value();
bool vbarAtMax = vbarValue >= vbar->maximum();
jsOutput->insertPlainText(text); jsOutput->insertPlainText(text);
if (vbarAtMax)
{
vbar->setValue( vbar->maximum() );
}
} }
} }
//---------------------------------------------------- //----------------------------------------------------

View File

@ -10,6 +10,7 @@
#include <QWidget> #include <QWidget>
#include <QDialog> #include <QDialog>
#include <QTabWidget>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QComboBox> #include <QComboBox>
@ -20,6 +21,9 @@
#include <QGroupBox> #include <QGroupBox>
#include <QLineEdit> #include <QLineEdit>
#include <QTextEdit> #include <QTextEdit>
#include <QTreeView>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QJSEngine> #include <QJSEngine>
#include "Qt/main.h" #include "Qt/main.h"
@ -149,6 +153,7 @@ public:
protected: protected:
void closeEvent(QCloseEvent *bar); void closeEvent(QCloseEvent *bar);
void openJSKillMessageBox(void); void openJSKillMessageBox(void);
void loadPropertyTree(QJSValue& val, QTreeWidgetItem* parentItem = nullptr);
QTimer *periodicTimer; QTimer *periodicTimer;
QLineEdit *scriptPath; QLineEdit *scriptPath;
@ -156,7 +161,10 @@ protected:
QPushButton *browseButton; QPushButton *browseButton;
QPushButton *stopButton; QPushButton *stopButton;
QPushButton *startButton; QPushButton *startButton;
QPushButton *clearButton;
QTabWidget *tabWidget;
QTextEdit *jsOutput; QTextEdit *jsOutput;
QTreeWidget *propTree;
QtScriptInstance *scriptInstance; QtScriptInstance *scriptInstance;
QString emuThreadText; QString emuThreadText;