[nemiver] Initial import of variable monitor work



commit 11940f85da451c6b933f59e255863dba01f1001b
Author: Dodji Seketeli <dodji seketeli org>
Date:   Sun Oct 23 18:53:45 2011 +0200

    Initial import of variable monitor work
    
    This is Work In Progress.  Nothing works yet, and the damin thing eats
    kitties.

 src/dbgengine/nmv-i-debugger.h                     |   50 +++-
 src/persp/dbgperspective/Makefile.am               |    2 +
 src/persp/dbgperspective/menus/menus.xml           |    2 +
 .../nmv-dbg-perspective-default-layout.cc          |    2 +-
 src/persp/dbgperspective/nmv-dbg-perspective.cc    |   55 +++-
 src/persp/dbgperspective/nmv-dbg-perspective.h     |    3 +-
 src/persp/dbgperspective/nmv-variables-utils.cc    |   27 ++-
 src/persp/dbgperspective/nmv-variables-utils.h     |    8 +-
 src/persp/dbgperspective/nmv-vars-monitor.cc       |  359 ++++++++++++++++++++
 src/persp/dbgperspective/nmv-vars-monitor.h        |   67 ++++
 10 files changed, 562 insertions(+), 13 deletions(-)
---
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 6fb5fff..d9232b0 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -351,7 +351,7 @@ public:
         FrameArgsSlot;
 
     typedef sigc::slot<void, const VariableSafePtr> ConstVariableSlot;
-    typedef sigc::slot<void, const VariableList> ConstVariableListSlot;
+    typedef sigc::slot<void, const VariableList&> ConstVariableListSlot;
     typedef sigc::slot<void, const UString&> ConstUStringSlot;
 
     class Variable : public Object {
@@ -507,7 +507,7 @@ public:
 
         /// Tests value equality between two variables.
         /// Two variables are considered equal by value if their
-        /// respective memebers have the same values and same type.
+        /// respective members have the same values and same type.
         /// \param a_other the other variable to test against
         /// \return true if a_other equals the current instance
         ///         by value.
@@ -579,6 +579,28 @@ public:
             return m_parent != 0;
         }
 
+        /// If this variable has a backend counterpart (e.g GDB
+        /// Backend variable object) then, there are cases where a
+        /// variable sub-object can be returned by the backend without
+        /// being linked to its ancestor tree.  Such a variable
+        /// appears as being structurally root (it has no parent), but
+        /// is morally a sub-variable.  A variable that is
+        /// structurally non-root is also morally non-root.
+        ///
+        /// To know if a variable is morally root, this function
+        /// detects if the fully qualified internal name of the
+        /// variable has dot (".") in it (e.g, "variable.member").  If
+        /// does not, then the function assumes the variable is
+        /// morally root and returns true.
+        bool is_morally_root () const
+        {
+            if (has_parent ())
+                return false;
+            if (internal_name ().empty ())
+                return !has_parent ();
+            return (internal_name ().find (".") == UString::npos);
+        }
+
         /// A getter of the parent Variable of the current instance.
         const VariableSafePtr parent () const
         {
@@ -1095,6 +1117,12 @@ public:
     virtual sigc::signal<void, const VariableSafePtr, const UString&>&
                                  variable_expression_evaluated_signal () const = 0;
 
+    /// This is a callback slot called upon completion of the
+    /// IDebugger::list_changed_variables entry point.
+    ///
+    /// The parameters of are the slots are: the list of variables
+    /// that changed, and the cookie passed to
+    /// IDebugger::list_changed_variables.
     virtual sigc::signal<void, const VariableList&, const UString&>&
                                 changed_variables_signal () const  = 0;
 
@@ -1417,8 +1445,26 @@ public:
              const ConstVariableSlot &a_slot,
              const UString &a_cookie = "")= 0;
 
+    /// List the sub-variables of a_root (included a_root) which value
+    /// changed since the last time this function was called.
+    ///
+    /// \param a_root the variable to consider
+    /// \a_cookie the cookie to be passed to the callback function
+    /// IDebugger::changed_variables_signal
     virtual void list_changed_variables (VariableSafePtr a_root,
                                          const UString &a_cookie = "") = 0;
+
+    /// List the sub-variables of a_root (included a_root) which value
+    /// changed since the last time this function was called.
+    ///
+    /// \param a_root the variable to consider
+    /// 
+    /// \param a_slot the slot to be invoked upon completion of this
+    /// function.  That slot is going to be passed the list of
+    /// sub-variables that have changed.
+    /// 
+    /// \a_cookie the cookie to be passed to the callback function
+    /// IDebugger::changed_variables_signal
     virtual void list_changed_variables
             (VariableSafePtr a_root,
              const ConstVariableListSlot &a_slot,
diff --git a/src/persp/dbgperspective/Makefile.am b/src/persp/dbgperspective/Makefile.am
index 7852432..e79cca7 100644
--- a/src/persp/dbgperspective/Makefile.am
+++ b/src/persp/dbgperspective/Makefile.am
@@ -42,6 +42,8 @@ $(h)/nmv-global-vars-inspector-dialog.cc \
 $(h)/nmv-global-vars-inspector-dialog.h \
 $(h)/nmv-var-inspector.cc \
 $(h)/nmv-var-inspector.h \
+$(h)/nmv-vars-monitor.cc \
+$(h)/nmv-vars-monitor.h \
 $(h)/nmv-breakpoints-view.cc \
 $(h)/nmv-breakpoints-view.h \
 $(h)/nmv-registers-view.cc \
diff --git a/src/persp/dbgperspective/menus/menus.xml b/src/persp/dbgperspective/menus/menus.xml
index 9273add..d8fa0f9 100644
--- a/src/persp/dbgperspective/menus/menus.xml
+++ b/src/persp/dbgperspective/menus/menus.xml
@@ -42,6 +42,8 @@
                 name="ActivateBreakpointsViewMenuItem"/>
             <menuitem action="ActivateRegistersViewMenuAction"
                 name="ActivateRegistersViewMenuItem"/>
+	    <menuitem action="ActivateVarsMonitorViewMenuAction"
+                name="ActivateVarsMonitorViewMenuItem"/>
         </menu>
         <menu action="DebugMenuAction" name="DebugMenu">
             <menuitem action="RunMenuItemAction" name="RunMenuItem"/>
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective-default-layout.cc b/src/persp/dbgperspective/nmv-dbg-perspective-default-layout.cc
index 05f7619..0c366eb 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective-default-layout.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective-default-layout.cc
@@ -186,8 +186,8 @@ DBGPerspectiveDefaultLayout::add_view (Gtk::Widget &a_widget,
         return;
     }
 
-    m_priv->views.insert (std::make_pair<int, Gtk::Widget&> (a_index, a_widget));
     a_widget.show_all ();
+    m_priv->views.insert (std::make_pair<int, Gtk::Widget&> (a_index, a_widget));
     int page_num = m_priv->statuses_notebook->insert_page (a_widget,
                                                            a_title,
                                                            a_index);
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 89e4fea..48f4126 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -97,6 +97,7 @@
 #include "nmv-dbg-perspective-dynamic-layout.h"
 #endif // WITH_DYNAMICLAYOUT
 #include "nmv-layout-manager.h"
+#include "nmv-vars-monitor.h"
 
 using namespace std;
 using namespace nemiver::common;
@@ -114,11 +115,12 @@ const char *STEP_OVER         = "nmv-step-over";
 const char *STEP_OUT          = "nmv-step-out";
 
 // labels for widget tabs in the status notebook
-const char *CONTEXT_VIEW_TITLE         = _("Context");
-const char *TARGET_TERMINAL_VIEW_TITLE = _("Target Terminal");
-const char *BREAKPOINTS_VIEW_TITLE     = _("Breakpoints");
-const char *REGISTERS_VIEW_TITLE       = _("Registers");
-const char *MEMORY_VIEW_TITLE          = _("Memory");
+const char *CONTEXT_VIEW_TITLE           = _("Context");
+const char *TARGET_TERMINAL_VIEW_TITLE   = _("Target Terminal");
+const char *BREAKPOINTS_VIEW_TITLE       = _("Breakpoints");
+const char *REGISTERS_VIEW_TITLE         = _("Registers");
+const char *MEMORY_VIEW_TITLE            = _("Memory");
+const char *VARS_MONITOR_VIEW_TITLE      = _("Variables Monitor");
 
 const char *SESSION_NAME = "sessionname";
 const char *PROGRAM_NAME = "programname";
@@ -419,6 +421,7 @@ private:
 #ifdef WITH_MEMORYVIEW
     void on_activate_memory_view ();
 #endif // WITH_MEMORYVIEW
+    void on_activate_vars_monitor_view ();
     void on_activate_global_variables ();
     void on_default_config_read ();
 
@@ -757,6 +760,8 @@ public:
     MemoryView& get_memory_view ();
 #endif // WITH_MEMORYVIEW
 
+    VarsMonitor& get_vars_monitor_view ();
+
     ThreadList& get_thread_list ();
 
     bool set_where (const IDebugger::Frame &a_frame,
@@ -907,6 +912,7 @@ struct DBGPerspective::Priv {
 #ifdef WITH_MEMORYVIEW
     SafePtr<MemoryView> memory_view;
 #endif // WITH_MEMORYVIEW
+    SafePtr<VarsMonitor> vars_monitor;
 
     int current_page_num;
     IDebuggerSafePtr debugger;
@@ -1834,6 +1840,7 @@ DBGPerspective::on_going_to_run_target_signal ()
     get_memory_view ().clear ();
 #endif
     get_registers_view ().clear ();
+    get_vars_monitor_view ().re_init_widget ();;
     NEMIVER_CATCH
 }
 
@@ -2868,6 +2875,19 @@ DBGPerspective::on_activate_memory_view ()
 #endif //WITH_MEMORYVIEW
 
 void
+DBGPerspective::on_activate_vars_monitor_view ()
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    NEMIVER_TRY;
+
+    THROW_IF_FAIL (m_priv);
+    m_priv->layout ().activate_view (VARS_MONITOR_VIEW_INDEX);
+
+    NEMIVER_CATCH;
+}
+
+void
 DBGPerspective::on_activate_global_variables ()
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -3398,6 +3418,16 @@ DBGPerspective::init_actions ()
         },
 #endif // WITH_MEMORYVIEW
         {
+            "ActivateVarsMonitorViewMenuAction",
+            nil_stock_id,
+            VARS_MONITOR_VIEW_TITLE,
+            _("Switch to Variables Monitor View"),
+            sigc::mem_fun (*this, &DBGPerspective::on_activate_vars_monitor_view),
+            ActionEntry::DEFAULT,
+            "<alt>6",
+            false
+        },
+        {
             "DebugMenuAction",
             nil_stock_id,
             _("_Debug"),
@@ -3792,6 +3822,7 @@ DBGPerspective::clear_status_notebook ()
 #ifdef WITH_MEMORYVIEW
     get_memory_view ().clear ();
 #endif // WITH_MEMORYVIEW
+    get_vars_monitor_view ().re_init_widget ();
 }
 
 void
@@ -4931,6 +4962,9 @@ DBGPerspective::add_views_to_layout ()
     m_priv->layout ().add_view (get_terminal_box (),
                                 TARGET_TERMINAL_VIEW_TITLE,
                                 TARGET_TERMINAL_VIEW_INDEX);
+    m_priv->layout ().add_view (get_vars_monitor_view ().widget (),
+                                VARS_MONITOR_VIEW_TITLE,
+                                VARS_MONITOR_VIEW_INDEX);
 
     m_priv->layout ().do_init ();
 
@@ -8092,6 +8126,17 @@ DBGPerspective::get_memory_view ()
 }
 #endif // WITH_MEMORYVIEW
 
+VarsMonitor&
+DBGPerspective::get_vars_monitor_view ()
+{
+    THROW_IF_FAIL (m_priv);
+
+    if (!m_priv->vars_monitor)
+        m_priv->vars_monitor.reset (new VarsMonitor (*debugger (),
+                                                     *this));
+    THROW_IF_FAIL (m_priv->vars_monitor);
+    return *m_priv->vars_monitor;
+}
 
 struct ScrollTextViewToEndClosure {
     Gtk::TextView* text_view;
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index ddb00ff..1eced95 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -47,8 +47,9 @@ enum ViewsIndex
     BREAKPOINTS_VIEW_INDEX,
     REGISTERS_VIEW_INDEX,
 #ifdef WITH_MEMORYVIEW
-    MEMORY_VIEW_INDEX
+    MEMORY_VIEW_INDEX,
 #endif // WITH_MEMORYVIEW
+    VARS_MONITOR_VIEW_INDEX
 };
 
 class SourceEditor;
diff --git a/src/persp/dbgperspective/nmv-variables-utils.cc b/src/persp/dbgperspective/nmv-variables-utils.cc
index cb05a9a..2eed442 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.cc
+++ b/src/persp/dbgperspective/nmv-variables-utils.cc
@@ -494,7 +494,7 @@ update_a_variable_real (const IDebugger::VariableSafePtr a_var,
 /// variable is added as the root node of the tree view widget.
 /// \return true if a_var was added, false otherwise.
 bool
-append_a_variable (const IDebugger::VariableSafePtr a_var,
+append_a_variable (const IDebugger::VariableSafePtr &a_var,
                    const Gtk::TreeView &a_tree_view,
                    const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
                    Gtk::TreeModel::iterator &a_parent_row_it,
@@ -521,7 +521,7 @@ append_a_variable (const IDebugger::VariableSafePtr a_var,
 /// the function returned true.
 /// \return true if a_var was added, false otherwise.
 bool
-append_a_variable (const IDebugger::VariableSafePtr a_var,
+append_a_variable (const IDebugger::VariableSafePtr &a_var,
                    const Gtk::TreeView &a_tree_view,
                    const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
                    Gtk::TreeModel::iterator &a_parent_row_it,
@@ -617,6 +617,29 @@ set_a_variable (const IDebugger::VariableSafePtr a_var,
     return true;
 }
 
+/// Unlike the graphical node representing a variable a_var.
+///
+/// \param a_var the variable which graphical node to unlink.
+///
+/// \param a_store the tree store of the tree view to act upon.
+///
+/// \param a_parent_row_it the parent graphical row under which we
+/// have to look to find the graphical node to unlink.
+///
+/// \return true upon successful unlinking, false otherwise.
+bool
+unlink_a_variable_row (const IDebugger::VariableSafePtr &a_var,
+                       const Glib::RefPtr<Gtk::TreeStore> &a_store,
+                       Gtk::TreeModel::iterator &a_parent_row_it)
+{
+    Gtk::TreeModel::iterator var_to_unlink_it;
+    if (!find_a_variable (a_var, a_parent_row_it, var_to_unlink_it))
+        return false;
+
+    a_store->erase (var_to_unlink_it);
+    return true;
+}
+
 /// Unlink the graphical nodes representing the member variables of
 /// the variable pointed to by the given row iterator.
 ///
diff --git a/src/persp/dbgperspective/nmv-variables-utils.h b/src/persp/dbgperspective/nmv-variables-utils.h
index d650ec2..0017f2b 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.h
+++ b/src/persp/dbgperspective/nmv-variables-utils.h
@@ -113,13 +113,13 @@ bool update_a_variable (const IDebugger::VariableSafePtr a_var,
                         bool a_is_new_frame,
                         bool a_update_members = false);
 
-bool append_a_variable (const IDebugger::VariableSafePtr a_var,
+bool append_a_variable (const IDebugger::VariableSafePtr &a_var,
                         const Gtk::TreeView &a_tree_view,
                         const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
                         Gtk::TreeModel::iterator &a_parent_row_it,
                         bool a_truncate_type);
 
-bool append_a_variable (const IDebugger::VariableSafePtr a_var,
+bool append_a_variable (const IDebugger::VariableSafePtr &a_var,
                         const Gtk::TreeView &a_tree_view,
                         const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
                         Gtk::TreeModel::iterator &a_parent_row_it,
@@ -132,6 +132,10 @@ bool set_a_variable (const IDebugger::VariableSafePtr a_var,
 		     Gtk::TreeModel::iterator a_row_it,
 		     bool a_truncate_type);
 
+bool unlink_a_variable_row (const IDebugger::VariableSafePtr &a_var,
+			    const Glib::RefPtr<Gtk::TreeStore> &a_store,
+			    Gtk::TreeModel::iterator &a_parent_row_it);
+
 bool unlink_member_variable_rows (const Gtk::TreeModel::iterator &a_row_it,
 				  const Glib::RefPtr<Gtk::TreeStore> &a_store);
 
diff --git a/src/persp/dbgperspective/nmv-vars-monitor.cc b/src/persp/dbgperspective/nmv-vars-monitor.cc
new file mode 100644
index 0000000..afd8213
--- /dev/null
+++ b/src/persp/dbgperspective/nmv-vars-monitor.cc
@@ -0,0 +1,359 @@
+//Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#include "nmv-vars-monitor.h"
+#include <glib/gi18n.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/treerowreference.h>
+#include "common/nmv-exception.h"
+#include "nmv-vars-treeview.h"
+#include "nmv-variables-utils.h"
+
+using namespace nemiver::common;
+namespace vutils = nemiver::variables_utils2;
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+struct VarsMonitor::Priv
+{
+    IDebugger &debugger;
+    IPerspective &perspective;
+    SafePtr<VarsTreeView> tree_view;
+    Glib::RefPtr<Gtk::TreeStore> tree_store;
+    SafePtr<Gtk::TreeRowReference> in_scope_vars_row_ref;
+    SafePtr<Gtk::TreeRowReference> out_of_scope_vars_row_ref;
+    Gtk::TreeModel::iterator cur_selected_row;
+    bool initialized;
+    IDebugger::VariableList monitored_variables;
+    map<IDebugger::VariableSafePtr, bool> in_scope_vars;
+
+    Priv (IDebugger &a_debugger,
+          IPerspective &a_perspective)
+        : debugger (a_debugger),
+          perspective (a_perspective),
+          initialized (false)
+    {
+        // The widget is built lazily when somone requests it from
+        // the outside.
+    }
+
+    /// Return the widget to visualize the variables managed by the
+    /// monitor.  This function lazily builds the widget and
+    /// initializes the monitor.
+    /// \return the widget to visualize the monitored variables
+    Gtk::Widget&
+    get_widget ()
+    {
+        if (!initialized)
+            init_widget ();
+        THROW_IF_FAIL (initialized && tree_view);
+        return *tree_view;
+    }
+
+    void
+    init_widget ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (initialized)
+            return;
+
+        // Neither in_scope_vars_row_ref nor out_of_scope_vars_row_ref
+        // nor tree_view should be non-null before the widget has been
+        // initialized.
+        THROW_IF_FAIL (!in_scope_vars_row_ref
+                       && !out_of_scope_vars_row_ref
+                       && !tree_view);
+
+        tree_view.reset (VarsTreeView::create ());
+        THROW_IF_FAIL (tree_view);
+
+        tree_store = tree_view->get_tree_store ();
+        THROW_IF_FAIL (tree_store);
+
+        // *************************************************************
+        // Create a row for variables that are in-scope and a row for
+        // variables that are out-of-scope
+        // *************************************************************
+        Gtk::TreeModel::iterator it = tree_store->append ();
+        (*it)[vutils::get_variable_columns ().name] = _("In scope variables");
+        in_scope_vars_row_ref.reset
+            (new Gtk::TreeRowReference (tree_store,
+                                        tree_store->get_path (it)));
+        it = tree_store->append ();
+        (*it)[vutils::get_variable_columns ().name] = _("Out of scope variables");
+        out_of_scope_vars_row_ref.reset
+            (new Gtk::TreeRowReference (tree_store,
+                                        tree_store->get_path (it)));
+
+        THROW_IF_FAIL (in_scope_vars_row_ref
+                       && out_of_scope_vars_row_ref);
+
+        // And now finish the initialization.
+        connect_to_debugger_signal ();
+        init_graphical_signals ();
+        init_actions ();
+        re_init_widget ();
+
+        initialized = true;
+    }
+
+    void
+    re_init_widget ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+    }
+
+    void
+    connect_to_debugger_signal ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        debugger.stopped_signal ().connect
+            (sigc::mem_fun (*this, &Priv::on_stopped_signal));
+    }
+
+    void
+    init_graphical_signals ()
+    {
+    }
+
+    void
+    init_actions ()
+    {
+    }
+
+    void
+    add_variable (const IDebugger::VariableSafePtr a_var)
+    {
+        if (a_var)
+            monitored_variables.push_back (a_var);
+    }
+
+    void
+    add_variables (const IDebugger::VariableList &a_vars)
+    {
+        IDebugger::VariableList::const_iterator it;
+        for (it = a_vars.begin (); it != a_vars.end (); ++it)
+            monitored_variables.push_back (*it);
+    }
+
+    bool
+    get_in_scope_vars_row_iterator (Gtk::TreeModel::iterator &a_it)
+    {
+        if (!in_scope_vars_row_ref)
+            return false;
+        a_it = tree_store->get_iter (in_scope_vars_row_ref->get_path ());
+        return true;
+    }
+
+    bool
+    get_out_of_scope_vars_row_iterator (Gtk::TreeModel::iterator &a_it)
+    {
+        if (!out_of_scope_vars_row_ref)
+            return false;
+        a_it = tree_store->get_iter (out_of_scope_vars_row_ref->get_path ());
+        return true;
+    }
+
+    void
+    ensure_var_under_first_but_not_under_second
+    (const IDebugger::VariableSafePtr &a_var,
+     Gtk::TreeModel::iterator &a_first,
+     Gtk::TreeModel::iterator &a_second,
+     Gtk::TreeModel::iterator &a_var_it)
+    {
+        // If is under a_second then remove it from there.
+        vutils::unlink_a_variable_row (a_var, tree_store, a_second);
+        
+        // If a_var is not in under a_first, add it now.
+        Gtk::TreeModel::iterator var_it;
+        if (!vutils::find_a_variable (a_var, a_first, a_var_it))
+            vutils::append_a_variable (a_var, *tree_view,
+                                       tree_store, a_first, a_var_it,
+                                       /*a_truncate_type=*/true);
+    }
+
+    void
+    update_var_in_scope_or_not (const IDebugger::VariableSafePtr &a_var,
+                                Gtk::TreeModel::iterator &a_var_it)
+    {
+        Gtk::TreeModel::iterator in_scope_vars_it, out_of_scope_vars_it;
+
+        if (!a_var->is_morally_root ())
+            return;
+
+        get_in_scope_vars_row_iterator (in_scope_vars_it);
+        get_out_of_scope_vars_row_iterator (out_of_scope_vars_it);
+
+        if (a_var->in_scope ()) {
+            in_scope_vars[a_var] = true;
+            ensure_var_under_first_but_not_under_second (a_var,
+                                                         in_scope_vars_it,
+                                                         out_of_scope_vars_it,
+                                                         a_var_it);
+        } else {
+            in_scope_vars.erase (a_var);
+            ensure_var_under_first_but_not_under_second (a_var,
+                                                         out_of_scope_vars_it,
+                                                         in_scope_vars_it,
+                                                         a_var_it);
+        }
+    }
+
+    bool
+    should_process_now () const
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        THROW_IF_FAIL (tree_view);
+        bool is_visible = tree_view->get_is_drawable ();
+        LOG_DD ("is visible: " << is_visible);
+        return is_visible;
+    }
+
+    void
+    finish_handling_debugger_stopped_event (IDebugger::StopReason /*a_reason*/,
+                                            bool a_has_frame,
+                                            const IDebugger::Frame &/*a_frame*/)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY;
+
+        THROW_IF_FAIL (tree_store);
+
+        if (!a_has_frame)
+            return;
+
+        //TODO: walk the monitored variables and list those that have
+        //changed.
+        IDebugger::VariableList::const_iterator it;
+        for (it = monitored_variables.begin ();
+             it != monitored_variables.end ();
+             ++it) {
+            debugger.list_changed_variables (*it,
+                                             sigc::bind
+                                             (sigc::mem_fun
+                                              (*this, &Priv::on_vars_changed),
+                                              *it));
+        }
+
+        NEMIVER_CATCH;
+    }
+
+    // *********************
+    // <signal handlers>
+    // ********************
+
+    void
+    on_stopped_signal (IDebugger::StopReason a_reason,
+                       bool a_has_frame,
+                       const IDebugger::Frame &a_frame,
+                       int /*a_thread_id*/,
+                       int /*a_bp_num*/,
+                       const UString &/*a_cookie*/)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY;
+
+        if (IDebugger::is_exited (a_reason)
+            || !a_has_frame)
+            return;
+
+        if (should_process_now ())
+            finish_handling_debugger_stopped_event (a_reason,
+                                                    a_has_frame,
+                                                    a_frame);
+        NEMIVER_CATCH;
+    }
+
+    void
+    on_vars_changed (const IDebugger::VariableList &/*a_sub_vars*/,
+                     const IDebugger::VariableSafePtr a_var_root)
+    {
+        NEMIVER_TRY;
+
+        // Is this variable in scope or not? Update the graphical
+        // stuff according to that property.
+        Gtk::TreeModel::iterator var_it;
+        update_var_in_scope_or_not (a_var_root, var_it);
+        THROW_IF_FAIL (var_it);
+
+        // TODO: Walk a_sub_vars (children of a_var_root) and update
+        // them graphically, using update_a_variable.
+        NEMIVER_CATCH;
+    }
+
+    // *********************
+    // </signal handlers>
+    // ********************
+
+}; // end struct VarsMonitor
+
+VarsMonitor::VarsMonitor (IDebugger &a_dbg,
+                          IPerspective &a_perspective)
+{
+    m_priv.reset (new Priv (a_dbg, a_perspective));
+}
+
+VarsMonitor::~VarsMonitor ()
+{
+}
+
+Gtk::Widget&
+VarsMonitor::widget ()
+{
+    THROW_IF_FAIL (m_priv);
+    return m_priv->get_widget ();
+}
+
+void
+VarsMonitor::add_variable (const IDebugger::VariableSafePtr a_var)
+{
+    m_priv->add_variable (a_var);
+}
+
+void
+VarsMonitor::add_variables (const IDebugger::VariableList &a_vars)
+{
+    m_priv->add_variables (a_vars);
+}
+
+void
+VarsMonitor::remove_variable (const IDebugger::VariableSafePtr /*a_var*/)
+{
+}
+
+void
+VarsMonitor::remove_variables (const std::list<IDebugger::VariableSafePtr> &/*a_vars*/)
+{
+}
+
+void
+VarsMonitor::re_init_widget ()
+{
+}
+
+NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-vars-monitor.h b/src/persp/dbgperspective/nmv-vars-monitor.h
new file mode 100644
index 0000000..44f1962
--- /dev/null
+++ b/src/persp/dbgperspective/nmv-vars-monitor.h
@@ -0,0 +1,67 @@
+//Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_VARS_MONITOR_H__
+#define __NMV_VARS_MONITOR_H__
+
+#include "common/nmv-safe-ptr-utils.h"
+#include "common/nmv-object.h"
+#include "nmv-i-perspective.h"
+#include "nmv-i-debugger.h"
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
+/// \brief A widget that can monitor the state of a given set of
+/// variables.
+///
+/// Each time the debugger stops, this widget updates the state of the
+/// variables that have been added to it.  Whenever a variable has
+/// gone out of scope [when it hasn't been created by address] the
+/// widget is supposed to clearly show it
+class NEMIVER_API VarsMonitor : public nemiver::common::Object {
+    // Non copyable
+    VarsMonitor (const VarsMonitor&);
+    VarsMonitor& operator= (const VarsMonitor&);
+
+    struct Priv;
+    SafePtr<Priv> m_priv;
+
+ protected:
+    VarsMonitor ();
+
+ public:
+    VarsMonitor (IDebugger &a_dbg,
+                 IPerspective &a_perspective);
+    virtual ~VarsMonitor ();
+    Gtk::Widget& widget ();
+    void add_variable (const IDebugger::VariableSafePtr a_var);
+    void add_variables (const IDebugger::VariableList &a_vars);
+    void remove_variable (const IDebugger::VariableSafePtr a_var);
+    void remove_variables (const IDebugger::VariableList &a_vars);
+    void re_init_widget ();
+};// end VarsMonitor
+
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif // __NMV_VARS_MONITOR_H__



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