1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <libgimp/gimp.h>
21 #include <libgimp/gimpui.h>
22 
23 #include "print.h"
24 #include "print-settings.h"
25 #include "print-utils.h"
26 
27 
28 #define PRINT_SETTINGS_MAJOR_VERSION 0
29 #define PRINT_SETTINGS_MINOR_VERSION 4
30 
31 #define PRINT_SETTINGS_NAME          "print-settings"
32 
33 
34 static GKeyFile * print_settings_key_file_from_settings      (PrintData         *data);
35 
36 static void       print_settings_add_to_key_file             (const gchar       *key,
37                                                               const gchar       *value,
38                                                               gpointer           data);
39 
40 static GKeyFile * print_settings_key_file_from_resource_file (void);
41 
42 static GKeyFile * print_settings_key_file_from_parasite      (gint32             image_ID);
43 
44 static gboolean   print_settings_load_from_key_file          (PrintData         *data,
45                                                               GKeyFile          *key_file);
46 
47 static gboolean   print_settings_check_version               (GKeyFile          *key_file);
48 
49 /*
50  * set GtkPrintSettings from the contents of a "print-settings"
51  * image parasite, or, if none exists, from a resource
52  * file of the same name
53  */
54 gboolean
print_settings_load(PrintData * data)55 print_settings_load (PrintData *data)
56 {
57   GKeyFile *key_file = print_settings_key_file_from_parasite (data->image_id);
58 
59   if (! key_file)
60     key_file = print_settings_key_file_from_resource_file ();
61 
62   if (key_file)
63     {
64       print_settings_load_from_key_file (data, key_file);
65       g_key_file_free (key_file);
66       return TRUE;
67     }
68 
69   return FALSE;
70 }
71 
72 /*
73  * save all settings as a resource file "print-settings"
74  * and as an image parasite
75  */
76 void
print_settings_save(PrintData * data)77 print_settings_save (PrintData *data)
78 {
79   GKeyFile *key_file = print_settings_key_file_from_settings (data);
80 
81   /* image setup */
82   if (gimp_image_is_valid (data->image_id))
83     {
84       gdouble xres;
85       gdouble yres;
86 
87       gimp_image_get_resolution (data->image_id, &xres, &yres);
88 
89       g_key_file_set_integer (key_file, "image-setup",
90                               "unit", data->unit);
91       /* Do not save the print resolution when it is the expected image
92        * resolution so that changing it (i.e. in "print size" dialog)
93        * is not overridden by any previous prints.
94        */
95       if ((data->min_xres <= xres && ABS (xres - data->xres) > 0.1)          ||
96           (data->min_yres <= yres && ABS (yres - data->yres) > 0.1)          ||
97           (data->min_xres > xres && ABS (data->min_xres - data->xres) > 0.1) ||
98           (data->min_yres > yres && ABS (data->min_yres - data->yres) > 0.1))
99         {
100           g_key_file_set_double  (key_file, "image-setup",
101                                   "x-resolution", data->xres);
102           g_key_file_set_double  (key_file, "image-setup",
103                                   "y-resolution", data->yres);
104         }
105       g_key_file_set_double  (key_file, "image-setup",
106                               "x-offset", data->offset_x);
107       g_key_file_set_double  (key_file, "image-setup",
108                               "y-offset", data->offset_y);
109       g_key_file_set_integer (key_file, "image-setup",
110                               "center-mode", data->center);
111       g_key_file_set_boolean (key_file, "image-setup",
112                               "use-full-page", data->use_full_page);
113       g_key_file_set_boolean (key_file, "image-setup",
114                               "crop-marks", data->draw_crop_marks);
115 
116       print_utils_key_file_save_as_parasite (key_file,
117                                              data->image_id,
118                                              PRINT_SETTINGS_NAME);
119     }
120 
121   /* some settings shouldn't be made persistent on a global level,
122    * so they are only stored in the image, not in the rcfile
123    */
124 
125   g_key_file_remove_key (key_file, "image-setup", "x-resolution", NULL);
126   g_key_file_remove_key (key_file, "image-setup", "y-resolution", NULL);
127   g_key_file_remove_key (key_file, "image-setup", "x-offset", NULL);
128   g_key_file_remove_key (key_file, "image-setup", "y-offset", NULL);
129 
130   g_key_file_remove_key (key_file, PRINT_SETTINGS_NAME, "n-copies", NULL);
131 
132   print_utils_key_file_save_as_rcfile (key_file, PRINT_SETTINGS_NAME);
133 
134   g_key_file_free (key_file);
135 }
136 
137 /*
138  * serialize print settings into a GKeyFile
139  */
140 static GKeyFile *
print_settings_key_file_from_settings(PrintData * data)141 print_settings_key_file_from_settings (PrintData *data)
142 {
143   GtkPrintOperation *operation = data->operation;
144   GtkPrintSettings  *settings;
145   GKeyFile          *key_file  = g_key_file_new ();
146 
147   /* put version information into the file */
148   g_key_file_set_integer (key_file, "meta", "major-version",
149                           PRINT_SETTINGS_MAJOR_VERSION);
150   g_key_file_set_integer (key_file, "meta", "minor-version",
151                           PRINT_SETTINGS_MINOR_VERSION);
152 
153   /* save the contents of the GtkPrintSettings for the operation */
154   settings = gtk_print_operation_get_print_settings (operation);
155 
156   if (settings)
157     gtk_print_settings_foreach (settings,
158                                 print_settings_add_to_key_file, key_file);
159 
160   return key_file;
161 }
162 
163 /*
164  * callback used in gtk_print_settings_foreach loop
165  */
166 static void
print_settings_add_to_key_file(const gchar * key,const gchar * value,gpointer data)167 print_settings_add_to_key_file (const gchar *key,
168                                 const gchar *value,
169                                 gpointer     data)
170 {
171   GKeyFile *key_file = data;
172 
173   g_key_file_set_value (key_file, PRINT_SETTINGS_NAME, key, value);
174 }
175 
176 /*
177  * deserialize a "print-settings" resource file into a GKeyFile
178  */
179 static GKeyFile *
print_settings_key_file_from_resource_file(void)180 print_settings_key_file_from_resource_file (void)
181 {
182   GKeyFile *key_file;
183 
184   key_file = print_utils_key_file_load_from_rcfile (PRINT_SETTINGS_NAME);
185 
186   if (key_file && ! print_settings_check_version (key_file))
187     {
188       g_key_file_free (key_file);
189       return NULL;
190     }
191 
192   return key_file;
193 }
194 
195 /* load information from an image parasite called "print-settings"
196  * return a GKeyFile containing the information if a valid parasite is found,
197  * NULL otherwise
198  */
199 static GKeyFile *
print_settings_key_file_from_parasite(gint32 image_ID)200 print_settings_key_file_from_parasite (gint32 image_ID)
201 {
202   GKeyFile *key_file;
203 
204   key_file = print_utils_key_file_load_from_parasite (image_ID,
205                                                       PRINT_SETTINGS_NAME);
206 
207   if (key_file && ! print_settings_check_version (key_file))
208     {
209       g_key_file_free (key_file);
210       return NULL;
211     }
212 
213   return key_file;
214 }
215 
216 static gboolean
print_settings_load_from_key_file(PrintData * data,GKeyFile * key_file)217 print_settings_load_from_key_file (PrintData *data,
218                                    GKeyFile  *key_file)
219 {
220   GtkPrintOperation  *operation = data->operation;
221   GtkPrintSettings   *settings;
222   gchar             **keys;
223   gsize               n_keys;
224   gint                i;
225 
226   settings = gtk_print_operation_get_print_settings (operation);
227   if (! settings)
228     settings = gtk_print_settings_new ();
229 
230   keys = g_key_file_get_keys (key_file, PRINT_SETTINGS_NAME, &n_keys, NULL);
231 
232   if (! keys)
233     return FALSE;
234 
235   for (i = 0; i < n_keys; i++)
236     {
237       gchar *value;
238 
239       value = g_key_file_get_value (key_file,
240                                     PRINT_SETTINGS_NAME, keys[i], NULL);
241 
242       if (value)
243         {
244           gtk_print_settings_set (settings, keys[i], value);
245           g_free (value);
246         }
247     }
248 
249   g_strfreev (keys);
250 
251   if (g_key_file_has_key (key_file, "image-setup", "unit", NULL))
252     {
253       data->unit = g_key_file_get_integer (key_file, "image-setup",
254                                            "unit", NULL);
255     }
256 
257   if (g_key_file_has_key (key_file, "image-setup", "x-resolution", NULL) &&
258       g_key_file_has_key (key_file, "image-setup", "y-resolution", NULL))
259     {
260       data->xres = g_key_file_get_double (key_file, "image-setup",
261                                           "x-resolution", NULL);
262       data->yres = g_key_file_get_double (key_file, "image-setup",
263                                           "y-resolution", NULL);
264     }
265 
266   if (g_key_file_has_key (key_file, "image-setup", "x-offset", NULL) &&
267       g_key_file_has_key (key_file, "image-setup", "y-offset", NULL))
268     {
269       data->offset_x = g_key_file_get_double (key_file, "image-setup",
270                                               "x-offset", NULL);
271       data->offset_y = g_key_file_get_double (key_file, "image-setup",
272                                               "y-offset", NULL);
273     }
274 
275   if (g_key_file_has_key (key_file, "image-setup", "center-mode", NULL))
276     {
277       data->center = g_key_file_get_integer (key_file, "image-setup",
278                                              "center-mode", NULL);
279     }
280 
281   if (g_key_file_has_key (key_file, "image-setup", "use-full-page", NULL))
282     {
283       data->use_full_page = g_key_file_get_boolean (key_file, "image-setup",
284                                                     "use-full-page", NULL);
285     }
286 
287   if (g_key_file_has_key (key_file, "image-setup", "crop-marks", NULL))
288     {
289       data->draw_crop_marks = g_key_file_get_boolean (key_file, "image-setup",
290                                                       "crop-marks", NULL);
291     }
292 
293   gtk_print_operation_set_print_settings (operation, settings);
294 
295   return TRUE;
296 }
297 
298 static gboolean
print_settings_check_version(GKeyFile * key_file)299 print_settings_check_version (GKeyFile *key_file)
300 {
301   gint  major_version;
302   gint  minor_version;
303 
304   if (! g_key_file_has_group (key_file, "meta"))
305     return FALSE;
306 
307   major_version = g_key_file_get_integer (key_file,
308                                           "meta", "major-version", NULL);
309 
310   if (major_version != PRINT_SETTINGS_MAJOR_VERSION)
311     return FALSE;
312 
313   minor_version = g_key_file_get_integer (key_file,
314                                           "meta", "minor-version", NULL);
315 
316   if (minor_version != PRINT_SETTINGS_MINOR_VERSION)
317     return FALSE;
318 
319   return TRUE;
320 }
321