[nemiver/varobjs-support] Make the variable inspector dialog support variable objects



commit 0866e5e130f9871eb1671f529c74847bffc3cdc8
Author: Dodji Seketeli <dodji redhat com>
Date:   Sun Apr 5 18:21:37 2009 +0200

    Make the variable inspector dialog support variable objects
    
    	* src/dbgengine/nmv-i-debugger.h:
    	(IDebugger::Variable::need_unfolding): New entry point.
    	(IDebugger::Variable::*): Add some comments here and there.
    	* src/persp/dbgperspective/nmv-variables-utils.cc (append_a_variable):
    	When adding a variable that needs unfolding later, add a dummy child
    	node to it, so that the user can see a tree row expander and click on it
    	to unfold the variable. Later, when adding variable members to that
    	variable that needs unfolding, delete the dummy node and add the
    	proper children nodes.
    	* src/persp/dbgperspective/nmv-var-inspector2.[cc|]: Added
    	the VarInspector2 type that uses the variable objects backend to
    	inspect variables.
    	* src/persp/dbgperspective/Makefile.am: Add nmv-var-inspector2.[cc|h]
    	to the build system.
    	* src/persp/dbgperspective/nmv-var-inspector-dialog.cc: Use
    	VarInspector2 when configured with --enable-varobjs.
---
 src/dbgengine/nmv-i-debugger.h                     |   20 +
 src/persp/dbgperspective/Makefile.am               |    2 +
 .../dbgperspective/nmv-var-inspector-dialog.cc     |   13 +
 src/persp/dbgperspective/nmv-var-inspector2.cc     |  363 ++++++++++++++++++++
 src/persp/dbgperspective/nmv-var-inspector2.h      |   61 ++++
 src/persp/dbgperspective/nmv-variables-utils.cc    |   65 +++-
 src/persp/dbgperspective/nmv-variables-utils.h     |    7 +-
 7 files changed, 521 insertions(+), 10 deletions(-)

diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index eda5354..4a10aee 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -280,6 +280,9 @@ public:
     typedef list<VariableSafePtr> VariableList;
     class Variable : public Object {
         VariableList m_members;
+        // If this variable was created with a backend counterpart
+        // (e.g: backend side variable objects in GDB), then this
+        // is the name of the backend side counterpart of this variable.
         UString m_internal_name;
         UString m_name;
         UString m_name_caption;
@@ -338,7 +341,17 @@ public:
             a_var->parent (this);
         }
 
+        /// If this variable was created with a backend counterpart
+        /// (e.g. backend side variable objects in GDB), then this
+        /// returns the name of the backend side counterpart of this variable.
+        /// \return the name of the backend side counterpart of this
+        /// variable. It can be an empty string if there is no backend side
+        /// counterpart variable object created for this object.
         const UString& internal_name () const {return m_internal_name;}
+
+        /// Set the name of the backend side counterpart object.
+        /// (e.g. variable object in GDB).
+        /// \param a_in the new name of backend side counterpart variable object.
         void internal_name (const UString &a_in) {m_internal_name = a_in;}
 
         const UString& name () const {return m_name;}
@@ -553,6 +566,13 @@ public:
             return m_num_expected_children != 0;
         }
 
+        /// \return true if the current variable needs to be unfolded
+        /// by a call to IDebugger::unfold_variable()
+        bool needs_unfolding () const
+        {
+            return (has_expected_children () && members ().empty ());
+        }
+
         /// Return the descendant of the current instance of Variable.
         /// \param a_internal_path the internal fully qualified path of the
         ///        descendant variable.
diff --git a/src/persp/dbgperspective/Makefile.am b/src/persp/dbgperspective/Makefile.am
index f9f62af..32b961e 100644
--- a/src/persp/dbgperspective/Makefile.am
+++ b/src/persp/dbgperspective/Makefile.am
@@ -54,6 +54,8 @@ nmv-global-vars-inspector-dialog.cc \
 nmv-global-vars-inspector-dialog.h \
 nmv-var-inspector.cc \
 nmv-var-inspector.h \
+nmv-var-inspector2.cc \
+nmv-var-inspector2.h \
 nmv-breakpoints-view.cc \
 nmv-breakpoints-view.h \
 nmv-registers-view.cc \
diff --git a/src/persp/dbgperspective/nmv-var-inspector-dialog.cc b/src/persp/dbgperspective/nmv-var-inspector-dialog.cc
index 7913722..b1348cc 100644
--- a/src/persp/dbgperspective/nmv-var-inspector-dialog.cc
+++ b/src/persp/dbgperspective/nmv-var-inspector-dialog.cc
@@ -27,7 +27,11 @@
 #include <gtkmm/liststore.h>
 #include "common/nmv-exception.h"
 #include "nmv-var-inspector-dialog.h"
+#ifdef WITH_VAROBJS
+#include "nmv-var-inspector2.h"
+#else
 #include "nmv-var-inspector.h"
+#endif //WITH_VAROBJS
 #include "nmv-ui-utils.h"
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
@@ -51,7 +55,11 @@ class VarInspectorDialog::Priv {
     Gtk::ComboBoxEntry *var_name_entry;
     Glib::RefPtr<Gtk::ListStore> m_variable_history;
     Gtk::Button *inspect_button;
+#ifdef WITH_VAROBJS
+    SafePtr<VarInspector2> var_inspector;
+#else
     SafePtr<VarInspector> var_inspector;
+#endif //WITH_VAROBJS
     Gtk::Dialog &dialog;
     Glib::RefPtr<Gnome::Glade::Xml> glade;
     IDebuggerSafePtr debugger;
@@ -93,8 +101,13 @@ public:
         Gtk::Box *box =
             ui_utils::get_widget_from_glade<Gtk::Box> (glade,
                                                        "inspectorwidgetbox");
+#ifdef WITH_VAROBJS
+        var_inspector.reset (new VarInspector2 (debugger));
+#else
         var_inspector.reset (new VarInspector (debugger));
+#endif // WITH_VAROBJS
         THROW_IF_FAIL (var_inspector);
+
         Gtk::ScrolledWindow *scr = Gtk::manage (new Gtk::ScrolledWindow);
         scr->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
         scr->set_shadow_type (Gtk::SHADOW_IN);
diff --git a/src/persp/dbgperspective/nmv-var-inspector2.cc b/src/persp/dbgperspective/nmv-var-inspector2.cc
new file mode 100644
index 0000000..549b082
--- /dev/null
+++ b/src/persp/dbgperspective/nmv-var-inspector2.cc
@@ -0,0 +1,363 @@
+//Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtkmm/treestore.h>
+#include "common/nmv-exception.h"
+#include "nmv-var-inspector2.h"
+#include "nmv-variables-utils.h"
+#include "nmv-i-var-walker.h"
+#include "nmv-ui-utils.h"
+#include "nmv-vars-treeview.h"
+
+namespace uutil = nemiver::ui_utils;
+namespace vutil = nemiver::variables_utils2;
+namespace cmn = nemiver::common;
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+class VarInspector2::Priv : public sigc::trackable {
+    friend class VarInspector2;
+    Priv ();
+
+    bool requested_variable;
+    bool requested_type;
+    IDebuggerSafePtr debugger;
+    // Variable that is being inspected
+    // at a given point in time
+    IDebugger::VariableSafePtr variable;
+    VarsTreeViewSafePtr tree_view;
+    Glib::RefPtr<Gtk::TreeStore> tree_store;
+    Gtk::TreeModel::iterator var_row_it;
+    Gtk::TreeModel::iterator cur_selected_row;
+
+    void
+    build_widget ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        tree_view = VarsTreeView::create ();
+        THROW_IF_FAIL (tree_view);
+        tree_store = tree_view->get_tree_store ();
+        THROW_IF_FAIL (tree_store);
+    }
+
+    void
+    connect_to_signals ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        Glib::RefPtr<Gtk::TreeSelection> selection =
+                                        tree_view->get_selection ();
+        THROW_IF_FAIL (selection);
+        selection->signal_changed ().connect
+            (sigc::mem_fun (*this,
+                            &Priv::on_tree_view_selection_changed_signal));
+        tree_view->signal_row_activated ().connect
+            (sigc::mem_fun (*this, &Priv::on_tree_view_row_activated_signal));
+
+        tree_view->signal_row_expanded ().connect
+            (sigc::mem_fun (*this, &Priv::on_tree_view_row_expanded_signal));
+    }
+
+    void
+    re_init_tree_view ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        THROW_IF_FAIL (tree_store);
+        tree_store->clear ();
+    }
+
+    // If the variable we are inspected was created
+    // with a backend counterpart (variable objects for GDB),
+    // instruct the backend to delete its variable counterpart.
+    void
+    delete_variable_if_needed ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        if (variable
+            && !variable->internal_name ().empty ()
+            && debugger) {
+            debugger->delete_variable (variable);
+        }
+    }
+
+    void
+    set_variable (const IDebugger::VariableSafePtr a_variable)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        THROW_IF_FAIL (tree_view && tree_store);
+        re_init_tree_view ();
+        delete_variable_if_needed ();
+
+        Gtk::TreeModel::iterator parent_iter =
+                                    tree_store->children ().begin ();
+        Gtk::TreeModel::iterator var_row;
+        vutil::append_a_variable (a_variable,
+                                  *tree_view,
+                                  tree_store,
+                                  parent_iter,
+                                  var_row);
+        LOG_DD ("set variable" << a_variable->name ());
+        // Don't expand the row if the variable needs unfolding.
+        // It means its children nodes (members) are not known yet, and
+        // will be queried when the user wants to expand it himself.
+        if (var_row
+            && !(*var_row)[vutil::get_variable_columns ().needs_unfolding]) {
+            tree_view->expand_row (tree_store->get_path (var_row), false);
+        }
+        variable = a_variable;
+    }
+
+    void
+    update_unfolded_variable (const IDebugger::VariableSafePtr a_variable,
+                              Gtk::TreeModel::iterator &a_var_it)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        Gtk::TreeModel::iterator result_var_row_it;
+        IDebugger::VariableList::const_iterator var_it;
+        IDebugger::VariableList::const_iterator member_it;
+        for (member_it = a_variable->members ().begin ();
+             member_it != a_variable->members ().end ();
+             ++member_it) {
+            vutil::append_a_variable (*member_it,
+                                      *tree_view,
+                                      tree_store,
+                                      a_var_it,
+                                      result_var_row_it);
+        }
+    }
+
+    void
+    show_variable_type_in_dialog ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (!cur_selected_row) {return;}
+        UString type =
+        (Glib::ustring)
+                (*cur_selected_row)[vutil::get_variable_columns ().type];
+        UString message;
+        message.printf (_("Variable type is: \n %s"), type.c_str ());
+
+        IDebugger::VariableSafePtr variable =
+            (IDebugger::VariableSafePtr)
+                cur_selected_row->get_value
+                                (vutil::get_variable_columns ().variable);
+        THROW_IF_FAIL (variable);
+        // message += "\nDumped for debug: \n";
+        // variable->to_string (message, false);
+        ui_utils::display_info (message);
+    }
+
+    void
+    create_variable (const UString &a_name)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        debugger->create_variable
+            (a_name, sigc::mem_fun
+                    (this, &VarInspector2::Priv::on_variable_created_signal));
+    }
+
+    // ******************
+    // <signal handlers>
+    // ******************
+
+
+    void
+    on_tree_view_selection_changed_signal ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        NEMIVER_TRY
+
+        THROW_IF_FAIL (tree_view);
+        Glib::RefPtr<Gtk::TreeSelection> sel = tree_view->get_selection ();
+        THROW_IF_FAIL (sel);
+        cur_selected_row = sel->get_selected ();
+        if (!cur_selected_row) {return;}
+        IDebugger::VariableSafePtr variable =
+            (IDebugger::VariableSafePtr)cur_selected_row->get_value
+                                    (vutil::get_variable_columns ().variable);
+        if (!variable) {return;}
+        UString qname;
+        variable->build_qname (qname);
+        LOG_DD ("row of variable '" << qname << "'");
+
+        NEMIVER_CATCH
+    }
+
+    void
+    on_tree_view_row_activated_signal (const Gtk::TreeModel::Path &a_path,
+                                            Gtk::TreeViewColumn *a_col)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY
+
+        THROW_IF_FAIL (tree_store);
+        Gtk::TreeModel::iterator it = tree_store->get_iter (a_path);
+        UString type =
+            (Glib::ustring) it->get_value
+                            (vutil::get_variable_columns ().type);
+        if (type == "") {return;}
+
+        if (a_col != tree_view->get_column (2)) {return;}
+        cur_selected_row = it;
+        show_variable_type_in_dialog ();
+
+        NEMIVER_CATCH
+    }
+
+    void
+    on_tree_view_row_expanded_signal (const Gtk::TreeModel::iterator &a_row_it,
+                                      const Gtk::TreeModel::Path &a_row_path)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY
+
+        if (!(*a_row_it)[vutil::get_variable_columns ().needs_unfolding]) {
+            return;
+        }
+        LOG_DD ("The variable needs unfolding");
+
+        IDebugger::VariableSafePtr var =
+            (*a_row_it)[vutil::get_variable_columns ().variable];
+        debugger->unfold_variable
+        (var, sigc::bind (sigc::mem_fun (*this,
+                                         &Priv::on_variable_unfolded_signal),
+                          a_row_path));
+        LOG_DD ("variable unfolding triggered");
+
+        NEMIVER_CATCH
+    }
+
+    void
+    on_variable_created_signal (const IDebugger::VariableSafePtr a_var)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY
+
+        set_variable (a_var);
+
+        NEMIVER_CATCH
+    }
+
+    void
+    on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
+                                 const Gtk::TreeModel::Path &a_var_node)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY
+
+        Gtk::TreeModel::iterator var_it = tree_store->get_iter (a_var_node);
+        update_unfolded_variable (a_var, var_it);
+        tree_view->expand_row (a_var_node, false);
+
+        NEMIVER_CATCH
+    }
+
+    // ******************
+    // </signal handlers>
+    // ******************
+
+public:
+
+    Priv (IDebuggerSafePtr a_debugger) :
+          requested_variable (false),
+          requested_type (false),
+          debugger (a_debugger)
+    {
+        build_widget ();
+        re_init_tree_view ();
+        connect_to_signals ();
+    }
+
+    ~Priv ()
+    {
+        delete_variable_if_needed ();
+    }
+};//end class VarInspector2::Priv
+
+VarInspector2::VarInspector2 (IDebuggerSafePtr a_debugger)
+{
+    m_priv.reset (new Priv (a_debugger));
+}
+
+VarInspector2::~VarInspector2 ()
+{
+    LOG_D ("deleted", "destructor-domain");
+}
+
+Gtk::Widget&
+VarInspector2::widget () const
+{
+    THROW_IF_FAIL (m_priv);
+    THROW_IF_FAIL (m_priv->tree_view);
+    return *m_priv->tree_view;
+}
+
+void
+VarInspector2::set_variable (IDebugger::VariableSafePtr a_variable)
+{
+    THROW_IF_FAIL (m_priv);
+
+    m_priv->set_variable (a_variable);
+}
+
+void
+VarInspector2::inspect_variable (const UString &a_variable_name)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    if (a_variable_name == "") {return;}
+    THROW_IF_FAIL (m_priv);
+    m_priv->re_init_tree_view ();
+    m_priv->delete_variable_if_needed ();
+    m_priv->create_variable (a_variable_name);
+}
+
+IDebugger::VariableSafePtr
+VarInspector2::get_variable () const
+{
+    THROW_IF_FAIL (m_priv);
+
+    return m_priv->variable;
+}
+
+void
+VarInspector2::clear ()
+{
+    THROW_IF_FAIL (m_priv);
+    m_priv->re_init_tree_view ();
+    m_priv->delete_variable_if_needed ();
+}
+
+NEMIVER_END_NAMESPACE (nemiver)
+
diff --git a/src/persp/dbgperspective/nmv-var-inspector2.h b/src/persp/dbgperspective/nmv-var-inspector2.h
new file mode 100644
index 0000000..c83b7ad
--- /dev/null
+++ b/src/persp/dbgperspective/nmv-var-inspector2.h
@@ -0,0 +1,61 @@
+//Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_VAR_INSPECTOR2_H__
+#define __NMV_VAR_INSPECTOR2_H__
+
+#include "common/nmv-object.h"
+#include "common/nmv-safe-ptr-utils.h"
+#include "nmv-i-debugger.h"
+
+namespace Gtk {
+    class Widget;
+}
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+namespace common {
+    class UString;
+}
+
+class VarInspector2 : public nemiver::common::Object {
+    VarInspector2 (const VarInspector2 &);
+    VarInspector2& operator= (const VarInspector2 &);
+    VarInspector2 ();
+    class Priv;
+    SafePtr<Priv> m_priv;
+
+public:
+    VarInspector2 (IDebuggerSafePtr a_debugger);
+    virtual ~VarInspector2 ();
+    Gtk::Widget& widget () const;
+    void set_variable (IDebugger::VariableSafePtr a_variable);
+    void inspect_variable (const UString &a_variable_name);
+    IDebugger::VariableSafePtr get_variable () const;
+    void clear ();
+};//end class VarInspector2
+
+NEMIVER_END_NAMESPACE (nemiver)
+#endif //__NMV_VAR_INSPECTOR2_H__
+
diff --git a/src/persp/dbgperspective/nmv-variables-utils.cc b/src/persp/dbgperspective/nmv-variables-utils.cc
index 4d5a2cf..d677fd7 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.cc
+++ b/src/persp/dbgperspective/nmv-variables-utils.cc
@@ -230,7 +230,16 @@ update_a_variable_real (const IDebugger::VariableSafePtr a_var,
     }
 }
 
-void
+/// Append a variable to a variable tree view widget.
+///
+/// \param a_var the variable to add
+/// \param a_tree_view the variable tree view widget to consider
+/// \param a_tree_store the tree store of the variable tree view widget
+/// \param a_parent_row_it an iterator to the graphical parent node the
+/// the variable is to be added to. If the iterator is false, then the
+/// variable is added as the root node of the tree view widget.
+/// \return true if a_var was added, false otherwise.
+bool
 append_a_variable (const IDebugger::VariableSafePtr a_var,
                    const Gtk::TreeView &a_tree_view,
                    const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
@@ -239,11 +248,24 @@ append_a_variable (const IDebugger::VariableSafePtr a_var,
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
     Gtk::TreeModel::iterator row_it;
-    append_a_variable (a_var, a_tree_view, a_tree_store,
-                       a_parent_row_it, row_it);
+    return append_a_variable (a_var, a_tree_view, a_tree_store,
+                              a_parent_row_it, row_it);
 }
 
-void
+/// Append a variable to a variable tree view widget.
+///
+/// \param a_var the variable to add. It can be zero. In that case,
+/// a dummy (empty) node is added as a graphical child of a_parent_row_it.
+/// \param a_tree_view the variable tree view widget to consider
+/// \param a_tree_store the tree store of the variable tree view widget
+/// \param a_parent_row_it an iterator to the graphical parent node the
+/// the variable is to be added to. If the iterator is false, then the
+/// variable is added as the root node of the tree view widget.
+/// \param result the resulting graphical node that was created an added
+/// to the variable tree view widget. This parameter is set if and only if
+/// the function returned true.
+/// \return true if a_var was added, false otherwise.
+bool
 append_a_variable (const IDebugger::VariableSafePtr a_var,
                    const Gtk::TreeView &a_tree_view,
                    const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
@@ -257,16 +279,43 @@ append_a_variable (const IDebugger::VariableSafePtr a_var,
     if (!a_parent_row_it) {
         row_it = a_tree_store->append ();
     } else {
+        if (a_parent_row_it->children ()
+            && a_var
+            && (*a_parent_row_it)[get_variable_columns ().needs_unfolding]){
+            // So a_parent_row_it might have dummy empty nodes as children.
+            // Remove those, so that that we can properly add a_var as a
+            // child node of a_parent_row_it. Then, don't forget to
+            // set get_variable_columns ().needs_unfolding to false.
+            Gtk::TreeModel::Children::const_iterator it;
+            for (it = a_parent_row_it->children ().begin ();
+                 it != a_parent_row_it->children ().end ();) {
+                it = a_tree_store->erase (it);
+            }
+            (*a_parent_row_it)[get_variable_columns ().needs_unfolding]
+                                                                        = false;
+        }
         row_it = a_tree_store->append (a_parent_row_it->children ());
     }
+    if (!a_var) {
+        return false;
+    }
     update_a_variable_node (a_var, a_tree_view, row_it, true, true);
     list<IDebugger::VariableSafePtr>::const_iterator it;
-    for (it = a_var->members ().begin ();
-         it != a_var->members ().end ();
-         ++it) {
-        append_a_variable (*it, a_tree_view, a_tree_store, row_it);
+    if (a_var->needs_unfolding ()) {
+        // Mark *row_it as needing unfolding, and add an empty
+        // child node to it
+        (*row_it)[get_variable_columns ().needs_unfolding] = true;
+        IDebugger::VariableSafePtr empty_var;
+        append_a_variable (empty_var, a_tree_view, a_tree_store, row_it);
+    } else {
+        for (it = a_var->members ().begin ();
+             it != a_var->members ().end ();
+             ++it) {
+            append_a_variable (*it, a_tree_view, a_tree_store, row_it);
+        }
     }
     a_result = row_it;
+    return true;
 }
 
 
diff --git a/src/persp/dbgperspective/nmv-variables-utils.h b/src/persp/dbgperspective/nmv-variables-utils.h
index da82743..be3d2e1 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.h
+++ b/src/persp/dbgperspective/nmv-variables-utils.h
@@ -44,6 +44,7 @@ struct VariableColumns : public Gtk::TreeModelColumnRecord {
         TYPE_CAPTION_OFFSET,
         VARIABLE_OFFSET,
         IS_HIGHLIGHTED_OFFSET,
+        NEEDS_UNFOLDING,
         FG_COLOR_OFFSET
     };
 
@@ -53,6 +54,7 @@ struct VariableColumns : public Gtk::TreeModelColumnRecord {
     Gtk::TreeModelColumn<Glib::ustring> type_caption;
     Gtk::TreeModelColumn<IDebugger::VariableSafePtr> variable;
     Gtk::TreeModelColumn<bool> is_highlighted;
+    Gtk::TreeModelColumn<bool> needs_unfolding;
     Gtk::TreeModelColumn<Gdk::Color> fg_color;
 
     VariableColumns ()
@@ -63,6 +65,7 @@ struct VariableColumns : public Gtk::TreeModelColumnRecord {
         add (type_caption);
         add (variable);
         add (is_highlighted);
+        add (needs_unfolding);
         add (fg_color);
     }
 };//end VariableColumns
@@ -90,12 +93,12 @@ bool update_a_variable (const IDebugger::VariableSafePtr a_var,
                         bool a_handle_highlight,
                         bool a_is_new_frame);
 
-void append_a_variable (const IDebugger::VariableSafePtr a_var,
+bool append_a_variable (const IDebugger::VariableSafePtr a_var,
                         const Gtk::TreeView &a_tree_view,
                         const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
                         Gtk::TreeModel::iterator &a_parent_row_it);
 
-void append_a_variable (const IDebugger::VariableSafePtr a_var,
+bool append_a_variable (const IDebugger::VariableSafePtr a_var,
                         const Gtk::TreeView &a_tree_view,
                         const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
                         Gtk::TreeModel::iterator &a_parent_row_it,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]