Skip to content
Extraits de code Groupes Projets
Vérifiée Valider a653603f rédigé par Kubat's avatar Kubat
Parcourir les fichiers

UI: Avoid the segfault on MainWindow destruction

We destroy the log console before the final flush, take that into
account => disable handle message for the ConsoleLogSinkDispatcher if
the corresponding LogConsole was destroyed.

This is a quick and dirty solution, but I don't know any other way for
now!
parent 19c48a8c
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!21Add clean logs support + dependent MR
......@@ -197,13 +197,6 @@ public:
return dispatch;
}
template <Derived<LogSinkDispatcher> DispatcherType, typename... Args>
DispatcherType *newUnmanagedDispatcher(Args &&...args) noexcept
{
DispatcherType *dispatch = new DispatcherType(std::forward<Args>(args)...);
return dispatch;
}
std::shared_ptr<Logger> newLogger(const StringType auto &category) noexcept
{
std::shared_ptr<Logger> logger = std::make_shared<Logger>(this, category);
......
......@@ -2,9 +2,29 @@
using namespace Vivy;
ConsoleLogSinkDispatcher::ConsoleLogSinkDispatcher(QWidget *parent) noexcept
ConsoleLogSinkDispatcher::ConsoleLogSinkDispatcher() noexcept
: LogSinkDispatcher(std::string_view{ "console" })
, QListWidget(parent)
{
}
void
ConsoleLogSinkDispatcher::handleLogMessage(const std::string_view strv,
const LogMessage &msg) noexcept
{
if (console)
console->handleLogMessage(strv, msg);
}
void
ConsoleLogSinkDispatcher::attachLogConsole(LogConsole *widget) noexcept
{
console = widget;
if (widget)
widget->setDispatcher(shared_from_this());
}
LogConsole::LogConsole(QWidget *parent) noexcept
: QListWidget(parent)
{
setSortingEnabled(false);
setSelectionMode(QAbstractItemView::NoSelection);
......@@ -13,8 +33,24 @@ ConsoleLogSinkDispatcher::ConsoleLogSinkDispatcher(QWidget *parent) noexcept
setStyleSheet(style);
}
LogConsole::~LogConsole() noexcept
{
if (auto parentDispatcher = dispatcher.lock()) {
qDebug() << "Reset parent LogConsole pointer";
parentDispatcher->attachLogConsole(nullptr);
} else {
qCritical() << "Failed to reset LogConsole from parent";
}
}
void
ConsoleLogSinkDispatcher::setMessageCountLimit(int limit)
LogConsole::setDispatcher(std::shared_ptr<ConsoleLogSinkDispatcher> ptr) noexcept
{
dispatcher = std::weak_ptr<ConsoleLogSinkDispatcher>(ptr);
}
void
LogConsole::setMessageCountLimit(int limit)
{
if (limit <= 0)
throw std::logic_error("Can't pass a negative count!");
......@@ -22,8 +58,7 @@ ConsoleLogSinkDispatcher::setMessageCountLimit(int limit)
}
void
ConsoleLogSinkDispatcher::handleLogMessage(const std::string_view cat,
const LogMessage &msg) noexcept
LogConsole::handleLogMessage(const std::string_view cat, const LogMessage &msg) noexcept
{
while (count() >= messageLimit) {
QListWidgetItem *itemWidget = item(0);
......
......@@ -5,15 +5,42 @@
namespace Vivy
{
class ConsoleLogSinkDispatcher final : public LogSinkDispatcher, public QListWidget {
VIVY_UNMOVABLE_OBJECT(ConsoleLogSinkDispatcher)
class LogConsole;
class ConsoleLogSinkDispatcher;
class LogConsole final : public QListWidget {
VIVY_UNMOVABLE_OBJECT(LogConsole)
int messageLimit{ 1'000 };
std::weak_ptr<ConsoleLogSinkDispatcher> dispatcher;
public:
explicit ConsoleLogSinkDispatcher(QWidget *parent = nullptr) noexcept;
void handleLogMessage(const std::string_view, const LogMessage &) noexcept override;
LogConsole(QWidget *parent = nullptr) noexcept;
~LogConsole() noexcept override;
void setMessageCountLimit(int limit);
void handleLogMessage(const std::string_view, const LogMessage &) noexcept;
// Hacky boi to set the `LogConsole *` in the dispatcher to nullptr when
// the `LogConsole` is destroyed.
void setDispatcher(std::shared_ptr<ConsoleLogSinkDispatcher> ptr) noexcept;
};
// Log console dispatcher, this is a proxy for the LogConsole which is the real
// widget, we don't directly set the dispatcher being the widget because the
// QDockWidget will demete its child on destruction, but the dispatcher is
// already managed by the std::shared_ptr...
class ConsoleLogSinkDispatcher final
: public LogSinkDispatcher,
public std::enable_shared_from_this<ConsoleLogSinkDispatcher> {
VIVY_UNMOVABLE_OBJECT(ConsoleLogSinkDispatcher)
LogConsole *console{ nullptr };
public:
explicit ConsoleLogSinkDispatcher() noexcept;
void handleLogMessage(const std::string_view, const LogMessage &) noexcept override;
void attachLogConsole(LogConsole *const) noexcept;
};
}
......@@ -84,13 +84,15 @@ VivyApplication::exec() noexcept
// Show the main window, also set up the log console
mainWindowPtr = std::make_shared<MainWindow>();
QDockWidget *logConsoleDock = new QDockWidget("Console", mainWindowPtr.get());
LogConsole *logConsole = new LogConsole(mainWindowPtr.get());
std::shared_ptr<ConsoleLogSinkDispatcher> consoleLogSinkDispatcher =
logSink->newDispatcher<ConsoleLogSinkDispatcher>(nullptr);
logSink->newDispatcher<ConsoleLogSinkDispatcher>();
DockWidgetTitleBar::addToDock(logConsoleDock);
consoleLogSinkDispatcher->attachLogConsole(logConsole);
logConsoleDock->setAllowedAreas(Qt::BottomDockWidgetArea);
logConsoleDock->setFeatures(QDockWidget::DockWidgetMovable);
logConsoleDock->setWidget(consoleLogSinkDispatcher.get());
logConsoleDock->setWidget(logConsole);
mainWindowPtr->addDockWidget(Qt::BottomDockWidgetArea, logConsoleDock);
mainWindowPtr->show();
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter