[nemiver] 561239 UI to select and copy text from source editor
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver] 561239 UI to select and copy text from source editor
- Date: Mon, 13 May 2013 18:27:55 +0000 (UTC)
commit 0d1dfb5ea4cf6c8b3a47a4e556243fe56d511afb
Author: Dodji Seketeli <dodji seketeli org>
Date: Mon May 13 14:37:40 2013 +0200
561239 UI to select and copy text from source editor
* src/persp/dbgperspective/menus/menus.xml: Add a copy text menu
item.
* src/persp/dbgperspective/nmv-dbg-perspective.cc
(DBGPerspective::{on_copy_action, on_popup_menu,
update_copy_action_sensitivity, setup_and_popup_contextual_menu}):
New methods.
(DBGPerspective::on_run_action): Call the new
setup_and_popup_contextual_menu to popup the context menu.
(DBGPerspective::on_insertion_changed_signal): Update the
sensitivity of the copy action whenever the user clicks in the
source view.
(s_file_opened_action_entries): Add an entry for a "copy text"
action.
(DBGPerspective::append_source_editor ): Do not display the
default context menu that comes with instances of Gtk::TextView.
Rather, display our own. Make sure the copy action sensitivity is
properly set even before the user ever clicks in the source view.
(DBGPerspective::get_contextual_menu): Add a "copy" text to the
contextual menu.
(DBGPerspective::popup_source_view_contextual_menu): Remove this
as its core functionality it provided by
SourceView::setup_and_popup_contextual_menu now.
* src/uicommon/nmv-source-editor.h
(SourceEditor::setup_and_popup_contextual_menu): New declaration.
* src/uicommon/nmv-source-editor.cc
(SourceView::setup_and_popup_contextual_menu): New. Move the core
of DBGPerspective::popup_source_view_contextual_menu here.
(SourceEditor::setup_and_popup_menu): New. Just call the new
SourceView::setup_and_popup_contextual_menu above.
src/persp/dbgperspective/menus/menus.xml | 11 +-
src/persp/dbgperspective/nmv-dbg-perspective.cc | 175 ++++++++++++++++-------
src/uicommon/nmv-source-editor.cc | 58 +++++++-
src/uicommon/nmv-source-editor.h | 4 +
4 files changed, 186 insertions(+), 62 deletions(-)
---
diff --git a/src/persp/dbgperspective/menus/menus.xml b/src/persp/dbgperspective/menus/menus.xml
index fa4dd70..2ec3ea5 100644
--- a/src/persp/dbgperspective/menus/menus.xml
+++ b/src/persp/dbgperspective/menus/menus.xml
@@ -28,10 +28,13 @@
</menu>
<placeholder name="MenuBarAdditions">
<menu action="EditMenuAction" name="EditMenu">
- <menuitem action="FindMenuItemAction"
- name="FindMenutItem"/>
- <menuitem action="CurrentSessionPropertiesMenuItemAction"
- name="CurrentSessionPropertiesMenuItem"/>
+ <menuitem action="CopyMenuItemAction"
+ name="CopyMenutItem"/>
+ <separator/>
+ <menuitem action="FindMenuItemAction"
+ name="FindMenutItem"/>
+ <menuitem action="CurrentSessionPropertiesMenuItemAction"
+ name="CurrentSessionPropertiesMenuItem"/>
</menu>
<menu action="ViewMenuAction" name="ViewMenu">
<menuitem action="ActivateTargetTerminalViewMenuAction"
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 6547439..e5daebe 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -260,6 +260,7 @@ private:
void on_detach_from_program_action ();
void on_choose_a_saved_session_action ();
void on_current_session_properties_action ();
+ void on_copy_action ();
void on_stop_debugger_action ();
void on_run_action ();
void on_save_session_action ();
@@ -307,6 +308,8 @@ private:
bool on_button_pressed_in_source_view_signal (GdkEventButton *a_event);
+ bool on_popup_menu ();
+
bool on_motion_notify_event_signal (GdkEventMotion *a_event);
void on_leave_notify_event_signal (GdkEventCrossing *a_event);
@@ -430,6 +433,7 @@ private:
//************
void update_action_group_sensitivity (IDebugger::State a_state);
+ void update_copy_action_sensitivity ();
string build_resource_path (const UString &a_dir, const UString &a_name);
void add_stock_icon (const UString &a_stock_id,
const UString &icon_dir,
@@ -466,7 +470,6 @@ private:
int get_num_notebook_pages ();
SourceEditor* bring_source_as_current (const UString &a_path);
void bring_source_as_current (SourceEditor *a_editor);
- void popup_source_view_contextual_menu (GdkEventButton *a_event);
void record_and_save_new_session ();
void record_and_save_session (ISessMgr::Session &a_session);
IProcMgr* get_process_manager ();
@@ -790,6 +793,8 @@ public:
Gtk::Widget* get_contextual_menu ();
+ void setup_and_popup_contextual_menu ();
+
bool uses_launch_terminal () const;
void uses_launch_terminal (bool a_flag);
@@ -881,7 +886,7 @@ struct DBGPerspective::Priv {
SafePtr<Gtk::ScrolledWindow> thread_list_scrolled_win;
SafePtr<Gtk::HPaned> call_stack_paned;
SafePtr<Gtk::HPaned> context_paned;
-
+
Glib::RefPtr<Gtk::ActionGroup> default_action_group;
Glib::RefPtr<Gtk::ActionGroup> target_not_started_action_group;
Glib::RefPtr<Gtk::ActionGroup> inferior_loaded_action_group;
@@ -976,6 +981,10 @@ struct DBGPerspective::Priv {
list<UString> call_expr_history;
list<UString> var_inspector_dialog_history;
+ // This is set when the user presses a mouse button in the source
+ // view
+ GdkEventButton *source_view_event_button;
+
Priv () :
initialized (false),
reused_session (false),
@@ -1003,7 +1012,8 @@ struct DBGPerspective::Priv {
mouse_in_source_editor_y (0),
in_show_var_value_at_pos_transaction (false),
var_popup_tip_x (0),
- var_popup_tip_y (0)
+ var_popup_tip_y (0),
+ source_view_event_button (0)
{
}
@@ -1344,6 +1354,22 @@ DBGPerspective::on_current_session_properties_action ()
}
void
+DBGPerspective::on_copy_action ()
+{
+ if (SourceEditor *e = get_current_source_editor ()) {
+ Glib::RefPtr<Gsv::Buffer> buffer =
+ e->source_view ().get_source_buffer ();
+ THROW_IF_FAIL (buffer);
+
+ Gtk::TextIter start, end;
+ if (buffer->get_selection_bounds (start, end))
+ g_signal_emit_by_name (e->source_view ().gobj (),
+ "copy-clipboard");
+ }
+
+}
+
+void
DBGPerspective::on_run_action ()
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -1876,22 +1902,22 @@ DBGPerspective::on_button_pressed_in_source_view_signal
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
- NEMIVER_TRY;
-
- if (a_event->type != GDK_BUTTON_PRESS) {
- return false;
+ if (a_event->type == GDK_BUTTON_PRESS) {
+ m_priv->source_view_event_button = a_event;
+ update_copy_action_sensitivity ();
+ if (a_event->button == 3)
+ setup_and_popup_contextual_menu ();
}
- if (a_event->button == 3) {
- popup_source_view_contextual_menu (a_event);
- return true;
- }
-
- NEMIVER_CATCH;
-
return false;
}
+bool
+DBGPerspective::on_popup_menu ()
+{
+ setup_and_popup_contextual_menu ();
+ return true;
+}
bool
DBGPerspective::on_motion_notify_event_signal (GdkEventMotion *a_event)
@@ -1992,6 +2018,7 @@ DBGPerspective::on_insertion_changed_signal
THROW_IF_FAIL (a_editor);
update_toggle_menu_text (*a_editor, a_it);
+ update_copy_action_sensitivity ();
NEMIVER_CATCH;
}
@@ -2976,6 +3003,32 @@ DBGPerspective::update_action_group_sensitivity (IDebugger::State a_state)
}
}
+/// Updates the sensitivity of the 'Copy' action item.
+///
+/// If there is something to copy, then the action is made sensitive
+/// (i.e, clickable), otherwise it's made unsensitive.
+void
+DBGPerspective::update_copy_action_sensitivity ()
+{
+ Glib::RefPtr<Gtk::Action> action =
+ m_priv->opened_file_action_group->get_action ("CopyMenuItemAction");
+
+ if (!action)
+ return;
+
+ if (SourceEditor *e = get_current_source_editor ()) {
+ Glib::RefPtr<Gsv::Buffer> buffer =
+ e->source_view ().get_source_buffer ();
+ if (!buffer)
+ return;
+ Gtk::TextIter start, end;
+ bool sensitive = false;
+ if (buffer->get_selection_bounds (start, end))
+ sensitive = true;
+ action->set_sensitive (sensitive);
+ }
+}
+
string
DBGPerspective::build_resource_path (const UString &a_dir,
const UString &a_name)
@@ -3022,10 +3075,10 @@ DBGPerspective::add_perspective_menu_entries ()
relative_path = Glib::build_filename ("menus", "contextualmenu.xml");
THROW_IF_FAIL (build_absolute_resource_path
- (Glib::filename_to_utf8 (relative_path), absolute_path));
+ (Glib::filename_to_utf8 (relative_path), absolute_path));
m_priv->contextual_menu_merge_id =
workbench ().get_ui_manager ()->add_ui_from_file
- (Glib::filename_to_utf8 (absolute_path));
+ (Glib::filename_to_utf8 (absolute_path));
#ifdef WITH_MEMORYVIEW
// Add memory view menu item if we're compiling with memoryview support
@@ -3572,6 +3625,16 @@ DBGPerspective::init_actions ()
static ui_utils::ActionEntry s_file_opened_action_entries [] = {
{
+ "CopyMenuItemAction",
+ Gtk::Stock::COPY,
+ _("_Copy selected text"),
+ _("Copy the text selected in the current source file"),
+ sigc::mem_fun (*this, &DBGPerspective::on_copy_action),
+ ActionEntry::DEFAULT,
+ "<control>C",
+ false
+ },
+ {
"ReloadSourceMenuItemAction",
Gtk::Stock::REFRESH,
_("_Reload Source File"),
@@ -3971,11 +4034,23 @@ DBGPerspective::append_source_editor (SourceEditor &a_sv,
if (a_sv.source_view ().get_has_window ()) {
a_sv.source_view ().add_events (Gdk::BUTTON3_MOTION_MASK);
+
a_sv.source_view ().signal_button_press_event ().connect
(sigc::mem_fun
(*this,
&DBGPerspective::on_button_pressed_in_source_view_signal));
+ // OK, this is a hack but it's the cleaner way I've found to
+ // prevent the default popup menu of GtkTextView to show up
+ // whent he user hits the "menu" keyboard key or shit F10.
+ GTK_WIDGET_GET_CLASS (a_sv.source_view ().gobj())->popup_menu = NULL;
+
+ // Then wire our own contextual popup menu when the user hits
+ // the menu key.
+ a_sv.source_view ().signal_popup_menu ().connect
+ (sigc::mem_fun (*this,
+ &DBGPerspective::on_popup_menu));
+
a_sv.source_view ().signal_motion_notify_event ().connect
(sigc::mem_fun
(*this,
@@ -3990,6 +4065,7 @@ DBGPerspective::append_source_editor (SourceEditor &a_sv,
if (get_num_notebook_pages () == 1) {
m_priv->opened_file_action_group->set_sensitive (true);
update_src_dependant_bp_actions_sensitiveness ();
+ update_copy_action_sensitivity ();
}
}
@@ -4428,7 +4504,17 @@ DBGPerspective::get_contextual_menu ()
{
THROW_IF_FAIL (m_priv && m_priv->contextual_menu_merge_id);
- if (!m_priv->contextual_menu) {
+ if (m_priv->contextual_menu == NULL) {
+ workbench ().get_ui_manager ()->add_ui
+ (m_priv->contextual_menu_merge_id,
+ "/ContextualMenu",
+ "CopyMenuItem",
+ "CopyMenuItemAction",
+ Gtk::UI_MANAGER_AUTO,
+ false);
+
+ workbench ().get_ui_manager ()->add_ui_separator
+ (m_priv->contextual_menu_merge_id, "/ContextualMenu");
workbench ().get_ui_manager ()->add_ui
(m_priv->contextual_menu_merge_id,
@@ -4569,11 +4655,28 @@ DBGPerspective::get_contextual_menu ()
m_priv->contextual_menu =
workbench ().get_ui_manager ()->get_widget
("/ContextualMenu");
- THROW_IF_FAIL (m_priv->contextual_menu);
}
+
+ THROW_IF_FAIL (m_priv->contextual_menu);
+
return m_priv->contextual_menu;
}
+/// Get the contextual menu, massage it as necessary and pop it up.
+void
+DBGPerspective::setup_and_popup_contextual_menu ()
+{
+ GdkEventButton *event = m_priv->source_view_event_button;
+ RETURN_IF_FAIL (event);
+
+ SourceEditor *editor = get_current_source_editor ();
+ THROW_IF_FAIL (editor);
+
+ editor->setup_and_popup_menu
+ (event, NULL,
+ dynamic_cast<Gtk::Menu*> (get_contextual_menu ()));
+}
+
bool
DBGPerspective::uses_launch_terminal () const
{
@@ -4741,42 +4844,6 @@ DBGPerspective::get_num_notebook_pages ()
}
void
-DBGPerspective::popup_source_view_contextual_menu (GdkEventButton *a_event)
-{
- int buffer_x=0, buffer_y=0, line_top=0;
- Gtk::TextBuffer::iterator cur_iter;
- UString file_name;
-
- SourceEditor *editor = get_current_source_editor ();
- THROW_IF_FAIL (editor);
-
- editor->source_view ().window_to_buffer_coords (Gtk::TEXT_WINDOW_TEXT,
- (int)a_event->x,
- (int)a_event->y,
- buffer_x, buffer_y);
- editor->source_view ().get_line_at_y (cur_iter, buffer_y, line_top);
-
- editor->get_path (file_name);
-
- Gtk::Menu *menu = dynamic_cast<Gtk::Menu*> (get_contextual_menu ());
- THROW_IF_FAIL (menu);
-
- Gtk::TextIter start, end;
- Glib::RefPtr<Gsv::Buffer> buffer =
- editor->source_view ().get_source_buffer ();
- THROW_IF_FAIL (buffer);
- bool has_selected_text=false;
- if (buffer->get_selection_bounds (start, end)) {
- has_selected_text = true;
- }
- editor->source_view ().get_buffer ()->place_cursor (cur_iter);
- if (has_selected_text) {
- buffer->select_range (start, end);
- }
- menu->popup (a_event->button, a_event->time);
-}
-
-void
DBGPerspective::record_and_save_new_session ()
{
THROW_IF_FAIL (m_priv);
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index 9dacbe5..45de74b 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -88,19 +88,22 @@ public:
init_font ();
}
- void init_font ()
+ void
+ init_font ()
{
Pango::FontDescription font("monospace");
override_font(font);
}
- void enable_events ()
+ void
+ enable_events ()
{
add_events (Gdk::LEAVE_NOTIFY_MASK
|Gdk::BUTTON_PRESS_MASK);
}
- bool on_button_press_event (GdkEventButton *a_event)
+ bool
+ on_button_press_event (GdkEventButton *a_event)
{
if (a_event->type == GDK_BUTTON_PRESS
&& a_event->button == 3) {
@@ -112,11 +115,42 @@ public:
}
}
- sigc::signal<void, int, bool>& marker_region_got_clicked_signal ()
+ sigc::signal<void, int, bool>&
+ marker_region_got_clicked_signal ()
{
return m_marker_region_got_clicked_signal;
}
+ /// Given a menu to popup, pop it up at the right place;
+ ///
+ /// \param a_event the event that triggered this whole button
+ /// popup business or NULL.
+ ///
+ /// \param a_attach_to a widget to attach the popup menu to, or NULL.
+ ///
+ /// \param a_menu the menu to popup.
+ void
+ setup_and_popup_menu (GdkEventButton* a_event,
+ Gtk::Widget *a_attach_to,
+ Gtk::Menu *a_menu)
+ {
+ Gtk::TextBuffer::iterator cur_iter;
+
+ RETURN_IF_FAIL (a_menu);
+
+ if (a_attach_to && a_menu->get_attach_widget () == NULL) {
+ gtk_menu_attach_to_widget (GTK_MENU (a_menu->gobj()),
+ GTK_WIDGET (a_attach_to->gobj()),
+ NULL);
+ }
+
+ Gtk::TextIter start, end;
+ Glib::RefPtr<Gsv::Buffer> buffer = get_source_buffer ();
+ THROW_IF_FAIL (buffer);
+
+ a_menu->popup (a_event ? a_event->button : 0,
+ a_event ? a_event->time : 0);
+ }
};//end class Sourceview
void
@@ -1453,6 +1487,22 @@ SourceEditor::load_file (const UString &a_path,
return true;
}
+ /// Given a menu to popup, pop it up at the right place;
+ ///
+ /// \param a_event the event that triggered this whole button
+ /// popup business or NULL.
+ ///
+ /// \param a_attach_to a widget to attach the popup menu to, or NULL.
+ ///
+ /// \param a_menu the menu to popup.
+void
+SourceEditor::setup_and_popup_menu (GdkEventButton *a_event,
+ Gtk::Widget *a_attach_to,
+ Gtk::Menu *a_menu)
+{
+ m_priv->source_view->setup_and_popup_menu (a_event, a_attach_to,
+ a_menu);
+}
bool
SourceEditor::add_asm (const common::DisassembleInfo &/*a_info*/,
const std::list<common::Asm> &a_asm,
diff --git a/src/uicommon/nmv-source-editor.h b/src/uicommon/nmv-source-editor.h
index 96afaae..c0a6e7f 100644
--- a/src/uicommon/nmv-source-editor.h
+++ b/src/uicommon/nmv-source-editor.h
@@ -114,6 +114,10 @@ public:
bool a_search_backwards=false,
bool a_clear_selection=false);
+ void setup_and_popup_menu (GdkEventButton *a_event,
+ Gtk::Widget *attach_to,
+ Gtk::Menu *custom_menu);
+
static bool get_file_mime_type (const UString &a_path,
UString &a_mime_type);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]