Implemented helper method of QFileDialog::getSaveFileName to prevent user from saving files with invalid names.

Signed-off-by: Chris Galvan <chgalvan@amazon.com>
monroegm-disable-blank-issue-2
Chris Galvan 4 years ago
parent 9e5ef08229
commit d590a91fe7

@ -34,6 +34,7 @@
// AzQtComponents
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
// CryCommon
#include <CryCommon/Maestro/Bus/EditorSequenceComponentBus.h>
@ -2324,7 +2325,7 @@ void CTrackViewDialog::SaveCurrentSequenceToFBX()
}
}
QString filename = QFileDialog::getSaveFileName(this, tr("Export Selected Nodes To FBX File"), selectedSequenceFBXStr, szFilters);
QString filename = AzQtComponents::FileDialog::GetSaveFileName(this, tr("Export Selected Nodes To FBX File"), selectedSequenceFBXStr, szFilters);
if (!filename.isEmpty())
{
pExportManager->SetBakedKeysSequenceExport(true);

@ -30,6 +30,7 @@
// AzQtComponents
#include <AzQtComponents/Components/Widgets/ColorPicker.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
// CryCommon
#include <CryCommon/Maestro/Bus/EditorSequenceComponentBus.h>
@ -1044,7 +1045,7 @@ void CTrackViewNodesCtrl::OnNMRclick(QPoint point)
file = QString::fromUtf8(selectedNodes.GetNode(0)->GetName().c_str()) + QString(".fbx");
}
QString path = QFileDialog::getSaveFileName(this, tr("Export Selected Nodes To FBX File"), QString(), tr("FBX Files (*.fbx)"));
QString path = AzQtComponents::FileDialog::GetSaveFileName(this, tr("Export Selected Nodes To FBX File"), QString(), tr("FBX Files (*.fbx)"));
if (!path.isEmpty())
{

@ -0,0 +1,53 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <QMessageBox>
#include <QRegExp>
namespace AzQtComponents
{
QString FileDialog::GetSaveFileName(QWidget* parent, const QString& caption, const QString& dir,
const QString& filter, QString* selectedFilter, QFileDialog::Options options)
{
bool shouldPromptAgain = false;
QString filePath;
do
{
// Trigger Qt's save filename dialog
// If filePath isn't empty, it means we are prompting again because the filename was invalid,
// so pass it instead of the directory so the filename is pre-filled in for the user
filePath = QFileDialog::getSaveFileName(parent, caption, (filePath.isEmpty()) ? dir : filePath, filter, selectedFilter, options);
if (!filePath.isEmpty())
{
QFileInfo fileInfo(filePath);
QString fileName = fileInfo.fileName();
// Check if the filename has any invalid characters
QRegExp validFileNameRegex("^[a-zA-Z0-9_\\-./]*$");
shouldPromptAgain = !validFileNameRegex.exactMatch(fileName);
// If the filename had invalid characters, then show a warning message and then we will re-prompt the save filename dialog
if (shouldPromptAgain)
{
QMessageBox::warning(parent, QObject::tr("Invalid filename"), QObject::tr("The filename contains invalid characters\n\n%1").arg(fileName));
}
}
else
{
// If the filePath is empty, then the user cancelled the dialog so we don't need to prompt again
shouldPromptAgain = false;
}
} while (shouldPromptAgain);
return filePath;
}
} // namespace AzQtComponents

@ -0,0 +1,29 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzQtComponents/AzQtComponentsAPI.h>
#if !defined(Q_MOC_RUN)
#include <QFileDialog>
#endif
namespace AzQtComponents
{
class AZ_QT_COMPONENTS_API FileDialog
{
public:
//! Helper method that extends QFileDialog::getSaveFileName to prevent the user from
//! saving a filename with invalid characters (e.g. AP doesn't allow @ characters because they are used for aliases)
static QString GetSaveFileName(QWidget* parent = nullptr, const QString& caption = QString(),
const QString& dir = QString(), const QString& filter = QString(),
QString* selectedFilter = nullptr, QFileDialog::Options options = QFileDialog::Options());
};
} // namespace AzQtComponents

@ -146,6 +146,8 @@ set(FILES
Components/Widgets/Eyedropper.h
Components/Widgets/Eyedropper.cpp
Components/Widgets/EyedropperConfig.ini
Components/Widgets/FileDialog.cpp
Components/Widgets/FileDialog.h
Components/Widgets/FilteredSearchWidget.qss
Components/Widgets/FilteredSearchWidgetConfig.ini
Components/Widgets/GradientSlider.cpp

@ -37,6 +37,10 @@ AZ_POP_DISABLE_WARNING
#include <AzFramework/Asset/GenericAssetHandler.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <SourceControl/SourceControlAPI.h>
#include <UI/PropertyEditor/PropertyRowWidget.hxx>
@ -46,9 +50,6 @@ AZ_POP_DISABLE_WARNING
#include <QMessageBox>
#include <QMenu>
#include <QMenuBar>
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QFileInfo::d_ptr': class 'QSharedDataPointer<QFileInfoPrivate>' needs to have dll-interface to be used by clients of class 'QFileInfo'
#include <QFileDialog>
AZ_POP_DISABLE_WARNING
#include <QAction>
namespace AzToolsFramework
@ -414,7 +415,7 @@ namespace AzToolsFramework
filter.append(")");
}
const QString saveAs = QFileDialog::getSaveFileName(nullptr, tr("Save As..."), m_userSettings->m_lastSavePath.c_str(), filter);
const QString saveAs = AzQtComponents::FileDialog::GetSaveFileName(AzToolsFramework::GetActiveWindow(), tr("Save As..."), m_userSettings->m_lastSavePath.c_str(), filter);
return SaveImpl(asset, saveAs);
}
@ -902,7 +903,7 @@ namespace AzToolsFramework
statusString = QString("%1");
}
statusString = statusString.arg(m_currentAsset).arg(m_queuedAssetStatus);
statusString = statusString.arg(m_currentAsset);
if (!m_queuedAssetStatus.isEmpty())
{
@ -920,7 +921,7 @@ namespace AzToolsFramework
void AssetEditorWidget::SetupHeader()
{
QString nameString = QString("%1").arg(m_currentAsset).arg(m_queuedAssetStatus);
QString nameString = QString("%1").arg(m_currentAsset);
m_header->setName(nameString);

@ -17,6 +17,8 @@
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/string/wildcard.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
@ -202,7 +204,7 @@ namespace ImageProcessingAtom
AZ::Data::AssetId assetId = product->GetAssetId();
menu->addAction("Save as DDS...", [assetId, this]()
{
QString filePath = QFileDialog::getSaveFileName(nullptr, QString("Save to file"), m_lastSavedPath, QString("DDS file (*.dds)"));
QString filePath = AzQtComponents::FileDialog::GetSaveFileName(nullptr, QString("Save to file"), m_lastSavedPath, QString("DDS file (*.dds)"));
if (filePath.isEmpty())
{
return;

@ -11,13 +11,13 @@
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
AZ_POP_DISABLE_WARNING
@ -29,7 +29,7 @@ namespace AtomToolsFramework
const QFileInfo initialFileInfo(initialPath);
const QString initialExt(initialFileInfo.completeSuffix());
const QFileInfo selectedFileInfo(QFileDialog::getSaveFileName(
const QFileInfo selectedFileInfo(AzQtComponents::FileDialog::GetSaveFileName(
QApplication::activeWindow(),
"Save File",
initialFileInfo.absolutePath() +
@ -104,7 +104,7 @@ namespace AtomToolsFramework
const QFileInfo initialFileInfo(initialPath);
const QString initialExt(initialFileInfo.completeSuffix());
const QFileInfo duplicateFileInfo(QFileDialog::getSaveFileName(
const QFileInfo duplicateFileInfo(AzQtComponents::FileDialog::GetSaveFileName(
QApplication::activeWindow(),
"Duplicate File",
GetUniqueFileInfo(initialPath).absoluteFilePath(),

@ -11,6 +11,8 @@
#include <AzFramework/Application/Application.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
@ -19,8 +21,6 @@
#include <Atom/Document/MaterialDocumentSettings.h>
#include <QFileDialog>
namespace MaterialEditor
{
CreateMaterialDialog::CreateMaterialDialog(QWidget* parent)
@ -95,7 +95,7 @@ namespace MaterialEditor
//When the file selection button is pressed, open a file dialog to select where the material will be saved
QObject::connect(m_ui->m_materialFilePicker, &AzQtComponents::BrowseEdit::attachedButtonTriggered, m_ui->m_materialFilePicker, [this]() {
QFileInfo fileInfo = QFileDialog::getSaveFileName(this,
QFileInfo fileInfo = AzQtComponents::FileDialog::GetSaveFileName(this,
QString("Select Material Filename"),
m_materialFileInfo.absoluteFilePath(),
QString("Material (*.material)"));

@ -11,6 +11,7 @@
#include <AzFramework/API/ApplicationAPI.h>
#include <AzQtComponents/Components/Widgets/BrowseEdit.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
@ -22,7 +23,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
#include <QCheckBox>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
@ -145,7 +145,7 @@ namespace AZ
// Whenever the browse button is clicked, open a save file dialog in the same location as the current export file setting
QObject::connect(materialFileWidget, &AzQtComponents::BrowseEdit::attachedButtonTriggered, materialFileWidget, [&dialog, &exportItem, materialFileWidget, overwriteCheckBox]() {
QFileInfo fileInfo = QFileDialog::getSaveFileName(&dialog,
QFileInfo fileInfo = AzQtComponents::FileDialog::GetSaveFileName(&dialog,
QString("Select Material Filename"),
exportItem.GetExportPath().c_str(),
QString("Material (*.material)"),

@ -9,7 +9,6 @@
#include "FileManager.h"
#include <MCore/Source/LogManager.h>
#include <MCore/Source/FileSystem.h>
#include <QFileDialog>
#include <QString>
#include <QTranslator>
#include <QMessageBox>
@ -36,6 +35,8 @@
#include <Source/Integration/Assets/MotionSetAsset.h>
#include <Source/Integration/Assets/AnimGraphAsset.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
@ -412,14 +413,12 @@ namespace EMStudio
{
GetManager()->SetAvoidRendering(true);
QFileDialog::Options options;
QString selectedFilter;
const AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent
const AZStd::string filename = AzQtComponents::FileDialog::GetSaveFileName(parent, // parent
"Save", // caption
GetLastUsedFolder(m_lastActorFolder), // directory
"EMotion FX Actor Files (*.actor)",
&selectedFilter,
options).toUtf8().data();
&selectedFilter).toUtf8().data();
GetManager()->SetAvoidRendering(false);
@ -471,14 +470,12 @@ namespace EMStudio
{
GetManager()->SetAvoidRendering(true);
QFileDialog::Options options;
QString selectedFilter;
AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent
AZStd::string filename = AzQtComponents::FileDialog::GetSaveFileName(parent, // parent
"Save", // caption
GetLastUsedFolder(m_lastWorkspaceFolder), // directory
"EMotionFX Editor Workspace Files (*.emfxworkspace)",
&selectedFilter,
options).toUtf8().data();
&selectedFilter).toUtf8().data();
GetManager()->SetAvoidRendering(false);
@ -553,14 +550,12 @@ namespace EMStudio
{
GetManager()->SetAvoidRendering(true);
QFileDialog::Options options;
QString selectedFilter;
AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent
AZStd::string filename = AzQtComponents::FileDialog::GetSaveFileName(parent, // parent
"Save", // caption
GetLastUsedFolder(m_lastMotionSetFolder), // directory
"EMotion FX Motion Set Files (*.motionset)",
&selectedFilter,
options).toUtf8().data();
&selectedFilter).toUtf8().data();
GetManager()->SetAvoidRendering(false);
@ -632,14 +627,12 @@ namespace EMStudio
{
GetManager()->SetAvoidRendering(true);
QFileDialog::Options options;
QString selectedFilter;
AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent
AZStd::string filename = AzQtComponents::FileDialog::GetSaveFileName(parent, // parent
"Save", // caption
GetLastUsedFolder(m_lastAnimGraphFolder), // directory
"EMotion FX Anim Graph Files (*.animgraph);;All Files (*)",
&selectedFilter,
options).toUtf8().data();
&selectedFilter).toUtf8().data();
GetManager()->SetAvoidRendering(false);
@ -675,14 +668,12 @@ namespace EMStudio
{
GetManager()->SetAvoidRendering(true);
QFileDialog::Options options;
QString selectedFilter;
const AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent
const AZStd::string filename = AzQtComponents::FileDialog::GetSaveFileName(parent, // parent
"Save", // caption
GetLastUsedFolder(m_lastNodeMapFolder), // directory
"Node Map Files (*.nodeMap);;All Files (*)",
&selectedFilter,
options).toUtf8().data();
&selectedFilter).toUtf8().data();
GetManager()->SetAvoidRendering(false);
@ -737,14 +728,12 @@ namespace EMStudio
GetManager()->SetAvoidRendering(true);
QFileDialog::Options options;
QString selectedFilter;
QString filename = QFileDialog::getSaveFileName(parent, // parent
QString filename = AzQtComponents::FileDialog::GetSaveFileName(parent, // parent
"Save", // caption
dir.c_str(), // directory
"EMotion FX Blend Config Files (*.cfg);;All Files (*)",
&selectedFilter,
options);
&selectedFilter);
GetManager()->SetAvoidRendering(false);

@ -14,6 +14,7 @@
#include <AzToolsFramework/Slice/SliceUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzQtComponents/Components/Widgets/TabWidget.h>
#include <LyShine/UiComponentTypes.h>
#include <LyShine/Bus/UiEditorCanvasBus.h>
@ -32,7 +33,6 @@
#include <QClipboard>
#include <QUndoGroup>
#include <QScrollBar>
#include <QFileDialog>
#define UICANVASEDITOR_SETTINGS_EDIT_MODE_STATE_KEY (QString("Edit Mode State") + " " + FileHelpers::GetAbsoluteGameDir())
#define UICANVASEDITOR_SETTINGS_EDIT_MODE_GEOM_KEY (QString("Edit Mode Geometry") + " " + FileHelpers::GetAbsoluteGameDir())
@ -706,7 +706,7 @@ bool EditorWindow::SaveCanvasToXml(UiCanvasMetadata& canvasMetadata, bool forceA
dir.append(canvasMetadata.m_canvasDisplayName.c_str());
}
QString filename = QFileDialog::getSaveFileName(nullptr,
QString filename = AzQtComponents::FileDialog::GetSaveFileName(nullptr,
QString(),
dir,
"*." UICANVASEDITOR_CANVAS_EXTENSION,

@ -15,7 +15,6 @@
#include <QSplitter>
#include <QListView>
#include <QFileDialog>
#include <QShortcut>
#include <QKeySequence>
#include <QKeyEvent>
@ -91,6 +90,7 @@
#include <AzToolsFramework/ToolsComponents/ToolsAssetCatalogBus.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzQtComponents/Components/Widgets/TabWidget.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
@ -1868,7 +1868,7 @@ namespace ScriptCanvasEditor
while (!isValidFileName)
{
selectedFile = QFileDialog::getSaveFileName(this, tr("Save As..."), suggestedFilename.data(), filter);
selectedFile = AzQtComponents::FileDialog::GetSaveFileName(this, tr("Save As..."), suggestedFilename.data(), filter);
// If the selected file is empty that means we just cancelled.
// So we want to break out.

@ -24,6 +24,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/numeric.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
@ -31,7 +32,6 @@
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <QFileDialog>
#include <QMessageBox>
#include <WhiteBox/EditorWhiteBoxColliderBus.h>
#include <WhiteBox/WhiteBoxBus.h>
@ -513,7 +513,7 @@ namespace WhiteBox
WhiteBoxPathAtProjectRoot(GetEntity()->GetName(), ObjExtension);
const QString fileFilter = AZStd::string::format("*.%s", ObjExtension).c_str();
const QString absoluteSaveFilePath = QFileDialog::getSaveFileName(
const QString absoluteSaveFilePath = AzQtComponents::FileDialog::GetSaveFileName(
nullptr, "Save As...", QString(initialAbsolutePathToExport.c_str()), fileFilter);
const auto absoluteSaveFilePathUtf8 = absoluteSaveFilePath.toUtf8();
@ -577,7 +577,7 @@ namespace WhiteBox
{
const QString fileFilter =
AZStd::string::format("*.%s", Pipeline::WhiteBoxMeshAssetHandler::AssetFileExtension).c_str();
const QString absolutePath = QFileDialog::getSaveFileName(
const QString absolutePath = AzQtComponents::FileDialog::GetSaveFileName(
nullptr, "Save As Asset...", QString(initialAbsolutePath.c_str()), fileFilter);
return AZStd::string(absolutePath.toUtf8());

Loading…
Cancel
Save