diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/ui/dialog/memory.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-upstream/1.2.2.tar.xz inkscape-upstream/1.2.2.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/ui/dialog/memory.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/src/ui/dialog/memory.cpp b/src/ui/dialog/memory.cpp new file mode 100644 index 0000000..10829e6 --- /dev/null +++ b/src/ui/dialog/memory.cpp @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Memory statistics dialog. + */ +/* Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "ui/dialog/memory.h" +#include <glibmm/i18n.h> +#include <glibmm/main.h> + +#include <gtkmm/liststore.h> +#include <gtkmm/treeview.h> +#include <gtkmm/dialog.h> + +#include "inkgc/gc-core.h" +#include "debug/heap.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +namespace { + +Glib::ustring format_size(std::size_t value) { + if (!value) { + return Glib::ustring("0"); + } + + typedef std::vector<char> Digits; + typedef std::vector<Digits *> Groups; + + Groups groups; + + Digits *digits; + + while (value) { + unsigned places=3; + digits = new Digits(); + digits->reserve(places); + + while ( value && places ) { + digits->push_back('0' + (char)( value % 10 )); + value /= 10; + --places; + } + + groups.push_back(digits); + } + + Glib::ustring temp; + + while (true) { + digits = groups.back(); + while (!digits->empty()) { + temp.append(1, digits->back()); + digits->pop_back(); + } + delete digits; + + groups.pop_back(); + if (groups.empty()) { + break; + } + + temp.append(","); + } + + return temp; +} + +} + +struct Memory::Private { + class ModelColumns : public Gtk::TreeModel::ColumnRecord { + public: + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> used; + Gtk::TreeModelColumn<Glib::ustring> slack; + Gtk::TreeModelColumn<Glib::ustring> total; + + ModelColumns() { add(name); add(used); add(slack); add(total); } + }; + + Private() { + model = Gtk::ListStore::create(columns); + view.set_model(model); + view.append_column(_("Heap"), columns.name); + view.append_column(_("In Use"), columns.used); + // TRANSLATORS: "Slack" refers to memory which is in the heap but currently unused. + // More typical usage is to call this memory "free" rather than "slack". + view.append_column(_("Slack"), columns.slack); + view.append_column(_("Total"), columns.total); + } + + void update(); + + void start_update_task(); + void stop_update_task(); + + ModelColumns columns; + Glib::RefPtr<Gtk::ListStore> model; + Gtk::TreeView view; + + sigc::connection update_task; +}; + +void Memory::Private::update() { + Debug::Heap::Stats total = { 0, 0 }; + + int aggregate_features = Debug::Heap::SIZE_AVAILABLE | Debug::Heap::USED_AVAILABLE; + Gtk::ListStore::iterator row; + + row = model->children().begin(); + + for ( unsigned i = 0 ; i < Debug::heap_count() ; i++ ) { + Debug::Heap *heap=Debug::get_heap(i); + if (heap) { + Debug::Heap::Stats stats=heap->stats(); + int features=heap->features(); + + aggregate_features &= features; + + if ( row == model->children().end() ) { + row = model->append(); + } + + row->set_value(columns.name, Glib::ustring(heap->name())); + if ( features & Debug::Heap::SIZE_AVAILABLE ) { + row->set_value(columns.total, format_size(stats.size)); + total.size += stats.size; + } else { + row->set_value(columns.total, Glib::ustring(_("Unknown"))); + } + if ( features & Debug::Heap::USED_AVAILABLE ) { + row->set_value(columns.used, format_size(stats.bytes_used)); + total.bytes_used += stats.bytes_used; + } else { + row->set_value(columns.used, Glib::ustring(_("Unknown"))); + } + if ( features & Debug::Heap::SIZE_AVAILABLE && + features & Debug::Heap::USED_AVAILABLE ) + { + row->set_value(columns.slack, format_size(stats.size - stats.bytes_used)); + } else { + row->set_value(columns.slack, Glib::ustring(_("Unknown"))); + } + + ++row; + } + } + + if ( row == model->children().end() ) { + row = model->append(); + } + + Glib::ustring value; + + row->set_value(columns.name, Glib::ustring(_("Combined"))); + + if ( aggregate_features & Debug::Heap::SIZE_AVAILABLE ) { + row->set_value(columns.total, format_size(total.size)); + } else { + row->set_value(columns.total, Glib::ustring("> ") + format_size(total.size)); + } + + if ( aggregate_features & Debug::Heap::USED_AVAILABLE ) { + row->set_value(columns.used, format_size(total.bytes_used)); + } else { + row->set_value(columns.used, Glib::ustring("> ") + format_size(total.bytes_used)); + } + + if ( aggregate_features & Debug::Heap::SIZE_AVAILABLE && + aggregate_features & Debug::Heap::USED_AVAILABLE ) + { + row->set_value(columns.slack, format_size(total.size - total.bytes_used)); + } else { + row->set_value(columns.slack, Glib::ustring(_("Unknown"))); + } + + ++row; + + while ( row != model->children().end() ) { + row = model->erase(row); + } +} + +void Memory::Private::start_update_task() { + update_task.disconnect(); + update_task = Glib::signal_timeout().connect( + sigc::bind_return(sigc::mem_fun(*this, &Private::update), true), + 500 + ); +} + +void Memory::Private::stop_update_task() { + update_task.disconnect(); +} + +Memory::Memory() + : DialogBase("/dialogs/memory", "Memory") + , _private(*(new Memory::Private())) +{ + // Private conf + pack_start(_private.view); + + _private.update(); + + signal_show().connect(sigc::mem_fun(_private, &Private::start_update_task)); + signal_hide().connect(sigc::mem_fun(_private, &Private::stop_update_task)); + + // Add button + Gtk::Button *button = Gtk::manage(new Gtk::Button(_("Recalculate"))); + button->signal_button_press_event().connect(sigc::mem_fun(*this, &Memory::_apply)); + + Gtk::ButtonBox *button_box = Gtk::manage(new Gtk::ButtonBox()); + button_box->set_layout(Gtk::BUTTONBOX_END); + button_box->set_spacing(6); + button_box->set_border_width(4); + button_box->pack_end(*button); + pack_end(*button_box, Gtk::PACK_SHRINK, 0); + + // Start + _private.start_update_task(); + + show_all_children(); +} + +Memory::~Memory() { + _private.stop_update_task(); + delete &_private; +} + +bool Memory::_apply(GdkEventButton * /* button */) +{ + GC::Core::gcollect(); + _private.update(); + + return false; +} + +} // namespace Dialog +} // 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 : |