Compare commits

...

2 commits

8 changed files with 76 additions and 1 deletions

View file

@ -72,6 +72,19 @@ void CSignalConnection::Call(std::vector<Data::Variant> args) {
//
SignalConnectionHolder::SignalConnectionHolder() : heldConnection() {}
SignalConnectionHolder::SignalConnectionHolder(std::shared_ptr<SignalConnection> connection) : heldConnection(connection) {}
SignalConnectionHolder::SignalConnectionHolder(Data::SignalConnectionRef other) : heldConnection(other) {}
SignalConnectionHolder::~SignalConnectionHolder() {
// printf("Prediscon!\n");
// if (!heldConnection.expired()) printf("Disconnected!\n");
if (!heldConnection.expired())
heldConnection.lock()->Disconnect();
}
//
SignalConnectionRef Signal::Connect(std::function<void(std::vector<Data::Variant>)> callback) {
auto conn = std::dynamic_pointer_cast<SignalConnection>(std::make_shared<CSignalConnection>(callback, weak_from_this()));
connections.push_back(conn);
@ -96,6 +109,8 @@ SignalConnectionRef Signal::Once(lua_State* state) {
return SignalConnectionRef(conn);
}
//
int __waitingThreads = 0;
int Signal::Wait(lua_State* thread) {
// If the table hasn't been constructed yet, make it

View file

@ -56,6 +56,27 @@ public:
~LuaSignalConnection();
};
// Holds a signal connection such that when the holder is deleted (either via its parent object being deleted, or being overwritten),
// the connection is disconnected. Useful to prevent lingering connections that no longer contain valid objects
class SignalConnectionHolder {
std::weak_ptr<SignalConnection> heldConnection;
public:
SignalConnectionHolder();
SignalConnectionHolder(std::shared_ptr<SignalConnection>);
SignalConnectionHolder(Data::SignalConnectionRef other);
~SignalConnectionHolder();
// Prevent SignalConnectionHolder being accidentally copied, making it useless
// https://stackoverflow.com/a/10473009/16255372
SignalConnectionHolder(const SignalConnectionHolder&) = delete;
SignalConnectionHolder& operator=(const SignalConnectionHolder&) = delete;
SignalConnectionHolder(SignalConnectionHolder&&) = default;
SignalConnectionHolder& operator=(SignalConnectionHolder&&) = default;
inline bool Connected() { return !heldConnection.expired() && heldConnection.lock()->Connected(); }
inline void Disconnect() { if (!heldConnection.expired()) heldConnection.lock()->Disconnect(); }
};
class Signal : public std::enable_shared_from_this<Signal> {
std::vector<std::shared_ptr<SignalConnection>> connections;
std::vector<std::shared_ptr<SignalConnection>> onceConnections;

View file

@ -96,6 +96,7 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
}
OnAncestryChanged(updatedChild, newParent);
AncestryChanged->Fire({updatedChild.has_value() ? Data::InstanceRef(updatedChild.value()) : Data::InstanceRef(), newParent.has_value() ? Data::InstanceRef(newParent.value()) : Data::InstanceRef()});
// Old workspace used to exist, and workspaces differ
if (!oldWorkspace.expired() && oldWorkspace != _workspace) {

View file

@ -11,6 +11,7 @@
#include <string>
#include <vector>
#include "datatypes/signal.h"
#include "error/instance.h"
#include "error/result.h"
#include "member.h"
@ -93,6 +94,9 @@ public:
const static InstanceType TYPE;
std::string name;
// Signals
SignalSource AncestryChanged;
// Instance is abstract, so it should not implement GetClass directly
virtual const InstanceType* GetClass() = 0;
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);

View file

@ -484,13 +484,30 @@ std::optional<std::string> MainWindow::openFileDialog(QString filter, QString de
}
void MainWindow::openScriptDocument(std::shared_ptr<Script> script) {
// Document already exists, don't open it
if (scriptDocuments.count(script) > 0) {
ui->mdiArea->setActiveSubWindow(scriptDocuments[script]);
return;
}
ScriptDocument* doc = new ScriptDocument(script);
scriptDocuments[script] = doc;
doc->setAttribute(Qt::WA_DeleteOnClose, true);
ui->mdiArea->addSubWindow(doc);
ui->mdiArea->setActiveSubWindow(doc);
doc->showMaximized();
}
void MainWindow::closeScriptDocument(std::shared_ptr<Script> script) {
if (scriptDocuments.count(script) == 0) return;
ScriptDocument* doc = scriptDocuments[script];
ui->mdiArea->removeSubWindow(doc);
ui->mdiArea->activeSubWindow()->showMaximized();
scriptDocuments.erase(script);
doc->deleteLater();
}
MainWindow::~MainWindow()
{
delete ui;

View file

@ -5,8 +5,10 @@
#include "placedocument.h"
#include "qbasictimer.h"
#include "qcoreevent.h"
#include "script/scriptdocument.h"
#include <QMainWindow>
#include <QLineEdit>
#include <map>
#include <memory>
#include <qfiledialog.h>
@ -53,10 +55,12 @@ public:
bool editSoundEffects = true;
void openScriptDocument(std::shared_ptr<Script>);
void closeScriptDocument(std::shared_ptr<Script>);
Ui::MainWindow *ui;
private:
PlaceDocument* placeDocument;
std::map<std::shared_ptr<Script>, ScriptDocument*> scriptDocuments;
void updateToolbars();
void closeEvent(QCloseEvent* evt) override;

View file

@ -5,13 +5,16 @@
#include <Qsci/qsciscintillabase.h>
#include <Qsci/qscistyle.h>
#include <map>
#include <memory>
#include <qboxlayout.h>
#include <qcolor.h>
#include <qfont.h>
#include <qdebug.h>
#include <qglobal.h>
#include <qlayout.h>
#include "mainwindow.h"
#include "objects/script.h"
#include "datatypes/meta.h"
std::map<int, const QColor> DARK_MODE_COLOR_SCHEME = {{
{QsciLexerLua::Comment, QColor("#808080")},
@ -37,6 +40,15 @@ ScriptDocument::ScriptDocument(std::shared_ptr<Script> script, QWidget* parent):
setWindowTitle(QString::fromStdString(script->name));
// Add detector for script deletion to automatically close this document
scriptDeletionHandler = script->AncestryChanged->Connect([this, script](std::vector<Data::Variant> args) {
std::weak_ptr<Instance> child = args[0].get<Data::InstanceRef>();
std::weak_ptr<Instance> newParent = args[1].get<Data::InstanceRef>();
if (child.expired() || child.lock() != script || !newParent.expired()) return;
dynamic_cast<MainWindow*>(window())->closeScriptDocument(script);
});
// QFrame* frame = new QFrame;
// QVBoxLayout* frameLayout = new QVBoxLayout;
// frame->setLayout(frameLayout);
@ -74,7 +86,6 @@ ScriptDocument::ScriptDocument(std::shared_ptr<Script> script, QWidget* parent):
// lexer->setAutoIndentStyle(QsciScintilla::AiOpening | QsciScintilla::AiMaintain | QsciScintilla::AiClosing);
// scintilla->setAutoIndent(true);
connect(scintilla, &QsciScintilla::textChanged, [this]() {
// this-> is important here, as otherwise it will refer to the

View file

@ -1,5 +1,6 @@
#pragma once
#include "datatypes/signal.h"
#include <Qsci/qsciscintilla.h>
#include <memory>
#include <qmdisubwindow.h>
@ -8,6 +9,7 @@ class Script;
class ScriptDocument : public QMdiSubWindow {
std::shared_ptr<Script> script;
SignalConnectionHolder scriptDeletionHandler;
QsciScintilla* scintilla;
public: