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)
86 if (QFontDatabase::addApplicationFont(QStringLiteral(
":/Fonts/NotoSans-Regular.ttf")) == -1) {
87 qWarning() <<
"Failed to register bundled font: NotoSans-Regular.ttf";
93 return qobject_cast<Application *>(QCoreApplication::instance());
105 done = QApplication::notify(receiver, event);
106 }
catch (
const std::exception &e) {
112ExceptionInfo Application::makeExceptionInfo(
const std::exception &e)
115 info.
what = QString::fromUtf8(e.what());
116 if (
const auto *pandaEx =
dynamic_cast<const Pandaception *
>(&e)) {
118 const char *f = pandaEx->file();
119 info.
file = f ? QString::fromUtf8(f) : QString();
120 info.
line = pandaEx->line();
133 const QWidget *parent = qobject_cast<const QWidget *>(context);
135 parent = QApplication::activeWindow();
146 auto *box =
new QMessageBox(QMessageBox::Critical, tr(
"Error!"),
147 info.
what, QMessageBox::Ok,
148 const_cast<QWidget *
>(parent));
149 box->setAttribute(Qt::WA_DeleteOnClose);
160 sentry_value_t event_ = sentry_value_new_event();
161 sentry_value_set_by_key(event_,
"level", sentry_value_new_string(
"warning"));
163 sentry_value_t exc = sentry_value_new_exception(
166 sentry_value_t mechanism = sentry_value_new_object();
167 sentry_value_set_by_key(mechanism,
"type", sentry_value_new_string(
"generic"));
168 sentry_value_set_by_key(mechanism,
"handled", sentry_value_new_bool(1));
169 if (!info.
file.isEmpty()) {
172 sentry_value_set_by_key(mechanism,
"description",
173 sentry_value_new_string(
174 QStringLiteral(
"%1:%2").arg(info.
file).arg(info.
line).toStdString().c_str()));
176 sentry_value_set_by_key(exc,
"mechanism", mechanism);
178 sentry_value_set_stacktrace(exc, NULL, 0);
179 sentry_event_add_exception(event_, exc);
180 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.