123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- /*
- * 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 "EditorDefs.h"
- #include "StartupTraceHandler.h"
- // Qt
- #include <QMessageBox>
- // AzCore
- #include <AzCore/Component/TickBus.h>
- // AzToolsFramework
- #include <AzToolsFramework/API/ToolsApplicationAPI.h>
- // Editor
- #include "ErrorDialog.h"
- namespace SandboxEditor
- {
- StartupTraceHandler::StartupTraceHandler()
- {
- ConnectToMessageBus();
- }
- StartupTraceHandler::~StartupTraceHandler()
- {
- EndCollectionAndShowCollectedErrors();
- DisconnectFromMessageBus();
- }
- bool StartupTraceHandler::OnPreAssert(const char* fileName, int line, const char* func, const char* message)
- {
- AZ_UNUSED(fileName);
- AZ_UNUSED(line);
- AZ_UNUSED(func);
- AZ_UNUSED(message);
- // Return false so other listeners can handle this. The StartupTraceHandler won't report messages
- // will probably crash before that occurs, because this is an assert.
- return false;
- }
- bool StartupTraceHandler::OnException(const char* message)
- {
- // Exceptions are more fatal than errors, and need to be displayed right away.
- // After the exception occurs, nothing else may be functional enough to collect and display messages.
- OnMessage(message, nullptr, MessageDisplayBehavior::AlwaysShow);
- // Return false so other listeners can handle this. The StartupTraceHandler won't report messages
- // until the next time the main thread updates the system tick bus function queue. The editor
- // will probably crash before that occurs, because this is an exception.
- return false;
- }
- bool StartupTraceHandler::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message)
- {
- // If a collection is not active, then show this error. Otherwise, collect it
- // and show it with other occurs that occured in the operation.
- return OnMessage(message, &m_errors, MessageDisplayBehavior::ShowWhenNotCollecting);
- }
- bool StartupTraceHandler::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message)
- {
- // Only track warnings if messages are being collected.
- return OnMessage(message, &m_warnings, MessageDisplayBehavior::OnlyCollect);
- }
- bool StartupTraceHandler::OnMessage(
- const char *message,
- AZStd::list<QString>* messageList,
- MessageDisplayBehavior messageDisplayBehavior)
- {
- if (m_isCollecting && messageList)
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
- messageList->push_back(QString(message));
- return true;
- }
- if ((!m_isCollecting && messageDisplayBehavior == MessageDisplayBehavior::ShowWhenNotCollecting) ||
- messageDisplayBehavior == MessageDisplayBehavior::AlwaysShow)
- {
- ShowMessageBox(message);
- return true;
- }
- return false;
- }
- void StartupTraceHandler::StartCollection()
- {
- ConnectToMessageBus();
- if (m_isCollecting)
- {
- EndCollectionAndShowCollectedErrors();
- }
- m_isCollecting = true;
- }
- void StartupTraceHandler::EndCollectionAndShowCollectedErrors()
- {
- AZStd::list<QString> cachedWarnings;
- AZStd::list<QString> cachedErrors;
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
- m_isCollecting = false;
- if (m_warnings.size() == 0 && m_errors.size() == 0)
- {
- return;
- }
- if (m_warnings.size() > 0)
- {
- cachedWarnings.splice(cachedWarnings.end(), m_warnings);
- }
- if (m_errors.size() > 0)
- {
- cachedErrors.splice(cachedErrors.end(), m_errors);
- }
- }
- if (m_showWindow)
- {
- AZ::SystemTickBus::QueueFunction([cachedWarnings, cachedErrors]()
- {
- // Parent to the main window, so that the error dialog doesn't
- // show up as a separate window when alt-tabbing.
- QWidget* mainWindow = nullptr;
- AzToolsFramework::EditorRequests::Bus::BroadcastResult(
- mainWindow,
- &AzToolsFramework::EditorRequests::Bus::Events::GetMainWindow);
- ErrorDialog* errorDialog = new ErrorDialog(mainWindow);
- errorDialog->AddMessages(
- SandboxEditor::ErrorDialog::MessageType::Warning,
- cachedWarnings);
- errorDialog->AddMessages(
- SandboxEditor::ErrorDialog::MessageType::Error,
- cachedErrors);
- // Use open() instead of exec() here so that we still achieve the modal dialog functionality without
- // blocking the event queue
- errorDialog->setAttribute(Qt::WA_DeleteOnClose, true);
- errorDialog->open();
- });
- }
- }
- void StartupTraceHandler::ShowMessageBox(const QString& message)
- {
- AZ::SystemTickBus::QueueFunction([message]()
- {
- // Parent to the main window, so that the error dialog doesn't
- // show up as a separate window when alt-tabbing.
- QWidget* mainWindow = nullptr;
- AzToolsFramework::EditorRequests::Bus::BroadcastResult(
- mainWindow,
- &AzToolsFramework::EditorRequests::Bus::Events::GetMainWindow);
- QMessageBox* msg = new QMessageBox(
- QMessageBox::Critical,
- QObject::tr("Error"),
- message,
- QMessageBox::Ok,
- mainWindow);
- msg->setTextInteractionFlags(Qt::TextSelectableByMouse);
- // Use open() instead of exec() here so that we still achieve the modal dialog functionality without
- // blocking the event queue
- msg->setAttribute(Qt::WA_DeleteOnClose, true);
- msg->open();
- });
- }
- void StartupTraceHandler::ConnectToMessageBus()
- {
- AZ::Debug::TraceMessageBus::Handler::BusConnect();
- }
- void StartupTraceHandler::DisconnectFromMessageBus()
- {
- AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
- }
- bool StartupTraceHandler::IsConnectedToMessageBus() const
- {
- return AZ::Debug::TraceMessageBus::Handler::BusIsConnected();
- }
- }
|