Mercurial > geeqie.yaz
annotate src/collect-dlg.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 | 9faf34f047b1 |
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 "collect.h" | |
15 #include "collect-dlg.h" | |
16 | |
17 #include "collect-io.h" | |
18 #include "utilops.h" | |
19 #include "ui_fileops.h" | |
20 #include "ui_tabcomp.h" | |
21 #include "ui_utildlg.h" | |
22 | |
23 | |
24 enum { | |
25 DIALOG_SAVE, | |
26 DIALOG_SAVE_CLOSE, | |
27 DIALOG_LOAD, | |
28 DIALOG_APPEND | |
29 }; | |
30 | |
31 | |
32 static gint collection_save_confirmed(FileDialog *fd, gint overwrite, CollectionData *cd); | |
33 | |
34 | |
35 static void collection_confirm_ok_cb(GenericDialog *gd, gpointer data) | |
36 { | |
37 FileDialog *fd = data; | |
38 CollectionData *cd = GENERIC_DIALOG(fd)->data; | |
39 | |
40 if (!collection_save_confirmed(fd, TRUE, cd)) | |
41 { | |
42 collection_unref(cd); | |
43 file_dialog_close(fd); | |
44 } | |
45 } | |
46 | |
47 static void collection_confirm_cancel_cb(GenericDialog *gd, gpointer data) | |
48 { | |
49 /* this is a no-op, so the cancel button is added */ | |
50 } | |
51 | |
52 static gint collection_save_confirmed(FileDialog *fd, gint overwrite, CollectionData *cd) | |
53 { | |
54 gchar *buf; | |
55 | |
56 if (isdir(fd->dest_path)) | |
57 { | |
58 buf = g_strdup_printf(_("Specified path:\n%s\nis a folder, collections are files"), fd->dest_path); | |
59 file_util_warning_dialog(_("Invalid filename"), buf, GTK_STOCK_DIALOG_INFO, GENERIC_DIALOG(fd)->dialog); | |
60 g_free(buf); | |
61 return FALSE; | |
62 } | |
63 | |
64 if (!overwrite && isfile(fd->dest_path)) | |
65 { | |
66 GenericDialog *gd; | |
67 | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
196
diff
changeset
|
68 gd = file_util_gen_dlg(_("Overwrite File"), GQ_WMCLASS, "dlg_confirm", |
9 | 69 GENERIC_DIALOG(fd)->dialog, TRUE, |
70 collection_confirm_cancel_cb, fd); | |
71 | |
72 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, | |
73 _("Overwrite existing file?"), fd->dest_path); | |
74 | |
75 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), collection_confirm_ok_cb, TRUE); | |
76 | |
77 gtk_widget_show(gd->dialog); | |
78 | |
79 return TRUE; | |
80 } | |
81 | |
82 if (!collection_save(cd, fd->dest_path)) | |
83 { | |
84 buf = g_strdup_printf(_("Failed to save the collection:\n%s"), fd->dest_path); | |
85 file_util_warning_dialog(_("Save Failed"), buf, GTK_STOCK_DIALOG_ERROR, GENERIC_DIALOG(fd)->dialog); | |
86 g_free(buf); | |
87 } | |
88 | |
89 collection_unref(cd); | |
90 file_dialog_sync_history(fd, TRUE); | |
91 | |
92 if (fd->type == DIALOG_SAVE_CLOSE) collection_window_close_by_collection(cd); | |
93 file_dialog_close(fd); | |
94 | |
95 return TRUE; | |
96 } | |
97 | |
98 static void collection_save_cb(FileDialog *fd, gpointer data) | |
99 { | |
100 CollectionData *cd = data; | |
101 const gchar *path; | |
102 | |
103 path = fd->dest_path; | |
104 | |
105 if (!(strlen(path) > 7 && strncasecmp(path + (strlen(path) - 4), ".gqv", 4) == 0)) | |
106 { | |
107 gchar *buf; | |
108 buf = g_strconcat(path, ".gqv", NULL); | |
109 gtk_entry_set_text(GTK_ENTRY(fd->entry), buf); | |
110 g_free(buf); | |
111 } | |
112 | |
113 collection_save_confirmed(fd, FALSE, cd); | |
114 } | |
115 | |
116 static void real_collection_button_pressed(FileDialog *fd, gpointer data, gint append) | |
117 { | |
118 CollectionData *cd = data; | |
119 | |
120 if (!fd->dest_path || isdir(fd->dest_path)) return; | |
121 | |
122 if (append) | |
123 { | |
124 collection_load(cd, fd->dest_path, TRUE); | |
125 collection_unref(cd); | |
126 } | |
127 else | |
128 { | |
129 collection_window_new(fd->dest_path); | |
130 } | |
131 | |
132 file_dialog_sync_history(fd, TRUE); | |
133 file_dialog_close(fd); | |
134 } | |
135 | |
136 static void collection_load_cb(FileDialog *fd, gpointer data) | |
137 { | |
138 real_collection_button_pressed(fd, data, FALSE); | |
139 } | |
140 | |
141 static void collection_append_cb(FileDialog *fd, gpointer data) | |
142 { | |
143 real_collection_button_pressed(fd, data, TRUE); | |
144 } | |
145 | |
146 static void collection_save_or_load_dialog_close_cb(FileDialog *fd, gpointer data) | |
147 { | |
148 CollectionData *cd = data; | |
149 | |
150 if (cd) collection_unref(cd); | |
151 file_dialog_close(fd); | |
152 } | |
153 | |
154 static void collection_save_or_load_dialog(const gchar *path, | |
155 gint type, CollectionData *cd) | |
156 { | |
157 FileDialog *fd; | |
158 GtkWidget *parent = NULL; | |
159 CollectWindow *cw; | |
160 const gchar *title; | |
161 const gchar *btntext; | |
162 void *btnfunc; | |
163 gchar *base; | |
164 const gchar *stock_id; | |
165 | |
166 if (type == DIALOG_SAVE || type == DIALOG_SAVE_CLOSE) | |
167 { | |
168 if (!cd) return; | |
169 title = _("Save collection"); | |
170 btntext = NULL; | |
171 btnfunc = collection_save_cb; | |
172 stock_id = GTK_STOCK_SAVE; | |
173 } | |
174 else if (type == DIALOG_LOAD) | |
175 { | |
176 title = _("Open collection"); | |
177 btntext = NULL; | |
178 btnfunc = collection_load_cb; | |
179 stock_id = GTK_STOCK_OPEN; | |
180 } | |
181 else | |
182 { | |
183 if (!cd) return; | |
184 title = _("Append collection"); | |
185 btntext = _("_Append"); | |
186 btnfunc = collection_append_cb; | |
187 stock_id = GTK_STOCK_ADD; | |
188 } | |
189 | |
190 if (cd) collection_ref(cd); | |
191 | |
192 cw = collection_window_find(cd); | |
193 if (cw) parent = cw->window; | |
194 | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
196
diff
changeset
|
195 fd = file_util_file_dlg(title, GQ_WMCLASS, "dlg_collection", parent, |
9 | 196 collection_save_or_load_dialog_close_cb, cd); |
197 | |
198 generic_dialog_add_message(GENERIC_DIALOG(fd), NULL, title, NULL); | |
199 file_dialog_add_button(fd, stock_id, btntext, btnfunc, TRUE); | |
200 | |
201 base = g_strconcat(homedir(), "/", GQVIEW_RC_DIR_COLLECTIONS, NULL); | |
202 file_dialog_add_path_widgets(fd, base, path, | |
203 "collection_load_save", ".gqv", _("Collection Files")); | |
204 g_free(base); | |
205 | |
206 fd->type = type; | |
207 | |
208 gtk_widget_show(GENERIC_DIALOG(fd)->dialog); | |
209 } | |
210 | |
211 void collection_dialog_save_as(gchar *path, CollectionData *cd) | |
212 { | |
213 #if 0 | |
214 if (!cd->list) | |
215 { | |
216 GtkWidget *parent = NULL; | |
217 CollectWindow *cw; | |
218 | |
219 cw = collection_window_find(cd); | |
220 if (cw) parent = cw->window; | |
221 file_util_warning_dialog(_("Collection empty"), | |
222 _("The current collection is empty, save aborted."), | |
223 GTK_STOCK_DIALOG_INFO, parent); | |
224 return; | |
225 } | |
226 #endif | |
227 | |
228 if (!path) path = cd->path; | |
229 if (!path) path = cd->name; | |
230 | |
231 collection_save_or_load_dialog(path, DIALOG_SAVE, cd); | |
232 } | |
233 | |
234 void collection_dialog_save_close(gchar *path, CollectionData *cd) | |
235 { | |
236 if (!path) path = cd->path; | |
237 if (!path) path = cd->name; | |
238 | |
239 collection_save_or_load_dialog(path, DIALOG_SAVE_CLOSE, cd); | |
240 } | |
241 | |
242 void collection_dialog_load(gchar *path) | |
243 { | |
244 collection_save_or_load_dialog(path, DIALOG_LOAD, NULL); | |
245 } | |
246 | |
247 void collection_dialog_append(gchar *path, CollectionData *cd) | |
248 { | |
249 collection_save_or_load_dialog(path, DIALOG_APPEND, cd); | |
250 } | |
251 |