1 /*
2 * gedit-encodings-dialog.c
3 * This file is part of gedit
4 *
5 * Copyright (C) 2002-2005 Paolo Maggi
6 * Copyright (C) 2015 Sébastien Wilmet
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include "gedit-encodings-dialog.h"
25
26 #include <string.h>
27 #include <glib/gi18n.h>
28 #include <gtksourceview/gtksource.h>
29
30 #include "gedit-settings.h"
31
32 typedef enum _State
33 {
34 STATE_UNMODIFIED,
35 STATE_MODIFIED,
36 STATE_RESET
37 } State;
38
39 struct _GeditEncodingsDialog
40 {
41 GtkDialog parent_instance;
42
43 GSettings *enc_settings;
44
45 /* Available encodings */
46 GtkListStore *liststore_available;
47 GtkTreeModelSort *sort_available;
48 GtkTreeView *treeview_available;
49 GtkWidget *add_button;
50
51 /* Chosen encodings */
52 GtkListStore *liststore_chosen;
53 GtkTreeView *treeview_chosen;
54 GtkWidget *remove_button;
55 GtkWidget *up_button;
56 GtkWidget *down_button;
57 GtkWidget *reset_button;
58
59 State state;
60 };
61
62 enum
63 {
64 COLUMN_NAME,
65 COLUMN_CHARSET,
66 COLUMN_ENCODING,
67 N_COLUMNS
68 };
69
G_DEFINE_TYPE(GeditEncodingsDialog,gedit_encodings_dialog,GTK_TYPE_DIALOG)70 G_DEFINE_TYPE (GeditEncodingsDialog, gedit_encodings_dialog, GTK_TYPE_DIALOG)
71
72 static void
73 set_modified (GeditEncodingsDialog *dialog)
74 {
75 dialog->state = STATE_MODIFIED;
76 gtk_widget_set_sensitive (dialog->reset_button, TRUE);
77 }
78
79 static void
append_encoding(GtkListStore * liststore,const GtkSourceEncoding * encoding)80 append_encoding (GtkListStore *liststore,
81 const GtkSourceEncoding *encoding)
82 {
83 GtkTreeIter iter;
84
85 gtk_list_store_append (liststore, &iter);
86 gtk_list_store_set (liststore, &iter,
87 COLUMN_NAME, gtk_source_encoding_get_name (encoding),
88 COLUMN_ENCODING, encoding,
89 -1);
90
91 if (encoding == gtk_source_encoding_get_current ())
92 {
93 gchar *charset = g_strdup_printf (_("%s (Current Locale)"),
94 gtk_source_encoding_get_charset (encoding));
95
96 gtk_list_store_set (liststore, &iter,
97 COLUMN_CHARSET, charset,
98 -1);
99
100 g_free (charset);
101 }
102 else
103 {
104 gtk_list_store_set (liststore, &iter,
105 COLUMN_CHARSET, gtk_source_encoding_get_charset (encoding),
106 -1);
107 }
108 }
109
110 static void
init_liststores(GeditEncodingsDialog * dialog,gboolean reset)111 init_liststores (GeditEncodingsDialog *dialog,
112 gboolean reset)
113 {
114 gboolean default_candidates;
115 GSList *chosen_encodings;
116 GSList *all_encodings;
117 GSList *l;
118
119 /* Chosen encodings */
120
121 if (reset)
122 {
123 chosen_encodings = gtk_source_encoding_get_default_candidates ();
124 default_candidates = TRUE;
125 }
126 else
127 {
128 chosen_encodings = gedit_settings_get_candidate_encodings (&default_candidates);
129 }
130
131 gtk_widget_set_sensitive (dialog->reset_button, !default_candidates);
132
133 for (l = chosen_encodings; l != NULL; l = l->next)
134 {
135 const GtkSourceEncoding *cur_encoding = l->data;
136 append_encoding (dialog->liststore_chosen, cur_encoding);
137 }
138
139 /* Available encodings */
140
141 all_encodings = gtk_source_encoding_get_all ();
142
143 for (l = chosen_encodings; l != NULL; l = l->next)
144 {
145 const GtkSourceEncoding *chosen_encoding = l->data;
146 all_encodings = g_slist_remove (all_encodings, chosen_encoding);
147 }
148
149 for (l = all_encodings; l != NULL; l = l->next)
150 {
151 const GtkSourceEncoding *cur_encoding = l->data;
152 append_encoding (dialog->liststore_available, cur_encoding);
153 }
154
155 g_slist_free (chosen_encodings);
156 g_slist_free (all_encodings);
157 }
158
159 static void
reset_dialog_response_cb(GtkDialog * msg_dialog,gint response,GeditEncodingsDialog * dialog)160 reset_dialog_response_cb (GtkDialog *msg_dialog,
161 gint response,
162 GeditEncodingsDialog *dialog)
163 {
164 if (response == GTK_RESPONSE_ACCEPT)
165 {
166 gtk_list_store_clear (dialog->liststore_available);
167 gtk_list_store_clear (dialog->liststore_chosen);
168
169 init_liststores (dialog, TRUE);
170 dialog->state = STATE_RESET;
171 }
172
173 gtk_widget_destroy (GTK_WIDGET (msg_dialog));
174 }
175
176 static void
reset_button_clicked_cb(GtkWidget * button,GeditEncodingsDialog * dialog)177 reset_button_clicked_cb (GtkWidget *button,
178 GeditEncodingsDialog *dialog)
179 {
180 GtkDialog *msg_dialog;
181
182 msg_dialog = GTK_DIALOG (gtk_message_dialog_new (GTK_WINDOW (dialog),
183 GTK_DIALOG_DESTROY_WITH_PARENT |
184 GTK_DIALOG_MODAL,
185 GTK_MESSAGE_QUESTION,
186 GTK_BUTTONS_NONE,
187 "%s",
188 _("Do you really want to reset the "
189 "character encodings’ preferences?")));
190
191 gtk_dialog_add_buttons (msg_dialog,
192 _("_Cancel"), GTK_RESPONSE_CANCEL,
193 _("_Reset"), GTK_RESPONSE_ACCEPT,
194 NULL);
195
196 g_signal_connect (msg_dialog,
197 "response",
198 G_CALLBACK (reset_dialog_response_cb),
199 dialog);
200
201 gtk_widget_show_all (GTK_WIDGET (msg_dialog));
202 }
203
204 static GSList *
get_chosen_encodings_list(GeditEncodingsDialog * dialog)205 get_chosen_encodings_list (GeditEncodingsDialog *dialog)
206 {
207 GtkTreeModel *model = GTK_TREE_MODEL (dialog->liststore_chosen);
208 GtkTreeIter iter;
209 gboolean iter_set;
210 GSList *ret = NULL;
211
212 iter_set = gtk_tree_model_get_iter_first (model, &iter);
213
214 while (iter_set)
215 {
216 const GtkSourceEncoding *encoding = NULL;
217
218 gtk_tree_model_get (model, &iter,
219 COLUMN_ENCODING, &encoding,
220 -1);
221
222 ret = g_slist_prepend (ret, (gpointer)encoding);
223
224 iter_set = gtk_tree_model_iter_next (model, &iter);
225 }
226
227 return g_slist_reverse (ret);
228 }
229
230 static gchar **
encoding_list_to_strv(const GSList * enc_list)231 encoding_list_to_strv (const GSList *enc_list)
232 {
233 GSList *l;
234 GPtrArray *array;
235
236 array = g_ptr_array_sized_new (g_slist_length ((GSList *)enc_list) + 1);
237
238 for (l = (GSList *)enc_list; l != NULL; l = l->next)
239 {
240 const GtkSourceEncoding *enc = l->data;
241 const gchar *charset = gtk_source_encoding_get_charset (enc);
242
243 g_return_val_if_fail (charset != NULL, NULL);
244
245 g_ptr_array_add (array, g_strdup (charset));
246 }
247
248 g_ptr_array_add (array, NULL);
249
250 return (gchar **)g_ptr_array_free (array, FALSE);
251 }
252
253 static void
apply_settings(GeditEncodingsDialog * dialog)254 apply_settings (GeditEncodingsDialog *dialog)
255 {
256 switch (dialog->state)
257 {
258 case STATE_MODIFIED:
259 {
260 GSList *enc_list;
261 gchar **enc_strv;
262
263 enc_list = get_chosen_encodings_list (dialog);
264 enc_strv = encoding_list_to_strv (enc_list);
265
266 g_settings_set_strv (dialog->enc_settings,
267 GEDIT_SETTINGS_CANDIDATE_ENCODINGS,
268 (const gchar * const *)enc_strv);
269
270 g_slist_free (enc_list);
271 g_strfreev (enc_strv);
272 break;
273 }
274
275 case STATE_RESET:
276 g_settings_reset (dialog->enc_settings,
277 GEDIT_SETTINGS_CANDIDATE_ENCODINGS);
278 break;
279
280 case STATE_UNMODIFIED:
281 /* Do nothing. */
282 break;
283
284 default:
285 g_assert_not_reached ();
286
287 }
288 }
289
290 static void
gedit_encodings_dialog_response(GtkDialog * gtk_dialog,gint response_id)291 gedit_encodings_dialog_response (GtkDialog *gtk_dialog,
292 gint response_id)
293 {
294 GeditEncodingsDialog *dialog = GEDIT_ENCODINGS_DIALOG (gtk_dialog);
295
296 switch (response_id)
297 {
298 case GTK_RESPONSE_APPLY:
299 apply_settings (dialog);
300 break;
301
302 case GTK_RESPONSE_CANCEL:
303 default:
304 /* Do nothing */
305 break;
306 }
307 }
308
309 static void
gedit_encodings_dialog_dispose(GObject * object)310 gedit_encodings_dialog_dispose (GObject *object)
311 {
312 GeditEncodingsDialog *dialog = GEDIT_ENCODINGS_DIALOG (object);
313
314 g_clear_object (&dialog->enc_settings);
315 g_clear_object (&dialog->add_button);
316 g_clear_object (&dialog->remove_button);
317 g_clear_object (&dialog->up_button);
318 g_clear_object (&dialog->down_button);
319 g_clear_object (&dialog->reset_button);
320
321 G_OBJECT_CLASS (gedit_encodings_dialog_parent_class)->dispose (object);
322 }
323
324 static void
gedit_encodings_dialog_class_init(GeditEncodingsDialogClass * klass)325 gedit_encodings_dialog_class_init (GeditEncodingsDialogClass *klass)
326 {
327 GObjectClass *object_class = G_OBJECT_CLASS (klass);
328 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
329 GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
330
331 object_class->dispose = gedit_encodings_dialog_dispose;
332
333 dialog_class->response = gedit_encodings_dialog_response;
334
335 /* Bind class to template */
336 gtk_widget_class_set_template_from_resource (widget_class,
337 "/org/gnome/gedit/ui/gedit-encodings-dialog.ui");
338 gtk_widget_class_bind_template_child (widget_class, GeditEncodingsDialog, liststore_available);
339 gtk_widget_class_bind_template_child (widget_class, GeditEncodingsDialog, liststore_chosen);
340 gtk_widget_class_bind_template_child (widget_class, GeditEncodingsDialog, sort_available);
341 gtk_widget_class_bind_template_child (widget_class, GeditEncodingsDialog, treeview_available);
342 gtk_widget_class_bind_template_child (widget_class, GeditEncodingsDialog, treeview_chosen);
343 gtk_widget_class_bind_template_child_full (widget_class, "scrolledwindow_available", FALSE, 0);
344 gtk_widget_class_bind_template_child_full (widget_class, "scrolledwindow_chosen", FALSE, 0);
345 gtk_widget_class_bind_template_child_full (widget_class, "toolbar_available", FALSE, 0);
346 gtk_widget_class_bind_template_child_full (widget_class, "toolbar_chosen", FALSE, 0);
347 }
348
349 static void
update_add_button_sensitivity(GeditEncodingsDialog * dialog)350 update_add_button_sensitivity (GeditEncodingsDialog *dialog)
351 {
352 GtkTreeSelection *selection;
353 gint count;
354
355 selection = gtk_tree_view_get_selection (dialog->treeview_available);
356 count = gtk_tree_selection_count_selected_rows (selection);
357 gtk_widget_set_sensitive (dialog->add_button, count > 0);
358 }
359
360 static void
update_remove_button_sensitivity(GeditEncodingsDialog * dialog)361 update_remove_button_sensitivity (GeditEncodingsDialog *dialog)
362 {
363 const GtkSourceEncoding *utf8_encoding;
364 const GtkSourceEncoding *current_encoding;
365 GtkTreeSelection *selection;
366 GtkTreeModel *model;
367 GList *selected_rows;
368 GList *l;
369 gboolean sensitive;
370
371 utf8_encoding = gtk_source_encoding_get_utf8 ();
372 current_encoding = gtk_source_encoding_get_current ();
373
374 selection = gtk_tree_view_get_selection (dialog->treeview_chosen);
375
376 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
377 g_return_if_fail (model == GTK_TREE_MODEL (dialog->liststore_chosen));
378
379 sensitive = FALSE;
380 for (l = selected_rows; l != NULL; l = l->next)
381 {
382 GtkTreePath *path = l->data;
383 GtkTreeIter iter;
384 const GtkSourceEncoding *encoding = NULL;
385
386 if (!gtk_tree_model_get_iter (model, &iter, path))
387 {
388 g_warning ("Remove button: invalid path");
389 continue;
390 }
391
392 gtk_tree_model_get (model, &iter,
393 COLUMN_ENCODING, &encoding,
394 -1);
395
396 /* If at least one encoding other than UTF-8 or current is
397 * selected, set the Remove button as sensitive. But if UTF-8 or
398 * current is selected, it won't be removed. So Ctrl+A works
399 * fine to remove (almost) all encodings in one go.
400 */
401 if (encoding != utf8_encoding &&
402 encoding != current_encoding)
403 {
404 sensitive = TRUE;
405 break;
406 }
407 }
408
409 gtk_widget_set_sensitive (dialog->remove_button, sensitive);
410
411 g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
412 }
413
414 static void
update_up_down_buttons_sensitivity(GeditEncodingsDialog * dialog)415 update_up_down_buttons_sensitivity (GeditEncodingsDialog *dialog)
416 {
417 GtkTreeSelection *selection;
418 gint count;
419 GList *selected_rows;
420 GtkTreeModel *model;
421 GtkTreePath *path;
422 gint *indices;
423 gint depth;
424 gint items_count;
425 gboolean first_item_selected;
426 gboolean last_item_selected;
427
428 selection = gtk_tree_view_get_selection (dialog->treeview_chosen);
429 count = gtk_tree_selection_count_selected_rows (selection);
430
431 if (count != 1)
432 {
433 gtk_widget_set_sensitive (dialog->up_button, FALSE);
434 gtk_widget_set_sensitive (dialog->down_button, FALSE);
435 return;
436 }
437
438 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
439 g_assert (g_list_length (selected_rows) == 1);
440
441 path = selected_rows->data;
442 indices = gtk_tree_path_get_indices_with_depth (path, &depth);
443 g_assert (depth == 1);
444
445 items_count = gtk_tree_model_iter_n_children (model, NULL);
446
447 first_item_selected = indices[0] == 0;
448 last_item_selected = indices[0] == (items_count - 1);
449
450 gtk_widget_set_sensitive (dialog->up_button, !first_item_selected);
451 gtk_widget_set_sensitive (dialog->down_button, !last_item_selected);
452
453 g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
454 }
455
456 static void
update_chosen_buttons_sensitivity(GeditEncodingsDialog * dialog)457 update_chosen_buttons_sensitivity (GeditEncodingsDialog *dialog)
458 {
459 update_remove_button_sensitivity (dialog);
460 update_up_down_buttons_sensitivity (dialog);
461 }
462
463 /* Removes all @paths from @orig, and append them at the end of @dest in the
464 * same order.
465 */
466 static void
transfer_encodings(GList * paths,GtkListStore * orig,GtkListStore * dest)467 transfer_encodings (GList *paths,
468 GtkListStore *orig,
469 GtkListStore *dest)
470 {
471 GtkTreeModel *model_orig = GTK_TREE_MODEL (orig);
472 GList *refs = NULL;
473 GList *l;
474
475 for (l = paths; l != NULL; l = l->next)
476 {
477 GtkTreePath *path = l->data;
478 refs = g_list_prepend (refs, gtk_tree_row_reference_new (model_orig, path));
479 }
480
481 refs = g_list_reverse (refs);
482
483 for (l = refs; l != NULL; l = l->next)
484 {
485 GtkTreeRowReference *ref = l->data;
486 GtkTreePath *path;
487 GtkTreeIter iter;
488 const GtkSourceEncoding *encoding = NULL;
489
490 path = gtk_tree_row_reference_get_path (ref);
491
492 if (!gtk_tree_model_get_iter (model_orig, &iter, path))
493 {
494 gtk_tree_path_free (path);
495 g_warning ("Remove encoding: invalid path");
496 continue;
497 }
498
499 /* Transfer encoding */
500 gtk_tree_model_get (model_orig, &iter,
501 COLUMN_ENCODING, &encoding,
502 -1);
503
504 append_encoding (dest, encoding);
505
506 gtk_list_store_remove (orig, &iter);
507
508 gtk_tree_path_free (path);
509 }
510
511 g_list_free_full (refs, (GDestroyNotify) gtk_tree_row_reference_free);
512 }
513
514 static void
add_button_clicked_cb(GtkWidget * button,GeditEncodingsDialog * dialog)515 add_button_clicked_cb (GtkWidget *button,
516 GeditEncodingsDialog *dialog)
517 {
518 GtkTreeSelection *selection;
519 GtkTreeModel *model;
520 GList *filter_paths;
521 GList *children_paths = NULL;
522 GList *l;
523
524 selection = gtk_tree_view_get_selection (dialog->treeview_available);
525 filter_paths = gtk_tree_selection_get_selected_rows (selection, &model);
526
527 g_return_if_fail (model == GTK_TREE_MODEL (dialog->sort_available));
528
529 for (l = filter_paths; l != NULL; l = l->next)
530 {
531 GtkTreePath *filter_path = l->data;
532 GtkTreePath *child_path;
533
534 child_path = gtk_tree_model_sort_convert_path_to_child_path (dialog->sort_available,
535 filter_path);
536
537 children_paths = g_list_prepend (children_paths, child_path);
538 }
539
540 children_paths = g_list_reverse (children_paths);
541
542 transfer_encodings (children_paths,
543 dialog->liststore_available,
544 dialog->liststore_chosen);
545
546 set_modified (dialog);
547
548 /* For the treeview_available, it's more natural to unselect the added
549 * encodings.
550 * Note that when removing encodings from treeview_chosen, it is
551 * desirable to keep a selection, so we can remove several elements in a
552 * row (if the user doesn't know that several elements can be selected
553 * at once with Ctrl or Shift).
554 */
555 gtk_tree_selection_unselect_all (selection);
556
557 g_list_free_full (filter_paths, (GDestroyNotify) gtk_tree_path_free);
558 g_list_free_full (children_paths, (GDestroyNotify) gtk_tree_path_free);
559 }
560
561 static void
remove_button_clicked_cb(GtkWidget * button,GeditEncodingsDialog * dialog)562 remove_button_clicked_cb (GtkWidget *button,
563 GeditEncodingsDialog *dialog)
564 {
565 const GtkSourceEncoding *utf8_encoding;
566 const GtkSourceEncoding *current_encoding;
567 GtkTreeSelection *selection;
568 GtkTreeModel *model;
569 GList *selected_rows;
570 GList *to_remove = NULL;
571 GList *l;
572
573 utf8_encoding = gtk_source_encoding_get_utf8 ();
574 current_encoding = gtk_source_encoding_get_current ();
575
576 selection = gtk_tree_view_get_selection (dialog->treeview_chosen);
577 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
578
579 g_return_if_fail (model == GTK_TREE_MODEL (dialog->liststore_chosen));
580
581 /* Ensure that UTF-8 and the current locale encodings cannot be removed. */
582 for (l = selected_rows; l != NULL; l = l->next)
583 {
584 GtkTreePath *path = l->data;
585 GtkTreeIter iter;
586 const GtkSourceEncoding *encoding = NULL;
587
588 if (!gtk_tree_model_get_iter (model, &iter, path))
589 {
590 gtk_tree_path_free (path);
591 g_warning ("Remove button: invalid path");
592 continue;
593 }
594
595 gtk_tree_model_get (model, &iter,
596 COLUMN_ENCODING, &encoding,
597 -1);
598
599 if (encoding == utf8_encoding ||
600 encoding == current_encoding)
601 {
602 gtk_tree_path_free (path);
603 }
604 else
605 {
606 to_remove = g_list_prepend (to_remove, path);
607 }
608 }
609
610 to_remove = g_list_reverse (to_remove);
611
612 transfer_encodings (to_remove,
613 dialog->liststore_chosen,
614 dialog->liststore_available);
615
616 set_modified (dialog);
617
618 g_list_free (selected_rows);
619 g_list_free_full (to_remove, (GDestroyNotify) gtk_tree_path_free);
620 }
621
622 static void
up_button_clicked_cb(GtkWidget * button,GeditEncodingsDialog * dialog)623 up_button_clicked_cb (GtkWidget *button,
624 GeditEncodingsDialog *dialog)
625 {
626 GtkTreeSelection *selection;
627 GtkTreeModel *model;
628 GList *selected_rows;
629 GtkTreePath *path;
630 GtkTreeIter iter;
631 GtkTreeIter prev_iter;
632
633 selection = gtk_tree_view_get_selection (dialog->treeview_chosen);
634 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
635
636 g_return_if_fail (model == GTK_TREE_MODEL (dialog->liststore_chosen));
637 g_return_if_fail (g_list_length (selected_rows) == 1);
638
639 path = selected_rows->data;
640 if (!gtk_tree_model_get_iter (model, &iter, path))
641 {
642 g_return_if_reached ();
643 }
644
645 prev_iter = iter;
646 if (!gtk_tree_model_iter_previous (model, &prev_iter))
647 {
648 g_return_if_reached ();
649 }
650
651 gtk_list_store_move_before (dialog->liststore_chosen,
652 &iter,
653 &prev_iter);
654
655 set_modified (dialog);
656
657 update_chosen_buttons_sensitivity (dialog);
658
659 g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
660 }
661
662 static void
down_button_clicked_cb(GtkWidget * button,GeditEncodingsDialog * dialog)663 down_button_clicked_cb (GtkWidget *button,
664 GeditEncodingsDialog *dialog)
665 {
666 GtkTreeSelection *selection;
667 GtkTreeModel *model;
668 GList *selected_rows;
669 GtkTreePath *path;
670 GtkTreeIter iter;
671 GtkTreeIter next_iter;
672
673 selection = gtk_tree_view_get_selection (dialog->treeview_chosen);
674 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
675
676 g_return_if_fail (model == GTK_TREE_MODEL (dialog->liststore_chosen));
677 g_return_if_fail (g_list_length (selected_rows) == 1);
678
679 path = selected_rows->data;
680 if (!gtk_tree_model_get_iter (model, &iter, path))
681 {
682 g_return_if_reached ();
683 }
684
685 next_iter = iter;
686 if (!gtk_tree_model_iter_next (model, &next_iter))
687 {
688 g_return_if_reached ();
689 }
690
691 gtk_list_store_move_after (dialog->liststore_chosen,
692 &iter,
693 &next_iter);
694
695 set_modified (dialog);
696
697 update_chosen_buttons_sensitivity (dialog);
698
699 g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
700 }
701
702 static void
init_toolbar_available(GeditEncodingsDialog * dialog)703 init_toolbar_available (GeditEncodingsDialog *dialog)
704 {
705 GtkWidget *scrolled_window;
706 GtkToolbar *toolbar;
707 GtkStyleContext *context;
708
709 scrolled_window = GTK_WIDGET (gtk_widget_get_template_child (GTK_WIDGET (dialog),
710 GEDIT_TYPE_ENCODINGS_DIALOG,
711 "scrolledwindow_available"));
712
713 toolbar = GTK_TOOLBAR (gtk_widget_get_template_child (GTK_WIDGET (dialog),
714 GEDIT_TYPE_ENCODINGS_DIALOG,
715 "toolbar_available"));
716
717 context = gtk_widget_get_style_context (scrolled_window);
718 gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
719
720 context = gtk_widget_get_style_context (GTK_WIDGET (toolbar));
721 gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
722 gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
723
724 /* Add button */
725 dialog->add_button = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
726 g_object_ref_sink (dialog->add_button);
727
728 gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (dialog->add_button), "list-add-symbolic");
729 gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (dialog->add_button), _("Add"));
730
731 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (dialog->add_button), -1);
732
733 g_signal_connect_object (dialog->add_button,
734 "clicked",
735 G_CALLBACK (add_button_clicked_cb),
736 dialog,
737 0);
738
739 gtk_widget_show_all (GTK_WIDGET (toolbar));
740 }
741
742 static void
init_toolbar_chosen(GeditEncodingsDialog * dialog)743 init_toolbar_chosen (GeditEncodingsDialog *dialog)
744 {
745 GtkWidget *scrolled_window;
746 GtkToolbar *toolbar;
747 GtkStyleContext *context;
748 GtkWidget *left_box;
749 GtkWidget *right_box;
750 GtkToolItem *left_group;
751 GtkToolItem *right_group;
752 GtkToolItem *separator;
753
754 scrolled_window = GTK_WIDGET (gtk_widget_get_template_child (GTK_WIDGET (dialog),
755 GEDIT_TYPE_ENCODINGS_DIALOG,
756 "scrolledwindow_chosen"));
757
758 toolbar = GTK_TOOLBAR (gtk_widget_get_template_child (GTK_WIDGET (dialog),
759 GEDIT_TYPE_ENCODINGS_DIALOG,
760 "toolbar_chosen"));
761
762 context = gtk_widget_get_style_context (scrolled_window);
763 gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
764
765 context = gtk_widget_get_style_context (GTK_WIDGET (toolbar));
766 gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
767 gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
768
769 /* Remove button */
770 dialog->remove_button = gtk_button_new_from_icon_name ("list-remove-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
771 g_object_ref_sink (dialog->remove_button);
772 gtk_widget_set_tooltip_text (dialog->remove_button, _("Remove"));
773
774 g_signal_connect_object (dialog->remove_button,
775 "clicked",
776 G_CALLBACK (remove_button_clicked_cb),
777 dialog,
778 0);
779
780 /* Up button */
781 dialog->up_button = gtk_button_new_from_icon_name ("go-up-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
782 g_object_ref_sink (dialog->up_button);
783 gtk_widget_set_tooltip_text (dialog->up_button, _("Move to a higher priority"));
784
785 g_signal_connect_object (dialog->up_button,
786 "clicked",
787 G_CALLBACK (up_button_clicked_cb),
788 dialog,
789 0);
790
791 /* Down button */
792 dialog->down_button = gtk_button_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
793 g_object_ref_sink (dialog->down_button);
794 gtk_widget_set_tooltip_text (dialog->down_button, _("Move to a lower priority"));
795
796 g_signal_connect_object (dialog->down_button,
797 "clicked",
798 G_CALLBACK (down_button_clicked_cb),
799 dialog,
800 0);
801
802 /* Left group (with a trick for rounded borders) */
803 left_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
804 left_group = gtk_tool_item_new ();
805 gtk_box_pack_start (GTK_BOX (left_box), dialog->remove_button, FALSE, FALSE, 0);
806 gtk_box_pack_start (GTK_BOX (left_box), dialog->up_button, FALSE, FALSE, 0);
807 gtk_box_pack_start (GTK_BOX (left_box), dialog->down_button, FALSE, FALSE, 0);
808 gtk_container_add (GTK_CONTAINER (left_group), left_box);
809 gtk_toolbar_insert (toolbar, left_group, -1);
810
811 /* Separator */
812 separator = gtk_separator_tool_item_new ();
813 gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (separator), FALSE);
814 gtk_tool_item_set_expand (separator, TRUE);
815 gtk_toolbar_insert (toolbar, separator, -1);
816
817 /* Reset button */
818 dialog->reset_button = gtk_button_new_with_mnemonic (_("_Reset"));
819 g_object_ref_sink (dialog->reset_button);
820
821 g_signal_connect_object (dialog->reset_button,
822 "clicked",
823 G_CALLBACK (reset_button_clicked_cb),
824 dialog,
825 0);
826
827 /* Right group */
828 right_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
829 right_group = gtk_tool_item_new ();
830 gtk_box_pack_start (GTK_BOX (right_box), dialog->reset_button, FALSE, FALSE, 0);
831 gtk_container_add (GTK_CONTAINER (right_group), right_box);
832 gtk_toolbar_insert (toolbar, right_group, -1);
833
834 gtk_widget_show_all (GTK_WIDGET (toolbar));
835 }
836
837 static void
gedit_encodings_dialog_init(GeditEncodingsDialog * dialog)838 gedit_encodings_dialog_init (GeditEncodingsDialog *dialog)
839 {
840 GtkTreeSelection *selection;
841
842 dialog->enc_settings = g_settings_new ("org.gnome.gedit.preferences.encodings");
843
844 gtk_widget_init_template (GTK_WIDGET (dialog));
845
846 init_toolbar_available (dialog);
847 init_toolbar_chosen (dialog);
848 init_liststores (dialog, FALSE);
849 dialog->state = STATE_UNMODIFIED;
850
851 /* Available encodings */
852 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->sort_available),
853 COLUMN_NAME,
854 GTK_SORT_ASCENDING);
855
856 selection = gtk_tree_view_get_selection (dialog->treeview_available);
857
858 g_signal_connect_swapped (selection,
859 "changed",
860 G_CALLBACK (update_add_button_sensitivity),
861 dialog);
862
863 update_add_button_sensitivity (dialog);
864
865 /* Chosen encodings */
866 selection = gtk_tree_view_get_selection (dialog->treeview_chosen);
867
868 g_signal_connect_swapped (selection,
869 "changed",
870 G_CALLBACK (update_chosen_buttons_sensitivity),
871 dialog);
872
873 update_chosen_buttons_sensitivity (dialog);
874 }
875
876 GtkWidget *
gedit_encodings_dialog_new(void)877 gedit_encodings_dialog_new (void)
878 {
879 return g_object_new (GEDIT_TYPE_ENCODINGS_DIALOG,
880 "use-header-bar", TRUE,
881 NULL);
882 }
883
884 /* ex:set ts=8 noet: */
885