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

Signed-off-by: Chris Galvan <chgalvan@amazon.com>
This commit is contained in:
Chris Galvan
2021-08-27 11:24:05 -05:00
parent 9e5ef08229
commit d590a91fe7
14 changed files with 127 additions and 49 deletions
+2 -1
View File
@@ -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);
+2 -1
View File
@@ -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);