[nautilus-actions] Open a popup on right click in the treeview
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Open a popup on right click in the treeview
- Date: Sun, 18 Oct 2009 19:08:08 +0000 (UTC)
commit b4717597cfab4b1ca066b9215307ba5b217bb8ff
Author: Pierre Wieser <pwieser trychlos org>
Date: Sun Oct 18 21:07:20 2009 +0200
Open a popup on right click in the treeview
ChangeLog | 17 +++
src/nact/nact-iactions-list.c | 145 ++++++++++++++++---------
src/nact/nact-main-menubar.c | 26 +++++-
src/nact/nact-main-menubar.h | 1 +
src/nact/nautilus-actions-config-tool.actions | 19 ++++
5 files changed, 155 insertions(+), 53 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e7ae1bd..0ffe0da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2009-10-18 Pierre Wieser <pwieser trychlos org>
+
+ Open a popup on right click on the treeview.
+
+ * src/nact/nact-iactions-list.c
+ (on_button_press_event): Manage right mouse click.
+ (open_popup): New function.
+ (on_key_pressed_event): Only manage acclerators when treeview has the
+ focus.
+
+ * src/nact/nact-main-menubar.c:
+ * src/nact/nact-main-menubar.h (nact_main_menubar_open_popup):
+ New function.
+
+ * src/nact/nautilus-actions-config-tool.actions:
+ Define the contextual popup menu.
+
2009-10-17 Pierre Wieser <pwieser trychlos org>
* src/nact/nact-main-menubar.c (on_iactions_list_count_updated):
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 3eb99a3..94e6baa 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -41,8 +41,9 @@
#include "nact-application.h"
#include "nact-marshal.h"
#include "nact-main-tab.h"
+#include "nact-main-menubar.h"
+#include "nact-main-window.h"
#include "nact-tree-model.h"
-#include "nact-window.h"
#include "nact-iactions-list.h"
/* private interface data
@@ -174,13 +175,14 @@ static GtkTreePath *object_to_path( NactIActionsList *instance, NactTreeModel *m
static gboolean object_to_path_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ObjectToPathIter *otp );
static gboolean on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsList *instance );
static void on_edition_status_changed( NactIActionsList *instance, NAIDuplicable *object );
+static void on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
static gboolean on_focus_in( GtkWidget *widget, GdkEventFocus *event, NactIActionsList *instance );
static gboolean on_focus_out( GtkWidget *widget, GdkEventFocus *event, NactIActionsList *instance );
static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *instance );
static void on_label_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, NactIActionsList *instance );
-static void on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance );
static void on_tab_updatable_item_updated( NactIActionsList *instance, NAObject *object, gboolean force_display );
-static void on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
+static void on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance );
+static void open_popup( NactIActionsList *instance, GdkEventButton *event );
static void select_first_row( NactIActionsList *instance );
static void select_row_at_path( NactIActionsList *instance, GtkTreeView *treeview, GtkTreeModel *model, GtkTreePath *path );
static void send_list_count_updated_signal( NactIActionsList *instance, IActionsListInstanceData *ialid );
@@ -1978,11 +1980,18 @@ on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsLis
gboolean stop = FALSE;
- if( event->type == GDK_2BUTTON_PRESS ){
+ /* double-click of left button */
+ if( event->type == GDK_2BUTTON_PRESS && event->button == 1 ){
toggle_collapse( instance );
stop = TRUE;
}
+ /* single click on right button */
+ if( event->type == GDK_BUTTON_PRESS && event->button == 3 ){
+ open_popup( instance, event );
+ stop = TRUE;
+ }
+
return( stop );
}
@@ -2018,6 +2027,31 @@ on_edition_status_changed( NactIActionsList *instance, NAIDuplicable *object )
g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_STATUS_CHANGED, NULL );
}
+/*
+ * our handler for "selection-changed" emitted by the interface
+ * this let us transform the signal in a virtual function
+ * so that our implementors have the best of two worlds ;-)
+ */
+static void
+on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
+{
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->selection_changed ){
+ NACT_IACTIONS_LIST_GET_INTERFACE( instance )->selection_changed( instance, selected_items );
+ }
+}
+
+/*
+ * focus is monitored to avoid an accelerator being pressed while on a tab
+ * triggers an unwaited operation on the list
+ * e.g. when editing an entry field on the tab, pressing Del should _not_
+ * delete current row in the list !
+ *
+ * this has the disadvantage that opening a popup menu makes the treeview
+ * loses its focus, and so the edit menu is all disabled
+ *
+ * to fix that, we consider in menubar that treeview always has the focus
+ * and we check it in on_key_pressed()
+ */
static gboolean
on_focus_in( GtkWidget *widget, GdkEventFocus *event, NactIActionsList *instance )
{
@@ -2025,7 +2059,7 @@ on_focus_in( GtkWidget *widget, GdkEventFocus *event, NactIActionsList *instance
gboolean stop = FALSE;
/*g_debug( "%s: widget=%p, event=%p, instance=%p", thisfn, ( void * ) widget, ( void * ) event, ( void * ) instance );*/
- g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_FOCUS_IN, instance );
+ /*g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_FOCUS_IN, instance );*/
return( stop );
}
@@ -2037,7 +2071,7 @@ on_focus_out( GtkWidget *widget, GdkEventFocus *event, NactIActionsList *instanc
gboolean stop = FALSE;
/*g_debug( "%s: widget=%p, event=%p, instance=%p", thisfn, ( void * ) widget, ( void * ) event, ( void * ) instance );*/
- g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_FOCUS_OUT, instance );
+ /*g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_FOCUS_OUT, instance );*/
return( stop );
}
@@ -2047,27 +2081,31 @@ on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *i
{
/*static const gchar *thisfn = "nact_iactions_list_v_on_key_pressed_event";
g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
-
+ GtkTreeView *treeview;
gboolean stop = FALSE;
- if( event->keyval == GDK_Return || event->keyval == GDK_KP_Enter ){
- toggle_collapse( instance );
- stop = TRUE;
- }
+ treeview = get_actions_list_treeview( instance );
+ if( GTK_WIDGET_HAS_FOCUS( treeview )){
- if( event->keyval == GDK_F2 ){
- inline_edition( instance );
- stop = TRUE;
- }
+ if( event->keyval == GDK_Return || event->keyval == GDK_KP_Enter ){
+ toggle_collapse( instance );
+ stop = TRUE;
+ }
- if( event->keyval == GDK_Right ){
- expand_to_first_child( instance );
- stop = TRUE;
- }
+ if( event->keyval == GDK_F2 ){
+ inline_edition( instance );
+ stop = TRUE;
+ }
- if( event->keyval == GDK_Left ){
- collapse_to_parent( instance );
- stop = TRUE;
+ if( event->keyval == GDK_Right ){
+ expand_to_first_child( instance );
+ stop = TRUE;
+ }
+
+ if( event->keyval == GDK_Left ){
+ collapse_to_parent( instance );
+ stop = TRUE;
+ }
}
return( stop );
@@ -2100,6 +2138,32 @@ on_label_edited( GtkCellRendererText *renderer, const gchar *path_str, const gch
}
/*
+ * an item has been updated in one of the tabs
+ * update the treeview to reflects its new edition status
+ */
+static void
+on_tab_updatable_item_updated( NactIActionsList *instance, NAObject *object, gboolean force_display )
+{
+ static const gchar *thisfn = "nact_iactions_list_on_tab_updatable_item_updated";
+ GtkTreeView *treeview;
+ GtkTreeModel *model;
+
+ g_debug( "%s: instance=%p, object=%p (%s)", thisfn,
+ ( void * ) instance, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( NA_IS_IDUPLICABLE( object ));
+
+ if( object ){
+ treeview = get_actions_list_treeview( instance );
+ model = gtk_tree_view_get_model( treeview );
+ if( !na_object_check_status_up( object ) && force_display ){
+ on_edition_status_changed( instance, NA_IDUPLICABLE( object ));
+ }
+ }
+}
+
+/*
* this is our handler of "changed" signal emitted by the treeview
* it is inhibited while filling the list (usually only at runtime init)
* and while deleting a selection
@@ -2125,42 +2189,19 @@ on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *in
/* selection list if free in cleanup handler for the signal */
}
-/*
- * an item has been updated in one of the tabs
- * update the treeview to reflects its new edition status
- */
static void
-on_tab_updatable_item_updated( NactIActionsList *instance, NAObject *object, gboolean force_display )
+open_popup( NactIActionsList *instance, GdkEventButton *event )
{
- static const gchar *thisfn = "nact_iactions_list_on_tab_updatable_item_updated";
GtkTreeView *treeview;
GtkTreeModel *model;
+ GtkTreePath *path;
- g_debug( "%s: instance=%p, object=%p (%s)", thisfn,
- ( void * ) instance, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
- g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
- g_return_if_fail( NA_IS_OBJECT( object ));
- g_return_if_fail( NA_IS_IDUPLICABLE( object ));
-
- if( object ){
- treeview = get_actions_list_treeview( instance );
+ treeview = get_actions_list_treeview( instance );
+ if( gtk_tree_view_get_path_at_pos( treeview, event->x, event->y, &path, NULL, NULL, NULL )){
model = gtk_tree_view_get_model( treeview );
- if( !na_object_check_status_up( object ) && force_display ){
- on_edition_status_changed( instance, NA_IDUPLICABLE( object ));
- }
- }
-}
-
-/*
- * our handler for "selection-changed" emitted by the interface
- * this let us transform the signal in a virtual function
- * so that our implementors have the best of two worlds ;-)
- */
-static void
-on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
-{
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->selection_changed ){
- NACT_IACTIONS_LIST_GET_INTERFACE( instance )->selection_changed( instance, selected_items );
+ select_row_at_path( instance, treeview, model, path );
+ gtk_tree_path_free( path );
+ nact_main_menubar_open_popup( NACT_MAIN_WINDOW( instance ), event );
}
}
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index 02a2c8c..dde5f59 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -259,7 +259,7 @@ nact_main_menubar_runtime_init( NactMainWindow *window )
* - pack menu bar in the main window
*/
ui_manager = gtk_ui_manager_new();
- g_object_set_data_full( G_OBJECT( window ), MENUBAR_PROP_UI_MANAGER, ui_manager, ( GDestroyNotify ) on_destroy_callback );
+ g_object_set_data_full( G_OBJECT( window ), MENUBAR_PROP_UI_MANAGER, ui_manager, ( GDestroyNotify ) on_destroy_callback );
g_debug( "%s: ui_manager=%p", thisfn, ( void * ) ui_manager );
base_window_signal_connect(
@@ -368,6 +368,7 @@ nact_main_menubar_runtime_init( NactMainWindow *window )
G_CALLBACK( on_level_zero_order_changed ));
mis = g_new0( MenubarIndicatorsStruct, 1 );
+ mis->treeview_has_focus = TRUE;
g_object_set_data( G_OBJECT( window ), MENUBAR_PROP_INDICATORS, mis );
}
@@ -390,6 +391,25 @@ nact_main_menubar_dispose( NactMainWindow *window )
g_free( mis );
}
+/**
+ * nact_main_menubar_open_popup:
+ * @window: this #NactMainWindow window.
+ * @event: the mouse event.
+ *
+ * Opens a popup menu.
+ */
+void
+nact_main_menubar_open_popup( NactMainWindow *instance, GdkEventButton *event )
+{
+ GtkUIManager *ui_manager;
+ GtkWidget *menu;
+
+ ui_manager = ( GtkUIManager * ) g_object_get_data( G_OBJECT( instance ), MENUBAR_PROP_UI_MANAGER );
+ menu = gtk_ui_manager_get_widget( ui_manager, "/ui/Popup" );
+
+ gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL, event->button, event->time );
+}
+
/*
* when the IActionsList is refilled, update our internal counters so
* that we are knowing if we have some exportables
@@ -439,6 +459,10 @@ on_iactions_list_selection_changed( NactMainWindow *window, GList *selected )
g_signal_emit_by_name( window, MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES, NULL );
}
+/*
+ * these two functions are no more used
+ * see comment in nact-iactions-list.c::on_focus_in().
+ */
static void
on_iactions_list_focus_in( NactMainWindow *window, gpointer user_data )
{
diff --git a/src/nact/nact-main-menubar.h b/src/nact/nact-main-menubar.h
index d5815fd..e26a698 100644
--- a/src/nact/nact-main-menubar.h
+++ b/src/nact/nact-main-menubar.h
@@ -43,6 +43,7 @@ G_BEGIN_DECLS
void nact_main_menubar_runtime_init( NactMainWindow *window );
void nact_main_menubar_dispose( NactMainWindow *window );
+void nact_main_menubar_open_popup( NactMainWindow *window, GdkEventButton *event );
G_END_DECLS
diff --git a/src/nact/nautilus-actions-config-tool.actions b/src/nact/nautilus-actions-config-tool.actions
index 484fb40..812fe90 100644
--- a/src/nact/nautilus-actions-config-tool.actions
+++ b/src/nact/nautilus-actions-config-tool.actions
@@ -37,6 +37,25 @@
</menu>
</menubar>
+ <popup name="Popup">
+ <menuitem action="NewMenuItem" />
+ <menuitem action="NewActionItem" />
+ <menuitem action="NewProfileItem" />
+ <separator />
+ <menuitem action="CutItem" />
+ <menuitem action="CopyItem" />
+ <menuitem action="PasteItem" />
+ <menuitem action="PasteIntoItem" />
+ <menuitem action="DuplicateItem" />
+ <menuitem action="DeleteItem" />
+ <separator />
+ <menuitem action="ImportItem" />
+ <menuitem action="ExportItem" />
+ <separator />
+ <menuitem action="PreferencesItem" />
+ <menuitem action="AboutItem" />
+ </popup>
+
<toolbar name="FileToolbar">
<toolitem action="NewActionItem" />
<toolitem action="SaveItem" />
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]