From 634bc2e3280656987f4cea87736dd34329458775 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Fri, 22 Nov 2019 12:15:57 -0300 Subject: [PATCH] Improving the "can't paste formatted data" popup dialog. It can be disabled now. --- src/dialogs/popups.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/include/internals.h | 10 +++++++++- src/include/terminal.h | 8 ++++++++ src/selection/linux/paste.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++------------------- src/terminal/properties/init.c | 39 +++++++++++++++++++++++++++++++++++++++ src/terminal/widget.c | 4 ++++ 6 files changed, 184 insertions(+), 20 deletions(-) diff --git a/src/dialogs/popups.c b/src/dialogs/popups.c index be14564..a0ec165 100644 --- a/src/dialogs/popups.c +++ b/src/dialogs/popups.c @@ -29,6 +29,7 @@ #include #include + #include #include /*--[ Implement ]------------------------------------------------------------------------------------*/ @@ -131,3 +132,79 @@ gtk_widget_show_all(dialog); } + + GtkResponseType v3270_popup_toggleable_dialog(GtkWidget *widget, V3270_TOGGLEABLE_DIALOG id, const gchar *title, const gchar *summary, const gchar *body, const gchar *first_button_text, ...) + { + GtkResponseType response = GTK_V3270(widget)->responses[id]; + + if(response == GTK_RESPONSE_NONE) + { + GtkWidget * dialog = + gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_toplevel(widget)), + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_NONE, + summary + ); + + if(body) + gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),"%s",body); + + gtk_window_set_title(GTK_WINDOW(dialog),title); + + // Set check button + GtkWidget * dont_ask = gtk_check_button_new_with_label(_("Don't ask again")); + + gtk_widget_set_valign(dont_ask, GTK_ALIGN_BASELINE); + gtk_widget_set_halign(dont_ask, GTK_ALIGN_START); + + gtk_box_pack_start( + GTK_BOX(gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog))), + dont_ask, + TRUE, + TRUE, + 0 + ); + + if(first_button_text) + { + // From https://github.com/GNOME/gtk/blob/master/gtk/gtkdialog.c + va_list args; + const gchar* text; + gint response_id; + + va_start(args, first_button_text); + + text = first_button_text; + while(text) + { + response_id = va_arg(args, gint); + + gtk_dialog_add_button(GTK_DIALOG(dialog), text, response_id); + + if(response_id == GTK_RESPONSE_APPLY || response_id == GTK_RESPONSE_OK || response_id == GTK_RESPONSE_YES) + gtk_dialog_set_default_response(GTK_DIALOG(dialog),response_id); + + text = va_arg(args, gchar*); + } + + va_end (args); + } + + gtk_widget_show_all(dialog); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dont_ask))) + { + GTK_V3270(widget)->responses[id] = response; + g_object_notify_by_pspec(G_OBJECT(widget), GTK_V3270_GET_CLASS(widget)->responses[id]); + v3270_emit_save_settings(widget); + } + + gtk_widget_destroy(dialog); + } + + return response; + + } diff --git a/src/include/internals.h b/src/include/internals.h index 429995c..f3578b7 100644 --- a/src/include/internals.h +++ b/src/include/internals.h @@ -142,13 +142,21 @@ /*--[ Internal Widgets & Tools ]---------------------------------------------------------------------*/ + typedef enum v3270_toggleable_dialog + { + V3270_TOGGLEABLE_DIALOG_PASTE_FAILED, + + V3270_TOGGLEABLE_DIALOG_CUSTOM + } V3270_TOGGLEABLE_DIALOG; + + G_GNUC_INTERNAL GtkResponseType v3270_popup_toggleable_dialog(GtkWidget *widget, V3270_TOGGLEABLE_DIALOG id, const gchar *title, const gchar *summary, const gchar *body, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED; + #if GTK_CHECK_VERSION(3,12,0) G_GNUC_INTERNAL GtkHeaderBar * v3270_dialog_get_header_bar(GtkWidget * widget); #endif // ! GTK 3.12 G_GNUC_INTERNAL void v3270_grid_attach(GtkGrid *grid, const struct v3270_entry_field * description, GtkWidget *widget); - // Toggle button widget #define GTK_TYPE_V3270_TOGGLE_BUTTON (V3270ToggleButton_get_type ()) #define GTK_V3270_TOGGLE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270_TOGGLE_BUTTON, V3270ToggleButton)) diff --git a/src/include/terminal.h b/src/include/terminal.h index 976e928..3d7f2c8 100644 --- a/src/include/terminal.h +++ b/src/include/terminal.h @@ -36,6 +36,8 @@ G_BEGIN_DECLS { GtkWidgetClass parent_class; + // Dialog boxes. + // Internal properties. struct { @@ -68,6 +70,9 @@ G_BEGIN_DECLS } properties; + // Predefined responses. + GParamSpec *responses[V3270_TOGGLEABLE_DIALOG_CUSTOM]; + // Cursors GdkCursor * cursors[LIB3270_POINTER_COUNT]; @@ -115,6 +120,9 @@ G_BEGIN_DECLS int scaled_fonts : 1; /**< Use scaled fonts */ int drawing : 1; /**< Draw widget? */ + /// @brief Action properties. + GtkResponseType responses[V3270_TOGGLEABLE_DIALOG_CUSTOM]; + GSource * timer; GtkIMContext * input_method; unsigned short keyflags; diff --git a/src/selection/linux/paste.c b/src/selection/linux/paste.c index 2fb3d03..8f5bc4f 100644 --- a/src/selection/linux/paste.c +++ b/src/selection/linux/paste.c @@ -107,30 +107,57 @@ static void formatted_received(GtkClipboard *clipboard, GtkSelectionData *select if(!v3270_set_from_data_block(terminal, selection)) { - GtkWidget * dialog = - gtk_message_dialog_new( - GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_NONE, - _("Unable to paste formatted data") - ); - + debug("%s: Can't paste data",__FUNCTION__); + if( + v3270_popup_toggleable_dialog( + widget, + V3270_TOGGLEABLE_DIALOG_PASTE_FAILED, + _("Can't paste"), + _("Unable to paste formatted data."), + _("None of the screens in the clipboard match with the current one."), + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Paste as text"), GTK_RESPONSE_APPLY, + NULL + ) == GTK_RESPONSE_APPLY) + { + gtk_clipboard_request_text( + clipboard, + (GtkClipboardTextReceivedFunc) text_received, + (gpointer) widget + ); + } - gtk_window_set_title(GTK_WINDOW(dialog),_("Can't paste")); + /* + GtkResponseType response = GTK_V3270(terminal)->responses[V3270_TOGGLEABLE_DIALOG_PASTE_FAILED]; - gtk_dialog_add_buttons( - GTK_DIALOG (dialog), - _("_Cancel"), GTK_RESPONSE_CANCEL, - _("_Paste as text"), GTK_RESPONSE_APPLY, - NULL - ); + if(response == GTK_RESPONSE_NONE) + { + // No predefined response, ask. + GtkWidget * dialog = + gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_toplevel(widget)), + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_NONE, + _("Unable to paste formatted data") + ); + + + gtk_window_set_title(GTK_WINDOW(dialog),_("Can't paste")); + + gtk_dialog_add_buttons( + GTK_DIALOG (dialog), + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Paste as text"), GTK_RESPONSE_APPLY, + NULL + ); - gtk_dialog_set_default_response(GTK_DIALOG (dialog),GTK_RESPONSE_APPLY); + gtk_dialog_set_default_response(GTK_DIALOG (dialog),response); - gint response = gtk_dialog_run(GTK_DIALOG(dialog)); + gint response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + gtk_widget_destroy(dialog); + } if(response == GTK_RESPONSE_APPLY) { @@ -141,6 +168,7 @@ static void formatted_received(GtkClipboard *clipboard, GtkSelectionData *select ); } + */ return; diff --git a/src/terminal/properties/init.c b/src/terminal/properties/init.c index d425692..e94c488 100644 --- a/src/terminal/properties/init.c +++ b/src/terminal/properties/init.c @@ -193,11 +193,50 @@ klass->properties.trace ); + // // Create dynamic properties + // klass->properties.count = V3270_PROPERTY_DYNAMIC; // + // Create action properties. + // + static const struct + { + const gchar *name; ///< @brief canonical name of the property specified. + const gchar *nick; ///< @brief nick name for the property specified. + const gchar *blurb; ///< @brief description of the property specified. + } actions[G_N_ELEMENTS(klass->responses)] = + { + { + .name = "paste_fails", + .nick = "paste_fails", + .blurb = "The action when formatted paste fails" + } + + }; + + for(ix = 0; ix < G_N_ELEMENTS(klass->responses); ix++) + { + if(actions[ix].name) + { + klass->responses[ix] = + g_param_spec_enum( + actions[ix].name, + actions[ix].nick, + actions[ix].blurb, + GTK_TYPE_RESPONSE_TYPE, + GTK_RESPONSE_NONE, + (G_PARAM_READABLE|G_PARAM_WRITABLE) + ); + + v3270_install_property(gobject_class, klass->properties.count++, klass->responses[ix]); + } + + } + + // // Extract properties from LIB3270 control tables // // Extract toggle class. diff --git a/src/terminal/widget.c b/src/terminal/widget.c index cb97c11..3d9b3d9 100644 --- a/src/terminal/widget.c +++ b/src/terminal/widget.c @@ -483,6 +483,7 @@ static void release_activity_timer(v3270 *widget) static void v3270_init(v3270 *widget) { + size_t ix; widget->host = lib3270_session_new(NULL); lib3270_set_user_data(widget->host,widget); @@ -522,6 +523,9 @@ static void v3270_init(v3270 *widget) v3270_font_info_init(&widget->font); v3270_set_color_table(widget->color,v3270_default_colors); + for(ix = 0; ix < G_N_ELEMENTS(widget->responses); ix++) + widget->responses[ix] = GTK_RESPONSE_NONE; + } LIB3270_EXPORT GtkWidget * v3270_new(void) -- libgit2 0.21.2