mirror of https://github.com/mgba-emu/mgba.git
Qt: Refactor the script buffer list into a model (#2566)
This commit is contained in:
parent
c1b1f72005
commit
1bda318531
|
@ -252,6 +252,7 @@ if(ENABLE_SCRIPTING)
|
|||
list(APPEND SOURCE_FILES
|
||||
ScriptingController.cpp
|
||||
ScriptingTextBuffer.cpp
|
||||
ScriptingTextBufferModel.cpp
|
||||
ScriptingView.cpp)
|
||||
|
||||
list(APPEND UI_FILES
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "CoreController.h"
|
||||
#include "ScriptingTextBuffer.h"
|
||||
#include "ScriptingTextBufferModel.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
|
@ -33,6 +34,9 @@ ScriptingController::ScriptingController(QObject* parent)
|
|||
}
|
||||
};
|
||||
|
||||
m_bufferModel = new ScriptingTextBufferModel(this);
|
||||
QObject::connect(m_bufferModel, &ScriptingTextBufferModel::textBufferCreated, this, &ScriptingController::textBufferCreated);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
@ -87,10 +91,7 @@ void ScriptingController::clearController() {
|
|||
|
||||
void ScriptingController::reset() {
|
||||
CoreController::Interrupter interrupter(m_controller);
|
||||
for (ScriptingTextBuffer* buffer : m_buffers) {
|
||||
delete buffer;
|
||||
}
|
||||
m_buffers.clear();
|
||||
m_bufferModel->reset();
|
||||
mScriptContextDetachCore(&m_scriptContext);
|
||||
mScriptContextDeinit(&m_scriptContext);
|
||||
m_engines.clear();
|
||||
|
@ -106,21 +107,13 @@ void ScriptingController::runCode(const QString& code) {
|
|||
load(vf, "*prompt");
|
||||
}
|
||||
|
||||
mScriptTextBuffer* ScriptingController::createTextBuffer(void* context) {
|
||||
ScriptingController* self = static_cast<ScriptingController*>(context);
|
||||
ScriptingTextBuffer* buffer = new ScriptingTextBuffer(self);
|
||||
self->m_buffers.append(buffer);
|
||||
emit self->textBufferCreated(buffer);
|
||||
return buffer->textBuffer();
|
||||
}
|
||||
|
||||
void ScriptingController::init() {
|
||||
mScriptContextInit(&m_scriptContext);
|
||||
mScriptContextAttachStdlib(&m_scriptContext);
|
||||
mScriptContextRegisterEngines(&m_scriptContext);
|
||||
|
||||
mScriptContextAttachLogger(&m_scriptContext, &m_logger);
|
||||
mScriptContextSetTextBufferFactory(&m_scriptContext, &ScriptingController::createTextBuffer, this);
|
||||
m_bufferModel->attachToContext(&m_scriptContext);
|
||||
|
||||
HashTableEnumerate(&m_scriptContext.engines, [](const char* key, void* engine, void* context) {
|
||||
ScriptingController* self = static_cast<ScriptingController*>(context);
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
class QTextDocument;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class CoreController;
|
||||
class ScriptingTextBuffer;
|
||||
class ScriptingTextBufferModel;
|
||||
|
||||
class ScriptingController : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -33,7 +36,7 @@ public:
|
|||
bool load(VFileDevice& vf, const QString& name);
|
||||
|
||||
mScriptContext* context() { return &m_scriptContext; }
|
||||
QList<ScriptingTextBuffer*> textBuffers() { return m_buffers; }
|
||||
ScriptingTextBufferModel* textBufferModel() const { return m_bufferModel; }
|
||||
|
||||
signals:
|
||||
void log(const QString&);
|
||||
|
@ -59,7 +62,7 @@ private:
|
|||
|
||||
mScriptEngineContext* m_activeEngine = nullptr;
|
||||
QHash<QString, mScriptEngineContext*> m_engines;
|
||||
QList<ScriptingTextBuffer*> m_buffers;
|
||||
ScriptingTextBufferModel* m_bufferModel;
|
||||
|
||||
std::shared_ptr<CoreController> m_controller;
|
||||
};
|
||||
|
|
|
@ -47,12 +47,12 @@ private:
|
|||
static void deinit(struct mScriptTextBuffer*);
|
||||
|
||||
static void setName(struct mScriptTextBuffer*, const char* name);
|
||||
|
||||
|
||||
static uint32_t getX(const struct mScriptTextBuffer*);
|
||||
static uint32_t getY(const struct mScriptTextBuffer*);
|
||||
static uint32_t cols(const struct mScriptTextBuffer*);
|
||||
static uint32_t rows(const struct mScriptTextBuffer*);
|
||||
|
||||
|
||||
static void print(struct mScriptTextBuffer*, const char* text);
|
||||
static void clear(struct mScriptTextBuffer*);
|
||||
static void setSize(struct mScriptTextBuffer*, uint32_t cols, uint32_t rows);
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* Copyright (c) 2013-2022 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "ScriptingTextBufferModel.h"
|
||||
|
||||
#include "ScriptingTextBuffer.h"
|
||||
|
||||
#include <QTextDocument>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
ScriptingTextBufferModel::ScriptingTextBufferModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
// initializers only
|
||||
}
|
||||
|
||||
void ScriptingTextBufferModel::attachToContext(mScriptContext* context)
|
||||
{
|
||||
mScriptContextSetTextBufferFactory(context, &ScriptingTextBufferModel::createTextBuffer, this);
|
||||
}
|
||||
|
||||
void ScriptingTextBufferModel::reset() {
|
||||
beginResetModel();
|
||||
QList<ScriptingTextBuffer*> toDelete = m_buffers;
|
||||
m_buffers.clear();
|
||||
endResetModel();
|
||||
for (ScriptingTextBuffer* buffer : toDelete) {
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
|
||||
mScriptTextBuffer* ScriptingTextBufferModel::createTextBuffer(void* context) {
|
||||
ScriptingTextBufferModel* self = static_cast<ScriptingTextBufferModel*>(context);
|
||||
self->beginInsertRows(QModelIndex(), self->m_buffers.size(), self->m_buffers.size() + 1);
|
||||
ScriptingTextBuffer* buffer = new ScriptingTextBuffer(self);
|
||||
QObject::connect(buffer, &ScriptingTextBuffer::bufferNameChanged, self, &ScriptingTextBufferModel::bufferNameChanged);
|
||||
self->m_buffers.append(buffer);
|
||||
emit self->textBufferCreated(buffer);
|
||||
self->endInsertRows();
|
||||
return buffer->textBuffer();
|
||||
}
|
||||
|
||||
void ScriptingTextBufferModel::bufferNameChanged(const QString&) {
|
||||
ScriptingTextBuffer* buffer = qobject_cast<ScriptingTextBuffer*>(sender());
|
||||
int row = m_buffers.indexOf(buffer);
|
||||
if (row < 0) {
|
||||
return;
|
||||
}
|
||||
QModelIndex idx = index(row, 0);
|
||||
emit dataChanged(idx, idx, { Qt::DisplayRole });
|
||||
}
|
||||
|
||||
int ScriptingTextBufferModel::rowCount(const QModelIndex& parent) const {
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_buffers.size();
|
||||
}
|
||||
|
||||
QVariant ScriptingTextBufferModel::data(const QModelIndex& index, int role) const {
|
||||
if (index.parent().isValid() || index.row() < 0 || index.row() >= m_buffers.size() || index.column() != 0) {
|
||||
return QVariant();
|
||||
}
|
||||
if (role == Qt::DisplayRole) {
|
||||
return m_buffers[index.row()]->document()->metaInformation(QTextDocument::DocumentTitle);
|
||||
} else if (role == ScriptingTextBufferModel::DocumentRole) {
|
||||
return QVariant::fromValue<QTextDocument*>(m_buffers[index.row()]->document());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2013-2022 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include <mgba/script/context.h>
|
||||
|
||||
class mScriptTextBuffer;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class ScriptingTextBuffer;
|
||||
|
||||
class ScriptingTextBufferModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum ItemDataRole {
|
||||
DocumentRole = Qt::UserRole + 1,
|
||||
};
|
||||
|
||||
ScriptingTextBufferModel(QObject* parent = nullptr);
|
||||
|
||||
void attachToContext(mScriptContext* context);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
|
||||
signals:
|
||||
void textBufferCreated(ScriptingTextBuffer*);
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
|
||||
private slots:
|
||||
void bufferNameChanged(const QString&);
|
||||
|
||||
private:
|
||||
static mScriptTextBuffer* createTextBuffer(void* context);
|
||||
|
||||
QList<ScriptingTextBuffer*> m_buffers;
|
||||
};
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include "ConfigController.h"
|
||||
#include "ScriptingController.h"
|
||||
#include "ScriptingTextBuffer.h"
|
||||
#include "ScriptingTextBufferModel.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
|
@ -19,26 +20,34 @@ ScriptingView::ScriptingView(ScriptingController* controller, ConfigController*
|
|||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
ScriptingTextBufferModel* bufferModel = controller->textBufferModel();
|
||||
m_ui.prompt->setFont(GBAApp::app()->monospaceFont());
|
||||
m_ui.log->setNewlineTerminated(true);
|
||||
m_ui.buffers->setModel(bufferModel);
|
||||
|
||||
connect(m_ui.prompt, &QLineEdit::returnPressed, this, &ScriptingView::submitRepl);
|
||||
connect(m_ui.runButton, &QAbstractButton::clicked, this, &ScriptingView::submitRepl);
|
||||
|
||||
connect(bufferModel, &QAbstractItemModel::modelAboutToBeReset, this, &ScriptingView::controllerReset);
|
||||
connect(bufferModel, &QAbstractItemModel::rowsInserted, this, [this, bufferModel](const QModelIndex&, int row, int) {
|
||||
m_ui.buffers->setCurrentIndex(bufferModel->index(row, 0));
|
||||
});
|
||||
|
||||
connect(m_controller, &ScriptingController::log, m_ui.log, &LogWidget::log);
|
||||
connect(m_controller, &ScriptingController::warn, m_ui.log, &LogWidget::warn);
|
||||
connect(m_controller, &ScriptingController::error, m_ui.log, &LogWidget::error);
|
||||
connect(m_controller, &ScriptingController::textBufferCreated, this, &ScriptingView::addTextBuffer);
|
||||
|
||||
connect(m_ui.buffers, &QListWidget::currentRowChanged, this, &ScriptingView::selectBuffer);
|
||||
connect(m_ui.buffers->selectionModel(), &QItemSelectionModel::currentChanged, this, &ScriptingView::selectBuffer);
|
||||
connect(m_ui.load, &QAction::triggered, this, &ScriptingView::load);
|
||||
connect(m_ui.reset, &QAction::triggered, controller, &ScriptingController::reset);
|
||||
|
||||
m_mruFiles = m_config->getMRU(ConfigController::MRU::Script);
|
||||
updateMRU();
|
||||
|
||||
for (ScriptingTextBuffer* buffer : controller->textBuffers()) {
|
||||
addTextBuffer(buffer);
|
||||
}
|
||||
m_blankDocument = new QTextDocument(this);
|
||||
m_blankDocument->setDocumentLayout(new QPlainTextDocumentLayout(m_blankDocument));
|
||||
|
||||
m_ui.buffers->setCurrentIndex(bufferModel->index(0, 0));
|
||||
}
|
||||
|
||||
void ScriptingView::submitRepl() {
|
||||
|
@ -57,27 +66,16 @@ void ScriptingView::load() {
|
|||
}
|
||||
}
|
||||
|
||||
void ScriptingView::addTextBuffer(ScriptingTextBuffer* buffer) {
|
||||
QTextDocument* document = buffer->document();
|
||||
m_textBuffers.append(buffer);
|
||||
QListWidgetItem* item = new QListWidgetItem(document->metaInformation(QTextDocument::DocumentTitle));
|
||||
connect(buffer, &ScriptingTextBuffer::bufferNameChanged, this, [item](const QString& name) {
|
||||
item->setText(name);
|
||||
});
|
||||
connect(buffer, &QObject::destroyed, this, [this, buffer, item]() {
|
||||
m_textBuffers.removeAll(buffer);
|
||||
delete item;
|
||||
});
|
||||
m_ui.buffers->addItem(item);
|
||||
m_ui.buffers->setCurrentItem(item);
|
||||
void ScriptingView::controllerReset() {
|
||||
selectBuffer(QModelIndex());
|
||||
}
|
||||
|
||||
void ScriptingView::selectBuffer(int index) {
|
||||
if (index < 0 || index >= m_textBuffers.size()) {
|
||||
// If the selected buffer is out of bounds, clear the document.
|
||||
m_ui.buffer->setDocument(nullptr);
|
||||
void ScriptingView::selectBuffer(const QModelIndex& current, const QModelIndex&) {
|
||||
if (current.isValid()) {
|
||||
m_ui.buffer->setDocument(current.data(ScriptingTextBufferModel::DocumentRole).value<QTextDocument*>());
|
||||
} else {
|
||||
m_ui.buffer->setDocument(m_textBuffers[index]->document());
|
||||
// If there is no selected buffer, use the blank document.
|
||||
m_ui.buffer->setDocument(m_blankDocument);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ private slots:
|
|||
void submitRepl();
|
||||
void load();
|
||||
|
||||
void addTextBuffer(ScriptingTextBuffer*);
|
||||
void selectBuffer(int);
|
||||
void controllerReset();
|
||||
void selectBuffer(const QModelIndex& current, const QModelIndex& = QModelIndex());
|
||||
|
||||
private:
|
||||
QString getFilters() const;
|
||||
|
@ -36,8 +36,8 @@ private:
|
|||
|
||||
ConfigController* m_config;
|
||||
ScriptingController* m_controller;
|
||||
QList<ScriptingTextBuffer*> m_textBuffers;
|
||||
QStringList m_mruFiles;
|
||||
QTextDocument* m_blankDocument;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<widget class="QListWidget" name="buffers">
|
||||
<widget class="QListView" name="buffers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
Loading…
Reference in New Issue