Commit d7731cec4fb275291549275d0c674b284c660aa0

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

Implementing validity signal and oversize input.

src/dialogs/hostselect.c
... ... @@ -118,8 +118,8 @@
118 118  
119 119 },
120 120 {
121   - .top = 0,
122   - .left = 6,
  121 + .top = 1,
  122 + .left = 0,
123 123 .width = 2,
124 124 .height = 1,
125 125  
... ... @@ -179,6 +179,18 @@
179 179 .tooltip = N_("Port or service name (empty for \"telnet\")."),
180 180 .max_length = 6,
181 181 .width_chars = 7,
  182 + },
  183 +
  184 + {
  185 + .top = 1,
  186 + .left = 3,
  187 + .width = 2,
  188 + .height = 1,
  189 +
  190 + .label = N_( "Oversize" ),
  191 + .tooltip = N_("Makes the screen larger than the default for the chosen model number."),
  192 + .max_length = 7,
  193 + .width_chars = 8,
182 194 }
183 195 };
184 196  
... ... @@ -224,6 +236,30 @@ static void V3270HostSelectWidget_class_init(G_GNUC_UNUSED V3270HostSelectWidget
224 236  
225 237 }
226 238  
  239 +static void oversize_changed(GtkEditable *editable, GtkWidget *settings)
  240 +{
  241 + const gchar * chars = gtk_editable_get_chars(editable,0,-1);
  242 + gboolean valid = TRUE;
  243 + char junk;
  244 + unsigned int ovc = 0, ovr = 0;
  245 +
  246 + if(*chars)
  247 + {
  248 + if(sscanf(chars, "%ux%u%c", &ovc, &ovr, &junk) != 2)
  249 + {
  250 + valid = FALSE;
  251 + debug("Can't parse \"%s\"",chars);
  252 + }
  253 + else if( (ovc * ovr) > 0x4000)
  254 + {
  255 + valid = FALSE;
  256 + debug("Invalid values on \"%s\"",chars);
  257 + }
  258 + }
  259 +
  260 + v3270_settings_set_valid(settings,valid);
  261 +}
  262 +
227 263 static void V3270HostSelectWidget_init(V3270HostSelectWidget *widget)
228 264 {
229 265 // Cell renderer
... ... @@ -258,21 +294,35 @@ static void V3270HostSelectWidget_init(V3270HostSelectWidget *widget)
258 294 for(entry = 0; entry < G_N_ELEMENTS(entryfields); entry++)
259 295 {
260 296 widget->input.entry[entry] = GTK_ENTRY(gtk_entry_new());
261   -
262 297 gtk_entry_set_max_length(widget->input.entry[entry],entryfields[entry].max_length);
263 298 gtk_entry_set_width_chars(widget->input.entry[entry],entryfields[entry].width_chars);
264   -
265   - v3270_grid_attach(
266   - GTK_GRID(connection),
267   - (struct v3270_entry_field *) & entryfields[entry],
268   - GTK_WIDGET(widget->input.entry[entry])
269   - );
270   -
271 299 }
272 300  
  301 + // Custom settings
273 302 gtk_entry_set_placeholder_text(widget->input.entry[ENTRY_SRVCNAME],"telnet");
274 303 gtk_widget_set_hexpand(GTK_WIDGET(widget->input.entry[ENTRY_HOSTNAME]),TRUE);
275 304  
  305 + // Add to containers
  306 + v3270_grid_attach(
  307 + GTK_GRID(connection),
  308 + (struct v3270_entry_field *) & entryfields[0],
  309 + GTK_WIDGET(widget->input.entry[0])
  310 + );
  311 +
  312 + v3270_grid_attach(
  313 + GTK_GRID(connection),
  314 + (struct v3270_entry_field *) & entryfields[1],
  315 + GTK_WIDGET(widget->input.entry[1])
  316 + );
  317 +
  318 + v3270_grid_attach(
  319 + GTK_GRID(emulation),
  320 + (struct v3270_entry_field *) & entryfields[2],
  321 + GTK_WIDGET(widget->input.entry[2])
  322 + );
  323 +
  324 + g_signal_connect(G_OBJECT(widget->input.entry[2]),"changed",G_CALLBACK(oversize_changed),widget);
  325 +
276 326 }
277 327  
278 328 // SSL checkbox
... ... @@ -338,8 +388,8 @@ static void V3270HostSelectWidget_init(V3270HostSelectWidget *widget)
338 388  
339 389 static const struct v3270_entry_field descriptor =
340 390 {
341   - .top = 1,
342   - .left = 0,
  391 + .top = 0,
  392 + .left = 6,
343 393 .width = 2,
344 394 .height = 1,
345 395  
... ...
src/dialogs/settings/dialog.c
... ... @@ -47,6 +47,39 @@ static gboolean on_tab_focus(V3270Settings *settings, GdkEvent G_GNUC_UNUSED(*ev
47 47 return FALSE;
48 48 }
49 49  
  50 +static void check_valid(GtkWidget *widget, gboolean *valid)
  51 +{
  52 + if(*valid && GTK_IS_V3270_SETTINGS(widget))
  53 + {
  54 + if(!v3270_settings_get_valid(widget))
  55 + *valid = FALSE;
  56 + }
  57 +
  58 +}
  59 +
  60 +static void on_validity(V3270Settings G_GNUC_UNUSED(*settings), gboolean valid, V3270SettingsDialog * dialog)
  61 +{
  62 + if(valid)
  63 + {
  64 + // Check validity of all childs.
  65 + gtk_container_foreach(
  66 + GTK_CONTAINER(dialog->tabs),
  67 + (GtkCallback) check_valid,
  68 + &valid
  69 + );
  70 +
  71 + }
  72 +
  73 + debug("The current state is %s",valid ? "valid" : "invalid");
  74 +
  75 + GtkWidget * button = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
  76 +
  77 + if(button)
  78 + gtk_widget_set_sensitive(button,valid);
  79 +
  80 +
  81 +}
  82 +
50 83 static void add(GtkContainer *container, GtkWidget *widget)
51 84 {
52 85 g_return_if_fail(GTK_IS_V3270_SETTINGS(widget));
... ... @@ -73,6 +106,7 @@ static void add(GtkContainer *container, GtkWidget *widget)
73 106 );
74 107  
75 108 g_signal_connect(G_OBJECT(widget), "focus-in-event", G_CALLBACK(on_tab_focus), container);
  109 + g_signal_connect(G_OBJECT(widget), "validity", G_CALLBACK(on_validity), container);
76 110  
77 111  
78 112 }
... ... @@ -123,33 +157,9 @@ void v3270_settings_dialog_revert(GtkWidget *dialog)
123 157  
124 158 }
125 159  
126   -/*
127   -static void response(GtkDialog *dialog, gint response_id)
128   -{
129   - if(!terminal)
130   - return;
131   -
132   -
133   -}
134   -*/
135   -
136   -static void dispose(GObject *object)
137   -{
138   - debug("%s",__FUNCTION__);
139   -
140   -// V3270SettingsDialog * widget = GTK_V3270_SETTINGS_DIALOG(object);
141   -
142   -
143   - G_OBJECT_CLASS(V3270SettingsDialog_parent_class)->dispose(object);
144   -}
145   -
146 160 static void V3270SettingsDialog_class_init(V3270SettingsDialogClass *klass)
147 161 {
148 162 GTK_CONTAINER_CLASS(klass)->add = add;
149   -
150   - // Object class
151   - G_OBJECT_CLASS(klass)->dispose = dispose;
152   -
153 163 }
154 164  
155 165 static void on_page_changed(GtkNotebook *notebook, GtkWidget G_GNUC_UNUSED(*child), guint G_GNUC_UNUSED(page_num), V3270SettingsDialog G_GNUC_UNUSED(*dialog)) {
... ... @@ -220,6 +230,8 @@ void v3270_settings_dialog_set_terminal_widget(GtkWidget *widget, GtkWidget *ter
220 230 {
221 231 g_return_if_fail(GTK_IS_V3270_SETTINGS_DIALOG(widget));
222 232  
  233 + debug("%s(%p,%p)",__FUNCTION__,widget,terminal);
  234 +
223 235 GTK_V3270_SETTINGS_DIALOG(widget)->terminal = terminal;
224 236  
225 237 gtk_container_foreach(
... ...
src/dialogs/settings/widget.c
... ... @@ -28,12 +28,24 @@
28 28 */
29 29  
30 30 #include "../private.h"
  31 + #include "../terminal/marshal.h"
31 32 #include <internals.h>
32 33 #include <v3270/settings.h>
33 34 #include <lib3270/log.h>
34 35  
  36 + static void signal_update_message(GtkWidget *terminal, LIB3270_MESSAGE G_GNUC_UNUSED(id), GtkWidget *settings);
  37 +
35 38 G_DEFINE_TYPE(V3270Settings, V3270Settings, GTK_TYPE_GRID);
36 39  
  40 + enum
  41 + {
  42 + VALIDITY_SIGNAL, ///< @brief Signal for valid state.
  43 + SIGNAL_LAST
  44 + };
  45 +
  46 + static guint signals[SIGNAL_LAST] = { 0 };
  47 +
  48 +
37 49 /*--[ Implement ]------------------------------------------------------------------------------------*/
38 50  
39 51 static void apply(GtkWidget G_GNUC_UNUSED(*widget), GtkWidget G_GNUC_UNUSED(*terminal))
... ... @@ -58,23 +70,65 @@ static void update_message(GtkWidget G_GNUC_UNUSED(*widget), GtkWidget G_GNUC_UN
58 70  
59 71 static void finalize(GObject *object)
60 72 {
61   - v3270_settings_set_terminal_widget(GTK_WIDGET(object),NULL);
  73 + V3270Settings * settings = GTK_V3270_SETTINGS(object);
  74 +
  75 + if(settings->terminal)
  76 + {
  77 + // Disconnect terminal widget
  78 + //
  79 + // (Can't use v3270_settings_set_terminal_widget here)
  80 + //
  81 + gulong handler = g_signal_handler_find(
  82 + settings->terminal,
  83 + G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA,
  84 + 0,
  85 + 0,
  86 + NULL,
  87 + G_CALLBACK(signal_update_message),
  88 + object
  89 + );
  90 +
  91 + if(handler)
  92 + g_signal_handler_disconnect(settings->terminal, handler);
  93 +
  94 + settings->terminal = NULL;
  95 + }
  96 +
62 97 G_OBJECT_CLASS(V3270Settings_parent_class)->finalize(object);
63 98 }
64 99  
  100 +static void validity(GtkWidget *widget, gboolean state)
  101 +{
  102 +
  103 +}
  104 +
65 105 static void V3270Settings_class_init(V3270SettingsClass *klass)
66 106 {
  107 + GObjectClass * gobject_class = G_OBJECT_CLASS(klass);
  108 +
67 109 klass->apply = apply;
68 110 klass->revert = cancel;
69 111 klass->load = load;
  112 + klass->validity = validity;
70 113 klass->update_message = update_message;
71 114  
72   - G_OBJECT_CLASS(klass)->finalize = finalize;
  115 + gobject_class->finalize = finalize;
  116 +
  117 + signals[VALIDITY_SIGNAL] =
  118 + g_signal_new( I_("validity"),
  119 + G_OBJECT_CLASS_TYPE (gobject_class),
  120 + G_SIGNAL_RUN_FIRST,
  121 + G_STRUCT_OFFSET (V3270SettingsClass, validity),
  122 + NULL, NULL,
  123 + v3270_VOID__VOID_BOOLEAN,
  124 + G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
  125 +
73 126 }
74 127  
75 128 static void V3270Settings_init(V3270Settings *widget)
76 129 {
77   - widget->terminal = NULL;
  130 + widget->terminal = NULL;
  131 + widget->valid = FALSE;
78 132  
79 133 // https://developer.gnome.org/hig/stable/visual-layout.html.en
80 134 gtk_grid_set_row_spacing(GTK_GRID(widget),6);
... ... @@ -93,6 +147,8 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid
93 147  
94 148 V3270Settings * settings = GTK_V3270_SETTINGS(widget);
95 149  
  150 + debug("%s(%p,%p)",__FUNCTION__,widget,terminal);
  151 +
96 152 // Return if there's nothing to do.
97 153 if(settings->terminal == terminal)
98 154 return;
... ... @@ -125,12 +181,19 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid
125 181 // Connect the new widget.
126 182 g_signal_connect(G_OBJECT(terminal),I_("message_changed"), G_CALLBACK(signal_update_message), widget);
127 183  
  184 + // Set as valid before update message and load contents.
  185 + v3270_settings_set_valid(widget,TRUE);
  186 +
128 187 // Update dialog state.
129 188 GTK_V3270_SETTINGS_GET_CLASS(widget)->update_message(widget,terminal);
130 189  
131 190 // Load the dialog contents.
132 191 GTK_V3270_SETTINGS_GET_CLASS(widget)->load(widget,terminal);
133 192 }
  193 + else
  194 + {
  195 + v3270_settings_set_valid(widget,FALSE);
  196 + }
134 197  
135 198 }
136 199  
... ... @@ -144,15 +207,6 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid
144 207 {
145 208 g_return_if_fail(GTK_IS_V3270_SETTINGS(widget));
146 209 GTK_V3270_SETTINGS_GET_CLASS(widget)->apply(widget,GTK_V3270_SETTINGS(widget)->terminal);
147   -
148   - /*
149   -
150   - BUG: The signal should be sent by the dialog!
151   -
152   - V3270Settings * settings = GTK_V3270_SETTINGS(widget);
153   - if(settings && settings->terminal)
154   - v3270_emit_save_settings(settings->terminal);
155   - */
156 210 }
157 211  
158 212 LIB3270_EXPORT void v3270_settings_revert(GtkWidget *widget)
... ... @@ -178,3 +232,22 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid
178 232 g_return_val_if_fail(GTK_IS_V3270_SETTINGS(widget),NULL);
179 233 return GTK_V3270_SETTINGS(widget)->tooltip;
180 234 }
  235 +
  236 + LIB3270_EXPORT gboolean v3270_settings_get_valid(GtkWidget *widget)
  237 + {
  238 + // Non settings widget is always valid.
  239 + g_return_val_if_fail(GTK_IS_V3270_SETTINGS(widget),TRUE);
  240 + return GTK_V3270_SETTINGS(widget)->valid;
  241 + }
  242 +
  243 + LIB3270_EXPORT void v3270_settings_set_valid(GtkWidget *widget, gboolean is_valid)
  244 + {
  245 + V3270Settings * settings = GTK_V3270_SETTINGS(widget);
  246 +
  247 + if(is_valid != settings->valid)
  248 + {
  249 + settings->valid = is_valid;
  250 + g_signal_emit(widget, signals[VALIDITY_SIGNAL], 0, settings->valid);
  251 + }
  252 +
  253 + }
... ...
src/include/v3270/settings.h
... ... @@ -50,6 +50,7 @@
50 50 const gchar * label; ///< @brief Label for settings dialog.
51 51 const gchar * title; ///< @brief Title for settings dialog.
52 52 const gchar * tooltip; ///< @brief Tooltip for settings dialog.
  53 + gboolean valid; ///< @brief True if the settings can be applyed.
53 54 } V3270Settings;
54 55  
55 56 typedef struct _V3270SettingsClass {
... ... @@ -59,7 +60,7 @@
59 60 void (*apply)(GtkWidget *widget, GtkWidget *terminal); ///< @brief Method for GTK_RESPONSE_APPLY
60 61 void (*revert)(GtkWidget *widget, GtkWidget *terminal); ///< @brief Method for GTK_RESPONSE_CANCEL
61 62 void (*update_message)(GtkWidget *widget, GtkWidget *terminal); ///< @brief Lib3270 message has changed.
62   -
  63 + void (*validity)(GtkWidget *, gboolean);
63 64 } V3270SettingsClass;
64 65  
65 66 LIB3270_EXPORT GType V3270Settings_get_type(void);
... ... @@ -70,6 +71,9 @@
70 71 LIB3270_EXPORT void v3270_settings_apply(GtkWidget *widget);
71 72 LIB3270_EXPORT void v3270_settings_revert(GtkWidget *widget);
72 73  
  74 + LIB3270_EXPORT void v3270_settings_set_valid(GtkWidget *widget, gboolean is_valid);
  75 + LIB3270_EXPORT gboolean v3270_settings_get_valid(GtkWidget *widget);
  76 +
73 77 LIB3270_EXPORT const gchar * v3270_settings_get_title(GtkWidget *widget);
74 78 LIB3270_EXPORT const gchar * v3270_settings_get_label(GtkWidget *widget);
75 79 LIB3270_EXPORT const gchar * v3270_settings_get_tooltip(GtkWidget *widget);
... ... @@ -97,7 +101,6 @@
97 101  
98 102 typedef struct _V3270SettingsDialogClass {
99 103 GtkDialogClass parent_class;
100   -
101 104 } V3270SettingsDialogClass;
102 105  
103 106 LIB3270_EXPORT GType V3270SettingsDialog_get_type(void);
... ...