mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-11 03:15:46 -05:00
Custom Scripts -> Plugins
Some checks failed
Build Porymap / build-linux (, 5.14.2) (push) Has been cancelled
Build Porymap / build-linux (, 6.8.*) (push) Has been cancelled
Build Porymap / build-linux (minimal, 5.14.2) (push) Has been cancelled
Build Porymap / build-macos (macos-15-intel) (push) Has been cancelled
Build Porymap / build-macos (macos-latest) (push) Has been cancelled
Build Porymap / build-static-windows (push) Has been cancelled
Some checks failed
Build Porymap / build-linux (, 5.14.2) (push) Has been cancelled
Build Porymap / build-linux (, 6.8.*) (push) Has been cancelled
Build Porymap / build-linux (minimal, 5.14.2) (push) Has been cancelled
Build Porymap / build-macos (macos-15-intel) (push) Has been cancelled
Build Porymap / build-macos (macos-latest) (push) Has been cancelled
Build Porymap / build-static-windows (push) Has been cancelled
This commit is contained in:
@@ -15,24 +15,24 @@ Porymap is extensible via scripting capabilities. This allows the user to write
|
||||
If you are compiling Porymap yourself, these features will only be available if Qt's ``qml`` module is installed.
|
||||
|
||||
|
||||
Custom Scripts Editor
|
||||
---------------------
|
||||
Plugin Editor
|
||||
-------------
|
||||
|
||||
Your custom scripts can be managed with the Custom Scripts Editor accessible under ``Options -> Custom Scripts...``.
|
||||
Your plugins can be managed with the Plugin Editor accessible under ``Options -> Plugins...``.
|
||||
|
||||
.. figure:: images/scripting-capabilities/custom-scripts-editor.png
|
||||
:alt: Custom Scripts Editor
|
||||
:alt: Plugins Editor
|
||||
:width: 60%
|
||||
:align: center
|
||||
|
||||
Custom Scripts Editor
|
||||
Plugins Editor
|
||||
|
||||
At the top there are three basic buttons for managing your scripts:
|
||||
- |button-create| Opens a prompt to create a new script file, which will be populated with a basic template.
|
||||
- |button-load| Lets you add an existing script file to Porymap that you've already created or downloaded from elsewhere.
|
||||
- |button-refresh| Any edits made to your scripts while Porymap is already open will not be reflected until you select this button.
|
||||
|
||||
Below these buttons is a list of all the custom scripts you have loaded for your project. Each entry will have a text box showing the path of the script file. This path can be freely updated, or you can choose a new path with the |button-folder| button next to it. The |button-edit| button will open the script file in your default text editor, and the |button-remove| button will remove it from the list. The check box to the left of the filepath indicates whether your script should be running. If you'd like to temporarily disable a script you can uncheck this box.
|
||||
Below these buttons is a list of all the plugins you have loaded for your project. Each entry will have a text box showing the path of the script file. This path can be freely updated, or you can choose a new path with the |button-folder| button next to it. The |button-edit| button will open the script file in your default text editor, and the |button-remove| button will remove it from the list. The check box to the left of the filepath indicates whether your script should be running. If you'd like to temporarily disable a script you can uncheck this box.
|
||||
|
||||
.. |button-create| image:: images/scripting-capabilities/button-create.png
|
||||
:height: 24
|
||||
@@ -51,12 +51,12 @@ Below these buttons is a list of all the custom scripts you have loaded for your
|
||||
:height: 24
|
||||
|
||||
|
||||
Writing a Custom Script
|
||||
Writing a Plugin Script
|
||||
-----------------------
|
||||
|
||||
Let's write a custom script that will randomize grass patterns when the user is editing the map. This is useful, since it's cumbersome to manually add randomness to grass patches. With the custom script, it will happen automatically. Whenever the user paints a grass tile onto the map, the script will overwrite the tile with a random grass tile instead.
|
||||
Let's write a plugin script that will randomize grass patterns when the user is editing the map. This is useful, since it's cumbersome to manually add randomness to grass patches. With the plugin script, it will happen automatically. Whenever the user paints a grass tile onto the map, the script will overwrite the tile with a random grass tile instead.
|
||||
|
||||
First, open the ``Options -> Custom Scripts...`` window and select the |button-create| button. This will open a file save prompt; let's name our new script file ``my_script.js`` and save it. We've successfully added a new script! We can now see it listed in the editor.
|
||||
First, open the ``Options -> Plugins...`` window and select the |button-create| button. This will open a file save prompt; let's name our new script file ``my_script.js`` and save it. We've successfully added a new script! We can now see it listed in the editor.
|
||||
|
||||
.. figure:: images/scripting-capabilities/new-script.png
|
||||
:alt: Our New Script
|
||||
@@ -117,7 +117,7 @@ Now let's test our script! If we try to paint grass on the map, we should see ou
|
||||
Registering Script Actions
|
||||
--------------------------
|
||||
|
||||
The grass-randomizer script above happens implicitly when the user paints on the map. However, other times we probably want to call the custom script on demand. One of the API functions Porymap provides is the ability to trigger scripting functions from the ``Tools`` menu, or a keyboard shortcut. To do this, we will usually want to register the action when the project loads. Here is an example script where some custom actions are registered.
|
||||
The grass-randomizer script above happens implicitly when the user paints on the map. However, other times we probably want to call the plugin script on demand. One of the API functions Porymap provides is the ability to trigger scripting functions from the ``Tools`` menu, or a keyboard shortcut. To do this, we will usually want to register the action when the project loads. Here is an example script where some custom actions are registered.
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
@@ -1829,11 +1829,11 @@ All settings functions are callable via the global ``utility`` object.
|
||||
:param enabled: smart paths enabled
|
||||
:type enabled: boolean
|
||||
|
||||
.. js:function:: utility.getCustomScripts()
|
||||
.. js:function:: utility.getPluginScripts()
|
||||
|
||||
Gets the list of paths to custom scripts.
|
||||
Gets the list of paths to plugin scripts.
|
||||
|
||||
:returns: string array of custom scripts paths
|
||||
:returns: string array of plugin script paths
|
||||
:rtype: array
|
||||
|
||||
.. js:function:: utility.getMainTab()
|
||||
@@ -1908,7 +1908,7 @@ All settings functions are callable via the global ``utility`` object.
|
||||
Utility Functions
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
These are some miscellaneous functions that can be very useful when building custom scripts.
|
||||
These are some miscellaneous functions that can be very useful when building plugins.
|
||||
|
||||
All utility functions are callable via the global ``utility`` object.
|
||||
|
||||
@@ -1947,7 +1947,7 @@ All utility functions are callable via the global ``utility`` object.
|
||||
|
||||
.. js:function:: utility.log(message)
|
||||
|
||||
Logs a message to the Porymap log file with the prefix ``[INFO]``. This is useful for debugging custom scripts.
|
||||
Logs a message to the Porymap log file with the prefix ``[INFO]``. This is useful for debugging.
|
||||
|
||||
:param message: the message to log
|
||||
:type message: string
|
||||
|
||||
@@ -2919,7 +2919,7 @@
|
||||
<addaction name="actionProject_Settings"/>
|
||||
<addaction name="actionPreferences"/>
|
||||
<addaction name="actionShortcuts"/>
|
||||
<addaction name="actionCustom_Scripts"/>
|
||||
<addaction name="actionPlugins"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
@@ -3161,9 +3161,9 @@
|
||||
<string>Project Settings...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCustom_Scripts">
|
||||
<action name="actionPlugins">
|
||||
<property name="text">
|
||||
<string>Custom Scripts...</string>
|
||||
<string>Plugins...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCheck_for_Updates">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CustomScriptsEditor</class>
|
||||
<widget class="QMainWindow" name="CustomScriptsEditor">
|
||||
<class>PluginEditor</class>
|
||||
<widget class="QMainWindow" name="PluginEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Custom Scripts Editor</string>
|
||||
<string>Plugin Editor</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
@@ -58,12 +58,12 @@
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_CreateNewScript">
|
||||
<widget class="QPushButton" name="button_CreateNewPlugin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Create a new Porymap script file with a default template</p></body></html></string>
|
||||
<string><html><head/><body><p>Create a new Porymap plugin script file with a default template</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create New Script...</string>
|
||||
<string>Create New Plugin...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
@@ -72,12 +72,12 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_LoadScript">
|
||||
<widget class="QPushButton" name="button_LoadPlugin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Add an existing script file to the list below</p></body></html></string>
|
||||
<string><html><head/><body><p>Add an existing plugin script file to the list below</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Script...</string>
|
||||
<string>Load Plugin...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
@@ -86,12 +86,12 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_RefreshScripts">
|
||||
<widget class="QPushButton" name="button_RefreshPlugins">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Refresh all loaded scripts to account for any recent edits</p></body></html></string>
|
||||
<string><html><head/><body><p>Refresh all loaded plugins to account for any recent edits</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh Scripts</string>
|
||||
<string>Refresh Plugins</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
@@ -142,7 +142,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_ListHeader">
|
||||
<property name="text">
|
||||
<string>Scripts</string>
|
||||
<string>Plugins</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CustomScriptsListItem</class>
|
||||
<widget class="QFrame" name="CustomScriptsListItem">
|
||||
<class>PluginListItem</class>
|
||||
<widget class="QFrame" name="PluginListItem">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -26,7 +26,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_Enable">
|
||||
<property name="toolTip">
|
||||
<string>If unchecked this script will be ignored</string>
|
||||
<string>If unchecked this plugin will be ignored</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -49,7 +49,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="b_Choose">
|
||||
<property name="toolTip">
|
||||
<string>Choose a new filepath for this script</string>
|
||||
<string>Choose a new filepath for this plugin</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -63,7 +63,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="b_Edit">
|
||||
<property name="toolTip">
|
||||
<string>Open this script file</string>
|
||||
<string>Open this plugin's script file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -77,7 +77,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="b_Delete">
|
||||
<property name="toolTip">
|
||||
<string>Remove this script</string>
|
||||
<string>Remove this plugin</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
27
include/api/pluginsettings.h
Normal file
27
include/api/pluginsettings.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#ifndef PLUGINSETTINGS_H
|
||||
#define PLUGINSETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
// Holds the basic user-provided information about a plugin.
|
||||
struct PluginSettings {
|
||||
QString path;
|
||||
bool enabled = true;
|
||||
|
||||
// Plugins can either be specific to the project, or specific to the user.
|
||||
// This allows projects to send plugin scripts downstream to their users,
|
||||
// while still allowing them to use their own personal plugins.
|
||||
bool userOnly = true;
|
||||
|
||||
static QStringList filter(const QList<PluginSettings>& plugins) {
|
||||
QStringList paths;
|
||||
for (auto& plugin : plugins) {
|
||||
if (plugin.enabled) paths.append(plugin.path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PLUGINSETTINGS_H
|
||||
@@ -21,7 +21,7 @@ class MainWindow;
|
||||
#ifdef QT_QML_LIB
|
||||
|
||||
// !! New callback functions or changes to existing callback function names/arguments
|
||||
// should be synced to resources/text/script_template.txt and docsrc/manual/scripting-capabilities.rst
|
||||
// should be synced to resources/text/plugin_template.txt and docsrc/manual/scripting-capabilities.rst
|
||||
class Scripting : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -50,7 +50,8 @@ public:
|
||||
Q_INVOKABLE bool getBorderVisibility();
|
||||
Q_INVOKABLE void setSmartPathsEnabled(bool visible);
|
||||
Q_INVOKABLE bool getSmartPathsEnabled();
|
||||
static Q_INVOKABLE QList<QString> getCustomScripts();
|
||||
static Q_INVOKABLE QList<QString> getPluginScripts();
|
||||
static Q_INVOKABLE QList<QString> getCustomScripts() {return getPluginScripts();} // Alias for backwards-compatibility
|
||||
Q_INVOKABLE QList<int> getMetatileLayerOrder();
|
||||
Q_INVOKABLE void setMetatileLayerOrder(const QList<int> &order);
|
||||
Q_INVOKABLE QList<float> getMetatileLayerOpacity();
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
int metatileSelectorWidth = 8;
|
||||
QStringList globalConstantsFilepaths;
|
||||
QMap<QString,QString> globalConstants;
|
||||
QList<ScriptSettings> customScripts;
|
||||
QList<PluginSettings> plugins;
|
||||
QMap<Event::Group, QString> eventIconPaths;
|
||||
QMap<QString, QString> pokemonIconPaths;
|
||||
QVersionNumber minimumVersion;
|
||||
@@ -248,7 +248,7 @@ public:
|
||||
m_fm->addField(&this->metatileSelectorWidth, "metatile_selector_width", 1, INT_MAX);
|
||||
m_fm->addField(&this->globalConstantsFilepaths, "global_constants_filepaths");
|
||||
m_fm->addField(&this->globalConstants, "global_constants");
|
||||
m_fm->addField(&this->customScripts, "custom_scripts");
|
||||
m_fm->addField(&this->plugins, "plugins");
|
||||
m_fm->addField(&this->eventIconPaths, "event_icon_paths");
|
||||
m_fm->addField(&this->pokemonIconPaths, "pokemon_icon_paths");
|
||||
m_fm->addField(&this->minimumVersion, "minimum_version");
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
QString prefabsFilepath;
|
||||
bool prefabsImportPrompted = false;
|
||||
bool useEncounterJson = true;
|
||||
QList<ScriptSettings> customScripts;
|
||||
QList<PluginSettings> plugins;
|
||||
|
||||
protected:
|
||||
virtual bool parseLegacyKeyValue(const QString& key, const QString& value) override;
|
||||
@@ -32,7 +32,7 @@ protected:
|
||||
m_fm->addField(&this->prefabsFilepath, "prefabs_filepath");
|
||||
m_fm->addField(&this->prefabsImportPrompted, "prefabs_import_prompted");
|
||||
m_fm->addField(&this->useEncounterJson, "use_encounter_json");
|
||||
m_fm->addField(&this->customScripts, "custom_scripts");
|
||||
m_fm->addField(&this->plugins, "plugins");
|
||||
}
|
||||
return m_fm.get();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "magic_enum.hpp"
|
||||
#include "orderedset.h"
|
||||
#include "scriptsettings.h"
|
||||
#include "pluginsettings.h"
|
||||
#include "gridsettings.h"
|
||||
#include "basegame.h"
|
||||
|
||||
@@ -360,16 +360,16 @@ struct Converter<QMargins> : DefaultConverter<QMargins> {
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<ScriptSettings> : DefaultConverter<ScriptSettings> {
|
||||
static QJsonValue toJson(const ScriptSettings& value) {
|
||||
struct Converter<PluginSettings> : DefaultConverter<PluginSettings> {
|
||||
static QJsonValue toJson(const PluginSettings& value) {
|
||||
QJsonObject obj;
|
||||
obj["path"] = value.path;
|
||||
obj["enabled"] = value.enabled;
|
||||
return obj;
|
||||
}
|
||||
static ScriptSettings fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
static PluginSettings fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
ScriptSettings settings;
|
||||
PluginSettings settings;
|
||||
settings.path = obj.value("path").toString();
|
||||
settings.enabled = obj.value("enabled").toBool();
|
||||
return settings;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef SCRIPTSETTINGS_H
|
||||
#define SCRIPTSETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
// Holds the basic user-provided information about a plug-in script.
|
||||
struct ScriptSettings {
|
||||
QString path;
|
||||
bool enabled = true;
|
||||
|
||||
// Scripts can either be specific to the project, or specific to the user.
|
||||
// This allows projects to send scripts downstream to their users,
|
||||
// while still allowing them to use their own personal scripts.
|
||||
bool userOnly = true;
|
||||
|
||||
static QStringList filter(const QList<ScriptSettings>& scripts) {
|
||||
QStringList paths;
|
||||
for (auto& script : scripts) {
|
||||
if (script.enabled) paths.append(script.path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SCRIPTSETTINGS_H
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "preferenceeditor.h"
|
||||
#include "projectsettingseditor.h"
|
||||
#include "gridsettings.h"
|
||||
#include "customscriptseditor.h"
|
||||
#include "plugineditor.h"
|
||||
#include "wildmonchart.h"
|
||||
#include "wildmonsearch.h"
|
||||
#include "updatepromoter.h"
|
||||
@@ -303,7 +303,7 @@ private slots:
|
||||
void on_actionCheck_for_Updates_triggered();
|
||||
void togglePreferenceSpecificUi();
|
||||
void on_actionProject_Settings_triggered();
|
||||
void on_actionCustom_Scripts_triggered();
|
||||
void on_actionPlugins_triggered();
|
||||
void reloadScriptEngine();
|
||||
void on_actionShow_Grid_triggered();
|
||||
void on_actionGrid_Settings_triggered();
|
||||
@@ -326,7 +326,7 @@ private:
|
||||
QPointer<PreferenceEditor> preferenceEditor = nullptr;
|
||||
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
|
||||
QPointer<GridSettingsDialog> gridSettingsDialog = nullptr;
|
||||
QPointer<CustomScriptsEditor> customScriptsEditor = nullptr;
|
||||
QPointer<PluginEditor> pluginEditor = nullptr;
|
||||
|
||||
QPointer<FilterChildrenProxyModel> groupListProxyModel = nullptr;
|
||||
QPointer<MapGroupModel> mapGroupModel = nullptr;
|
||||
@@ -454,7 +454,7 @@ private:
|
||||
bool initRegionMapEditor(bool silent = false);
|
||||
bool askToFixRegionMapEditor();
|
||||
void initShortcutsEditor();
|
||||
void initCustomScriptsEditor();
|
||||
void initPluginEditor();
|
||||
void connectSubEditorsToShortcutsEditor();
|
||||
void openProjectSettingsEditor(int tab);
|
||||
bool isProjectOpen();
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#ifndef CUSTOMSCRIPTSEDITOR_H
|
||||
#define CUSTOMSCRIPTSEDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QListWidget>
|
||||
#include <QAbstractButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "customscriptslistitem.h"
|
||||
|
||||
namespace Ui {
|
||||
class CustomScriptsEditor;
|
||||
}
|
||||
|
||||
|
||||
class CustomScriptsEditor : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CustomScriptsEditor(QWidget *parent = nullptr);
|
||||
~CustomScriptsEditor();
|
||||
|
||||
signals:
|
||||
void reloadScriptEngine();
|
||||
|
||||
public slots:
|
||||
void applyUserShortcuts();
|
||||
|
||||
private:
|
||||
Ui::CustomScriptsEditor *ui;
|
||||
|
||||
bool hasUnsavedChanges = false;
|
||||
const QString baseDir;
|
||||
|
||||
void displayScript(const ScriptSettings &settings);
|
||||
void displayNewScript(QString filepath);
|
||||
QString chooseScript(QString dir);
|
||||
void removeScript(QListWidgetItem * item);
|
||||
void replaceScript(QListWidgetItem * item);
|
||||
void openScript(QListWidgetItem * item);
|
||||
QString getScriptFilepath(QListWidgetItem * item, bool absolutePath = true) const;
|
||||
void setScriptFilepath(QListWidgetItem * item, QString filepath) const;
|
||||
bool getScriptEnabled(QListWidgetItem * item) const;
|
||||
void markEdited();
|
||||
int prompt(const QString &text, QMessageBox::StandardButton defaultButton);
|
||||
void save();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void initShortcuts();
|
||||
QObjectList shortcutableObjects() const;
|
||||
void openManual();
|
||||
|
||||
private slots:
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
void createNewScript();
|
||||
void loadScript();
|
||||
bool refreshScripts();
|
||||
void userRefreshScripts();
|
||||
void removeSelectedScripts();
|
||||
void openSelectedScripts();
|
||||
};
|
||||
|
||||
#endif // CUSTOMSCRIPTSEDITOR_H
|
||||
@@ -1,40 +0,0 @@
|
||||
#ifndef CUSTOMSCRIPTSLISTITEM_H
|
||||
#define CUSTOMSCRIPTSLISTITEM_H
|
||||
|
||||
#include <QFrame>
|
||||
#include "scriptsettings.h"
|
||||
|
||||
namespace Ui {
|
||||
class CustomScriptsListItem;
|
||||
}
|
||||
|
||||
class CustomScriptsListItem : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CustomScriptsListItem(QWidget *parent = nullptr);
|
||||
explicit CustomScriptsListItem(const ScriptSettings& settings, QWidget *parent = nullptr);
|
||||
~CustomScriptsListItem();
|
||||
|
||||
void setSettings(const ScriptSettings& settings);
|
||||
ScriptSettings getSettings() const;
|
||||
|
||||
void setPath(const QString& text);
|
||||
QString path() const;
|
||||
|
||||
void setScriptEnabled(bool enabled);
|
||||
bool scriptEnabled() const;
|
||||
|
||||
signals:
|
||||
void clickedChooseScript();
|
||||
void clickedEditScript();
|
||||
void clickedDeleteScript();
|
||||
void toggledEnable(bool checked);
|
||||
void pathEdited(const QString& text);
|
||||
|
||||
private:
|
||||
Ui::CustomScriptsListItem *ui;
|
||||
};
|
||||
|
||||
#endif // CUSTOMSCRIPTSLISTITEM_H
|
||||
63
include/ui/plugineditor.h
Normal file
63
include/ui/plugineditor.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef PLUGINEDITOR_H
|
||||
#define PLUGINEDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QListWidget>
|
||||
#include <QAbstractButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "pluginlistitem.h"
|
||||
|
||||
namespace Ui {
|
||||
class PluginEditor;
|
||||
}
|
||||
|
||||
|
||||
class PluginEditor : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PluginEditor(QWidget *parent = nullptr);
|
||||
~PluginEditor();
|
||||
|
||||
signals:
|
||||
void reloadScriptEngine();
|
||||
|
||||
public slots:
|
||||
void applyUserShortcuts();
|
||||
|
||||
private:
|
||||
Ui::PluginEditor *ui;
|
||||
|
||||
bool hasUnsavedChanges = false;
|
||||
const QString baseDir;
|
||||
|
||||
void displayPlugin(const PluginSettings &settings);
|
||||
void displayNewPlugin(QString filepath);
|
||||
QString choosePlugin(QString dir);
|
||||
void removePlugin(QListWidgetItem * item);
|
||||
void replacePlugin(QListWidgetItem * item);
|
||||
void openPlugin(QListWidgetItem * item);
|
||||
QString getPluginFilepath(QListWidgetItem * item, bool absolutePath = true) const;
|
||||
void setPluginFilepath(QListWidgetItem * item, QString filepath) const;
|
||||
bool getPluginEnabled(QListWidgetItem * item) const;
|
||||
void markEdited();
|
||||
int prompt(const QString &text, QMessageBox::StandardButton defaultButton);
|
||||
void save();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void initShortcuts();
|
||||
QObjectList shortcutableObjects() const;
|
||||
void openManual();
|
||||
|
||||
private slots:
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
void createNewPlugin();
|
||||
void loadPlugin();
|
||||
bool refreshPlugins();
|
||||
void userRefreshPlugins();
|
||||
void removeSelectedPlugins();
|
||||
void openSelectedPlugins();
|
||||
};
|
||||
|
||||
#endif // PLUGINEDITOR_H
|
||||
40
include/ui/pluginlistitem.h
Normal file
40
include/ui/pluginlistitem.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef PLUGINLISTITEM_H
|
||||
#define PLUGINLISTITEM_H
|
||||
|
||||
#include <QFrame>
|
||||
#include "pluginsettings.h"
|
||||
|
||||
namespace Ui {
|
||||
class PluginListItem;
|
||||
}
|
||||
|
||||
class PluginListItem : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PluginListItem(QWidget *parent = nullptr);
|
||||
explicit PluginListItem(const PluginSettings& settings, QWidget *parent = nullptr);
|
||||
~PluginListItem();
|
||||
|
||||
void setSettings(const PluginSettings& settings);
|
||||
PluginSettings getSettings() const;
|
||||
|
||||
void setPath(const QString& text);
|
||||
QString path() const;
|
||||
|
||||
void setPluginEnabled(bool enabled);
|
||||
bool pluginEnabled() const;
|
||||
|
||||
signals:
|
||||
void clickedChoosePlugin();
|
||||
void clickedEditPlugin();
|
||||
void clickedDeletePlugin();
|
||||
void toggledEnable(bool checked);
|
||||
void pathEdited(const QString& text);
|
||||
|
||||
private:
|
||||
Ui::PluginListItem *ui;
|
||||
};
|
||||
|
||||
#endif // PLUGINLISTITEM_H
|
||||
25
porymap.pro
25
porymap.pro
@@ -81,10 +81,10 @@ SOURCES += src/config/keyvalueconfigbase.cpp \
|
||||
src/lib/collapsiblesection.cpp \
|
||||
src/lib/orderedjson.cpp \
|
||||
src/core/regionmapeditcommands.cpp \
|
||||
src/scriptapi/apimap.cpp \
|
||||
src/scriptapi/apioverlay.cpp \
|
||||
src/scriptapi/apiutility.cpp \
|
||||
src/scriptapi/scripting.cpp \
|
||||
src/api/apimap.cpp \
|
||||
src/api/apioverlay.cpp \
|
||||
src/api/apiutility.cpp \
|
||||
src/api/scripting.cpp \
|
||||
src/ui/aboutporymap.cpp \
|
||||
src/ui/checkeredbgscene.cpp \
|
||||
src/ui/colorinputwidget.cpp \
|
||||
@@ -92,8 +92,8 @@ SOURCES += src/config/keyvalueconfigbase.cpp \
|
||||
src/ui/connectionslistitem.cpp \
|
||||
src/ui/customattributesdialog.cpp \
|
||||
src/ui/customattributestable.cpp \
|
||||
src/ui/customscriptseditor.cpp \
|
||||
src/ui/customscriptslistitem.cpp \
|
||||
src/ui/plugineditor.cpp \
|
||||
src/ui/pluginlistitem.cpp \
|
||||
src/ui/divingmappixmapitem.cpp \
|
||||
src/ui/eventpixmapitem.cpp \
|
||||
src/ui/bordermetatilespixmapitem.cpp \
|
||||
@@ -215,8 +215,8 @@ HEADERS += include/config/keyvalueconfigbase.h \
|
||||
include/ui/connectionslistitem.h \
|
||||
include/ui/customattributesdialog.h \
|
||||
include/ui/customattributestable.h \
|
||||
include/ui/customscriptseditor.h \
|
||||
include/ui/customscriptslistitem.h \
|
||||
include/ui/plugineditor.h \
|
||||
include/ui/pluginlistitem.h \
|
||||
include/ui/divingmappixmapitem.h \
|
||||
include/ui/edithistoryspinbox.h \
|
||||
include/ui/eventcombobox.h \
|
||||
@@ -289,8 +289,8 @@ HEADERS += include/config/keyvalueconfigbase.h \
|
||||
include/editor.h \
|
||||
include/mainwindow.h \
|
||||
include/project.h \
|
||||
include/scripting.h \
|
||||
include/scriptutility.h \
|
||||
include/api/scripting.h \
|
||||
include/api/scriptutility.h \
|
||||
include/settings.h \
|
||||
include/log.h \
|
||||
include/ui/uintspinbox.h \
|
||||
@@ -329,8 +329,8 @@ FORMS += forms/mainwindow.ui \
|
||||
forms/regionmappropertiesdialog.ui \
|
||||
forms/colorpicker.ui \
|
||||
forms/projectsettingseditor.ui \
|
||||
forms/customscriptseditor.ui \
|
||||
forms/customscriptslistitem.ui \
|
||||
forms/plugineditor.ui \
|
||||
forms/pluginlistitem.ui \
|
||||
forms/customattributesdialog.ui \
|
||||
forms/updatepromoter.ui \
|
||||
forms/wildmonchart.ui \
|
||||
@@ -343,6 +343,7 @@ RESOURCES += \
|
||||
resources/text.qrc
|
||||
|
||||
INCLUDEPATH += include
|
||||
INCLUDEPATH += include/api
|
||||
INCLUDEPATH += include/config
|
||||
INCLUDEPATH += include/core
|
||||
INCLUDEPATH += include/ui
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<file>text/prefabs_default_emerald.json</file>
|
||||
<file>text/prefabs_default_firered.json</file>
|
||||
<file>text/prefabs_default_ruby.json</file>
|
||||
<file>text/script_template.txt</file>
|
||||
<file>text/plugin_template.txt</file>
|
||||
<file>../CHANGELOG.md</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -197,12 +197,12 @@ bool ScriptUtility::getSmartPathsEnabled() {
|
||||
return window->ui->checkBox_smartPaths->isChecked();
|
||||
}
|
||||
|
||||
QList<QString> ScriptUtility::getCustomScripts() {
|
||||
QList<QString> ScriptUtility::getPluginScripts() {
|
||||
QList<QString> paths;
|
||||
for (const auto& settings : userConfig.customScripts)
|
||||
paths.append(settings.path);
|
||||
for (const auto& settings : projectConfig.customScripts)
|
||||
paths.append(settings.path);
|
||||
for (const auto& plugin : userConfig.plugins)
|
||||
paths.append(plugin.path);
|
||||
for (const auto& plugin : projectConfig.plugins)
|
||||
paths.append(plugin.path);
|
||||
return paths;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ Scripting::Scripting(MainWindow *mainWindow)
|
||||
{
|
||||
this->engine->installExtensions(QJSEngine::ConsoleExtension);
|
||||
|
||||
const QStringList paths = ScriptSettings::filter(userConfig.customScripts)
|
||||
+ ScriptSettings::filter(projectConfig.customScripts);
|
||||
const QStringList paths = PluginSettings::filter(userConfig.plugins)
|
||||
+ PluginSettings::filter(projectConfig.plugins);
|
||||
for (const auto& path : paths) {
|
||||
loadScript(path);
|
||||
}
|
||||
@@ -61,7 +61,7 @@ void Scripting::loadScript(const QString &filepath) {
|
||||
if (script->filepath().isEmpty() || tryErrorJS(script->module())) {
|
||||
QMessageBox messageBox(this->mainWindow);
|
||||
messageBox.setText("Failed to load script");
|
||||
messageBox.setInformativeText(QString("An error occurred while loading custom script file '%1'").arg(filepath));
|
||||
messageBox.setInformativeText(QString("An error occurred while loading plugin script file '%1'").arg(filepath));
|
||||
messageBox.setDetailedText(getMostRecentError());
|
||||
messageBox.setIcon(QMessageBox::Warning);
|
||||
messageBox.addButton(QMessageBox::Ok);
|
||||
@@ -69,7 +69,7 @@ void Scripting::loadScript(const QString &filepath) {
|
||||
return;
|
||||
}
|
||||
|
||||
logInfo(QString("Successfully loaded custom script file '%1'").arg(filepath));
|
||||
logInfo(QString("Successfully loaded plugin script file '%1'").arg(filepath));
|
||||
this->scripts.append(script);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ bool Scripting::tryErrorJS(QJSValue js) {
|
||||
QString fileErrStr = fileName == "undefined" ? "" : QString(" '%1'").arg(fileName);
|
||||
QString lineErrStr = lineNumber == "undefined" ? "" : QString(" at line %1").arg(lineNumber);
|
||||
|
||||
logError(QString("Error in custom script%1%2: '%3'")
|
||||
logError(QString("Error in plugin script%1%2: '%3'")
|
||||
.arg(fileErrStr)
|
||||
.arg(lineErrStr)
|
||||
.arg(errStr));
|
||||
@@ -367,7 +367,7 @@ bool ProjectConfig::parseLegacyKeyValue(const QString &key, const QString &value
|
||||
// The format is a comma-separated list of paths. Each path can be followed (before the comma)
|
||||
// by a :0 or :1 to indicate whether it should be disabled or enabled, respectively. If neither
|
||||
// follow, it's assumed the script should be enabled.
|
||||
QList<ScriptSettings> parseCustomScripts(const QString &input) {
|
||||
QList<PluginSettings> parseCustomScripts(const QString &input) {
|
||||
QMap<QString,bool> customScripts;
|
||||
const QList<QString> paths = input.split(",", Qt::SkipEmptyParts);
|
||||
for (QString path : paths) {
|
||||
@@ -381,7 +381,7 @@ QList<ScriptSettings> parseCustomScripts(const QString &input) {
|
||||
customScripts.insert(path, enabled);
|
||||
}
|
||||
}
|
||||
QList<ScriptSettings> settingsList;
|
||||
QList<PluginSettings> settingsList;
|
||||
for (auto it = customScripts.begin(); it != customScripts.end(); it++) {
|
||||
settingsList.append({
|
||||
.path = it.key(),
|
||||
@@ -398,7 +398,7 @@ bool UserConfig::parseLegacyKeyValue(const QString &key, const QString &value) {
|
||||
} else if (key == "use_encounter_json") {
|
||||
this->useEncounterJson = toBool(value);
|
||||
} else if (key == "custom_scripts") {
|
||||
this->customScripts = parseCustomScripts(value);
|
||||
this->plugins = parseCustomScripts(value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -239,8 +239,8 @@ void ProjectConfig::loadFromJson(const QJsonObject& obj_) {
|
||||
|
||||
KeyValueConfigBase::loadFromJson(obj);
|
||||
|
||||
// Enforce this setting for projectConfig's custom scripts
|
||||
for (auto& settings : this->customScripts) settings.userOnly = false;
|
||||
// Enforce this setting for projectConfig's plugins
|
||||
for (auto& settings : this->plugins) settings.userOnly = false;
|
||||
}
|
||||
|
||||
QJsonObject ProjectConfig::getDefaultJson() const {
|
||||
|
||||
@@ -6,8 +6,8 @@ UserConfig userConfig;
|
||||
void UserConfig::loadFromJson(const QJsonObject& obj) {
|
||||
KeyValueConfigBase::loadFromJson(obj);
|
||||
|
||||
// Enforce this setting for userConfig's custom scripts
|
||||
for (auto& settings : this->customScripts) settings.userOnly = true;
|
||||
// Enforce this setting for userConfig's plugins
|
||||
for (auto& settings : this->plugins) settings.userOnly = true;
|
||||
}
|
||||
|
||||
QJsonObject UserConfig::getDefaultJson() const {
|
||||
|
||||
@@ -212,7 +212,7 @@ void MainWindow::initWindow() {
|
||||
#endif
|
||||
|
||||
#ifndef QT_QML_LIB
|
||||
ui->actionCustom_Scripts->setVisible(false);
|
||||
ui->actionPlugins->setVisible(false);
|
||||
missingModules.append(" 'qml'");
|
||||
#endif
|
||||
|
||||
@@ -806,7 +806,7 @@ bool MainWindow::openProject(QString dir, bool initial) {
|
||||
return false;
|
||||
}
|
||||
|
||||
porysplash->showLoadingMessage("custom scripts");
|
||||
porysplash->showLoadingMessage("plugin scripts");
|
||||
Scripting::init(this);
|
||||
|
||||
// Create the project
|
||||
@@ -2405,12 +2405,12 @@ void MainWindow::connectSubEditorsToShortcutsEditor() {
|
||||
this->regionMapEditor, &RegionMapEditor::applyUserShortcuts);
|
||||
}
|
||||
|
||||
if (!this->customScriptsEditor) {
|
||||
initCustomScriptsEditor();
|
||||
if (!this->pluginEditor) {
|
||||
initPluginEditor();
|
||||
}
|
||||
if (this->customScriptsEditor) {
|
||||
if (this->pluginEditor) {
|
||||
connect(this->shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
this->customScriptsEditor, &CustomScriptsEditor::applyUserShortcuts);
|
||||
this->pluginEditor, &PluginEditor::applyUserShortcuts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3107,19 +3107,19 @@ void MainWindow::onWarpBehaviorWarningClicked() {
|
||||
msgBox->open();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCustom_Scripts_triggered() {
|
||||
if (!this->customScriptsEditor) {
|
||||
initCustomScriptsEditor();
|
||||
void MainWindow::on_actionPlugins_triggered() {
|
||||
if (!this->pluginEditor) {
|
||||
initPluginEditor();
|
||||
}
|
||||
if (this->customScriptsEditor) {
|
||||
Util::show(this->customScriptsEditor);
|
||||
if (this->pluginEditor) {
|
||||
Util::show(this->pluginEditor);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::initCustomScriptsEditor() {
|
||||
void MainWindow::initPluginEditor() {
|
||||
#ifdef QT_QML_LIB
|
||||
this->customScriptsEditor = new CustomScriptsEditor(this);
|
||||
connect(this->customScriptsEditor, &CustomScriptsEditor::reloadScriptEngine,
|
||||
this->pluginEditor = new PluginEditor(this);
|
||||
connect(this->pluginEditor, &PluginEditor::reloadScriptEngine,
|
||||
this, &MainWindow::reloadScriptEngine);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
#include "customscriptseditor.h"
|
||||
#include "ui_customscriptseditor.h"
|
||||
#include "ui_customscriptslistitem.h"
|
||||
#include "config.h"
|
||||
#include "editor.h"
|
||||
#include "shortcut.h"
|
||||
#include "filedialog.h"
|
||||
#include "eventfilters.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QToolTip>
|
||||
|
||||
CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::CustomScriptsEditor),
|
||||
baseDir(userConfig.projectDir() + "/")
|
||||
{
|
||||
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 (const auto& settings : projectConfig.customScripts)
|
||||
displayScript(settings);
|
||||
for (const auto& settings : userConfig.customScripts)
|
||||
displayScript(settings);
|
||||
|
||||
connect(ui->button_Help, &QAbstractButton::clicked, this, &CustomScriptsEditor::openManual);
|
||||
connect(ui->button_CreateNewScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::createNewScript);
|
||||
connect(ui->button_LoadScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::loadScript);
|
||||
connect(ui->button_RefreshScripts, &QAbstractButton::clicked, this, &CustomScriptsEditor::userRefreshScripts);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &CustomScriptsEditor::dialogButtonClicked);
|
||||
|
||||
initShortcuts();
|
||||
installEventFilter(new GeometrySaver(this));
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
auto *shortcut_open = new Shortcut(QKeySequence(), this, SLOT(openSelectedScripts()));
|
||||
shortcut_open->setObjectName("shortcut_open");
|
||||
shortcut_open->setWhatsThis("Open Selected Scripts");
|
||||
|
||||
auto *shortcut_createNew = new Shortcut(QKeySequence(), this, SLOT(createNewScript()));
|
||||
shortcut_createNew->setObjectName("shortcut_createNew");
|
||||
shortcut_createNew->setWhatsThis("Create New Script...");
|
||||
|
||||
auto *shortcut_load = new Shortcut(QKeySequence(), this, SLOT(loadScript()));
|
||||
shortcut_load->setObjectName("shortcut_load");
|
||||
shortcut_load->setWhatsThis("Load Script...");
|
||||
|
||||
auto *shortcut_refresh = new Shortcut(QKeySequence(), this, SLOT(userRefreshScripts()));
|
||||
shortcut_refresh->setObjectName("shortcut_refresh");
|
||||
shortcut_refresh->setWhatsThis("Refresh Scripts");
|
||||
|
||||
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
|
||||
applyUserShortcuts();
|
||||
}
|
||||
|
||||
QObjectList CustomScriptsEditor::shortcutableObjects() const {
|
||||
QObjectList shortcutable_objects;
|
||||
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(shortcut));
|
||||
|
||||
return shortcutable_objects;
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::applyUserShortcuts() {
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
action->setShortcuts(shortcutsConfig.userShortcuts(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::displayScript(const ScriptSettings& settings) {
|
||||
auto item = new QListWidgetItem(ui->list);
|
||||
auto widget = new CustomScriptsListItem(settings, ui->list);
|
||||
item->setSizeHint(widget->sizeHint());
|
||||
|
||||
connect(widget, &CustomScriptsListItem::clickedChooseScript, [this, item] { this->replaceScript(item); });
|
||||
connect(widget, &CustomScriptsListItem::clickedEditScript, [this, item] { this->openScript(item); });
|
||||
connect(widget, &CustomScriptsListItem::clickedDeleteScript, [this, item] { this->removeScript(item); });
|
||||
connect(widget, &CustomScriptsListItem::toggledEnable, this, &CustomScriptsEditor::markEdited);
|
||||
connect(widget, &CustomScriptsListItem::pathEdited, this, &CustomScriptsEditor::markEdited);
|
||||
|
||||
// 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, widget);
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::markEdited() {
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
QString CustomScriptsEditor::getScriptFilepath(QListWidgetItem * item, bool absolutePath) const {
|
||||
auto widget = dynamic_cast<CustomScriptsListItem *>(ui->list->itemWidget(item));
|
||||
if (!widget) return QString();
|
||||
|
||||
QString path = widget->path();
|
||||
if (absolutePath) {
|
||||
QFileInfo fileInfo(path);
|
||||
if (fileInfo.isRelative())
|
||||
path.prepend(this->baseDir);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::setScriptFilepath(QListWidgetItem * item, QString filepath) const {
|
||||
auto widget = dynamic_cast<CustomScriptsListItem *>(ui->list->itemWidget(item));
|
||||
if (widget) {
|
||||
widget->setPath(Util::stripPrefix(filepath, this->baseDir));
|
||||
}
|
||||
}
|
||||
|
||||
bool CustomScriptsEditor::getScriptEnabled(QListWidgetItem * item) const {
|
||||
auto widget = dynamic_cast<CustomScriptsListItem *>(ui->list->itemWidget(item));
|
||||
return widget && widget->scriptEnabled();
|
||||
}
|
||||
|
||||
QString CustomScriptsEditor::chooseScript(QString dir) {
|
||||
return FileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)");
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::createNewScript() {
|
||||
const QString filepath = FileDialog::getSaveFileName(this, "Create New Script File", FileDialog::getDirectory() + "/new_script.js", "JavaScript Files (*.js)");
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
|
||||
QFile scriptFile(filepath);
|
||||
if (!scriptFile.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Error: Could not open %1 for writing").arg(filepath));
|
||||
QMessageBox messageBox(this);
|
||||
messageBox.setText("Failed to create new script file!");
|
||||
messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(filepath));
|
||||
messageBox.setIcon(QMessageBox::Warning);
|
||||
messageBox.exec();
|
||||
return;
|
||||
}
|
||||
ParseUtil parser;
|
||||
scriptFile.write(parser.readTextFile(":/text/script_template.txt").toUtf8());
|
||||
scriptFile.close();
|
||||
|
||||
this->displayNewScript(filepath);
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::loadScript() {
|
||||
QString filepath = this->chooseScript(FileDialog::getDirectory());
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->displayNewScript(filepath);
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::displayNewScript(QString filepath) {
|
||||
filepath = Util::stripPrefix(filepath, this->baseDir);
|
||||
|
||||
// Verify new script path is not already in list
|
||||
for (int i = 0; i < ui->list->count(); i++) {
|
||||
if (filepath == this->getScriptFilepath(ui->list->item(i), false)) {
|
||||
QMessageBox::information(this, QApplication::applicationName(), QString("The script '%1' is already loaded").arg(filepath));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptSettings settings;
|
||||
settings.path = filepath;
|
||||
this->displayScript(settings);
|
||||
this->markEdited();
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::removeScript(QListWidgetItem * item) {
|
||||
ui->list->takeItem(ui->list->row(item));
|
||||
this->markEdited();
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::removeSelectedScripts() {
|
||||
QList<QListWidgetItem *> 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->getScriptFilepath(item));
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->setScriptFilepath(item, filepath);
|
||||
this->markEdited();
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::openScript(QListWidgetItem * item) {
|
||||
const QString path = this->getScriptFilepath(item);
|
||||
QFileInfo fileInfo(path);
|
||||
if (!fileInfo.exists() || !fileInfo.isFile()){
|
||||
QMessageBox::warning(this, QApplication::applicationName(), 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::openManual() {
|
||||
static const QUrl url("https://huderlem.github.io/porymap/manual/scripting-capabilities.html");
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
// When the user refreshes the scripts we show a little tooltip as feedback.
|
||||
// We don't want this tooltip to display when we refresh programmatically, like when changes are saved.
|
||||
void CustomScriptsEditor::userRefreshScripts() {
|
||||
if (refreshScripts())
|
||||
QToolTip::showText(ui->button_RefreshScripts->mapToGlobal(QPoint(0, 0)), "Refreshed!");
|
||||
}
|
||||
|
||||
bool CustomScriptsEditor::refreshScripts() {
|
||||
if (this->hasUnsavedChanges) {
|
||||
if (this->prompt("Scripts have been modified, save changes and reload the script engine?", QMessageBox::Yes) == QMessageBox::No)
|
||||
return false;
|
||||
this->save();
|
||||
}
|
||||
emit reloadScriptEngine();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::save() {
|
||||
if (!this->hasUnsavedChanges)
|
||||
return;
|
||||
|
||||
QList<ScriptSettings> userScripts;
|
||||
QList<ScriptSettings> projectScripts;
|
||||
for (int i = 0; i < ui->list->count(); i++) {
|
||||
auto item = ui->list->item(i);
|
||||
auto widget = dynamic_cast<CustomScriptsListItem *>(ui->list->itemWidget(item));
|
||||
if (!widget) continue;
|
||||
const ScriptSettings settings = widget->getSettings();
|
||||
if (settings.userOnly) userScripts.append(settings);
|
||||
else projectScripts.append(settings);
|
||||
}
|
||||
|
||||
userConfig.customScripts = userScripts;
|
||||
userConfig.save();
|
||||
|
||||
projectConfig.customScripts = projectScripts;
|
||||
projectConfig.save();
|
||||
|
||||
this->hasUnsavedChanges = false;
|
||||
this->refreshScripts();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#include "customscriptslistitem.h"
|
||||
#include "ui_customscriptslistitem.h"
|
||||
|
||||
CustomScriptsListItem::CustomScriptsListItem(QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::CustomScriptsListItem)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->b_Choose, &QAbstractButton::clicked, this, &CustomScriptsListItem::clickedChooseScript);
|
||||
connect(ui->b_Edit, &QAbstractButton::clicked, this, &CustomScriptsListItem::clickedEditScript);
|
||||
connect(ui->b_Delete, &QAbstractButton::clicked, this, &CustomScriptsListItem::clickedDeleteScript);
|
||||
connect(ui->checkBox_Enable, &QCheckBox::toggled, this, &CustomScriptsListItem::toggledEnable);
|
||||
connect(ui->lineEdit_filepath, &QLineEdit::textEdited, this, &CustomScriptsListItem::pathEdited);
|
||||
}
|
||||
|
||||
CustomScriptsListItem::CustomScriptsListItem(const ScriptSettings& settings, QWidget *parent) :
|
||||
CustomScriptsListItem(parent)
|
||||
{
|
||||
setSettings(settings);
|
||||
}
|
||||
|
||||
CustomScriptsListItem::~CustomScriptsListItem() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CustomScriptsListItem::setPath(const QString& text) {
|
||||
ui->lineEdit_filepath->setText(text);
|
||||
}
|
||||
|
||||
QString CustomScriptsListItem::path() const {
|
||||
return ui->lineEdit_filepath->text();
|
||||
}
|
||||
|
||||
void CustomScriptsListItem::setScriptEnabled(bool enabled) {
|
||||
ui->checkBox_Enable->setChecked(enabled);
|
||||
}
|
||||
|
||||
bool CustomScriptsListItem::scriptEnabled() const {
|
||||
return ui->checkBox_Enable->isChecked();
|
||||
}
|
||||
|
||||
// TODO: The two functions below should read/write from/to the UI whether the script belongs to the project or user.
|
||||
void CustomScriptsListItem::setSettings(const ScriptSettings& settings) {
|
||||
setPath(settings.path);
|
||||
setScriptEnabled(settings.enabled);
|
||||
}
|
||||
|
||||
ScriptSettings CustomScriptsListItem::getSettings() const {
|
||||
return {
|
||||
.path = path(),
|
||||
.enabled = scriptEnabled(),
|
||||
.userOnly = true,
|
||||
};
|
||||
}
|
||||
295
src/ui/plugineditor.cpp
Normal file
295
src/ui/plugineditor.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
#include "plugineditor.h"
|
||||
#include "ui_plugineditor.h"
|
||||
#include "config.h"
|
||||
#include "editor.h"
|
||||
#include "shortcut.h"
|
||||
#include "filedialog.h"
|
||||
#include "eventfilters.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QToolTip>
|
||||
|
||||
PluginEditor::PluginEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::PluginEditor),
|
||||
baseDir(userConfig.projectDir() + "/")
|
||||
{
|
||||
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 (const auto& plugin : projectConfig.plugins)
|
||||
displayPlugin(plugin);
|
||||
for (const auto& plugin : userConfig.plugins)
|
||||
displayPlugin(plugin);
|
||||
|
||||
connect(ui->button_Help, &QAbstractButton::clicked, this, &PluginEditor::openManual);
|
||||
connect(ui->button_CreateNewPlugin, &QAbstractButton::clicked, this, &PluginEditor::createNewPlugin);
|
||||
connect(ui->button_LoadPlugin, &QAbstractButton::clicked, this, &PluginEditor::loadPlugin);
|
||||
connect(ui->button_RefreshPlugins, &QAbstractButton::clicked, this, &PluginEditor::userRefreshPlugins);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &PluginEditor::dialogButtonClicked);
|
||||
|
||||
initShortcuts();
|
||||
installEventFilter(new GeometrySaver(this));
|
||||
}
|
||||
|
||||
PluginEditor::~PluginEditor()
|
||||
{
|
||||
ui->list->clear();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PluginEditor::initShortcuts() {
|
||||
auto *shortcut_remove = new Shortcut({QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(removeSelectedPlugins()));
|
||||
shortcut_remove->setObjectName("shortcut_remove");
|
||||
shortcut_remove->setWhatsThis("Remove Selected Plugins");
|
||||
|
||||
auto *shortcut_open = new Shortcut(QKeySequence(), this, SLOT(openSelectedPlugins()));
|
||||
shortcut_open->setObjectName("shortcut_open");
|
||||
shortcut_open->setWhatsThis("Open Selected Plugins");
|
||||
|
||||
auto *shortcut_createNew = new Shortcut(QKeySequence(), this, SLOT(createNewPlugin()));
|
||||
shortcut_createNew->setObjectName("shortcut_createNew");
|
||||
shortcut_createNew->setWhatsThis("Create New Plugin...");
|
||||
|
||||
auto *shortcut_load = new Shortcut(QKeySequence(), this, SLOT(loadPlugin()));
|
||||
shortcut_load->setObjectName("shortcut_load");
|
||||
shortcut_load->setWhatsThis("Load Plugin...");
|
||||
|
||||
auto *shortcut_refresh = new Shortcut(QKeySequence(), this, SLOT(userRefreshPlugins()));
|
||||
shortcut_refresh->setObjectName("shortcut_refresh");
|
||||
shortcut_refresh->setWhatsThis("Refresh Plugins");
|
||||
|
||||
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
|
||||
applyUserShortcuts();
|
||||
}
|
||||
|
||||
QObjectList PluginEditor::shortcutableObjects() const {
|
||||
QObjectList shortcutable_objects;
|
||||
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(shortcut));
|
||||
|
||||
return shortcutable_objects;
|
||||
}
|
||||
|
||||
void PluginEditor::applyUserShortcuts() {
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
action->setShortcuts(shortcutsConfig.userShortcuts(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
|
||||
}
|
||||
|
||||
void PluginEditor::displayPlugin(const PluginSettings& settings) {
|
||||
auto item = new QListWidgetItem(ui->list);
|
||||
auto widget = new PluginListItem(settings, ui->list);
|
||||
item->setSizeHint(widget->sizeHint());
|
||||
|
||||
connect(widget, &PluginListItem::clickedChoosePlugin, [this, item] { this->replacePlugin(item); });
|
||||
connect(widget, &PluginListItem::clickedEditPlugin, [this, item] { this->openPlugin(item); });
|
||||
connect(widget, &PluginListItem::clickedDeletePlugin, [this, item] { this->removePlugin(item); });
|
||||
connect(widget, &PluginListItem::toggledEnable, this, &PluginEditor::markEdited);
|
||||
connect(widget, &PluginListItem::pathEdited, this, &PluginEditor::markEdited);
|
||||
|
||||
// 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 plugins for that to be a problem.
|
||||
ui->list->addItem(item);
|
||||
ui->list->setItemWidget(item, widget);
|
||||
}
|
||||
|
||||
void PluginEditor::markEdited() {
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
QString PluginEditor::getPluginFilepath(QListWidgetItem * item, bool absolutePath) const {
|
||||
auto widget = dynamic_cast<PluginListItem *>(ui->list->itemWidget(item));
|
||||
if (!widget) return QString();
|
||||
|
||||
QString path = widget->path();
|
||||
if (absolutePath) {
|
||||
QFileInfo fileInfo(path);
|
||||
if (fileInfo.isRelative())
|
||||
path.prepend(this->baseDir);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void PluginEditor::setPluginFilepath(QListWidgetItem * item, QString filepath) const {
|
||||
auto widget = dynamic_cast<PluginListItem *>(ui->list->itemWidget(item));
|
||||
if (widget) {
|
||||
widget->setPath(Util::stripPrefix(filepath, this->baseDir));
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginEditor::getPluginEnabled(QListWidgetItem * item) const {
|
||||
auto widget = dynamic_cast<PluginListItem *>(ui->list->itemWidget(item));
|
||||
return widget && widget->pluginEnabled();
|
||||
}
|
||||
|
||||
QString PluginEditor::choosePlugin(QString dir) {
|
||||
return FileDialog::getOpenFileName(this, "Choose Plugin", dir, "JavaScript Files (*.js)");
|
||||
}
|
||||
|
||||
void PluginEditor::createNewPlugin() {
|
||||
const QString filepath = FileDialog::getSaveFileName(this, "Create New Plugin", FileDialog::getDirectory() + "/new_plugin.js", "JavaScript Files (*.js)");
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
|
||||
QFile pluginFile(filepath);
|
||||
if (!pluginFile.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Error: Could not open %1 for writing").arg(filepath));
|
||||
QMessageBox messageBox(this);
|
||||
messageBox.setText("Failed to create new plugin file!");
|
||||
messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(filepath));
|
||||
messageBox.setIcon(QMessageBox::Warning);
|
||||
messageBox.exec();
|
||||
return;
|
||||
}
|
||||
ParseUtil parser;
|
||||
pluginFile.write(parser.readTextFile(":/text/plugin_template.txt").toUtf8());
|
||||
pluginFile.close();
|
||||
|
||||
this->displayNewPlugin(filepath);
|
||||
}
|
||||
|
||||
void PluginEditor::loadPlugin() {
|
||||
QString filepath = this->choosePlugin(FileDialog::getDirectory());
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->displayNewPlugin(filepath);
|
||||
}
|
||||
|
||||
void PluginEditor::displayNewPlugin(QString filepath) {
|
||||
filepath = Util::stripPrefix(filepath, this->baseDir);
|
||||
|
||||
// Verify new plugin path is not already in list
|
||||
for (int i = 0; i < ui->list->count(); i++) {
|
||||
if (filepath == this->getPluginFilepath(ui->list->item(i), false)) {
|
||||
QMessageBox::information(this, QApplication::applicationName(), QString("The plugin '%1' is already loaded").arg(filepath));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PluginSettings settings;
|
||||
settings.path = filepath;
|
||||
this->displayPlugin(settings);
|
||||
this->markEdited();
|
||||
}
|
||||
|
||||
void PluginEditor::removePlugin(QListWidgetItem * item) {
|
||||
ui->list->takeItem(ui->list->row(item));
|
||||
this->markEdited();
|
||||
}
|
||||
|
||||
void PluginEditor::removeSelectedPlugins() {
|
||||
QList<QListWidgetItem *> items = ui->list->selectedItems();
|
||||
if (items.length() == 0)
|
||||
return;
|
||||
for (auto item : items)
|
||||
this->removePlugin(item);
|
||||
}
|
||||
|
||||
void PluginEditor::replacePlugin(QListWidgetItem * item) {
|
||||
const QString filepath = this->choosePlugin(this->getPluginFilepath(item));
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->setPluginFilepath(item, filepath);
|
||||
this->markEdited();
|
||||
}
|
||||
|
||||
void PluginEditor::openPlugin(QListWidgetItem * item) {
|
||||
const QString path = this->getPluginFilepath(item);
|
||||
QFileInfo fileInfo(path);
|
||||
if (!fileInfo.exists() || !fileInfo.isFile()){
|
||||
QMessageBox::warning(this, QApplication::applicationName(), QString("Failed to open plugin '%1'").arg(path));
|
||||
return;
|
||||
}
|
||||
Editor::openInTextEditor(path);
|
||||
}
|
||||
|
||||
void PluginEditor::openSelectedPlugins() {
|
||||
for (auto item : ui->list->selectedItems())
|
||||
this->openPlugin(item);
|
||||
}
|
||||
|
||||
void PluginEditor::openManual() {
|
||||
static const QUrl url("https://huderlem.github.io/porymap/manual/scripting-capabilities.html");
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
// When the user refreshes the plugins we show a little tooltip as feedback.
|
||||
// We don't want this tooltip to display when we refresh programmatically, like when changes are saved.
|
||||
void PluginEditor::userRefreshPlugins() {
|
||||
if (refreshPlugins())
|
||||
QToolTip::showText(ui->button_RefreshPlugins->mapToGlobal(QPoint(0, 0)), "Refreshed!");
|
||||
}
|
||||
|
||||
bool PluginEditor::refreshPlugins() {
|
||||
if (this->hasUnsavedChanges) {
|
||||
if (this->prompt("Plugins have been modified, save changes and reload plugins?", QMessageBox::Yes) == QMessageBox::No)
|
||||
return false;
|
||||
this->save();
|
||||
}
|
||||
emit reloadScriptEngine();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PluginEditor::save() {
|
||||
if (!this->hasUnsavedChanges)
|
||||
return;
|
||||
|
||||
QList<PluginSettings> userPlugins;
|
||||
QList<PluginSettings> projectPlugins;
|
||||
for (int i = 0; i < ui->list->count(); i++) {
|
||||
auto item = ui->list->item(i);
|
||||
auto widget = dynamic_cast<PluginListItem *>(ui->list->itemWidget(item));
|
||||
if (!widget) continue;
|
||||
const PluginSettings settings = widget->getSettings();
|
||||
if (settings.userOnly) userPlugins.append(settings);
|
||||
else projectPlugins.append(settings);
|
||||
}
|
||||
|
||||
userConfig.plugins = userPlugins;
|
||||
userConfig.save();
|
||||
|
||||
projectConfig.plugins = projectPlugins;
|
||||
projectConfig.save();
|
||||
|
||||
this->hasUnsavedChanges = false;
|
||||
this->refreshPlugins();
|
||||
}
|
||||
|
||||
int PluginEditor::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 PluginEditor::dialogButtonClicked(QAbstractButton *button) {
|
||||
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
|
||||
this->save();
|
||||
close(); // All buttons (OK and Cancel) close the window
|
||||
}
|
||||
|
||||
void PluginEditor::closeEvent(QCloseEvent* event) {
|
||||
if (this->hasUnsavedChanges) {
|
||||
int result = this->prompt("Plugins have been modified, save changes?", QMessageBox::Cancel);
|
||||
if (result == QMessageBox::Cancel) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
if (result == QMessageBox::Yes)
|
||||
this->save();
|
||||
}
|
||||
}
|
||||
55
src/ui/pluginlistitem.cpp
Normal file
55
src/ui/pluginlistitem.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "pluginlistitem.h"
|
||||
#include "ui_pluginlistitem.h"
|
||||
|
||||
PluginListItem::PluginListItem(QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::PluginListItem)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->b_Choose, &QAbstractButton::clicked, this, &PluginListItem::clickedChoosePlugin);
|
||||
connect(ui->b_Edit, &QAbstractButton::clicked, this, &PluginListItem::clickedEditPlugin);
|
||||
connect(ui->b_Delete, &QAbstractButton::clicked, this, &PluginListItem::clickedDeletePlugin);
|
||||
connect(ui->checkBox_Enable, &QCheckBox::toggled, this, &PluginListItem::toggledEnable);
|
||||
connect(ui->lineEdit_filepath, &QLineEdit::textEdited, this, &PluginListItem::pathEdited);
|
||||
}
|
||||
|
||||
PluginListItem::PluginListItem(const PluginSettings& settings, QWidget *parent) :
|
||||
PluginListItem(parent)
|
||||
{
|
||||
setSettings(settings);
|
||||
}
|
||||
|
||||
PluginListItem::~PluginListItem() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PluginListItem::setPath(const QString& text) {
|
||||
ui->lineEdit_filepath->setText(text);
|
||||
}
|
||||
|
||||
QString PluginListItem::path() const {
|
||||
return ui->lineEdit_filepath->text();
|
||||
}
|
||||
|
||||
void PluginListItem::setPluginEnabled(bool enabled) {
|
||||
ui->checkBox_Enable->setChecked(enabled);
|
||||
}
|
||||
|
||||
bool PluginListItem::pluginEnabled() const {
|
||||
return ui->checkBox_Enable->isChecked();
|
||||
}
|
||||
|
||||
// TODO: The two functions below should read/write from/to the UI whether the plugin belongs to the project or user.
|
||||
void PluginListItem::setSettings(const PluginSettings& settings) {
|
||||
setPath(settings.path);
|
||||
setPluginEnabled(settings.enabled);
|
||||
}
|
||||
|
||||
PluginSettings PluginListItem::getSettings() const {
|
||||
return {
|
||||
.path = path(),
|
||||
.enabled = pluginEnabled(),
|
||||
.userOnly = true,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user