I am working on an app that uses gtk bindings for ui elements, and I cannot figure out how to so something that seems like it should be simple. I want to be able to move the information contained in a notebook page to another notebook (eg move Page 1 from notebook_1 to notebook_2).
I tried to do this with the following code snippet:
page = gtk_notebook_get_current_page(notebook_1)
child = gtk_notebook_get_nth_page(notebook_1, page)
call gtk_notebook_remove_page(notebook_1, page)
label = gtk_label_new("Test")
nb = gtk_notebook_append_page(notebook_2, child, test)
When I try to run this, I get an error in the console:
(:87313): Gtk-CRITICAL **: 19:58:29.515: gtk_notebook_append_page: assertion 'GTK_IS_WIDGET (child)' failed
And nb is -1, indicating the operation failed.
I thought that maybe the remove page was destroying the child object, so I omitted that line. But then I get the following error in the console
(:87293): Gtk-WARNING **: 19:56:50.684: Duplicate child name in GtkStack: (null)
(:87293): Gtk-CRITICAL **: 19:56:50.684: gtk_widget_set_parent: assertion '_gtk_widget_get_parent (widget) == NULL'
failed
When I run this nb is not -1, but the information in the child does not show in notebook_2.
I feel like I am missing something basic here, but I don't know what. I tried a few other things such as attaching the child to a scrolled window, and also reproduced the error using c code (instead of bindings). If anyone has any tips on how to do this or direction on how to further troubleshoot, I'd appreciate it.
Update - here is a full c app that give me the problem, that I hacked together from an old gtk2? notebook example I found on the web. When I run it and click on the move page button, it does not work. I do not really know c, so apologies if this is a mess, but it does reproduce the problem FWIW.
It seems like what I want to do isn't possible - when I remove the old page it is probably wiping the reference to the child, but when I don't remove the old page it complains that the child exists somewhere else.
#include <gtk/gtk.h>
GtkWidget *notebook_1;
GtkWidget *notebook_2;
/* move a page from notebook_1 to notebook_2 */
void move_page (GtkButton *button)
{
gint page;
GtkWidget *child;
GtkWidget *label;
GtkWidget *scroll_win;
page = gtk_notebook_get_current_page(notebook_1);
child = gtk_notebook_get_nth_page(notebook_1, page);
label = gtk_notebook_get_tab_label(notebook_1, child);
gtk_notebook_remove_page (notebook_1, page);
gtk_notebook_append_page(GTK_NOTEBOOK (notebook_2), GTK_WIDGET(child), label);
/* If I use this instead of child, no errors are thrown in the console and the
label info is transferred to notebook_2
scroll_win = gtk_scrolled_window_new();
gtk_notebook_append_page(notebook_2, scroll_win, label);
*/
gtk_widget_queue_draw(GTK_WIDGET(notebook_1));
}
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *table;
GtkWidget *frame;
GtkWidget *label;
GtkWidget *checkbutton;
int i;
char bufferf[32];
char bufferl[32];
char istr[32];
window = gtk_application_window_new (app);
gtk_window_set_default_size (GTK_WINDOW (window), 400,400);
table = gtk_grid_new();
gtk_window_set_child (window, table);
/* Create a new notebook, place the position of the tabs */
notebook_1 = gtk_notebook_new ();
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook_1), GTK_POS_TOP);
gtk_grid_attach(GTK_GRID (table), notebook_1, 0,0,6,1);
gtk_widget_show(notebook_1);
/* lets append a bunch of pages to the notebook */
for (i=0; i < 5; i++) {
sprintf(bufferf, "Append Frame %d", i+1);
sprintf(bufferl, "Page %d", i+1);
frame = gtk_frame_new (bufferf);
gtk_widget_set_margin_start(frame, 10);
gtk_widget_set_margin_end(frame, 10);
gtk_widget_set_margin_top(frame, 10);
gtk_widget_set_margin_bottom(frame, 10);
gtk_widget_set_size_request (frame, 100, 75);
gtk_widget_show (frame);
label = gtk_label_new (bufferf);
label = gtk_label_new (bufferl);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook_1), frame, label);
}
/* now lets add a page to a specific spot */
checkbutton = gtk_check_button_new_with_label ("Check me please!");
gtk_widget_set_size_request(checkbutton, 100, 75);
gtk_widget_show (checkbutton);
label = gtk_label_new ("Add spot");
label = gtk_label_new ("Add page");
gtk_notebook_insert_page (GTK_NOTEBOOK (notebook_1), checkbutton, label, 2);
/* Now finally lets prepend pages to the notebook */
for (i=0; i < 5; i++) {
sprintf(bufferf, "Prepend Frame %d", i+1);
sprintf(bufferl, "PPage %d", i+1);
frame = gtk_frame_new (bufferf);
gtk_widget_set_margin_start(frame, 10);
gtk_widget_set_margin_end(frame, 10);
gtk_widget_set_margin_top(frame, 10);
gtk_widget_set_margin_bottom(frame, 10);
gtk_widget_set_size_request (frame, 100, 75);
gtk_widget_show (frame);
label = gtk_label_new (bufferf);
label = gtk_label_new (bufferl);
gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook_1), frame, label);
}
/* Set what page to start at (page 4) */
gtk_notebook_set_current_page (GTK_NOTEBOOK(notebook_1), 3);
button = gtk_button_new_with_label ("move page");
g_signal_connect (button, "clicked",
G_CALLBACK (move_page),
NULL);
gtk_grid_attach(GTK_GRID(table), button, 6,1,1,1);
gtk_widget_show(button);
notebook_2 = gtk_notebook_new();
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook_2), GTK_POS_TOP);
gtk_grid_attach(GTK_GRID (table), notebook_2, 0,2,6,1);
gtk_widget_show(notebook_2);
gtk_notebook_set_group_name(notebook_2,"group");
for (i=0; i < 5; i++) {
sprintf(istr, "N2 %d", i);
frame = gtk_frame_new (istr);
gtk_widget_set_margin_start(frame, 10);
gtk_widget_set_margin_end(frame, 10);
gtk_widget_set_margin_top(frame, 10);
gtk_widget_set_margin_bottom(frame, 10);
gtk_widget_set_size_request (frame, 100, 75);
gtk_widget_show (frame);
label = gtk_label_new (istr);
gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook_2), frame, label);
}
gtk_notebook_popup_enable(notebook_2);
gtk_widget_show(table);
gtk_widget_show(window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
Before I come to my reply, I would like to point out once again that consistent cast seems to be a problem of the given programme!! Please check again thoroughly.
The other problem is that the function
gtk-notebook-remove-page (GTK-NOTEBOOK(notebook), page);
Also deletes the connected GtkWidget "child" or decrement the reference pointer by 1.
I solved the sample as follows:
/* move a page from notebook_1 to notebook_2 */
void move_page (GtkButton *button)
{
gint page;
GtkWidget *child;
GtkWidget *label;
GtkWidget *scroll_win;
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_1));
g_print("Current_page ist %i\n",page);
child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook_1), page);
if (GTK_IS_WIDGET(child))
g_print("child is GtkWidget %i\n",page);
else
g_print("child is not GtkWidget %i\n",page);
g_object_ref(G_OBJECT(child));
label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook_1), child);
gtk_notebook_remove_page (GTK_NOTEBOOK(notebook_1), page);
if (GTK_IS_WIDGET(child))
g_print("child is GtkWidget %i\n",page);
else
g_print("child is not GtkWidget %i\n",page);
gtk_notebook_append_page(GTK_NOTEBOOK (notebook_2), child, label);
/* If I use this instead of child, no errors are thrown in the console and the
label info is transferred to notebook_2
scroll_win = gtk_scrolled_window_new();
gtk_notebook_append_page(notebook_2, scroll_win, label);
*/
gtk_widget_queue_draw(GTK_WIDGET(notebook_1));
}
That's how it worked for me.
You can comment out g_object_ref(G_OBJECT(child));
times, you can do so, you also see how I came to it.
Have fun programming.