Add button to import default prefabs
This commit is contained in:
parent
871a6ed9b7
commit
143e5cf79b
8 changed files with 94 additions and 58 deletions
|
@ -29,7 +29,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>544</width>
|
<width>544</width>
|
||||||
<height>1096</height>
|
<height>1107</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
@ -185,23 +185,6 @@
|
||||||
<string>Prefabs</string>
|
<string>Prefabs</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="lineEdit_PrefabsPath"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_PrefabImportPrompted">
|
|
||||||
<property name="text">
|
|
||||||
<string>Prefab import prompted</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_PrefabsPath">
|
|
||||||
<property name="text">
|
|
||||||
<string>Prefabs Path</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QToolButton" name="button_ChoosePrefabs">
|
<widget class="QToolButton" name="button_ChoosePrefabs">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -213,6 +196,23 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QPushButton" name="button_ImportDefaultPrefabs">
|
||||||
|
<property name="text">
|
||||||
|
<string>Import Defaults</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_PrefabsPath"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_PrefabsPath">
|
||||||
|
<property name="text">
|
||||||
|
<string>Prefabs Path</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -228,6 +228,7 @@ public:
|
||||||
void setBaseGameVersion(BaseGameVersion baseGameVersion);
|
void setBaseGameVersion(BaseGameVersion baseGameVersion);
|
||||||
BaseGameVersion getBaseGameVersion();
|
BaseGameVersion getBaseGameVersion();
|
||||||
QString getBaseGameVersionString();
|
QString getBaseGameVersionString();
|
||||||
|
QString getBaseGameVersionString(BaseGameVersion version);
|
||||||
BaseGameVersion stringToBaseGameVersion(QString string, bool * ok = nullptr);
|
BaseGameVersion stringToBaseGameVersion(QString string, bool * ok = nullptr);
|
||||||
void setUsePoryScript(bool usePoryScript);
|
void setUsePoryScript(bool usePoryScript);
|
||||||
bool getUsePoryScript();
|
bool getUsePoryScript();
|
||||||
|
@ -269,7 +270,7 @@ public:
|
||||||
void setFilePath(ProjectFilePath pathId, QString path);
|
void setFilePath(ProjectFilePath pathId, QString path);
|
||||||
QString getFilePath(ProjectFilePath pathId);
|
QString getFilePath(ProjectFilePath pathId);
|
||||||
void setPrefabFilepath(QString filepath);
|
void setPrefabFilepath(QString filepath);
|
||||||
QString getPrefabFilepath(bool setIfEmpty);
|
QString getPrefabFilepath();
|
||||||
void setPrefabImportPrompted(bool prompted);
|
void setPrefabImportPrompted(bool prompted);
|
||||||
bool getPrefabImportPrompted();
|
bool getPrefabImportPrompted();
|
||||||
void setTilesetsHaveCallback(bool has);
|
void setTilesetsHaveCallback(bool has);
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map);
|
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map);
|
||||||
void addPrefab(MetatileSelection selection, Map *map, QString name);
|
void addPrefab(MetatileSelection selection, Map *map, QString name);
|
||||||
void updatePrefabUi(Map *map);
|
void updatePrefabUi(Map *map);
|
||||||
void tryImportDefaultPrefabs(Map *map);
|
bool tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath = "");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MetatileSelector *selector;
|
MetatileSelector *selector;
|
||||||
|
|
|
@ -44,6 +44,7 @@ private:
|
||||||
private slots:
|
private slots:
|
||||||
void dialogButtonClicked(QAbstractButton *button);
|
void dialogButtonClicked(QAbstractButton *button);
|
||||||
void choosePrefabsFileClicked(bool);
|
void choosePrefabsFileClicked(bool);
|
||||||
|
void importDefaultPrefabsClicked(bool);
|
||||||
void markEdited();
|
void markEdited();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -801,8 +801,15 @@ BaseGameVersion ProjectConfig::getBaseGameVersion() {
|
||||||
return this->baseGameVersion;
|
return this->baseGameVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ProjectConfig::getBaseGameVersionString(BaseGameVersion version) {
|
||||||
|
if (!baseGameVersionMap.contains(version)) {
|
||||||
|
version = BaseGameVersion::pokeemerald;
|
||||||
|
}
|
||||||
|
return baseGameVersionMap.value(version);
|
||||||
|
}
|
||||||
|
|
||||||
QString ProjectConfig::getBaseGameVersionString() {
|
QString ProjectConfig::getBaseGameVersionString() {
|
||||||
return baseGameVersionMap.value(this->baseGameVersion);
|
return this->getBaseGameVersionString(this->baseGameVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectConfig::setUsePoryScript(bool usePoryScript) {
|
void ProjectConfig::setUsePoryScript(bool usePoryScript) {
|
||||||
|
@ -970,10 +977,7 @@ void ProjectConfig::setPrefabFilepath(QString filepath) {
|
||||||
this->save();
|
this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ProjectConfig::getPrefabFilepath(bool setIfEmpty) {
|
QString ProjectConfig::getPrefabFilepath() {
|
||||||
if (setIfEmpty && this->prefabFilepath.isEmpty()) {
|
|
||||||
this->setPrefabFilepath("prefabs.json");
|
|
||||||
}
|
|
||||||
return this->prefabFilepath;
|
return this->prefabFilepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1678,7 +1678,12 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index)
|
||||||
editor->setEditingCollision();
|
editor->setEditingCollision();
|
||||||
} else if (index == 2) {
|
} else if (index == 2) {
|
||||||
editor->setEditingMap();
|
editor->setEditingMap();
|
||||||
prefab.tryImportDefaultPrefabs(this->editor->map);
|
if (projectConfig.getPrefabFilepath().isEmpty() && !projectConfig.getPrefabImportPrompted()) {
|
||||||
|
// User hasn't set up prefabs and hasn't been prompted before.
|
||||||
|
// Ask if they'd like to import the default prefabs file.
|
||||||
|
if (prefab.tryImportDefaultPrefabs(this, projectConfig.getBaseGameVersion()))
|
||||||
|
prefab.updatePrefabUi(this->editor->map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
editor->setCursorRectVisible(false);
|
editor->setCursorRectVisible(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
using OrderedJson = poryjson::Json;
|
using OrderedJson = poryjson::Json;
|
||||||
using OrderedJsonDoc = poryjson::JsonDoc;
|
using OrderedJsonDoc = poryjson::JsonDoc;
|
||||||
|
|
||||||
|
const QString defaultFilepath = "prefabs.json";
|
||||||
|
|
||||||
void Prefab::loadPrefabs() {
|
void Prefab::loadPrefabs() {
|
||||||
this->items.clear();
|
this->items.clear();
|
||||||
QString filepath = projectConfig.getPrefabFilepath(false);
|
QString filepath = projectConfig.getPrefabFilepath();
|
||||||
if (filepath.isEmpty()) return;
|
if (filepath.isEmpty()) return;
|
||||||
|
|
||||||
ParseUtil parser;
|
ParseUtil parser;
|
||||||
|
@ -85,8 +87,11 @@ void Prefab::loadPrefabs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prefab::savePrefabs() {
|
void Prefab::savePrefabs() {
|
||||||
QString filepath = projectConfig.getPrefabFilepath(true);
|
QString filepath = projectConfig.getPrefabFilepath();
|
||||||
if (filepath.isEmpty()) return;
|
if (filepath.isEmpty()) {
|
||||||
|
filepath = defaultFilepath;
|
||||||
|
projectConfig.setPrefabFilepath(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
QFileInfo info(filepath);
|
QFileInfo info(filepath);
|
||||||
if (info.isRelative()) {
|
if (info.isRelative()) {
|
||||||
|
@ -269,48 +274,58 @@ void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) {
|
||||||
this->updatePrefabUi(map);
|
this->updatePrefabUi(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prefab::tryImportDefaultPrefabs(Map *map) {
|
bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath) {
|
||||||
BaseGameVersion version = projectConfig.getBaseGameVersion();
|
|
||||||
// Ensure we have default prefabs for the project's game version.
|
// Ensure we have default prefabs for the project's game version.
|
||||||
if (version != BaseGameVersion::pokeruby && version != BaseGameVersion::pokeemerald && version != BaseGameVersion::pokefirered)
|
if (version != BaseGameVersion::pokeruby && version != BaseGameVersion::pokeemerald && version != BaseGameVersion::pokefirered)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// Exit early if the user has already setup prefabs.
|
if (filepath.isEmpty())
|
||||||
if (!projectConfig.getPrefabFilepath(false).isEmpty())
|
filepath = defaultFilepath;
|
||||||
return;
|
|
||||||
|
|
||||||
// Exit early if the user has already gone through this import prompt before.
|
// Get the absolute filepath for writing/warnings
|
||||||
if (projectConfig.getPrefabImportPrompted())
|
QString absFilepath;
|
||||||
return;
|
QFileInfo fileInfo(filepath);
|
||||||
|
if (fileInfo.suffix().isEmpty())
|
||||||
|
filepath += ".json";
|
||||||
|
if (fileInfo.isRelative()) {
|
||||||
|
absFilepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
|
||||||
|
} else {
|
||||||
|
absFilepath = filepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The warning message when importing defaults changes if there's a pre-existing file.
|
||||||
|
QString fileWarning;
|
||||||
|
if (!QFileInfo::exists(absFilepath)) {
|
||||||
|
fileWarning = QString("This will create a file called '%1'").arg(absFilepath);
|
||||||
|
} else {
|
||||||
|
fileWarning = QString("This will overwrite any existing prefabs in '%1'").arg(absFilepath);
|
||||||
|
}
|
||||||
|
|
||||||
// Display a dialog box to the user, asking if the default prefabs should be imported
|
// Display a dialog box to the user, asking if the default prefabs should be imported
|
||||||
// into their project.
|
// into their project.
|
||||||
QMessageBox::StandardButton prompt =
|
QMessageBox::StandardButton prompt =
|
||||||
QMessageBox::question(nullptr,
|
QMessageBox::question(parent,
|
||||||
"Import Default Prefabs",
|
"Import Default Prefabs",
|
||||||
QString("Would you like to import the default prefabs for %1? This will create a file called 'prefabs.json' in your project directory.")
|
QString("Would you like to import the default prefabs for %1? %2.")
|
||||||
.arg(projectConfig.getBaseGameVersionString()),
|
.arg(projectConfig.getBaseGameVersionString(version))
|
||||||
|
.arg(fileWarning),
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
if (prompt == QMessageBox::Yes) {
|
bool acceptedImport = (prompt == QMessageBox::Yes);
|
||||||
|
if (acceptedImport) {
|
||||||
// Sets up the default prefabs.json filepath.
|
// Sets up the default prefabs.json filepath.
|
||||||
QString filepath = projectConfig.getPrefabFilepath(true);
|
projectConfig.setPrefabFilepath(filepath);
|
||||||
|
QFile prefabsFile(absFilepath);
|
||||||
QFileInfo info(filepath);
|
|
||||||
if (info.isRelative()) {
|
|
||||||
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
|
|
||||||
}
|
|
||||||
QFile prefabsFile(filepath);
|
|
||||||
if (!prefabsFile.open(QIODevice::WriteOnly)) {
|
if (!prefabsFile.open(QIODevice::WriteOnly)) {
|
||||||
projectConfig.setPrefabFilepath(QString());
|
projectConfig.setPrefabFilepath(QString());
|
||||||
|
|
||||||
logError(QString("Error: Could not open %1 for writing").arg(filepath));
|
logError(QString("Error: Could not open %1 for writing").arg(absFilepath));
|
||||||
QMessageBox messageBox;
|
QMessageBox messageBox(parent);
|
||||||
messageBox.setText("Failed to import default prefabs file!");
|
messageBox.setText("Failed to import default prefabs file!");
|
||||||
messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(filepath));
|
messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(absFilepath));
|
||||||
messageBox.setIcon(QMessageBox::Warning);
|
messageBox.setIcon(QMessageBox::Warning);
|
||||||
messageBox.exec();
|
messageBox.exec();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseUtil parser;
|
ParseUtil parser;
|
||||||
|
@ -330,10 +345,10 @@ void Prefab::tryImportDefaultPrefabs(Map *map) {
|
||||||
prefabsFile.write(content.toUtf8());
|
prefabsFile.write(content.toUtf8());
|
||||||
prefabsFile.close();
|
prefabsFile.close();
|
||||||
this->loadPrefabs();
|
this->loadPrefabs();
|
||||||
this->updatePrefabUi(map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
projectConfig.setPrefabImportPrompted(true);
|
projectConfig.setPrefabImportPrompted(true);
|
||||||
|
return acceptedImport;
|
||||||
}
|
}
|
||||||
|
|
||||||
Prefab prefab;
|
Prefab prefab;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "ui_projectsettingseditor.h"
|
#include "ui_projectsettingseditor.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "noscrollcombobox.h"
|
#include "noscrollcombobox.h"
|
||||||
|
#include "prefab.h"
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
|
@ -31,8 +32,10 @@ ProjectSettingsEditor::~ProjectSettingsEditor()
|
||||||
// TODO: Move tool tips to editable areas
|
// TODO: Move tool tips to editable areas
|
||||||
|
|
||||||
void ProjectSettingsEditor::connectSignals() {
|
void ProjectSettingsEditor::connectSignals() {
|
||||||
|
// Connect buttons
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked);
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked);
|
||||||
connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked);
|
connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked);
|
||||||
|
connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked);
|
||||||
|
|
||||||
// Connect combo boxes
|
// Connect combo boxes
|
||||||
QList<NoScrollComboBox *> combos = ui->centralwidget->findChildren<NoScrollComboBox *>();
|
QList<NoScrollComboBox *> combos = ui->centralwidget->findChildren<NoScrollComboBox *>();
|
||||||
|
@ -106,7 +109,6 @@ void ProjectSettingsEditor::refresh() {
|
||||||
ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript());
|
ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript());
|
||||||
ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.getEncounterJsonActive());
|
ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.getEncounterJsonActive());
|
||||||
ui->checkBox_CreateTextFile->setChecked(projectConfig.getCreateMapTextFileEnabled());
|
ui->checkBox_CreateTextFile->setChecked(projectConfig.getCreateMapTextFileEnabled());
|
||||||
ui->checkBox_PrefabImportPrompted->setChecked(projectConfig.getPrefabImportPrompted());
|
|
||||||
ui->checkBox_EnableTripleLayerMetatiles->setChecked(projectConfig.getTripleLayerMetatilesEnabled());
|
ui->checkBox_EnableTripleLayerMetatiles->setChecked(projectConfig.getTripleLayerMetatilesEnabled());
|
||||||
ui->checkBox_EnableRequiresItemfinder->setChecked(projectConfig.getHiddenItemRequiresItemfinderEnabled());
|
ui->checkBox_EnableRequiresItemfinder->setChecked(projectConfig.getHiddenItemRequiresItemfinderEnabled());
|
||||||
ui->checkBox_EnableQuantity->setChecked(projectConfig.getHiddenItemQuantityEnabled());
|
ui->checkBox_EnableQuantity->setChecked(projectConfig.getHiddenItemQuantityEnabled());
|
||||||
|
@ -130,7 +132,7 @@ void ProjectSettingsEditor::refresh() {
|
||||||
|
|
||||||
// Set line edit texts
|
// Set line edit texts
|
||||||
ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString());
|
ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString());
|
||||||
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath(false));
|
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath());
|
||||||
|
|
||||||
this->refreshing = false; // Allow signals
|
this->refreshing = false; // Allow signals
|
||||||
}
|
}
|
||||||
|
@ -150,7 +152,6 @@ void ProjectSettingsEditor::save() {
|
||||||
projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked());
|
projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked());
|
||||||
userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked());
|
userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked());
|
||||||
projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked());
|
projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked());
|
||||||
projectConfig.setPrefabImportPrompted(ui->checkBox_PrefabImportPrompted->isChecked());
|
|
||||||
projectConfig.setTripleLayerMetatilesEnabled(ui->checkBox_EnableTripleLayerMetatiles->isChecked());
|
projectConfig.setTripleLayerMetatilesEnabled(ui->checkBox_EnableTripleLayerMetatiles->isChecked());
|
||||||
projectConfig.setHiddenItemRequiresItemfinderEnabled(ui->checkBox_EnableRequiresItemfinder->isChecked());
|
projectConfig.setHiddenItemRequiresItemfinderEnabled(ui->checkBox_EnableRequiresItemfinder->isChecked());
|
||||||
projectConfig.setHiddenItemQuantityEnabled(ui->checkBox_EnableQuantity->isChecked());
|
projectConfig.setHiddenItemQuantityEnabled(ui->checkBox_EnableQuantity->isChecked());
|
||||||
|
@ -203,10 +204,19 @@ void ProjectSettingsEditor::choosePrefabsFileClicked(bool) {
|
||||||
return;
|
return;
|
||||||
this->project->setImportExportPath(filepath);
|
this->project->setImportExportPath(filepath);
|
||||||
ui->lineEdit_PrefabsPath->setText(filepath);
|
ui->lineEdit_PrefabsPath->setText(filepath);
|
||||||
ui->checkBox_PrefabImportPrompted->setChecked(true);
|
|
||||||
this->hasUnsavedChanges = true;
|
this->hasUnsavedChanges = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProjectSettingsEditor::importDefaultPrefabsClicked(bool) {
|
||||||
|
// If the prompt is accepted the prefabs file will be created and its filepath will be saved in the config.
|
||||||
|
// No need to set hasUnsavedChanges here.
|
||||||
|
BaseGameVersion version = projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText());
|
||||||
|
if (prefab.tryImportDefaultPrefabs(this, version, ui->lineEdit_PrefabsPath->text())) {
|
||||||
|
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); // Refresh with new filepath
|
||||||
|
this->projectNeedsReload = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ProjectSettingsEditor::prompt(const QString &text, QMessageBox::StandardButton defaultButton) {
|
int ProjectSettingsEditor::prompt(const QString &text, QMessageBox::StandardButton defaultButton) {
|
||||||
QMessageBox messageBox(this);
|
QMessageBox messageBox(this);
|
||||||
messageBox.setText(text);
|
messageBox.setText(text);
|
||||||
|
|
Loading…
Reference in a new issue