Mercurial > geeqie.yaz
annotate src/info.c @ 276:4f526d436873
Implement secure rc file saving.
First data is written to a temporary file, then if nothing
was wrong, this file is renamed to the final name.
This way the risk of corrupted rc file is greatly reduced.
The code is borrowed from ELinks (http://elinks.cz).
author | zas_ |
---|---|
date | Tue, 08 Apr 2008 21:55:58 +0000 |
parents | 35f9083c6b95 |
children | 9995c5fb202a |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
9 | 3 * (C) 2004 John Ellis |
4 * | |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 | |
13 #include "gqview.h" | |
14 #include "info.h" | |
15 | |
16 #include "bar_info.h" | |
17 #include "bar_exif.h" | |
18 #include "dnd.h" | |
19 #include "filelist.h" | |
20 #include "image.h" | |
21 #include "image-load.h" | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
22 #include "pixbuf-renderer.h" |
9 | 23 #include "ui_bookmark.h" |
24 #include "ui_fileops.h" | |
25 #include "ui_misc.h" | |
26 | |
27 #include <pwd.h> | |
28 #include <grp.h> | |
29 | |
30 | |
31 #define IMAGE_SIZE_W 200 | |
32 #define IMAGE_SIZE_H 200 | |
33 | |
90
dc3c77d027e6
Tue Oct 31 18:06:42 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
34 #define DEF_PROPERTY_WIDTH 600 |
dc3c77d027e6
Tue Oct 31 18:06:42 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
35 #define DEF_PROPERTY_HEIGHT 400 |
9 | 36 |
37 typedef struct _TabData TabData; | |
38 struct _TabData | |
39 { | |
40 void (*func_free)(gpointer data); | |
41 void (*func_sync)(InfoData *id, gpointer data); | |
42 void (*func_image)(InfoData *id, gpointer data); | |
43 gpointer data; | |
221 | 44 TabData *(*func_new)(InfoData *id); |
45 GtkWidget *child; | |
9 | 46 }; |
47 | |
221 | 48 typedef struct _InfoTabsPos InfoTabsPos; |
49 struct _InfoTabsPos | |
50 { | |
51 TabData *(*func)(InfoData *id); | |
52 gint pos; | |
53 }; | |
54 | |
55 static GList *info_tabs_pos_list = NULL; | |
9 | 56 |
271
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
57 static void notebook_set_tab_reorderable(GtkNotebook *notebook, GtkWidget *child, gboolean reorderable) |
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
58 { |
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
59 #if GTK_CHECK_VERSION(2,10,0) |
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
60 gtk_notebook_set_tab_reorderable(notebook, child, reorderable); |
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
61 #endif |
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
62 } |
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
63 |
9 | 64 /* |
65 *------------------------------------------------------------------- | |
66 * table utils | |
67 *------------------------------------------------------------------- | |
68 */ | |
69 | |
70 GtkWidget *table_add_line(GtkWidget *table, gint x, gint y, | |
71 const gchar *description, const gchar *text) | |
72 { | |
73 GtkWidget *label; | |
74 | |
75 if (!text) text = ""; | |
76 | |
77 label = pref_table_label(table, x, y, description, 1.0); | |
78 pref_label_bold(label, TRUE, FALSE); | |
79 | |
80 label = pref_table_label(table, x + 1, y, text, 0.0); | |
81 return label; | |
82 } | |
83 | |
84 /* | |
85 *------------------------------------------------------------------- | |
86 * EXIF tab | |
87 *------------------------------------------------------------------- | |
88 */ | |
89 | |
90 static void info_tab_exif_image(InfoData *id, gpointer data) | |
91 { | |
92 GtkWidget *bar = data; | |
138 | 93 FileData *fd; |
9 | 94 |
95 if (id->image->unknown) | |
96 { | |
138 | 97 fd = NULL; |
9 | 98 } |
99 else | |
100 { | |
138 | 101 fd = id->image->image_fd; |
9 | 102 } |
103 | |
138 | 104 bar_exif_set(bar, fd); |
9 | 105 } |
106 | |
107 static void info_tab_exif_sync(InfoData *id, gpointer data) | |
108 { | |
109 GtkWidget *bar = data; | |
110 | |
111 bar_exif_set(bar, NULL); | |
112 } | |
113 | |
114 static TabData *info_tab_exif_new(InfoData *id) | |
115 { | |
116 TabData *td; | |
117 GtkWidget *bar; | |
118 GtkWidget *label; | |
119 | |
120 bar = bar_exif_new(FALSE, NULL, FALSE, NULL); | |
121 gtk_container_set_border_width(GTK_CONTAINER(bar), PREF_PAD_BORDER); | |
122 | |
123 label = gtk_label_new(_("Exif")); | |
124 gtk_notebook_append_page(GTK_NOTEBOOK(id->notebook), bar, label); | |
271
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
125 notebook_set_tab_reorderable(GTK_NOTEBOOK(id->notebook), bar, TRUE); |
9 | 126 gtk_widget_show(bar); |
127 | |
128 /* register */ | |
129 td = g_new0(TabData, 1); | |
130 td->func_free = NULL; | |
131 td->func_sync = info_tab_exif_sync; | |
132 td->func_image = info_tab_exif_image; | |
133 td->data = bar; | |
221 | 134 td->func_new = info_tab_exif_new; |
135 td->child = bar; | |
9 | 136 |
137 return td; | |
138 } | |
139 | |
140 /* | |
141 *------------------------------------------------------------------- | |
142 * file attributes tab | |
143 *------------------------------------------------------------------- | |
144 */ | |
145 | |
146 typedef struct _InfoTabMeta InfoTabMeta; | |
147 struct _InfoTabMeta | |
148 { | |
149 GtkWidget *bar_info; | |
150 }; | |
151 | |
152 static void info_tab_meta_free(gpointer data) | |
153 { | |
154 InfoTabMeta *tab = data; | |
155 | |
156 g_free(tab); | |
157 } | |
158 | |
159 static void info_tab_meta_sync(InfoData *id, gpointer data) | |
160 { | |
161 InfoTabMeta *tab = data; | |
162 | |
138 | 163 bar_info_set(tab->bar_info, id->fd); |
9 | 164 } |
165 | |
166 static GList *info_tab_meta_list_cb(gpointer data) | |
167 { | |
168 InfoData *id = data; | |
169 | |
170 return path_list_copy(id->list); | |
171 } | |
172 | |
173 static TabData *info_tab_meta_new(InfoData *id) | |
174 { | |
175 TabData *td; | |
176 InfoTabMeta *tab; | |
177 GtkWidget *label; | |
178 | |
179 tab = g_new0(InfoTabMeta, 1); | |
180 | |
181 tab->bar_info = bar_info_new(NULL, TRUE, NULL); | |
182 bar_info_set_selection_func(tab->bar_info, info_tab_meta_list_cb, id); | |
183 bar_info_selection(tab->bar_info, g_list_length(id->list) - 1); | |
184 | |
185 gtk_container_set_border_width(GTK_CONTAINER(tab->bar_info), PREF_PAD_BORDER); | |
186 | |
187 label = gtk_label_new(_("Keywords")); | |
188 gtk_notebook_append_page(GTK_NOTEBOOK(id->notebook), tab->bar_info, label); | |
271
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
189 notebook_set_tab_reorderable(GTK_NOTEBOOK(id->notebook), tab->bar_info, TRUE); |
9 | 190 gtk_widget_show(tab->bar_info); |
191 | |
192 /* register */ | |
193 td = g_new0(TabData, 1); | |
194 td->func_free = info_tab_meta_free; | |
195 td->func_sync = info_tab_meta_sync; | |
196 td->func_image = NULL; | |
197 td->data = tab; | |
221 | 198 td->func_new = info_tab_meta_new; |
199 td->child = tab->bar_info; | |
9 | 200 |
201 return td; | |
202 } | |
203 | |
204 /* | |
205 *------------------------------------------------------------------- | |
206 * general tab | |
207 *------------------------------------------------------------------- | |
208 */ | |
209 | |
210 typedef struct _InfoTabGeneral InfoTabGeneral; | |
211 struct _InfoTabGeneral | |
212 { | |
213 GtkWidget *label_file_time; | |
214 GtkWidget *label_file_size; | |
215 GtkWidget *label_dimensions; | |
216 GtkWidget *label_transparent; | |
217 GtkWidget *label_image_size; | |
218 GtkWidget *label_compression; | |
219 GtkWidget *label_mime_type; | |
220 | |
221 GtkWidget *label_user; | |
222 GtkWidget *label_group; | |
223 GtkWidget *label_perms; | |
224 | |
225 gint compression_done; | |
226 gint64 byte_size; | |
227 }; | |
228 | |
229 static void info_tab_general_image(InfoData *id, gpointer data) | |
230 { | |
231 InfoTabGeneral *tab = data; | |
232 gchar *buf; | |
233 guint mem_size; | |
234 gint has_alpha; | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
235 GdkPixbuf *pixbuf; |
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
236 gint width, height; |
9 | 237 |
238 if (id->image->unknown) return; | |
239 | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
240 pixbuf_renderer_get_image_size(PIXBUF_RENDERER(id->image->pr), &width, &height); |
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
241 |
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
242 buf = g_strdup_printf("%d x %d", width, height); |
9 | 243 gtk_label_set_text(GTK_LABEL(tab->label_dimensions), buf); |
244 g_free(buf); | |
245 | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
246 pixbuf = image_get_pixbuf(id->image); |
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
247 if (pixbuf) |
9 | 248 { |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
249 has_alpha = gdk_pixbuf_get_has_alpha(pixbuf); |
9 | 250 } |
251 else | |
252 { | |
253 has_alpha = FALSE; | |
254 } | |
255 gtk_label_set_text(GTK_LABEL(tab->label_transparent), has_alpha ? _("yes") : _("no")); | |
256 | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
257 mem_size = width * height * ((has_alpha) ? 4 : 3); |
9 | 258 buf = text_from_size_abrev(mem_size); |
259 gtk_label_set_text(GTK_LABEL(tab->label_image_size), buf); | |
260 g_free(buf); | |
261 | |
262 if (!tab->compression_done && mem_size > 0) | |
263 { | |
15
3263965d5f9e
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
264 buf = g_strdup_printf("%.1f%%", (double)tab->byte_size / mem_size * 100.0); |
9 | 265 gtk_label_set_text(GTK_LABEL(tab->label_compression), buf); |
266 g_free(buf); | |
267 | |
268 tab->compression_done = TRUE; | |
269 } | |
270 | |
271 buf = image_loader_get_format(id->image->il); | |
272 if (buf) | |
273 gtk_label_set_text(GTK_LABEL(tab->label_mime_type), buf); | |
274 g_free(buf); | |
275 } | |
276 | |
277 static gchar *mode_number(mode_t m) | |
278 { | |
279 int mb, mu, mg, mo; | |
280 | |
281 mb = mu = mg = mo = 0; | |
282 | |
283 if (m & S_ISUID) mb |= 4; | |
284 if (m & S_ISGID) mb |= 2; | |
285 if (m & S_ISVTX) mb |= 1; | |
286 | |
287 if (m & S_IRUSR) mu |= 4; | |
288 if (m & S_IWUSR) mu |= 2; | |
289 if (m & S_IXUSR) mu |= 1; | |
290 | |
291 if (m & S_IRGRP) mg |= 4; | |
292 if (m & S_IWGRP) mg |= 2; | |
293 if (m & S_IXGRP) mg |= 1; | |
294 | |
295 if (m & S_IROTH) mo |= 4; | |
296 if (m & S_IWOTH) mo |= 2; | |
297 if (m & S_IXOTH) mo |= 1; | |
298 | |
299 return g_strdup_printf("%d%d%d%d", mb, mu, mg, mo); | |
300 } | |
301 | |
302 static void info_tab_general_sync_perm(InfoTabGeneral *tab, InfoData *id) | |
303 { | |
304 struct stat st; | |
305 | |
138 | 306 if (!stat_utf8(id->fd->path, &st)) |
9 | 307 { |
308 gtk_label_set_text(GTK_LABEL(tab->label_user), ""); | |
309 gtk_label_set_text(GTK_LABEL(tab->label_group), ""); | |
310 gtk_label_set_text(GTK_LABEL(tab->label_perms), ""); | |
311 } | |
312 else | |
313 { | |
314 struct passwd *user; | |
315 struct group *grp; | |
316 gchar pbuf[12]; | |
317 gchar *pmod; | |
318 gchar *buf; | |
319 | |
320 user = getpwuid(st.st_uid); | |
321 gtk_label_set_text(GTK_LABEL(tab->label_user), (user) ? user->pw_name : ""); | |
322 | |
323 grp = getgrgid(st.st_gid); | |
324 gtk_label_set_text(GTK_LABEL(tab->label_group), (grp) ? grp->gr_name : ""); | |
325 | |
326 pbuf[0] = (st.st_mode & S_IRUSR) ? 'r' : '-'; | |
327 pbuf[1] = (st.st_mode & S_IWUSR) ? 'w' : '-'; | |
328 pbuf[2] = (st.st_mode & S_IXUSR) ? 'x' : '-'; | |
329 pbuf[3] = (st.st_mode & S_IRGRP) ? 'r' : '-'; | |
330 pbuf[4] = (st.st_mode & S_IWGRP) ? 'w' : '-'; | |
331 pbuf[5] = (st.st_mode & S_IXGRP) ? 'x' : '-'; | |
332 pbuf[6] = (st.st_mode & S_IROTH) ? 'r' : '-'; | |
333 pbuf[7] = (st.st_mode & S_IWOTH) ? 'w' : '-'; | |
334 pbuf[8] = (st.st_mode & S_IXOTH) ? 'x' : '-'; | |
335 pbuf[9] = '\0'; | |
336 | |
337 pmod = mode_number(st.st_mode); | |
338 buf = g_strdup_printf("%s (%s)", pbuf, pmod); | |
339 gtk_label_set_text(GTK_LABEL(tab->label_perms), buf); | |
340 g_free(buf); | |
341 g_free(pmod); | |
342 } | |
343 } | |
344 | |
345 static void info_tab_general_sync(InfoData *id, gpointer data) | |
346 { | |
347 InfoTabGeneral *tab = data; | |
348 gchar *buf; | |
349 | |
138 | 350 gtk_label_set_text(GTK_LABEL(tab->label_file_time), text_from_time(id->fd->date)); |
9 | 351 |
138 | 352 tab->byte_size = id->fd->size; |
9 | 353 |
354 buf = text_from_size(tab->byte_size); | |
355 gtk_label_set_text(GTK_LABEL(tab->label_file_size), buf); | |
356 g_free(buf); | |
357 | |
358 gtk_label_set_text(GTK_LABEL(tab->label_dimensions), ""); | |
359 gtk_label_set_text(GTK_LABEL(tab->label_transparent), ""); | |
360 gtk_label_set_text(GTK_LABEL(tab->label_image_size), ""); | |
361 | |
362 gtk_label_set_text(GTK_LABEL(tab->label_compression), ""); | |
363 gtk_label_set_text(GTK_LABEL(tab->label_mime_type), ""); | |
364 | |
365 info_tab_general_sync_perm(tab, id); | |
366 | |
367 tab->compression_done = FALSE; | |
368 } | |
369 | |
370 static void info_tab_general_free(gpointer data) | |
371 { | |
372 InfoTabGeneral *tab = data; | |
373 | |
374 g_free(tab); | |
375 } | |
376 | |
377 static TabData *info_tab_general_new(InfoData *id) | |
378 { | |
379 TabData *td; | |
380 InfoTabGeneral *tab; | |
381 GtkWidget *table; | |
382 GtkWidget *label; | |
383 | |
384 tab = g_new0(InfoTabGeneral, 1); | |
385 | |
386 table = pref_table_new(NULL, 2, 11, FALSE, FALSE); | |
387 gtk_container_set_border_width(GTK_CONTAINER(table), PREF_PAD_BORDER); | |
388 | |
389 tab->label_file_time = table_add_line(table, 0, 0, _("File date:"), NULL); | |
390 tab->label_file_size = table_add_line(table, 0, 1, _("File size:"), NULL); | |
391 | |
392 tab->label_dimensions = table_add_line(table, 0, 2, _("Dimensions:"), NULL); | |
393 tab->label_transparent = table_add_line(table, 0, 3, _("Transparent:"), NULL); | |
394 tab->label_image_size = table_add_line(table, 0, 4, _("Image size:"), NULL); | |
395 | |
396 tab->label_compression = table_add_line(table, 0, 5, _("Compress ratio:"), NULL); | |
397 tab->label_mime_type = table_add_line(table, 0, 6, _("File type:"), NULL); | |
398 | |
399 tab->label_user = table_add_line(table, 0, 7, _("Owner:"), NULL); | |
400 tab->label_group = table_add_line(table, 0, 8, _("Group:"), NULL); | |
401 tab->label_perms = table_add_line(table, 0, 9, "", NULL); | |
402 | |
403 label = gtk_label_new(_("General")); | |
404 gtk_notebook_append_page(GTK_NOTEBOOK(id->notebook), table, label); | |
271
35f9083c6b95
gtk_notebook_set_tab_reorderable() is only available sinc gtk+ 2.10.
zas_
parents:
254
diff
changeset
|
405 notebook_set_tab_reorderable(GTK_NOTEBOOK(id->notebook), table, TRUE); |
9 | 406 gtk_widget_show(table); |
407 | |
408 /* register */ | |
409 td = g_new0(TabData, 1); | |
410 td->func_free = info_tab_general_free; | |
411 td->func_sync = info_tab_general_sync; | |
412 td->func_image = info_tab_general_image; | |
413 td->data = tab; | |
221 | 414 td->func_new = info_tab_general_new; |
415 td->child = table; | |
9 | 416 |
417 return td; | |
418 } | |
419 | |
420 /* | |
421 *------------------------------------------------------------------- | |
422 * tabs | |
423 *------------------------------------------------------------------- | |
424 */ | |
425 | |
426 static void info_tabs_sync(InfoData *id, gint image) | |
427 { | |
428 GList *work; | |
429 | |
430 work = id->tab_list; | |
431 while (work) | |
432 { | |
433 TabData *td = work->data; | |
434 work = work->next; | |
435 | |
436 if (image) | |
437 { | |
438 if (td->func_image) td->func_image(id, td->data); | |
439 } | |
440 else | |
441 { | |
442 if (td->func_sync) td->func_sync(id, td->data); | |
443 } | |
444 } | |
445 } | |
446 | |
447 static void info_tabs_free(InfoData *id) | |
448 { | |
449 GList *work; | |
450 | |
451 work = id->tab_list; | |
452 while (work) | |
453 { | |
454 TabData *td = work->data; | |
455 work = work->next; | |
456 | |
457 if (td->func_free) td->func_free(td->data); | |
458 g_free(td); | |
459 } | |
460 g_list_free(id->tab_list); | |
461 id->tab_list = NULL; | |
462 } | |
463 | |
221 | 464 static InfoTabsPos *info_tabs_pos_new(gpointer func, gint pos) |
465 { | |
466 InfoTabsPos *t = g_new0(InfoTabsPos, 1); | |
467 t->func = func; | |
468 t->pos = pos; | |
469 | |
470 return t; | |
471 } | |
472 | |
473 static void info_tabs_pos_list_append(gpointer func) | |
474 { | |
475 static gint pos = 0; | |
476 | |
477 info_tabs_pos_list = g_list_append(info_tabs_pos_list, info_tabs_pos_new(func, pos++)); | |
478 } | |
479 | |
480 static gint compare_info_tabs_pos(gconstpointer a, gconstpointer b) | |
481 { | |
482 InfoTabsPos *ta = (InfoTabsPos *) a; | |
483 InfoTabsPos *tb = (InfoTabsPos *) b; | |
484 | |
485 if (ta->pos > tb->pos) return 1; | |
486 return -1; | |
487 } | |
488 | |
9 | 489 static void info_tabs_init(InfoData *id) |
490 { | |
221 | 491 GList *work; |
492 | |
493 if (!info_tabs_pos_list) | |
494 { | |
495 /* First run, default tabs order is defined here. */ | |
496 info_tabs_pos_list_append(info_tab_general_new); | |
497 info_tabs_pos_list_append(info_tab_meta_new); | |
498 info_tabs_pos_list_append(info_tab_exif_new); | |
499 } | |
500 else | |
501 info_tabs_pos_list = g_list_sort(info_tabs_pos_list, compare_info_tabs_pos); | |
502 | |
503 work = info_tabs_pos_list; | |
504 while (work) | |
505 { | |
506 InfoTabsPos *t = work->data; | |
507 work = work->next; | |
508 | |
509 id->tab_list = g_list_append(id->tab_list, t->func(id)); | |
510 } | |
9 | 511 } |
512 | |
513 /* | |
514 *------------------------------------------------------------------- | |
515 * sync | |
516 *------------------------------------------------------------------- | |
517 */ | |
518 | |
138 | 519 static void info_window_sync(InfoData *id, FileData *fd) |
9 | 520 { |
521 | |
138 | 522 if (!fd) return; |
9 | 523 |
138 | 524 gtk_entry_set_text(GTK_ENTRY(id->name_entry), fd->name); |
9 | 525 |
526 if (id->label_count) | |
527 { | |
528 gchar *buf; | |
529 buf = g_strdup_printf(_("Image %d of %d"), | |
219
92d2444893b8
Fix display of image number in properties dialog when more than one image is selected.
zas_
parents:
196
diff
changeset
|
530 g_list_index(id->list, (gpointer)fd) + 1, |
9 | 531 g_list_length(id->list)); |
532 gtk_label_set_text(GTK_LABEL(id->label_count), buf); | |
533 g_free(buf); | |
534 } | |
535 | |
536 info_tabs_sync(id, FALSE); | |
537 | |
538 id->updated = FALSE; | |
138 | 539 image_change_fd(id->image, fd, 0.0); |
9 | 540 } |
541 | |
221 | 542 static void info_notebook_reordered_cb(GtkNotebook *notebook, GtkWidget *child, guint page_num, gpointer data) |
543 { | |
544 InfoData *id = data; | |
545 GList *work; | |
546 | |
547 info_tabs_sync(id, 0); | |
548 | |
549 /* Save current tabs position to be able to restore them later. */ | |
550 work = id->tab_list; | |
551 while (work) | |
552 { | |
553 GList *tabpos; | |
554 TabData *td = work->data; | |
555 gint pos = gtk_notebook_page_num(GTK_NOTEBOOK(id->notebook), GTK_WIDGET(td->child)); | |
556 work = work->next; | |
557 | |
558 tabpos = info_tabs_pos_list; | |
559 while (tabpos) | |
560 { | |
561 InfoTabsPos *t = tabpos->data; | |
562 tabpos = tabpos->next; | |
563 | |
564 if (t->func == td->func_new) | |
565 { | |
566 t->pos = pos; | |
567 break; | |
568 } | |
569 } | |
570 } | |
571 } | |
572 | |
9 | 573 /* |
574 *------------------------------------------------------------------- | |
575 * drag n drop (dropping not supported!) | |
576 *------------------------------------------------------------------- | |
577 */ | |
578 | |
579 static void info_window_dnd_data_set(GtkWidget *widget, GdkDragContext *context, | |
580 GtkSelectionData *selection_data, guint info, | |
581 guint time, gpointer data) | |
582 { | |
583 InfoData *id = data; | |
138 | 584 FileData *fd; |
9 | 585 |
138 | 586 fd = image_get_fd(id->image); |
587 if (fd) | |
9 | 588 { |
589 gchar *text; | |
590 gint len; | |
591 GList *list; | |
592 gint plain_text; | |
593 | |
594 switch (info) | |
595 { | |
596 case TARGET_URI_LIST: | |
597 plain_text = FALSE; | |
598 break; | |
599 case TARGET_TEXT_PLAIN: | |
600 default: | |
601 plain_text = TRUE; | |
602 break; | |
603 } | |
138 | 604 list = g_list_append(NULL, fd); |
605 text = uri_text_from_filelist(list, &len, plain_text); | |
9 | 606 g_list_free(list); |
607 | |
608 gtk_selection_data_set(selection_data, selection_data->target, | |
64
04ff0df3ad2f
Mon Aug 15 17:13:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
23
diff
changeset
|
609 8, (guchar *)text, len); |
9 | 610 g_free(text); |
611 } | |
612 } | |
613 | |
614 static void info_window_dnd_init(InfoData *id) | |
615 { | |
616 ImageWindow *imd; | |
617 | |
618 imd = id->image; | |
619 | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
620 gtk_drag_source_set(imd->pr, GDK_BUTTON2_MASK, |
9 | 621 dnd_file_drag_types, dnd_file_drag_types_count, |
622 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
623 g_signal_connect(G_OBJECT(imd->pr), "drag_data_get", |
9 | 624 G_CALLBACK(info_window_dnd_data_set), id); |
625 | |
626 #if 0 | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
627 gtk_drag_dest_set(imd->pr, |
9 | 628 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, |
629 dnd_file_drop_types, dnd_file_drop_types_count, | |
630 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
23
17acca639a86
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
15
diff
changeset
|
631 g_signal_connect(G_OBJECT(imd->pr), "drag_data_received", |
9 | 632 G_CALLBACK(info_window_dnd_data_get), id); |
633 #endif | |
634 } | |
635 | |
636 /* | |
637 *------------------------------------------------------------------- | |
638 * base window | |
639 *------------------------------------------------------------------- | |
640 */ | |
641 | |
642 static gint info_window_last_width = DEF_PROPERTY_WIDTH; | |
643 static gint info_window_last_height = DEF_PROPERTY_HEIGHT; | |
644 | |
645 static void info_window_image_update_cb(ImageWindow *imd, gpointer data) | |
646 { | |
647 InfoData *id = data; | |
648 | |
649 /* only do this once after when loading a new image, | |
650 * for tabs that depend on image data (exif) | |
651 * Subsequent updates are ignored, as the image | |
652 * should not really changed if id->updated is TRUE. | |
653 */ | |
654 | |
655 if (id->updated) return; | |
656 if (imd->unknown) return; | |
657 | |
658 info_tabs_sync(id, TRUE); | |
659 id->updated = TRUE; | |
660 } | |
661 | |
662 static void info_window_back_cb(GtkWidget *widget, gpointer data) | |
663 { | |
664 InfoData *id = data; | |
665 GList *work; | |
666 | |
138 | 667 work = g_list_find(id->list, (gpointer)id->fd); |
9 | 668 if (!work || !work->prev) return; |
669 | |
670 work = work->prev; | |
138 | 671 id->fd = work->data; |
9 | 672 |
138 | 673 info_window_sync(id, id->fd); |
9 | 674 |
675 gtk_widget_set_sensitive(id->button_back, (work->prev != NULL)); | |
676 gtk_widget_set_sensitive(id->button_next, TRUE); | |
677 } | |
678 | |
679 static void info_window_next_cb(GtkWidget *widget, gpointer data) | |
680 { | |
681 InfoData *id = data; | |
682 GList *work; | |
683 | |
138 | 684 work = g_list_find(id->list, (gpointer)id->fd); |
9 | 685 if (!work || !work->next) return; |
686 | |
687 work = work->next; | |
138 | 688 id->fd = work->data; |
9 | 689 |
138 | 690 info_window_sync(id, id->fd); |
9 | 691 |
692 gtk_widget_set_sensitive(id->button_next, (work->next != NULL)); | |
693 gtk_widget_set_sensitive(id->button_back, TRUE); | |
694 } | |
695 | |
696 static void info_window_image_button_cb(ImageWindow *imd, gint button, guint32 time, | |
697 gdouble x, gdouble y, guint state, gpointer data) | |
698 { | |
699 if (button == 1) | |
700 { | |
701 info_window_next_cb(NULL, data); | |
702 } | |
703 else if (button == 2 || button == 3) | |
704 { | |
705 info_window_back_cb(NULL, data); | |
706 } | |
707 } | |
708 | |
709 static void info_window_image_scroll_cb(ImageWindow *imd, GdkScrollDirection direction, guint32 time, | |
710 gdouble x, gdouble y, guint state, gpointer data) | |
711 { | |
712 if (direction == GDK_SCROLL_UP) | |
713 { | |
714 info_window_back_cb(NULL, data); | |
715 } | |
716 else if (direction == GDK_SCROLL_DOWN) | |
717 { | |
718 info_window_next_cb(NULL, data); | |
719 } | |
720 } | |
721 | |
722 static void info_window_close(InfoData *id) | |
723 { | |
724 gdk_drawable_get_size(id->window->window, &info_window_last_width, &info_window_last_height); | |
725 info_window_last_width = MAX(info_window_last_width, DEF_PROPERTY_WIDTH); | |
726 info_window_last_height = MAX(info_window_last_height, DEF_PROPERTY_HEIGHT); | |
727 | |
728 gtk_widget_destroy(id->window); | |
729 } | |
730 | |
731 static void info_window_close_cb(GtkWidget *widget, gpointer data) | |
732 { | |
733 InfoData *id = data; | |
734 | |
735 info_window_close(id); | |
736 } | |
737 | |
738 static gint info_window_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data) | |
739 { | |
740 InfoData *id = data; | |
741 | |
742 info_window_close(id); | |
743 return TRUE; | |
744 } | |
745 | |
746 static void info_window_destroy_cb(GtkWidget *widget, gpointer data) | |
747 { | |
748 InfoData *id = data; | |
749 | |
750 info_tabs_free(id); | |
138 | 751 filelist_free(id->list); |
9 | 752 g_free(id); |
753 } | |
754 | |
138 | 755 void info_window_new(FileData *fd, GList *list) |
9 | 756 { |
757 InfoData *id; | |
758 GtkWidget *main_vbox; | |
759 GtkWidget *paned; | |
760 GtkWidget *hbox; | |
761 GtkWidget *button; | |
762 GtkWidget *label; | |
763 GdkGeometry geometry; | |
764 | |
138 | 765 if (!fd && !list) return; |
9 | 766 |
767 if (!list) | |
768 { | |
138 | 769 list = g_list_append(NULL, file_data_ref(fd)); |
9 | 770 } |
771 | |
772 id = g_new0(InfoData, 1); | |
773 | |
774 id->list = list; | |
138 | 775 id->fd = (FileData *)id->list->data; |
9 | 776 id->updated = FALSE; |
777 | |
778 id->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
779 gtk_window_set_type_hint(GTK_WINDOW(id->window), GDK_WINDOW_TYPE_HINT_DIALOG); | |
780 window_set_icon(id->window, NULL, NULL); | |
781 | |
782 gtk_window_set_resizable(GTK_WINDOW(id->window), TRUE); | |
196 | 783 gtk_window_set_title(GTK_WINDOW(id->window), _("Image properties - Geeqie")); |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
221
diff
changeset
|
784 gtk_window_set_wmclass(GTK_WINDOW(id->window), "properties", GQ_WMCLASS); |
9 | 785 |
786 geometry.min_width = 32; | |
787 geometry.min_height = 32; | |
788 geometry.base_width = DEF_PROPERTY_WIDTH; | |
789 geometry.base_height = DEF_PROPERTY_HEIGHT; | |
790 gtk_window_set_geometry_hints(GTK_WINDOW(id->window), NULL, &geometry, | |
791 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); | |
792 | |
793 | |
794 gtk_window_set_default_size(GTK_WINDOW(id->window), info_window_last_width, info_window_last_height); | |
795 gtk_container_set_border_width(GTK_CONTAINER(id->window), PREF_PAD_BORDER); | |
796 | |
797 g_signal_connect(G_OBJECT(id->window), "delete_event", | |
798 G_CALLBACK(info_window_delete_cb), id); | |
799 g_signal_connect(G_OBJECT(id->window), "destroy", | |
800 G_CALLBACK(info_window_destroy_cb), id); | |
801 | |
802 paned = gtk_hpaned_new(); | |
803 gtk_container_add(GTK_CONTAINER(id->window), paned); | |
804 gtk_widget_show(paned); | |
805 | |
806 id->image = image_new(FALSE); | |
807 image_set_update_func(id->image, info_window_image_update_cb, id); | |
808 | |
809 image_set_button_func(id->image, info_window_image_button_cb, id); | |
810 image_set_scroll_func(id->image, info_window_image_scroll_cb, id); | |
811 | |
812 gtk_widget_set_size_request(id->image->widget, IMAGE_SIZE_W, IMAGE_SIZE_H); | |
813 gtk_paned_pack1(GTK_PANED(paned), id->image->widget, FALSE, TRUE); | |
814 gtk_widget_show(id->image->widget); | |
815 | |
816 main_vbox = gtk_vbox_new(FALSE, 0); | |
817 gtk_paned_pack2(GTK_PANED(paned), main_vbox, TRUE, TRUE); | |
818 gtk_widget_show(main_vbox); | |
819 | |
820 hbox = pref_box_new(main_vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | |
821 label = pref_label_new(hbox, _("Filename:")); | |
822 pref_label_bold(label, TRUE, FALSE); | |
823 | |
824 id->name_entry = gtk_entry_new(); | |
825 gtk_editable_set_editable(GTK_EDITABLE(id->name_entry), FALSE); | |
826 gtk_box_pack_start(GTK_BOX(hbox), id->name_entry, TRUE, TRUE, 0); | |
827 gtk_widget_show(id->name_entry); | |
828 | |
829 id->notebook = gtk_notebook_new(); | |
830 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(id->notebook), GTK_POS_TOP); | |
831 gtk_box_pack_start(GTK_BOX(main_vbox), id->notebook, TRUE, TRUE, 5); | |
221 | 832 g_signal_connect(G_OBJECT(id->notebook), "page-reordered", |
833 G_CALLBACK(info_notebook_reordered_cb), id); | |
834 | |
9 | 835 gtk_widget_show(id->notebook); |
836 | |
837 pref_spacer(main_vbox, PREF_PAD_GAP); | |
838 | |
839 hbox = pref_box_new(main_vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
840 | |
841 id->button_back = pref_button_new(hbox, GTK_STOCK_GO_BACK, NULL, TRUE, | |
842 G_CALLBACK(info_window_back_cb), id); | |
843 gtk_widget_set_sensitive(id->button_back, FALSE); | |
844 | |
845 id->button_next = pref_button_new(hbox, GTK_STOCK_GO_FORWARD, NULL, TRUE, | |
846 G_CALLBACK(info_window_next_cb), id); | |
847 gtk_widget_set_sensitive(id->button_next, (id->list->next != NULL)); | |
848 | |
849 if (id->list->next) | |
850 { | |
851 id->label_count = pref_label_new(hbox, ""); | |
852 } | |
853 | |
854 button = pref_button_new(NULL, GTK_STOCK_CLOSE, NULL, FALSE, | |
855 G_CALLBACK(info_window_close_cb), id); | |
856 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
857 gtk_widget_show(button); | |
858 | |
859 /* set up tabs */ | |
860 | |
861 info_tabs_init(id); | |
862 | |
863 /* fill it */ | |
864 | |
138 | 865 info_window_sync(id, id->fd); |
9 | 866 |
867 /* finish */ | |
868 | |
869 info_window_dnd_init(id); | |
870 | |
871 gtk_widget_show(id->window); | |
872 } | |
873 |