[Gnucash-changes] r13847 - gnucash/trunk/src - Implement a keynav policy for the budget page. Addresses bug #339515.

Chris Shoemaker chris at cvs.gnucash.org
Tue Apr 25 00:18:46 EDT 2006


Author: chris
Date: 2006-04-25 00:18:45 -0400 (Tue, 25 Apr 2006)
New Revision: 13847
Trac: http://svn.gnucash.org/trac/changeset/13847

Modified:
   gnucash/trunk/src/gnome-utils/gnc-tree-view.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view.h
   gnucash/trunk/src/gnome/gnc-plugin-page-budget.c
Log:
  Implement a keynav policy for the budget page.  Addresses bug #339515.


Modified: gnucash/trunk/src/gnome/gnc-plugin-page-budget.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-budget.c	2006-04-25 04:17:48 UTC (rev 13846)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-budget.c	2006-04-25 04:18:45 UTC (rev 13847)
@@ -95,12 +95,14 @@
     GtkWidget *window, GKeyFile *file, const gchar *group);
 
 
-static gboolean gnc_plugin_page_budget_button_press_cb(
+static gboolean gppb_button_press_cb(
     GtkWidget *widget, GdkEventButton *event, GncPluginPage *page);
-static void gnc_plugin_page_budget_double_click_cb(
+static gboolean gppb_key_press_cb(
+    GtkWidget *treeview, GdkEventKey *event, gpointer userdata);
+static void gppb_double_click_cb(
     GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col,
     GncPluginPageBudget *page);
-static void gnc_plugin_page_budget_selection_changed_cb(
+static void gppb_selection_changed_cb(
     GtkTreeSelection *selection, GncPluginPageBudget *page);
 
 static void gnc_plugin_page_budget_view_refresh (GncPluginPageBudget *page);
@@ -394,17 +396,16 @@
     selection = gtk_tree_view_get_selection(tree_view);
     gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
 
-    g_signal_connect (G_OBJECT (selection), "changed",
-		      G_CALLBACK (gnc_plugin_page_budget_selection_changed_cb),
-		      plugin_page);
-    g_signal_connect (G_OBJECT (tree_view), "button-press-event",
-                      G_CALLBACK (gnc_plugin_page_budget_button_press_cb),
-                      plugin_page);
-    g_signal_connect (G_OBJECT (tree_view), "row-activated",
-                      G_CALLBACK (gnc_plugin_page_budget_double_click_cb),
-                      page);
+    g_signal_connect(G_OBJECT(selection), "changed",
+                     G_CALLBACK(gppb_selection_changed_cb), plugin_page);
+    g_signal_connect(G_OBJECT(tree_view), "button-press-event",
+                     G_CALLBACK(gppb_button_press_cb), plugin_page);
+    g_signal_connect(G_OBJECT(tree_view), "row-activated",
+                     G_CALLBACK(gppb_double_click_cb), page);
+    g_signal_connect_after(G_OBJECT(tree_view), "key-press-event",
+                           G_CALLBACK(gppb_key_press_cb), NULL);
 
-    gnc_plugin_page_budget_selection_changed_cb (NULL, page);
+    gppb_selection_changed_cb (NULL, page);
     gtk_tree_view_set_headers_visible(tree_view, TRUE);
     gtk_widget_show (GTK_WIDGET (tree_view));
     gtk_container_add (GTK_CONTAINER (scrolled_window),
@@ -564,9 +565,8 @@
  *  Button presses on all other pages are caught by the signal
  *  registered in gnc-main-window.c. */
 static gboolean
-gnc_plugin_page_budget_button_press_cb (GtkWidget *widget,
-					GdkEventButton *event,
-					GncPluginPage *page)
+gppb_button_press_cb(GtkWidget *widget, GdkEventButton *event,
+                     GncPluginPage *page)
 {
   gboolean result;
 
@@ -578,11 +578,36 @@
   return result;
 }
 
+static gboolean
+gppb_key_press_cb(GtkWidget *treeview, GdkEventKey *event, gpointer userdata)
+{
+    GtkTreeView *tv = GTK_TREE_VIEW(treeview);
+    GtkTreeViewColumn *col;
+    GtkTreePath *path = NULL;
+
+    if (event->type != GDK_KEY_PRESS) return TRUE;
+
+    switch (event->keyval) {
+    case GDK_Tab:
+    case GDK_ISO_Left_Tab:
+    case GDK_KP_Tab:
+    case GDK_Return:
+    case GDK_KP_Enter:
+        gtk_tree_view_get_cursor(tv, &path, &col);
+        if (!path) return TRUE;
+        //finish_edit(col);
+        break;
+    }
+    gnc_tree_view_keynav(GNC_TREE_VIEW(tv), &col, path, event);
+    
+    if (path && gnc_tree_view_path_is_valid(GNC_TREE_VIEW(tv), path))
+        gtk_tree_view_set_cursor(tv, path, col, TRUE);
+    return TRUE;
+}
+
 static void
-gnc_plugin_page_budget_double_click_cb (GtkTreeView        *treeview,
-					GtkTreePath        *path,
-					GtkTreeViewColumn  *col,
-					GncPluginPageBudget *page)
+gppb_double_click_cb(GtkTreeView *treeview, GtkTreePath *path,
+                     GtkTreeViewColumn *col, GncPluginPageBudget *page)
 {
     GtkWidget *window;
     GncPluginPage *new_page;
@@ -600,8 +625,8 @@
 }
 
 static void
-gnc_plugin_page_budget_selection_changed_cb (GtkTreeSelection *selection,
-					     GncPluginPageBudget *page)
+gppb_selection_changed_cb(GtkTreeSelection *selection,
+                          GncPluginPageBudget *page)
 {
     GtkActionGroup *action_group;
     GtkTreeView *view;
@@ -627,7 +652,6 @@
     gnc_plugin_update_actions (action_group, actions_requiring_account,
 				   "sensitive", sensitive);
 }
-	
 
 /* Command callbacks */
 

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view.c	2006-04-25 04:17:48 UTC (rev 13846)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view.c	2006-04-25 04:18:45 UTC (rev 13847)
@@ -35,6 +35,7 @@
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
 #include <string.h>
 
 #include "gnc-tree-view.h"
@@ -2084,4 +2085,98 @@
   return gtk_tree_view_insert_column (GTK_TREE_VIEW(view), column, n);
 }
 
+static gboolean
+get_column_next_to(GtkTreeView *tv, GtkTreeViewColumn **col, gboolean backward)
+{
+    GList *cols, *node;
+    GtkTreeViewColumn *c = NULL;
+    gint seen = 0;
+    gboolean wrapped = FALSE;
+    
+    cols = gtk_tree_view_get_columns(tv);
+    g_return_val_if_fail(g_list_length(cols) > 0, FALSE);
+    
+    node = g_list_find(cols, *col);
+    g_return_val_if_fail(node, FALSE);
+    do {
+        node = backward ? node->prev : node->next;
+        if (!node) {
+            wrapped = TRUE;
+            node = backward ? g_list_last(cols) : cols;
+        }
+        c = GTK_TREE_VIEW_COLUMN(node->data);
+        if (c && gtk_tree_view_column_get_visible(c))
+            seen++;
+        if (c == *col) break;
+    } while (!seen);
+    
+    g_list_free(cols);
+    *col = c;
+    return wrapped;
+}
+
+gboolean
+gnc_tree_view_path_is_valid(GncTreeView *view, GtkTreePath *path)
+{
+    GtkTreeView *tv = GTK_TREE_VIEW(view);
+    GtkTreeModel *s_model;
+    GtkTreeIter iter;
+
+    s_model = gtk_tree_view_get_model(tv);
+    return gtk_tree_model_get_iter(s_model, &iter, path);
+}
+
+void
+gnc_tree_view_keynav(GncTreeView *view, GtkTreeViewColumn **col, 
+                     GtkTreePath *path, GdkEventKey *event)
+{
+    GtkTreeView *tv = GTK_TREE_VIEW(view);
+    gint depth;
+    gboolean shifted;
+
+    if (event->type != GDK_KEY_PRESS) return;
+
+    switch (event->keyval) {
+    case GDK_Tab:
+    case GDK_ISO_Left_Tab:
+    case GDK_KP_Tab:
+        shifted = event->state & GDK_SHIFT_MASK;
+        if (get_column_next_to(tv, col, shifted)) {
+            /* This is the end (or beginning) of the line, buddy. */
+            depth = gtk_tree_path_get_depth(path);
+            if (shifted) {
+                if (!gtk_tree_path_prev(path) && depth > 1) {
+                    gtk_tree_path_up(path);
+                }
+            } else if (gtk_tree_view_row_expanded(tv, path)) {
+                gtk_tree_path_down(path);
+            } else {
+                gtk_tree_path_next(path);
+                if (!gnc_tree_view_path_is_valid(view, path) && depth > 1) {
+                    gtk_tree_path_prev(path);
+                    gtk_tree_path_up(path);
+                    gtk_tree_path_next(path);
+                }
+            }
+        }
+        break;
+
+    case GDK_Return:
+    case GDK_KP_Enter:
+        if (gtk_tree_view_row_expanded(tv, path)) {
+            gtk_tree_path_down(path);
+        } else {
+            gtk_tree_path_next(path);
+            if (!gnc_tree_view_path_is_valid(view, path) && depth > 1) {
+                gtk_tree_path_prev(path);
+                gtk_tree_path_up(path);
+                gtk_tree_path_next(path);
+            }
+        }
+        break;
+    }
+    return;
+}
+
+
 /** @} */

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view.h	2006-04-25 04:17:48 UTC (rev 13846)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view.h	2006-04-25 04:18:45 UTC (rev 13847)
@@ -369,6 +369,19 @@
 GtkCellRenderer *
 gnc_tree_view_column_get_renderer(GtkTreeViewColumn *column);
 
+
+/* Takes a GdkEventKey and the current path and column for the
+ * treeview.  Interprets the event as something that might move the
+ * cursor.  Returns the new column and the possibly changed (if
+ * navigation wrapped a row) path. */
+void
+gnc_tree_view_keynav(GncTreeView *view, GtkTreeViewColumn **col, 
+                     GtkTreePath *path, GdkEventKey *event);
+
+/* Returns TRUE if path is a vaid path for the treeview */
+gboolean
+gnc_tree_view_path_is_valid(GncTreeView *view, GtkTreePath *path);
+
 /** @} */
 
 /** @} */



More information about the gnucash-changes mailing list