123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894 |
- /*
- * 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 "native/utilities/GUIApplicationManager.h"
- #include "native/connection/connectionManager.h"
- #include "native/utilities/IniConfiguration.h"
- #include "native/utilities/GUIApplicationServer.h"
- #include "native/resourcecompiler/rccontroller.h"
- #include "native/FileServer/fileServer.h"
- #include "native/AssetManager/assetScanner.h"
- #include <native/utilities/PlatformConfiguration.h>
- #include <QApplication>
- #include <QDialogButtonBox>
- #include <QLabel>
- #include <QMessageBox>
- #include <QSettings>
- #include <AzQtComponents/Components/StyleManager.h>
- #include <AzQtComponents/Components/WindowDecorationWrapper.h>
- #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
- #include <AzCore/Utils/Utils.h>
- #if defined(EXTERNAL_CRASH_REPORTING)
- #include <ToolsCrashHandler.h>
- #endif
- #if defined(AZ_PLATFORM_MAC)
- #include <native/utilities/MacDockIconHandler.h>
- #include <ApplicationServices/ApplicationServices.h>
- #endif
- #include <QJsonArray>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QSettings>
- #include <ui/MessageWindow.h>
- using namespace AssetProcessor;
- namespace
- {
- static const int s_errorMessageBoxDelay = 5000;
- void RemoveTemporaries()
- {
- // get currently running app
- QFileInfo moduleFileInfo;
- char executableDirectory[AZ_MAX_PATH_LEN];
- AZ::Utils::GetExecutablePathReturnType result = AZ::Utils::GetExecutablePath(executableDirectory, AZStd::size(executableDirectory));
- if (result.m_pathStored == AZ::Utils::ExecutablePathResult::Success)
- {
- moduleFileInfo.setFile(executableDirectory);
- }
- QDir binaryDir = moduleFileInfo.absoluteDir();
- // strip extension
- QString applicationBase = moduleFileInfo.completeBaseName();
- // add wildcard filter
- applicationBase.append("*_tmp");
- // set to qt
- binaryDir.setNameFilters(QStringList() << applicationBase);
- binaryDir.setFilter(QDir::Files);
- // iterate all matching
- foreach(QString tempFile, binaryDir.entryList())
- {
- binaryDir.remove(tempFile);
- }
- }
- }
- ErrorCollector::~ErrorCollector()
- {
- if (!m_errorMessages.isEmpty())
- {
- MessageWindow messageWindow(m_parent);
- messageWindow.SetHeaderText("The following errors occurred during startup:");
- messageWindow.SetMessageText(m_errorMessages);
- messageWindow.SetTitleText("Startup Errors");
- messageWindow.exec();
- }
- }
- void ErrorCollector::AddError(AZStd::string message)
- {
- QString qMessage(message.c_str());
- qMessage = qMessage.trimmed();
- m_errorMessages << qMessage;
- }
- GUIApplicationManager::GUIApplicationManager(int* argc, char*** argv, QObject* parent)
- : GUIApplicationManager(argc, argv, parent, {})
- {
- }
- GUIApplicationManager::GUIApplicationManager(int* argc, char*** argv, AZ::ComponentApplicationSettings componentAppSettings)
- : GUIApplicationManager(argc, argv, nullptr, AZStd::move(componentAppSettings))
- {
- }
- GUIApplicationManager::GUIApplicationManager(int* argc, char*** argv, QObject* parent, AZ::ComponentApplicationSettings componentAppSettings)
- : ApplicationManagerBase(argc, argv, parent, AZStd::move(componentAppSettings))
- {
- #if defined(AZ_PLATFORM_MAC)
- // Since AP is not shipped as a '.app' package, it will not receive keyboard focus
- // unless we tell the OS specifically to treat it as a foreground application.
- ProcessSerialNumber psn = { 0, kCurrentProcess };
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- #endif
- }
- GUIApplicationManager::~GUIApplicationManager()
- {
- Destroy();
- }
- ApplicationManager::BeforeRunStatus GUIApplicationManager::BeforeRun()
- {
- AssetProcessor::MessageInfoBus::Handler::BusConnect();
- ApplicationManager::BeforeRunStatus status = ApplicationManagerBase::BeforeRun();
- if (status != ApplicationManager::BeforeRunStatus::Status_Success)
- {
- return status;
- }
- // The build process may leave behind some temporaries, try to delete them
- RemoveTemporaries();
- QDir projectAssetRoot;
- AssetUtilities::ComputeAssetRoot(projectAssetRoot);
- #if defined(EXTERNAL_CRASH_REPORTING)
- CrashHandler::ToolsCrashHandler::InitCrashHandler("AssetProcessor", projectAssetRoot.absolutePath().toStdString());
- #endif
- // we have to monitor both the cache folder and the database file and restart AP if either of them gets deleted
- // It is important to note that we are monitoring the parent folder and not the actual cache folder itself since
- // we want to handle the use case on Mac OS if the user moves the cache folder to the trash.
- m_qtFileWatcher.addPath(projectAssetRoot.absolutePath());
- QDir projectCacheRoot;
- AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
- QString assetDbPath = projectCacheRoot.filePath("assetdb.sqlite");
- m_qtFileWatcher.addPath(assetDbPath);
- // if our Gems file changes, make sure we watch that, too.
- QString projectPath = AssetUtilities::ComputeProjectPath();
- QObject::connect(&m_qtFileWatcher, &QFileSystemWatcher::fileChanged, this, &GUIApplicationManager::FileChanged);
- QObject::connect(&m_qtFileWatcher, &QFileSystemWatcher::directoryChanged, this, &GUIApplicationManager::DirectoryChanged);
- return ApplicationManager::BeforeRunStatus::Status_Success;
- }
- void GUIApplicationManager::Destroy()
- {
- m_startupErrorCollector = nullptr;
- if (m_mainWindow)
- {
- delete m_mainWindow;
- m_mainWindow = nullptr;
- }
- AssetProcessor::MessageInfoBus::Handler::BusDisconnect();
- ApplicationManagerBase::Destroy();
- DestroyIniConfiguration();
- DestroyFileServer();
- }
- bool GUIApplicationManager::Run()
- {
- qRegisterMetaType<AZ::u32>("AZ::u32");
- qRegisterMetaType<AZ::Uuid>("AZ::Uuid");
- AZ::IO::FixedMaxPath engineRootPath;
- if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
- {
- settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
- }
- AzQtComponents::StyleManager* styleManager = new AzQtComponents::StyleManager(qApp);
- styleManager->initialize(qApp, engineRootPath);
- QDir engineRoot;
- AssetUtilities::ComputeAssetRoot(engineRoot);
- AssetUtilities::ComputeEngineRoot(engineRoot);
- AzQtComponents::StyleManager::addSearchPaths(
- QStringLiteral("style"),
- engineRoot.filePath(QStringLiteral("Code/Tools/AssetProcessor/native/ui/style")),
- QStringLiteral(":/AssetProcessor/style"),
- engineRootPath);
- m_mainWindow = new MainWindow(this);
- auto wrapper = new AzQtComponents::WindowDecorationWrapper(
- #if defined(AZ_PLATFORM_WINDOWS)
- // On windows we do want our custom title bar
- AzQtComponents::WindowDecorationWrapper::OptionAutoAttach
- #else
- // On others platforms we don't want our custom title bar (ie, use native title bars).
- AzQtComponents::WindowDecorationWrapper::OptionDisabled
- #endif
- );
- wrapper->setGuest(m_mainWindow);
- // Use this variant of the enableSaveRestoreGeometry because the global QCoreApplication::setOrganization and setApplicationName
- // are called in ApplicationManager::Activate, which happens much later on in this function.
- // ApplicationManager::Activate is shared between the Batch version of the AP and the GUI version,
- // and there are thing
- const bool restoreOnFirstShow = true;
- wrapper->enableSaveRestoreGeometry(GetOrganizationName(), GetApplicationName(), "MainWindow", restoreOnFirstShow);
- AzQtComponents::StyleManager::setStyleSheet(m_mainWindow, QStringLiteral("style:AssetProcessor.qss"));
- auto refreshStyleSheets = [styleManager]()
- {
- styleManager->Refresh();
- };
- // CheckForRegistryProblems can pop up a dialog, so we need to check after
- // we initialize the stylesheet
- bool showErrorMessageOnRegistryProblem = true;
- RegistryCheckInstructions registryCheckInstructions = CheckForRegistryProblems(m_mainWindow, showErrorMessageOnRegistryProblem);
- if (registryCheckInstructions != RegistryCheckInstructions::Continue)
- {
- if (registryCheckInstructions == RegistryCheckInstructions::Restart)
- {
- Restart();
- }
- return false;
- }
- bool startHidden = QApplication::arguments().contains("--start-hidden", Qt::CaseInsensitive);
- if (!startHidden)
- {
- wrapper->show();
- }
- else
- {
- #ifdef AZ_PLATFORM_WINDOWS
- // Qt / Windows has issues if the main window isn't shown once
- // so we show it then hide it
- wrapper->show();
- // Have a delay on the hide, to make sure that the show is entirely processed
- // first
- QTimer::singleShot(0, wrapper, &QWidget::hide);
- #endif
- }
- #ifdef AZ_PLATFORM_MAC
- connect(new MacDockIconHandler(this), &MacDockIconHandler::dockIconClicked, m_mainWindow, &MainWindow::ShowWindow);
- #endif
- QAction* quitAction = new QAction(QObject::tr("Quit"), m_mainWindow);
- quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
- quitAction->setMenuRole(QAction::QuitRole);
- m_mainWindow->addAction(quitAction);
- m_mainWindow->connect(quitAction, SIGNAL(triggered()), this, SLOT(QuitRequested()));
- QAction* refreshAction = new QAction(QObject::tr("Refresh Stylesheet"), m_mainWindow);
- refreshAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R));
- m_mainWindow->addAction(refreshAction);
- m_mainWindow->connect(refreshAction, &QAction::triggered, this, refreshStyleSheets);
- QObject::connect(this, &GUIApplicationManager::ShowWindow, m_mainWindow, &MainWindow::ShowWindow);
- if (QSystemTrayIcon::isSystemTrayAvailable())
- {
- QAction* showAction = new QAction(QObject::tr("Show"), m_mainWindow);
- QObject::connect(showAction, &QAction::triggered, m_mainWindow, &MainWindow::ShowWindow);
- QAction* hideAction = new QAction(QObject::tr("Hide"), m_mainWindow);
- QObject::connect(hideAction, &QAction::triggered, wrapper, &AzQtComponents::WindowDecorationWrapper::hide);
- QMenu* trayIconMenu = new QMenu();
- trayIconMenu->addAction(showAction);
- trayIconMenu->addAction(hideAction);
- trayIconMenu->addSeparator();
- #if AZ_TRAIT_OS_PLATFORM_APPLE
- QAction* systemTrayQuitAction = new QAction(QObject::tr("Quit"), m_mainWindow);
- systemTrayQuitAction->setMenuRole(QAction::NoRole);
- m_mainWindow->connect(systemTrayQuitAction, SIGNAL(triggered()), this, SLOT(QuitRequested()));
- trayIconMenu->addAction(systemTrayQuitAction);
- #else
- trayIconMenu->addAction(quitAction);
- #endif
- m_trayIcon = new QSystemTrayIcon(QIcon(":/o3de_assetprocessor_taskbar.svg"), m_mainWindow);
- m_trayIcon->setContextMenu(trayIconMenu);
- m_trayIcon->setToolTip(QObject::tr("O3DE Asset Processor"));
- m_trayIcon->show();
- QObject::connect(m_trayIcon, &QSystemTrayIcon::activated, m_mainWindow, [&, wrapper](QSystemTrayIcon::ActivationReason reason)
- {
- if (reason == QSystemTrayIcon::DoubleClick)
- {
- if (wrapper->isVisible())
- {
- wrapper->hide();
- }
- else
- {
- m_mainWindow->ShowWindow();
- }
- }
- });
- QObject::connect(m_trayIcon, &QSystemTrayIcon::messageClicked, m_mainWindow, &MainWindow::ShowWindow);
- if (startHidden)
- {
- m_trayIcon->showMessage(
- QCoreApplication::translate("Tray Icon", "O3DE Asset Processor has started"),
- QCoreApplication::translate("Tray Icon", "The O3DE Asset Processor monitors raw project assets and converts those assets into runtime-ready data."),
- QSystemTrayIcon::Information, 3000);
- }
- }
- connect(this, &GUIApplicationManager::AssetProcessorStatusChanged, m_mainWindow, &MainWindow::OnAssetProcessorStatusChanged);
- if (!Activate())
- {
- return false;
- }
- m_mainWindow->Activate();
- connect(GetAssetScanner(), &AssetProcessor::AssetScanner::AssetScanningStatusChanged, this, [this](AssetScanningStatus status)
- {
- if (status == AssetScanningStatus::Started)
- {
- AssetProcessor::AssetProcessorStatusEntry entry(AssetProcessor::AssetProcessorStatus::Scanning_Started);
- m_mainWindow->OnAssetProcessorStatusChanged(entry);
- }
- });
- connect(GetRCController(), &AssetProcessor::RCController::ActiveJobsCountChanged, this, &GUIApplicationManager::OnActiveJobsCountChanged);
- connect(this, &GUIApplicationManager::ConnectionStatusMsg, this, &GUIApplicationManager::ShowTrayIconMessage);
- qApp->setQuitOnLastWindowClosed(false);
- m_duringStartup = false;
- m_startedSuccessfully = true;
- int resultCode = qApp->exec(); // this blocks until the last window is closed.
- if(!InitiatedShutdown())
- {
- // if we are here it implies that AP did not stop the Qt event loop and is shutting down prematurely
- // we need to call QuitRequested and start the event loop once again so that AP shuts down correctly
- QuitRequested();
- resultCode = qApp->exec();
- }
- if (m_trayIcon)
- {
- m_trayIcon->hide();
- delete m_trayIcon;
- }
- m_mainWindow->SaveLogPanelState();
- // mainWindow indirectly uses some UserSettings so clean it up before we clean those up
- delete m_mainWindow;
- m_mainWindow = nullptr;
- AZ::SerializeContext* context = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
- AZ_Assert(context, "No serialize context");
- QDir projectCacheRoot;
- AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
- m_localUserSettings.Save(projectCacheRoot.filePath("AssetProcessorUserSettings.xml").toUtf8().data(), context);
- m_localUserSettings.Deactivate();
- if (NeedRestart())
- {
- bool launched = Restart();
- if (!launched)
- {
- return false;
- }
- }
- Destroy();
- return !resultCode && m_startedSuccessfully;
- }
- void GUIApplicationManager::NegotiationFailed()
- {
- QString message = QCoreApplication::translate("error", "An attempt to connect to the game or editor has failed. The game or editor appears to be running from a different folder or a different project. Please restart the asset processor from the correct branch or make sure the game/editor is running the same project as the asset processor.");
- QMetaObject::invokeMethod(this, "ShowMessageBox", Qt::QueuedConnection, Q_ARG(QString, QString("Negotiation Failed")), Q_ARG(QString, message), Q_ARG(bool, false));
- }
- void GUIApplicationManager::OnAssetFailed(const AZStd::string& sourceFileName)
- {
- QString message = tr("Error : %1 failed to compile\nPlease check the Asset Processor for more information.").arg(QString::fromUtf8(sourceFileName.c_str()));
- QMetaObject::invokeMethod(this, "ShowTrayIconErrorMessage", Qt::QueuedConnection, Q_ARG(QString, message));
- }
- void GUIApplicationManager::OnErrorMessage(const char* error)
- {
- QMessageBox msgBox;
- msgBox.setText(QCoreApplication::translate("errors", error));
- msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.setDefaultButton(QMessageBox::Ok);
- msgBox.exec();
- }
- void GUIApplicationManager::ShowMessageBox(QString title, QString msg, bool isCritical)
- {
- if (!m_messageBoxIsVisible)
- {
- // Only show the message box if it is not visible
- m_messageBoxIsVisible = true;
- QMessageBox msgBox(m_mainWindow);
- msgBox.setWindowTitle(title);
- msgBox.setText(msg);
- msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.setDefaultButton(QMessageBox::Ok);
- if (isCritical)
- {
- msgBox.setIcon(QMessageBox::Critical);
- }
- msgBox.exec();
- m_messageBoxIsVisible = false;
- }
- }
- bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
- {
- // if we're in a worker thread, errors must not pop up a dialog box
- if (AssetProcessor::GetThreadLocalJobId() != 0)
- {
- // just absorb the error, do not perform default op
- return true;
- }
- if (m_startupErrorCollector)
- {
- m_startupErrorCollector->AddError(message);
- return true;
- }
- if (!InitiatedShutdown())
- {
- // During quitting, we don't pop up error message boxes.
- // instead, we're going to return true, which will cause it to
- // process to the log file instead.
- return true;
- }
- // If we're the main thread, then consider showing the message box directly.
- // note that all other threads will PAUSE if they emit a message while the main thread is showing this box
- // due to the way the trace system EBUS is mutex-protected.
- Qt::ConnectionType connection = Qt::DirectConnection;
- if (QThread::currentThread() != qApp->thread())
- {
- connection = Qt::QueuedConnection;
- }
- QMetaObject::invokeMethod(this, "ShowMessageBox", connection, Q_ARG(QString, QString("Error")), Q_ARG(QString, QString(message)), Q_ARG(bool, true));
- return true;
- }
- bool GUIApplicationManager::OnAssert(const char* message)
- {
- if (!OnError(nullptr, message))
- {
- return false;
- }
- // Asserts should be severe enough for data corruption,
- // so the process should quit to avoid that happening for users.
- if (!AZ::Debug::Trace::Instance().IsDebuggerPresent())
- {
- QuitRequested();
- return true;
- }
- AZ::Debug::Trace::Instance().Break();
- return true;
- }
- WId GUIApplicationManager::GetWindowId() const
- {
- return m_mainWindow->effectiveWinId();
- }
- bool GUIApplicationManager::Activate()
- {
- m_startupErrorCollector = AZStd::make_unique<ErrorCollector>(m_mainWindow);
- AZ::SerializeContext* context = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
- AZ_Assert(context, "No serialize context");
- QDir projectCacheRoot;
- AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
- m_localUserSettings.Load(projectCacheRoot.filePath("AssetProcessorUserSettings.xml").toUtf8().data(), context);
- m_localUserSettings.Activate(AZ::UserSettings::CT_LOCAL);
- InitIniConfiguration();
- InitFileServer();
- //activate the base stuff.
- if (!ApplicationManagerBase::Activate())
- {
- return false;
- }
- return true;
- }
- bool GUIApplicationManager::PostActivate()
- {
- if (!ApplicationManagerBase::PostActivate())
- {
- m_startupErrorCollector = nullptr;
- m_startedSuccessfully = false;
- return false;
- }
- m_fileWatcher->StartWatching();
- m_startupErrorCollector = nullptr;
- return true;
- }
- void GUIApplicationManager::CreateQtApplication()
- {
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
- QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
- // Qt actually modifies the argc and argv, you must pass the real ones in as ref so it can.
- m_qApp = new QApplication(*m_frameworkApp.GetArgC(), *m_frameworkApp.GetArgV());
- }
- void GUIApplicationManager::DirectoryChanged([[maybe_unused]] QString path)
- {
- QDir projectCacheRoot;
- AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
- if (!projectCacheRoot.exists() || !projectCacheRoot.exists("assetdb.sqlite"))
- {
- // If either the Cache directory or database file has been removed, we need to restart
- QTimer::singleShot(200, this, [this]()
- {
- QMetaObject::invokeMethod(this, "Restart", Qt::QueuedConnection);
- });
- }
- }
- void GUIApplicationManager::FileChanged(QString path)
- {
- QDir projectCacheRoot;
- AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
- QString assetDbPath = projectCacheRoot.filePath("assetdb.sqlite");
- if (QString::compare(AssetUtilities::NormalizeFilePath(path), assetDbPath, Qt::CaseInsensitive) == 0)
- {
- if (!QFile::exists(assetDbPath))
- {
- // if the database file is deleted we need to restart
- QTimer::singleShot(200, this, [this]()
- {
- QMetaObject::invokeMethod(this, "Restart", Qt::QueuedConnection);
- });
- }
- }
- }
- bool GUIApplicationManager::InitApplicationServer()
- {
- m_applicationServer = new GUIApplicationServer();
- return true;
- }
- void GUIApplicationManager::InitConnectionManager()
- {
- ApplicationManagerBase::InitConnectionManager();
- using namespace std::placeholders;
- using namespace AzFramework::AssetSystem;
- using namespace AzToolsFramework::AssetSystem;
- //File Server related
- m_connectionManager->RegisterService(FileOpenRequest::MessageType, std::bind(&FileServer::ProcessOpenRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileCloseRequest::MessageType, std::bind(&FileServer::ProcessCloseRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileReadRequest::MessageType, std::bind(&FileServer::ProcessReadRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileWriteRequest::MessageType, std::bind(&FileServer::ProcessWriteRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileSeekRequest::MessageType, std::bind(&FileServer::ProcessSeekRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileTellRequest::MessageType, std::bind(&FileServer::ProcessTellRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileIsReadOnlyRequest::MessageType, std::bind(&FileServer::ProcessIsReadOnlyRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(PathIsDirectoryRequest::MessageType, std::bind(&FileServer::ProcessIsDirectoryRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileSizeRequest::MessageType, std::bind(&FileServer::ProcessSizeRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileModTimeRequest::MessageType, std::bind(&FileServer::ProcessModificationTimeRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileExistsRequest::MessageType, std::bind(&FileServer::ProcessExistsRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileFlushRequest::MessageType, std::bind(&FileServer::ProcessFlushRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(PathCreateRequest::MessageType, std::bind(&FileServer::ProcessCreatePathRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(PathDestroyRequest::MessageType, std::bind(&FileServer::ProcessDestroyPathRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileRemoveRequest::MessageType, std::bind(&FileServer::ProcessRemoveRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileCopyRequest::MessageType, std::bind(&FileServer::ProcessCopyRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileRenameRequest::MessageType, std::bind(&FileServer::ProcessRenameRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FindFilesRequest::MessageType, std::bind(&FileServer::ProcessFindFileNamesRequest, m_fileServer, _1, _2, _3, _4));
- m_connectionManager->RegisterService(FileTreeRequest::MessageType, std::bind(&FileServer::ProcessFileTreeRequest, m_fileServer, _1, _2, _3, _4));
- QObject::connect(m_connectionManager, SIGNAL(connectionAdded(uint, Connection*)), m_fileServer, SLOT(ConnectionAdded(unsigned int, Connection*)));
- QObject::connect(m_connectionManager, SIGNAL(ConnectionDisconnected(unsigned int)), m_fileServer, SLOT(ConnectionRemoved(unsigned int)));
- QObject::connect(m_fileServer, SIGNAL(AddBytesReceived(unsigned int, qint64, bool)), m_connectionManager, SLOT(AddBytesReceived(unsigned int, qint64, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddBytesSent(unsigned int, qint64, bool)), m_connectionManager, SLOT(AddBytesSent(unsigned int, qint64, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddBytesRead(unsigned int, qint64, bool)), m_connectionManager, SLOT(AddBytesRead(unsigned int, qint64, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddBytesWritten(unsigned int, qint64, bool)), m_connectionManager, SLOT(AddBytesWritten(unsigned int, qint64, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddOpenRequest(unsigned int, bool)), m_connectionManager, SLOT(AddOpenRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddCloseRequest(unsigned int, bool)), m_connectionManager, SLOT(AddCloseRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddOpened(unsigned int, bool)), m_connectionManager, SLOT(AddOpened(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddClosed(unsigned int, bool)), m_connectionManager, SLOT(AddClosed(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddReadRequest(unsigned int, bool)), m_connectionManager, SLOT(AddReadRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddWriteRequest(unsigned int, bool)), m_connectionManager, SLOT(AddWriteRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddTellRequest(unsigned int, bool)), m_connectionManager, SLOT(AddTellRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddSeekRequest(unsigned int, bool)), m_connectionManager, SLOT(AddSeekRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddIsReadOnlyRequest(unsigned int, bool)), m_connectionManager, SLOT(AddIsReadOnlyRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddIsDirectoryRequest(unsigned int, bool)), m_connectionManager, SLOT(AddIsDirectoryRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddSizeRequest(unsigned int, bool)), m_connectionManager, SLOT(AddSizeRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddModificationTimeRequest(unsigned int, bool)), m_connectionManager, SLOT(AddModificationTimeRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddExistsRequest(unsigned int, bool)), m_connectionManager, SLOT(AddExistsRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddFlushRequest(unsigned int, bool)), m_connectionManager, SLOT(AddFlushRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddCreatePathRequest(unsigned int, bool)), m_connectionManager, SLOT(AddCreatePathRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddDestroyPathRequest(unsigned int, bool)), m_connectionManager, SLOT(AddDestroyPathRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddRemoveRequest(unsigned int, bool)), m_connectionManager, SLOT(AddRemoveRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddCopyRequest(unsigned int, bool)), m_connectionManager, SLOT(AddCopyRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddRenameRequest(unsigned int, bool)), m_connectionManager, SLOT(AddRenameRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(AddFindFileNamesRequest(unsigned int, bool)), m_connectionManager, SLOT(AddFindFileNamesRequest(unsigned int, bool)));
- QObject::connect(m_fileServer, SIGNAL(UpdateConnectionMetrics()), m_connectionManager, SLOT(UpdateConnectionMetrics()));
- m_connectionManager->RegisterService(ShowAssetProcessorRequest::MessageType,
- std::bind([this](unsigned int /*connId*/, unsigned int /*type*/, unsigned int /*serial*/, QByteArray /*payload*/)
- {
- Q_EMIT ShowWindow();
- }, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)
- );
- m_connectionManager->RegisterService(ShowAssetInAssetProcessorRequest::MessageType,
- std::bind([this](unsigned int /*connId*/, unsigned int /*type*/, unsigned int /*serial*/, QByteArray payload)
- {
- ShowAssetInAssetProcessorRequest request;
- bool readFromStream = AZ::Utils::LoadObjectFromBufferInPlace(payload.data(), payload.size(), request);
- AZ_Assert(readFromStream, "GUIApplicationManager::ShowAssetInAssetProcessorRequest: Could not deserialize from stream");
- if (readFromStream)
- {
- m_mainWindow->HighlightAsset(request.m_assetPath.c_str());
- Q_EMIT ShowWindow();
- }
- }, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)
- );
- }
- void GUIApplicationManager::InitIniConfiguration()
- {
- m_iniConfiguration = new IniConfiguration();
- m_iniConfiguration->readINIConfigFile();
- m_iniConfiguration->parseCommandLine();
- }
- void GUIApplicationManager::DestroyIniConfiguration()
- {
- if (m_iniConfiguration)
- {
- delete m_iniConfiguration;
- m_iniConfiguration = nullptr;
- }
- }
- void GUIApplicationManager::InitFileServer()
- {
- m_fileServer = new FileServer();
- m_fileServer->SetSystemRoot(GetSystemRoot());
- }
- void GUIApplicationManager::DestroyFileServer()
- {
- if (m_fileServer)
- {
- delete m_fileServer;
- m_fileServer = nullptr;
- }
- }
- IniConfiguration* GUIApplicationManager::GetIniConfiguration() const
- {
- return m_iniConfiguration;
- }
- FileServer* GUIApplicationManager::GetFileServer() const
- {
- return m_fileServer;
- }
- void GUIApplicationManager::ShowTrayIconErrorMessage(QString msg)
- {
- AZStd::chrono::steady_clock::time_point currentTime = AZStd::chrono::steady_clock::now();
- if (m_trayIcon && m_mainWindow)
- {
- if((currentTime - m_timeWhenLastWarningWasShown) >= AZStd::chrono::milliseconds(s_errorMessageBoxDelay))
- {
- m_timeWhenLastWarningWasShown = currentTime;
- m_trayIcon->showMessage(
- QCoreApplication::translate("Tray Icon", "O3DE Asset Processor"),
- QCoreApplication::translate("Tray Icon", msg.toUtf8().data()),
- QSystemTrayIcon::Critical, 3000);
- }
- }
- }
- void GUIApplicationManager::QuitRequested()
- {
- m_startupErrorCollector = nullptr;
- ApplicationManagerBase::QuitRequested();
- }
- void GUIApplicationManager::ShowTrayIconMessage(QString msg)
- {
- if (m_trayIcon && m_mainWindow && !m_mainWindow->isVisible())
- {
- m_trayIcon->showMessage(
- QCoreApplication::translate("Tray Icon", "O3DE Asset Processor"),
- QCoreApplication::translate("Tray Icon", msg.toUtf8().data()),
- QSystemTrayIcon::Information, 3000);
- }
- }
- bool GUIApplicationManager::Restart()
- {
- bool launched = QProcess::startDetached(QCoreApplication::applicationFilePath(), QCoreApplication::arguments());
- if (!launched)
- {
- QMessageBox::critical(nullptr,
- QCoreApplication::translate("application", "Unable to launch Asset Processor"),
- QCoreApplication::translate("application", "Unable to launch Asset Processor"));
- }
- return launched;
- }
- void GUIApplicationManager::Reflect()
- {
- ApplicationManagerBase::Reflect();
- AZ::SerializeContext* context = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
- AZ_Assert(context, "No serialize context");
- AzToolsFramework::LogPanel::BaseLogPanel::Reflect(context);
- AssetProcessor::PlatformConfiguration::Reflect(context);
- }
- const char* GUIApplicationManager::GetLogBaseName()
- {
- return "AP_GUI";
- }
- ApplicationManager::RegistryCheckInstructions GUIApplicationManager::PopupRegistryProblemsMessage(QString warningText)
- {
- warningText = warningText.arg(tr("Click the Restart button"));
- // Doing all of this as a custom dialog because QMessageBox
- // has a fixed width, which doesn't display the extremely large
- // block of warning text well.
- QDialog dialog(nullptr, Qt::WindowCloseButtonHint | Qt::WindowTitleHint);
- dialog.setWindowTitle("Asset Processor Error");
- QVBoxLayout* layout = new QVBoxLayout(&dialog);
- layout->addSpacing(16);
- QHBoxLayout* messageLayout = new QHBoxLayout(&dialog);
- QLabel* icon = new QLabel("", &dialog);
- QPixmap errorIcon(":/stylesheet/img/lineedit-invalid.png");
- errorIcon = errorIcon.scaled(errorIcon.size() * 4);
- icon->setPixmap(errorIcon);
- icon->setMaximumSize(errorIcon.size());
- QLabel* label = new QLabel(warningText, &dialog);
- messageLayout->addWidget(icon);
- messageLayout->addSpacing(16);
- messageLayout->addWidget(label);
- layout->addLayout(messageLayout);
- layout->addSpacing(16);
- QDialogButtonBox* buttons = new QDialogButtonBox(&dialog);
- QPushButton* exitButton = buttons->addButton(tr("Exit"), QDialogButtonBox::RejectRole);
- connect(exitButton, &QPushButton::pressed, &dialog, &QDialog::reject);
- QPushButton* restartButton = buttons->addButton(tr("Restart"), QDialogButtonBox::AcceptRole);
- connect(restartButton, &QPushButton::pressed, &dialog, &QDialog::accept);
- layout->addWidget(buttons);
- if (dialog.exec() == QDialog::Accepted)
- {
- return RegistryCheckInstructions::Restart;
- }
- else
- {
- return RegistryCheckInstructions::Exit;
- }
- }
- void GUIApplicationManager::InitSourceControl()
- {
- // Look in the editor's settings for the Source Control value
- constexpr AZStd::string_view enableSourceControlKey = "/Amazon/Settings/EnableSourceControl";
- bool enableSourceControl = false;
- if (const auto* registry = AZ::SettingsRegistry::Get())
- {
- bool potentialValue;
- if (registry->Get(potentialValue, enableSourceControlKey))
- {
- enableSourceControl = AZStd::move(potentialValue);
- }
- }
- const AzFramework::CommandLine* commandLine = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine);
- if (commandLine->HasSwitch("enablescm"))
- {
- enableSourceControl = true;
- }
- AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequestBus::Events::EnableSourceControl, enableSourceControl);
- if (!enableSourceControl)
- {
- // Source control is disabled, emit the SourceControlReady signal immediately since the source control system will not emit it
- Q_EMIT SourceControlReady();
- }
- // Register the source control status request - whenever it comes in, we need to reset our source control
- // to follow that state:
- if (m_connectionManager)
- {
- auto refreshSourceControl = [](unsigned int /*connId*/, unsigned int /*type*/, unsigned int /*serial*/, QByteArray payload, QString /*platform*/)
- {
- AzFramework::AssetSystem::UpdateSourceControlStatusRequest request;
- bool readFromStream = AZ::Utils::LoadObjectFromBufferInPlace(payload.data(), payload.size(), request);
- AZ_Assert(readFromStream, "GUIApplicationManager::UpdateSourceControlStatusRequest: Could not deserialize from stream");
- if (readFromStream)
- {
- AzToolsFramework::SourceControlState state = AzToolsFramework::SourceControlState::Disabled;
- AzToolsFramework::SourceControlConnectionRequestBus::BroadcastResult(state, &AzToolsFramework::SourceControlConnectionRequestBus::Events::GetSourceControlState);
- bool wasEnabled = state != AzToolsFramework::SourceControlState::Disabled;
- bool isEnabled = request.m_sourceControlEnabled;
- if (wasEnabled != isEnabled)
- {
- AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequestBus::Events::EnableSourceControl, isEnabled);
- }
- }
- };
- m_connectionManager->RegisterService(AzFramework::AssetSystem::UpdateSourceControlStatusRequest::MessageType, refreshSourceControl);
- }
- }
- bool GUIApplicationManager::GetShouldExitOnIdle() const
- {
- bool shouldExit = false;
- const AzFramework::CommandLine* commandLine = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine);
- if (commandLine->HasSwitch("quitonidle"))
- {
- shouldExit = true;
- }
- return shouldExit;
- }
|