summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/memory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/dialog/memory.cpp')
-rw-r--r--src/ui/dialog/memory.cpp261
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 :