[nemiver/better-variable-format: 6/8] Support pretty printing instantly applied



commit 80a6edf4568f7e5be4573dcf3cd3bd15fbd70bd3
Author: Dodji Seketeli <dodji seketeli org>
Date:   Tue Mar 1 18:10:39 2011 +0100

    Support pretty printing instantly applied
    
    	* src/dbgengine/nmv-dbg-common.h (Command::should_emit_signal):
    	New accessor.  Returns TRUE by default.
    	* src/dbgengine/nmv-gdb-engine.h
    	(GDBEngine::variable_visualized_signal)
    	(GDBEngine::on_rv_eval_var, GDBEngine::on_rv_unfold_var)
    	(GDBEngine::on_rv_set_visualizer_on_member)
    	(GDBEngine::on_rv_set_visualizer_on_next_sibling)
    	(GDBEngine::on_rv_flag)
    	(GDBEngine::unfold_variable_with_visualizer)
    	(GDBEngine::revisualize_variable)
    	(GDBEngine::revisualize_variable_real): Declare new functions.
    	(GDBEngine::create_variable, GDBEngine::unfold_variable): Declare
    	new overloads.
    	(GDBEngine::enable_pretty_printing): Rename
    	GDBEngine::disable_pretty_printing into this.
    	(GDBEngine::set_variable_visualizer): Rename
    	GDBEngine::set_variable_vizualizer.
    	* src/dbgengine/nmv-gdb-engine.cc
    	(GDBEngine::Priv::variable_visualized_signal): New fn.
    	(GDBEngine::Priv::on_conf_key_changed_signal): If pretty printing
    	has been enabled, send the -enable-pretty-printing command down
    	the wire.
    	(OnCommandDoneHandler::do_handle): Handle new
    	set-variable-visualizer command.
    	(OnCreateVariableHandler::do_handle): Do not emit
    	IDebugger:variable_created_signal if it was been requested
    	otherwise at command creation time.
    	(OnUnfoldVariableHandler::do_handle): Likewise.
    	(GDBEngine::variable_visualized_signal, GDBEngine::on_rv_eval_var)
    	(GDBEngine::on_rv_unfold_var)
    	(GDBEngine::on_rv_set_visualizer_on_members)
    	(GDBEngine::on_rv_set_visualizer_on_next_sibling)
    	(GDBEngine::on_rv_flag)
    	(GDBEngine::unfold_variable_with_visualizer)
    	(GDBEngine::revisualize_variable)
    	(GDBEngine::revisualize_variable_real): New functions.
    	(GDBEngine::register_names_listed_signal)
    	(GDBEngine::register_values_listed_signal): Re-indent return type.
    	Add comments.
    	(GDBEngine::on_detached_from_target_signal): Add ';' after
    	NEMIVER_TRY/CATCH_NOX.  Add comments.
    	(GDBEngine::create_variable, GDBEngine::unfold_variable): Add
    	comments.  Add an overload that enables disabling broadcast signal
    	emitting.
    	(GDBEngine::enable_pretty_printing): Renamed
    	GDBEngine::disable_pretty_printing into this.  Added comments.
    	(GDBEngine::set_variable_vizualizer): Update comments.  Fix MI
    	commands sending.
    	* src/dbgengine/nmv-i-debugger.h (IDebugger::ConstVariableSlot)
    	(IDebugger::ConstVariableListSlot, IDebugger::ConstUStringSlot):
    	Move these defines right before declaring the IDebugger::Variable
    	type.
    	(IDebugger::visualizer, IDebugger::needs_revisualizing): New
    	accessors.
    	(IDebugger::members): Add a new accessor that returns non-const
    	members.
    	(IDebugger::variable_visualized_signal): New signal.
    	(IDebugger::revisualize_variable): New entry point.
    	(IDebugger::enable_pretty_printing): Renamed
    	IDebugger::disable_pretty_printing into this.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc
    	(DBGPerspective::on_conf_key_changed_signal): Add comments.
    	Re-indent somewhat.  Re-visualize the local variables of the
    	current function whenever the pretty-printing enabling setting
    	changes.
    	(DBGPerspective::Priv::pretty_printing_toggled): New member.
    	(DBGPerspective::on_conf_key_changed_signal): Set it.
    	(DBGPerspective::show_underline_tip_at_position): Use it.
    	* src/persp/dbgperspective/nmv-local-vars-inspector.h
    	(LocalVarsInspector::set_local_variables)
    	(LocalVarsInspector::show_local_variables_of_current_function):
    	Re-indent.
    	(LocalVarsInspector::visualize_local_variables_of_current_function):
    	New function.
    	* src/persp/dbgperspective/nmv-local-vars-inspector.cc
    	(LocalVarsInspector::Priv::append_a_function_argument): Add
    	logging.
    	(LocalVarsInspector::Priv::update_a_visualized_local_variable)
    	(LocalVarsInspector::Priv::update_a_visualized_function_arg)
    	(LocalVarsInspector::Priv::on_local_var_visualized_signal)
    	(LocalVarsInspector::Priv::on_function_arg_visualized_signal)
    	(LocalVarsInspector::visualize_local_variables_of_current_function):
    	New functions.
    	* src/persp/dbgperspective/nmv-var-inspector.h
    	(VarInspector::set_variable): Take a new flag to re-visualize the
    	variable.
    	* src/persp/dbgperspective/nmv-var-inspector.cc
    	(VarInspector::Priv::rev_visualize): New member.
    	(VarInspector::Priv::on_var_revisualized): New function.
    	(VarInspector::Priv::graphically_set_variable): Factor out from
    	...
    	(VarInspector::Priv::set_variable): ... here.  Use the new
    	VarInspector::Priv::on_var_revisualized.  Take a new flag to
    	re-visualize the variable.
    	(VarInspector::set_variable): Take a new flag to re-visualize the
    	variable.
    	* src/persp/dbgperspective/nmv-variables-utils.h ():
    	* src/persp/dbgperspective/nmv-variables-utils.cc
    	(variables_match): Consider variables with the same internal name
    	being equal.
    	(set_a_variable): Factorize out of ...
    	(append_a_variable): ... here.
    	(unlink_member_variable_rows): New function.
    	(visualize_a_variable): Likewise.  Use set_a_variable.
    	* tests/test-breakpoint.cc (test_main): Adjust for the renaming of
    	IDebugger::enable_pretty_printing.
    	* tests/test-types.cc (test_main): Likewise.
    	* tests/test-var-path-expr.cc (test_main): Likewise.
    	* tests/test-vars.cc (test_main): Likewise.

 src/dbgengine/nmv-dbg-common.h                     |   40 +-
 src/dbgengine/nmv-gdb-engine.cc                    |  582 ++++++++++++++++++--
 src/dbgengine/nmv-gdb-engine.h                     |   55 ++-
 src/dbgengine/nmv-i-debugger.h                     |   53 ++-
 src/persp/dbgperspective/nmv-dbg-perspective.cc    |   24 +-
 .../dbgperspective/nmv-local-vars-inspector.cc     |  109 ++++
 .../dbgperspective/nmv-local-vars-inspector.h      |    5 +-
 src/persp/dbgperspective/nmv-var-inspector.cc      |   67 ++-
 src/persp/dbgperspective/nmv-var-inspector.h       |    3 +-
 src/persp/dbgperspective/nmv-variables-utils.cc    |  110 ++++-
 src/persp/dbgperspective/nmv-variables-utils.h     |   14 +
 tests/test-breakpoint.cc                           |    2 +-
 tests/test-types.cc                                |    2 +-
 tests/test-var-path-expr.cc                        |    2 +-
 tests/test-vars.cc                                 |    2 +-
 15 files changed, 972 insertions(+), 98 deletions(-)
---
diff --git a/src/dbgengine/nmv-dbg-common.h b/src/dbgengine/nmv-dbg-common.h
index 7f48b25..d41f56b 100644
--- a/src/dbgengine/nmv-dbg-common.h
+++ b/src/dbgengine/nmv-dbg-common.h
@@ -40,40 +40,45 @@ class Command {
     UString m_tag4;
     IDebugger::VariableSafePtr m_var;
     sigc::slot_base m_slot;
+    bool m_should_emit_signal;
 
 public:
 
-    Command ()  :
-        m_tag2 (0),
-        m_slot (0)
+    Command () :
+    m_tag2 (0),
+      m_slot (0),
+      m_should_emit_signal (true)
     {
         clear ();
     }
 
     /// \param a_value a textual command to send to the debugger.
     Command (const UString &a_value) :
-        m_value (a_value),
-        m_tag2 (0),
-        m_slot (0)
+    m_value (a_value),
+      m_tag2 (0),
+      m_slot (0),
+      m_should_emit_signal (true)
     {
     }
 
     Command (const UString &a_name, const UString &a_value) :
-        m_name (a_name),
-        m_value (a_value),
-        m_tag2 (0),
-        m_slot (0)
+    m_name (a_name),
+      m_value (a_value),
+      m_tag2 (0),
+      m_slot (0),
+      m_should_emit_signal (true)
     {
     }
 
     Command (const UString &a_name,
              const UString &a_value,
              const UString &a_cookie) :
-        m_cookie (a_cookie),
-        m_name (a_name),
-        m_value (a_value),
-        m_tag2 (0),
-        m_slot (0)
+    m_cookie (a_cookie),
+      m_name (a_name),
+      m_value (a_value),
+      m_tag2 (0),
+      m_slot (0),
+      m_should_emit_signal (true)
     {
     }
 
@@ -125,6 +130,9 @@ public:
         return reinterpret_cast<const T&> (m_slot);
     }
 
+    bool should_emit_signal () const {return m_should_emit_signal;}
+    void should_emit_signal (bool a) {m_should_emit_signal = a;}
+
     /// @}
 
     void clear ()
@@ -136,6 +144,7 @@ public:
         m_tag2 = 0;
         m_tag3.clear ();
         m_tag4.clear ();
+	m_should_emit_signal = true;
     }
 
 };//end class Command
@@ -923,7 +932,6 @@ public:
     void submit_command_and_output (CommandAndOutput &a_cao);
 };//end class OutputHandlerList
 
-
 NEMIVER_END_NAMESPACE (nemiver)
 
 #endif //__NMV_DBG_COMMON_H_H__
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index cfc380e..f2fa126 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -50,8 +50,10 @@ using namespace std;
 using namespace nemiver::common;
 using namespace nemiver::cpp;
 
-static const UString GDBMI_OUTPUT_DOMAIN = "gdbmi-output-domain";
-static const UString DEFAULT_GDB_BINARY = "default-gdb-binary";
+typedef nemiver::IDebugger::ConstVariableSlot ConstVariableSlot;
+typedef nemiver::IDebugger::ConstVariableListSlot ConstVariableListSlot;
+typedef nemiver::IDebugger::ConstUStringSlot ConstUStringSlot;
+typedef nemiver::IDebugger::VariableSafePtr VariableSafePtr;
 
 using nemiver::debugger_utils::null_const_variable_slot;
 using nemiver::debugger_utils::null_const_variable_list_slot;
@@ -60,6 +62,12 @@ using nemiver::debugger_utils::null_frame_args_slot;
 using nemiver::debugger_utils::null_disass_slot;
 using nemiver::debugger_utils::null_breakpoints_slot;
 
+static const char* GDBMI_OUTPUT_DOMAIN = "gdbmi-output-domain";
+static const char* DEFAULT_GDB_BINARY = "default-gdb-binary";
+static const char* GDB_DEFAULT_PRETTY_PRINTING_VISUALIZER =
+    "gdb.default_visualizer";
+static const char* GDB_NULL_PRETTY_PRINTING_VISUALIZER = "None";
+
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 
 extern const char* CONF_KEY_GDB_BINARY;
@@ -324,6 +332,11 @@ public:
     mutable sigc::signal<void, const VariableSafePtr, const UString&>
                                       variable_dereferenced_signal;
 
+    mutable sigc::signal<void,
+                         const VariableSafePtr,
+                         const UString&> variable_visualized_signal;
+    
+
     mutable sigc::signal<void, int, const UString&> got_target_info_signal;
 
     mutable sigc::signal<void> running_signal;
@@ -1174,7 +1187,7 @@ public:
                    && conf_mgr->get_key_value (a_key,
                                                enable_pretty_printing,
                                                a_namespace)) {
-            ;
+            queue_command (Command ("-enable-pretty-printing"));
         } else if (a_key == CONF_KEY_DISASSEMBLY_FLAVOR
                    && conf_mgr->get_key_value (a_key,
                                                disassembly_flavor,
@@ -1762,6 +1775,19 @@ struct OnCommandDoneHandler : OutputHandler {
             IDebugger::BreakpointsSlot slot =
                 a_in.command ().get_slot<IDebugger::BreakpointsSlot> ();
             slot (m_engine->get_cached_breakpoints ());
+        } else if (a_in.command ().name () == "set-variable-visualizer") {
+            VariableSafePtr var = a_in.command ().variable ();
+            THROW_IF_FAIL (var);
+            var->visualizer (a_in.command ().tag0 ());
+            if (a_in.command ().has_slot ()) {
+                LOG_DD ("set-variable-visualizer command has a slot");
+                ConstVariableSlot slot =
+                    a_in.command ().get_slot<ConstVariableSlot> ();
+                slot (var);
+            } else {
+                LOG_DD ("set-variable-visualizer command "
+                        "does not have a slot");
+            }
         }
 
         // So, if we are still attached to the target and we receive
@@ -2697,10 +2723,11 @@ struct OnCreateVariableHandler : public OutputHandler
 
     void do_handle (CommandAndOutput &a_in)
     {
+        VariableSafePtr var = a_in.output ().result_record ().variable ();
+
         // Set the name of the variable to the name that got stored
         // in the tag0 member of the command.
-        a_in.output ().result_record ().variable ()->name
-                                                (a_in.command ().tag0 ());
+        var->name (a_in.command ().tag0 ());
 
         // Call the slot associated to IDebugger::create_variable (), if
         // any.
@@ -2708,13 +2735,15 @@ struct OnCreateVariableHandler : public OutputHandler
             LOG_DD ("calling IDebugger::create_variable slot");
             typedef sigc::slot<void, IDebugger::VariableSafePtr> SlotType;
             SlotType slot = a_in.command ().get_slot<SlotType> ();
-            slot (a_in.output ().result_record ().variable ());
+            slot (var);
         }
         LOG_DD ("emit IDebugger::variable_create_signal");
-        // Emit the general IDebugger::variable_create_signal () signal
-        m_engine->variable_created_signal ().emit
-                            (a_in.output ().result_record ().variable (),
-                             a_in.command ().cookie ());
+        // Emit the general IDebugger::variable_create_signal ()
+        // signal
+        if (a_in.command ().should_emit_signal ())
+            m_engine->variable_created_signal ().emit
+                (var, a_in.command ().cookie ());
+
         if (m_engine->get_state () != IDebugger::PROGRAM_EXITED
             || m_engine->get_state () != IDebugger::NOT_STARTED) {
             m_engine->set_state (IDebugger::READY);
@@ -2808,8 +2837,9 @@ struct OnUnfoldVariableHandler : public OutputHandler {
         }
 
         // Now tell the world we have an unfolded variable.
-        m_engine->variable_unfolded_signal ().emit
-                                    (parent_var, a_in.command ().cookie ());
+        if (a_in.command ().should_emit_signal ())
+            m_engine->variable_unfolded_signal ().emit
+                (parent_var, a_in.command ().cookie ());
     }
 };// End struct OnUnfoldVariableHandler
 
@@ -3484,14 +3514,30 @@ GDBEngine::variable_dereferenced_signal () const
     return m_priv->variable_dereferenced_signal;
 }
 
-sigc::signal<void, const std::map<IDebugger::register_id_t, UString>&, const UString& >&
+/// A signal emitted upon completion of
+/// GDBEngine::revisualize_variable.
+///
+/// The first parameter of the slot is the variable that has been
+/// re-visualized and the second is the cookie passed to
+/// GDBEngine::revisualize_variable.
+sigc::signal<void, const VariableSafePtr, const UString&>&
+GDBEngine::variable_visualized_signal () const
+{
+    return m_priv->variable_visualized_signal;
+}
+
+sigc::signal<void,
+             const std::map<IDebugger::register_id_t, UString>&,
+             const UString& >&
 GDBEngine::register_names_listed_signal () const
 {
 
     return m_priv->register_names_listed_signal;
 }
 
-sigc::signal<void, const std::map<IDebugger::register_id_t, UString>&, const UString& >&
+sigc::signal<void,
+             const std::map<IDebugger::register_id_t, UString>&,
+             const UString& >&
 GDBEngine::register_values_listed_signal () const
 {
 
@@ -3661,26 +3707,246 @@ GDBEngine::on_stopped_signal (IDebugger::StopReason a_reason,
     NEMIVER_CATCH_NOX
 }
 
+/// Slot called from revisualize_variable_real.
+///
+/// Evaluates the expression of the given variable and schedules the
+/// unfolding of the variable upon completion of the expression
+/// evaluation.  Upon unfolding of the variable, revisualization is
+/// scheduled for the member variables, if any.  That revisualization
+/// uses the visualization given in parameter.
+///
+/// \param a_var the variable which expression to evaluate.
+///
+/// \param a_visualizer the pretty printer visualizer to use for the
+/// revisualization of the children member variables that will appear
+/// as the result of the scheduled unfolding.
+///
+/// \param a_slot the slot to call upon completion of the evaluation
+/// of the expression of this a_var.
 void
-GDBEngine::on_detached_from_target_signal ()
+GDBEngine::on_rv_eval_var (const VariableSafePtr a_var,
+                           const UString &a_visualizer,
+                           const ConstVariableSlot &a_slot)
 {
-    NEMIVER_TRY
+    NEMIVER_TRY;
+
+    evaluate_variable_expr
+        (a_var,
+         sigc::bind
+         (sigc::mem_fun
+          (*this, &GDBEngine::on_rv_unfold_var),
+          a_visualizer, a_slot),
+         "");
+
+    NEMIVER_CATCH_NOX;
+}
+
+/// Slot called from GDBEngine::on_rv_eval_var.
+///
+/// Unfolds the given variable and schedules lazy revisualization on
+/// its member variables if any.  The unfolding is done using a given
+/// variable revisualizer.
+///
+/// \param a_var the variable to unfold.
+///
+/// \param a_visualizer to use for revisualization of the member
+/// variables, if any.
+///
+/// \param a_slot the slot to call upon completion of the unfolding.
+/// The slot takes a_var in argument.
+void
+GDBEngine::on_rv_unfold_var (const VariableSafePtr a_var,
+                             const UString &a_visualizer,
+                             const ConstVariableSlot &a_slot)
+{
+    NEMIVER_TRY;
+    
+    unfold_variable_with_visualizer (a_var, a_visualizer, a_slot);
+
+    NEMIVER_CATCH_NOX;
+}
+
+/// Callback slot invoked from unfold_variable, set by
+/// GDBEngine::unfold_variable_with_visualizer.
+///
+/// It triggers the setting of the pretty-printing visualizer of each
+/// member variable of a given variable.  Once each member variable
+/// has seen its visualizer set, the initial variable is unfolded.
+/// The resulting children variables will be unfolded and rendered
+/// using the visualize that got set on their children.
+///
+/// \param a_var the variable to act upon.  The member variables of
+/// this one are the ones that are going to see their visualizer set.
+/// This variable will then be unfolded.
+///
+/// \param a_visualizer the vizualizer to set on the member variables
+/// of a_var.
+///
+/// \param a_slot the slot to call upon completion of the unfolding of
+/// a_var that happens after the visualizer setting on each member of
+/// a_var.
+void
+GDBEngine::on_rv_set_visualizer_on_members (const VariableSafePtr a_var,
+                                            const UString &a_visualizer,
+                                            const ConstVariableSlot &a_slot)
+{
+    NEMIVER_TRY;
+
+    IDebugger::VariableList::iterator it = a_var->members ().begin (),
+        end = a_var->members ().end ();
 
+    if (it != end)
+        set_variable_visualizer
+            (*it,
+             a_visualizer,
+             sigc::bind
+             (sigc::mem_fun
+              (*this,
+               &GDBEngine::on_rv_set_visualizer_on_next_sibling),
+              a_visualizer, it, end, a_slot));
+
+    NEMIVER_CATCH_NOX;
+}
+
+/// This is a callback slot called from
+/// GDBEngine::set_variable_visualizer, connected by
+/// GDBEngine::on_rv_set_visualizer_on_members.
+///
+/// It sets the pretty-printing visualizer for the next sibling
+/// variable.  Once it reached the last sibling, it unfolds the parent
+/// variable, forcing the the re-printing of the siblings of the this
+/// function walked through, with a the new visualizer it did set.
+///
+/// \param a_var the variable which visualizer got set at the previous
+/// invocation of this function.
+///
+/// \param a_member_it an iterator pointing to the previous sibling
+/// variable which visualuzer got set.  So this function is going to
+/// set the visualizer of ++a_member_it.
+///
+/// \param a_members_end  an iterator pointing to right after the last
+/// slibling variable we need to walk.
+///
+/// \param a_slot the callback slot to invoke once the parent variable
+/// of a_var has been unfolded.
+void
+GDBEngine::on_rv_set_visualizer_on_next_sibling
+(const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ IDebugger::VariableList::iterator a_member_it,
+ IDebugger::VariableList::iterator a_members_end,
+ const ConstVariableSlot &a_slot)
+{
+    NEMIVER_TRY;
+
+    THROW_IF_FAIL (a_member_it != a_members_end);
+
+    ++a_member_it;
+    if (a_member_it != a_members_end) {
+        set_variable_visualizer
+            (*a_member_it,
+             a_visualizer,
+             sigc::bind
+             (sigc::mem_fun
+              (*this,
+               &GDBEngine::on_rv_set_visualizer_on_next_sibling),
+              a_visualizer, a_member_it, a_members_end, a_slot));
+    } else {
+        IDebugger::VariableList::iterator it;
+        IDebugger::VariableSafePtr parent = a_var->parent ();
+        // This invalidates a_member_it and a_members_end iterators.
+        parent->members ().clear ();
+        unfold_variable (parent,
+                         sigc::bind
+                         (sigc::mem_fun (*this, &GDBEngine::on_rv_flag),
+                          a_visualizer, a_slot),
+                         "");
+    }
+
+    NEMIVER_CATCH_NOX;
+}
+
+/// Slot called by GDBEngine::on_rv_unfold_var.
+///
+/// Locally set the visualizer of each member variable of the given
+/// variable and flag them as needing revisualization.  Later, when
+/// any of these member variables will be about to be unfolded
+/// GDBEngine::unfold_variable is going to actually unfold them using
+/// that visualizer.  I.e, the member variables of that member
+/// variable are going to be rendered using that visualizer.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_visualizer the visualizer to set on the member variables
+/// of a_var if any.
+///
+/// \param a_slot the slot to call upon completion of this function.
+void
+GDBEngine::on_rv_flag (const VariableSafePtr a_var,
+                       const UString &a_visualizer,
+                       const ConstVariableSlot &a_slot)
+{
+    NEMIVER_TRY;
+
+    THROW_IF_FAIL (a_var);
+    
+    IDebugger::VariableList::iterator it;
+    for (it = a_var->members ().begin ();
+         it != a_var->members ().end ();
+         ++it) {
+        (*it)->visualizer (a_visualizer);
+        (*it)->needs_revisualizing (true);
+    }
+
+    if (a_slot)
+        a_slot (a_var);
+
+    NEMIVER_CATCH_NOX;
+}
+
+/// Unfold a variable, using a given visualizer to render the children
+/// variable objects resulting from the unfolding.
+///
+/// This has a lot of kludge as GDB doesn't
+void
+GDBEngine::unfold_variable_with_visualizer (const VariableSafePtr a_var,
+                                            const UString &a_visualizer,
+                                            const ConstVariableSlot &a_slot)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    unfold_variable
+        (a_var,
+         sigc::bind
+         (sigc::mem_fun
+          (*this, &GDBEngine::on_rv_set_visualizer_on_members),
+          a_visualizer, a_slot),
+         "",
+         /*a_should_emit_signal*/false);
+}
+
+/// Signal handler called when GDBEngine::detached_from_target_signal
+/// is emitted.
+void
+GDBEngine::on_detached_from_target_signal ()
+{
+    NEMIVER_TRY;
 
     m_priv->is_attached = false;
 
-    NEMIVER_CATCH_NOX
+    NEMIVER_CATCH_NOX;
 }
 
+/// Signal handler called when GDBEngine::program_finished_signal is
+/// emitted.
 void
 GDBEngine::on_program_finished_signal ()
 {
-    NEMIVER_TRY
-
+    NEMIVER_TRY;
 
     m_priv->is_attached = false;
 
-    NEMIVER_CATCH_NOX
+    NEMIVER_CATCH_NOX;
 }
 
 //******************
@@ -4821,7 +5087,109 @@ GDBEngine::dereference_variable (const VariableSafePtr &a_var,
     return true;
 }
 
-/// Lists the source files htat make up the executable
+/// Re-build a given variable using the relevant visualizer if
+/// pretty-printing is in effect, or no visualizer if pretty printing
+/// is turned off.  Bear in mind that for now, once pretty printing
+/// has been turned on, GDB doesn't support turning it back off.  To
+/// turn it off in practise, one needs to set the 'None' visualizer for
+/// each variable we want to visualize.
+///
+/// This function clears the current member variables of the given
+/// variable, sets its relevant visualizer, re-evaluates its
+/// expression, unfolds it and schedules a similar set of actions for
+/// each of the member variables.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_slot the slot function to call once a_var has been
+/// unfolded as part part of the revisualization process.
+void
+GDBEngine::revisualize_variable (const VariableSafePtr a_var,
+                                 const ConstVariableSlot &a_slot)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    THROW_IF_FAIL (m_priv);
+
+
+    NEMIVER_TRY;
+
+    get_conf_mgr ().get_key_value (CONF_KEY_PRETTY_PRINTING,
+                                   m_priv->enable_pretty_printing);
+
+    NEMIVER_CATCH_NOX;
+
+    revisualize_variable (a_var, m_priv->enable_pretty_printing, a_slot);
+}
+
+/// A subroutine of GDBEngine::revisualize_variable above.
+///
+/// This function clears the current member variables of the given
+/// variable, sets its relevant visualizer, re-evaluates its
+/// expression, unfolds it and schedules a similar set of actions for
+/// each of the member variables.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_pretty_printing a flag saying whether to turn pretty
+/// printing on or off.
+///
+/// \param a_slot a slot to be called when the revisualization is
+/// done.  It is called when a_var is effectively unfolded.
+void
+GDBEngine::revisualize_variable (IDebugger::VariableSafePtr a_var,
+                                 bool a_pretty_printing,
+                                 const ConstVariableSlot &a_slot)
+{
+    a_var->members ().clear ();
+    UString v;
+    if (a_pretty_printing)
+        v = GDB_DEFAULT_PRETTY_PRINTING_VISUALIZER;
+    else
+        v = GDB_NULL_PRETTY_PRINTING_VISUALIZER;
+    revisualize_variable_real (a_var, v, a_slot);
+}
+
+/// A subroutine of revisualize_variable.
+///
+/// Here is the actual sequence of action taken:
+///
+/// 1/ Set its visualizer.  That is instruct the backend to use that
+///    visualizer to visualize this variable.
+/// 2/ Evaluate the expression of the variable
+/// 3/ Unfold variable with visualizer <-- TODO: need to write this.
+///    3.1/ Unfold it w/o signaling
+///    3.2/ Set visualizers of each children
+///    3.3/ Unfold again, with normal signaling
+///    3.4/ Mark each children variable as needing to go to 3 whenever
+///         they are going to be revisualized.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_visualizer the visualizer to use for revisualizing the
+/// variable.
+///
+/// \param a_slot the slot function to call upon completion of step 4.
+void
+GDBEngine::revisualize_variable_real (IDebugger::VariableSafePtr a_var,
+                                      const UString& a_visualizer,
+                                      const ConstVariableSlot &a_slot)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    THROW_IF_FAIL (a_var);
+
+    a_var->needs_revisualizing (false);
+
+    set_variable_visualizer
+        (a_var, a_visualizer,
+         sigc::bind
+         (sigc::mem_fun
+          (*this, &GDBEngine::on_rv_eval_var),
+          a_visualizer, a_slot));
+}
+
+/// Lists the source files that make up the executable
 void
 GDBEngine::list_files (const UString &a_cookie)
 {
@@ -5295,6 +5663,24 @@ GDBEngine::create_variable (const UString &a_name,
                      a_cookie);
 }
 
+/// Create a GDB-side variable object for a given variable.  The name
+/// of the variable must be  accessible from the current frame.
+///
+/// Emits IDebugger::variable_created_signal upon creation of the
+/// GDB-side variable object.
+/// 
+/// \param a_name the name of the variable to create.
+///
+/// \param a_s the slot callback function to invoke upon creation of
+/// the GDB-side variable object.
+///
+/// \param a_cookie a string value passed to the the
+/// IDebugger::variable_created_signal emitted upon creation of the
+/// server side variable object.
+///
+/// \param a_should_emit_signal if set to TRUE, emit the
+/// IDebugger::variable_created_signal signal.  Otherwise that signal
+/// is not emitted.
 void
 GDBEngine::create_variable (const UString &a_name ,
                             const ConstVariableSlot &a_slot,
@@ -5302,6 +5688,33 @@ GDBEngine::create_variable (const UString &a_name ,
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
+    create_variable (a_name, a_slot, a_cookie,
+                     /*a_should_emit_signal=*/true);
+}
+
+/// Create a GDB-side variable object for a given variable.  The name
+/// of the variable must be  accessible from the current frame.
+///
+/// \param a_name the name of the variable to create.
+///
+/// \param a_slot the slot callback function to invoke upon creation
+/// of the GDB-side variable object.
+///
+/// \param a_cookie a string value passed to the the
+/// IDebugger::variable_created_signal emitted upon creation of the
+/// server side variable object.
+///
+/// \param a_should_emit_signal if set to TRUE, emit the
+/// IDebugger::variable_created_signal signal.  Otherwise that signal
+/// is not emitted.
+void
+GDBEngine::create_variable (const UString &a_name,
+                            const ConstVariableSlot &a_slot,
+                            const UString &a_cookie,
+                            bool a_should_emit_signal)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
     if (a_name.empty ()) {
         LOG ("got empty name");
         return;
@@ -5318,6 +5731,7 @@ GDBEngine::create_variable (const UString &a_name ,
                      a_cookie);
     command.tag0 (a_name);
     command.set_slot (a_slot);
+    command.should_emit_signal (a_should_emit_signal);
     queue_command (command);
 }
 
@@ -5349,6 +5763,20 @@ GDBEngine::delete_variable (const VariableSafePtr a_var,
     queue_command (command);
 }
 
+/// Unfold a given variable.
+///
+/// Query the backend for the member variables of the given variable.
+/// This is not recursive.  Each member will in turn need to be
+/// unfolded to get its member variables.
+///
+/// Upon completion of the backend side of this command, signal
+/// IDebugger::variable_unfolded_signal is emitted, with a_var as an
+/// argument.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_cookie the cookie to pass to the
+/// IDebugger::variable_unfolded_signal signal.
 void
 GDBEngine::unfold_variable (const VariableSafePtr a_var,
                             const UString &a_cookie)
@@ -5359,6 +5787,23 @@ GDBEngine::unfold_variable (const VariableSafePtr a_var,
                      a_cookie);
 }
 
+/// A subroutine of GDBEngine::unfold_variable above.
+///
+/// Query the backend for the member variables of the given variable.
+/// This is not recursive.  Each member will in turn need to be
+/// unfolded to get its member variables.
+///
+/// Upon completion of the backend side of this command, signal
+/// IDebugger::variable_unfolded_signal is emitted, with a_var as an
+/// argument.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_slot a slot function to be invoked upon completion of the
+/// backend side of this command.
+///
+/// \param a_cookie a string that is going to be passed to signal
+/// IDebugger::variable_unfolded_signal.
 void
 GDBEngine::unfold_variable (const VariableSafePtr a_var,
                             const ConstVariableSlot &a_slot,
@@ -5366,7 +5811,45 @@ GDBEngine::unfold_variable (const VariableSafePtr a_var,
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
+    unfold_variable (a_var, a_slot, a_cookie,
+                     /*a_should_emit_signal=*/true);
+}
+
+/// A subroutine of GDBEngine::unfold_variable above.
+///
+/// Query the backend for the member variables of the given variable.
+/// This is not recursive.  Each member will in turn need to be
+/// unfolded to get its member variables.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_slot a slot function to be invoked upon completion of the
+/// backend side of this command.
+///
+/// \param a_cookie a string that is going to be passed to signal
+/// IDebugger::variable_unfolded_signal.
+///
+/// \param a_should_emit_signal if TRUE, emits
+/// IDebugger::variable_unfolded_signal upon completion of the GDB
+/// side of this command.  Otherwise, no signal is emitted.
+void
+GDBEngine::unfold_variable (VariableSafePtr a_var,
+                            const ConstVariableSlot &a_slot,
+                            const UString &a_cookie,
+                            bool a_should_emit_signal)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
     THROW_IF_FAIL (a_var);
+
+    // If this variable was asked to be revisualized, let the backend
+    // use the visualizer for it during its unfolding process.
+    if (a_var->needs_revisualizing ()) {
+        a_var->needs_revisualizing (false);
+        return unfold_variable_with_visualizer (a_var,
+                                                a_var->visualizer (),
+                                                a_slot);
+    }
     if (a_var->internal_name ().empty ()) {
         UString qname;
         a_var->build_qualified_internal_name (qname);
@@ -5381,6 +5864,7 @@ GDBEngine::unfold_variable (const VariableSafePtr a_var,
                      a_cookie);
     command.variable (a_var);
     command.set_slot (a_slot);
+    command.should_emit_signal (a_should_emit_signal);
     queue_command (command);
 }
 
@@ -5560,41 +6044,65 @@ GDBEngine::set_variable_format (const VariableSafePtr a_var,
     queue_command (command);
 }
 
+/// Set the relevant confmgr key enabling or disabling
+/// pretty-printing.
+///
+/// \param a_flag TRUE to enable pretty-printing, false otherwise.
 void
-GDBEngine::disable_pretty_printing ()
-{
-    // Doing it this way for now b/c you can't change this in GDB on
-    // the fly at the moment.
-    m_priv->enable_pretty_printing = false;
-    get_conf_mgr ().get_key_value (CONF_KEY_PRETTY_PRINTING,
-                                   m_priv->enable_pretty_printing);
+GDBEngine::enable_pretty_printing (bool a_flag)
+{
+    // Note that disabling (passing false) this feature doesn't work
+    // in GDB </grin>.
+    //
+    // The workaround to disabling the feature is to set the
+    // visualizer to None on all subsequent varobjs that are created.
+    // For those that are already created, we basically set the
+    // visualizer to None, re-evaluate the expression of the variable
+    // and do that recursively for the member varobjs.
+
+    // Don't bother changing anything if we are asked to do what we
+    // already have.
+    if (a_flag == m_priv->enable_pretty_printing)
+        return;
+
+    // Note that on_conf_key_changed_signal instructs GDB to enable
+    // pretty printing when once the key is set to TRUE.
+    get_conf_mgr ().set_key_value (CONF_KEY_PRETTY_PRINTING,
+                                   a_flag);
 }
 
-/// Set the variable vizualizer used by the GDB Pretty Printing system
-/// to print the value of a given variable.
+/// Instruct GDB to set the variable vizualizer used by the GDB Pretty
+/// Printing system to print the value of a given variable.
+/// 
 /// \param a_var the variable to set the vizualizer for.
+/// 
 /// \param a_vizualizer a string representing the vizualizer to set
 /// for this variable. If you don't want any vizualizer to be set,
 /// then set this variableto "None". If you want the default
 /// vizualizer for this type to be set, then set this variable to
 /// "gdb.default_visualizer".
+///
+/// \param a_slot the slot function called when GDB finishes to set
+/// the visualizer for this variable.
 void
-GDBEngine::set_variable_vizualizer (const VariableSafePtr a_var,
-				    const std::string &a_vizualizer,
-				    const UString &a_cookie)
+GDBEngine::set_variable_visualizer (const VariableSafePtr a_var,
+				    const std::string &a_visualizer,
+				    const ConstVariableSlot &a_slot)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
     THROW_IF_FAIL (a_var);
     THROW_IF_FAIL (!a_var->internal_name ().empty ());
 
-    UString cmd_str = "-var-set-vizualizer ";
+    UString cmd_str = "-var-set-visualizer ";
     cmd_str += a_var->internal_name () + " ";
-    cmd_str += a_vizualizer;
+    cmd_str += a_visualizer;
 
-    Command command ("set-variable-vizualizer",
-                     cmd_str, a_cookie);
+    Command command ("set-variable-visualizer",
+                     cmd_str);
     command.variable (a_var);
+    command.set_slot (a_slot);
+    command.tag0 (a_visualizer);
     queue_command (command);
 }
 
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index 3d670bb..0285470 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -151,6 +151,9 @@ public:
     sigc::signal<void, const VariableSafePtr, const UString&>&
                                       variable_dereferenced_signal () const;
 
+    sigc::signal<void, const VariableSafePtr, const UString&>&
+      variable_visualized_signal () const;
+
     sigc::signal<void, int, const UString&>& got_target_info_signal () const ;
 
     sigc::signal<void>& running_signal () const;
@@ -222,6 +225,30 @@ public:
     void on_detached_from_target_signal ();
 
     void on_program_finished_signal ();
+    void on_rv_eval_var (const VariableSafePtr,
+			 const UString&,
+			 const ConstVariableSlot&);
+    void on_rv_unfold_var (const VariableSafePtr,
+			   const UString&,
+			   const ConstVariableSlot&);
+    void on_rv_set_visualizer_on_members (const VariableSafePtr,
+					  const UString&,
+					  const ConstVariableSlot&);
+    void on_rv_set_visualizer_on_next_sibling
+      (const VariableSafePtr,
+       const UString&,
+       IDebugger::VariableList::iterator,
+       IDebugger::VariableList::iterator,
+       const ConstVariableSlot&);
+
+    void on_rv_flag (const VariableSafePtr,
+		     const UString&,
+		     const ConstVariableSlot&);
+
+    void unfold_variable_with_visualizer (const VariableSafePtr,
+					  const UString &a_visualizer,
+					  const ConstVariableSlot&);
+
     //***************
     //</signal handlers>
     //***************
@@ -468,6 +495,17 @@ public:
     bool dereference_variable (const VariableSafePtr &a_var,
                                const UString &a_cookie);
 
+    void revisualize_variable (const VariableSafePtr a_var,
+			       const ConstVariableSlot &a_slot);
+
+    void revisualize_variable (const VariableSafePtr a_var,
+			       bool a_toggle_pretty_printing,
+			       const ConstVariableSlot &a_slot);
+
+    void revisualize_variable_real (IDebugger::VariableSafePtr,
+				    const UString&,
+				    const ConstVariableSlot &a_slot);
+
     void list_files (const UString &a_cookie);
 
     bool extract_proc_info (Output &a_output,
@@ -534,6 +572,11 @@ public:
                           const ConstVariableSlot &a_s,
                           const UString &a_cookie="");
 
+    void create_variable (const UString &a_name,
+                          const ConstVariableSlot &a_s,
+                          const UString &a_cookie,
+			  bool a_should_emit_signal);
+
     void delete_variable (const VariableSafePtr a_var,
                           const UString &a_cookie);
 
@@ -543,10 +586,16 @@ public:
 
     void unfold_variable (VariableSafePtr a_var,
                           const UString &a_cookie);
+
     void unfold_variable (VariableSafePtr a_var,
                           const ConstVariableSlot &a_s,
                           const UString &a_cookie);
 
+    void unfold_variable (VariableSafePtr a_var,
+                          const ConstVariableSlot &a_s,
+                          const UString &a_cookie,
+			  bool a_should_emit_signal);
+
     void assign_variable (const VariableSafePtr a_var,
                           const UString &a_expression,
                           const UString &a_cookie);
@@ -587,11 +636,11 @@ public:
 			      const Variable::Format a_format,
 			      const UString &a_cookie);
 
-    void disable_pretty_printing ();
+    void enable_pretty_printing (bool a_flag);
 
-    void set_variable_vizualizer (const VariableSafePtr a_var,
+    void set_variable_visualizer (const VariableSafePtr a_var,
 				  const std::string &a_vizualizer,
-				  const UString &a_cookie);
+				  const ConstVariableSlot &a_slot);
 };//end class GDBEngine
 
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 5f130de..93a0901 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -345,6 +345,10 @@ public:
     typedef sigc::slot<void, const map<int, IDebugger::VariableList>& >
         FrameArgsSlot;
 
+    typedef sigc::slot<void, const VariableSafePtr> ConstVariableSlot;
+    typedef sigc::slot<void, const VariableList> ConstVariableListSlot;
+    typedef sigc::slot<void, const UString&> ConstUStringSlot;
+
     class Variable : public Object {
     public:
         enum Format {
@@ -373,6 +377,16 @@ public:
         UString m_name_caption;
         UString m_value;
         UString m_type;
+        // When using GDB pretty-printers, this is a string naming the
+        // pretty printer used to visualize this variable. As
+        // disabling pretty printing is not possible globally in GDB
+        // we need to use this even when the user doesn't want to
+        // change it.  Setting it to "" should do the right thing: if
+        // pretty printing is enabled, the variable will be displayed
+        // using  the default pretty printer; if pretty printing is
+        // disabled the variable would be displayed using no pretty
+        // printer.
+        UString m_visualizer;
         Variable *m_parent;
         //if this variable is a pointer,
         //it can be dereferenced. The variable
@@ -386,6 +400,7 @@ public:
         UString m_path_expression;
         bool m_in_scope;
         Format m_format;
+        bool m_needs_revisualizing;
 
     public:
         Variable (const UString &a_internal_name,
@@ -400,7 +415,8 @@ public:
             m_parent (0),
             m_num_expected_children (0),
             m_in_scope (a_in_scope),
-            m_format (UNDEFINED_FORMAT)
+            m_format (UNDEFINED_FORMAT),
+            m_needs_revisualizing (false)
         {
         }
 
@@ -413,7 +429,9 @@ public:
             m_type (a_type),
             m_parent (0),
             m_num_expected_children (0),
-            m_in_scope (a_in_scope)
+            m_in_scope (a_in_scope),
+            m_format (UNDEFINED_FORMAT),
+            m_needs_revisualizing (false)
 
         {
         }
@@ -422,19 +440,25 @@ public:
             : m_name (a_name),
             m_parent (0),
             m_num_expected_children (0),
-            m_in_scope (true)
+            m_in_scope (true),
+            m_format (UNDEFINED_FORMAT),
+            m_needs_revisualizing (false)
                 
         {}
 
         Variable ()
             : m_parent (0),
             m_num_expected_children (0),
-            m_in_scope (true)
+            m_in_scope (true),
+            m_format (UNDEFINED_FORMAT),
+            m_needs_revisualizing (false)
                 
         {}
 
         const VariableList& members () const {return m_members;}
 
+        VariableList& members () {return m_members;}
+
         /// Returns the Nth member variable, if any.
         /// Please note that this function has O(n) complexity. So use it with
         /// care.
@@ -540,6 +564,9 @@ public:
         void type (const UString &a_type) {m_type = a_type;}
         void type (const string &a_type) {m_type = a_type;}
 
+        const UString& visualizer () const {return m_visualizer;}
+        void visualizer (const UString &a) {m_visualizer = a;}
+
         /// Return true if this instance of Variable has a parent variable,
         /// false otherwise.
         bool has_parent () const
@@ -781,6 +808,9 @@ public:
         Format format () const {return m_format;}
         void format (Format a_format) {m_format = a_format;}
 
+        bool needs_revisualizing () const {return m_needs_revisualizing;}
+        void needs_revisualizing (bool a) {m_needs_revisualizing = a;}
+
     };//end class Variable
 
     enum State {
@@ -983,6 +1013,9 @@ public:
                          const UString&/*cookie*/>&
                                       variable_dereferenced_signal () const=0;
 
+    sigc::signal<void, const VariableSafePtr, const UString&>&
+      variable_visualized_signal () const;
+
     virtual sigc::signal<void, const vector<UString>&, const UString&>&
                             files_listed_signal () const = 0;
 
@@ -1286,6 +1319,9 @@ public:
     virtual bool dereference_variable (const VariableSafePtr &a_var,
                                        const UString &a_cookie="") = 0;
 
+    virtual void revisualize_variable (const VariableSafePtr a_var,
+                                       const ConstVariableSlot &a_slot) = 0;
+
     virtual void list_files (const UString &a_cookie="") = 0;
 
     virtual void list_register_names (const UString &a_cookie="") = 0;
@@ -1335,10 +1371,6 @@ public:
                                     bool a_pure_asm = true,
                                     const UString &a_cookie = "") = 0;
 
-    typedef sigc::slot<void, const VariableSafePtr> ConstVariableSlot;
-    typedef sigc::slot<void, const VariableList> ConstVariableListSlot;
-    typedef sigc::slot<void, const UString&> ConstUStringSlot;
-
     virtual void create_variable (const UString &a_name,
                                   const UString &a_cookie = "") = 0;
 
@@ -1399,11 +1431,8 @@ public:
                                       const Variable::Format a_format,
                                       const UString &a_cookie = "") = 0;
 
-    virtual void disable_pretty_printing () = 0;
+    virtual void enable_pretty_printing (bool a_flag = true) = 0;
 
-    virtual void set_variable_vizualizer (const VariableSafePtr a_var,
-                                          const std::string &a_vizualizer,
-                                          const UString &a_cookie = "") = 0;
 };//end IDebugger
 
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 435d50a..792b26f 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -920,6 +920,8 @@ struct DBGPerspective::Priv {
     bool use_launch_terminal;
     int num_instr_to_disassemble;
     bool asm_style_pure;
+    bool enable_pretty_printing;
+    bool pretty_printing_toggled;
 #ifdef WITH_SOURCEVIEWMM2
     Glib::RefPtr<gtksourceview::SourceStyleScheme> editor_style;
 #endif // WITH_SOURCEVIEWMM2
@@ -972,6 +974,8 @@ struct DBGPerspective::Priv {
         use_launch_terminal (false),
         num_instr_to_disassemble (NUM_INSTR_TO_DISASSEMBLE),
         asm_style_pure (true),
+        enable_pretty_printing (true),
+        pretty_printing_toggled (false),
         mouse_in_source_editor_x (0),
         mouse_in_source_editor_y (0),
         in_show_var_value_at_pos_transaction (false),
@@ -2185,6 +2189,12 @@ DBGPerspective::on_shutdown_signal ()
     NEMIVER_CATCH
 }
 
+/// Function called whenever a the value of a configuration key
+/// changes on the sytem.
+///
+/// \param a_key the key which value changed
+///
+/// \param a_namespace the namespace of the key
 void
 DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
                                             const UString &a_namespace)
@@ -2290,9 +2300,18 @@ DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
         conf_mgr.get_key_value (a_key,
                                 m_priv->asm_style_pure,
                                 a_namespace);
+    } else if (a_key == CONF_KEY_PRETTY_PRINTING) {
+        bool e = false;
+        conf_mgr.get_key_value (a_key, e, a_namespace);
+        if (m_priv->enable_pretty_printing != e) {
+            m_priv->enable_pretty_printing = e;
+            m_priv->pretty_printing_toggled = true;
+            get_local_vars_inspector ()
+                .visualize_local_variables_of_current_function ();
+        }
     }
 
-    NEMIVER_CATCH;
+    NEMIVER_CATCH
 }
 
 void
@@ -4895,7 +4914,8 @@ DBGPerspective::show_underline_tip_at_position
     LOG_FUNCTION_SCOPE_NORMAL_DD
     get_popup_tip ().show_at_position (a_x, a_y);
     get_popup_var_inspector ().set_variable (a_var,
-                                             true /* expand variable */);
+                                             true/*expand variable*/,
+                                             m_priv->pretty_printing_toggled);
 }
 
 VarInspector&
diff --git a/src/persp/dbgperspective/nmv-local-vars-inspector.cc b/src/persp/dbgperspective/nmv-local-vars-inspector.cc
index 8eb5e32..8ead5b3 100644
--- a/src/persp/dbgperspective/nmv-local-vars-inspector.cc
+++ b/src/persp/dbgperspective/nmv-local-vars-inspector.cc
@@ -380,6 +380,7 @@ public:
 
         Gtk::TreeModel::iterator parent_row_it;
         if (get_function_arguments_row_iterator (parent_row_it)) {
+            LOG_DD ("appending argument: " << a_var->name ());
             vutil::append_a_variable (a_var,
                                       *tree_view,
                                       tree_store,
@@ -409,6 +410,53 @@ public:
         }
     }
 
+    /// Graphically update a local variable that has been
+    /// re-visualized.
+    ///
+    /// Re-visualization means that the variable's members have been
+    /// erased and the variable has been re-built, probably using a
+    /// different visualizer, at the backend level.
+    ///
+    /// \param a_var the local variable to grpahically update.
+    void
+    update_a_visualized_local_variable (const IDebugger::VariableSafePtr a_var)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        THROW_IF_FAIL (tree_view);
+
+        Gtk::TreeModel::iterator parent_row_it, row_it;
+        if (get_local_variables_row_iterator (parent_row_it)) {
+            THROW_IF_FAIL (vutil::find_a_variable (a_var,
+                                                   parent_row_it,
+                                                   row_it));
+            vutil::visualize_a_variable (a_var, row_it,
+                                         *tree_view, tree_store);
+        }
+    }
+
+    /// Like update_a_visualized_local_variable, but for a function
+    /// argument.
+    ///
+    /// \param a_var the function argument variable to graphically
+    /// update.
+    void
+    update_a_visualized_function_arg (const IDebugger::VariableSafePtr a_var)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        THROW_IF_FAIL (tree_view);
+
+        Gtk::TreeModel::iterator parent_row_it, row_it;
+        if (get_function_arguments_row_iterator (parent_row_it)) {
+            THROW_IF_FAIL (vutil::find_a_variable (a_var, parent_row_it,
+                                                   row_it));
+            vutil::visualize_a_variable (a_var, row_it,
+                                         *tree_view,
+                                         tree_store);
+        }
+    }
+
     /// \return true if the variable was found in the TreeModel, false
     ///  otherwise. If the variable was found, the function updates it.
     bool
@@ -842,6 +890,47 @@ public:
         NEMIVER_CATCH
     }
 
+    /// Signal handler called when a local variable has been
+    /// re-visualized, probably using a new pretty-printing
+    /// visualizer.
+    ///
+    /// This function graphically updates the re-visualized local
+    /// variable.
+    ///
+    /// \param a_var the re-visualized variable to act upon.
+    void
+    on_local_var_visualized_signal (const IDebugger::VariableSafePtr a_var)
+
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY;
+
+        update_a_visualized_local_variable (a_var);
+
+        NEMIVER_CATCH;
+    }
+
+    /// Signal handler called when a function argument variable has
+    /// been re-visualized by the backend, probably with a new
+    /// pretty-printing visualizer.
+    ///
+    /// This function gaphically updates the re-visualized function
+    /// argument variable.
+    ///
+    /// \param a_arg the re-visualized argument variable to act upon.
+    void
+    on_function_arg_visualized_signal (const IDebugger::VariableSafePtr a_arg)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY;
+
+        update_a_visualized_function_arg (a_arg);
+
+        NEMIVER_CATCH;
+    }
+
     void
     on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
                                  const Gtk::TreeModel::Path a_var_node)
@@ -1154,6 +1243,26 @@ LocalVarsInspector::show_local_variables_of_current_function
                                              "");
 }
 
+/// Re-visualize the local variables of the current function, possibly
+/// using the a backend pretty-printing visualizer.
+void
+LocalVarsInspector::visualize_local_variables_of_current_function ()
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+    THROW_IF_FAIL (m_priv);
+    THROW_IF_FAIL (m_priv->debugger);
+
+    IDebugger::VariableList::const_iterator it;
+    for (it = m_priv->local_vars.begin ();
+         it != m_priv->local_vars.end ();
+         ++it)
+        m_priv->debugger->revisualize_variable
+            (*it,
+             sigc::mem_fun
+             (*m_priv,
+              &Priv::on_local_var_visualized_signal));
+}
+
 void
 LocalVarsInspector::re_init_widget ()
 {
diff --git a/src/persp/dbgperspective/nmv-local-vars-inspector.h b/src/persp/dbgperspective/nmv-local-vars-inspector.h
index ce89182..85d0df9 100644
--- a/src/persp/dbgperspective/nmv-local-vars-inspector.h
+++ b/src/persp/dbgperspective/nmv-local-vars-inspector.h
@@ -58,9 +58,10 @@ public:
     virtual ~LocalVarsInspector ();
     Gtk::Widget& widget () const;
     void set_local_variables
-                    (const std::list<IDebugger::VariableSafePtr> &a_vars);
+      (const std::list<IDebugger::VariableSafePtr> &a_vars);
     void show_local_variables_of_current_function
-                                        (const IDebugger::Frame &a_frame);
+      (const IDebugger::Frame &a_frame);
+    void visualize_local_variables_of_current_function ();
     void re_init_widget ();
 };//end LocalVarsInspector
 
diff --git a/src/persp/dbgperspective/nmv-var-inspector.cc b/src/persp/dbgperspective/nmv-var-inspector.cc
index e37f2f6..c95ad97 100644
--- a/src/persp/dbgperspective/nmv-var-inspector.cc
+++ b/src/persp/dbgperspective/nmv-var-inspector.cc
@@ -52,6 +52,7 @@ class VarInspector::Priv : public sigc::trackable {
     bool requested_variable;
     bool requested_type;
     bool expand_variable;
+    bool re_visualize;
     bool enable_contextual_menu;
     IDebuggerSafePtr debugger;
     // Variable that is being inspected
@@ -83,6 +84,7 @@ class VarInspector::Priv : public sigc::trackable {
     connect_to_signals ()
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
+
         Glib::RefPtr<Gtk::TreeSelection> selection =
                                         tree_view->get_selection ();
         THROW_IF_FAIL (selection);
@@ -176,17 +178,11 @@ class VarInspector::Priv : public sigc::trackable {
     }
 
     void
-    set_variable (const IDebugger::VariableSafePtr a_variable,
-                  bool a_expand)
+    graphically_set_variable (const IDebugger::VariableSafePtr a_variable,
+                              bool a_expand)
     {
-        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 ();
+            tree_store->children ().begin ();
         Gtk::TreeModel::iterator var_row;
         vutil::append_a_variable (a_variable,
                                   *tree_view,
@@ -206,6 +202,32 @@ class VarInspector::Priv : public sigc::trackable {
     }
 
     void
+    set_variable (const IDebugger::VariableSafePtr a_variable,
+                  bool a_expand,
+                  bool a_re_visualize)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        THROW_IF_FAIL (tree_view && tree_store);
+
+        re_visualize = a_re_visualize;
+
+        re_init_tree_view ();
+        delete_variable_if_needed ();
+        variable = a_variable;
+        if (a_re_visualize) {
+            debugger->revisualize_variable (a_variable,
+                                            sigc::bind
+                                            (sigc::mem_fun
+                                             (*this,
+                                              &Priv::on_var_revisualized),
+                                             a_expand));
+        } else {
+            graphically_set_variable (a_variable, a_expand);
+        }
+    }
+
+    void
     show_variable_type_in_dialog ()
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -335,7 +357,6 @@ class VarInspector::Priv : public sigc::trackable {
     // <signal handlers>
     // ******************
 
-
     void
     on_visited_variable_signal (const IDebugger::VariableSafePtr a_var)
     {
@@ -353,6 +374,19 @@ class VarInspector::Priv : public sigc::trackable {
     }
 
     void
+    on_var_revisualized (const IDebugger::VariableSafePtr a_var,
+                         bool a_expand)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY;
+
+        graphically_set_variable (a_var, a_expand);
+
+        NEMIVER_CATCH;
+    }
+
+    void
     on_tree_view_selection_changed_signal ()
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -474,11 +508,11 @@ class VarInspector::Priv : public sigc::trackable {
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
 
-        NEMIVER_TRY
+        NEMIVER_TRY;
 
-        set_variable (a_var, expand_variable);
+        set_variable (a_var, expand_variable, re_visualize);
 
-        NEMIVER_CATCH
+        NEMIVER_CATCH;
     }
 
     void
@@ -580,6 +614,7 @@ public:
           requested_variable (false),
           requested_type (false),
           expand_variable (false),
+          re_visualize (false),
           enable_contextual_menu (false),
           debugger (a_debugger),
           perspective (a_perspective),
@@ -599,7 +634,7 @@ public:
 };//end class VarInspector::Priv
 
 VarInspector::VarInspector (IDebuggerSafePtr a_debugger,
-                              IPerspective &a_perspective)
+                            IPerspective &a_perspective)
 {
     m_priv.reset (new Priv (a_debugger, a_perspective));
 }
@@ -619,11 +654,11 @@ VarInspector::widget () const
 
 void
 VarInspector::set_variable (IDebugger::VariableSafePtr a_variable,
-                             bool a_expand)
+                            bool a_expand, bool a_revisualize)
 {
     THROW_IF_FAIL (m_priv);
 
-    m_priv->set_variable (a_variable, a_expand);
+    m_priv->set_variable (a_variable, a_expand, a_revisualize);
 }
 
 void
diff --git a/src/persp/dbgperspective/nmv-var-inspector.h b/src/persp/dbgperspective/nmv-var-inspector.h
index 5de547b..406eacc 100644
--- a/src/persp/dbgperspective/nmv-var-inspector.h
+++ b/src/persp/dbgperspective/nmv-var-inspector.h
@@ -53,7 +53,8 @@ public:
     virtual ~VarInspector ();
     Gtk::Widget& widget () const;
     void set_variable (IDebugger::VariableSafePtr a_variable,
-                       bool a_expand = false);
+                       bool a_expand = false,
+		       bool a_re_visualize = false);
     void inspect_variable (const UString &a_variable_name,
                            bool a_expand = false);
     IDebugger::VariableSafePtr get_variable () const;
diff --git a/src/persp/dbgperspective/nmv-variables-utils.cc b/src/persp/dbgperspective/nmv-variables-utils.cc
index 4a078b5..2e4e113 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.cc
+++ b/src/persp/dbgperspective/nmv-variables-utils.cc
@@ -387,6 +387,9 @@ variables_match (const IDebugger::VariableSafePtr &a_var,
         return true;
     if (!var || !a_var)
         return false;
+    if (a_var->internal_name () == var->internal_name ())
+        return true;
+
     return var->equals_by_value (*a_var);
 }
 
@@ -546,30 +549,127 @@ append_a_variable (const IDebugger::VariableSafePtr a_var,
     if (!a_var) {
         return false;
     }
-    update_a_variable_node (a_var, a_tree_view, row_it,
+    if (!set_a_variable (a_var, a_tree_view, a_tree_store,
+                         row_it, a_truncate_type))
+        return false;
+    a_result = row_it;
+    return true;
+}
+
+/// (Re-)render a variable into the node holding its graphical
+/// representation.
+///
+/// \param a_var the variable to render
+///
+/// \param a_tree_view the treeview containing the graphical
+/// representation to set.
+///
+/// \param a_tree_store the treestore of the treeview.
+///
+/// \param a_row_it an iterator to the row of the graphical
+/// representation of the variable.
+///
+/// \param a_truncate_type if set to TRUE, the string representing the
+/// type is going to be truncated if it is too long.
+///
+/// \return TRUE upon successful completion
+bool
+set_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_row_it,
+                bool a_truncate_type)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+    THROW_IF_FAIL (a_tree_store);
+
+    if (!a_var) {
+        return false;
+    }
+
+    update_a_variable_node (a_var, a_tree_view, a_row_it,
                             a_truncate_type, true, true);
+
     list<IDebugger::VariableSafePtr>::const_iterator 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;
+        (*a_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,
+                           a_tree_store, a_row_it,
                            a_truncate_type);
     } 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_tree_store, a_row_it,
                                a_truncate_type);
         }
     }
-    a_result = row_it;
     return true;
 }
 
+/// Unlink the graphical nodes representing the member variables of
+/// the variable pointed to by the given row iterator.
+///
+/// \param a_row_it the iterator pointing at the graphical node which
+/// containing the variable which member variables we want to unlink.
+///
+/// \param a_store the treestore containing a_row_it.
+bool
+unlink_member_variable_rows (const Gtk::TreeModel::iterator &a_row_it,
+                             const Glib::RefPtr<Gtk::TreeStore> &a_store)
+{
+    IDebugger::VariableSafePtr var;
+
+    var = a_row_it->get_value (get_variable_columns ().variable);
+    if (!var)
+        return false;
+
+    vector<Gtk::TreePath> paths;
+    for (Gtk::TreeModel::iterator it = a_row_it->children ().begin ();
+	 it != a_row_it->children ().end ();
+	 ++it) {
+	var = it->get_value (get_variable_columns ().variable);
+	if (var)
+	    paths.push_back (a_store->get_path (it));
+    }
+    for (int i = paths.size (); i > 0; --i) {
+	Gtk::TreeIter it = a_store->get_iter (paths[i - 1]);
+        IDebugger::VariableSafePtr empty_var;
+        (*it)->get_value(get_variable_columns ().variable).reset ();
+	a_store->erase (it);
+    }
+    return true;
+}
+
+/// Re-visualize a given variable.  That is, unlink the graphical
+/// nodes of the member variables of the given variable, and
+/// re-visualize that same variable into its graphical node.
+///
+/// \param a_var the variable to re-visualize
+/// 
+/// \param a_row_it an iterator to the graphical node of the variable
+/// to re-visualize
+///
+/// \param a_tree_view the treeview containing the graphical node
+///
+/// \param a_store the tree store containing the graphical node
+bool
+visualize_a_variable (const IDebugger::VariableSafePtr a_var,
+		      const Gtk::TreeModel::iterator &a_row_it,
+                      const Gtk::TreeView &a_tree_view,
+		      const Glib::RefPtr<Gtk::TreeStore> &a_store)
+{
+    if (!unlink_member_variable_rows (a_row_it, a_store))
+        return false;
+
+    return set_a_variable (a_var, a_tree_view,
+                           a_store, a_row_it,
+                           /*a_truncate_type=*/true);
+}
 
 NEMIVER_END_NAMESPACE (variables_utils2)
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-variables-utils.h b/src/persp/dbgperspective/nmv-variables-utils.h
index d0c2cf0..d650ec2 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.h
+++ b/src/persp/dbgperspective/nmv-variables-utils.h
@@ -126,6 +126,20 @@ bool append_a_variable (const IDebugger::VariableSafePtr a_var,
                         Gtk::TreeModel::iterator &a_result,
                         bool a_truncate_type);
 
+bool set_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_row_it,
+		     bool a_truncate_type);
+
+bool unlink_member_variable_rows (const Gtk::TreeModel::iterator &a_row_it,
+				  const Glib::RefPtr<Gtk::TreeStore> &a_store);
+
+bool visualize_a_variable (const IDebugger::VariableSafePtr a_var,
+			   const Gtk::TreeModel::iterator &a_var_row_it,
+			   const Gtk::TreeView &a_tree_view,
+			   const Glib::RefPtr<Gtk::TreeStore> &a_store);
+
 NEMIVER_END_NAMESPACE (variables_utils2)
 NEMIVER_END_NAMESPACE (nemiver)
 
diff --git a/tests/test-breakpoint.cc b/tests/test-breakpoint.cc
index 75b3761..143a10e 100644
--- a/tests/test-breakpoint.cc
+++ b/tests/test-breakpoint.cc
@@ -241,7 +241,7 @@ test_main (int argc, char *argv[])
     //*****************************
 
     std::vector<UString> args, source_search_dir;
-    debugger->disable_pretty_printing ();
+    debugger->enable_pretty_printing (false);
     source_search_dir.push_back (".");
     debugger->load_program ("fooprog", args, ".",
                             source_search_dir, "",
diff --git a/tests/test-types.cc b/tests/test-types.cc
index 962a1be..d628de2 100644
--- a/tests/test-types.cc
+++ b/tests/test-types.cc
@@ -96,7 +96,7 @@ test_main (int, char **)
 
     debugger->variable_value_signal ().connect (&on_variable_value_signal);
 
-    debugger->disable_pretty_printing ();
+    debugger->enable_pretty_printing (false);
     std::vector<UString> args, source_search_dir;
     source_search_dir.push_back (".");
 
diff --git a/tests/test-var-path-expr.cc b/tests/test-var-path-expr.cc
index 2936144..4f5485a 100644
--- a/tests/test-var-path-expr.cc
+++ b/tests/test-var-path-expr.cc
@@ -139,7 +139,7 @@ test_main (int argc, char *argv[])
                                                      debugger));
 
     std::vector<UString> args, source_search_dir;
-    debugger->disable_pretty_printing ();
+    debugger->enable_pretty_printing (false);
     source_search_dir.push_back (".");
     debugger->load_program ("fooprog", args, ".",
                             source_search_dir, "", false);
diff --git a/tests/test-vars.cc b/tests/test-vars.cc
index b33fbc7..c07dd12 100644
--- a/tests/test-vars.cc
+++ b/tests/test-vars.cc
@@ -273,7 +273,7 @@ test_main (int, char **)
     //</connect to IDebugger events>
     //******************************
     vector<UString> args;
-    debugger->disable_pretty_printing ();
+    debugger->enable_pretty_printing (false);
     debugger->load_program ("fooprog", args, ".");
     debugger->set_breakpoint ("main");
     debugger->set_breakpoint ("func4");



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