diff --git a/src/Lib/Log.hh b/src/Lib/Log.hh index 063187a9ea52e5e79fb8a84d0f2fc99c59c4c557..428fb35879cc48849da4d9cd91cea82fcd0e3b60 100644 --- a/src/Lib/Log.hh +++ b/src/Lib/Log.hh @@ -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); diff --git a/src/UI/LogConsole.cc b/src/UI/LogConsole.cc index 7428a1a6a569d0c48b3f3994a5b19d82c338fd87..18363b67cab641a9b08ba83ea4cef2a794f9128a 100644 --- a/src/UI/LogConsole.cc +++ b/src/UI/LogConsole.cc @@ -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); diff --git a/src/UI/LogConsole.hh b/src/UI/LogConsole.hh index 2525f10e86a7ba936e13566bff1efe2673652005..a388e330d81b87ff10e4ba93ee520bbf1ca30d16 100644 --- a/src/UI/LogConsole.hh +++ b/src/UI/LogConsole.hh @@ -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; }; } diff --git a/src/VivyApplication.cc b/src/VivyApplication.cc index de244c0a3cffb4b231736bcdef17e8578990c96f..f511fe9d3f34a840508a268651b7a4658639c04f 100644 --- a/src/VivyApplication.cc +++ b/src/VivyApplication.cc @@ -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();