Project Manager Can Cancel Project Builds (#1694)

* Fixed misc building and project screen bugs, added ability to cancel active builds and queued builds

* Cancelling in-progress cmake build working

Signed-off-by: nggieber <nggieber@amazon.com>
This commit is contained in:
AMZN-nggieber
2021-07-01 21:53:54 -07:00
committed by GitHub
parent e6cb13f14f
commit 9758aea3d6
17 changed files with 591 additions and 342 deletions
@@ -1,244 +0,0 @@
/*
* 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 <ProjectBuilder.h>
#include <ProjectManagerDefs.h>
#include <ProjectButtonWidget.h>
#include <PythonBindingsInterface.h>
#include <QProcess>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include <QDir>
#include <QProcessEnvironment>
//#define MOCK_BUILD_PROJECT true
namespace O3DE::ProjectManager
{
// QProcess::waitForFinished uses -1 to indicate that the process should not timeout
constexpr int MaxBuildTimeMSecs = -1;
ProjectBuilderWorker::ProjectBuilderWorker(const ProjectInfo& projectInfo)
: QObject()
, m_projectInfo(projectInfo)
{
}
void ProjectBuilderWorker::BuildProject()
{
#ifdef MOCK_BUILD_PROJECT
for (int i = 0; i < 10; ++i)
{
QThread::sleep(1);
UpdateProgress(i * 10);
}
Done(m_projectPath);
#else
EngineInfo engineInfo;
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
if (engineInfoResult.IsSuccess())
{
engineInfo = engineInfoResult.GetValue();
}
else
{
emit Done(tr("Failed to get engine info."));
return;
}
// Show some kind of progress with very approximate estimates
UpdateProgress(1);
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
// Append cmake path to PATH incase it is missing
QDir cmakePath(engineInfo.m_path);
cmakePath.cd("cmake/runtime/bin");
QString pathValue = currentEnvironment.value("PATH");
pathValue += ";" + cmakePath.path();
currentEnvironment.insert("PATH", pathValue);
QProcess configProjectProcess;
configProjectProcess.setProcessChannelMode(QProcess::MergedChannels);
configProjectProcess.setWorkingDirectory(m_projectInfo.m_path);
configProjectProcess.setProcessEnvironment(currentEnvironment);
configProjectProcess.start(
"cmake",
QStringList
{
"-B",
QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix),
"-S",
m_projectInfo.m_path,
"-G",
"Visual Studio 16",
"-DLY_3RDPARTY_PATH=" + engineInfo.m_thirdPartyPath
});
if (!configProjectProcess.waitForStarted())
{
emit Done(tr("Configuring project failed to start."));
return;
}
if (!configProjectProcess.waitForFinished(MaxBuildTimeMSecs))
{
WriteErrorLog(configProjectProcess.readAllStandardOutput());
emit Done(tr("Configuring project timed out. See log for details"));
return;
}
QString configProjectOutput(configProjectProcess.readAllStandardOutput());
if (configProjectProcess.exitCode() != 0 || !configProjectOutput.contains("Generating done"))
{
WriteErrorLog(configProjectOutput);
emit Done(tr("Configuring project failed. See log for details."));
return;
}
UpdateProgress(20);
QProcess buildProjectProcess;
buildProjectProcess.setProcessChannelMode(QProcess::MergedChannels);
buildProjectProcess.setWorkingDirectory(m_projectInfo.m_path);
buildProjectProcess.setProcessEnvironment(currentEnvironment);
buildProjectProcess.start(
"cmake",
QStringList
{
"--build",
QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix),
"--target",
m_projectInfo.m_projectName + ".GameLauncher",
"Editor",
"--config",
"profile"
});
if (!buildProjectProcess.waitForStarted())
{
emit Done(tr("Building project failed to start."));
return;
}
if (!buildProjectProcess.waitForFinished(MaxBuildTimeMSecs))
{
WriteErrorLog(configProjectProcess.readAllStandardOutput());
emit Done(tr("Building project timed out. See log for details"));
return;
}
QString buildProjectOutput(buildProjectProcess.readAllStandardOutput());
if (configProjectProcess.exitCode() != 0)
{
WriteErrorLog(buildProjectOutput);
emit Done(tr("Building project failed. See log for details."));
}
else
{
emit Done("");
}
#endif
}
QString ProjectBuilderWorker::LogFilePath() const
{
QDir logFilePath(m_projectInfo.m_path);
logFilePath.cd(ProjectBuildPathPostfix);
return logFilePath.filePath(ProjectBuildErrorLogPathPostfix);
}
void ProjectBuilderWorker::WriteErrorLog(const QString& log)
{
QFile logFile(LogFilePath());
// Overwrite file with truncate
if (logFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
QTextStream output(&logFile);
output << log;
logFile.close();
}
}
ProjectBuilderController::ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent)
: QObject()
, m_projectInfo(projectInfo)
, m_projectButton(projectButton)
, m_parent(parent)
{
m_worker = new ProjectBuilderWorker(m_projectInfo);
m_worker->moveToThread(&m_workerThread);
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
connect(m_worker, &ProjectBuilderWorker::Done, this, &ProjectBuilderController::HandleResults);
connect(m_worker, &ProjectBuilderWorker::UpdateProgress, this, &ProjectBuilderController::UpdateUIProgress);
}
ProjectBuilderController::~ProjectBuilderController()
{
m_workerThread.quit();
m_workerThread.wait();
}
void ProjectBuilderController::Start()
{
m_workerThread.start();
UpdateUIProgress(0);
}
void ProjectBuilderController::SetProjectButton(ProjectButton* projectButton)
{
m_projectButton = projectButton;
}
QString ProjectBuilderController::GetProjectPath() const
{
return m_projectInfo.m_path;
}
void ProjectBuilderController::UpdateUIProgress(int progress)
{
if (m_projectButton)
{
m_projectButton->SetButtonOverlayText(QString("%1 (%2%)\n\n").arg(tr("Building Project..."), QString::number(progress)));
m_projectButton->SetProgressBarValue(progress);
}
}
void ProjectBuilderController::HandleResults(const QString& result)
{
if (!result.isEmpty())
{
if (result.contains(tr("log")))
{
QMessageBox::StandardButton openLog = QMessageBox::critical(
m_parent,
tr("Project Failed to Build!"),
result + tr("\n\nWould you like to view log?"),
QMessageBox::No | QMessageBox::Yes);
if (openLog == QMessageBox::Yes)
{
// Open application assigned to this file type
QDesktopServices::openUrl(QUrl("file:///" + m_worker->LogFilePath()));
}
}
else
{
QMessageBox::critical(m_parent, tr("Project Failed to Build!"), result);
}
}
emit Done();
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,113 @@
/*
* 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 <ProjectBuilderController.h>
#include <ProjectBuilderWorker.h>
#include <ProjectButtonWidget.h>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
namespace O3DE::ProjectManager
{
ProjectBuilderController::ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent)
: QObject()
, m_projectInfo(projectInfo)
, m_projectButton(projectButton)
, m_lastProgress(0)
, m_parent(parent)
{
m_worker = new ProjectBuilderWorker(m_projectInfo);
m_worker->moveToThread(&m_workerThread);
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
connect(m_worker, &ProjectBuilderWorker::Done, this, &ProjectBuilderController::HandleResults);
connect(m_worker, &ProjectBuilderWorker::UpdateProgress, this, &ProjectBuilderController::UpdateUIProgress);
}
ProjectBuilderController::~ProjectBuilderController()
{
m_workerThread.requestInterruption();
m_workerThread.quit();
m_workerThread.wait();
}
void ProjectBuilderController::Start()
{
m_workerThread.start();
UpdateUIProgress(0);
}
void ProjectBuilderController::SetProjectButton(ProjectButton* projectButton)
{
m_projectButton = projectButton;
if (projectButton)
{
projectButton->SetProjectButtonAction(tr("Cancel Build"), [this] { HandleCancel(); });
if (m_lastProgress != 0)
{
UpdateUIProgress(m_lastProgress);
}
}
}
const ProjectInfo& ProjectBuilderController::GetProjectInfo() const
{
return m_projectInfo;
}
void ProjectBuilderController::UpdateUIProgress(int progress)
{
m_lastProgress = progress;
if (m_projectButton)
{
m_projectButton->SetButtonOverlayText(QString("%1 (%2%)\n\n").arg(tr("Building Project..."), QString::number(progress)));
m_projectButton->SetProgressBarValue(progress);
}
}
void ProjectBuilderController::HandleResults(const QString& result)
{
if (!result.isEmpty())
{
if (result.contains(tr("log")))
{
QMessageBox::StandardButton openLog = QMessageBox::critical(
m_parent,
tr("Project Failed to Build!"),
result + tr("\n\nWould you like to view log?"),
QMessageBox::No | QMessageBox::Yes);
if (openLog == QMessageBox::Yes)
{
// Open application assigned to this file type
QDesktopServices::openUrl(QUrl("file:///" + m_worker->GetLogFilePath()));
}
}
else
{
QMessageBox::critical(m_parent, tr("Project Failed to Build!"), result);
}
emit Done(false);
return;
}
emit Done(true);
}
void ProjectBuilderController::HandleCancel()
{
m_workerThread.quit();
emit Done(false);
}
} // namespace O3DE::ProjectManager
@@ -12,32 +12,12 @@
#include <QThread>
#endif
QT_FORWARD_DECLARE_CLASS(QProcess)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(ProjectButton)
class ProjectBuilderWorker : public QObject
{
Q_OBJECT
public:
explicit ProjectBuilderWorker(const ProjectInfo& projectInfo);
~ProjectBuilderWorker() = default;
QString LogFilePath() const;
public slots:
void BuildProject();
signals:
void UpdateProgress(int progress);
void Done(QString result);
private:
void WriteErrorLog(const QString& log);
ProjectInfo m_projectInfo;
};
QT_FORWARD_DECLARE_CLASS(ProjectBuilderWorker)
class ProjectBuilderController : public QObject
{
@@ -48,15 +28,16 @@ namespace O3DE::ProjectManager
~ProjectBuilderController();
void SetProjectButton(ProjectButton* projectButton);
QString GetProjectPath() const;
const ProjectInfo& GetProjectInfo() const;
public slots:
void Start();
void UpdateUIProgress(int progress);
void HandleResults(const QString& result);
void HandleCancel();
signals:
void Done();
void Done(bool success = true);
private:
ProjectInfo m_projectInfo;
@@ -64,5 +45,7 @@ namespace O3DE::ProjectManager
QThread m_workerThread;
ProjectButton* m_projectButton;
QWidget* m_parent;
int m_lastProgress;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,71 @@
/*
* 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 <ProjectBuilderWorker.h>
#include <ProjectManagerDefs.h>
#include <QDir>
//#define MOCK_BUILD_PROJECT true
namespace O3DE::ProjectManager
{
const QString ProjectBuilderWorker::BuildCancelled = ProjectBuilderWorker::tr("Build Cancelled.");
ProjectBuilderWorker::ProjectBuilderWorker(const ProjectInfo& projectInfo)
: QObject()
, m_projectInfo(projectInfo)
, m_progressEstimate(0)
{
}
void ProjectBuilderWorker::BuildProject()
{
#ifdef MOCK_BUILD_PROJECT
for (int i = 0; i < 10; ++i)
{
QThread::sleep(1);
UpdateProgress(i * 10);
}
Done("");
#else
auto result = BuildProjectForPlatform();
if (result.IsSuccess())
{
emit Done();
}
else
{
emit Done(result.GetError());
}
#endif
}
QString ProjectBuilderWorker::GetLogFilePath() const
{
QDir logFilePath(m_projectInfo.m_path);
// Make directories if they aren't on disk
if (!logFilePath.cd(ProjectBuildPathPostfix))
{
logFilePath.mkpath(ProjectBuildPathPostfix);
logFilePath.cd(ProjectBuildPathPostfix);
}
if (!logFilePath.cd(ProjectBuildPathCmakeFiles))
{
logFilePath.mkpath(ProjectBuildPathCmakeFiles);
logFilePath.cd(ProjectBuildPathCmakeFiles);
}
return logFilePath.filePath(ProjectBuildErrorLogName);
}
void ProjectBuilderWorker::QStringToAZTracePrint(const QString& error)
{
AZ_TracePrintf("Project Manager", error.toStdString().c_str());
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,52 @@
/*
* 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
#if !defined(Q_MOC_RUN)
#include <ProjectInfo.h>
#include <AzCore/Outcome/Outcome.h>
#include <QObject>
#endif
QT_FORWARD_DECLARE_CLASS(QProcess)
namespace O3DE::ProjectManager
{
class ProjectBuilderWorker : public QObject
{
// QProcess::waitForFinished uses -1 to indicate that the process should not timeout
static constexpr int MaxBuildTimeMSecs = -1;
// Build was cancelled
static const QString BuildCancelled;
Q_OBJECT
public:
explicit ProjectBuilderWorker(const ProjectInfo& projectInfo);
~ProjectBuilderWorker() = default;
QString GetLogFilePath() const;
public slots:
void BuildProject();
signals:
void UpdateProgress(int progress);
void Done(QString result = "");
private:
AZ::Outcome<void, QString> BuildProjectForPlatform();
void QStringToAZTracePrint(const QString& error);
QProcess* m_configProjectProcess = nullptr;
QProcess* m_buildProjectProcess = nullptr;
ProjectInfo m_projectInfo;
int m_progressEstimate;
};
} // namespace O3DE::ProjectManager
@@ -40,8 +40,8 @@ namespace O3DE::ProjectManager
m_overlayLabel->setVisible(false);
vLayout->addWidget(m_overlayLabel);
m_buildButton = new QPushButton(tr("Build Project"), this);
m_buildButton->setVisible(false);
m_actionButton = new QPushButton(tr("Project Action"), this);
m_actionButton->setVisible(false);
m_progressBar = new QProgressBar(this);
m_progressBar->setObjectName("labelButtonProgressBar");
@@ -78,9 +78,9 @@ namespace O3DE::ProjectManager
return m_progressBar;
}
QPushButton* LabelButton::GetBuildButton()
QPushButton* LabelButton::GetActionButton()
{
return m_buildButton;
return m_actionButton;
}
ProjectButton::ProjectButton(const ProjectInfo& projectInfo, QWidget* parent, bool processing)
@@ -135,7 +135,6 @@ namespace O3DE::ProjectManager
void ProjectButton::ProcessingSetup()
{
m_projectImageLabel->GetOverlayLabel()->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
m_projectImageLabel->SetEnabled(false);
m_projectImageLabel->SetOverlayText(tr("Processing...\n\n"));
@@ -146,8 +145,6 @@ namespace O3DE::ProjectManager
void ProjectButton::ReadySetup()
{
connect(m_projectImageLabel->GetBuildButton(), &QPushButton::clicked, [this](){ emit BuildProject(m_projectInfo); });
QMenu* menu = new QMenu(this);
menu->addAction(tr("Edit Project Settings..."), this, [this]() { emit EditProject(m_projectInfo.m_path); });
menu->addAction(tr("Build"), this, [this]() { emit BuildProject(m_projectInfo); });
@@ -168,20 +165,40 @@ namespace O3DE::ProjectManager
m_projectFooter->layout()->addWidget(projectMenuButton);
}
void ProjectButton::SetProjectButtonAction(const QString& text, AZStd::function<void()> lambda)
{
QPushButton* projectActionButton = m_projectImageLabel->GetActionButton();
if (!m_actionButtonConnection)
{
QSpacerItem* buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
m_projectImageLabel->layout()->addItem(buttonSpacer);
m_projectImageLabel->layout()->addWidget(projectActionButton);
projectActionButton->setVisible(true);
}
else
{
disconnect(m_actionButtonConnection);
}
projectActionButton->setText(text);
m_actionButtonConnection = connect(projectActionButton, &QPushButton::clicked, lambda);
}
void ProjectButton::SetProjectBuildButtonAction()
{
SetProjectButtonAction(tr("Build Project"), [this]() { emit BuildProject(m_projectInfo); });
}
void ProjectButton::BuildThisProject()
{
emit BuildProject(m_projectInfo);
}
void ProjectButton::SetLaunchButtonEnabled(bool enabled)
{
m_projectImageLabel->SetEnabled(enabled);
}
void ProjectButton::ShowBuildButton(bool show)
{
QSpacerItem* buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
m_projectImageLabel->layout()->addItem(buttonSpacer);
m_projectImageLabel->layout()->addWidget(m_projectImageLabel->GetBuildButton());
m_projectImageLabel->GetBuildButton()->setVisible(show);
}
void ProjectButton::SetButtonOverlayText(const QString& text)
{
m_projectImageLabel->SetOverlayText(text);
@@ -191,4 +208,9 @@ namespace O3DE::ProjectManager
{
m_projectImageLabel->GetProgressBar()->setValue(progress);
}
LabelButton* ProjectButton::GetLabelButton()
{
return m_projectImageLabel;
}
} // namespace O3DE::ProjectManager
@@ -9,12 +9,15 @@
#if !defined(Q_MOC_RUN)
#include <ProjectInfo.h>
#include <AzCore/std/functional.h>
#include <QLabel>
#include <QPushButton>
#include <QSpacerItem>
#include <QLayout>
#endif
QT_FORWARD_DECLARE_CLASS(QPixmap)
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QProgressBar)
@@ -34,7 +37,7 @@ namespace O3DE::ProjectManager
QLabel* GetOverlayLabel();
QProgressBar* GetProgressBar();
QPushButton* GetBuildButton();
QPushButton* GetActionButton();
signals:
void triggered();
@@ -45,7 +48,7 @@ namespace O3DE::ProjectManager
private:
QLabel* m_overlayLabel;
QProgressBar* m_progressBar;
QPushButton* m_buildButton;
QPushButton* m_actionButton;
bool m_enabled = true;
};
@@ -58,10 +61,13 @@ namespace O3DE::ProjectManager
explicit ProjectButton(const ProjectInfo& m_projectInfo, QWidget* parent = nullptr, bool processing = false);
~ProjectButton() = default;
void SetProjectButtonAction(const QString& text, AZStd::function<void()> lambda);
void SetProjectBuildButtonAction();
void SetLaunchButtonEnabled(bool enabled);
void ShowBuildButton(bool show);
void SetButtonOverlayText(const QString& text);
void SetProgressBarValue(int progress);
LabelButton* GetLabelButton();
signals:
void OpenProject(const QString& projectName);
@@ -75,9 +81,12 @@ namespace O3DE::ProjectManager
void BaseSetup();
void ProcessingSetup();
void ReadySetup();
void BuildThisProject();
ProjectInfo m_projectInfo;
LabelButton* m_projectImageLabel;
QFrame* m_projectFooter;
QMetaObject::Connection m_actionButtonConnection;
};
} // namespace O3DE::ProjectManager
@@ -14,6 +14,7 @@ namespace O3DE::ProjectManager
inline constexpr static int ProjectPreviewImageHeight = 280;
static const QString ProjectBuildPathPostfix = "build/windows_vs2019";
static const QString ProjectBuildErrorLogPathPostfix = "CMakeFiles/CMakeProjectBuildError.log";
static const QString ProjectBuildPathCmakeFiles = "CMakeFiles";
static const QString ProjectBuildErrorLogName = "CMakeProjectBuildError.log";
static const QString ProjectPreviewImagePath = "preview.png";
} // namespace O3DE::ProjectManager
@@ -11,7 +11,7 @@
#include <ProjectButtonWidget.h>
#include <PythonBindingsInterface.h>
#include <ProjectUtils.h>
#include <ProjectBuilder.h>
#include <ProjectBuilderController.h>
#include <ScreensCtrl.h>
#include <AzQtComponents/Components/FlowLayout.h>
@@ -43,8 +43,6 @@
#include <QDir>
#include <QGuiApplication>
//#define DISPLAY_PROJECT_DEV_DATA true
namespace O3DE::ProjectManager
{
ProjectsScreen::ProjectsScreen(QWidget* parent)
@@ -164,43 +162,38 @@ namespace O3DE::ProjectManager
projectsScrollArea->setWidget(scrollWidget);
projectsScrollArea->setWidgetResizable(true);
#ifndef DISPLAY_PROJECT_DEV_DATA
// Iterate once to insert building project first
if (!buildProjectPath.isEmpty())
QVector<ProjectInfo> nonProcessingProjects;
buildProjectPath = QDir::fromNativeSeparators(buildProjectPath);
for (auto& project : projectsResult.GetValue())
{
buildProjectPath = QDir::fromNativeSeparators(buildProjectPath);
for (auto project : projectsResult.GetValue())
if (projectButton && !*projectButton)
{
if (QDir::fromNativeSeparators(project.m_path) == buildProjectPath)
{
ProjectButton* buildingProjectButton = CreateProjectButton(project, flowLayout, true);
if (projectButton)
{
*projectButton = buildingProjectButton;
}
break;
*projectButton = CreateProjectButton(project, flowLayout, true);
continue;
}
}
nonProcessingProjects.append(project);
}
for (auto project : projectsResult.GetValue())
#else
ProjectInfo project = projectsResult.GetValue().at(0);
for (int i = 0; i < 15; i++)
#endif
for (auto& project : nonProcessingProjects)
{
// Add all other projects skipping building project
// Safe if no building project because it is just an empty string
if (project.m_path != buildProjectPath)
{
ProjectButton* projectButtonWidget = CreateProjectButton(project, flowLayout);
ProjectButton* projectButtonWidget = CreateProjectButton(project, flowLayout);
if (RequiresBuildProjectIterator(project.m_path) != m_requiresBuild.end())
{
projectButtonWidget->ShowBuildButton(true);
}
if (BuildQueueContainsProject(project.m_path))
{
projectButtonWidget->SetProjectButtonAction(tr("Cancel Queued Build"),
[this, project]
{
UnqueueBuildProject(project);
SuggestBuildProjectMsg(project, false);
});
}
else if (RequiresBuildProjectIterator(project.m_path) != m_requiresBuild.end())
{
projectButtonWidget->SetProjectBuildButtonAction();
}
}
@@ -242,9 +235,9 @@ namespace O3DE::ProjectManager
// Make sure to update builder with latest Project Button
if (m_currentBuilder)
{
ProjectButton* projectButtonPtr;
ProjectButton* projectButtonPtr = nullptr;
m_projectsContent = CreateProjectsContent(m_currentBuilder->GetProjectPath(), &projectButtonPtr);
m_projectsContent = CreateProjectsContent(m_currentBuilder->GetProjectInfo().m_path, &projectButtonPtr);
m_currentBuilder->SetProjectButton(projectButtonPtr);
}
else
@@ -412,17 +405,15 @@ namespace O3DE::ProjectManager
}
}
void ProjectsScreen::SuggestBuildProject(const ProjectInfo& projectInfo)
void ProjectsScreen::SuggestBuildProjectMsg(const ProjectInfo& projectInfo, bool showMessage)
{
if (projectInfo.m_needsBuild)
if (RequiresBuildProjectIterator(projectInfo.m_path) == m_requiresBuild.end())
{
if (RequiresBuildProjectIterator(projectInfo.m_path) == m_requiresBuild.end())
{
m_requiresBuild.append(projectInfo);
}
ResetProjectsContent();
m_requiresBuild.append(projectInfo);
}
else
ResetProjectsContent();
if (showMessage)
{
QMessageBox::information(this,
tr("Project Should be rebuilt."),
@@ -430,6 +421,11 @@ namespace O3DE::ProjectManager
}
}
void ProjectsScreen::SuggestBuildProject(const ProjectInfo& projectInfo)
{
SuggestBuildProjectMsg(projectInfo, true);
}
void ProjectsScreen::QueueBuildProject(const ProjectInfo& projectInfo)
{
auto requiredIter = RequiresBuildProjectIterator(projectInfo.m_path);
@@ -443,14 +439,22 @@ namespace O3DE::ProjectManager
if (m_buildQueue.empty() && !m_currentBuilder)
{
StartProjectBuild(projectInfo);
// Projects Content is already reset in fuction
}
else
{
m_buildQueue.append(projectInfo);
ResetProjectsContent();
}
}
}
void ProjectsScreen::UnqueueBuildProject(const ProjectInfo& projectInfo)
{
m_buildQueue.removeAll(projectInfo);
ResetProjectsContent();
}
void ProjectsScreen::NotifyCurrentScreen()
{
if (ShouldDisplayFirstTimeContent())
@@ -481,7 +485,7 @@ namespace O3DE::ProjectManager
return displayFirstTimeContent;
}
void ProjectsScreen::StartProjectBuild(const ProjectInfo& projectInfo)
bool ProjectsScreen::StartProjectBuild(const ProjectInfo& projectInfo)
{
if (ProjectUtils::IsVS2019Installed())
{
@@ -501,25 +505,42 @@ namespace O3DE::ProjectManager
}
else
{
ProjectBuildDone();
SuggestBuildProjectMsg(projectInfo, false);
return false;
}
return true;
}
return false;
}
void ProjectsScreen::ProjectBuildDone()
void ProjectsScreen::ProjectBuildDone(bool success)
{
ProjectInfo currentBuilderProject;
if (!success)
{
currentBuilderProject = m_currentBuilder->GetProjectInfo();
}
delete m_currentBuilder;
m_currentBuilder = nullptr;
if (!success)
{
SuggestBuildProjectMsg(currentBuilderProject, false);
}
if (!m_buildQueue.empty())
{
StartProjectBuild(m_buildQueue.front());
while (!StartProjectBuild(m_buildQueue.front()) && m_buildQueue.size() > 1)
{
m_buildQueue.pop_front();
}
m_buildQueue.pop_front();
}
else
{
ResetProjectsContent();
}
ResetProjectsContent();
}
QList<ProjectInfo>::iterator ProjectsScreen::RequiresBuildProjectIterator(const QString& projectPath)
@@ -37,7 +37,7 @@ namespace O3DE::ProjectManager
protected:
void NotifyCurrentScreen() override;
void ProjectBuildDone();
void SuggestBuildProjectMsg(const ProjectInfo& projectInfo, bool showMessage);
protected slots:
void HandleNewProjectButton();
@@ -50,6 +50,9 @@ namespace O3DE::ProjectManager
void SuggestBuildProject(const ProjectInfo& projectInfo);
void QueueBuildProject(const ProjectInfo& projectInfo);
void UnqueueBuildProject(const ProjectInfo& projectInfo);
void ProjectBuildDone(bool success = true);
void paintEvent(QPaintEvent* event) override;
@@ -60,7 +63,7 @@ namespace O3DE::ProjectManager
void ResetProjectsContent();
bool ShouldDisplayFirstTimeContent();
void StartProjectBuild(const ProjectInfo& projectInfo);
bool StartProjectBuild(const ProjectInfo& projectInfo);
QList<ProjectInfo>::iterator RequiresBuildProjectIterator(const QString& projectPath);
bool BuildQueueContainsProject(const QString& projectPath);
bool WarnIfInBuildQueue(const QString& projectPath);