You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
9.0 KiB
C++
252 lines
9.0 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include "EditorDefs.h"
|
|
|
|
#include "SelectDestinationDialog.h"
|
|
|
|
// Qt
|
|
#include <QValidator>
|
|
#include <QSettings>
|
|
#include <QStyle>
|
|
|
|
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
#include <AssetImporter/UI/ui_SelectDestinationDialog.h>
|
|
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
|
|
|
|
static const char* g_assetProcessorLink = "<a href=\"https://o3de.org/docs/user-guide/assets/pipeline/processor-ui/\">Asset Processor</a>";
|
|
static const char* g_copyFilesMessage = "The original file will remain outside of the project and the %1 will not monitor the file.";
|
|
static const char* g_moveFilesMessage = "The original file will be moved inside of the project and the %1 will monitor the file for changes.";
|
|
static const char* g_selectDestinationFilesPath = "AssetImporter/SelectDestinationFilesPath";
|
|
|
|
static const char* g_toolTipInvalidRoot = "<p style='white-space:pre'> <span style=\"color:#cccccc;\">Invalid directory. Please choose a destination directory within your game project: %1.</span> </p>";
|
|
static const char* g_toolTipPathMustExist = "<p style='white-space:pre'> <span style=\"color:#cccccc;\">Invalid directory. Please choose a destination directory that exists.</span> </p>";
|
|
static const char* g_toolTipPathMustBeDirectory = "<p style='white-space:pre'> <span style=\"color:#cccccc;\">Invalid directory. Please choose a valid destination directory.</span> </p>";
|
|
static const char* g_toolTipInvalidLength = "<p style='white-space:pre'> <span style=\"color:#cccccc;\">Invalid directory name length. Please choose a destination path that has fewer than %1 characters.</span> </p>";
|
|
|
|
namespace
|
|
{
|
|
static QString GetAbsoluteRootDirectoryPath()
|
|
{
|
|
QDir gameRoot(Path::GetEditingGameDataFolder().c_str());
|
|
return gameRoot.absolutePath();
|
|
}
|
|
}
|
|
|
|
class DestinationDialogValidator
|
|
: public QValidator
|
|
{
|
|
public:
|
|
DestinationDialogValidator(QObject* parent)
|
|
: QValidator(parent)
|
|
, m_gameRootAbsolutePath(GetAbsoluteRootDirectoryPath())
|
|
{
|
|
}
|
|
|
|
State validate(QString& input, [[maybe_unused]] int& pos) const override
|
|
{
|
|
m_toolTip = "";
|
|
|
|
if (input.isEmpty())
|
|
{
|
|
return QValidator::Acceptable;
|
|
}
|
|
|
|
// The underlying file system code can't cope with long file paths, regardless of platform
|
|
if (input.length() > (AZ_MAX_PATH_LEN - 1))
|
|
{
|
|
m_toolTip = QString(g_toolTipInvalidLength).arg(AZ_MAX_PATH_LEN);
|
|
return QValidator::Intermediate;
|
|
}
|
|
|
|
QString normalizedInput = QDir::fromNativeSeparators(input);
|
|
|
|
// Note: the check for the root directory is case insensitive.
|
|
// We check if the directory actually exists after this, and at that point,
|
|
// if the file path has to be case sensitive, the directory won't exist anyways
|
|
// and QFileInfo::exists() will tell us so this should still work even on
|
|
// case sensitive file systems (such as Mac and Linux)
|
|
if (!normalizedInput.startsWith(m_gameRootAbsolutePath, Qt::CaseInsensitive))
|
|
{
|
|
m_toolTip = QString(g_toolTipInvalidRoot).arg(m_gameRootAbsolutePath);
|
|
return QValidator::Intermediate;
|
|
}
|
|
|
|
QFileInfo fileInfo(normalizedInput);
|
|
if (!fileInfo.exists())
|
|
{
|
|
m_toolTip = g_toolTipPathMustExist;
|
|
return QValidator::Intermediate;
|
|
}
|
|
|
|
if (!fileInfo.isDir())
|
|
{
|
|
m_toolTip = g_toolTipPathMustBeDirectory;
|
|
return QValidator::Intermediate;
|
|
}
|
|
|
|
return QValidator::Acceptable;
|
|
}
|
|
|
|
QString infoToolTip() const
|
|
{
|
|
return m_toolTip;
|
|
}
|
|
|
|
private:
|
|
QString m_gameRootAbsolutePath;
|
|
mutable QString m_toolTip;
|
|
};
|
|
|
|
SelectDestinationDialog::SelectDestinationDialog(QString message, QWidget* parent)
|
|
: QDialog(parent)
|
|
, m_ui(new Ui::SelectDestinationDialog)
|
|
, m_validator(new DestinationDialogValidator(this))
|
|
{
|
|
m_ui->setupUi(this);
|
|
|
|
QString radioButtonMessage = QString(g_copyFilesMessage).arg(g_assetProcessorLink);
|
|
m_ui->RaidoButtonMessage->setText(radioButtonMessage);
|
|
|
|
SetPreviousDestinationDirectory();
|
|
|
|
m_ui->DestinationLineEdit->setValidator(m_validator);
|
|
m_ui->DestinationLineEdit->setAlignment(Qt::AlignVCenter);
|
|
|
|
// Based on the current code structure, in order to prevent texts from overlapping the
|
|
// invalid icon, intentionally insert an empty icon at the end of the line edit field can do the trick.
|
|
m_ui->DestinationLineEdit->addAction(QIcon(""), QLineEdit::TrailingPosition);
|
|
|
|
connect(m_ui->DestinationLineEdit, &QLineEdit::textChanged, this, &SelectDestinationDialog::ValidatePath);
|
|
connect(m_ui->BrowseButton, &QPushButton::clicked, this, &SelectDestinationDialog::OnBrowseDestinationFilePath, Qt::UniqueConnection);
|
|
connect(m_ui->CopyFileRadioButton, &QRadioButton::toggled, this, &SelectDestinationDialog::ShowMessage);
|
|
|
|
UpdateMessage(message);
|
|
InitializeButtons();
|
|
}
|
|
|
|
SelectDestinationDialog::~SelectDestinationDialog()
|
|
{
|
|
}
|
|
|
|
void SelectDestinationDialog::InitializeButtons()
|
|
{
|
|
m_ui->CopyFileRadioButton->setChecked(true);
|
|
|
|
m_ui->buttonBox->setContentsMargins(0, 0, 16, 16);
|
|
|
|
QPushButton* importButton = m_ui->buttonBox->addButton(tr("Import"), QDialogButtonBox::AcceptRole);
|
|
QPushButton* cancelButton = m_ui->buttonBox->addButton(QDialogButtonBox::Cancel);
|
|
|
|
importButton->setProperty("class", "Primary");
|
|
importButton->setDefault(true);
|
|
|
|
cancelButton->setProperty("class", "AssetImporterButton");
|
|
cancelButton->style()->unpolish(cancelButton);
|
|
cancelButton->style()->polish(cancelButton);
|
|
cancelButton->update();
|
|
|
|
connect(importButton, &QPushButton::clicked, this, &SelectDestinationDialog::accept);
|
|
connect(cancelButton, &QPushButton::clicked, this, &SelectDestinationDialog::reject);
|
|
connect(this, &SelectDestinationDialog::UpdateImportButtonState, importButton, &QPushButton::setEnabled);
|
|
|
|
// To make sure the import button state is up to date
|
|
ValidatePath();
|
|
importButton->setAutoDefault(true);
|
|
|
|
}
|
|
|
|
void SelectDestinationDialog::SetPreviousDestinationDirectory()
|
|
{
|
|
QString gameRootAbsPath = GetAbsoluteRootDirectoryPath();
|
|
QSettings settings;
|
|
QString previousDestination = settings.value(g_selectDestinationFilesPath).toString();
|
|
|
|
// Case 1: if currentDestination is empty at this point, that means this is the first time
|
|
// users using the Asset Importer, set the default directory to be the current game project's root folder
|
|
// Case 2: if the current folder directory stored in the registry doesn't exist anymore,
|
|
// that means users have removed the directory already (deleted or use the Move feature).
|
|
// Case 3: if it's a directory outside of the game root folder, then in general,
|
|
// users have modified the folder directory in the registry. It should not be happening.
|
|
if (previousDestination.isEmpty() || !QDir(previousDestination).exists() || !previousDestination.startsWith(gameRootAbsPath, Qt::CaseInsensitive))
|
|
{
|
|
previousDestination = gameRootAbsPath;
|
|
}
|
|
|
|
m_ui->DestinationLineEdit->setText(QDir::toNativeSeparators(previousDestination));
|
|
}
|
|
|
|
void SelectDestinationDialog::accept()
|
|
{
|
|
QDialog::accept();
|
|
|
|
// This prevent users from not editing the destination line edit (manually type the directory or browse for the directory)
|
|
Q_EMIT SetDestinationDirectory(DestinationDirectory());
|
|
|
|
if (m_ui->CopyFileRadioButton->isChecked())
|
|
{
|
|
Q_EMIT DoCopyFiles();
|
|
}
|
|
else if (m_ui->MoveFileRadioButton->isChecked())
|
|
{
|
|
Q_EMIT DoMoveFiles();
|
|
}
|
|
}
|
|
|
|
void SelectDestinationDialog::reject()
|
|
{
|
|
Q_EMIT Cancel();
|
|
QDialog::reject();
|
|
}
|
|
|
|
void SelectDestinationDialog::ShowMessage()
|
|
{
|
|
QString message = m_ui->CopyFileRadioButton->isChecked() ? g_copyFilesMessage : g_moveFilesMessage;
|
|
m_ui->RaidoButtonMessage->setText(message.arg(g_assetProcessorLink));
|
|
}
|
|
|
|
void SelectDestinationDialog::OnBrowseDestinationFilePath()
|
|
{
|
|
Q_EMIT BrowseDestinationPath(m_ui->DestinationLineEdit);
|
|
}
|
|
|
|
void SelectDestinationDialog::UpdateMessage(QString message)
|
|
{
|
|
m_ui->NumberOfFilesMessage->setText(message);
|
|
}
|
|
|
|
void SelectDestinationDialog::ValidatePath()
|
|
{
|
|
if (!m_ui->DestinationLineEdit->hasAcceptableInput())
|
|
{
|
|
m_ui->DestinationLineEdit->setToolTip(m_validator->infoToolTip());
|
|
Q_EMIT UpdateImportButtonState(false);
|
|
}
|
|
else
|
|
{
|
|
QString destinationDirectory = DestinationDirectory();
|
|
int strLength = destinationDirectory.length();
|
|
|
|
// store the updated acceptable destination directory into the registry,
|
|
// so that when users manually modify the directory,
|
|
// the Asset Importer will remember it
|
|
Q_EMIT SetDestinationDirectory(destinationDirectory);
|
|
|
|
m_ui->DestinationLineEdit->setToolTip("");
|
|
Q_EMIT UpdateImportButtonState(strLength > 0);
|
|
}
|
|
}
|
|
|
|
QString SelectDestinationDialog::DestinationDirectory() const
|
|
{
|
|
return QDir::fromNativeSeparators(m_ui->DestinationLineEdit->text());
|
|
}
|
|
|
|
#include <AssetImporter/UI/moc_SelectDestinationDialog.cpp>
|
|
|