Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,61 @@
/*
* 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 <SceneAPI/SceneUI/CommonWidgets/ExpandCollapseToggler.h>
#include <QPainter>
namespace AZ
{
namespace SceneAPI
{
namespace SceneUI
{
ExpandCollapseToggler::ExpandCollapseToggler(QWidget* parent)
: QAbstractButton(parent)
, m_expandActionImage(":/SceneUI/Common/ExpandIcon.png")
, m_collapseActionImage(":/SceneUI/Common/CollapseIcon.png")
{
setCheckable(true);
connect(this, &ExpandCollapseToggler::toggled, this, &ExpandCollapseToggler::ExpandedChanged);
}
void ExpandCollapseToggler::SetExpanded(bool isExpanded)
{
setChecked(isExpanded);
}
bool ExpandCollapseToggler::IsExpanded() const
{
return isChecked();
}
const QImage* ExpandCollapseToggler::CurrentTargetImage() const
{
return IsExpanded() ? &m_collapseActionImage : &m_expandActionImage;
}
QSize ExpandCollapseToggler::sizeHint() const
{
return CurrentTargetImage()->size();
}
void ExpandCollapseToggler::paintEvent([[maybe_unused]] QPaintEvent* evt)
{
QPainter painter(this);
const QImage* target = CurrentTargetImage();
painter.drawImage(QPoint(0,0), *target);
}
} // SceneUI
} // SceneAPI
} // AZ
#include <CommonWidgets/moc_ExpandCollapseToggler.cpp>
@@ -0,0 +1,55 @@
#pragma once
/*
* 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.
*
*/
#if !defined(Q_MOC_RUN)
#include <QAbstractButton>
#include <QImage>
#include <SceneAPI/SceneUI/SceneUIConfiguration.h>
#endif
class QPaintEvent;
namespace AZ
{
namespace SceneAPI
{
namespace SceneUI
{
/**
ExpandCollapseToggler - Button that shows expand & collapse images and aliases
"checked" state & signals with "Expanded" functions & signals
**/
class SCENE_UI_API ExpandCollapseToggler : public QAbstractButton
{
Q_OBJECT
public:
explicit ExpandCollapseToggler(QWidget* parent = nullptr);
~ExpandCollapseToggler() override = default;
void SetExpanded(bool isExpanded);
bool IsExpanded() const;
signals:
void ExpandedChanged(bool isExpanded);
protected:
QSize sizeHint() const override;
void paintEvent(QPaintEvent* evt) override;
const QImage* CurrentTargetImage() const;
protected:
QImage m_expandActionImage;
QImage m_collapseActionImage;
};
} // SceneUI
} // SceneAPI
} // AZ
@@ -0,0 +1,101 @@
/*
* 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 <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> // for AssetSystemJobRequestBus
#include <AzToolsFramework/Debug/TraceContext.h>
#include <SceneAPI/SceneUI/CommonWidgets/JobWatcher.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneUI
{
const int JobWatcher::s_jobQueryInterval = 750; // ms
JobWatcher::JobWatcher(const AZStd::string& sourceAssetFullPath, Uuid traceTag)
: m_jobQueryTimer(new QTimer(this))
, m_sourceAssetFullPath(sourceAssetFullPath)
, m_traceTag(traceTag)
{
connect(m_jobQueryTimer, &QTimer::timeout, this, &JobWatcher::OnQueryJobs);
}
void JobWatcher::StartMonitoring()
{
m_jobQueryTimer->start(s_jobQueryInterval);
}
void JobWatcher::OnQueryJobs()
{
using namespace AzToolsFramework;
using namespace AzToolsFramework::AssetSystem;
AZ_TraceContext("Tag", m_traceTag);
// Query for the relevant jobs
Outcome<AssetSystem::JobInfoContainer> result = Failure();
AssetSystemJobRequestBus::BroadcastResult(result, &AssetSystemJobRequestBus::Events::GetAssetJobsInfo, m_sourceAssetFullPath, true);
if (!result.IsSuccess())
{
m_jobQueryTimer->stop();
emit JobQueryFailed("Failed to retrieve job information from Asset Processor.");
return;
}
JobInfoContainer& allJobs = result.GetValue();
if (allJobs.empty())
{
m_jobQueryTimer->stop();
emit JobQueryFailed("Queued file didn't produce any jobs.");
return;
}
bool allFinished = true;
for (const JobInfo& job : allJobs)
{
AZ_Assert(job.m_status != JobStatus::Any,
"The 'Any' status for job should be exclusive to the database and never be a result to a query.");
if (job.m_status != JobStatus::Queued && job.m_status != JobStatus::InProgress)
{
if (AZStd::find(m_reportedJobs.begin(), m_reportedJobs.end(), job.m_jobRunKey) == m_reportedJobs.end())
{
bool wasSuccessful = job.m_status == AzToolsFramework::AssetSystem::JobStatus::Completed;
Outcome<AZStd::string> logFetchResult = Failure();
AssetSystemJobRequestBus::BroadcastResult(logFetchResult, &AssetSystemJobRequestBus::Events::GetJobLog, job.m_jobRunKey);
emit JobProcessingComplete(job.m_platform, job.m_jobRunKey, wasSuccessful,
logFetchResult.IsSuccess() ? logFetchResult.GetValue() : "");
m_reportedJobs.push_back(job.m_jobRunKey);
}
}
else
{
allFinished = false;
}
}
if (allFinished)
{
m_jobQueryTimer->stop();
emit AllJobsComplete();
}
}
} // namespace SceneUI
} // namespace SceneAPI
} // namespace AZ
#include <CommonWidgets/moc_JobWatcher.cpp>
@@ -0,0 +1,66 @@
#pragma once
/*
* 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.
*
*/
#if !defined(Q_MOC_RUN)
#include <QObject>
#include <QTimer>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <SceneAPI/SceneUI/SceneUIConfiguration.h>
#endif
namespace AzToolsFramework
{
namespace AssetSystem
{
struct JobInfo;
}
}
namespace AZ
{
namespace SceneAPI
{
namespace SceneUI
{
class SCENE_UI_API JobWatcher : public QObject
{
Q_OBJECT
public:
explicit JobWatcher(const AZStd::string& sourceAssetFullPath, Uuid traceTag);
void StartMonitoring();
signals:
void JobQueryFailed(const char* message);
void JobProcessingComplete(const AZStd::string& platform, u64 jobId, bool success, const AZStd::string& fullLog);
void AllJobsComplete();
private slots:
void OnQueryJobs();
private:
static const int s_jobQueryInterval;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
AZStd::vector<u64> m_reportedJobs;
AZStd::string m_sourceAssetFullPath;
QTimer* m_jobQueryTimer;
Uuid m_traceTag;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
} // namespace SceneUI
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,40 @@
#pragma once
/*
* 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 <AzQtComponents/Components/Widgets/OverlayWidget.h>
#include <AzCore/Memory/SystemAllocator.h>
namespace AZ
{
namespace SceneAPI
{
namespace UI
{
// left in for backwards compatibility with original SceneAPI code
using OverlayWidgetButton = AzQtComponents::OverlayWidgetButton;
// left in for backwards compatibility with original SceneAPI code
using OverlayWidgetButtonList = AzQtComponents::OverlayWidgetButtonList;
// left in for backwards compatibility with original SceneAPI code
class OverlayWidget : public AzQtComponents::OverlayWidget
{
public:
AZ_CLASS_ALLOCATOR(OverlayWidget, SystemAllocator, 0)
using AzQtComponents::OverlayWidget::OverlayWidget;
};
} // namespace SceneUI
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,33 @@
#pragma once
/*
* 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 <AzQtComponents/Components/Widgets/OverlayWidgetLayer.h>
namespace AZ
{
namespace SceneAPI
{
namespace UI
{
// left in for backwards compatibility with original SceneAPI code
class OverlayWidgetLayer : public AzQtComponents::OverlayWidgetLayer
{
public:
AZ_CLASS_ALLOCATOR(OverlayWidgetLayer, SystemAllocator, 0)
using AzQtComponents::OverlayWidgetLayer::OverlayWidgetLayer;
};
} // namespace UI
} // namespace SceneAPI
} // namespace AZ
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AZ::SceneAPI::UI::OverlayWidgetLayer</class>
<widget class="QWidget" name="AZ::SceneAPI::UI::OverlayWidgetLayer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>64</width>
<height>75</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="m_center">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="m_centerLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="m_controls">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>30</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="m_controlsLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,432 @@
/*
* 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 <ctime>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Components/StyledBusyLabel.h>
#include <AzQtComponents/Components/StyledDetailsTableView.h>
#include <AzToolsFramework/Debug/TraceContextLogFormatter.h>
#include <AzToolsFramework/UI/Logging/LogEntry.h>
#include <CommonWidgets/ui_ProcessingOverlayWidget.h>
#include <SceneAPI/SceneUI/CommonWidgets/ProcessingOverlayWidget.h>
#include <SceneAPI/SceneUI/CommonWidgets/OverlayWidget.h>
#include <SceneAPI/SceneUI/Handlers/ProcessingHandlers/ProcessingHandler.h>
#include <SceneAPI/SceneUI/CommonWidgets/OverlayWidget.h>
#include <QCloseEvent>
#include <QDateTime>
#include <QLabel>
#include <QTimer>
#include <QHeaderView>
namespace AZ
{
namespace SceneAPI
{
namespace SceneUI
{
namespace Internal
{
QtWebEngineMessageFilter::QtWebEngineMessageFilter(QObject* parent)
: QSortFilterProxyModel(parent)
{
}
QtWebEngineMessageFilter::~QtWebEngineMessageFilter()
{
}
bool QtWebEngineMessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
auto tableModel = qobject_cast<AzQtComponents::StyledDetailsTableModel*>(sourceModel());
if (!tableModel)
{
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
const int sourceColumn = tableModel->GetColumnIndex(QStringLiteral("message"));
const QModelIndex index = tableModel->index(sourceRow, sourceColumn, sourceParent);
const QVariant data = tableModel->data(index);
static const QString filteredMessage = QStringLiteral("Qt WebEngine seems to be initialized from a plugin. Please set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute before constructing QGuiApplication.");
if (data.toString() == filteredMessage)
{
return false;
}
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
}
ProcessingOverlayWidget::ProcessingOverlayWidget(UI::OverlayWidget* overlay, Layout layout, Uuid traceTag)
: QWidget()
, m_traceTag(traceTag)
, ui(new Ui::ProcessingOverlayWidget())
, m_overlay(overlay)
, m_progressLabel(nullptr)
, m_layerId(UI::OverlayWidget::s_invalidOverlayIndex)
, m_isProcessingComplete(false)
, m_isClosingBlocked(false)
, m_autoCloseOnSuccess(false)
, m_encounteredIssues(false)
, m_resizeTimer(new QTimer(this))
{
ui->setupUi(this);
m_busyLabel = new AzQtComponents::StyledBusyLabel();
m_busyLabel->SetIsBusy(true);
m_busyLabel->SetBusyIconSize(14);
ui->m_header->addWidget(m_busyLabel);
m_reportModel = new AzQtComponents::StyledDetailsTableModel();
m_reportModel->AddColumn("Status", AzQtComponents::StyledDetailsTableModel::StatusIcon);
if (layout == Layout::Exporting)
{
m_reportModel->AddColumn("Platform");
}
m_reportModel->AddColumn("Message");
m_reportModel->AddColumnAlias("message", "Message");
auto messageFilterModel = new Internal::QtWebEngineMessageFilter(this);
messageFilterModel->setSourceModel(m_reportModel);
m_reportView = new AzQtComponents::StyledDetailsTableView();
m_reportView->setModel(messageFilterModel);
ui->m_reportArea->addWidget(m_reportView);
UpdateColumnSizes();
connect(m_overlay, &UI::OverlayWidget::LayerRemoved, this, &ProcessingOverlayWidget::OnLayerRemoved);
BusConnect();
m_resizeTimer->setSingleShot(true);
m_resizeTimer->setInterval(0);
connect(m_resizeTimer, &QTimer::timeout, this, &ProcessingOverlayWidget::UpdateColumnSizes);
}
ProcessingOverlayWidget::~ProcessingOverlayWidget()
{
BusDisconnect();
}
bool ProcessingOverlayWidget::OnPrintf(const char* window, const char* message)
{
if (ShouldProcessMessage())
{
AzQtComponents::StyledDetailsTableModel::TableEntry entry;
if (AzFramework::StringFunc::Find(window, "Success") != AZStd::string::npos)
{
entry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusSuccess);
}
else if (AzFramework::StringFunc::Find(window, "Warning") != AZStd::string::npos)
{
entry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusWarning);
m_encounteredIssues = true;
}
else if (AzFramework::StringFunc::Find(window, "Error") != AZStd::string::npos)
{
entry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusError);
m_encounteredIssues = true;
}
else
{
// To reduce noise in the report widget, only show success, warning and error messages.
return false;
}
entry.Add("Message", message);
CopyTraceContext(entry);
m_reportModel->AddEntry(entry);
}
return false;
}
bool ProcessingOverlayWidget::OnError(const char* /*window*/, const char* message)
{
if (ShouldProcessMessage())
{
AzQtComponents::StyledDetailsTableModel::TableEntry entry;
entry.Add("Message", message);
entry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusError);
CopyTraceContext(entry);
m_reportModel->AddEntry(entry);
m_encounteredIssues = true;
return true;
}
return false;
}
bool ProcessingOverlayWidget::OnWarning(const char* /*window*/, const char* message)
{
if (ShouldProcessMessage())
{
AzQtComponents::StyledDetailsTableModel::TableEntry entry;
entry.Add("Message", message);
entry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusWarning);
CopyTraceContext(entry);
m_reportModel->AddEntry(entry);
m_encounteredIssues = true;
return true;
}
return false;
}
bool ProcessingOverlayWidget::OnAssert(const char* message)
{
if (ShouldProcessMessage())
{
AzQtComponents::StyledDetailsTableModel::TableEntry entry;
entry.Add("Message", message);
entry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusError);
CopyTraceContext(entry);
m_reportModel->AddEntry(entry);
m_encounteredIssues = true;
// Don't return true here as assert should pop a window.
}
return false;
}
void ProcessingOverlayWidget::OnLayerRemoved(int layerId)
{
if (layerId == m_layerId)
{
delete m_progressLabel;
m_progressLabel = nullptr;
layerId = UI::OverlayWidget::s_invalidOverlayIndex;
emit Closing();
}
}
int ProcessingOverlayWidget::PushToOverlay()
{
AZ_Assert(m_layerId == UI::OverlayWidget::s_invalidOverlayIndex, "Processing overlay widget already pushed.");
if (m_layerId != UI::OverlayWidget::s_invalidOverlayIndex)
{
return m_layerId;
}
UI::OverlayWidgetButtonList buttons;
UI::OverlayWidgetButton button;
button.m_text = "Ok";
button.m_triggersPop = true;
button.m_isCloseButton = true;
button.m_enabledCheck = [this]() -> bool
{
return CanClose();
};
buttons.push_back(&button);
m_progressLabel = new QLabel("Processing...");
m_progressLabel->setAlignment(Qt::AlignCenter);
m_layerId = m_overlay->PushLayer(m_progressLabel, this, "File progress", buttons);
return m_layerId;
}
bool ProcessingOverlayWidget::GetAutoCloseOnSuccess() const
{
return m_autoCloseOnSuccess;
}
void ProcessingOverlayWidget::SetAutoCloseOnSuccess(bool closeOnComplete)
{
m_autoCloseOnSuccess = closeOnComplete;
}
bool ProcessingOverlayWidget::HasProcessingCompleted() const
{
return m_isProcessingComplete;
}
void ProcessingOverlayWidget::SetAndStartProcessingHandler(const AZStd::shared_ptr<ProcessingHandler>& handler)
{
AZ_Assert(handler, "Processing handler was null");
AZ_Assert(!m_targetHandler, "A handler has already been assigned. Only one can be active per layer at any given time.");
if (m_targetHandler)
{
return;
}
m_targetHandler = handler;
connect(m_targetHandler.get(), &ProcessingHandler::StatusMessageUpdated, this, &ProcessingOverlayWidget::OnSetStatusMessage);
connect(m_targetHandler.get(), &ProcessingHandler::AddLogEntry, this, &ProcessingOverlayWidget::AddLogEntry);
connect(m_targetHandler.get(), &ProcessingHandler::ProcessingComplete, this, &ProcessingOverlayWidget::OnProcessingComplete);
handler->BeginProcessing();
}
AZStd::shared_ptr<ProcessingHandler> ProcessingOverlayWidget::GetProcessingHandler() const
{
return m_targetHandler;
}
void ProcessingOverlayWidget::BlockClosing()
{
m_isClosingBlocked = true;
}
void ProcessingOverlayWidget::UnblockClosing()
{
m_isClosingBlocked = false;
SetUIToCompleteState();
}
void ProcessingOverlayWidget::AddLogEntry(const AzToolsFramework::Logging::LogEntry& entry)
{
if (entry.GetSeverity() == AzToolsFramework::Logging::LogEntry::Severity::Message)
{
return;
}
m_encounteredIssues = true;
bool hasStatus = false;
AzQtComponents::StyledDetailsTableModel::TableEntry reportEntry;
for (auto& field : entry.GetFields())
{
size_t offset = 0;
hasStatus = hasStatus || AzFramework::StringFunc::Equal("status", field.second.m_name.c_str());
if (AzFramework::StringFunc::Equal("message", field.second.m_name.c_str()))
{
if (field.second.m_value.length() > 2)
{
// Removing the prefixes such as "W: " and "E: ".
if (field.second.m_value[1] == ':' && field.second.m_value[2] == ' ')
{
offset = 3;
}
}
}
reportEntry.Add(field.second.m_name.c_str(), field.second.m_value.c_str() + offset);
}
if (!hasStatus)
{
if (entry.GetSeverity() == AzToolsFramework::Logging::LogEntry::Severity::Error)
{
reportEntry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusError);
}
else if (entry.GetSeverity() == AzToolsFramework::Logging::LogEntry::Severity::Warning)
{
reportEntry.Add("Status", AzQtComponents::StyledDetailsTableModel::StatusWarning);
}
}
time_t time = QDateTime::fromMSecsSinceEpoch(entry.GetRecordedTime()).toTime_t();
struct tm timeInfo;
#if defined(AZ_PLATFORM_WINDOWS)
localtime_s(&timeInfo, &time);
#else
localtime_r(&time, &timeInfo);
#endif
char buffer[128];
std::strftime(buffer, sizeof(buffer), "%H:%M:%S", &timeInfo);
reportEntry.Add("Time", buffer);
std::strftime(buffer, sizeof(buffer), "%A, %B %d, %Y", &timeInfo);
reportEntry.Add("Date", buffer);
m_reportModel->AddEntry(reportEntry);
m_resizeTimer->start();
}
void ProcessingOverlayWidget::OnProcessingComplete()
{
m_isProcessingComplete = true;
SetUIToCompleteState();
if (!m_encounteredIssues && m_autoCloseOnSuccess)
{
close();
}
else if (m_progressLabel != nullptr)
{
m_progressLabel->setText("Close the processing report to continue editing settings.");
}
}
void ProcessingOverlayWidget::OnSetStatusMessage(const AZStd::string& message)
{
m_busyLabel->SetText(message.c_str());
}
void ProcessingOverlayWidget::SetUIToCompleteState()
{
if (CanClose())
{
if (m_overlay && m_layerId != UI::OverlayWidget::s_invalidOverlayIndex)
{
m_overlay->RefreshLayer(m_layerId);
}
m_busyLabel->SetIsBusy(false);
}
}
bool ProcessingOverlayWidget::CanClose() const
{
return !m_isClosingBlocked && m_isProcessingComplete;
}
bool ProcessingOverlayWidget::ShouldProcessMessage() const
{
AZStd::shared_ptr<const AzToolsFramework::Debug::TraceContextStack> stack = m_traceStackHandler.GetCurrentStack();
if (stack)
{
for (size_t i = 0; i < stack->GetStackCount(); ++i)
{
if (stack->GetType(i) == AzToolsFramework::Debug::TraceContextStackInterface::ContentType::UuidType)
{
if (stack->GetUuidValue(i) == m_traceTag)
{
return true;
}
}
}
}
return false;
}
void ProcessingOverlayWidget::CopyTraceContext(AzQtComponents::StyledDetailsTableModel::TableEntry& entry) const
{
AZStd::shared_ptr<const AzToolsFramework::Debug::TraceContextStack> stack = m_traceStackHandler.GetCurrentStack();
if (stack)
{
AZStd::string value;
for (size_t i = 0; i < stack->GetStackCount(); ++i)
{
if (stack->GetType(i) != AzToolsFramework::Debug::TraceContextStackInterface::ContentType::UuidType)
{
const char* key = stack->GetKey(i);
AzToolsFramework::Debug::TraceContextLogFormatter::PrintValue(value, *stack, i);
entry.Add(key, value.c_str());
value.clear();
}
}
}
}
void ProcessingOverlayWidget::UpdateColumnSizes()
{
const int headerPadding = 5;
m_reportView->resizeColumnsToContents();
m_reportView->horizontalHeader()->resizeSection(0,
fontMetrics().horizontalAdvance("Status")
+ style()->pixelMetric(QStyle::PM_HeaderMarkSize) + headerPadding);
}
} // SceneUI
} // SceneAPI
} // AZ
#include <CommonWidgets/moc_ProcessingOverlayWidget.cpp>
@@ -0,0 +1,166 @@
#pragma once
/*
* 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.
*
*/
#if !defined(Q_MOC_RUN)
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <AzToolsFramework/Debug/TraceContextMultiStackHandler.h>
#include <AzQtComponents/Components/StyledDetailsTableModel.h>
#include <SceneAPI/SceneUI/SceneUIConfiguration.h>
#include <QScopedPointer>
#include <QWidget>
#include <SceneAPI/SceneUI/CommonWidgets/OverlayWidget.h>
#include <QSortFilterProxyModel>
#endif
class QCloseEvent;
class QLabel;
class QTimer;
namespace AzQtComponents
{
class StyledBusyLabel;
class StyledDetailsTableView;
}
namespace AzToolsFramework
{
namespace Logging
{
class LogEntry;
}
}
namespace AZ
{
namespace SceneAPI
{
namespace SceneUI
{
// The qt-generated ui code (from the .ui)
namespace Ui
{
class ProcessingOverlayWidget;
}
namespace Internal
{
// This QSortFilterProxyModel filters out an erroneous message.
// ResourceCompiler loads all gems. There are some gems which depend on
// EditorLib, which loads QtWebEngineWidgets. QtWebEngineWidgets prints a
// warning if it is loaded after a QCoreApplication has been instantiated,
// but no QOpenGLContext exists, which is always the case with
// ResourceCompiler.
// The correct fix would be to remove all dependencies on EditorLib from
// gems.
class QtWebEngineMessageFilter
: public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit QtWebEngineMessageFilter(QObject* parent = nullptr);
~QtWebEngineMessageFilter() override;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
};
}
class ProcessingHandler;
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
class SCENE_UI_API ProcessingOverlayWidget
: public QWidget
, public Debug::TraceMessageBus::Handler
{
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(ProcessingOverlayWidget, SystemAllocator, 0);
//! Layout configurations for the various stages the Scene Settings can be in.
enum class Layout
{
Loading,
Resetting,
Exporting
};
ProcessingOverlayWidget(UI::OverlayWidget* overlay, Layout layout, Uuid traceTag);
~ProcessingOverlayWidget() override;
bool OnPrintf(const char* window, const char* message) override;
bool OnError(const char* window, const char* message) override;
bool OnWarning(const char* window, const char* message) override;
bool OnAssert(const char* message) override;
int PushToOverlay();
void SetAndStartProcessingHandler(const AZStd::shared_ptr<ProcessingHandler>& handler);
AZStd::shared_ptr<ProcessingHandler> GetProcessingHandler() const;
bool GetAutoCloseOnSuccess() const;
void SetAutoCloseOnSuccess(bool autoCloseOnSuccess);
bool HasProcessingCompleted() const;
void BlockClosing();
void UnblockClosing();
signals:
void Closing();
public slots:
void AddLogEntry(const AzToolsFramework::Logging::LogEntry& entry);
void OnLayerRemoved(int layerId);
void OnSetStatusMessage(const AZStd::string& message);
void OnProcessingComplete();
void UpdateColumnSizes();
private:
void SetUIToCompleteState();
bool CanClose() const;
bool ShouldProcessMessage() const;
void CopyTraceContext(AzQtComponents::StyledDetailsTableModel::TableEntry& entry) const;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
AzToolsFramework::Debug::TraceContextMultiStackHandler m_traceStackHandler;
Uuid m_traceTag;
QScopedPointer<Ui::ProcessingOverlayWidget> ui;
AZStd::shared_ptr<ProcessingHandler> m_targetHandler;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
UI::OverlayWidget* m_overlay;
AzQtComponents::StyledBusyLabel* m_busyLabel;
AzQtComponents::StyledDetailsTableView* m_reportView;
AzQtComponents::StyledDetailsTableModel* m_reportModel;
QLabel* m_progressLabel;
int m_layerId;
QTimer* m_resizeTimer;
bool m_isProcessingComplete;
bool m_isClosingBlocked;
bool m_autoCloseOnSuccess;
bool m_encounteredIssues;
};
}
}
}
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AZ::SceneAPI::SceneUI::ProcessingOverlayWidget</class>
<widget class="QWidget" name="AZ::SceneAPI::SceneUI::ProcessingOverlayWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>133</width>
<height>123</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QVBoxLayout" name="m_header"/>
</item>
<item>
<layout class="QVBoxLayout" name="m_reportArea"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>