Commit 9767f7f9f81acfee3cd1f5a9dcade478512b1fb1

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

Checking for duplicate accelerators.

src/dialogs/settings/accelerator.c
... ... @@ -30,6 +30,10 @@
30 30 /**
31 31 * @brief Implements the accelerator settings widget.
32 32 *
  33 + * References:
  34 + *
  35 + * <https://github.com/Apress/foundations-of-gtk-dev/blob/master/chapter_8/accelerators.c>
  36 + *
33 37 */
34 38  
35 39 #include <internals.h>
... ... @@ -38,6 +42,7 @@
38 42 #include <lib3270/log.h>
39 43 #include <v3270/actions.h>
40 44 #include <terminal.h>
  45 + #include <gdk/gdkkeysyms-compat.h>
41 46  
42 47 /*--[ Widget Definition ]----------------------------------------------------------------------------*/
43 48  
... ... @@ -69,6 +74,9 @@
69 74 static void load(GtkWidget *w, GtkWidget *terminal);
70 75 static void apply(GtkWidget *w, GtkWidget *terminal);
71 76  
  77 + static void accel_edited(GtkCellRendererAccel*, gchar*, guint, GdkModifierType, guint, V3270AcceleratorSettings*);
  78 + static void alternative_edited(GtkCellRendererAccel*, gchar*, guint, GdkModifierType, guint, V3270AcceleratorSettings*);
  79 +
72 80 /*--[ Implement ]------------------------------------------------------------------------------------*/
73 81  
74 82 static void V3270AcceleratorSettings_class_init(V3270AcceleratorSettingsClass *klass)
... ... @@ -95,13 +103,23 @@
95 103 // Create Accelerator list
96 104 GtkCellRenderer * text_renderer = gtk_cell_renderer_text_new();
97 105  
98   - GtkCellRenderer * accel_renderer = gtk_cell_renderer_accel_new();
  106 + GtkCellRenderer * accel_renderer[] = { gtk_cell_renderer_accel_new(), gtk_cell_renderer_accel_new() };
  107 +
  108 + g_object_set(
  109 + accel_renderer[0],
  110 + "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
  111 + "editable", TRUE,
  112 + NULL);
  113 +
99 114 g_object_set(
100   - accel_renderer,
  115 + accel_renderer[1],
101 116 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
102 117 "editable", TRUE,
103 118 NULL);
104 119  
  120 + g_signal_connect (G_OBJECT (accel_renderer[0]), "accel_edited", G_CALLBACK (accel_edited), widget);
  121 + g_signal_connect (G_OBJECT (accel_renderer[1]), "accel_edited", G_CALLBACK (alternative_edited), widget);
  122 +
105 123 widget->store = GTK_LIST_STORE(gtk_list_store_new(COLUMNS, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_INT, G_TYPE_UINT, G_TYPE_INT, G_TYPE_UINT));
106 124  
107 125 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(widget->store),1,GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID);
... ... @@ -124,7 +142,7 @@
124 142 GTK_TREE_VIEW(view),
125 143 -1,
126 144 _("Accelerator"),
127   - accel_renderer,
  145 + accel_renderer[0],
128 146 "accel-mods", MAIN_MASK,
129 147 "accel-key", MAIN_VALUE,
130 148 NULL
... ... @@ -134,7 +152,7 @@
134 152 GTK_TREE_VIEW(view),
135 153 -1,
136 154 _("Alternative"),
137   - accel_renderer,
  155 + accel_renderer[1],
138 156 "accel-mods", ALTERNATIVE_MASK,
139 157 "accel-key", ALTERNATIVE_VALUE,
140 158 NULL
... ... @@ -155,7 +173,8 @@
155 173 gtk_grid_attach(GTK_GRID(widget),box,0,0,4,4);
156 174 }
157 175  
158   - }
  176 +}
  177 +
159 178  
160 179 LIB3270_EXPORT GtkWidget * v3270_accelerator_settings_new()
161 180 {
... ... @@ -167,6 +186,163 @@ LIB3270_EXPORT GtkWidget * v3270_accelerator_settings_new()
167 186 return GTK_WIDGET(settings);
168 187 }
169 188  
  189 +struct AccelEditInfo
  190 +{
  191 + GtkWidget * widget;
  192 + gint response;
  193 + V3270Accelerator * origin;
  194 + V3270Accelerator * accel;
  195 + GtkTreePath *path;
  196 + guint accel_key;
  197 + GdkModifierType mask;
  198 + int id_key;
  199 + int id_mask;
  200 +};
  201 +
  202 +static gboolean check_accel(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, struct AccelEditInfo * info)
  203 +{
  204 + static const gint columns[] = { MAIN_MASK, MAIN_VALUE, ALTERNATIVE_MASK, ALTERNATIVE_VALUE };
  205 + size_t ix;
  206 + GValue value;
  207 +
  208 + debug("%s",__FUNCTION__);
  209 +
  210 + for(ix = 0; ix < 2; ix++)
  211 + {
  212 + guint key;
  213 + GdkModifierType mask;
  214 +
  215 + memset(&value,0,sizeof(value));
  216 + gtk_tree_model_get_value(model, iter, columns[(ix * 2)], &value);
  217 + mask = (GdkModifierType) g_value_get_int(&value);
  218 + g_value_unset(&value);
  219 +
  220 + memset(&value,0,sizeof(value));
  221 + gtk_tree_model_get_value(model, iter, columns[(ix * 2)+1], &value);
  222 + key = g_value_get_uint(&value);
  223 + g_value_unset(&value);
  224 +
  225 + if(key == info->accel_key && mask == info->mask) {
  226 +
  227 + debug("************ Index %d cmp=%d",(unsigned int) ix, gtk_tree_path_compare(path, info->path));
  228 + GtkWidget * dialog;
  229 +
  230 + if(gtk_tree_path_compare(path, info->path))
  231 + {
  232 + // Another entry, rejects.
  233 + memset(&value,0,sizeof(value));
  234 + gtk_tree_model_get_value(model, iter, ACTION, &value);
  235 + info->accel = (V3270Accelerator *) g_value_get_pointer(&value);
  236 + g_value_unset(&value);
  237 +
  238 + debug("Key is already set on accel %s",v3270_accelerator_get_name(info->accel));
  239 +
  240 + // Ask for what the user wants to do.
  241 + dialog = gtk_message_dialog_new_with_markup(
  242 + GTK_WINDOW(gtk_widget_get_toplevel(info->widget)),
  243 + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
  244 + GTK_MESSAGE_QUESTION,
  245 + GTK_BUTTONS_YES_NO,
  246 + _( "The selected accelerator is in use by action <b>%s</b> (<b>%s</b>)" ),
  247 + v3270_accelerator_get_description(info->accel),
  248 + v3270_accelerator_get_name(info->accel)
  249 + );
  250 +
  251 + gtk_message_dialog_format_secondary_markup(
  252 + GTK_MESSAGE_DIALOG(dialog),
  253 + _( "Assign it to action (<b>%s</b>)?"),
  254 + v3270_accelerator_get_name(info->origin)
  255 + );
  256 +
  257 + }
  258 + else
  259 + {
  260 + // It's on the same entry.
  261 + dialog = gtk_message_dialog_new_with_markup(
  262 + GTK_WINDOW(gtk_widget_get_toplevel(info->widget)),
  263 + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
  264 + GTK_MESSAGE_QUESTION,
  265 + GTK_BUTTONS_CANCEL,
  266 + _( "The selected accelerator is in use by the same action" )
  267 + );
  268 +
  269 + }
  270 +
  271 + gtk_window_set_title(GTK_WINDOW(dialog),_("Accelerator is in use"));
  272 + gtk_widget_show_all(dialog);
  273 +
  274 + info->response = gtk_dialog_run(GTK_DIALOG(dialog));
  275 + if(info->response == GTK_RESPONSE_YES)
  276 + {
  277 + debug("%s: Removing accelerator from the other action",__FUNCTION__);
  278 +
  279 + }
  280 +
  281 + gtk_widget_destroy(dialog);
  282 +
  283 + return TRUE;
  284 +
  285 + }
  286 +
  287 + }
  288 +
  289 + return FALSE;
  290 +
  291 +}
  292 +
  293 +static void change_accel(V3270AcceleratorSettings *widget, gchar *path, guint accel_key, GdkModifierType mask, int id_key, int id_mask)
  294 +{
  295 + struct AccelEditInfo info = {
  296 + .response = GTK_RESPONSE_YES,
  297 + .widget = GTK_WIDGET(widget),
  298 + .accel = NULL,
  299 + .accel_key = accel_key,
  300 + .mask = mask,
  301 + .id_key = id_key,
  302 + .id_mask = id_mask,
  303 + .path = gtk_tree_path_new_from_string(path)
  304 + };
  305 +
  306 + GtkTreeIter iter;
  307 + if(gtk_tree_model_get_iter(GTK_TREE_MODEL(widget->store),&iter,info.path))
  308 + {
  309 + GValue value;
  310 + memset(&value,0,sizeof(value));
  311 + gtk_tree_model_get_value(GTK_TREE_MODEL(widget->store), &iter, ACTION, &value);
  312 + info.origin = (V3270Accelerator *) g_value_get_pointer(&value);
  313 + g_value_unset(&value);
  314 +
  315 + if(!info.origin)
  316 + {
  317 + g_warning("Can't identify the origin accelerator, aborting action");
  318 + return;
  319 + }
  320 +
  321 + }
  322 +
  323 + gtk_tree_model_foreach(GTK_TREE_MODEL(widget->store), (GtkTreeModelForeachFunc) check_accel, &info);
  324 +
  325 + gtk_tree_path_free(info.path);
  326 +
  327 + if(info.response == GTK_RESPONSE_YES)
  328 + {
  329 + debug("%s: Aplicar alteração",__FUNCTION__);
  330 +
  331 + }
  332 +
  333 +}
  334 +
  335 +static void accel_edited(GtkCellRendererAccel *renderer, gchar *path, guint accel_key, GdkModifierType mask, guint hardware_keycode, V3270AcceleratorSettings *widget)
  336 +{
  337 + debug("%s(%s)",__FUNCTION__,path);
  338 + change_accel(widget, path, accel_key, mask, MAIN_MASK, MAIN_VALUE);
  339 +}
  340 +
  341 +static void alternative_edited(GtkCellRendererAccel *renderer, gchar *path, guint accel_key, GdkModifierType mask, guint hardware_keycode, V3270AcceleratorSettings *widget)
  342 +{
  343 + debug("%s(%s)",__FUNCTION__,path);
  344 + change_accel(widget, path, accel_key, mask, ALTERNATIVE_MASK, ALTERNATIVE_VALUE);
  345 +}
170 346  
171 347 void load(GtkWidget *widget, GtkWidget *terminal)
172 348 {
... ... @@ -195,8 +371,17 @@ void load(GtkWidget *widget, GtkWidget *terminal)
195 371  
196 372 if(ix < G_N_ELEMENTS(keymaps))
197 373 {
198   - keymaps[ix].key = accel->key;
199   - keymaps[ix].mods = accel->mods;
  374 + if(accel->type == V3270_ACCELERATOR_TYPE_PFKEY)
  375 + {
  376 + keymaps[ix].key = GDK_F1 + (((V3270PFKeyAccelerator *)accel)->keycode - 1);
  377 + keymaps[ix].mods = 0;
  378 + }
  379 + else
  380 + {
  381 + keymaps[ix].key = accel->key;
  382 + keymaps[ix].mods = accel->mods;
  383 + }
  384 +
200 385 ix++;
201 386 }
202 387  
... ... @@ -206,6 +391,7 @@ void load(GtkWidget *widget, GtkWidget *terminal)
206 391 // Add entry
207 392 GtkTreeIter iter;
208 393 gtk_list_store_append(store, &iter);
  394 +
209 395 gtk_list_store_set(
210 396 store,
211 397 &iter,
... ... @@ -218,6 +404,7 @@ void load(GtkWidget *widget, GtkWidget *terminal)
218 404 -1
219 405 );
220 406  
  407 +
221 408 }
222 409  
223 410 }
... ... @@ -226,3 +413,4 @@ void apply(GtkWidget *widget, GtkWidget *terminal)
226 413 {
227 414 debug("%s::%s","V3270AcceleratorSettings",__FUNCTION__);
228 415 }
  416 +
... ...
src/terminal/keyboard/accelerator.c
... ... @@ -114,6 +114,11 @@
114 114  
115 115 break;
116 116  
  117 + case V3270_ACCELERATOR_TYPE_PFKEY:
  118 + if( ((V3270PFKeyAccelerator *)accel)->name )
  119 + return ((V3270PFKeyAccelerator *)accel)->name;
  120 + break;
  121 +
117 122 }
118 123  
119 124 return v3270_accelerator_get_name(accel);
... ...