diff options
Diffstat (limited to '')
-rw-r--r-- | src/ui/dialog/debug.cpp | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/src/ui/dialog/debug.cpp b/src/ui/dialog/debug.cpp new file mode 100644 index 0000000..b9e7f28 --- /dev/null +++ b/src/ui/dialog/debug.cpp @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * A dialog that displays log messages. + */ +/* Authors: + * Bob Jamison + * Other dudes from The Inkscape Organization + * + * Copyright (C) 2004 The Inkscape Organization + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <gtkmm/box.h> +#include <gtkmm/dialog.h> +#include <gtkmm/textview.h> +#include <gtkmm/menubar.h> +#include <gtkmm/scrolledwindow.h> +#include <glibmm/i18n.h> + +#include "debug.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +/** + * A very simple dialog for displaying Inkscape messages - implementation. + */ +class DebugDialogImpl : public DebugDialog, public Gtk::Dialog +{ +public: + DebugDialogImpl(); + ~DebugDialogImpl() override; + + void show() override; + void hide() override; + void clear() override; + void message(char const *msg) override; + void captureLogMessages() override; + void releaseLogMessages() override; + +private: + Gtk::MenuBar menuBar; + Gtk::Menu fileMenu; + Gtk::ScrolledWindow textScroll; + Gtk::TextView messageText; + + //Handler ID's + guint handlerDefault; + guint handlerGlibmm; + guint handlerAtkmm; + guint handlerPangomm; + guint handlerGdkmm; + guint handlerGtkmm; +}; + +void DebugDialogImpl::clear() +{ + Glib::RefPtr<Gtk::TextBuffer> buffer = messageText.get_buffer(); + buffer->erase(buffer->begin(), buffer->end()); +} + +DebugDialogImpl::DebugDialogImpl() +{ + set_title(_("Messages")); + set_size_request(300, -1); + auto mainVBox = get_content_area(); + + //## Add a menu for clear() + Gtk::MenuItem* item = Gtk::manage(new Gtk::MenuItem(_("_File"), true)); + item->set_submenu(fileMenu); + menuBar.append(*item); + + item = Gtk::manage(new Gtk::MenuItem(_("_Clear"), true)); + item->signal_activate().connect(sigc::mem_fun(*this, &DebugDialogImpl::clear)); + fileMenu.append(*item); + + item = Gtk::manage(new Gtk::MenuItem(_("Capture log messages"))); + item->signal_activate().connect(sigc::mem_fun(*this, &DebugDialogImpl::captureLogMessages)); + fileMenu.append(*item); + + item = Gtk::manage(new Gtk::MenuItem(_("Release log messages"))); + item->signal_activate().connect(sigc::mem_fun(*this, &DebugDialogImpl::releaseLogMessages)); + fileMenu.append(*item); + + mainVBox->pack_start(menuBar, Gtk::PACK_SHRINK); + + + //### Set up the text widget + messageText.set_editable(false); + textScroll.add(messageText); + textScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); + mainVBox->pack_start(textScroll); + + show_all_children(); + + message("ready."); + message("enable log display by setting "); + message("dialogs.debug 'redirect' attribute to 1 in preferences.xml"); + + handlerDefault = 0; + handlerGlibmm = 0; + handlerAtkmm = 0; + handlerPangomm = 0; + handlerGdkmm = 0; + handlerGtkmm = 0; +} + + +DebugDialog *DebugDialog::create() +{ + DebugDialog *dialog = new DebugDialogImpl(); + return dialog; +} + +DebugDialogImpl::~DebugDialogImpl() += default; + +void DebugDialogImpl::show() +{ + //call super() + Gtk::Dialog::show(); + //sp_transientize(GTK_WIDGET(gobj())); //Make transient + raise(); + Gtk::Dialog::present(); +} + +void DebugDialogImpl::hide() +{ + // call super + Gtk::Dialog::hide(); +} + +void DebugDialogImpl::message(char const *msg) +{ + Glib::RefPtr<Gtk::TextBuffer> buffer = messageText.get_buffer(); + Glib::ustring uMsg = msg; + if (uMsg[uMsg.length()-1] != '\n') + uMsg += '\n'; + buffer->insert (buffer->end(), uMsg); +} + +/* static instance, to reduce dependencies */ +static DebugDialog *debugDialogInstance = nullptr; + +DebugDialog *DebugDialog::getInstance() +{ + if (!debugDialogInstance) { + debugDialogInstance = new DebugDialogImpl(); + } + return debugDialogInstance; +} + + + +void DebugDialog::showInstance() +{ + DebugDialog *debugDialog = getInstance(); + debugDialog->show(); + // this is not a real memleak because getInstance() only creates a debug dialog once, and returns that instance for all subsequent calls + // cppcheck-suppress memleak +} + + + + +/*##### THIS IS THE IMPORTANT PART ##### */ +static void dialogLoggingFunction(const gchar */*log_domain*/, + GLogLevelFlags /*log_level*/, + const gchar *messageText, + gpointer user_data) +{ + DebugDialogImpl *dlg = static_cast<DebugDialogImpl *>(user_data); + dlg->message(messageText); +} + + +void DebugDialogImpl::captureLogMessages() +{ + /* + This might likely need more code, to capture Gtkmm + and Glibmm warnings, or maybe just simply grab stdout/stderr + */ + GLogLevelFlags flags = (GLogLevelFlags) (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | + G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | + G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG); + if ( !handlerDefault ) { + handlerDefault = g_log_set_handler(nullptr, flags, + dialogLoggingFunction, (gpointer)this); + } + if ( !handlerGlibmm ) { + handlerGlibmm = g_log_set_handler("glibmm", flags, + dialogLoggingFunction, (gpointer)this); + } + if ( !handlerAtkmm ) { + handlerAtkmm = g_log_set_handler("atkmm", flags, + dialogLoggingFunction, (gpointer)this); + } + if ( !handlerPangomm ) { + handlerPangomm = g_log_set_handler("pangomm", flags, + dialogLoggingFunction, (gpointer)this); + } + if ( !handlerGdkmm ) { + handlerGdkmm = g_log_set_handler("gdkmm", flags, + dialogLoggingFunction, (gpointer)this); + } + if ( !handlerGtkmm ) { + handlerGtkmm = g_log_set_handler("gtkmm", flags, + dialogLoggingFunction, (gpointer)this); + } + message("log capture started"); +} + +void DebugDialogImpl::releaseLogMessages() +{ + if ( handlerDefault ) { + g_log_remove_handler(nullptr, handlerDefault); + handlerDefault = 0; + } + if ( handlerGlibmm ) { + g_log_remove_handler("glibmm", handlerGlibmm); + handlerGlibmm = 0; + } + if ( handlerAtkmm ) { + g_log_remove_handler("atkmm", handlerAtkmm); + handlerAtkmm = 0; + } + if ( handlerPangomm ) { + g_log_remove_handler("pangomm", handlerPangomm); + handlerPangomm = 0; + } + if ( handlerGdkmm ) { + g_log_remove_handler("gdkmm", handlerGdkmm); + handlerGdkmm = 0; + } + if ( handlerGtkmm ) { + g_log_remove_handler("gtkmm", handlerGtkmm); + handlerGtkmm = 0; + } + message("log capture discontinued"); +} + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |