Skip to content

Commit 3948e1d

Browse files
committed
Merge Roberto Kok's 'tab-middle-click-close' into stable.
2 parents ad9ed45 + a2edf9d commit 3948e1d

File tree

2 files changed

+82
-23
lines changed

2 files changed

+82
-23
lines changed

gnucash/gnome-utils/gnc-main-window.cpp

+82-22
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,33 @@ gnc_main_window_update_all_titles (void)
16131613
nullptr);
16141614
}
16151615

1616+
/* Callback function invoked when the user clicks on a GtkNotebook tab.
1617+
*
1618+
* This function is needed to make it possible to close a tab
1619+
* when it's clicked using the middle mouse button;
1620+
* there does not seem to be a way to do this with GtkNotebook natively.
1621+
*
1622+
* @param widget The event box in the tab, which was clicked.
1623+
*
1624+
* @param event The event parameter describing where on the screen
1625+
* the mouse was pointing when clicked, type of click, modifiers,
1626+
* etc.
1627+
*
1628+
* @param page This is the GncPluginPage corresponding to the tab.
1629+
*
1630+
* @return Returns TRUE if this was a middle-click, meaning Gnucash
1631+
* handled the click.
1632+
*/
1633+
static gboolean
1634+
gnc_tab_clicked_cb(GtkWidget *widget, GdkEventButton *event, GncPluginPage *page) {
1635+
if (event->type == GDK_BUTTON_PRESS && event->button == 2)
1636+
{
1637+
gnc_main_window_close_page(page);
1638+
return TRUE;
1639+
}
1640+
return FALSE;
1641+
}
1642+
16161643
static void
16171644
gnc_main_window_book_dirty_cb (QofBook *book,
16181645
gboolean dirty,
@@ -2258,11 +2285,19 @@ main_window_find_tab_items (GncMainWindow *window,
22582285

22592286
tab_widget = gtk_notebook_get_tab_label(GTK_NOTEBOOK(priv->notebook),
22602287
page->notebook_page);
2261-
if (GTK_IS_EVENT_BOX (tab_widget))
2262-
tab_hbox = gtk_bin_get_child(GTK_BIN(tab_widget));
2263-
else if (GTK_IS_BOX (tab_widget))
2264-
tab_hbox = tab_widget;
2265-
else
2288+
2289+
// Walk through children to find the box containing label+entry
2290+
tab_hbox = tab_widget;
2291+
while (tab_hbox) {
2292+
if (g_strcmp0(gtk_widget_get_name(tab_hbox), "tab-content") == 0) {
2293+
break;
2294+
}
2295+
GList* _children = gtk_container_get_children(GTK_CONTAINER(tab_hbox));
2296+
tab_hbox = _children ? GTK_WIDGET(_children->data) : nullptr;
2297+
g_list_free(_children);
2298+
}
2299+
2300+
if (!GTK_IS_BOX(tab_hbox))
22662301
{
22672302
PWARN ("Unknown widget for tab label %p", tab_widget);
22682303
return FALSE;
@@ -3215,7 +3250,7 @@ gnc_main_window_open_page (GncMainWindow *window,
32153250
GncPluginPage *page)
32163251
{
32173252
GncMainWindowPrivate *priv;
3218-
GtkWidget *tab_hbox;
3253+
GtkWidget *tab_container, *tab_clickable_area;
32193254
GtkWidget *label, *entry;
32203255
const gchar *icon, *text, *color_string, *lab_text;
32213256
GtkWidget *image;
@@ -3263,6 +3298,15 @@ gnc_main_window_open_page (GncMainWindow *window,
32633298

32643299
/*
32653300
* The page tab.
3301+
* Component structure:
3302+
*
3303+
* tab_container (GtkBox)
3304+
* ├── tab_clickable_area (GtkEventBox)
3305+
* │ └── tab_content (GtkBox)
3306+
* │ ├── image (GtkImage, optional)
3307+
* │ ├── label (GtkLabel)
3308+
* │ └── entry (GtkEntry, hidden)
3309+
* └── close_button (GtkButton, if not immutable)
32663310
*/
32673311
icon = GNC_PLUGIN_PAGE_GET_CLASS(page)->tab_icon;
32683312
lab_text = gnc_plugin_page_get_page_name(page);
@@ -3275,34 +3319,46 @@ gnc_main_window_open_page (GncMainWindow *window,
32753319

32763320
gtk_widget_show (label);
32773321

3278-
tab_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
3322+
tab_container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
3323+
3324+
text = gnc_plugin_page_get_page_long_name(page);
3325+
if (text)
3326+
{
3327+
gtk_widget_set_tooltip_text(tab_container, text);
3328+
}
32793329

32803330
if (g_strcmp0 (gnc_plugin_page_get_plugin_name (page), "GncPluginPageAccountTree") == 0)
3281-
gtk_widget_set_name (GTK_WIDGET(tab_hbox), "gnc-id-account-page-tab-box");
3331+
gtk_widget_set_name (GTK_WIDGET(tab_container), "gnc-id-account-page-tab-box");
32823332

3283-
gtk_box_set_homogeneous (GTK_BOX (tab_hbox), FALSE);
3284-
gtk_widget_show (tab_hbox);
3333+
gtk_box_set_homogeneous (GTK_BOX (tab_container), FALSE);
3334+
gtk_widget_show (tab_container);
3335+
3336+
// Create a custom clickable area for the tab to support middle-clicking
3337+
tab_clickable_area = gtk_event_box_new();
3338+
gtk_widget_show(tab_clickable_area);
3339+
gtk_box_pack_start (GTK_BOX (tab_container), tab_clickable_area, TRUE, TRUE, 0);
3340+
3341+
// Create a box for the tab's content
3342+
// Give it a name so we can find it later (see main_window_find_tab_items)
3343+
GtkWidget *tab_content = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
3344+
gtk_widget_set_name(tab_content, "tab-content");
3345+
gtk_container_add(GTK_CONTAINER(tab_clickable_area), tab_content);
3346+
gtk_widget_show(tab_content);
32853347

32863348
if (icon != nullptr)
32873349
{
32883350
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU);
32893351
gtk_widget_show (image);
3290-
gtk_box_pack_start (GTK_BOX (tab_hbox), image, FALSE, FALSE, 0);
3352+
gtk_box_pack_start (GTK_BOX (tab_content), image, FALSE, FALSE, 0);
32913353
gtk_widget_set_margin_start (GTK_WIDGET(image), 5);
3292-
gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE, TRUE, 0);
3354+
gtk_box_pack_start (GTK_BOX (tab_content), label, TRUE, TRUE, 0);
32933355
}
32943356
else
3295-
gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE, TRUE, 0);
3296-
3297-
text = gnc_plugin_page_get_page_long_name(page);
3298-
if (text)
3299-
{
3300-
gtk_widget_set_tooltip_text(tab_hbox, text);
3301-
}
3357+
gtk_box_pack_start (GTK_BOX (tab_content), label, TRUE, TRUE, 0);
33023358

33033359
entry = gtk_entry_new();
33043360
gtk_widget_hide (entry);
3305-
gtk_box_pack_start (GTK_BOX (tab_hbox), entry, TRUE, TRUE, 0);
3361+
gtk_box_pack_start (GTK_BOX (tab_content), entry, TRUE, TRUE, 0);
33063362
g_signal_connect(G_OBJECT(entry), "activate",
33073363
G_CALLBACK(gnc_main_window_tab_entry_activate), page);
33083364
g_signal_connect(G_OBJECT(entry), "focus-out-event",
@@ -3334,10 +3390,14 @@ gnc_main_window_open_page (GncMainWindow *window,
33343390
else
33353391
gtk_widget_hide (close_button);
33363392

3393+
// Custom handler to close on middle-clicks
3394+
g_signal_connect(G_OBJECT(tab_clickable_area), "button-press-event",
3395+
G_CALLBACK(gnc_tab_clicked_cb), page);
3396+
33373397
g_signal_connect_swapped (G_OBJECT (close_button), "clicked",
33383398
G_CALLBACK(gnc_main_window_close_page), page);
33393399

3340-
gtk_box_pack_start (GTK_BOX (tab_hbox), close_button, FALSE, FALSE, 0);
3400+
gtk_box_pack_start (GTK_BOX (tab_container), close_button, FALSE, FALSE, 0);
33413401
gtk_widget_set_margin_end (GTK_WIDGET(close_button), 5);
33423402
g_object_set_data (G_OBJECT (page), PLUGIN_PAGE_CLOSE_BUTTON, close_button);
33433403
}
@@ -3350,7 +3410,7 @@ gnc_main_window_open_page (GncMainWindow *window,
33503410
/*
33513411
* Now install it all in the window.
33523412
*/
3353-
gnc_main_window_connect(window, page, tab_hbox, label);
3413+
gnc_main_window_connect(window, page, tab_container, label);
33543414

33553415
color_string = gnc_plugin_page_get_page_color(page);
33563416
main_window_update_page_color (page, color_string);

gnucash/gnome-utils/gnc-main-window.h

-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,6 @@ gboolean gnc_main_window_button_press_cb (GtkWidget *whatever,
410410
GdkEventButton *event,
411411
GncPluginPage *page);
412412

413-
414413
/** Callback function invoked when the user requests that Gnucash
415414
* popup the contextual menu via the keyboard context-menu request
416415
* key combination (Shift-F10 by default).

0 commit comments

Comments
 (0)