[nemiver/better-variable-format: 6/8] Support pretty printing instantly applied
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver/better-variable-format: 6/8] Support pretty printing instantly applied
- Date: Tue, 30 Aug 2011 15:33:40 +0000 (UTC)
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]