[nemiver] Support graphically adding a variable to the monitor



commit 5c4b2227fd2477f224120575b42776d63549cddb
Author: Dodji Seketeli <dodji seketeli org>
Date:   Sun Nov 13 15:26:10 2011 +0100

    Support graphically adding a variable to the monitor
    
    [This is not a proper commit entry.  Commits on this branch are
    all going to be re-hashed anyway.]
    
    The variable inspector dialog now has a button that lets you add
    the current variable/expression to the monitor.  It's very rough as no
    check is performed to make sure you can't add the same expression to the
    monitor twice, etc.  Also, once the variable is added, we face an issue
    that is explained in #663959, namely the life time management of expressions
    backed by variable objects.  I need to address that issue separately
    before getting back to this business.

 src/persp/dbgperspective/nmv-dbg-perspective.cc    |   19 ++
 .../dbgperspective/nmv-var-inspector-dialog.cc     |   31 ++++-
 .../dbgperspective/nmv-var-inspector-dialog.h      |    4 +
 src/persp/dbgperspective/nmv-variables-utils.cc    |    2 +-
 src/persp/dbgperspective/nmv-vars-monitor.cc       |  177 ++++++++++++++++++--
 src/persp/dbgperspective/ui/varinspectordialog.ui  |   17 ++-
 6 files changed, 229 insertions(+), 21 deletions(-)
---
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 48f4126..eb39062 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -285,6 +285,7 @@ private:
     void on_toggle_breakpoint_enabled_action ();
     void on_toggle_countpoint_action ();
     void on_inspect_variable_action ();
+    void on_expr_monitoring_requested (const IDebugger::VariableSafePtr);
     void on_call_function_action ();
     void on_find_text_response_signal (int);
     void on_breakpoint_delete_action
@@ -1631,6 +1632,21 @@ DBGPerspective::on_inspect_variable_action ()
 }
 
 void
+DBGPerspective::on_expr_monitoring_requested
+(const IDebugger::VariableSafePtr a_var)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    NEMIVER_TRY;
+
+    THROW_IF_FAIL (m_priv && m_priv->vars_monitor);
+
+    m_priv->vars_monitor->add_variable (a_var);
+
+    NEMIVER_CATCH;
+}
+
+void
 DBGPerspective::on_call_function_action ()
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -7825,6 +7841,9 @@ DBGPerspective::inspect_variable (const UString &a_variable_name)
                                debugger (),
                                *this);
     dialog.set_history (m_priv->var_inspector_dialog_history);
+    dialog.expr_monitoring_requested ().connect
+        (sigc::mem_fun (*this,
+                        &DBGPerspective::on_expr_monitoring_requested));
     if (a_variable_name != "") {
         dialog.inspect_variable (a_variable_name);
     }
diff --git a/src/persp/dbgperspective/nmv-var-inspector-dialog.cc b/src/persp/dbgperspective/nmv-var-inspector-dialog.cc
index 95ba726..e546bbd 100644
--- a/src/persp/dbgperspective/nmv-var-inspector-dialog.cc
+++ b/src/persp/dbgperspective/nmv-var-inspector-dialog.cc
@@ -51,11 +51,13 @@ class VarInspectorDialog::Priv {
     Gtk::ComboBox *var_name_entry;
     Glib::RefPtr<Gtk::ListStore> m_variable_history;
     Gtk::Button *inspect_button;
+    Gtk::Button *add_to_monitor_button;
     SafePtr<VarInspector> var_inspector;
     Gtk::Dialog &dialog;
     Glib::RefPtr<Gtk::Builder> gtkbuilder;
     IDebuggerSafePtr debugger;
     IPerspective &perspective;
+    sigc::signal<void, IDebugger::VariableSafePtr> expr_monitoring_requested;
 
     Priv ();
 public:
@@ -94,6 +96,11 @@ public:
                                                           "inspectbutton");
         inspect_button->set_sensitive (false);
 
+        add_to_monitor_button =
+            ui_utils::get_widget_from_gtkbuilder<Gtk::Button> (gtkbuilder,
+                                                               "addtomonitorbutton");
+        add_to_monitor_button->set_sensitive (false);
+
         Gtk::Box *box =
             ui_utils::get_widget_from_gtkbuilder<Gtk::Box> (gtkbuilder,
                                                        "inspectorwidgetbox");
@@ -116,6 +123,8 @@ public:
         THROW_IF_FAIL (var_name_entry);
         inspect_button->signal_clicked ().connect (sigc::mem_fun
                 (*this, &Priv::do_inspect_variable));
+        add_to_monitor_button->signal_clicked ().connect
+            (sigc::mem_fun (*this, &Priv::on_do_monitor_button_clicked));
         var_name_entry->signal_changed ().connect (sigc::mem_fun
                 (*this, &Priv::on_var_name_changed_signal));
         var_name_entry->get_entry()->signal_activate ().connect (sigc::mem_fun
@@ -266,8 +275,10 @@ public:
         UString var_name = var_name_entry->get_entry ()->get_text ();
         if (var_name == "") {
             inspect_button->set_sensitive (false);
+            add_to_monitor_button->set_sensitive (false);
         } else {
             inspect_button->set_sensitive (true);
+            add_to_monitor_button->set_sensitive (true);
         }
 
         // this handler is called when any text is changed in the entry or when
@@ -281,6 +292,18 @@ public:
         NEMIVER_CATCH
     }
 
+    void
+    on_do_monitor_button_clicked ()
+    {
+        NEMIVER_TRY;
+
+        THROW_IF_FAIL (var_inspector->get_variable ());
+
+        expr_monitoring_requested.emit (var_inspector->get_variable ());
+
+        NEMIVER_CATCH
+    }
+
     //************************
     //</signal handlers>
     //*************************
@@ -352,5 +375,11 @@ VarInspectorDialog::get_history (std::list<UString> &a_hist) const
     m_priv->get_history (a_hist);
 }
 
-NEMIVER_END_NAMESPACE (nemiver)
+sigc::signal<void, IDebugger::VariableSafePtr>&
+VarInspectorDialog::expr_monitoring_requested ()
+{
+    THROW_IF_FAIL (m_priv);
+    return m_priv->expr_monitoring_requested;
+}
 
+NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-var-inspector-dialog.h b/src/persp/dbgperspective/nmv-var-inspector-dialog.h
index d02928f..383bca9 100644
--- a/src/persp/dbgperspective/nmv-var-inspector-dialog.h
+++ b/src/persp/dbgperspective/nmv-var-inspector-dialog.h
@@ -53,6 +53,10 @@ public:
     const IDebugger::VariableSafePtr variable () const;
     void set_history (const std::list<UString> &);
     void get_history (std::list<UString> &) const;
+    
+    // Signals
+
+    sigc::signal<void, IDebugger::VariableSafePtr>& expr_monitoring_requested ();
 };//end class VarInspectorDialog
 
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-variables-utils.cc b/src/persp/dbgperspective/nmv-variables-utils.cc
index 2eed442..f4871a5 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.cc
+++ b/src/persp/dbgperspective/nmv-variables-utils.cc
@@ -630,7 +630,7 @@ set_a_variable (const IDebugger::VariableSafePtr a_var,
 bool
 unlink_a_variable_row (const IDebugger::VariableSafePtr &a_var,
                        const Glib::RefPtr<Gtk::TreeStore> &a_store,
-                       Gtk::TreeModel::iterator &a_parent_row_it)
+                       const 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))
diff --git a/src/persp/dbgperspective/nmv-vars-monitor.cc b/src/persp/dbgperspective/nmv-vars-monitor.cc
index afd8213..7ee6f7a 100644
--- a/src/persp/dbgperspective/nmv-vars-monitor.cc
+++ b/src/persp/dbgperspective/nmv-vars-monitor.cc
@@ -44,15 +44,24 @@ struct VarsMonitor::Priv
     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;
+    IDebugger::Frame saved_frame;
+    IDebugger::StopReason saved_reason;
+    bool saved_has_frame;
+    bool initialized;
+    bool is_new_frame;
+    bool is_up2date;
 
     Priv (IDebugger &a_debugger,
           IPerspective &a_perspective)
         : debugger (a_debugger),
           perspective (a_perspective),
-          initialized (false)
+          saved_reason (IDebugger::UNDEFINED_REASON),
+          saved_has_frame (false),
+          initialized (false),
+          is_new_frame (true),
+          is_up2date (true)
     {
         // The widget is built lazily when somone requests it from
         // the outside.
@@ -137,6 +146,13 @@ struct VarsMonitor::Priv
     void
     init_graphical_signals ()
     {
+        THROW_IF_FAIL (tree_view);
+
+        tree_view->signal_row_expanded ().connect
+            (sigc::mem_fun (*this, &Priv::on_tree_view_row_expanded_signal));
+
+        tree_view->signal_draw ().connect_notify
+            (sigc::mem_fun (this, &Priv::on_draw_signal));
     }
 
     void
@@ -147,16 +163,60 @@ struct VarsMonitor::Priv
     void
     add_variable (const IDebugger::VariableSafePtr a_var)
     {
-        if (a_var)
-            monitored_variables.push_back (a_var);
+        if (!a_var)
+            return;
+        monitored_variables.push_back (a_var);
+        Gtk::TreeModel::iterator root_node;
+        if (a_var->in_scope ())
+            get_in_scope_vars_row_iterator (root_node);
+        else
+            get_out_of_scope_vars_row_iterator (root_node);
+        THROW_IF_FAIL (root_node);
+        vutils::append_a_variable (a_var, *tree_view,
+                                   tree_store, root_node,
+                                   /*a_truncate_type=*/true);
     }
 
     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);
+        IDebugger::VariableList::const_iterator it = a_vars.begin ();
+        for (; it != a_vars.end (); ++it)
+            add_variable (*it);
+    }
+
+    void
+    remove_variable (const IDebugger::VariableSafePtr a_var)
+    {
+        IDebugger::VariableList::iterator it = monitored_variables.begin ();
+        for (; it != monitored_variables.end (); ++it) {
+            if ((*it)->internal_name () == a_var->internal_name ()
+                || (*it)->equals_by_value (*a_var)) {
+                // Remove the graphical representation of the node,
+                // and then remove the node itself from the list of
+                // monitored variables.
+                Gtk::TreeModel::iterator parent_row;
+                if (a_var->in_scope ())
+                    get_in_scope_vars_row_iterator (parent_row);
+                else
+                    get_out_of_scope_vars_row_iterator (parent_row);
+                THROW_IF_FAIL (parent_row);
+                vutils::unlink_a_variable_row (a_var, tree_store, parent_row);
+                monitored_variables.erase (it);
+                // We removed an element from the array while
+                // iterating on it so the iterator is invalidated.  We
+                // must not use it again.
+                break;
+            }
+        }
+    }
+
+    void
+    remove_variables (const IDebugger::VariableList &a_vars)
+    {
+        IDebugger::VariableList::const_iterator it = a_vars.begin ();
+        for (; it != a_vars.end (); ++it)
+            remove_variable (*it);
     }
 
     bool
@@ -233,9 +293,9 @@ struct VarsMonitor::Priv
     }
 
     void
-    finish_handling_debugger_stopped_event (IDebugger::StopReason /*a_reason*/,
+    finish_handling_debugger_stopped_event (IDebugger::StopReason a_reason,
                                             bool a_has_frame,
-                                            const IDebugger::Frame &/*a_frame*/)
+                                            const IDebugger::Frame &a_frame)
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
 
@@ -243,11 +303,20 @@ struct VarsMonitor::Priv
 
         THROW_IF_FAIL (tree_store);
 
-        if (!a_has_frame)
+        LOG_DD ("stopped, reason: " << a_reason);
+        if (a_reason == IDebugger::EXITED_SIGNALLED
+            || a_reason == IDebugger::EXITED_NORMALLY
+            || a_reason == IDebugger::EXITED
+            || !a_has_frame) {
             return;
+        }
 
-        //TODO: walk the monitored variables and list those that have
-        //changed.
+        is_new_frame = (saved_frame != a_frame);
+        saved_frame = a_frame;
+
+
+        // Walk the monitored variables and list those that have
+        // changed.
         IDebugger::VariableList::const_iterator it;
         for (it = monitored_variables.begin ();
              it != monitored_variables.end ();
@@ -282,15 +351,20 @@ struct VarsMonitor::Priv
             || !a_has_frame)
             return;
 
-        if (should_process_now ())
+        if (should_process_now ()) {
             finish_handling_debugger_stopped_event (a_reason,
                                                     a_has_frame,
                                                     a_frame);
+        } else {
+            saved_reason = a_reason;
+            saved_has_frame = a_has_frame;
+            is_up2date = false;
+        }
         NEMIVER_CATCH;
     }
 
     void
-    on_vars_changed (const IDebugger::VariableList &/*a_sub_vars*/,
+    on_vars_changed (const IDebugger::VariableList &a_sub_vars,
                      const IDebugger::VariableSafePtr a_var_root)
     {
         NEMIVER_TRY;
@@ -301,8 +375,73 @@ struct VarsMonitor::Priv
         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.
+        // Walk children of a_var_root and update their graphical
+        // representation.
+        IDebugger::VariableList::const_iterator v = a_sub_vars.begin ();
+        for (; v != a_sub_vars.end (); ++v) {
+            vutils::update_a_variable (*v, *tree_view,
+                                       var_it,
+                                       /*a_truncate_type=*/false,
+                                       /*a_handle_highlight=*/true,
+                                       /*a_is_new_frame=*/is_new_frame,
+                                       /*a_update_members=*/false);
+        }
+        NEMIVER_CATCH;
+    }
+
+  void
+  on_tree_view_row_expanded_signal (const Gtk::TreeModel::iterator &a_it,
+				    const Gtk::TreeModel::Path &a_path)
+  {
+      LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+      NEMIVER_TRY;
+
+      if (!(*a_it)[vutils::get_variable_columns ().needs_unfolding]) {
+          return;
+      }
+      LOG_DD ("A variable needs unfolding");
+
+      IDebugger::VariableSafePtr var =
+          (*a_it)[vutils::get_variable_columns ().variable];
+      debugger.unfold_variable
+          (var,
+           sigc::bind  (sigc::mem_fun (*this,
+                                       &Priv::on_variable_unfolded_signal),
+                        a_path));
+
+      NEMIVER_CATCH;
+  }
+
+    void
+    on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
+                                 const Gtk::TreeModel::Path a_var_node)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY;
+
+        Gtk::TreeModel::iterator var_it = tree_store->get_iter (a_var_node);
+        vutils::update_unfolded_variable (a_var,
+                                          *tree_view,
+                                          tree_store,
+                                          var_it,
+                                          false /* do not truncate type */);
+        tree_view->expand_row (a_var_node, false);
+        NEMIVER_CATCH;
+    }
+
+    void
+    on_draw_signal (const Cairo::RefPtr<Cairo::Context> &)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+        NEMIVER_TRY;
+        if (!is_up2date) {
+            finish_handling_debugger_stopped_event (saved_reason,
+                                                    saved_has_frame,
+                                                    saved_frame);
+            is_up2date = true;
+        }
         NEMIVER_CATCH;
     }
 
@@ -342,13 +481,15 @@ VarsMonitor::add_variables (const IDebugger::VariableList &a_vars)
 }
 
 void
-VarsMonitor::remove_variable (const IDebugger::VariableSafePtr /*a_var*/)
+VarsMonitor::remove_variable (const IDebugger::VariableSafePtr a_var)
 {
+    m_priv->remove_variable (a_var);
 }
 
 void
-VarsMonitor::remove_variables (const std::list<IDebugger::VariableSafePtr> &/*a_vars*/)
+VarsMonitor::remove_variables (const std::list<IDebugger::VariableSafePtr> &a_vars)
 {
+    m_priv->remove_variables (a_vars);
 }
 
 void
diff --git a/src/persp/dbgperspective/ui/varinspectordialog.ui b/src/persp/dbgperspective/ui/varinspectordialog.ui
index 5b6bf75..4fab8c4 100644
--- a/src/persp/dbgperspective/ui/varinspectordialog.ui
+++ b/src/persp/dbgperspective/ui/varinspectordialog.ui
@@ -19,6 +19,20 @@
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
             <child>
+              <object class="GtkButton" id="addtomonitorbutton">
+                <property name="label" translatable="yes">Add to monitor</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkButton" id="okbutton">
                 <property name="label">gtk-close</property>
                 <property name="visible">True</property>
@@ -31,7 +45,7 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
-                <property name="position">0</property>
+                <property name="position">1</property>
               </packing>
             </child>
           </object>
@@ -133,6 +147,7 @@
       </object>
     </child>
     <action-widgets>
+      <action-widget response="-3">addtomonitorbutton</action-widget>
       <action-widget response="-7">okbutton</action-widget>
     </action-widgets>
   </object>



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