diff --git a/src/gnome-utils/glade/preferences.glade b/src/gnome-utils/glade/preferences.glade index beed29e24b..21f8747c94 100644 --- a/src/gnome-utils/glade/preferences.glade +++ b/src/gnome-utils/glade/preferences.glade @@ -3457,7 +3457,7 @@ 6 True - 19 + 20 4 False 0 @@ -3478,7 +3478,7 @@ 0 - 1 + 4 8 9 12 @@ -3503,7 +3503,7 @@ 0 - 1 + 4 7 8 12 @@ -3528,7 +3528,7 @@ 0 - 1 + 4 6 7 12 @@ -3553,7 +3553,7 @@ 0 - 1 + 4 5 6 12 @@ -3578,7 +3578,7 @@ 0 - 1 + 4 4 5 12 @@ -3607,7 +3607,7 @@ 0 - 1 + 4 3 4 fill @@ -3635,7 +3635,7 @@ 0 - 1 + 4 0 1 fill @@ -3685,7 +3685,7 @@ 0 - 1 + 4 1 2 12 @@ -3708,7 +3708,7 @@ 0 - 1 + 4 12 13 12 @@ -3738,8 +3738,8 @@ 0 1 - 13 - 14 + 14 + 15 fill @@ -3765,9 +3765,9 @@ 0 - 1 - 14 - 15 + 4 + 15 + 16 fill @@ -3788,9 +3788,9 @@ 0 - 1 - 15 - 16 + 4 + 16 + 17 12 fill @@ -3813,9 +3813,9 @@ 0 - 1 - 16 - 17 + 4 + 17 + 18 12 fill @@ -3838,9 +3838,9 @@ 0 - 1 - 17 - 18 + 4 + 18 + 19 12 fill @@ -3863,9 +3863,9 @@ 0 - 1 - 18 - 19 + 4 + 19 + 20 12 fill @@ -3903,7 +3903,7 @@ True - <b>Close Button</b> + <b>Tabs</b> False True GTK_JUSTIFY_LEFT @@ -3920,7 +3920,7 @@ 0 - 1 + 4 10 11 fill @@ -3943,7 +3943,7 @@ 0 - 1 + 4 11 12 12 @@ -3951,6 +3951,108 @@ + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + _Width: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + 1 + 13 + 14 + fill + fill + + + + + + True + False + 0 + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 30 1 100 1 10 10 + + + 0 + False + True + + + + + + True + characters + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 3 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 1 + 2 + 13 + 14 + fill + fill + + False diff --git a/src/gnome-utils/gnc-main-window.c b/src/gnome-utils/gnc-main-window.c index c6d45ee99b..77dd085137 100644 --- a/src/gnome-utils/gnc-main-window.c +++ b/src/gnome-utils/gnc-main-window.c @@ -79,10 +79,12 @@ enum { #define PLUGIN_PAGE_LABEL "plugin-page" #define PLUGIN_PAGE_CLOSE_BUTTON "close-button" +#define PLUGIN_PAGE_TAB_LABEL "label" #define KEY_SHOW_CLOSE_BUTTON "tab_close_buttons" #define KEY_TAB_NEXT_RECENT "tab_next_recent" #define KEY_TAB_POSITION "tab_position" +#define KEY_TAB_WIDTH "tab_width" #define GNC_MAIN_WINDOW_NAME "GncMainWindow" @@ -392,6 +394,11 @@ static const gchar *multiple_page_actions[] = { }; +/* This data structure holds the tooltops for all notebook tabs. + * Typically these are used to provide the full path of a register + * page. */ +static GtkTooltips *tips = NULL; + /************************************************************ * * ************************************************************/ @@ -419,6 +426,29 @@ typedef struct { } GncMainWindowSaveData; +/* Iterator function to walk all pages in all windows, calling the + * specified function for each page. */ +void +gnc_main_window_foreach_page (GncMainWindowPageFunc fn, gpointer user_data) +{ + GncMainWindowPrivate *priv; + GncMainWindow *window; + GncPluginPage *page; + GList *w, *p; + + ENTER(" "); + for (w = active_windows; w; w = g_list_next(w)) { + window = w->data; + priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); + for (p = priv->installed_pages; p; p = g_list_next(p)) { + page = p->data; + fn(page, user_data); + } + } + LEAVE(" "); +} + + /** Restore a single page to a window. This function calls a page * specific function to create the actual page. It then handles all * the common tasks such as insuring the page is installed into a @@ -1445,9 +1475,10 @@ gnc_main_window_update_all_menu_items (void) * or not the close button should be visible. */ static void -gnc_main_window_update_tabs_one_page (GncPluginPage *page, - gboolean *new_value) +gnc_main_window_update_tab_close_one_page (GncPluginPage *page, + gpointer user_data) { + gboolean *new_value = user_data; GtkWidget * close_button; ENTER("page %p, visible %d", page, *new_value); @@ -1465,35 +1496,9 @@ gnc_main_window_update_tabs_one_page (GncPluginPage *page, } -/** Show/hide the close box on all pages in a given window. This - * function calls the gnc_main_window_update_tabs_one_page() for each - * page in the window. - * - * @internal - * - * @param window The GncMainWindow whose notebook tabs should be - * updated. - * - * @param new_value A pointer to the boolean that indicates whether - * or not the close button should be visible. - */ -static void -gnc_main_window_update_tabs_one_window (GncMainWindow *window, gboolean *new_value) -{ - GncMainWindowPrivate *priv; - - ENTER("window %p, visible %d", window, *new_value); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - g_list_foreach(priv->installed_pages, - (GFunc)gnc_main_window_update_tabs_one_page, - new_value); - LEAVE(" "); -} - - -/** Show/hide the close box on all pages in all windows. This - * function calls the gnc_main_window_update_tabs_one_window() for - * each open window in the application. +/** Show/hide the close box on all pages in all windows. This function + * calls gnc_main_window_update_tab_close() for each plugin page in the + * application. * * @internal * @@ -1503,14 +1508,76 @@ gnc_main_window_update_tabs_one_window (GncMainWindow *window, gboolean *new_val * @param user_data Unused. */ static void -gnc_main_window_update_tabs (GConfEntry *entry, gpointer user_data) +gnc_main_window_update_tab_close (GConfEntry *entry, gpointer user_data) { gboolean new_value; ENTER(" "); new_value = gconf_value_get_bool(entry->value); - g_list_foreach(active_windows, - (GFunc)gnc_main_window_update_tabs_one_window, + gnc_main_window_foreach_page( + gnc_main_window_update_tab_close_one_page, + &new_value); + LEAVE(" "); +} + + +/** Update the width of the label in the tab of a notebook page. This + * function adjusts both the width and the ellipsize mode so that the tab + * label looks correct. The special check for a zero value handles the + * case where a user hasn't set a tab width and the gconf default isn't + * detected. + * + * @internal + * + * @param page The GncPluginPage whose notebook tab should be updated. + * + * @param new_value The new width of the label in the tab. + */ +static void +gnc_main_window_update_tab_width_one_page (GncPluginPage *page, + gpointer user_data) +{ + gint *new_value = user_data; + GtkWidget *label; + + ENTER("page %p, visible %d", page, *new_value); + label = g_object_get_data(G_OBJECT (page), PLUGIN_PAGE_TAB_LABEL); + if (!label) { + LEAVE("no label"); + return; + } + + if (*new_value != 0) { + gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE); + gtk_label_set_max_width_chars(GTK_LABEL(label), *new_value); + } else { + gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE); + gtk_label_set_max_width_chars(GTK_LABEL(label), 100); + } + LEAVE(" "); +} + + +/** Update the tab label width in all pages in all windows. This function + * calls gnc_main_window_update_tab_width() for each plugin page in the + * application. + * + * @internal + * + * @param entry A pointer to the GConfEntry which describes the new + * size of the tab label width. + * + * @param user_data Unused. + */ +static void +gnc_main_window_update_tab_width (GConfEntry *entry, gpointer user_data) +{ + gint new_value; + + ENTER(" "); + new_value = gconf_value_get_float(entry->value); + gnc_main_window_foreach_page( + gnc_main_window_update_tab_width_one_page, &new_value); LEAVE(" "); } @@ -1538,8 +1605,8 @@ main_window_find_tab_items (GncMainWindow *window, children = gtk_container_get_children(GTK_CONTAINER(tab_hbox)); for (tmp = children; tmp; tmp = g_list_next(tmp)) { widget = tmp->data; - if (GTK_IS_LABEL(widget)) { - *label_p = widget; + if (GTK_IS_EVENT_BOX(widget)) { + *label_p = gtk_bin_get_child(GTK_BIN(widget)); } else if (GTK_IS_ENTRY(widget)) { *entry_p = widget; } @@ -1771,12 +1838,17 @@ gnc_main_window_class_init (GncMainWindowClass *klass) G_TYPE_OBJECT); gnc_gconf_general_register_cb (KEY_SHOW_CLOSE_BUTTON, - gnc_main_window_update_tabs, + gnc_main_window_update_tab_close, + NULL); + gnc_gconf_general_register_cb (KEY_TAB_WIDTH, + gnc_main_window_update_tab_width, NULL); gnc_hook_add_dangler(HOOK_BOOK_SAVED, (GFunc)gnc_main_window_update_all_titles, NULL); gnc_hook_add_dangler(HOOK_BOOK_OPENED, (GFunc)gnc_main_window_attach_to_book, NULL); + + tips = gtk_tooltips_new(); } @@ -2070,10 +2142,11 @@ gnc_main_window_open_page (GncMainWindow *window, { GncMainWindowPrivate *priv; GtkWidget *tab_hbox; - GtkWidget *label, *entry; - const gchar *icon; + GtkWidget *label, *entry, *event_box; + const gchar *icon, *text; GtkWidget *image; GList *tmp; + gint width; ENTER("window %p, page %p", window, page); @@ -2112,9 +2185,15 @@ gnc_main_window_open_page (GncMainWindow *window, /* * The page tab. */ + width = gnc_gconf_get_float(GCONF_GENERAL, KEY_TAB_WIDTH, NULL); icon = GNC_PLUGIN_PAGE_GET_CLASS(page)->tab_icon; label = gtk_label_new (gnc_plugin_page_get_page_name(page)); + if (width != 0) { + gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE); + gtk_label_set_max_width_chars(GTK_LABEL(label), width); + } gtk_widget_show (label); + g_object_set_data(G_OBJECT (page), PLUGIN_PAGE_TAB_LABEL, label); tab_hbox = gtk_hbox_new (FALSE, 6); gtk_widget_show (tab_hbox); @@ -2125,8 +2204,17 @@ gnc_main_window_open_page (GncMainWindow *window, gtk_box_pack_start (GTK_BOX (tab_hbox), image, FALSE, FALSE, 0); } - gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE, TRUE, 0); - + event_box = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), FALSE); + gtk_widget_show(event_box); + gtk_container_add(GTK_CONTAINER(event_box), label); + gtk_box_pack_start (GTK_BOX (tab_hbox), event_box, TRUE, TRUE, 0); + + text = gnc_plugin_page_get_page_long_name(page); + if (text) { + gtk_tooltips_set_tip(tips, event_box, text, NULL); + } + entry = gtk_entry_new(); gtk_widget_hide (entry); gtk_box_pack_start (GTK_BOX (tab_hbox), entry, TRUE, TRUE, 0); diff --git a/src/gnome-utils/gnc-main-window.h b/src/gnome-utils/gnc-main-window.h index cfd2486669..44789cd7a3 100644 --- a/src/gnome-utils/gnc-main-window.h +++ b/src/gnome-utils/gnc-main-window.h @@ -76,6 +76,7 @@ typedef struct { } GncMainWindowActionData; typedef void (*GncMainWindowFunc) (GncMainWindow *window, GncPluginPage *page); +typedef void (*GncMainWindowPageFunc) (GncPluginPage *page, gpointer user_data); /* function prototypes */ @@ -127,6 +128,17 @@ void gnc_main_window_open_page (GncMainWindow *window, void gnc_main_window_close_page (GncPluginPage *page); +/* Iterator function to walk all pages in all windows, calling the + * specified function for each page. + * + * @param entry A pointer to the function to be called. + * + * @param user_data A data pointer passed to each call of the function. + */ +void gnc_main_window_foreach_page (GncMainWindowPageFunc fn, + gpointer user_data); + + /** Retrieve a pointer to the page that is currently at the front of * the specified window. Any plugin that needs to manipulate its * menus based upon the currently selected menu page should connect diff --git a/src/gnome-utils/gnc-plugin-page.c b/src/gnome-utils/gnc-plugin-page.c index f57a2c0b1a..7789135e91 100644 --- a/src/gnome-utils/gnc-plugin-page.c +++ b/src/gnome-utils/gnc-plugin-page.c @@ -95,6 +95,7 @@ typedef struct _GncPluginPagePrivate gboolean use_new_window; gchar *page_name; + gchar *page_long_name; gchar *uri; gchar *statusbar_text; } GncPluginPagePrivate; @@ -769,6 +770,38 @@ gnc_plugin_page_set_page_name (GncPluginPage *page, const gchar *name) } +/* Retrieve the long name of this page. This is the string used in + * the tooltip that is attached to the pate name in the notebook + * tab. */ +const gchar * +gnc_plugin_page_get_page_long_name (GncPluginPage *page) +{ + GncPluginPagePrivate *priv; + + g_return_val_if_fail (GNC_IS_PLUGIN_PAGE (page), NULL); + + priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page); + return priv->page_long_name; +} + + +/* Set the long name of this page. This is the string used in the + * tooltip that is attached to the pate name in the notebook tab. */ +void +gnc_plugin_page_set_page_long_name (GncPluginPage *page, const gchar *name) +{ + GncPluginPagePrivate *priv; + GncPluginPageClass *klass; + + g_return_if_fail (GNC_IS_PLUGIN_PAGE (page)); + + priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page); + if (priv->page_long_name) + g_free(priv->page_long_name); + priv->page_long_name = g_strdup(name); +} + + /* Retrieve the Uniform Resource Identifier for this page. */ const gchar * gnc_plugin_page_get_uri (GncPluginPage *page) diff --git a/src/gnome-utils/gnc-plugin-page.h b/src/gnome-utils/gnc-plugin-page.h index c5eda12427..8f0ac9536c 100644 --- a/src/gnome-utils/gnc-plugin-page.h +++ b/src/gnome-utils/gnc-plugin-page.h @@ -350,6 +350,28 @@ const gchar *gnc_plugin_page_get_page_name (GncPluginPage *page); void gnc_plugin_page_set_page_name (GncPluginPage *page, const char *name); +/** Retrieve the long name of this page. This is the string used in + * the tooltip that is attached to the pate name in the notebook + * tab. + * + * @param page The page whose name should be retrieved. + * + * @return The page's name. This string is owned by the page and + * should not be freed by the caller. + */ +const gchar *gnc_plugin_page_get_page_long_name (GncPluginPage *page); + + +/** Set the long name of this page. This is the string used in the + * tooltip that is attached to the pate name in the notebook tab. + * + * @param page The page whose name should be set. + * + * @param name The new string for the name. + */ +void gnc_plugin_page_set_page_long_name (GncPluginPage *page, const char *name); + + /** Retrieve the Uniform Resource Identifier for this page. * * @param page The page whose URI should be retrieved. diff --git a/src/gnome/gnc-plugin-page-register.c b/src/gnome/gnc-plugin-page-register.c index b80180c76c..4802e9e6de 100644 --- a/src/gnome/gnc-plugin-page-register.c +++ b/src/gnome/gnc-plugin-page-register.c @@ -95,6 +95,7 @@ static void gnc_plugin_page_register_update_edit_menu (GncPluginPage *page, gboo static gboolean gnc_plugin_page_register_finish_pending (GncPluginPage *page); static gchar *gnc_plugin_page_register_get_tab_name (GncPluginPage *plugin_page); +static gchar *gnc_plugin_page_register_get_long_name (GncPluginPage *plugin_page); /* Callbacks for the "Sort By" dialog */ void gnc_plugin_page_register_sort_button_cb(GtkToggleButton *button, GncPluginPageRegister *page); @@ -454,6 +455,10 @@ gnc_plugin_page_register_new_common (GNCLedgerDisplay *ledger) gnc_plugin_page_set_page_name(plugin_page, label); g_free(label); + label = gnc_plugin_page_register_get_long_name(plugin_page); + gnc_plugin_page_set_page_long_name(plugin_page, label); + g_free(label); + q = gnc_ledger_display_get_query (ledger); book_list = qof_query_get_books (q); for (item = book_list; item; item = g_list_next(item)) @@ -1154,6 +1159,37 @@ gnc_plugin_page_register_get_tab_name (GncPluginPage *plugin_page) return g_strdup(_("unknown")); } +static gchar * +gnc_plugin_page_register_get_long_name (GncPluginPage *plugin_page) +{ + GncPluginPageRegisterPrivate *priv; + GNCLedgerDisplayType ledger_type; + GNCLedgerDisplay *ld; + SplitRegister *reg; + Account *leader; + + g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), _("unknown")); + + priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(plugin_page); + ld = priv->ledger; + reg = gnc_ledger_display_get_split_register (ld); + ledger_type = gnc_ledger_display_type (ld); + leader = gnc_ledger_display_leader (ld); + + switch (ledger_type) { + case LD_SINGLE: + return g_strdup(xaccAccountGetFullName (leader)); + + case LD_SUBACCOUNT: + return g_strdup_printf("%s+", xaccAccountGetFullName (leader)); + + default: + break; + } + + return NULL; +} + /************************************************************/ /* "Sort By" Dialog */ /************************************************************/ diff --git a/src/gnome/schemas/apps_gnucash_general.schemas.in b/src/gnome/schemas/apps_gnucash_general.schemas.in index 5e3d6d219c..3a120eb59b 100644 --- a/src/gnome/schemas/apps_gnucash_general.schemas.in +++ b/src/gnome/schemas/apps_gnucash_general.schemas.in @@ -184,6 +184,23 @@ + + /schemas/apps/gnucash/general/tab_width + /apps/gnucash/general/tab_width + gnucash + float + 30.0 + + Width of notebook tabs + + This key specifies the maximum width of notebook tabs. + If the text in the tab is longer than this value (the test + is approximate) then the tab label will have the middle cut + and replaced with an ellipsis. + + + + /schemas/apps/gnucash/general/currency_choice /apps/gnucash/general/currency_choice