2a6c26a41b979f9f17cc706f494cff816581be68
[geeqie.git] / src / collect-dlg.cc
1 /*
2  * Copyright (C) 2004 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: John Ellis
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <memory>
23
24 #include "main.h"
25 #include "collect.h"
26 #include "collect-dlg.h"
27
28 #include "collect-io.h"
29 #include "utilops.h"
30 #include "ui-fileops.h"
31
32 enum {
33         DIALOG_SAVE,
34         DIALOG_SAVE_CLOSE,
35         DIALOG_LOAD,
36         DIALOG_APPEND
37 };
38
39
40 static gboolean collection_save_confirmed(FileDialog *fd, gboolean overwrite, CollectionData *cd);
41
42
43 static void collection_confirm_ok_cb(GenericDialog *UNUSED(gd), gpointer data)
44 {
45         auto fd = static_cast<FileDialog *>(data);
46         auto cd = static_cast<CollectionData *>(GENERIC_DIALOG(fd)->data);
47
48         if (!collection_save_confirmed(fd, TRUE, cd))
49                 {
50                 collection_unref(cd);
51                 file_dialog_close(fd);
52                 }
53 }
54
55 static void collection_confirm_cancel_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
56 {
57         /* this is a no-op, so the cancel button is added */
58 }
59
60 static gboolean collection_save_confirmed(FileDialog *fd, gboolean overwrite, CollectionData *cd)
61 {
62         gchar *buf;
63
64         if (isdir(fd->dest_path))
65                 {
66                 buf = g_strdup_printf(_("Specified path:\n%s\nis a folder, collections are files"), fd->dest_path);
67                 file_util_warning_dialog(_("Invalid filename"), buf, GTK_STOCK_DIALOG_INFO, GENERIC_DIALOG(fd)->dialog);
68                 g_free(buf);
69                 return FALSE;
70                 }
71
72         if (!overwrite && isfile(fd->dest_path))
73                 {
74                 GenericDialog *gd;
75
76                 gd = file_util_gen_dlg(_("Overwrite File"), "dlg_confirm",
77                                         GENERIC_DIALOG(fd)->dialog, TRUE,
78                                         collection_confirm_cancel_cb, fd);
79
80                 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION,
81                                            _("Overwrite existing file?"), fd->dest_path, TRUE);
82
83                 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), collection_confirm_ok_cb, TRUE);
84
85                 gtk_widget_show(gd->dialog);
86
87                 return TRUE;
88                 }
89
90         if (!collection_save(cd, fd->dest_path))
91                 {
92                 buf = g_strdup_printf(_("Failed to save the collection:\n%s"), fd->dest_path);
93                 file_util_warning_dialog(_("Save Failed"), buf, GTK_STOCK_DIALOG_ERROR, GENERIC_DIALOG(fd)->dialog);
94                 g_free(buf);
95                 }
96
97         collection_unref(cd);
98         file_dialog_sync_history(fd, TRUE);
99
100         if (fd->type == DIALOG_SAVE_CLOSE) collection_window_close_by_collection(cd);
101         file_dialog_close(fd);
102
103         return TRUE;
104 }
105
106 static void collection_save_cb(FileDialog *fd, gpointer data)
107 {
108         auto cd = static_cast<CollectionData *>(data);
109         const gchar *path;
110
111         path = fd->dest_path;
112
113         /** @FIXME utf8 */
114         if (!file_extension_match(path, GQ_COLLECTION_EXT))
115                 {
116                 gchar *buf;
117                 buf = g_strconcat(path, GQ_COLLECTION_EXT, NULL);
118                 gtk_entry_set_text(GTK_ENTRY(fd->entry), buf);
119                 g_free(buf);
120                 }
121
122         collection_save_confirmed(fd, FALSE, cd);
123 }
124
125 static void real_collection_button_pressed(FileDialog *fd, gpointer data, gint append)
126 {
127         auto cd = static_cast<CollectionData *>(data);
128         gboolean err = FALSE;
129         std::unique_ptr<gchar, decltype(&g_free)> text{nullptr, g_free};
130
131         if (!isname(fd->dest_path))
132                 {
133                 err = TRUE;
134                 text.reset(g_strdup_printf(_("No such file '%s'."), fd->dest_path));
135                 }
136         if (!err && isdir(fd->dest_path))
137                 {
138                 err = TRUE;
139                 text.reset(g_strdup_printf(_("'%s' is a directory, not a collection file."), fd->dest_path));
140                 }
141         if (!err && !access_file(fd->dest_path, R_OK))
142                 {
143                 err = TRUE;
144                 text.reset(g_strdup_printf(_("You do not have read permissions on the file '%s'."), fd->dest_path));
145                 }
146
147         if (err)
148                 {
149                 if (text)
150                         {
151                         file_util_warning_dialog(_("Can not open collection file"), text.get(), GTK_STOCK_DIALOG_ERROR, nullptr);
152                         }
153                 return;
154                 }
155
156         if (append)
157                 {
158                 collection_load(cd, fd->dest_path, COLLECTION_LOAD_APPEND);
159                 collection_unref(cd);
160                 }
161         else
162                 {
163                 collection_window_new(fd->dest_path);
164                 }
165
166         file_dialog_sync_history(fd, TRUE);
167         file_dialog_close(fd);
168 }
169
170 static void collection_load_cb(FileDialog *fd, gpointer data)
171 {
172         real_collection_button_pressed(fd, data, FALSE);
173 }
174
175 static void collection_append_cb(FileDialog *fd, gpointer data)
176 {
177         real_collection_button_pressed(fd, data, TRUE);
178 }
179
180 static void collection_save_or_load_dialog_close_cb(FileDialog *fd, gpointer data)
181 {
182         auto cd = static_cast<CollectionData *>(data);
183
184         if (cd) collection_unref(cd);
185         file_dialog_close(fd);
186 }
187
188 static void collection_save_or_load_dialog(const gchar *path,
189                                            gint type, CollectionData *cd)
190 {
191         FileDialog *fd;
192         GtkWidget *parent = nullptr;
193         CollectWindow *cw;
194         const gchar *title;
195         const gchar *btntext;
196         gpointer btnfunc;
197         const gchar *stock_id;
198
199         if (type == DIALOG_SAVE || type == DIALOG_SAVE_CLOSE)
200                 {
201                 if (!cd) return;
202                 title = _("Save collection");
203                 btntext = nullptr;
204                 btnfunc = reinterpret_cast<gpointer>(collection_save_cb);
205                 stock_id = GTK_STOCK_SAVE;
206                 }
207         else if (type == DIALOG_LOAD)
208                 {
209                 title = _("Open collection");
210                 btntext = nullptr;
211                 btnfunc = reinterpret_cast<gpointer>(collection_load_cb);
212                 stock_id = GTK_STOCK_OPEN;
213                 }
214         else
215                 {
216                 if (!cd) return;
217                 title = _("Append collection");
218                 btntext = _("_Append");
219                 btnfunc = reinterpret_cast<gpointer>(collection_append_cb);
220                 stock_id = GTK_STOCK_ADD;
221                 }
222
223         if (cd) collection_ref(cd);
224
225         cw = collection_window_find(cd);
226         if (cw) parent = cw->window;
227
228         fd = file_util_file_dlg(title, "dlg_collection", parent,
229                              collection_save_or_load_dialog_close_cb, cd);
230
231         generic_dialog_add_message(GENERIC_DIALOG(fd), nullptr, title, nullptr, FALSE);
232         file_dialog_add_button(fd, stock_id, btntext, reinterpret_cast<void (*)(FileDialog *, gpointer)>(btnfunc), TRUE);
233
234         file_dialog_add_path_widgets(fd, get_collections_dir(), path,
235                                      "collection_load_save", GQ_COLLECTION_EXT, _("Collection Files"));
236
237         fd->type = type;
238
239         gtk_widget_show(GENERIC_DIALOG(fd)->dialog);
240 }
241
242 void collection_dialog_save_as(gchar *path, CollectionData *cd)
243 {
244         if (!path) path = cd->path;
245         if (!path) path = cd->name;
246
247         collection_save_or_load_dialog(path, DIALOG_SAVE, cd);
248 }
249
250 void collection_dialog_save_close(gchar *path, CollectionData *cd)
251 {
252         if (!path) path = cd->path;
253         if (!path) path = cd->name;
254
255         collection_save_or_load_dialog(path, DIALOG_SAVE_CLOSE, cd);
256 }
257
258 void collection_dialog_load(gchar *path)
259 {
260         collection_save_or_load_dialog(path, DIALOG_LOAD, nullptr);
261 }
262
263 void collection_dialog_append(gchar *path, CollectionData *cd)
264 {
265         collection_save_or_load_dialog(path, DIALOG_APPEND, cd);
266 }
267 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */