Skip to content

Commit 243dc92

Browse files
authored
QtFRED better file dialog handling (#7364)
* better file dialog handling * fix copy/paste error * not static for a change
1 parent ec3f5cc commit 243dc92

16 files changed

Lines changed: 248 additions & 94 deletions

qtfred/source_groups.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ add_file_folder("Source/UI/General"
271271
)
272272

273273
add_file_folder("Source/UI/Util"
274+
src/ui/util/default_dir.cpp
275+
src/ui/util/default_dir.h
274276
src/ui/util/ImageRenderer.cpp
275277
src/ui/util/ImageRenderer.h
276278
src/ui/util/menu.cpp

qtfred/src/ui/FredView.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "FredView.h"
22
#include "ui_FredView.h"
33

4+
#include <ui/util/default_dir.h>
5+
46
#include <QDir>
57
#include <QFileDialog>
68
#include <QFileInfo>
@@ -254,13 +256,15 @@ void FredView::loadMissionFile(const QString& pathName, int flags) {
254256
}
255257

256258
void FredView::openLoadMissionDialog() {
257-
qDebug() << "Loading from directory:" << QDir::currentPath();
258-
QString pathName = QFileDialog::getOpenFileName(this, tr("Load mission"), QString(), tr("FS2 missions (*.fs2)"));
259+
const QString lastDir = fso::fred::util::getLastDir("missions/loadMission", CF_TYPE_MISSIONS);
260+
261+
QString pathName = QFileDialog::getOpenFileName(this, tr("Load mission"), lastDir, tr("FS2 missions (*.fs2)"));
259262

260263
if (pathName.isEmpty()) {
261264
return;
262265
}
263266

267+
fso::fred::util::saveLastDir("missions/loadMission", pathName);
264268
loadMissionFile(pathName.replace('/',DIR_SEPARATOR_CHAR));
265269
}
266270

@@ -302,10 +306,15 @@ bool FredView::saveMissionAs() {
302306
save.set_fred_alt_names(Fred_alt_names);
303307
save.set_fred_callsigns(Fred_callsigns);
304308

305-
saveName = QFileDialog::getSaveFileName(this, tr("Save mission"), QString(), tr("FS2 missions (*.fs2)"));
309+
{
310+
const QString lastDir = fso::fred::util::getLastDir("missions/saveMission", CF_TYPE_MISSIONS);
311+
saveName = QFileDialog::getSaveFileName(this, tr("Save mission"), lastDir, tr("FS2 missions (*.fs2)"));
306312

307-
if (saveName.isEmpty()) {
308-
return false;
313+
if (saveName.isEmpty()) {
314+
return false;
315+
}
316+
317+
fso::fred::util::saveLastDir("missions/saveMission", saveName);
309318
}
310319

311320
save.save_mission_file(saveName.replace('/',DIR_SEPARATOR_CHAR).toUtf8().constData());
@@ -319,18 +328,22 @@ void FredView::saveAsTemplate() {
319328
if (metaDialog.exec() != QDialog::Accepted)
320329
return;
321330

322-
// Default to data/missions/templates/ and create it if needed
323-
QString templatesDir = QDir::currentPath() + "/data/missions/templates";
324-
QDir().mkpath(templatesDir);
331+
// Ensure templates subdir exists; use missions dir as fallback default
332+
const QString defaultTemplatesDir = fso::fred::util::fredDefaultDir(CF_TYPE_MISSIONS) + "/templates";
333+
QDir().mkpath(defaultTemplatesDir);
334+
335+
const QString lastTemplatesDir = fso::fred::util::getLastDir("missions/saveTemplate", defaultTemplatesDir);
325336

326337
QString templateName = QFileDialog::getSaveFileName(this,
327338
tr("Save As Template"),
328-
templatesDir,
339+
lastTemplatesDir,
329340
tr("FS2 mission templates (*.fst)"));
330341

331342
if (templateName.isEmpty())
332343
return;
333344

345+
fso::fred::util::saveLastDir("missions/saveTemplate", templateName);
346+
334347
if (!templateName.endsWith(".fst", Qt::CaseInsensitive))
335348
templateName += ".fst";
336349

@@ -344,7 +357,7 @@ void FredView::saveAsTemplate() {
344357
}
345358

346359
void FredView::loadTemplate() {
347-
QString templatesDir = QDir::currentPath() + "/data/missions/templates";
360+
QString templatesDir = fso::fred::util::fredDefaultDir(CF_TYPE_MISSIONS) + "/templates";
348361
QDir().mkpath(templatesDir);
349362

350363
dialogs::TemplateBrowserDialog browser(this, templatesDir);
@@ -429,18 +442,23 @@ void FredView::on_actionFS1_Mission_triggered(bool) {
429442

430443
QStringList srcPaths = QFileDialog::getOpenFileNames(this,
431444
tr("Select FS1 mission(s) to import"),
432-
QString(),
445+
fso::fred::util::getLastDir("missions/importFS1Source", QDir::homePath()),
433446
tr("FreeSpace Missions (*.fsm)"));
434447

435448
if (srcPaths.isEmpty())
436449
return;
437450

451+
fso::fred::util::saveLastDir("missions/importFS1Source", srcPaths.first());
452+
438453
QString destDir = QFileDialog::getExistingDirectory(this,
439-
tr("Select destination folder for converted missions"));
454+
tr("Select destination folder for converted missions"),
455+
fso::fred::util::getLastDir("missions/importFS1Dest", CF_TYPE_MISSIONS));
440456

441457
if (destDir.isEmpty())
442458
return;
443459

460+
fso::fred::util::saveLastDir("missions/importFS1Dest", destDir);
461+
444462
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
445463

446464
int successes = 0;

qtfred/src/ui/dialogs/BackgroundEditorDialog.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#include "BackgroundEditorDialog.h"
22
#include <QCloseEvent>
3+
#include "ui/util/default_dir.h"
34
#include "ui/util/SignalBlockers.h"
45
#include "ui/dialogs/General/ImagePickerDialog.h"
56
#include "ui_BackgroundEditor.h"
67

78
#include <globalincs/globals.h>
89
#include <QMessageBox>
9-
#include <QSettings>
1010
#include <QFileDialog>
1111
#include <QFileInfo>
1212
#include <QInputDialog>
@@ -451,9 +451,12 @@ void BackgroundEditorDialog::on_removeButton_clicked()
451451

452452
void BackgroundEditorDialog::on_importButton_clicked()
453453
{
454-
const QString file = QFileDialog::getOpenFileName(this, "Import Backgrounds from File", QString(), "Freespace 2 Mission Files (*.fs2);;All Files (*)");
454+
const QString importLastDir = util::getLastDir("background/importBackgrounds", CF_TYPE_MISSIONS);
455+
456+
const QString file = QFileDialog::getOpenFileName(this, "Import Backgrounds from File", importLastDir, "Freespace 2 Mission Files (*.fs2);;All Files (*)");
455457
if (file.isEmpty())
456458
return;
459+
util::saveLastDir("background/importBackgrounds", file);
457460
int count = _model->getImportableBackgroundCount(file.toUtf8().constData());
458461

459462
if (count <= 0) {
@@ -852,19 +855,15 @@ void BackgroundEditorDialog::updateAmbientSwatch()
852855

853856
void BackgroundEditorDialog::on_skyboxModelButton_clicked()
854857
{
855-
QSettings settings("QtFRED", "BackgroundEditor");
856-
const QString lastDir = settings.value("skybox/lastDir", QDir::homePath()).toString();
858+
const QString lastDir = util::getLastDir("background/skyboxModel", CF_TYPE_MODELS);
857859

858860
const QString path =
859861
QFileDialog::getOpenFileName(this, tr("Select Skybox Model"), lastDir, tr("FS2 Models (*.pof);;All Files (*)"));
860862
if (path.isEmpty())
861863
return;
862864

863-
const QFileInfo fi(path);
864-
settings.setValue("skybox/lastDir", fi.absolutePath());
865-
866-
const QString baseName = fi.completeBaseName();
867-
_model->setSkyboxModelName(baseName.toUtf8().constData());
865+
util::saveLastDir("background/skyboxModel", path);
866+
_model->setSkyboxModelName(QFileInfo(path).completeBaseName().toUtf8().constData());
868867

869868
updateSkyboxControls();
870869
}
@@ -940,18 +939,15 @@ void BackgroundEditorDialog::on_subspaceCheckBox_toggled(bool checked)
940939

941940
void BackgroundEditorDialog::on_envMapButton_clicked()
942941
{
943-
QSettings settings("QtFRED", "BackgroundEditor");
944-
const QString lastDir = settings.value("envmap/lastDir", QDir::homePath()).toString();
942+
const QString lastDir = util::getLastDir("background/envMap", CF_TYPE_MAPS);
945943
const QString path = QFileDialog::getOpenFileName(this,
946944
tr("Select Environment Map"),
947945
lastDir,
948946
tr("Environment Maps (*.dds);;All Files (*)"));
949947
if (path.isEmpty())
950948
return;
951-
const QFileInfo fi(path);
952-
settings.setValue("envmap/lastDir", fi.absolutePath());
953-
const QString baseName = fi.completeBaseName();
954-
_model->setEnvironmentMapName(baseName.toUtf8().constData());
949+
util::saveLastDir("background/envMap", path);
950+
_model->setEnvironmentMapName(QFileInfo(path).completeBaseName().toUtf8().constData());
955951
updateMiscControls();
956952
}
957953

qtfred/src/ui/dialogs/BriefingEditorDialog.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
#include <globalincs/globals.h>
1616
#include <globalincs/linklist.h>
1717
#include <mission/missionbriefcommon.h>
18+
#include <ui/util/default_dir.h>
1819
#include <ui/util/SignalBlockers.h>
1920

2021
#include <QCloseEvent>
2122
#include <QCheckBox>
2223
#include <QFileDialog>
2324
#include <QVBoxLayout>
25+
#include <QFileInfo>
2426

2527
namespace fso::fred::dialogs {
2628

@@ -679,21 +681,18 @@ void BriefingEditorDialog::on_voiceFileLineEdit_textChanged(const QString& strin
679681

680682
void BriefingEditorDialog::on_voiceFileBrowseButton_clicked()
681683
{
682-
int dir_pushed = cfile_push_chdir(CF_TYPE_VOICE_DEBRIEFINGS);
684+
const QString lastDir = util::getLastDir("briefing/voiceFile", CF_TYPE_VOICE_DEBRIEFINGS);
683685

684-
QFileDialog dlg(this, "Select Voice File", "", "Voice Files (*.ogg *.wav)");
686+
QFileDialog dlg(this, "Select Voice File", lastDir, "Voice Files (*.ogg *.wav)");
685687
if (dlg.exec() == QDialog::Accepted) {
686688
QStringList files = dlg.selectedFiles();
687689
if (!files.isEmpty()) {
688-
QFileInfo fileInfo(files.first());
690+
const QFileInfo fileInfo(files.first());
691+
util::saveLastDir("briefing/voiceFile", files.first());
689692
_model->setSpeechFilename(fileInfo.fileName().toUtf8().constData());
690693
updateUi();
691694
}
692695
}
693-
694-
if (dir_pushed) {
695-
cfile_pop_dir();
696-
}
697696
}
698697

699698
void BriefingEditorDialog::on_voiceFilePlayButton_clicked()

qtfred/src/ui/dialogs/CampaignEditorDialog.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
#include <globalincs/globals.h>
66
#include "ui/widgets/sexp_tree.h"
77
#include "ui/widgets/SimpleListSelectDialog.h"
8+
#include "ui/util/default_dir.h"
89
#include "ui/util/SignalBlockers.h"
910
#include "mission/util.h"
1011
#include <ui/dialogs/MissionSpecs/CustomDataDialog.h>
12+
#include <QFileInfo>
1113
#include <QInputDialog>
1214
#include <QFileDialog>
1315
#include <QMessageBox>
@@ -387,12 +389,15 @@ void CampaignEditorDialog::on_actionOpen_triggered()
387389
}
388390

389391
// Open a file dialog to let the user select a campaign file.
390-
QString pathName = QFileDialog::getOpenFileName(this, "Load Campaign", "", "FS2 Campaigns (*.fc2)");
392+
const QString lastDir = util::getLastDir("campaign/loadCampaign", CF_TYPE_MISSIONS);
393+
394+
QString pathName = QFileDialog::getOpenFileName(this, "Load Campaign", lastDir, "FS2 Campaigns (*.fc2)");
391395

392396
if (pathName.isEmpty()) {
393397
return; // User cancelled the file dialog.
394398
}
395399

400+
util::saveLastDir("campaign/loadCampaign", pathName);
396401
QString nativePath = QDir::toNativeSeparators(pathName);
397402

398403
_model->loadCampaignFromFile(nativePath.toUtf8().constData());
@@ -416,12 +421,16 @@ void CampaignEditorDialog::on_actionSave_triggered()
416421
void CampaignEditorDialog::on_actionSave_As_triggered()
417422
{
418423
// Open a file dialog to let the user choose a save location and filename.
419-
QString pathName = QFileDialog::getSaveFileName(this, "Save Campaign As", "", "FS2 Campaigns (*.fc2)");
424+
const QString lastDir = util::getLastDir("campaign/saveCampaign", CF_TYPE_MISSIONS);
425+
426+
QString pathName = QFileDialog::getSaveFileName(this, "Save Campaign As", lastDir, "FS2 Campaigns (*.fc2)");
420427

421428
if (pathName.isEmpty()) {
422429
return; // User cancelled the file dialog.
423430
}
424431

432+
util::saveLastDir("campaign/saveCampaign", pathName);
433+
425434
// The model will handle the actual save operation.
426435
_model->saveCampaign(pathName.toUtf8().constData());
427436
}
@@ -744,21 +753,27 @@ void CampaignEditorDialog::on_loopVoiceLineEdit_textChanged(const QString& arg1)
744753
void CampaignEditorDialog::on_loopAnimBrowseButton_clicked()
745754
{
746755
util::SignalBlockers blocker(this);
747-
748-
QString filter = "FSO Animations (*.ani *.eff *.png);;All Files (*.*)";
749-
QString fileName = QFileDialog::getOpenFileName(this, "Select Loop Animation", "", filter);
756+
757+
const QString lastDir = util::getLastDir("campaign/loopAnim", CF_TYPE_INTERFACE);
758+
759+
const QString filter = "FSO Animations (*.ani *.eff *.png);;All Files (*.*)";
760+
const QString fileName = QFileDialog::getOpenFileName(this, "Select Loop Animation", lastDir, filter);
750761
if (!fileName.isEmpty()) {
762+
util::saveLastDir("campaign/loopAnim", fileName);
751763
ui->loopAnimLineEdit->setText(fileName);
752764
}
753765
}
754766

755767
void CampaignEditorDialog::on_loopVoiceBrowseButton_clicked()
756768
{
757769
util::SignalBlockers blocker(this);
758-
759-
QString filter = "Audio Files (*.wav *.ogg);;All Files (*.*)";
760-
QString fileName = QFileDialog::getOpenFileName(this, "Select Loop Voice", "", filter);
770+
771+
const QString lastDir = util::getLastDir("campaign/loopVoice", CF_TYPE_VOICE_SPECIAL);
772+
773+
const QString filter = "Audio Files (*.wav *.ogg);;All Files (*.*)";
774+
const QString fileName = QFileDialog::getOpenFileName(this, "Select Loop Voice", lastDir, filter);
761775
if (!fileName.isEmpty()) {
776+
util::saveLastDir("campaign/loopVoice", fileName);
762777
ui->loopVoiceLineEdit->setText(fileName);
763778
}
764779

qtfred/src/ui/dialogs/CommandBriefingDialog.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#include "mission/util.h"
55
#include <globalincs/globals.h>
66
#include <globalincs/linklist.h>
7+
#include <ui/util/default_dir.h>
78
#include <ui/util/SignalBlockers.h>
89
#include <QCloseEvent>
910
#include <QFileDialog>
11+
#include <QFileInfo>
1012

1113
namespace fso::fred::dialogs {
1214

@@ -172,7 +174,7 @@ void CommandBriefingDialog::on_actionBrowseAnimation_clicked()
172174
{
173175
QString filename;
174176

175-
if (CommandBriefingDialog::browseFile(&filename)) {
177+
if (browseFile(&filename, "commandBriefing/animation", util::fredDefaultDir(CF_TYPE_INTERFACE), "FSO Animations (*.ani *.eff *.png);;All Files (*.*)")) {
176178
_model->setAnimationFilename(filename.toUtf8().constData());
177179
}
178180
updateUi();
@@ -182,12 +184,12 @@ void CommandBriefingDialog::on_actionBrowseSpeechFile_clicked()
182184
{
183185
QString filename;
184186

185-
if (CommandBriefingDialog::browseFile(&filename)) {
187+
if (browseFile(&filename, "commandBriefing/speechFile", util::fredDefaultDir(CF_TYPE_VOICE), "Voice Files (*.ogg *.wav);;All Files (*.*)")) {
186188
_model->setSpeechFilename(filename.toUtf8().constData());
187189
}
188190
updateUi();
189191
}
190-
192+
191193
void CommandBriefingDialog::on_actionTestSpeechFileButton_clicked()
192194
{
193195
_model->testSpeech();
@@ -197,7 +199,7 @@ void CommandBriefingDialog::on_actionLowResolutionBrowse_clicked()
197199
{
198200
QString filename;
199201

200-
if (CommandBriefingDialog::browseFile(&filename)) {
202+
if (browseFile(&filename, "commandBriefing/lowRes", util::fredDefaultDir(CF_TYPE_INTERFACE), "FSO Animations (*.ani *.eff *.png);;All Files (*.*)")) {
201203
_model->setLowResolutionFilename(filename.toUtf8().constData());
202204
}
203205
updateUi();
@@ -207,7 +209,7 @@ void CommandBriefingDialog::on_actionHighResolutionBrowse_clicked()
207209
{
208210
QString filename;
209211

210-
if (CommandBriefingDialog::browseFile(&filename)) {
212+
if (browseFile(&filename, "commandBriefing/highRes", util::fredDefaultDir(CF_TYPE_INTERFACE), "FSO Animations (*.ani *.eff *.png);;All Files (*.*)")) {
211213
_model->setHighResolutionFilename(filename.toUtf8().constData());
212214
}
213215
updateUi();
@@ -245,9 +247,11 @@ void CommandBriefingDialog::on_actionHighResolutionFilenameEdit_textChanged(cons
245247
}
246248

247249
// string in returns the file name, and the function returns true for success or false for fail.
248-
bool CommandBriefingDialog::browseFile(QString* stringIn)
250+
bool CommandBriefingDialog::browseFile(QString* stringIn, const QString& settingsKey, const QString& defaultDir, const QString& filter)
249251
{
250-
QFileInfo fileInfo(QFileDialog::getOpenFileName());
252+
const QString lastDir = util::getLastDir(settingsKey, defaultDir);
253+
254+
const QFileInfo fileInfo(QFileDialog::getOpenFileName(this, QString(), lastDir, filter));
251255
*stringIn = fileInfo.fileName();
252256

253257
if (stringIn->length() >= CF_MAX_FILENAME_LENGTH) {
@@ -257,7 +261,8 @@ bool CommandBriefingDialog::browseFile(QString* stringIn)
257261
return false;
258262
}
259263

264+
util::saveLastDir(settingsKey, fileInfo.absoluteFilePath());
260265
return true;
261266
}
262267

263-
} // namespace fso::fred::dialogs
268+
} // namespace fso::fred::dialogs

0 commit comments

Comments
 (0)