8#include <QElapsedTimer>
9#include <QFontDatabase>
16#include "thirdparty/sentry/include/sentry.h"
30constexpr std::array kSentryDenyPatterns {
35 "One or more items was not found on the scene",
36 "One or more elements was not found on the scene",
37 "One or more elements were not found on scene",
43bool shouldSendToSentry(
const QString &message)
49 static QString lastMessage;
50 static QElapsedTimer timer;
53 QMutexLocker lock(&mutex);
55 constexpr qint64 cooldownMs = 5000;
57 if (message == lastMessage && timer.isValid() && timer.elapsed() < cooldownMs) {
61 lastMessage = message;
71 for (
const auto *pattern : kSentryDenyPatterns) {
72 if (message.contains(QLatin1String(pattern))) {
80 : QApplication(argc, argv)
90 if (QFontDatabase::addApplicationFont(QStringLiteral(
":/Fonts/NotoSans-Regular.ttf")) == -1) {
91 qWarning() <<
"Failed to register bundled font: NotoSans-Regular.ttf";
97 return qobject_cast<Application *>(QCoreApplication::instance());
109 done = QApplication::notify(receiver, event);
110 }
catch (
const std::exception &e) {
116ExceptionInfo Application::makeExceptionInfo(
const std::exception &e)
119 info.
what = QString::fromUtf8(e.what());
120 if (
const auto *pandaEx =
dynamic_cast<const Pandaception *
>(&e)) {
122 const char *f = pandaEx->file();
123 info.
file = f ? QString::fromUtf8(f) : QString();
124 info.
line = pandaEx->line();
137 const QWidget *parent = qobject_cast<const QWidget *>(context);
139 parent = QApplication::activeWindow();
150 auto *box =
new QMessageBox(QMessageBox::Critical, tr(
"Error!"), info.
what, QMessageBox::Ok,
const_cast<QWidget *
>(parent));
151 box->setAttribute(Qt::WA_DeleteOnClose);
162 sentry_value_t event_ = sentry_value_new_event();
163 sentry_value_set_by_key(event_,
"level", sentry_value_new_string(
"warning"));
165 sentry_value_t exc = sentry_value_new_exception(
168 sentry_value_t mechanism = sentry_value_new_object();
169 sentry_value_set_by_key(mechanism,
"type", sentry_value_new_string(
"generic"));
170 sentry_value_set_by_key(mechanism,
"handled", sentry_value_new_bool(1));
171 if (!info.
file.isEmpty()) {
174 sentry_value_set_by_key(mechanism,
"description",
175 sentry_value_new_string(
176 QStringLiteral(
"%1:%2").arg(info.
file).arg(info.
line).toStdString().c_str()));
178 sentry_value_set_by_key(exc,
"mechanism", mechanism);
180 sentry_value_set_stacktrace(exc, NULL, 0);
181 sentry_event_add_exception(event_, exc);
182 sentry_capture_event(event_);
Custom QApplication subclass with exception handling and main-window access.
Common logging utilities, the Pandaception error type, and helper macros.
static bool isSentryDenyMessage(const QString &message)
bool notify(QObject *receiver, QEvent *event) override
Application(int &argc, char **argv)
Constructs the application with command-line arguments.
static Application * instance()
Returns the application instance cast to Application*.
static void handleException(const ExceptionInfo &info, const QObject *context)
Centralised exception-reporting handler used by both Application::notify (defence-in-depth on Linux/W...
static bool interactiveMode
Exception type for user-facing circuit errors.
Value-captured exception details safe to forward across an event-loop boundary.
QString what
The translated message for QMessageBox display.
QString englishMessage
English message for Sentry; equals what for non-Pandaception types.
QString file
Throw-site file when the exception is a Pandaception, else empty.
int line
Throw-site line when the exception is a Pandaception, else 0.