diff --git a/forms/customscriptslistitem.ui b/forms/customscriptslistitem.ui index 5784b442..c6040aa1 100644 --- a/forms/customscriptslistitem.ui +++ b/forms/customscriptslistitem.ui @@ -7,7 +7,7 @@ 0 0 129 - 30 + 34 @@ -23,6 +23,20 @@ 4 + + + + Choose a new filepath for this script + + + ... + + + + :/icons/folder.ico:/icons/folder.ico + + + @@ -37,16 +51,9 @@ - - - Choose a new filepath for this script - + - ... - - - - :/icons/folder.ico:/icons/folder.ico + diff --git a/include/config.h b/include/config.h index f715e36c..8ce5e2d2 100644 --- a/include/config.h +++ b/include/config.h @@ -348,8 +348,11 @@ public: bool getEncounterJsonActive(); void setProjectDir(QString projectDir); QString getProjectDir(); - void setCustomScripts(QStringList scripts); - QStringList getCustomScripts(); + void setCustomScripts(QStringList scripts, QList enabled); + QStringList getCustomScriptPaths(); + QList getCustomScriptsEnabled(); + void parseCustomScripts(QString input); + QString outputCustomScripts(); protected: virtual QString getConfigFilepath() override; virtual void parseConfigKeyValue(QString key, QString value) override; @@ -363,7 +366,7 @@ private: QString projectDir; QString recentMap; bool useEncounterJson; - QStringList customScripts; + QMap customScripts; QStringList readKeys; }; diff --git a/include/ui/customscriptseditor.h b/include/ui/customscriptseditor.h index 1d8b88c2..a2482fc3 100644 --- a/include/ui/customscriptseditor.h +++ b/include/ui/customscriptseditor.h @@ -31,16 +31,17 @@ private: QString importDir; const QString baseDir; - void displayScript(const QString &filepath); + void displayScript(const QString &filepath, bool enabled); 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; - QString getListItemFilepath(QListWidgetItem * item) const; - void setListItemFilepath(QListWidgetItem * item, QString filepath) const; - + void markEdited(); int prompt(const QString &text, QMessageBox::StandardButton defaultButton); void save(); void closeEvent(QCloseEvent*); diff --git a/src/config.cpp b/src/config.cpp index d5e7e0fe..6e2193f2 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -646,14 +646,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { } else if (key == "use_encounter_json") { userConfig.useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { - userConfig.customScripts.clear(); - QList paths = value.split(",", Qt::SkipEmptyParts); - paths.removeDuplicates(); - for (QString script : paths) { - if (!script.isEmpty()) { - userConfig.customScripts.append(script); - } - } + userConfig.parseCustomScripts(value); #endif } else if (key.startsWith("path/")) { auto k = reverseDefaultPaths(key.mid(5)); @@ -1076,14 +1069,7 @@ void UserConfig::parseConfigKeyValue(QString key, QString value) { } else if (key == "use_encounter_json") { this->useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { - this->customScripts.clear(); - QList paths = value.split(",", Qt::SkipEmptyParts); - paths.removeDuplicates(); - for (QString script : paths) { - if (!script.isEmpty()) { - this->customScripts.append(script); - } - } + this->parseCustomScripts(value); } else { logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); } @@ -1097,7 +1083,7 @@ QMap UserConfig::getKeyValueMap() { QMap map; map.insert("recent_map", this->recentMap); map.insert("use_encounter_json", QString::number(this->useEncounterJson)); - map.insert("custom_scripts", this->customScripts.join(",")); + map.insert("custom_scripts", this->outputCustomScripts()); return map; } @@ -1133,13 +1119,51 @@ bool UserConfig::getEncounterJsonActive() { return this->useEncounterJson; } -void UserConfig::setCustomScripts(QStringList scripts) { - this->customScripts = scripts; +// Read input from the config to get the script paths and whether each is enabled or disbled. +// 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. +void UserConfig::parseCustomScripts(QString input) { + this->customScripts.clear(); + QList paths = input.split(",", Qt::SkipEmptyParts); + for (QString path : paths) { + // Read and remove suffix + bool enabled = !path.endsWith(":0"); + if (!enabled || path.endsWith(":1")) + path.chop(2); + + if (!path.isEmpty()) { + // If a path is repeated only its last instance will be considered. + this->customScripts.insert(path, enabled); + } + } +} + +// Inverse of UserConfig::parseCustomScripts +QString UserConfig::outputCustomScripts() { + QStringList list; + QMapIterator i(this->customScripts); + while (i.hasNext()) { + i.next(); + list.append(QString("%1:%2").arg(i.key()).arg(i.value() ? "1" : "0")); + } + return list.join(","); +} + +void UserConfig::setCustomScripts(QStringList scripts, QList enabled) { + this->customScripts.clear(); + size_t size = qMin(scripts.length(), enabled.length()); + for (size_t i = 0; i < size; i++) + this->customScripts.insert(scripts.at(i), enabled.at(i)); this->save(); } -QStringList UserConfig::getCustomScripts() { - return this->customScripts; +QStringList UserConfig::getCustomScriptPaths() { + return this->customScripts.keys(); +} + +QList UserConfig::getCustomScriptsEnabled() { + return this->customScripts.values(); } ShortcutsConfig shortcutsConfig; diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index baeb2017..559e46af 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -184,7 +184,7 @@ bool ScriptUtility::getSmartPathsEnabled() { } QList ScriptUtility::getCustomScripts() { - return userConfig.getCustomScripts(); + return userConfig.getCustomScriptPaths(); } QList ScriptUtility::getMetatileLayerOrder() { diff --git a/src/scriptapi/scripting.cpp b/src/scriptapi/scripting.cpp index 9aa6963c..5ff90d37 100644 --- a/src/scriptapi/scripting.cpp +++ b/src/scriptapi/scripting.cpp @@ -36,8 +36,11 @@ Scripting::Scripting(MainWindow *mainWindow) { this->mainWindow = mainWindow; this->engine = new QJSEngine(mainWindow); this->engine->installExtensions(QJSEngine::ConsoleExtension); - for (QString script : userConfig.getCustomScripts()) { - this->filepaths.append(script); + const QStringList paths = userConfig.getCustomScriptPaths(); + const QList enabled = userConfig.getCustomScriptsEnabled(); + for (int i = 0; i < paths.length(); i++) { + if (enabled.at(i)) + this->filepaths.append(paths.at(i)); } this->loadModules(this->filepaths); this->scriptUtility = new ScriptUtility(mainWindow); diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp index 36babd51..c54ec1c7 100644 --- a/src/ui/customscriptseditor.cpp +++ b/src/ui/customscriptseditor.cpp @@ -8,8 +8,6 @@ #include #include -// TODO: System for turning scripts on or off -// // TODO: Better URL colors on dark themes // TODO: Save window state @@ -23,8 +21,10 @@ CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) : // 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); + const QStringList paths = userConfig.getCustomScriptPaths(); + const QList enabled = userConfig.getCustomScriptsEnabled(); + for (int i = 0; i < paths.length(); i++) + this->displayScript(paths.at(i), enabled.at(i)); this->importDir = userConfig.getProjectDir(); @@ -90,36 +90,44 @@ void CustomScriptsEditor::applyUserShortcuts() { shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut)); } -void CustomScriptsEditor::displayScript(const QString &filepath) { +void CustomScriptsEditor::displayScript(const QString &filepath, bool enabled) { auto item = new QListWidgetItem(); - auto buttons = new CustomScriptsListItem(); + auto widget = new CustomScriptsListItem(); - buttons->ui->lineEdit_filepath->setText(filepath); - item->setSizeHint(buttons->sizeHint()); + widget->ui->checkBox_Enable->setChecked(enabled); + widget->ui->lineEdit_filepath->setText(filepath); + item->setSizeHint(widget->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; }); + connect(widget->ui->b_Choose, &QAbstractButton::clicked, [this, item](bool) { this->replaceScript(item); }); + connect(widget->ui->b_Edit, &QAbstractButton::clicked, [this, item](bool) { this->openScript(item); }); + connect(widget->ui->b_Delete, &QAbstractButton::clicked, [this, item](bool) { this->removeScript(item); }); + connect(widget->ui->checkBox_Enable, &QCheckBox::stateChanged, this, &CustomScriptsEditor::markEdited); + connect(widget->ui->lineEdit_filepath, &QLineEdit::textEdited, 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, buttons); + ui->list->setItemWidget(item, widget); } -QString CustomScriptsEditor::getListItemFilepath(QListWidgetItem * item) const { +void CustomScriptsEditor::markEdited() { + this->hasUnsavedChanges = true; +} + +QString CustomScriptsEditor::getScriptFilepath(QListWidgetItem * item, bool absolutePath) 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); + if (absolutePath) { + QFileInfo fileInfo(path); + if (fileInfo.isRelative()) + path.prepend(this->baseDir); + } return path; } -void CustomScriptsEditor::setListItemFilepath(QListWidgetItem * item, QString filepath) const { +void CustomScriptsEditor::setScriptFilepath(QListWidgetItem * item, QString filepath) const { auto widget = dynamic_cast(ui->list->itemWidget(item)); if (!widget) return; @@ -128,6 +136,11 @@ void CustomScriptsEditor::setListItemFilepath(QListWidgetItem * item, QString fi widget->ui->lineEdit_filepath->setText(filepath); } +bool CustomScriptsEditor::getScriptEnabled(QListWidgetItem * item) const { + auto widget = dynamic_cast(ui->list->itemWidget(item)); + return widget && widget->ui->checkBox_Enable->isChecked(); +} + QString CustomScriptsEditor::chooseScript(QString dir) { return QFileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)"); } @@ -139,13 +152,13 @@ void CustomScriptsEditor::addNewScript() { this->importDir = filepath; if (filepath.startsWith(this->baseDir)) filepath.remove(0, this->baseDir.length()); - this->displayScript(filepath); - this->hasUnsavedChanges = true; + this->displayScript(filepath, true); + this->markEdited(); } void CustomScriptsEditor::removeScript(QListWidgetItem * item) { ui->list->takeItem(ui->list->row(item)); - this->hasUnsavedChanges = true; + this->markEdited(); } void CustomScriptsEditor::removeSelectedScripts() { @@ -157,15 +170,15 @@ void CustomScriptsEditor::removeSelectedScripts() { } void CustomScriptsEditor::replaceScript(QListWidgetItem * item) { - const QString filepath = this->chooseScript(this->getListItemFilepath(item)); + const QString filepath = this->chooseScript(this->getScriptFilepath(item)); if (filepath.isEmpty()) return; - this->setListItemFilepath(item, filepath); - this->hasUnsavedChanges = true; + this->setScriptFilepath(item, filepath); + this->markEdited(); } void CustomScriptsEditor::openScript(QListWidgetItem * item) { - const QString path = this->getListItemFilepath(item); + const QString path = this->getScriptFilepath(item); QFileInfo fileInfo(path); if (!fileInfo.exists() || !fileInfo.isFile()){ QMessageBox::warning(this, "", QString("Failed to open script '%1'").arg(path)); @@ -191,7 +204,16 @@ void CustomScriptsEditor::reloadScripts() { void CustomScriptsEditor::save() { if (!this->hasUnsavedChanges) return; - // TODO: Set new paths in config + + QStringList paths; + QList enabledStates; + for (int i = 0; i < ui->list->count(); i++) { + auto item = ui->list->item(i); + paths.append(this->getScriptFilepath(item, false)); + enabledStates.append(this->getScriptEnabled(item)); + } + + userConfig.setCustomScripts(paths, enabledStates); this->hasUnsavedChanges = false; this->reloadScripts(); }