Enforce project folder for custom filepaths

This commit is contained in:
GriffinR 2023-09-09 19:36:12 -04:00
parent 7a399daaff
commit a5a864926a
4 changed files with 66 additions and 24 deletions

View file

@ -274,8 +274,8 @@ public:
void setDefaultSecondaryTileset(QString tilesetName);
void setFilePath(QString pathId, QString path);
void setFilePath(ProjectFilePath pathId, QString path);
QString getFilePath(QString defaultPath, bool allowDefault = true);
QString getFilePath(ProjectFilePath pathId, bool allowDefault = true);
QString getFilePath(QString defaultPath, bool customOnly = false);
QString getFilePath(ProjectFilePath pathId, bool customOnly = false);
void setPrefabFilepath(QString filepath);
QString getPrefabFilepath();
void setPrefabImportPrompted(bool prompted);

View file

@ -30,6 +30,7 @@ private:
bool hasUnsavedChanges = false;
bool projectNeedsReload = false;
bool refreshing = false;
const QString baseDir;
void initUi();
void connectSignals();
@ -42,6 +43,7 @@ private:
bool promptRestoreDefaults();
void createProjectPathsTable();
QString chooseProjectFile(const QString &defaultFilepath);
private slots:
void dialogButtonClicked(QAbstractButton *button);

View file

@ -804,18 +804,29 @@ void ProjectConfig::setFilePath(QString defaultPath, QString newPath) {
this->setFilePath(reverseDefaultPaths(defaultPath), newPath);
}
QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool allowDefault) {
if (this->filePaths.contains(pathId)) {
return this->filePaths[pathId];
} else if (allowDefault && defaultPaths.contains(pathId)) {
return defaultPaths[pathId].second;
QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool customOnly) {
const QString customPath = this->filePaths.value(pathId);
// When reading custom filepaths for the settings editor we don't care
// about the default path or whether the custom path exists.
if (customOnly)
return customPath;
if (!customPath.isEmpty()) {
// A custom filepath has been specified. If the file/folder exists, use that.
const QString absCustomPath = this->projectDir + QDir::separator() + customPath;
if (QFileInfo::exists(absCustomPath)) {
return customPath;
} else {
return QString();
logError(QString("Custom project filepath '%1' not found. Using default.").arg(absCustomPath));
}
}
return defaultPaths.contains(pathId) ? defaultPaths[pathId].second : QString();
}
QString ProjectConfig::getFilePath(QString defaultPath, bool allowDefault) {
return this->getFilePath(reverseDefaultPaths(defaultPath), allowDefault);
QString ProjectConfig::getFilePath(QString defaultPath, bool customOnly) {
return this->getFilePath(reverseDefaultPaths(defaultPath), customOnly);
}
void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) {

View file

@ -14,7 +14,8 @@
ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) :
QMainWindow(parent),
ui(new Ui::ProjectSettingsEditor),
project(project)
project(project),
baseDir(userConfig.getProjectDir() + QDir::separator())
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
@ -84,25 +85,54 @@ void ProjectSettingsEditor::createProjectPathsTable() {
name->setAlignment(Qt::AlignBottom);
name->setText(pathPair.first);
// Editable area of the path
auto path = new QLineEdit();
path->setObjectName(pathPair.first); // Used when saving the paths
path->setPlaceholderText(pathPair.second);
path->setClearButtonEnabled(true);
// Filepath line edit
auto lineEdit = new QLineEdit();
lineEdit->setObjectName(pathPair.first); // Used when saving the paths
lineEdit->setPlaceholderText(pathPair.second);
lineEdit->setClearButtonEnabled(true);
// "Choose file" button
auto button = new QToolButton();
button->setIcon(QIcon(":/icons/folder.ico"));
// TODO: file prompt
//connect(button, &QAbstractButton::clicked, this, &ProjectSettingsEditor::);
connect(button, &QAbstractButton::clicked, [this, lineEdit](bool) {
const QString path = this->chooseProjectFile(lineEdit->placeholderText());
if (!path.isEmpty()) {
lineEdit->setText(path);
this->markEdited();
}
});
// Add to list
auto editArea = new QWidget();
auto layout = new QHBoxLayout(editArea);
layout->addWidget(path);
layout->addWidget(lineEdit);
layout->addWidget(button);
ui->layout_ProjectPaths->addRow(name, editArea);
}
}
QString ProjectSettingsEditor::chooseProjectFile(const QString &defaultFilepath) {
const QString startDir = this->baseDir + defaultFilepath;
QString path;
if (defaultFilepath.endsWith("/")){
// Default filepath is a folder, choose a new folder
path = QFileDialog::getExistingDirectory(this, "Choose Project File Folder", startDir) + QDir::separator();
} else{
// Default filepath is not a folder, choose a new file
path = QFileDialog::getOpenFileName(this, "Choose Project File", startDir);
}
if (!path.startsWith(this->baseDir)){
// Most of Porymap's file-parsing code for project files will assume that filepaths
// are relative to the root project folder, so we enforce that here.
QMessageBox::warning(this, "Failed to set custom filepath",
QString("Custom filepaths must be inside the root project folder '%1'").arg(this->baseDir));
return QString();
}
return path.remove(0, this->baseDir.length());
}
void ProjectSettingsEditor::restoreWindowState() {
logInfo("Restoring project settings editor geometry from previous session.");
const QMap<QString, QByteArray> geometry = porymapConfig.getProjectSettingsEditorGeometry();
@ -149,7 +179,7 @@ void ProjectSettingsEditor::refresh() {
ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString());
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath());
for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>())
lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), false));
lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true));
this->refreshing = false; // Allow signals
}
@ -221,9 +251,8 @@ void ProjectSettingsEditor::choosePrefabsFileClicked(bool) {
this->project->setImportExportPath(filepath);
// Display relative path if this file is in the project folder
const QString projectDir = projectConfig.getProjectDir() + QDir::separator();
if (filepath.startsWith(projectDir))
filepath.remove(0, projectDir.length());
if (filepath.startsWith(this->baseDir))
filepath.remove(0, this->baseDir.length());
ui->lineEdit_PrefabsPath->setText(filepath);
this->hasUnsavedChanges = true;
}