[nemiver] Support copying variable value to the clipboard



commit cb7c903a806355ec5eae8f0d828ff9fdd7f7cdbb
Author: Dodji Seketeli <dodji redhat com>
Date:   Sat May 30 12:48:19 2009 +0200

    Support copying variable value to the clipboard
    
    	* src/persp/dbgperspective/nmv-var-inspector2.cc:
    	(VarsInspector2::Priv::init_actions): Don't make the array of
    	ActionEntry be static. It triggers side effects when the
    	LocalVarInspector2 is instantiated (and the menu used) more
    	than once.
    	Use a UIManager local to this class, not the one of the
    	debugging perspective. Add a new menu entry to copy the value of a
    	variable. This uses a varobj powered variable walker for cases
    	where the variable is a compound variable and thus must be unfolded
    	so that its member needs to be retrieved from the debugger.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc:
    	(DBGPerspective::init_actions): Don't make the array of ActionEntry
    	be static.
    	(DBGPerspective::load_menu): Allow this to be called twice with the
    	same menu file.
    	* src/persp/dbgperspective/nmv-local-vars-inspector2.cc:
    	(LocalVarsInspector2::Priv::init_actions): Don't make the array of
    	ActionEntry be static.
---
 src/persp/dbgperspective/nmv-dbg-perspective.cc    |   27 ++--
 .../dbgperspective/nmv-local-vars-inspector2.cc    |    2 +-
 src/persp/dbgperspective/nmv-var-inspector2.cc     |  186 +++++++++++++++++++-
 3 files changed, 195 insertions(+), 20 deletions(-)

diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 99fa794..ec9ddd1 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -2763,7 +2763,7 @@ DBGPerspective::init_actions ()
 {
     Gtk::StockID nil_stock_id ("");
     sigc::slot<void> nil_slot;
-    static ui_utils::ActionEntry s_target_connected_action_entries [] = {
+    ui_utils::ActionEntry s_target_connected_action_entries [] = {
         {
             "SaveSessionMenuItemAction",
             Gtk::Stock::SAVE,
@@ -4717,26 +4717,31 @@ Gtk::Widget*
 DBGPerspective::load_menu (const UString &a_filename,
                            const UString &a_widget_name)
 {
-    NEMIVER_TRY
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
 
-    string relative_path = Glib::build_filename ("menus", a_filename);
-    string absolute_path;
-    THROW_IF_FAIL (build_absolute_resource_path
-                        (Glib::filename_to_utf8 (relative_path),
-                         absolute_path));
+    Gtk::Widget *result =
+        workbench ().get_ui_manager ()->get_widget (a_widget_name);
 
-    workbench ().get_ui_manager ()->add_ui_from_file
-        (Glib::filename_to_utf8 (absolute_path));
+    if (!result) {
+        string relative_path = Glib::build_filename ("menus", a_filename);
+        string absolute_path;
+        THROW_IF_FAIL (build_absolute_resource_path
+                            (Glib::filename_to_utf8 (relative_path),
+                             absolute_path));
+        workbench ().get_ui_manager ()->add_ui_from_file
+            (Glib::filename_to_utf8 (absolute_path));
 
-    NEMIVER_CATCH
+        result = workbench ().get_ui_manager ()->get_widget (a_widget_name);
+    }
 
-    return workbench ().get_ui_manager ()->get_widget (a_widget_name);
+    return result;
 }
 
 void
 DBGPerspective::close_opened_files ()
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
+
     if (!get_n_pages ()) {return;}
 
     map<UString, int>::iterator it;
diff --git a/src/persp/dbgperspective/nmv-local-vars-inspector2.cc b/src/persp/dbgperspective/nmv-local-vars-inspector2.cc
index f97a23d..a99b986 100644
--- a/src/persp/dbgperspective/nmv-local-vars-inspector2.cc
+++ b/src/persp/dbgperspective/nmv-local-vars-inspector2.cc
@@ -226,7 +226,7 @@ public:
     void
     init_actions ()
     {
-        static ui_utils::ActionEntry s_local_vars_inspector_action_entries [] = {
+        ui_utils::ActionEntry s_local_vars_inspector_action_entries [] = {
             {
                 "CopyLocalVariablePathMenuItemAction",
                 Gtk::Stock::COPY,
diff --git a/src/persp/dbgperspective/nmv-var-inspector2.cc b/src/persp/dbgperspective/nmv-var-inspector2.cc
index 9a60813..b0d9117 100644
--- a/src/persp/dbgperspective/nmv-var-inspector2.cc
+++ b/src/persp/dbgperspective/nmv-var-inspector2.cc
@@ -25,8 +25,10 @@
 #include "config.h"
 
 #include <glib/gi18n.h>
+#include <sstream>
 #include <gtkmm/treestore.h>
 #include "common/nmv-exception.h"
+#include "common/nmv-dynamic-module.h"
 #include "nmv-var-inspector2.h"
 #include "nmv-variables-utils.h"
 #include "nmv-i-var-walker.h"
@@ -39,6 +41,8 @@ namespace uutil = nemiver::ui_utils;
 namespace vutil = nemiver::variables_utils2;
 namespace cmn = nemiver::common;
 
+using cmn::DynamicModuleManager;
+
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 
 class VarInspector2::Priv : public sigc::trackable {
@@ -59,6 +63,9 @@ class VarInspector2::Priv : public sigc::trackable {
     Gtk::TreeModel::iterator cur_selected_row;
     Glib::RefPtr<Gtk::ActionGroup> var_inspector_action_group;
     Gtk::Widget *var_inspector_menu;
+    IVarWalkerSafePtr varobj_walker;
+    DynamicModuleManager *module_manager;
+    Glib::RefPtr<Gtk::UIManager> ui_manager;
 
     void
     build_widget ()
@@ -110,7 +117,7 @@ class VarInspector2::Priv : public sigc::trackable {
 
     void init_actions ()
     {
-        static ui_utils::ActionEntry s_var_inspector_action_entries [] = {
+        ui_utils::ActionEntry s_var_inspector_action_entries [] = {
             {
                 "CopyVariablePathMenuItemAction",
                 Gtk::Stock::COPY,
@@ -121,6 +128,17 @@ class VarInspector2::Priv : public sigc::trackable {
                      &Priv::on_variable_path_expr_copy_to_clipboard_action),
                 ui_utils::ActionEntry::DEFAULT,
                 ""
+            },
+            {
+                "CopyVariableValueMenuItemAction",
+                Gtk::Stock::COPY,
+                _("_Copy variable value"),
+                _("Copy the variable value to the clipboard"),
+                sigc::mem_fun
+                    (*this,
+                     &Priv::on_variable_value_copy_to_clipboard_action),
+                ui_utils::ActionEntry::DEFAULT,
+                ""
             }
         };
 
@@ -137,8 +155,7 @@ class VarInspector2::Priv : public sigc::trackable {
              num_actions,
              var_inspector_action_group);
 
-        perspective.get_workbench ().get_ui_manager ()->insert_action_group
-                                            (var_inspector_action_group);
+        get_ui_manager ()->insert_action_group (var_inspector_action_group);
     }
 
     // If the variable we are inspected was created
@@ -218,20 +235,39 @@ class VarInspector2::Priv : public sigc::trackable {
                     (this, &VarInspector2::Priv::on_variable_created_signal));
     }
 
+    Glib::RefPtr<Gtk::UIManager> get_ui_manager ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (!ui_manager) {
+            ui_manager = Gtk::UIManager::create ();
+        }
+        return ui_manager;
+    }
+
     Gtk::Widget* get_var_inspector_menu ()
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
 
         if (!var_inspector_menu) {
+            string relative_path =
+                Glib::build_filename ("menus", "varinspectorpopup.xml");
+            string absolute_path;
+            THROW_IF_FAIL (perspective.build_absolute_resource_path
+                                                (relative_path, absolute_path));
+            get_ui_manager ()->add_ui_from_file (absolute_path);
+            get_ui_manager ()->ensure_update ();
             var_inspector_menu =
-                perspective.load_menu ("varinspectorpopup.xml",
-                                       "/VarInspectorPopup");
-            THROW_IF_FAIL (var_inspector_menu);
+                get_ui_manager ()->get_widget ("/VarInspectorPopup");
         }
         return var_inspector_menu;
     }
-    void popup_var_inspector_menu (GdkEventButton *a_event)
+
+    void
+    popup_var_inspector_menu (GdkEventButton *a_event)
     {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
         Gtk::Menu *menu =
             dynamic_cast<Gtk::Menu*> (get_var_inspector_menu ());
         THROW_IF_FAIL (menu);
@@ -252,12 +288,125 @@ class VarInspector2::Priv : public sigc::trackable {
         }
     }
 
+    DynamicModuleManager*
+    get_module_manager ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (!module_manager) {
+            DynamicModule::Loader *loader =
+                perspective.get_workbench ().get_dynamic_module
+                                                    ().get_module_loader ();
+            THROW_IF_FAIL (loader);
+            module_manager = loader->get_dynamic_module_manager ();
+            THROW_IF_FAIL (module_manager);
+        }
+        return module_manager;
+    }
+
+    IVarWalkerSafePtr
+    create_varobj_walker ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        IVarWalkerSafePtr result  =
+            get_module_manager ()->load_iface_with_default_manager<IVarWalker>
+                                            ("varobjwalker", "IVarWalker");
+        result->visited_variable_signal ().connect
+            (sigc::mem_fun (*this, &Priv::on_visited_variable_signal));
+        return result;
+    }
+
+    IVarWalkerSafePtr
+    get_varobj_walker ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        if (!varobj_walker)
+            varobj_walker = create_varobj_walker ();
+        return varobj_walker;
+    }
+
+    void
+    gen_white_spaces (int a_nb_ws,
+                      std::string &a_ws_str)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        for (int i = 0; i < a_nb_ws; i++) {
+            a_ws_str += ' ';
+        }
+
+    }
+
+    void
+    dump_variable_value (IDebugger::VariableSafePtr a_var,
+                         int a_indent_num,
+                         std::ostringstream &a_os,
+                         bool a_print_var_name = false)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        THROW_IF_FAIL (a_var);
+
+        std::string ws_string;
+
+        if (a_indent_num)
+            gen_white_spaces (a_indent_num, ws_string);
+
+        if (a_print_var_name)
+            a_os << ws_string << a_var->name ();
+
+        if (!a_var->members ().empty ()) {
+            a_os << "\n"  << ws_string << "{\n";
+            IDebugger::VariableList::const_iterator it;
+            for (it = a_var->members ().begin ();
+                 it != a_var->members ().end ();
+                 ++it) {
+                dump_variable_value (*it, a_indent_num + 2, a_os, true);
+            }
+            a_os << "\n" << ws_string <<  "}\n";
+        } else {
+            a_os << ws_string;
+            if (a_print_var_name)
+                a_os << " = ";
+            a_os << a_var->value ();
+        }
+    }
+
+    void
+    dump_variable_value (IDebugger::VariableSafePtr a_var,
+                         int a_indent_num,
+                         std::string &a_out_str)
+    {
+        std::ostringstream os;
+        dump_variable_value (a_var, a_indent_num, os);
+        a_out_str = os.str ();
+    }
+
+
     // ******************
     // <signal handlers>
     // ******************
 
 
     void
+    on_visited_variable_signal (const IDebugger::VariableSafePtr a_var)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY
+
+        std::string str;
+        dump_variable_value (a_var, 0, str);
+
+        if (!str.empty ())
+            Gtk::Clipboard::get ()->set_text (str);
+
+        NEMIVER_CATCH
+    }
+
+    void
     on_tree_view_selection_changed_signal ()
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -437,6 +586,26 @@ class VarInspector2::Priv : public sigc::trackable {
         NEMIVER_CATCH
     }
 
+    void on_variable_value_copy_to_clipboard_action ()
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+        NEMIVER_TRY
+
+        THROW_IF_FAIL (cur_selected_row);
+
+        IDebugger::VariableSafePtr variable =
+            cur_selected_row->get_value
+                (vutil::get_variable_columns ().variable);
+        THROW_IF_FAIL (variable);
+
+        IVarWalkerSafePtr walker = get_varobj_walker ();
+        walker->connect (debugger, variable);
+        walker->do_walk_variable ();
+
+        NEMIVER_CATCH
+    }
+
     void on_variable_path_expression_signal
                                     (const IDebugger::VariableSafePtr a_var)
     {
@@ -459,7 +628,8 @@ public:
           expand_variable (false),
           debugger (a_debugger),
           perspective (a_perspective),
-          var_inspector_menu (0)
+          var_inspector_menu (0),
+          module_manager (0)
     {
         build_widget ();
         re_init_tree_view ();



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