2d31a883d3b3448deb8deb476d117fa938a3f90c
[claws.git] / src / plugins / rssyl / rssyl_cb_menu.c
1 /*
2  * Claws-Mail-- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2004 Hiroyuki Yamamoto
4  * This file (C) 2005 Andrej Kacian <andrej@kacian.sk>
5  *
6  * - callback handler functions for folderview rssyl context menu items
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 2 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, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 /* Global includes */
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <gtk/gtk.h>
31
32 /* Claws Mail includes */
33 #include <folderview.h>
34 #include <alertpanel.h>
35 #include <gtk/inputdialog.h>
36 #include <prefs_common.h>
37 #include <folder_item_prefs.h>
38 #include <filesel.h>
39 #include <inc.h>
40
41 /* Local includes */
42 #include "libfeed/parser_opml.h"
43 #include "rssyl_gtk.h"
44 #include "rssyl_feed.h"
45 #include "rssyl_feed_props.h"
46 #include "rssyl_update_feed.h"
47 #include "rssyl_subscribe.h"
48 #include "opml_import.h"
49
50 void rssyl_new_feed_cb(GtkAction *action,
51                 gpointer data)
52 {
53         FolderView *folderview = (FolderView*)data;
54         GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
55         FolderItem *item;
56         gchar *url;
57
58         debug_print("RSSyl: new_feed_cb\n");
59
60         g_return_if_fail(folderview->selected != NULL);
61
62         item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
63         g_return_if_fail(item != NULL);
64         g_return_if_fail(item->folder != NULL);
65
66         url = input_dialog(_("Subscribe feed"),
67                         _("Input the URL of the news feed you wish to subscribe:"),
68                         "");
69         if( url == NULL )       /* User cancelled */
70                 return;
71
72         rssyl_subscribe(item, url, TRUE);
73
74         g_free(url);
75 }
76
77 void rssyl_new_folder_cb(GtkAction *action,
78                 gpointer data)
79 {
80         FolderView *folderview = (FolderView*)data;
81         GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
82         FolderItem *item;
83         FolderItem *new_item;
84         gchar *new_folder, *p, *tmp;
85         gint i = 1;
86
87         if (!folderview->selected) return;
88
89         item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
90         g_return_if_fail(item != NULL);
91         g_return_if_fail(item->folder != NULL);
92
93         new_folder = input_dialog(_("New folder"),
94                                   _("Input the name of new folder:"),
95                                   _("NewFolder"));
96         if (!new_folder) return;
97
98         p = strchr(new_folder, G_DIR_SEPARATOR);
99         if (p) {
100                 alertpanel_error(_("'%c' can't be used in folder name."),
101                                  G_DIR_SEPARATOR);
102                 g_free(new_folder);
103                 return;
104         }
105
106         if (!folder_local_name_ok(new_folder)) {
107                 g_free(new_folder);
108                 return;
109         }
110
111         /* Find an unused name for new folder */
112         /* TODO: Perhaps stop after X attempts? */
113         tmp = g_strdup(new_folder);
114         while (folder_find_child_item_by_name(item, tmp)) {
115                 debug_print("RSSyl: Folder '%s' already exists, trying another name\n",
116                                 new_folder);
117                 g_free(tmp);
118                 tmp = g_strdup_printf("%s__%d", new_folder, ++i);
119         }
120
121         g_free(new_folder);
122         new_folder = tmp;
123
124         new_item = folder_create_folder(item, new_folder);
125         if (!new_item) {
126                 alertpanel_error(_("Can't create the folder '%s'."), new_folder);
127                 g_free(new_folder);
128                 return;
129         }
130
131         g_free(new_folder);
132
133         folder_write_list();
134 }
135
136 void rssyl_remove_folder_cb(GtkAction *action,
137                              gpointer data)
138 {
139         FolderView *folderview = (FolderView*)data;
140         GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
141         FolderItem *item;
142         gchar *message, *name;
143         AlertValue avalue;
144         gchar *old_id;
145
146         item = folderview_get_selected_item(folderview);
147         g_return_if_fail(item != NULL);
148         g_return_if_fail(item->path != NULL);
149         g_return_if_fail(item->folder != NULL);
150
151         name = trim_string(item->name, 32);
152         AUTORELEASE_STR(name, {g_free(name); return;});
153         message = g_strdup_printf
154                 (_("All folders and messages under '%s' will be permanently deleted. "
155                    "Recovery will not be possible.\n\n"
156                    "Do you really want to delete?"), name);
157         avalue = alertpanel_full(_("Delete folder"), message,
158                                  GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
159                                  NULL, ALERT_WARNING, G_ALERTDEFAULT);
160         g_free(message);
161         if (avalue != G_ALERTALTERNATE) return;
162
163         old_id = folder_item_get_identifier(item);
164
165         if (folderview->opened == folderview->selected ||
166             gtk_cmctree_is_ancestor(ctree,
167                                   folderview->selected,
168                                   folderview->opened)) {
169                 summary_clear_all(folderview->summaryview);
170                 folderview->opened = NULL;
171         }
172
173         if (item->folder->klass->remove_folder(item->folder, item) < 0) {
174                 folder_item_scan(item);
175                 alertpanel_error(_("Can't remove the folder '%s'."), name);
176                 g_free(old_id);
177                 return;
178         }
179
180         folder_write_list();
181
182         prefs_filtering_delete_path(old_id);
183         g_free(old_id);
184
185 }
186
187 void rssyl_rename_cb(GtkAction *action,
188                              gpointer *data)
189 {
190         FolderItem *item;
191         gchar *new_folder;
192         gchar *name;
193         gchar *message;
194         FolderView *folderview = (FolderView*)data;
195         item = folderview_get_selected_item(folderview);
196         g_return_if_fail(item != NULL);
197         g_return_if_fail(item->path != NULL);
198         g_return_if_fail(item->folder != NULL);
199
200         name = trim_string(item->name, 32);
201         message = g_strdup_printf(_("Input new name for '%s':"), name);
202         new_folder = input_dialog(_("Rename folder"), message, name);
203         g_free(message);
204         g_free(name);
205         if (!new_folder) return;
206
207         if (strchr(new_folder, G_DIR_SEPARATOR) != NULL) {
208                 alertpanel_error(_("'%c' can't be included in folder name."),
209                                  G_DIR_SEPARATOR);
210                 g_free(new_folder);
211                 return;
212         }
213
214         if (!folder_local_name_ok(new_folder)) {
215                 g_free(new_folder);
216                 return;
217         }
218
219         if (folder_find_child_item_by_name(folder_item_parent(item), new_folder)) {
220                 name = trim_string(new_folder, 32);
221                 alertpanel_error(_("The folder '%s' already exists."), name);
222                 g_free(name);
223                 g_free(new_folder);
224                 return;
225         }
226
227         if (folder_item_rename(item, new_folder) < 0) {
228                 alertpanel_error(_("The folder could not be renamed.\n"
229                                    "The new folder name is not allowed."));
230                 g_free(new_folder);
231                 return;
232         }
233         g_free(new_folder);
234
235         folder_item_prefs_save_config(item);
236         folder_write_list();
237 }
238
239 void rssyl_refresh_feed_cb(GtkAction *action,
240                 gpointer data)
241 {
242         FolderView *folderview = (FolderView*)data;
243         FolderItem *item = NULL;
244         RFolderItem *ritem = NULL;
245
246         item = folderview_get_selected_item(folderview);
247         g_return_if_fail(item != NULL);
248         g_return_if_fail(item->folder != NULL);
249
250         ritem = (RFolderItem *)item;
251
252         /* Offline check */
253         if( prefs_common_get_prefs()->work_offline &&
254                         !inc_offline_should_override(TRUE,
255                                         ngettext("Claws Mail needs network access in order "
256                                         "to update the feed.",
257                                         "Claws Mail needs network access in order "
258                                         "to update feeds.", 1))) {
259                 return;
260         }
261
262         /* Update feed, displaying errors if any. */
263         rssyl_update_feed(ritem, TRUE);
264 }
265
266 void rssyl_prop_cb(GtkAction *action, gpointer data)
267 {
268         FolderView *folderview = (FolderView*)data;
269         FolderItem *item;
270         RFolderItem *ritem;
271
272         item = folderview_get_selected_item(folderview);
273         g_return_if_fail(item != NULL);
274         g_return_if_fail(item->folder != NULL);
275
276         debug_print("RSSyl: rssyl_prop_cb() for '%s'\n", item->name);
277
278         ritem = (RFolderItem *)item;
279
280         rssyl_gtk_prop(ritem);
281 }
282
283 void rssyl_update_all_cb( GtkAction *action, gpointer data)
284 {
285         FolderItem *item;
286         FolderView *folderview = (FolderView*)data;
287
288         item = folderview_get_selected_item(folderview);
289         g_return_if_fail(item != NULL);
290         g_return_if_fail(item->folder != NULL);
291
292         debug_print("RSSyl: rssyl_update_all_cb(): clicked on '%s'\n", item->name);
293
294         if( item->folder->klass != rssyl_folder_get_class() ) {
295                 debug_print("RSSyl: this is not a RSSyl folder, returning\n");
296                 return;
297         }
298
299         rssyl_update_recursively(item);
300 }
301
302 void rssyl_remove_mailbox_cb(GtkAction *action, gpointer data)
303 {
304         FolderView *folderview = (FolderView *)data;
305         FolderItem *item = NULL;
306         gchar *n, *message;
307         AlertValue avalue;
308
309         item = folderview_get_selected_item(folderview);
310
311         g_return_if_fail(item != NULL);
312         g_return_if_fail(item->folder != NULL);
313
314         if( folder_item_parent(item) )
315                 return;
316
317         n = trim_string(item->folder->name, 32);
318         message = g_strdup_printf(_("Really remove the feed tree `%s' ?\n"), n);
319         avalue = alertpanel_full(_("Remove feed tree"), message,
320                                  GTK_STOCK_CANCEL, _("_Remove"), NULL, FALSE,
321                                  NULL, ALERT_WARNING, G_ALERTDEFAULT);
322         g_free(message);
323         g_free(n);
324
325         if( avalue != G_ALERTALTERNATE )
326                 return;
327
328         folderview_unselect(folderview);
329         summary_clear_all(folderview->summaryview);
330
331         n = folder_item_get_path(item);
332         if( remove_dir_recursive(n) < 0 ) {
333                 g_warning("can't remove directory '%s'\n", n);
334                 g_free(n);
335                 return;
336         }
337
338         g_free(n);
339         folder_destroy(item->folder);
340 }
341
342 void rssyl_import_feed_list_cb(GtkAction *action, gpointer data)
343 {
344         FolderView *folderview = (FolderView *)data;
345         GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
346         FolderItem *item = NULL;
347         gchar *path = NULL;
348         OPMLImportCtx *ctx = NULL;
349
350         debug_print("RSSyl: import_feed_list_cb\n");
351
352         /* Ask user for a file to import */
353         path = filesel_select_file_open_with_filter(
354                         _("Select an OPML file"), NULL, "*.opml");
355         if (!is_file_exist(path)) {
356                 g_free(path);
357                 return;
358         }
359
360         /* Find the destination folder for the import */
361         g_return_if_fail(folderview->selected != NULL);
362         item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
363         g_return_if_fail(item != NULL);
364         g_return_if_fail(item->folder != NULL);
365
366         ctx = malloc( sizeof(OPMLImportCtx) );
367         ctx->failures = 0;
368         /* This needs to be +2, since we will be comparing it to depth of
369          * <outline> tag in OPML's XML structure. Topmost outlines are under
370          * <opml> and <body>, hence 2. */
371         ctx->depth = rssyl_folder_depth(item) + 2;
372         ctx->current = NULL;
373         ctx->current = g_slist_append(ctx->current, item);
374
375         /* Start the whole shebang - call libfeed's OPML parser with correct
376          * user function */
377         opml_process(path, rssyl_opml_import_func, (gpointer)ctx);
378
379         g_free(ctx);
380 }