/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "StdAfx.h" #include "SelectDestinationDialog.h" #include #include #include #include #include #include #include static const char* g_assetProcessorLink = "Asset Processor"; 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 = "

Invalid directory. Please choose a destination directory within your game project: %1.

"; static const char* g_toolTipPathMustExist = "

Invalid directory. Please choose a destination directory that exists.

"; static const char* g_toolTipPathMustBeDirectory = "

Invalid directory. Please choose a valid destination directory.

"; static const char* g_toolTipInvalidLength = "

Invalid directory name length. Please choose a destination path that has fewer than %1 characters.

"; 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, 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(); AzQtComponents::EditorProxyStyle::UpdatePrimaryButtonStyle(importButton); } 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