1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This is a plug-in for GIMP.
5  *
6  * Copyright (C) 2000 Michael Natterer <mitch@gimp.org>
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 3 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 <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <string.h>
25 
26 #include <libgimp/gimp.h>
27 #include <libgimp/gimpui.h>
28 
29 #include "libgimp/stdplugins-intl.h"
30 
31 
32 #define PLUG_IN_PROC     "plug-in-unit-editor"
33 #define PLUG_IN_BINARY   "unit-editor"
34 #define PLUG_IN_ROLE     "gimp-unit-editor"
35 #define RESPONSE_REFRESH 1
36 
37 enum
38 {
39   SAVE,
40   IDENTIFIER,
41   FACTOR,
42   DIGITS,
43   SYMBOL,
44   ABBREVIATION,
45   SINGULAR,
46   PLURAL,
47   UNIT,
48   USER_UNIT,
49   BG_COLOR,
50   NUM_COLUMNS
51 };
52 
53 typedef struct
54 {
55   const gchar *title;
56   const gchar *help;
57 
58 } UnitColumn;
59 
60 
61 static void     query                  (void);
62 static void     run                    (const gchar           *name,
63                                         gint                   n_params,
64                                         const GimpParam       *param,
65                                         gint                  *n_return_vals,
66                                         GimpParam            **return_vals);
67 
68 static GimpUnit new_unit_dialog        (GtkWidget             *main_dialog,
69                                         GimpUnit               template);
70 static void     unit_editor_dialog     (void);
71 static void     unit_editor_response   (GtkWidget             *widget,
72                                         gint                   response_id,
73                                         gpointer               data);
74 static void     new_callback           (GtkAction             *action,
75                                         GtkTreeView           *tv);
76 static void     duplicate_callback     (GtkAction             *action,
77                                         GtkTreeView           *tv);
78 static void     saved_toggled_callback (GtkCellRendererToggle *celltoggle,
79                                         gchar                 *path_string,
80                                         GtkListStore          *list_store);
81 static void     unit_list_init         (GtkTreeView           *tv);
82 
83 
84 const GimpPlugInInfo PLUG_IN_INFO =
85 {
86   NULL,  /* init_proc  */
87   NULL,  /* quit_proc  */
88   query, /* query_proc */
89   run,   /* run_proc   */
90 };
91 
92 static const UnitColumn columns[] =
93 {
94   { N_("Saved"),        N_("A unit definition will only be saved before "
95                            "GIMP exits if this column is checked.")         },
96   { N_("ID"),           N_("This string will be used to identify a "
97                            "unit in GIMP's configuration files.")           },
98   { N_("Factor"),       N_("How many units make up an inch.")               },
99   { N_("Digits"),       N_("This field is a hint for numerical input "
100                            "fields. It specifies how many decimal digits "
101                            "the input field should provide to get "
102                            "approximately the same accuracy as an "
103                            "\"inch\" input field with two decimal digits.") },
104   { N_("Symbol"),       N_("The unit's symbol if it has one (e.g. \" "
105                            "for inches). The unit's abbreviation is used "
106                            "if doesn't have a symbol.")                     },
107   { N_("Abbreviation"), N_("The unit's abbreviation (e.g. \"cm\" for "
108                            "centimeters).")                                 },
109   { N_("Singular"),     N_("The unit's singular form.")                     },
110   { N_("Plural"),       N_("The unit's plural form.")                       }
111 };
112 
113 static GtkActionEntry actions[] =
114 {
115   { "unit-editor-toolbar", NULL,
116     "Unit Editor Toolbar", NULL, NULL, NULL
117   },
118 
119   { "unit-editor-new", GIMP_ICON_DOCUMENT_NEW,
120     NULL, "<control>N",
121     N_("Create a new unit from scratch"),
122     G_CALLBACK (new_callback)
123   },
124 
125   { "unit-editor-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
126     NULL,  "<control>D",
127     N_("Create a new unit using the currently selected unit as template"),
128     G_CALLBACK (duplicate_callback)
129   }
130 };
131 
132 
MAIN()133 MAIN ()
134 
135 
136 static void
137 query (void)
138 {
139   static const GimpParamDef args[] =
140   {
141     { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0) }" }
142   };
143 
144   gimp_install_procedure (PLUG_IN_PROC,
145                           N_("Create or alter units used in GIMP"),
146                           "The GIMP unit editor",
147                           "Michael Natterer <mitch@gimp.org>",
148                           "Michael Natterer <mitch@gimp.org>",
149                           "2000",
150                           N_("U_nits"),
151                           "",
152                           GIMP_PLUGIN,
153                           G_N_ELEMENTS (args), 0,
154                           args, NULL);
155 
156   gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Edit/Preferences");
157   gimp_plugin_icon_register (PLUG_IN_PROC, GIMP_ICON_TYPE_ICON_NAME,
158                              (const guint8 *) GIMP_ICON_TOOL_MEASURE);
159 }
160 
161 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)162 run (const gchar      *name,
163      gint              nparams,
164      const GimpParam  *param,
165      gint             *nreturn_vals,
166      GimpParam       **return_vals)
167 {
168   static GimpParam values[2];
169 
170   INIT_I18N ();
171 
172   *nreturn_vals = 1;
173   *return_vals  = values;
174 
175   values[0].type          = GIMP_PDB_STATUS;
176   values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
177 
178   if (strcmp (name, PLUG_IN_PROC) == 0)
179     {
180       values[0].data.d_status = GIMP_PDB_SUCCESS;
181 
182       unit_editor_dialog ();
183     }
184 }
185 
186 static GimpUnit
new_unit_dialog(GtkWidget * main_dialog,GimpUnit template)187 new_unit_dialog (GtkWidget *main_dialog,
188                  GimpUnit   template)
189 {
190   GtkWidget     *dialog;
191   GtkWidget     *table;
192   GtkWidget     *entry;
193   GtkWidget     *spinbutton;
194 
195   GtkWidget     *identifier_entry;
196   GtkAdjustment *factor_adj;
197   GtkAdjustment *digits_adj;
198   GtkWidget     *symbol_entry;
199   GtkWidget     *abbreviation_entry;
200   GtkWidget     *singular_entry;
201   GtkWidget     *plural_entry;
202 
203   GimpUnit       unit = GIMP_UNIT_PIXEL;
204 
205   dialog = gimp_dialog_new (_("Add a New Unit"), PLUG_IN_ROLE,
206                             main_dialog, GTK_DIALOG_MODAL,
207                             gimp_standard_help_func, PLUG_IN_PROC,
208 
209                             _("_Cancel"), GTK_RESPONSE_CANCEL,
210                             _("_Add"),    GTK_RESPONSE_OK,
211 
212                             NULL);
213 
214   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
215                                            GTK_RESPONSE_OK,
216                                            GTK_RESPONSE_CANCEL,
217                                            -1);
218 
219   table = gtk_table_new (7, 2, FALSE);
220   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
221   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
222   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
223   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
224                       table, FALSE, FALSE, 0);
225   gtk_widget_show (table);
226 
227   entry = identifier_entry = gtk_entry_new ();
228   if (template != GIMP_UNIT_PIXEL)
229     {
230       gtk_entry_set_text (GTK_ENTRY (entry),
231                           gimp_unit_get_identifier (template));
232     }
233   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
234                              _("_ID:"), 0.0, 0.5,
235                              entry, 1, FALSE);
236 
237   gimp_help_set_help_data (entry, gettext (columns[IDENTIFIER].help), NULL);
238 
239   factor_adj = (GtkAdjustment *)
240     gtk_adjustment_new ((template != GIMP_UNIT_PIXEL) ?
241                         gimp_unit_get_factor (template) : 1.0,
242                         GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION,
243                         0.01, 0.1, 0.0);
244   spinbutton = gimp_spin_button_new (factor_adj, 0.01, 5);
245   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
246   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
247                              _("_Factor:"), 0.0, 0.5,
248                              spinbutton, 1, TRUE);
249 
250   gimp_help_set_help_data (spinbutton, gettext (columns[FACTOR].help), NULL);
251 
252   digits_adj = (GtkAdjustment *)
253     gtk_adjustment_new ((template != GIMP_UNIT_PIXEL) ?
254                         gimp_unit_get_digits (template) : 2.0,
255                         0, 5, 1, 1, 0);
256   spinbutton = gimp_spin_button_new (digits_adj, 0, 0);
257   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
258   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
259                              _("_Digits:"), 0.0, 0.5,
260                              spinbutton, 1, TRUE);
261 
262   gimp_help_set_help_data (spinbutton, gettext (columns[DIGITS].help), NULL);
263 
264   entry = symbol_entry = gtk_entry_new ();
265   if (template != GIMP_UNIT_PIXEL)
266     {
267       gtk_entry_set_text (GTK_ENTRY (entry),
268                           gimp_unit_get_symbol (template));
269     }
270   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
271                              _("_Symbol:"), 0.0, 0.5,
272                              entry, 1, FALSE);
273 
274   gimp_help_set_help_data (entry, gettext (columns[SYMBOL].help), NULL);
275 
276   entry = abbreviation_entry = gtk_entry_new ();
277   if (template != GIMP_UNIT_PIXEL)
278     {
279       gtk_entry_set_text (GTK_ENTRY (entry),
280                           gimp_unit_get_abbreviation (template));
281     }
282   gimp_table_attach_aligned (GTK_TABLE (table), 0, 4,
283                              _("_Abbreviation:"), 0.0, 0.5,
284                              entry, 1, FALSE);
285 
286   gimp_help_set_help_data (entry, gettext (columns[ABBREVIATION].help), NULL);
287 
288   entry = singular_entry = gtk_entry_new ();
289   if (template != GIMP_UNIT_PIXEL)
290     {
291       gtk_entry_set_text (GTK_ENTRY (entry),
292                           gimp_unit_get_singular (template));
293     }
294   gimp_table_attach_aligned (GTK_TABLE (table), 0, 5,
295                              _("Si_ngular:"), 0.0, 0.5,
296                              entry, 1, FALSE);
297 
298   gimp_help_set_help_data (entry, gettext (columns[SINGULAR].help), NULL);
299 
300   entry = plural_entry = gtk_entry_new ();
301   if (template != GIMP_UNIT_PIXEL)
302     {
303       gtk_entry_set_text (GTK_ENTRY (entry),
304                           gimp_unit_get_plural (template));
305     }
306   gimp_table_attach_aligned (GTK_TABLE (table), 0, 6,
307                              _("_Plural:"), 0.0, 0.5,
308                              entry, 1, FALSE);
309 
310   gimp_help_set_help_data (entry, gettext (columns[PLURAL].help), NULL);
311 
312   gtk_widget_show (dialog);
313 
314   while (TRUE)
315     {
316       gchar   *identifier;
317       gdouble  factor;
318       gint     digits;
319       gchar   *symbol;
320       gchar   *abbreviation;
321       gchar   *singular;
322       gchar   *plural;
323 
324       if (gimp_dialog_run (GIMP_DIALOG (dialog)) != GTK_RESPONSE_OK)
325         break;
326 
327       identifier   = g_strdup (gtk_entry_get_text (GTK_ENTRY (identifier_entry)));
328       factor       = gtk_adjustment_get_value (GTK_ADJUSTMENT (factor_adj));
329       digits       = gtk_adjustment_get_value (GTK_ADJUSTMENT (digits_adj));
330       symbol       = g_strdup (gtk_entry_get_text (GTK_ENTRY (symbol_entry)));
331       abbreviation = g_strdup (gtk_entry_get_text (GTK_ENTRY (abbreviation_entry)));
332       singular     = g_strdup (gtk_entry_get_text (GTK_ENTRY (singular_entry)));
333       plural       = g_strdup (gtk_entry_get_text (GTK_ENTRY (plural_entry)));
334 
335       identifier   = g_strstrip (identifier);
336       symbol       = g_strstrip (symbol);
337       abbreviation = g_strstrip (abbreviation);
338       singular     = g_strstrip (singular);
339       plural       = g_strstrip (plural);
340 
341       if (! strlen (identifier)   ||
342           ! strlen (symbol)       ||
343           ! strlen (abbreviation) ||
344           ! strlen (singular)     ||
345           ! strlen (plural))
346         {
347           GtkWidget *msg = gtk_message_dialog_new (GTK_WINDOW (dialog), 0,
348                                                    GTK_MESSAGE_ERROR,
349                                                    GTK_BUTTONS_OK,
350                                                    _("Incomplete input"));
351 
352           gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (msg),
353                                                     _("Please fill in all text fields."));
354           gtk_dialog_run (GTK_DIALOG (msg));
355           gtk_widget_destroy (msg);
356 
357           continue;
358         }
359 
360       unit = gimp_unit_new (identifier,
361                             factor, digits,
362                             symbol, abbreviation, singular, plural);
363 
364       g_free (identifier);
365       g_free (symbol);
366       g_free (abbreviation);
367       g_free (singular);
368       g_free (plural);
369 
370       break;
371     }
372 
373   gtk_widget_destroy (dialog);
374 
375   return unit;
376 }
377 
378 static void
unit_editor_dialog(void)379 unit_editor_dialog (void)
380 {
381   GtkWidget         *dialog;
382   GtkWidget         *scrolled_win;
383   GtkUIManager      *ui_manager;
384   GtkActionGroup    *group;
385   GtkWidget         *toolbar;
386   GtkListStore      *list_store;
387   GtkWidget         *tv;
388   GtkTreeViewColumn *col;
389   GtkWidget         *col_widget;
390   GtkWidget         *button;
391   GtkCellRenderer   *rend;
392   gint               i;
393 
394   gimp_ui_init (PLUG_IN_BINARY, FALSE);
395 
396   list_store = gtk_list_store_new (NUM_COLUMNS,
397                                    G_TYPE_BOOLEAN,   /*  SAVE          */
398                                    G_TYPE_STRING,    /*  IDENTIFIER    */
399                                    G_TYPE_DOUBLE,    /*  FACTOR        */
400                                    G_TYPE_INT,       /*  DIGITS        */
401                                    G_TYPE_STRING,    /*  SYMBOL        */
402                                    G_TYPE_STRING,    /*  ABBREVIATION  */
403                                    G_TYPE_STRING,    /*  SINGULAR      */
404                                    G_TYPE_STRING,    /*  PLURAL        */
405                                    GIMP_TYPE_UNIT,   /*  UNIT          */
406                                    G_TYPE_BOOLEAN,   /*  USER_UNIT     */
407                                    GDK_TYPE_COLOR);  /*  BG_COLOR      */
408 
409   tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
410   g_object_unref (list_store);
411 
412   dialog = gimp_dialog_new (_("Unit Editor"), PLUG_IN_ROLE,
413                             NULL, 0,
414                             gimp_standard_help_func, PLUG_IN_PROC,
415 
416                             _("_Refresh"), RESPONSE_REFRESH,
417                             _("_Close"),   GTK_RESPONSE_CLOSE,
418 
419                             NULL);
420 
421   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
422 
423   g_signal_connect (dialog, "response",
424                     G_CALLBACK (unit_editor_response),
425                     tv);
426   g_signal_connect (dialog, "destroy",
427                     G_CALLBACK (gtk_main_quit),
428                     NULL);
429 
430   /*  the toolbar  */
431   ui_manager = gtk_ui_manager_new ();
432 
433   group = gtk_action_group_new ("unit-editor");
434 
435   gtk_action_group_set_translation_domain (group, NULL);
436   gtk_action_group_add_actions (group, actions, G_N_ELEMENTS (actions), tv);
437 
438   gtk_window_add_accel_group (GTK_WINDOW (dialog),
439                               gtk_ui_manager_get_accel_group (ui_manager));
440   gtk_accel_group_lock (gtk_ui_manager_get_accel_group (ui_manager));
441 
442   gtk_ui_manager_insert_action_group (ui_manager, group, -1);
443   g_object_unref (group);
444 
445   gtk_ui_manager_add_ui_from_string
446     (ui_manager,
447      "<ui>\n"
448      "  <toolbar action=\"unit-editor-toolbar\">\n"
449      "    <toolitem action=\"unit-editor-new\" />\n"
450      "    <toolitem action=\"unit-editor-duplicate\" />\n"
451      "  </toolbar>\n"
452      "</ui>\n",
453      -1, NULL);
454 
455   toolbar = gtk_ui_manager_get_widget (ui_manager, "/unit-editor-toolbar");
456   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
457                       toolbar, FALSE, FALSE, 0);
458   gtk_widget_show (toolbar);
459 
460   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
461   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
462                                        GTK_SHADOW_IN);
463   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
464                                   GTK_POLICY_NEVER,
465                                   GTK_POLICY_ALWAYS);
466   gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 12);
467   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
468                       scrolled_win, TRUE, TRUE, 0);
469   gtk_widget_show (scrolled_win);
470 
471   gtk_widget_set_size_request (tv, -1, 220);
472   gtk_container_add (GTK_CONTAINER (scrolled_win), tv);
473   gtk_widget_show (tv);
474 
475   rend = gtk_cell_renderer_toggle_new ();
476   col =
477     gtk_tree_view_column_new_with_attributes (gettext (columns[SAVE].title),
478                                               rend,
479                                               "active",              SAVE,
480                                               "activatable",         USER_UNIT,
481                                               "cell-background-gdk", BG_COLOR,
482                                               NULL);
483 
484   gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col);
485 
486   col_widget = gtk_tree_view_column_get_widget (col);
487   if (col_widget)
488     {
489       button = gtk_widget_get_ancestor (col_widget, GTK_TYPE_BUTTON);
490 
491       if (button)
492         gimp_help_set_help_data (button,
493                                  gettext (columns[SAVE].help), NULL);
494     }
495 
496   g_signal_connect (rend, "toggled",
497                     G_CALLBACK (saved_toggled_callback),
498                     list_store);
499 
500   for (i = 0; i < G_N_ELEMENTS (columns); i++)
501     {
502       if (i == SAVE)
503         continue;
504 
505       col =
506         gtk_tree_view_column_new_with_attributes (gettext (columns[i].title),
507                                                   gtk_cell_renderer_text_new (),
508                                                   "text",                i,
509                                                   "cell-background-gdk", BG_COLOR,
510                                                   NULL);
511 
512       gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col);
513 
514       col_widget = gtk_tree_view_column_get_widget (col);
515       if (col_widget)
516         {
517           button = gtk_widget_get_ancestor (col_widget, GTK_TYPE_BUTTON);
518 
519           if (button)
520             gimp_help_set_help_data (button, gettext (columns[i].help), NULL);
521         }
522     }
523 
524   unit_list_init (GTK_TREE_VIEW (tv));
525 
526   gtk_widget_show (dialog);
527 
528   gtk_main ();
529 }
530 
531 static void
unit_editor_response(GtkWidget * widget,gint response_id,gpointer data)532 unit_editor_response (GtkWidget *widget,
533                       gint       response_id,
534                       gpointer   data)
535 {
536   switch (response_id)
537     {
538     case RESPONSE_REFRESH:
539       unit_list_init (GTK_TREE_VIEW (data));
540       break;
541 
542     default:
543       gtk_widget_destroy (widget);
544       break;
545     }
546 }
547 
548 static void
new_callback(GtkAction * action,GtkTreeView * tv)549 new_callback (GtkAction   *action,
550               GtkTreeView *tv)
551 {
552   GimpUnit  unit;
553 
554   unit = new_unit_dialog (gtk_widget_get_toplevel (GTK_WIDGET (tv)),
555                           GIMP_UNIT_PIXEL);
556 
557   if (unit != GIMP_UNIT_PIXEL)
558     {
559       GtkTreeModel *model;
560       GtkTreeIter   iter;
561 
562       unit_list_init (tv);
563 
564       model = gtk_tree_view_get_model (tv);
565 
566       if (gtk_tree_model_get_iter_first (model, &iter) &&
567           gtk_tree_model_iter_nth_child (model, &iter,
568                                          NULL, unit - GIMP_UNIT_INCH))
569         {
570           GtkAdjustment *adj;
571 
572           gtk_tree_selection_select_iter (gtk_tree_view_get_selection (tv),
573                                           &iter);
574 
575           adj = gtk_tree_view_get_vadjustment (tv);
576           gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj));
577         }
578     }
579 }
580 
581 static void
duplicate_callback(GtkAction * action,GtkTreeView * tv)582 duplicate_callback (GtkAction   *action,
583                     GtkTreeView *tv)
584 {
585   GtkTreeModel     *model;
586   GtkTreeSelection *sel;
587   GtkTreeIter       iter;
588 
589   model = gtk_tree_view_get_model (tv);
590   sel   = gtk_tree_view_get_selection (tv);
591 
592   if (gtk_tree_selection_get_selected (sel, NULL, &iter))
593     {
594       GimpUnit unit;
595 
596       gtk_tree_model_get (model, &iter,
597                           UNIT, &unit,
598                           -1);
599 
600       unit = new_unit_dialog (gtk_widget_get_toplevel (GTK_WIDGET (tv)),
601                               unit);
602 
603       if (unit != GIMP_UNIT_PIXEL)
604         {
605           GtkTreeIter iter;
606 
607           unit_list_init (tv);
608 
609           if (gtk_tree_model_get_iter_first (model, &iter) &&
610               gtk_tree_model_iter_nth_child (model, &iter,
611                                              NULL, unit - GIMP_UNIT_INCH))
612             {
613               GtkAdjustment *adj;
614 
615               gtk_tree_selection_select_iter (sel, &iter);
616 
617               adj = gtk_tree_view_get_vadjustment (tv);
618               gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj));
619             }
620         }
621     }
622 }
623 
624 static void
saved_toggled_callback(GtkCellRendererToggle * celltoggle,gchar * path_string,GtkListStore * list_store)625 saved_toggled_callback (GtkCellRendererToggle *celltoggle,
626                         gchar                 *path_string,
627                         GtkListStore          *list_store)
628 {
629   GtkTreePath *path;
630   GtkTreeIter  iter;
631   gboolean     saved;
632   GimpUnit     unit;
633 
634   path = gtk_tree_path_new_from_string (path_string);
635 
636   if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), &iter, path))
637     {
638       g_warning ("%s: bad tree path?", G_STRLOC);
639       return;
640     }
641   gtk_tree_path_free (path);
642 
643   gtk_tree_model_get (GTK_TREE_MODEL (list_store), &iter,
644                       SAVE, &saved,
645                       UNIT, &unit,
646                       -1);
647 
648   if (unit >= gimp_unit_get_number_of_built_in_units ())
649     {
650       gimp_unit_set_deletion_flag (unit, saved);
651       gtk_list_store_set (GTK_LIST_STORE (list_store), &iter,
652                           SAVE, ! saved,
653                           -1);
654     }
655 }
656 
657 static void
unit_list_init(GtkTreeView * tv)658 unit_list_init (GtkTreeView *tv)
659 {
660   GtkListStore *list_store;
661   GtkTreeIter   iter;
662   gint          num_units;
663   GimpUnit      unit;
664   GdkColor      color;
665 
666   list_store = GTK_LIST_STORE (gtk_tree_view_get_model (tv));
667 
668   gtk_list_store_clear (list_store);
669 
670   num_units = gimp_unit_get_number_of_units ();
671 
672   color.red   = 0xdddd;
673   color.green = 0xdddd;
674   color.blue  = 0xffff;
675 
676   for (unit = GIMP_UNIT_INCH; unit < num_units; unit++)
677     {
678       gboolean user_unit = (unit >= gimp_unit_get_number_of_built_in_units ());
679 
680       gtk_list_store_append (list_store, &iter);
681       gtk_list_store_set (list_store, &iter,
682                           SAVE,         ! gimp_unit_get_deletion_flag (unit),
683                           IDENTIFIER,   gimp_unit_get_identifier (unit),
684                           FACTOR,       gimp_unit_get_factor (unit),
685                           DIGITS,       gimp_unit_get_digits (unit),
686                           SYMBOL,       gimp_unit_get_symbol (unit),
687                           ABBREVIATION, gimp_unit_get_abbreviation (unit),
688                           SINGULAR,     gimp_unit_get_singular (unit),
689                           PLURAL,       gimp_unit_get_plural (unit),
690                           UNIT,         unit,
691                           USER_UNIT,    user_unit,
692 
693                           user_unit ? -1 : BG_COLOR, &color,
694 
695                           -1);
696     }
697 
698   if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter))
699     gtk_tree_selection_select_iter (gtk_tree_view_get_selection (tv), &iter);
700 }
701