// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #pragma once #include "common/log.h" #include #include #include #include class ALIGN_TO_CACHE_LINE LogWindow : public QMainWindow { Q_OBJECT public: LogWindow(bool attach_to_main); ~LogWindow(); static void updateSettings(); static void destroy(); ALWAYS_INLINE bool isAttachedToMainWindow() const { return m_attached_to_main_window; } void reattachToMainWindow(); void updateWindowTitle(); static void populateFilterMenu(QMenu* menu); private: void createUi(); void updateLogLevelUi(); void setLogLevel(Log::Level level); static void logCallback(void* pUserParam, Log::MessageCategory cat, const char* functionName, std::string_view message); protected: void closeEvent(QCloseEvent* event); void changeEvent(QEvent* event); private Q_SLOTS: void onClearTriggered(); void onSaveTriggered(); void appendMessage(const QLatin1StringView& channel, quint32 cat, const QString& message); void realAppendMessage(const QLatin1StringView& channel, quint32 cat, const QString& message); private: static constexpr int DEFAULT_WIDTH = 750; static constexpr int DEFAULT_HEIGHT = 400; static constexpr int MAX_LINES = 1000; static constexpr int BLOCK_UPDATES_THRESHOLD = 100; void saveSize(); void restoreSize(); QPlainTextEdit* m_text; QMenu* m_level_menu; int m_lines_to_skip = 0; bool m_is_dark_theme = false; bool m_attached_to_main_window = true; bool m_destroying = false; ALIGN_TO_CACHE_LINE std::atomic_int m_lines_pending{0}; }; extern LogWindow* g_log_window;