diff --git a/forms/customscriptseditor.ui b/forms/customscriptseditor.ui
new file mode 100644
index 00000000..12acb332
--- /dev/null
+++ b/forms/customscriptseditor.ui
@@ -0,0 +1,164 @@
+
+
+ CustomScriptsEditor
+
+
+
+ 0
+ 0
+ 374
+ 355
+
+
+
+ Custom Scripts Editor
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Add New Script...
+
+
+
+ :/icons/add.ico:/icons/add.ico
+
+
+
+ -
+
+
+ Reload Scripts
+
+
+
+ :/icons/refresh.ico:/icons/refresh.ico
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ <html><head/><body><p><a href="https://huderlem.github.io/porymap/manual/scripting-capabilities.html"><span style=" text-decoration: underline; color:#0000ff;">What are custom scripts?</span></a></p></body></html>
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Minimum
+
+
+
+ 20
+ 5
+
+
+
+
+ -
+
+
+ Scripts
+
+
+
+ -
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+ QAbstractItemView::NoDragDrop
+
+
+ Qt::IgnoreAction
+
+
+ QAbstractItemView::ExtendedSelection
+
+
+ Qt::ElideLeft
+
+
+ QListView::Free
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/forms/customscriptslistitem.ui b/forms/customscriptslistitem.ui
new file mode 100644
index 00000000..5784b442
--- /dev/null
+++ b/forms/customscriptslistitem.ui
@@ -0,0 +1,87 @@
+
+
+ CustomScriptsListItem
+
+
+
+ 0
+ 0
+ 129
+ 30
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 4
+
+
+ 4
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ Choose a new filepath for this script
+
+
+ ...
+
+
+
+ :/icons/folder.ico:/icons/folder.ico
+
+
+
+ -
+
+
+ Open this script file
+
+
+ ...
+
+
+
+ :/icons/edit_document.ico:/icons/edit_document.ico
+
+
+
+ -
+
+
+ Remove this script
+
+
+ ...
+
+
+
+ :/icons/delete.ico:/icons/delete.ico
+
+
+
+
+
+
+
+
+
+
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui
index f153538c..f23028b6 100644
--- a/forms/mainwindow.ui
+++ b/forms/mainwindow.ui
@@ -3018,6 +3018,7 @@
+
@@ -3314,6 +3315,11 @@
Edit Project Settings...
+
+
+ Custom Scripts...
+
+
diff --git a/include/config.h b/include/config.h
index 7ffcca38..f715e36c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -348,8 +348,8 @@ public:
bool getEncounterJsonActive();
void setProjectDir(QString projectDir);
QString getProjectDir();
- void setCustomScripts(QList scripts);
- QList getCustomScripts();
+ void setCustomScripts(QStringList scripts);
+ QStringList getCustomScripts();
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@@ -363,7 +363,7 @@ private:
QString projectDir;
QString recentMap;
bool useEncounterJson;
- QList customScripts;
+ QStringList customScripts;
QStringList readKeys;
};
diff --git a/include/editor.h b/include/editor.h
index e28d9120..2282fba7 100644
--- a/include/editor.h
+++ b/include/editor.h
@@ -149,7 +149,7 @@ public:
void shouldReselectEvents();
void scaleMapView(int);
- void openInTextEditor(const QString &path, int lineNum = 0) const;
+ static void openInTextEditor(const QString &path, int lineNum = 0);
bool eventLimitReached(Event::Type type);
public slots:
@@ -179,9 +179,9 @@ private:
void updateEncounterFields(EncounterFields newFields);
QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
QString getMetatileDisplayMessage(uint16_t metatileId);
- bool startDetachedProcess(const QString &command,
- const QString &workingDirectory = QString(),
- qint64 *pid = nullptr) const;
+ static bool startDetachedProcess(const QString &command,
+ const QString &workingDirectory = QString(),
+ qint64 *pid = nullptr);
private slots:
void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
diff --git a/include/mainwindow.h b/include/mainwindow.h
index 32bb03eb..4ccaa6ff 100644
--- a/include/mainwindow.h
+++ b/include/mainwindow.h
@@ -26,6 +26,7 @@
#include "shortcutseditor.h"
#include "preferenceeditor.h"
#include "projectsettingseditor.h"
+#include "customscriptseditor.h"
@@ -286,6 +287,7 @@ private slots:
void on_actionEdit_Preferences_triggered();
void togglePreferenceSpecificUi();
void on_actionEdit_Project_Settings_triggered();
+ void on_actionCustom_Scripts_triggered();
public:
Ui::MainWindow *ui;
@@ -300,6 +302,7 @@ private:
QPointer newMapPrompt = nullptr;
QPointer preferenceEditor = nullptr;
QPointer projectSettingsEditor = nullptr;
+ QPointer customScriptsEditor = nullptr;
FilterChildrenProxyModel *mapListProxyModel;
QStandardItemModel *mapListModel;
QList *mapGroupItemsList;
@@ -343,6 +346,7 @@ private:
bool loadProjectCombos();
bool populateMapList();
void sortMapList();
+ void openSubWindow(QWidget * window);
QString getExistingDirectory(QString);
bool openProject(QString dir);
QString getDefaultMap();
diff --git a/include/ui/customscriptseditor.h b/include/ui/customscriptseditor.h
new file mode 100644
index 00000000..1d8b88c2
--- /dev/null
+++ b/include/ui/customscriptseditor.h
@@ -0,0 +1,60 @@
+#ifndef CUSTOMSCRIPTSEDITOR_H
+#define CUSTOMSCRIPTSEDITOR_H
+
+#include
+#include
+#include
+#include
+
+#include "customscriptslistitem.h"
+
+namespace Ui {
+class CustomScriptsEditor;
+}
+
+
+class CustomScriptsEditor : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit CustomScriptsEditor(QWidget *parent = nullptr);
+ ~CustomScriptsEditor();
+
+signals:
+ void reloadScriptEngine();
+
+private:
+ Ui::CustomScriptsEditor *ui;
+
+ bool hasUnsavedChanges = false;
+ QString importDir;
+ const QString baseDir;
+
+ void displayScript(const QString &filepath);
+ QString chooseScript(QString dir);
+
+ void removeScript(QListWidgetItem * item);
+ void replaceScript(QListWidgetItem * item);
+ void openScript(QListWidgetItem * item);
+
+ QString getListItemFilepath(QListWidgetItem * item) const;
+ void setListItemFilepath(QListWidgetItem * item, QString filepath) const;
+
+ int prompt(const QString &text, QMessageBox::StandardButton defaultButton);
+ void save();
+ void closeEvent(QCloseEvent*);
+
+ void initShortcuts();
+ QObjectList shortcutableObjects() const;
+ void applyUserShortcuts();
+
+private slots:
+ void dialogButtonClicked(QAbstractButton *button);
+ void addNewScript();
+ void reloadScripts();
+ void removeSelectedScripts();
+ void openSelectedScripts();
+};
+
+#endif // CUSTOMSCRIPTSEDITOR_H
diff --git a/include/ui/customscriptslistitem.h b/include/ui/customscriptslistitem.h
new file mode 100644
index 00000000..d166db8a
--- /dev/null
+++ b/include/ui/customscriptslistitem.h
@@ -0,0 +1,22 @@
+#ifndef CUSTOMSCRIPTSLISTITEM_H
+#define CUSTOMSCRIPTSLISTITEM_H
+
+#include
+
+namespace Ui {
+class CustomScriptsListItem;
+}
+
+class CustomScriptsListItem : public QFrame
+{
+ Q_OBJECT
+
+public:
+ explicit CustomScriptsListItem(QWidget *parent = nullptr);
+ ~CustomScriptsListItem();
+
+public:
+ Ui::CustomScriptsListItem *ui;
+};
+
+#endif // CUSTOMSCRIPTSLISTITEM_H
diff --git a/porymap.pro b/porymap.pro
index 4728f177..4a2a2008 100644
--- a/porymap.pro
+++ b/porymap.pro
@@ -42,6 +42,8 @@ SOURCES += src/core/block.cpp \
src/scriptapi/apiutility.cpp \
src/scriptapi/scripting.cpp \
src/ui/aboutporymap.cpp \
+ src/ui/customscriptseditor.cpp \
+ src/ui/customscriptslistitem.cpp \
src/ui/draggablepixmapitem.cpp \
src/ui/bordermetatilespixmapitem.cpp \
src/ui/collisionpixmapitem.cpp \
@@ -129,6 +131,8 @@ HEADERS += include/core/block.h \
include/lib/orderedmap.h \
include/lib/orderedjson.h \
include/ui/aboutporymap.h \
+ include/ui/customscriptseditor.h \
+ include/ui/customscriptslistitem.h \
include/ui/draggablepixmapitem.h \
include/ui/bordermetatilespixmapitem.h \
include/ui/collisionpixmapitem.h \
@@ -204,7 +208,9 @@ FORMS += forms/mainwindow.ui \
forms/preferenceeditor.ui \
forms/regionmappropertiesdialog.ui \
forms/colorpicker.ui \
- forms/projectsettingseditor.ui
+ forms/projectsettingseditor.ui \
+ forms/customscriptseditor.ui \
+ forms/customscriptslistitem.ui
RESOURCES += \
resources/images.qrc \
diff --git a/resources/icons/edit_document.ico b/resources/icons/edit_document.ico
new file mode 100755
index 00000000..cd4bb026
Binary files /dev/null and b/resources/icons/edit_document.ico differ
diff --git a/resources/icons/refresh.ico b/resources/icons/refresh.ico
new file mode 100755
index 00000000..fdf20e26
Binary files /dev/null and b/resources/icons/refresh.ico differ
diff --git a/resources/images.qrc b/resources/images.qrc
index 4c739582..2399cbe9 100644
--- a/resources/images.qrc
+++ b/resources/images.qrc
@@ -4,6 +4,7 @@
icons/collapse_all.ico
icons/cursor.ico
icons/delete.ico
+ icons/edit_document.ico
icons/expand_all.ico
icons/fill_color_cursor.ico
icons/fill_color.ico
@@ -24,6 +25,7 @@
icons/porymap-icon-1.ico
icons/porymap-icon-2.ico
icons/porymap.icns
+ icons/refresh.ico
icons/shift_cursor.ico
icons/shift.ico
icons/sort_alphabet.ico
diff --git a/src/config.cpp b/src/config.cpp
index 7541a894..d5e7e0fe 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -647,7 +647,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
userConfig.useEncounterJson = getConfigBool(key, value);
} else if (key == "custom_scripts") {
userConfig.customScripts.clear();
- QList paths = value.split(",");
+ QList paths = value.split(",", Qt::SkipEmptyParts);
paths.removeDuplicates();
for (QString script : paths) {
if (!script.isEmpty()) {
@@ -1077,7 +1077,7 @@ void UserConfig::parseConfigKeyValue(QString key, QString value) {
this->useEncounterJson = getConfigBool(key, value);
} else if (key == "custom_scripts") {
this->customScripts.clear();
- QList paths = value.split(",");
+ QList paths = value.split(",", Qt::SkipEmptyParts);
paths.removeDuplicates();
for (QString script : paths) {
if (!script.isEmpty()) {
@@ -1133,12 +1133,12 @@ bool UserConfig::getEncounterJsonActive() {
return this->useEncounterJson;
}
-void UserConfig::setCustomScripts(QList scripts) {
+void UserConfig::setCustomScripts(QStringList scripts) {
this->customScripts = scripts;
this->save();
}
-QList UserConfig::getCustomScripts() {
+QStringList UserConfig::getCustomScripts() {
return this->customScripts;
}
diff --git a/src/editor.cpp b/src/editor.cpp
index 9996460e..4dc12885 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -2146,7 +2146,7 @@ void Editor::openScript(const QString &scriptLabel) const {
openInTextEditor(scriptPath, lineNum);
}
-void Editor::openInTextEditor(const QString &path, int lineNum) const {
+void Editor::openInTextEditor(const QString &path, int lineNum) {
QString command = porymapConfig.getTextEditorGotoLine();
if (command.isEmpty()) {
// Open map scripts in the system's default editor.
@@ -2159,7 +2159,7 @@ void Editor::openInTextEditor(const QString &path, int lineNum) const {
} else {
command += " \"" + path + '\"';
}
- startDetachedProcess(command);
+ Editor::startDetachedProcess(command);
}
}
@@ -2172,7 +2172,7 @@ void Editor::openProjectInTextEditor() const {
startDetachedProcess(command);
}
-bool Editor::startDetachedProcess(const QString &command, const QString &workingDirectory, qint64 *pid) const {
+bool Editor::startDetachedProcess(const QString &command, const QString &workingDirectory, qint64 *pid) {
logInfo("Executing command: " + command);
QProcess process;
#ifdef Q_OS_WIN
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 71283bc6..ef9f90c6 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -590,6 +590,19 @@ QString MainWindow::getDefaultMap() {
return QString();
}
+void MainWindow::openSubWindow(QWidget * window) {
+ if (!window) return;
+
+ if (!window->isVisible()) {
+ window->show();
+ } else if (window->isMinimized()) {
+ window->showNormal();
+ } else {
+ window->raise();
+ window->activateWindow();
+ }
+}
+
QString MainWindow::getExistingDirectory(QString dir) {
return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly);
}
@@ -1184,12 +1197,9 @@ void MainWindow::openNewMapPopupWindow() {
if (!this->newMapPrompt) {
this->newMapPrompt = new NewMapPopup(this, this->editor->project);
}
- if (!this->newMapPrompt->isVisible()) {
- this->newMapPrompt->show();
- } else {
- this->newMapPrompt->raise();
- this->newMapPrompt->activateWindow();
- }
+
+ openSubWindow(this->newMapPrompt);
+
connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
this->newMapPrompt->setAttribute(Qt::WA_DeleteOnClose);
}
@@ -1775,14 +1785,7 @@ void MainWindow::on_actionEdit_Shortcuts_triggered()
if (!shortcutsEditor)
initShortcutsEditor();
- if (shortcutsEditor->isHidden()) {
- shortcutsEditor->show();
- } else if (shortcutsEditor->isMinimized()) {
- shortcutsEditor->showNormal();
- } else {
- shortcutsEditor->raise();
- shortcutsEditor->activateWindow();
- }
+ openSubWindow(shortcutsEditor);
}
void MainWindow::initShortcutsEditor() {
@@ -2461,13 +2464,7 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) {
this->mapImageExporter = new MapImageExporter(this, this->editor, mode);
this->mapImageExporter->setAttribute(Qt::WA_DeleteOnClose);
- if (!this->mapImageExporter->isVisible()) {
- this->mapImageExporter->show();
- } else if (this->mapImageExporter->isMinimized()) {
- this->mapImageExporter->showNormal();
- } else {
- this->mapImageExporter->activateWindow();
- }
+ openSubWindow(this->mapImageExporter);
}
void MainWindow::on_comboBox_ConnectionDirection_currentTextChanged(const QString &direction)
@@ -2663,14 +2660,7 @@ void MainWindow::on_actionTileset_Editor_triggered()
initTilesetEditor();
}
- if (!this->tilesetEditor->isVisible()) {
- this->tilesetEditor->show();
- } else if (this->tilesetEditor->isMinimized()) {
- this->tilesetEditor->showNormal();
- } else {
- this->tilesetEditor->raise();
- this->tilesetEditor->activateWindow();
- }
+ openSubWindow(this->tilesetEditor);
MetatileSelection selection = this->editor->metatile_selector_item->getMetatileSelection();
this->tilesetEditor->selectMetatile(selection.metatileItems.first().metatileId);
@@ -2723,14 +2713,7 @@ void MainWindow::on_actionEdit_Preferences_triggered() {
this, &MainWindow::togglePreferenceSpecificUi);
}
- if (!preferenceEditor->isVisible()) {
- preferenceEditor->show();
- } else if (preferenceEditor->isMinimized()) {
- preferenceEditor->showNormal();
- } else {
- preferenceEditor->raise();
- preferenceEditor->activateWindow();
- }
+ openSubWindow(preferenceEditor);
}
void MainWindow::togglePreferenceSpecificUi() {
@@ -2747,14 +2730,15 @@ void MainWindow::on_actionEdit_Project_Settings_triggered() {
this, &MainWindow::on_action_Reload_Project_triggered);
}
- if (!this->projectSettingsEditor->isVisible()) {
- this->projectSettingsEditor->show();
- } else if (this->projectSettingsEditor->isMinimized()) {
- this->projectSettingsEditor->showNormal();
- } else {
- this->projectSettingsEditor->raise();
- this->projectSettingsEditor->activateWindow();
+ openSubWindow(this->projectSettingsEditor);
+}
+
+void MainWindow::on_actionCustom_Scripts_triggered() {
+ if (!this->customScriptsEditor) {
+ this->customScriptsEditor = new CustomScriptsEditor(this);
}
+
+ openSubWindow(this->customScriptsEditor);
}
void MainWindow::on_pushButton_AddCustomHeaderField_clicked()
@@ -2806,14 +2790,7 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() {
}
}
- if (!this->regionMapEditor->isVisible()) {
- this->regionMapEditor->show();
- } else if (this->regionMapEditor->isMinimized()) {
- this->regionMapEditor->showNormal();
- } else {
- this->regionMapEditor->raise();
- this->regionMapEditor->activateWindow();
- }
+ openSubWindow(this->regionMapEditor);
}
void MainWindow::on_pushButton_CreatePrefab_clicked() {
diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp
new file mode 100644
index 00000000..36babd51
--- /dev/null
+++ b/src/ui/customscriptseditor.cpp
@@ -0,0 +1,231 @@
+#include "customscriptseditor.h"
+#include "ui_customscriptseditor.h"
+#include "ui_customscriptslistitem.h"
+#include "config.h"
+#include "editor.h"
+#include "shortcut.h"
+
+#include
+#include
+
+// TODO: System for turning scripts on or off
+//
+// TODO: Better URL colors on dark themes
+// TODO: Save window state
+
+CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::CustomScriptsEditor),
+ baseDir(userConfig.getProjectDir() + QDir::separator())
+{
+ ui->setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+ // This property seems to be reset if we don't set it programmatically
+ ui->list->setDragDropMode(QAbstractItemView::NoDragDrop);
+
+ for (auto path : userConfig.getCustomScripts())
+ this->displayScript(path);
+
+ this->importDir = userConfig.getProjectDir();
+
+ connect(ui->button_AddNewScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::addNewScript);
+ connect(ui->button_ReloadScripts, &QAbstractButton::clicked, this, &CustomScriptsEditor::reloadScripts);
+ connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &CustomScriptsEditor::dialogButtonClicked);
+
+ this->initShortcuts();
+}
+
+CustomScriptsEditor::~CustomScriptsEditor()
+{
+ ui->list->clear();
+ delete ui;
+}
+
+void CustomScriptsEditor::initShortcuts() {
+ auto *shortcut_remove = new Shortcut({QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(removeSelectedScripts()));
+ shortcut_remove->setObjectName("shortcut_remove");
+ shortcut_remove->setWhatsThis("Remove Selected Scripts");
+
+ // TODO: Prevent ambiguity with MainWindow
+ auto *shortcut_open = new Shortcut(QKeySequence("Ctrl+O"), this, SLOT(openSelectedScripts()));
+ shortcut_open->setObjectName("shortcut_open");
+ shortcut_open->setWhatsThis("Open Selected Scripts");
+
+ auto *shortcut_addNew = new Shortcut(QKeySequence(), this, SLOT(addNewScript()));
+ shortcut_addNew->setObjectName("shortcut_addNew");
+ shortcut_addNew->setWhatsThis("Add New Script...");
+
+ auto *shortcut_reload = new Shortcut(QKeySequence(), this, SLOT(reloadScripts()));
+ shortcut_reload->setObjectName("shortcut_reload");
+ shortcut_reload->setWhatsThis("Reload Scripts");
+
+ //connect(new QShortcut(QKeySequence("Backspace"), this), &QShortcut::activated, this, &CustomScriptsEditor::removeSelectedScripts);
+ //connect(new QShortcut(QKeySequence("Ctrl+O"), this), &QShortcut::activated, this, &CustomScriptsEditor::openSelectedScripts);
+
+ shortcutsConfig.load();
+ shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
+ applyUserShortcuts();
+}
+
+QObjectList CustomScriptsEditor::shortcutableObjects() const {
+ QObjectList shortcutable_objects;
+
+ for (auto *action : findChildren())
+ if (!action->objectName().isEmpty())
+ shortcutable_objects.append(qobject_cast(action));
+ for (auto *shortcut : findChildren())
+ if (!shortcut->objectName().isEmpty())
+ shortcutable_objects.append(qobject_cast(shortcut));
+
+ return shortcutable_objects;
+}
+
+// TODO: Connect to shorcuts editor
+void CustomScriptsEditor::applyUserShortcuts() {
+ for (auto *action : findChildren())
+ if (!action->objectName().isEmpty())
+ action->setShortcuts(shortcutsConfig.userShortcuts(action));
+ for (auto *shortcut : findChildren())
+ if (!shortcut->objectName().isEmpty())
+ shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
+}
+
+void CustomScriptsEditor::displayScript(const QString &filepath) {
+ auto item = new QListWidgetItem();
+ auto buttons = new CustomScriptsListItem();
+
+ buttons->ui->lineEdit_filepath->setText(filepath);
+ item->setSizeHint(buttons->sizeHint());
+
+ connect(buttons->ui->b_Choose, &QAbstractButton::clicked, [this, item](bool) { this->replaceScript(item); });
+ connect(buttons->ui->b_Edit, &QAbstractButton::clicked, [this, item](bool) { this->openScript(item); });
+ connect(buttons->ui->b_Delete, &QAbstractButton::clicked, [this, item](bool) { this->removeScript(item); });
+ connect(buttons->ui->lineEdit_filepath, &QLineEdit::textEdited, [this](const QString&) { this->hasUnsavedChanges = true; });
+
+ // Per the Qt manual, for performance reasons QListWidget::setItemWidget shouldn't be used with non-static items.
+ // There's an assumption here that users won't have enough scripts for that to be a problem.
+ ui->list->addItem(item);
+ ui->list->setItemWidget(item, buttons);
+}
+
+QString CustomScriptsEditor::getListItemFilepath(QListWidgetItem * item) const {
+ auto widget = dynamic_cast(ui->list->itemWidget(item));
+ if (!widget) return QString();
+
+ QString path = widget->ui->lineEdit_filepath->text();
+ QFileInfo fileInfo(path);
+ if (fileInfo.isRelative())
+ path.prepend(this->baseDir);
+ return path;
+}
+
+void CustomScriptsEditor::setListItemFilepath(QListWidgetItem * item, QString filepath) const {
+ auto widget = dynamic_cast(ui->list->itemWidget(item));
+ if (!widget) return;
+
+ if (filepath.startsWith(this->baseDir))
+ filepath.remove(0, this->baseDir.length());
+ widget->ui->lineEdit_filepath->setText(filepath);
+}
+
+QString CustomScriptsEditor::chooseScript(QString dir) {
+ return QFileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)");
+}
+
+void CustomScriptsEditor::addNewScript() {
+ QString filepath = this->chooseScript(this->importDir);
+ if (filepath.isEmpty())
+ return;
+ this->importDir = filepath;
+ if (filepath.startsWith(this->baseDir))
+ filepath.remove(0, this->baseDir.length());
+ this->displayScript(filepath);
+ this->hasUnsavedChanges = true;
+}
+
+void CustomScriptsEditor::removeScript(QListWidgetItem * item) {
+ ui->list->takeItem(ui->list->row(item));
+ this->hasUnsavedChanges = true;
+}
+
+void CustomScriptsEditor::removeSelectedScripts() {
+ QList items = ui->list->selectedItems();
+ if (items.length() == 0)
+ return;
+ for (auto item : items)
+ this->removeScript(item);
+}
+
+void CustomScriptsEditor::replaceScript(QListWidgetItem * item) {
+ const QString filepath = this->chooseScript(this->getListItemFilepath(item));
+ if (filepath.isEmpty())
+ return;
+ this->setListItemFilepath(item, filepath);
+ this->hasUnsavedChanges = true;
+}
+
+void CustomScriptsEditor::openScript(QListWidgetItem * item) {
+ const QString path = this->getListItemFilepath(item);
+ QFileInfo fileInfo(path);
+ if (!fileInfo.exists() || !fileInfo.isFile()){
+ QMessageBox::warning(this, "", QString("Failed to open script '%1'").arg(path));
+ return;
+ }
+ Editor::openInTextEditor(path);
+}
+
+void CustomScriptsEditor::openSelectedScripts() {
+ for (auto item : ui->list->selectedItems())
+ this->openScript(item);
+}
+
+void CustomScriptsEditor::reloadScripts() {
+ if (this->hasUnsavedChanges) {
+ if (this->prompt("Scripts have been modified, save changes and reload the script engine?", QMessageBox::Yes) == QMessageBox::No)
+ return;
+ this->save();
+ }
+ emit reloadScriptEngine(); // TODO: Catch this signal
+}
+
+void CustomScriptsEditor::save() {
+ if (!this->hasUnsavedChanges)
+ return;
+ // TODO: Set new paths in config
+ this->hasUnsavedChanges = false;
+ this->reloadScripts();
+}
+
+int CustomScriptsEditor::prompt(const QString &text, QMessageBox::StandardButton defaultButton) {
+ QMessageBox messageBox(this);
+ messageBox.setText(text);
+ messageBox.setIcon(QMessageBox::Question);
+ messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | defaultButton);
+ messageBox.setDefaultButton(defaultButton);
+ return messageBox.exec();
+}
+
+void CustomScriptsEditor::dialogButtonClicked(QAbstractButton *button) {
+ if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
+ this->save();
+ close(); // All buttons (OK and Cancel) close the window
+}
+
+void CustomScriptsEditor::closeEvent(QCloseEvent* event) {
+ if (this->hasUnsavedChanges) {
+ int result = this->prompt("Scripts have been modified, save changes?", QMessageBox::Cancel);
+ if (result == QMessageBox::Cancel) {
+ event->ignore();
+ return;
+ }
+ if (result == QMessageBox::Yes)
+ this->save();
+ }
+/*
+ // TODO
+ porymapConfig.setProjectSettingsEditorGeometry(
+ this->saveGeometry(),
+ this->saveState()
+ );
+*/
+}
diff --git a/src/ui/customscriptslistitem.cpp b/src/ui/customscriptslistitem.cpp
new file mode 100644
index 00000000..e1452425
--- /dev/null
+++ b/src/ui/customscriptslistitem.cpp
@@ -0,0 +1,14 @@
+#include "customscriptslistitem.h"
+#include "ui_customscriptslistitem.h"
+
+CustomScriptsListItem::CustomScriptsListItem(QWidget *parent) :
+ QFrame(parent),
+ ui(new Ui::CustomScriptsListItem)
+{
+ ui->setupUi(this);
+}
+
+CustomScriptsListItem::~CustomScriptsListItem()
+{
+ delete ui;
+}
diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp
index 48428624..bf8d17ae 100644
--- a/src/ui/projectsettingseditor.cpp
+++ b/src/ui/projectsettingseditor.cpp
@@ -8,7 +8,7 @@
#include
/*
- Editor for the settings in a user's porymap.project.cfg and porymap.user.cfg files.
+ Editor for the settings in a user's porymap.project.cfg file (and 'use_encounter_json' in porymap.user.cfg).
*/
ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) :
@@ -32,31 +32,20 @@ ProjectSettingsEditor::~ProjectSettingsEditor()
// TODO: Move tool tips to editable areas
void ProjectSettingsEditor::connectSignals() {
- // Connect buttons
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked);
connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked);
connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked);
-
- // Connect combo boxes
- QList combos = ui->centralwidget->findChildren();
- foreach(auto i, combos)
- connect(i, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited);
connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults);
- // Connect check boxes
- QList checkboxes = ui->centralwidget->findChildren();
- foreach(auto i, checkboxes)
- connect(i, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited);
-
- // Connect spin boxes
- QList spinBoxes = ui->centralwidget->findChildren();
- foreach(auto i, spinBoxes)
- connect(i, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); });
-
- // Connect line edits
- QList lineEdits = ui->centralwidget->findChildren();
- foreach(auto i, lineEdits)
- connect(i, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited);
+ // Record that there are unsaved changes if any of the settings are modified
+ for (auto combo : ui->centralwidget->findChildren())
+ connect(combo, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited);
+ for (auto checkBox : ui->centralwidget->findChildren())
+ connect(checkBox, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited);
+ for (auto spinBox : ui->centralwidget->findChildren())
+ connect(spinBox, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); });
+ for (auto lineEdit : ui->centralwidget->findChildren())
+ connect(lineEdit, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited);
}
void ProjectSettingsEditor::markEdited() {
@@ -143,7 +132,6 @@ void ProjectSettingsEditor::save() {
// Prevent a call to save() for each of the config settings
projectConfig.setSaveDisabled(true);
- userConfig.setSaveDisabled(true);
projectConfig.setDefaultPrimaryTileset(ui->comboBox_DefaultPrimaryTileset->currentText());
projectConfig.setDefaultSecondaryTileset(ui->comboBox_DefaultSecondaryTileset->currentText());
@@ -183,8 +171,6 @@ void ProjectSettingsEditor::save() {
projectConfig.setSaveDisabled(false);
projectConfig.save();
- userConfig.setSaveDisabled(false);
- userConfig.save();
this->hasUnsavedChanges = false;
// Technically, a reload is not required for several of the config settings.
@@ -192,6 +178,7 @@ void ProjectSettingsEditor::save() {
this->projectNeedsReload = true;
}
+// TODO: If the selected file is in the project directory use a relative path
void ProjectSettingsEditor::choosePrefabsFileClicked(bool) {
QString startPath = this->project->importExportPath;
QFileInfo fileInfo(ui->lineEdit_PrefabsPath->text());
@@ -253,12 +240,9 @@ bool ProjectSettingsEditor::promptRestoreDefaults() {
// Restore defaults by resetting config in memory, refreshing the UI, then restoring the config.
// Don't want to save changes until user accepts them.
ProjectConfig tempProject = projectConfig;
- UserConfig tempUser = userConfig;
projectConfig.reset(projectConfig.stringToBaseGameVersion(versionText));
- userConfig.reset();
this->refresh();
projectConfig = tempProject;
- userConfig = tempUser;
this->hasUnsavedChanges = true;
return true;