Skip to content

Commit

Permalink
Merge pull request #621 from GriffinRichards/file-dialogs
Browse files Browse the repository at this point in the history
Correctly restore window focus for file dialogs
  • Loading branch information
GriffinRichards authored Oct 16, 2024
2 parents caeaeac + f192b74 commit e431c16
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 91 deletions.
65 changes: 65 additions & 0 deletions include/core/filedialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#ifndef FILEDIALOG_H
#define FILEDIALOG_H

#include <QFileDialog>

/*
Static QFileDialog functions will (unless otherwise specified) use native file dialogs.
In general this is good (we want our file dialogs to be visually seamless) but unfortunately
the native file dialogs ignore the parent widget, so in some cases they'll return focus to
the main window rather than the window that opened the file dialog.
To make working around this a little easier we use this class, which will use the native
file dialog and manually return focus to the parent widget.
It will also save the directory of the previous file selected in a file dialog, and if
no 'dir' argument is specified it will open new dialogs at that directory.
*/

class FileDialog : public QFileDialog
{
public:
FileDialog(QWidget *parent, Qt::WindowFlags flags) : QFileDialog(parent, flags) {};
FileDialog(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &directory = QString(),
const QString &filter = QString()) : QFileDialog(parent, caption, directory, filter) {};

static void setDirectory(const QString &dir) { FileDialog::prevDirectory = dir; }
static QString getDirectory() { return FileDialog::prevDirectory; }

static QString getOpenFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = Options());

static QStringList getOpenFileNames(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = Options());

static QString getExistingDirectory(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
QFileDialog::Options options = ShowDirsOnly);

static QString getSaveFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = Options());

private:
static QString prevDirectory;
static QString getDirectoryFromInput(const QString &dir);
static void setDirectoryFromFile(const QString &fileName);
static void restoreFocus(QWidget *parent);
};

#endif // FILEDIALOG_H
2 changes: 0 additions & 2 deletions include/project.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ class Project : public QObject
QFileSystemWatcher fileWatcher;
QMap<QString, qint64> modifiedFileTimestamps;
bool usingAsmTilesets;
QString importExportPath;
QSet<QString> disabledSettingsNames;
int pokemonMinLevel;
int pokemonMaxLevel;
Expand Down Expand Up @@ -216,7 +215,6 @@ class Project : public QObject
QString buildMetatileLabelsText(const QMap<QString, uint16_t> defines);
QString findMetatileLabelsTileset(QString label);

void setImportExportPath(QString filename);
static QString getExistingFilepath(QString filepath);
void applyParsedLimits();

Expand Down
1 change: 0 additions & 1 deletion include/ui/customscriptseditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public slots:
Ui::CustomScriptsEditor *ui;

bool hasUnsavedChanges = false;
QString fileDialogDir;
const QString baseDir;

void displayScript(const QString &filepath, bool enabled);
Expand Down
3 changes: 1 addition & 2 deletions include/ui/regionmappropertiesdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "orderedjson.h"

#include <QDialog>
#include <QFileDialog>

class Project;

Expand Down Expand Up @@ -33,7 +32,7 @@ class RegionMapPropertiesDialog : public QDialog

void hideMessages();

QString browse(QString filter, QFileDialog::FileMode mode);
QString browse(QString filter);

private slots:
void on_browse_tilesetImagePath_clicked();
Expand Down
2 changes: 2 additions & 0 deletions porymap.pro
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ SOURCES += src/core/block.cpp \
src/core/bitpacker.cpp \
src/core/blockdata.cpp \
src/core/events.cpp \
src/core/filedialog.cpp \
src/core/heallocation.cpp \
src/core/imageexport.cpp \
src/core/map.cpp \
Expand Down Expand Up @@ -123,6 +124,7 @@ HEADERS += include/core/block.h \
include/core/bitpacker.h \
include/core/blockdata.h \
include/core/events.h \
include/core/filedialog.h \
include/core/heallocation.h \
include/core/history.h \
include/core/imageexport.h \
Expand Down
51 changes: 51 additions & 0 deletions src/core/filedialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "filedialog.h"

QString FileDialog::prevDirectory;

QString FileDialog::getDirectoryFromInput(const QString &dir) {
if (dir.isEmpty())
return FileDialog::prevDirectory;
return dir;
}

void FileDialog::setDirectoryFromFile(const QString &fileName) {
if (!fileName.isEmpty())
FileDialog::prevDirectory = QFileInfo(fileName).absolutePath();
}

void FileDialog::restoreFocus(QWidget *parent) {
if (parent) {
parent->raise();
parent->activateWindow();
}
}

QString FileDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
const QString fileName = QFileDialog::getOpenFileName(parent, caption, getDirectoryFromInput(dir), filter, selectedFilter, options);
setDirectoryFromFile(fileName);
restoreFocus(parent);
return fileName;
}

QStringList FileDialog::getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
const QStringList fileNames = QFileDialog::getOpenFileNames(parent, caption, getDirectoryFromInput(dir), filter, selectedFilter, options);
if (!fileNames.isEmpty())
setDirectoryFromFile(fileNames.last());
restoreFocus(parent);
return fileNames;
}

QString FileDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
const QString fileName = QFileDialog::getSaveFileName(parent, caption, getDirectoryFromInput(dir), filter, selectedFilter, options);
setDirectoryFromFile(fileName);
restoreFocus(parent);
return fileName;
}

QString FileDialog::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) {
const QString existingDir = QFileDialog::getExistingDirectory(parent, caption, getDirectoryFromInput(dir), options);
if (!existingDir.isEmpty())
setDirectory(existingDir);
restoreFocus(parent);
return existingDir;
}
12 changes: 4 additions & 8 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#include "montabwidget.h"
#include "imageexport.h"
#include "newmapconnectiondialog.h"
#include "filedialog.h"

#include <QFileDialog>
#include <QClipboard>
#include <QDirIterator>
#include <QStandardItemModel>
Expand Down Expand Up @@ -730,7 +730,7 @@ void MainWindow::openSubWindow(QWidget * window) {
}

QString MainWindow::getExistingDirectory(QString dir) {
return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly);
return FileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly);
}

void MainWindow::on_action_Open_Project_triggered()
Expand Down Expand Up @@ -2596,15 +2596,11 @@ void MainWindow::on_actionImport_Map_from_Advance_Map_1_92_triggered(){

void MainWindow::importMapFromAdvanceMap1_92()
{
QString filepath = QFileDialog::getOpenFileName(
this,
QString("Import Map from Advance Map 1.92"),
this->editor->project->importExportPath,
"Advance Map 1.92 Map Files (*.map)");
QString filepath = FileDialog::getOpenFileName(this, "Import Map from Advance Map 1.92", "", "Advance Map 1.92 Map Files (*.map)");
if (filepath.isEmpty()) {
return;
}
this->editor->project->setImportExportPath(filepath);

MapParser parser;
bool error = false;
MapLayout *mapLayout = parser.parse(filepath, &error, editor->project);
Expand Down
8 changes: 2 additions & 6 deletions src/project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "tile.h"
#include "tileset.h"
#include "map.h"
#include "filedialog.h"

#include "orderedjson.h"

Expand Down Expand Up @@ -89,7 +90,7 @@ void Project::initSignals() {

void Project::set_root(QString dir) {
this->root = dir;
this->importExportPath = dir;
FileDialog::setDirectory(dir);
this->parser.set_root(dir);
}

Expand Down Expand Up @@ -2829,11 +2830,6 @@ QString Project::getDynamicMapDefineName() {
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
}

void Project::setImportExportPath(QString filename)
{
this->importExportPath = QFileInfo(filename).absolutePath();
}

// If the provided filepath is an absolute path to an existing file, return filepath.
// If not, and the provided filepath is a relative path from the project dir to an existing file, return the relative path.
// Otherwise return empty string.
Expand Down
17 changes: 4 additions & 13 deletions src/ui/customscriptseditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#include "config.h"
#include "editor.h"
#include "shortcut.h"
#include "filedialog.h"

#include <QDir>
#include <QFileDialog>

CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
QMainWindow(parent),
Expand All @@ -23,8 +23,6 @@ CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
for (int i = 0; i < paths.length(); i++)
this->displayScript(paths.at(i), enabled.at(i));

this->fileDialogDir = userConfig.projectDir;

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);
Expand Down Expand Up @@ -147,19 +145,13 @@ bool CustomScriptsEditor::getScriptEnabled(QListWidgetItem * item) const {
}

QString CustomScriptsEditor::chooseScript(QString dir) {
return QFileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)");
return FileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)");
}

void CustomScriptsEditor::createNewScript() {
QString filepath = QFileDialog::getSaveFileName(this, "Create New Script File", this->fileDialogDir + "/new_script.js", "JavaScript Files (*.js)");

// QFileDialog::getSaveFileName returns focus to the main editor window when closed. Workaround for this below
this->raise();
this->activateWindow();

const QString filepath = FileDialog::getSaveFileName(this, "Create New Script File", FileDialog::getDirectory() + "/new_script.js", "JavaScript Files (*.js)");
if (filepath.isEmpty())
return;
this->fileDialogDir = filepath;

QFile scriptFile(filepath);
if (!scriptFile.open(QIODevice::WriteOnly)) {
Expand All @@ -179,10 +171,9 @@ void CustomScriptsEditor::createNewScript() {
}

void CustomScriptsEditor::loadScript() {
QString filepath = this->chooseScript(this->fileDialogDir);
QString filepath = this->chooseScript(FileDialog::getDirectory());
if (filepath.isEmpty())
return;
this->fileDialogDir = filepath;
this->displayNewScript(filepath);
}

Expand Down
7 changes: 3 additions & 4 deletions src/ui/mapimageexporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#include "ui_mapimageexporter.h"
#include "qgifimage.h"
#include "editcommands.h"
#include "filedialog.h"

#include <QFileDialog>
#include <QImage>
#include <QPainter>
#include <QPoint>
Expand Down Expand Up @@ -98,13 +98,12 @@ void MapImageExporter::saveImage() {
}

QString defaultFilepath = QString("%1/%2.%3")
.arg(editor->project->importExportPath)
.arg(FileDialog::getDirectory())
.arg(defaultFilename)
.arg(this->mode == ImageExporterMode::Timelapse ? "gif" : "png");
QString filter = this->mode == ImageExporterMode::Timelapse ? "Image Files (*.gif)" : "Image Files (*.png *.jpg *.bmp)";
QString filepath = QFileDialog::getSaveFileName(this, title, defaultFilepath, filter);
QString filepath = FileDialog::getSaveFileName(this, title, defaultFilepath, filter);
if (!filepath.isEmpty()) {
editor->project->setImportExportPath(filepath);
switch (this->mode) {
case ImageExporterMode::Normal:
case ImageExporterMode::Stitch:
Expand Down
1 change: 0 additions & 1 deletion src/ui/newtilesetdialog.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "newtilesetdialog.h"
#include "ui_newtilesetdialog.h"
#include <QFileDialog>
#include "project.h"

NewTilesetDialog::NewTilesetDialog(Project* project, QWidget *parent) :
Expand Down
9 changes: 2 additions & 7 deletions src/ui/paletteeditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#include "paletteutil.h"
#include "config.h"
#include "log.h"
#include "filedialog.h"

#include <QFileDialog>
#include <QMessageBox>


Expand Down Expand Up @@ -158,15 +158,10 @@ void PaletteEditor::on_actionRedo_triggered()

void PaletteEditor::on_actionImport_Palette_triggered()
{
QString filepath = QFileDialog::getOpenFileName(
this,
QString("Import Tileset Palette"),
this->project->importExportPath,
"Palette Files (*.pal *.act *tpl *gpl)");
QString filepath = FileDialog::getOpenFileName(this, "Import Tileset Palette", "", "Palette Files (*.pal *.act *tpl *gpl)");
if (filepath.isEmpty()) {
return;
}
this->project->setImportExportPath(filepath);
bool error = false;
QList<QRgb> palette = PaletteUtil::parse(filepath, &error);
if (error) {
Expand Down
8 changes: 4 additions & 4 deletions src/ui/projectsettingseditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "config.h"
#include "noscrollcombobox.h"
#include "prefab.h"
#include "filedialog.h"

#include <QAbstractButton>
#include <QFormLayout>
Expand Down Expand Up @@ -383,10 +384,10 @@ QString ProjectSettingsEditor::chooseProjectFile(const QString &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();
path = FileDialog::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);
path = FileDialog::getOpenFileName(this, "Choose Project File", startDir);
}

if (!path.startsWith(this->baseDir)){
Expand Down Expand Up @@ -573,10 +574,9 @@ void ProjectSettingsEditor::chooseImageFile(QLineEdit * filepathEdit) {
}

void ProjectSettingsEditor::chooseFile(QLineEdit * filepathEdit, const QString &description, const QString &extensions) {
QString filepath = QFileDialog::getOpenFileName(this, description, this->project->importExportPath, extensions);
QString filepath = FileDialog::getOpenFileName(this, description, "", extensions);
if (filepath.isEmpty())
return;
this->project->setImportExportPath(filepath);

if (filepathEdit)
filepathEdit->setText(this->stripProjectDir(filepath));
Expand Down
1 change: 0 additions & 1 deletion src/ui/regionmapeditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <QDir>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QFormLayout>
#include <QLineEdit>
#include <QSpinBox>
Expand Down
Loading

0 comments on commit e431c16

Please sign in to comment.