Commit 634bc2e3280656987f4cea87736dd34329458775

Authored by Perry Werneck
1 parent 738d8997
Exists in master and in 1 other branch develop

Improving the "can't paste formatted data" popup dialog. It can be

disabled now.
src/dialogs/popups.c
... ... @@ -29,6 +29,7 @@
29 29  
30 30 #include <config.h>
31 31 #include <internals.h>
  32 + #include <terminal.h>
32 33 #include <v3270/dialogs.h>
33 34  
34 35 /*--[ Implement ]------------------------------------------------------------------------------------*/
... ... @@ -131,3 +132,79 @@
131 132 gtk_widget_show_all(dialog);
132 133  
133 134 }
  135 +
  136 + 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, ...)
  137 + {
  138 + GtkResponseType response = GTK_V3270(widget)->responses[id];
  139 +
  140 + if(response == GTK_RESPONSE_NONE)
  141 + {
  142 + GtkWidget * dialog =
  143 + gtk_message_dialog_new(
  144 + GTK_WINDOW(gtk_widget_get_toplevel(widget)),
  145 + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
  146 + GTK_MESSAGE_INFO,
  147 + GTK_BUTTONS_NONE,
  148 + summary
  149 + );
  150 +
  151 + if(body)
  152 + gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),"%s",body);
  153 +
  154 + gtk_window_set_title(GTK_WINDOW(dialog),title);
  155 +
  156 + // Set check button
  157 + GtkWidget * dont_ask = gtk_check_button_new_with_label(_("Don't ask again"));
  158 +
  159 + gtk_widget_set_valign(dont_ask, GTK_ALIGN_BASELINE);
  160 + gtk_widget_set_halign(dont_ask, GTK_ALIGN_START);
  161 +
  162 + gtk_box_pack_start(
  163 + GTK_BOX(gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog))),
  164 + dont_ask,
  165 + TRUE,
  166 + TRUE,
  167 + 0
  168 + );
  169 +
  170 + if(first_button_text)
  171 + {
  172 + // From https://github.com/GNOME/gtk/blob/master/gtk/gtkdialog.c
  173 + va_list args;
  174 + const gchar* text;
  175 + gint response_id;
  176 +
  177 + va_start(args, first_button_text);
  178 +
  179 + text = first_button_text;
  180 + while(text)
  181 + {
  182 + response_id = va_arg(args, gint);
  183 +
  184 + gtk_dialog_add_button(GTK_DIALOG(dialog), text, response_id);
  185 +
  186 + if(response_id == GTK_RESPONSE_APPLY || response_id == GTK_RESPONSE_OK || response_id == GTK_RESPONSE_YES)
  187 + gtk_dialog_set_default_response(GTK_DIALOG(dialog),response_id);
  188 +
  189 + text = va_arg(args, gchar*);
  190 + }
  191 +
  192 + va_end (args);
  193 + }
  194 +
  195 + gtk_widget_show_all(dialog);
  196 + response = gtk_dialog_run(GTK_DIALOG(dialog));
  197 +
  198 + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dont_ask)))
  199 + {
  200 + GTK_V3270(widget)->responses[id] = response;
  201 + g_object_notify_by_pspec(G_OBJECT(widget), GTK_V3270_GET_CLASS(widget)->responses[id]);
  202 + v3270_emit_save_settings(widget);
  203 + }
  204 +
  205 + gtk_widget_destroy(dialog);
  206 + }
  207 +
  208 + return response;
  209 +
  210 + }
... ...
src/include/internals.h
... ... @@ -142,13 +142,21 @@
142 142  
143 143 /*--[ Internal Widgets & Tools ]---------------------------------------------------------------------*/
144 144  
  145 + typedef enum v3270_toggleable_dialog
  146 + {
  147 + V3270_TOGGLEABLE_DIALOG_PASTE_FAILED,
  148 +
  149 + V3270_TOGGLEABLE_DIALOG_CUSTOM
  150 + } V3270_TOGGLEABLE_DIALOG;
  151 +
  152 + 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;
  153 +
145 154 #if GTK_CHECK_VERSION(3,12,0)
146 155 G_GNUC_INTERNAL GtkHeaderBar * v3270_dialog_get_header_bar(GtkWidget * widget);
147 156 #endif // ! GTK 3.12
148 157  
149 158 G_GNUC_INTERNAL void v3270_grid_attach(GtkGrid *grid, const struct v3270_entry_field * description, GtkWidget *widget);
150 159  
151   -
152 160 // Toggle button widget
153 161 #define GTK_TYPE_V3270_TOGGLE_BUTTON (V3270ToggleButton_get_type ())
154 162 #define GTK_V3270_TOGGLE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270_TOGGLE_BUTTON, V3270ToggleButton))
... ...
src/include/terminal.h
... ... @@ -36,6 +36,8 @@ G_BEGIN_DECLS
36 36 {
37 37 GtkWidgetClass parent_class;
38 38  
  39 + // Dialog boxes.
  40 +
39 41 // Internal properties.
40 42 struct {
41 43  
... ... @@ -68,6 +70,9 @@ G_BEGIN_DECLS
68 70  
69 71 } properties;
70 72  
  73 + // Predefined responses.
  74 + GParamSpec *responses[V3270_TOGGLEABLE_DIALOG_CUSTOM];
  75 +
71 76 // Cursors
72 77 GdkCursor * cursors[LIB3270_POINTER_COUNT];
73 78  
... ... @@ -115,6 +120,9 @@ G_BEGIN_DECLS
115 120 int scaled_fonts : 1; /**< Use scaled fonts */
116 121 int drawing : 1; /**< Draw widget? */
117 122  
  123 + /// @brief Action properties.
  124 + GtkResponseType responses[V3270_TOGGLEABLE_DIALOG_CUSTOM];
  125 +
118 126 GSource * timer;
119 127 GtkIMContext * input_method;
120 128 unsigned short keyflags;
... ...
src/selection/linux/paste.c
... ... @@ -107,30 +107,57 @@ static void formatted_received(GtkClipboard *clipboard, GtkSelectionData *select
107 107  
108 108 if(!v3270_set_from_data_block(terminal, selection))
109 109 {
110   - GtkWidget * dialog =
111   - gtk_message_dialog_new(
112   - GTK_WINDOW(gtk_widget_get_toplevel(widget)),
113   - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
114   - GTK_MESSAGE_INFO,
115   - GTK_BUTTONS_NONE,
116   - _("Unable to paste formatted data")
117   - );
118   -
  110 + debug("%s: Can't paste data",__FUNCTION__);
  111 + if(
  112 + v3270_popup_toggleable_dialog(
  113 + widget,
  114 + V3270_TOGGLEABLE_DIALOG_PASTE_FAILED,
  115 + _("Can't paste"),
  116 + _("Unable to paste formatted data."),
  117 + _("None of the screens in the clipboard match with the current one."),
  118 + _("_Cancel"), GTK_RESPONSE_CANCEL,
  119 + _("_Paste as text"), GTK_RESPONSE_APPLY,
  120 + NULL
  121 + ) == GTK_RESPONSE_APPLY)
  122 + {
  123 + gtk_clipboard_request_text(
  124 + clipboard,
  125 + (GtkClipboardTextReceivedFunc) text_received,
  126 + (gpointer) widget
  127 + );
  128 + }
119 129  
120   - gtk_window_set_title(GTK_WINDOW(dialog),_("Can't paste"));
  130 + /*
  131 + GtkResponseType response = GTK_V3270(terminal)->responses[V3270_TOGGLEABLE_DIALOG_PASTE_FAILED];
121 132  
122   - gtk_dialog_add_buttons(
123   - GTK_DIALOG (dialog),
124   - _("_Cancel"), GTK_RESPONSE_CANCEL,
125   - _("_Paste as text"), GTK_RESPONSE_APPLY,
126   - NULL
127   - );
  133 + if(response == GTK_RESPONSE_NONE)
  134 + {
  135 + // No predefined response, ask.
  136 + GtkWidget * dialog =
  137 + gtk_message_dialog_new(
  138 + GTK_WINDOW(gtk_widget_get_toplevel(widget)),
  139 + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
  140 + GTK_MESSAGE_INFO,
  141 + GTK_BUTTONS_NONE,
  142 + _("Unable to paste formatted data")
  143 + );
  144 +
  145 +
  146 + gtk_window_set_title(GTK_WINDOW(dialog),_("Can't paste"));
  147 +
  148 + gtk_dialog_add_buttons(
  149 + GTK_DIALOG (dialog),
  150 + _("_Cancel"), GTK_RESPONSE_CANCEL,
  151 + _("_Paste as text"), GTK_RESPONSE_APPLY,
  152 + NULL
  153 + );
128 154  
129   - gtk_dialog_set_default_response(GTK_DIALOG (dialog),GTK_RESPONSE_APPLY);
  155 + gtk_dialog_set_default_response(GTK_DIALOG (dialog),response);
130 156  
131   - gint response = gtk_dialog_run(GTK_DIALOG(dialog));
  157 + gint response = gtk_dialog_run(GTK_DIALOG(dialog));
132 158  
133   - gtk_widget_destroy(dialog);
  159 + gtk_widget_destroy(dialog);
  160 + }
134 161  
135 162 if(response == GTK_RESPONSE_APPLY)
136 163 {
... ... @@ -141,6 +168,7 @@ static void formatted_received(GtkClipboard *clipboard, GtkSelectionData *select
141 168 );
142 169 }
143 170  
  171 + */
144 172 return;
145 173  
146 174  
... ...
src/terminal/properties/init.c
... ... @@ -193,11 +193,50 @@
193 193 klass->properties.trace
194 194 );
195 195  
  196 +
196 197 //
197 198 // Create dynamic properties
  199 + //
198 200 klass->properties.count = V3270_PROPERTY_DYNAMIC;
199 201  
200 202 //
  203 + // Create action properties.
  204 + //
  205 + static const struct
  206 + {
  207 + const gchar *name; ///< @brief canonical name of the property specified.
  208 + const gchar *nick; ///< @brief nick name for the property specified.
  209 + const gchar *blurb; ///< @brief description of the property specified.
  210 + } actions[G_N_ELEMENTS(klass->responses)] =
  211 + {
  212 + {
  213 + .name = "paste_fails",
  214 + .nick = "paste_fails",
  215 + .blurb = "The action when formatted paste fails"
  216 + }
  217 +
  218 + };
  219 +
  220 + for(ix = 0; ix < G_N_ELEMENTS(klass->responses); ix++)
  221 + {
  222 + if(actions[ix].name)
  223 + {
  224 + klass->responses[ix] =
  225 + g_param_spec_enum(
  226 + actions[ix].name,
  227 + actions[ix].nick,
  228 + actions[ix].blurb,
  229 + GTK_TYPE_RESPONSE_TYPE,
  230 + GTK_RESPONSE_NONE,
  231 + (G_PARAM_READABLE|G_PARAM_WRITABLE)
  232 + );
  233 +
  234 + v3270_install_property(gobject_class, klass->properties.count++, klass->responses[ix]);
  235 + }
  236 +
  237 + }
  238 +
  239 + //
201 240 // Extract properties from LIB3270 control tables
202 241 //
203 242 // Extract toggle class.
... ...
src/terminal/widget.c
... ... @@ -483,6 +483,7 @@ static void release_activity_timer(v3270 *widget)
483 483  
484 484 static void v3270_init(v3270 *widget)
485 485 {
  486 + size_t ix;
486 487  
487 488 widget->host = lib3270_session_new(NULL);
488 489 lib3270_set_user_data(widget->host,widget);
... ... @@ -522,6 +523,9 @@ static void v3270_init(v3270 *widget)
522 523 v3270_font_info_init(&widget->font);
523 524 v3270_set_color_table(widget->color,v3270_default_colors);
524 525  
  526 + for(ix = 0; ix < G_N_ELEMENTS(widget->responses); ix++)
  527 + widget->responses[ix] = GTK_RESPONSE_NONE;
  528 +
525 529 }
526 530  
527 531 LIB3270_EXPORT GtkWidget * v3270_new(void)
... ...