From: Matthias Clasen Date: Sun, 12 Dec 2021 18:13:11 +0000 (-0500) Subject: gtk-demo: Rewrite the clipboard demo X-Git-Tag: archive/raspbian/4.6.5+ds-1+rpi1~1^2~19^2~5^2~69^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=ebb58b7cbcc65206d7fb5699e411caadadb16117;p=gtk4.git gtk-demo: Rewrite the clipboard demo This is more in line with the current clipboard api, and shows handling colors and files. --- diff --git a/demos/gtk-demo/clipboard.c b/demos/gtk-demo/clipboard.c index 45556a2ed6..f7348bcdc1 100644 --- a/demos/gtk-demo/clipboard.c +++ b/demos/gtk-demo/clipboard.c @@ -1,12 +1,7 @@ /* Clipboard * * GdkClipboard is used for clipboard handling. This demo shows how to - * copy and paste text to and from the clipboard. - * - * It also shows how to transfer images via the clipboard or via - * drag-and-drop, and how to make clipboard contents persist after - * the application exits. Clipboard persistence requires a clipboard - * manager to run. + * copy and paste text, images, colors or files to and from the clipboard. */ #include @@ -14,22 +9,52 @@ #include #include "demoimage.h" -static GtkWidget *window = NULL; - static void -copy_button_clicked (GtkWidget *button, - gpointer user_data) +copy_button_clicked (GtkStack *source_stack, + gpointer user_data) { - GtkWidget *entry; GdkClipboard *clipboard; + const char *visible_child_name; + GtkWidget *visible_child; - entry = GTK_WIDGET (user_data); + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (source_stack)); - /* Get the clipboard object */ - clipboard = gtk_widget_get_clipboard (entry); + visible_child = gtk_stack_get_visible_child (source_stack); + visible_child_name = gtk_stack_get_visible_child_name (source_stack); - /* Set clipboard text */ - gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (entry))); + if (strcmp (visible_child_name, "Text") == 0) + { + gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (visible_child))); + } + else if (strcmp (visible_child_name, "Image") == 0) + { + GtkWidget *child; + + for (child = gtk_widget_get_first_child (visible_child); child; child = gtk_widget_get_next_sibling (child)) + { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (child))) + { + GtkWidget *image = gtk_widget_get_first_child (child); + gdk_clipboard_set (clipboard, GDK_TYPE_PAINTABLE, gtk_image_get_paintable (GTK_IMAGE (image))); + break; + } + } + } + else if (strcmp (visible_child_name, "Color") == 0) + { + GdkRGBA color; + + gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (visible_child), &color); + gdk_clipboard_set (clipboard, GDK_TYPE_RGBA, &color); + } + else if (strcmp (visible_child_name, "File") == 0) + { + gdk_clipboard_set (clipboard, G_TYPE_FILE, g_object_get_data (G_OBJECT (visible_child), "file"), NULL); + } + else + { + g_print ("TODO"); + } } static void @@ -37,149 +62,240 @@ paste_received (GObject *source_object, GAsyncResult *result, gpointer user_data) { + GtkStack *dest_stack = user_data; GdkClipboard *clipboard; - GtkWidget *entry; - char *text; + const GValue *value; GError *error = NULL; + GtkWidget *child; clipboard = GDK_CLIPBOARD (source_object); - entry = GTK_WIDGET (user_data); - /* Get the resulting text of the read operation */ - text = gdk_clipboard_read_text_finish (clipboard, result, &error); - - if (text) + value = gdk_clipboard_read_value_finish (clipboard, result, &error); + if (value) { - /* Set the entry text */ - gtk_editable_set_text (GTK_EDITABLE (entry), text); - g_free (text); + if (G_VALUE_HOLDS (value, G_TYPE_FILE)) + { + GFile *file; + + gtk_stack_set_visible_child_name (dest_stack, "File"); + child = gtk_stack_get_visible_child (dest_stack); + + file = g_value_get_object (value); + g_object_set (child, "label", g_file_peek_path (file), NULL); + } + else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA)) + { + GdkRGBA *color; + + gtk_stack_set_visible_child_name (dest_stack, "Color"); + child = gtk_widget_get_first_child (gtk_stack_get_visible_child (dest_stack)); + + color = g_value_get_boxed (value); + g_object_set (child, "rgba", color, NULL); + } + else if (G_VALUE_HOLDS (value, GDK_TYPE_PAINTABLE)) + { + GdkPaintable *paintable; + + gtk_stack_set_visible_child_name (dest_stack, "Image"); + child = gtk_stack_get_visible_child (dest_stack); + + paintable = g_value_get_object (value); + g_object_set (child, "paintable", paintable, NULL); + } + else if (G_VALUE_HOLDS (value, G_TYPE_STRING)) + { + gtk_stack_set_visible_child_name (dest_stack, "Text"); + child = gtk_stack_get_visible_child (dest_stack); + + gtk_label_set_label (GTK_LABEL (child), g_value_get_string (value)); + } } else { - GtkWidget *dialog; - - /* Show an error about why pasting failed. - * Usually you probably want to ignore such failures, - * but for demonstration purposes, we show the error. - */ - dialog = gtk_message_dialog_new (GTK_WINDOW (window), - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Could not paste text: %s", - error->message); - g_signal_connect (dialog, "response", - G_CALLBACK (gtk_window_destroy), NULL); - gtk_widget_show (dialog); - + g_print ("%s\n", error->message); g_error_free (error); } } static void -paste_button_clicked (GtkWidget *button, - gpointer user_data) +paste_button_clicked (GtkStack *dest_stack, + gpointer user_data) { - GtkWidget *entry; GdkClipboard *clipboard; + GdkContentFormats *formats; + + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (dest_stack)); + formats = gdk_clipboard_get_formats (clipboard); + + if (gdk_content_formats_contain_gtype (formats, G_TYPE_FILE)) + gdk_clipboard_read_value_async (clipboard, G_TYPE_FILE, 0, NULL, paste_received, dest_stack); + else if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_RGBA)) + gdk_clipboard_read_value_async (clipboard, GDK_TYPE_RGBA, 0, NULL, paste_received, dest_stack); + else if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_PAINTABLE)) + gdk_clipboard_read_value_async (clipboard, GDK_TYPE_PAINTABLE, 0, NULL, paste_received, dest_stack); + else if (gdk_content_formats_contain_gtype (formats, G_TYPE_STRING)) + gdk_clipboard_read_value_async (clipboard, G_TYPE_STRING, 0, NULL, paste_received, dest_stack); +} + +static void +update_copy_button_sensitivity (GtkWidget *source_stack) +{ + GtkButton *copy_button; + const char *visible_child_name; + GtkWidget *visible_child; + gboolean sensitive; + + copy_button = GTK_BUTTON (g_object_get_data (G_OBJECT (source_stack), "copy-button")); - entry = GTK_WIDGET (user_data); + visible_child = gtk_stack_get_visible_child (GTK_STACK (source_stack)); + visible_child_name = gtk_stack_get_visible_child_name (GTK_STACK (source_stack)); + if (strcmp (visible_child_name, "Text") == 0) + { + sensitive = strlen (gtk_editable_get_text (GTK_EDITABLE (visible_child))) > 0; + } + else if (strcmp (visible_child_name, "Color") == 0 || + strcmp (visible_child_name, "Image") == 0) + { + sensitive = TRUE; + } + else if (strcmp (visible_child_name, "File") == 0) + { + sensitive = g_object_get_data (G_OBJECT (visible_child), "file") != NULL; + } + else + { + sensitive = FALSE; + } - /* Get the clipboard object */ - clipboard = gtk_widget_get_clipboard (entry); + gtk_widget_set_sensitive (GTK_WIDGET (copy_button), sensitive); +} - /* Request the contents of the clipboard, contents_received will be - called when we do get the contents. - */ - gdk_clipboard_read_text_async (clipboard, NULL, paste_received, entry); +static void +source_changed_cb (GtkButton *copy_button, + GParamSpec *pspec, + GtkWidget *source_stack) +{ + update_copy_button_sensitivity (source_stack); +} + +static void +text_changed_cb (GtkButton *copy_button, + GParamSpec *pspec, + GtkWidget *entry) +{ + update_copy_button_sensitivity (gtk_widget_get_ancestor (entry, GTK_TYPE_STACK)); +} + +static void +file_button_set_file (GtkButton *button, + GFile *file) +{ + gtk_label_set_label (GTK_LABEL (gtk_button_get_child (button)), g_file_peek_path (file)); + g_object_set_data_full (G_OBJECT (button), "file", g_object_ref (file), g_object_unref); +} + +static void +file_chooser_response (GtkNativeDialog *dialog, + int response, + GtkButton *button) +{ + gtk_native_dialog_hide (dialog); + + if (response == GTK_RESPONSE_ACCEPT) + { + GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); + file_button_set_file (button, file); + g_object_unref (file); + + update_copy_button_sensitivity (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_STACK)); + } + + gtk_native_dialog_destroy (dialog); +} + +static void +open_file_cb (GtkWidget *button) +{ + GtkFileChooserNative *chooser; + + chooser = gtk_file_chooser_native_new ("Choose a file", + GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)), + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Open", + "_Cancel"); + + g_signal_connect (chooser, "response", G_CALLBACK (file_chooser_response), button); + gtk_native_dialog_show (GTK_NATIVE_DIALOG (chooser)); +} + +static void +update_paste_button_sensitivity (GdkClipboard *clipboard, + GtkWidget *paste_button) +{ + GdkContentFormats *formats; + gboolean sensitive = FALSE; + + formats = gdk_clipboard_get_formats (clipboard); + + if (gdk_content_formats_contain_gtype (formats, G_TYPE_FILE) || + gdk_content_formats_contain_gtype (formats, GDK_TYPE_RGBA) || + gdk_content_formats_contain_gtype (formats, GDK_TYPE_PAINTABLE) || + gdk_content_formats_contain_gtype (formats, G_TYPE_STRING)) + sensitive = TRUE; + + gtk_widget_set_sensitive (paste_button, sensitive); +} + +static void +unset_clipboard_handler (gpointer data) +{ + GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data)); + + g_signal_handlers_disconnect_by_func (clipboard, update_paste_button_sensitivity, data); } GtkWidget * do_clipboard (GtkWidget *do_widget) { + static GtkWidget *window = NULL; + if (!window) { - GtkWidget *vbox, *hbox; - GtkWidget *label; - GtkWidget *entry, *button; - GtkWidget *image; - - window = gtk_window_new (); - gtk_window_set_display (GTK_WINDOW (window), - gtk_widget_get_display (do_widget)); - gtk_window_set_title (GTK_WINDOW (window), "Clipboard"); + GtkBuilderScope *scope; + GtkBuilder *builder; + GObject *copy_button; + GObject *source_stack; + GtkWidget *paste_button; + + scope = gtk_builder_cscope_new (); + gtk_builder_cscope_add_callback_symbols (GTK_BUILDER_CSCOPE (scope), + "copy_button_clicked", G_CALLBACK (copy_button_clicked), + "paste_button_clicked", G_CALLBACK (paste_button_clicked), + "source_changed_cb", G_CALLBACK (source_changed_cb), + "text_changed_cb", G_CALLBACK (text_changed_cb), + "open_file_cb", G_CALLBACK (open_file_cb), + NULL); + + builder = gtk_builder_new (); + gtk_builder_set_scope (builder, scope); + gtk_builder_add_from_resource (builder, "/clipboard/clipboard.ui", NULL); + + window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); + gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); + + copy_button = gtk_builder_get_object (builder, "copy_button"); + source_stack = gtk_builder_get_object (builder, "source_stack"); + g_object_set_data (source_stack, "copy-button", copy_button); + + paste_button = GTK_WIDGET (gtk_builder_get_object (builder, "paste_button")); + g_signal_connect (gtk_widget_get_clipboard (paste_button), "changed", + G_CALLBACK (update_paste_button_sensitivity), paste_button); + g_object_set_data_full (G_OBJECT (paste_button), "clipboard-handler", paste_button, unset_clipboard_handler); - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_widget_set_margin_start (vbox, 8); - gtk_widget_set_margin_end (vbox, 8); - gtk_widget_set_margin_top (vbox, 8); - gtk_widget_set_margin_bottom (vbox, 8); - - gtk_window_set_child (GTK_WINDOW (window), vbox); - - label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard"); - - gtk_box_append (GTK_BOX (vbox), label); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - gtk_widget_set_margin_start (hbox, 8); - gtk_widget_set_margin_end (hbox, 8); - gtk_widget_set_margin_top (hbox, 8); - gtk_widget_set_margin_bottom (hbox, 8); - gtk_box_append (GTK_BOX (vbox), hbox); - - /* Create the first entry */ - entry = gtk_entry_new (); - gtk_box_append (GTK_BOX (hbox), entry); - - /* Create the button */ - button = gtk_button_new_with_mnemonic (_("_Copy")); - gtk_box_append (GTK_BOX (hbox), button); - g_signal_connect (button, "clicked", - G_CALLBACK (copy_button_clicked), entry); - - label = gtk_label_new ("\"Paste\" will paste the text from the clipboard to the entry"); - gtk_box_append (GTK_BOX (vbox), label); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - gtk_widget_set_margin_start (hbox, 8); - gtk_widget_set_margin_end (hbox, 8); - gtk_widget_set_margin_top (hbox, 8); - gtk_widget_set_margin_bottom (hbox, 8); - gtk_box_append (GTK_BOX (vbox), hbox); - - /* Create the second entry */ - entry = gtk_entry_new (); - gtk_box_append (GTK_BOX (hbox), entry); - - /* Create the button */ - button = gtk_button_new_with_mnemonic (_("_Paste")); - gtk_box_append (GTK_BOX (hbox), button); - g_signal_connect (button, "clicked", - G_CALLBACK (paste_button_clicked), entry); - - label = gtk_label_new ("Images can be transferred via the clipboard, too"); - gtk_box_append (GTK_BOX (vbox), label); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - gtk_widget_set_margin_start (hbox, 8); - gtk_widget_set_margin_end (hbox, 8); - gtk_widget_set_margin_top (hbox, 8); - gtk_widget_set_margin_bottom (hbox, 8); - gtk_box_append (GTK_BOX (vbox), hbox); - - /* Create the first image */ - image = demo_image_new ("dialog-warning"); - gtk_box_append (GTK_BOX (hbox), image); - - /* Create the second image */ - image = demo_image_new ("process-stop"); - gtk_box_append (GTK_BOX (hbox), image); - - /* Create the third image */ - image = demo_image_new ("weather-clear"); - gtk_box_append (GTK_BOX (hbox), image); + g_object_unref (builder); + g_object_unref (scope); } if (!gtk_widget_get_visible (window)) diff --git a/demos/gtk-demo/clipboard.ui b/demos/gtk-demo/clipboard.ui new file mode 100644 index 0000000000..08fa51e9f8 --- /dev/null +++ b/demos/gtk-demo/clipboard.ui @@ -0,0 +1,255 @@ + + + + + 1 + Clipboard + + + vertical + 12 + 12 + 12 + 12 + 12 + + + “Copy” will copy the selected data the clipboard, “Paste” will present the current clipboard contents + 1 + 40 + + + + + 12 + + + center + + + + Text + Color + Image + File + + + + + + + + + 1 + + + + source_chooser + + + + + + Text + + + center + + Copy this! + + + + + + + Color + + + center + purple + + + + + + + Image + + + center + + + + 1 + + + + resource:///transparent/portland-rose.jpg + + + + + + + image_rose + + + + resource:///images/floppybuddy.gif + + + + + + + + + + + + + + File + + + center + + + — + 0 + start + + + + + + + + + + + + center + _Copy + + 1 + + + + + + + + + + + 12 + + + _Paste + + 1 + + + + + 0 + + + dest_stack + + + + + + + end + + + + + + + + + + + + Text + + + end + 0 + end + + + + + + + Image + + + end + + + + + + + + Color + + + end + + + img + 0 + 0 + 0 + + + + + + + + + File + + + end + 0 + 1 + start + + + + + + + + + + + + diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml index 83e798fd25..f1caed2b8d 100644 --- a/demos/gtk-demo/demo.gresource.xml +++ b/demos/gtk-demo/demo.gresource.xml @@ -15,6 +15,7 @@ demo.ui + clipboard.ui demoimage.c demoimage.h