]> git.datanom.net - vfolder.git/blob - src/vfolder_gtk.c
initial upload
[vfolder.git] / src / vfolder_gtk.c
1 /*
2 * $Id: $
3 */
4 /* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
5
6 /*
7 * Virtual folder plugin for claws-mail
8 *
9 * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #include "gtk/menu.h"
31 #include "gtk/gtk.h"
32 #include "mainwindow.h"
33 #include "inputdialog.h"
34 #include "folder.h"
35 #include "folderview.h"
36 #include "alertpanel.h"
37 #include "hooks.h"
38 #include "utils.h"
39 #include "summaryview.h"
40
41 #include "gettext.h"
42 #include "main.h"
43 #include "gtkutils.h"
44
45 #include "vfolder_gtk.h"
46 #include "vfolder.h"
47 #include "vfolder_prop.h"
48
49 #define CONFIG_GROUP "VFolder"
50
51 static guint folder_hook_id;
52 static guint item_hook_id;
53 static guint msginfo_hook_id;
54 static GSList* widgets = NULL;
55
56 typedef struct {
57 MsgInfoList* list;
58 VFolderItem* item;
59 gchar* file;
60 } AddMsgData;
61
62 typedef struct {
63 GtkWidget* widget;
64 GtkAction* action;
65 } MenuItem;
66
67 static char* vfolder_popup_menu_labels[] = {
68 N_("_Refresh folder"),
69 N_("Refresh _all folders"),
70 N_("Folder pr_operties..."),
71 N_("Rena_me..."),
72 N_("_Create new folder..."),
73 N_("_Delete folder..."),
74 NULL
75 };
76
77 static GtkActionEntry vfolder_popup_entries[] = {
78 {"FolderViewPopup/RefreshFolder", NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
79 {"FolderViewPopup/RefreshAllFolders", NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
80
81 {"FolderViewPopup/FolderProperties", NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_properties_cb) },
82
83 {"FolderViewPopup/RenameFolder", NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
84
85 {"FolderViewPopup/NewFolder", NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_new_folder_cb) },
86 {"FolderViewPopup/RemoveFolder", NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_remove_folder_cb) },
87 };
88
89 static void vfolder_add_menuitems(GtkUIManager *ui_manager, FolderItem *item) {
90 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RefreshFolder", "FolderViewPopup/RefreshFolder", GTK_UI_MANAGER_MENUITEM)
91 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RefreshAllFolders", "FolderViewPopup/RefreshAllFolders", GTK_UI_MANAGER_MENUITEM)
92 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
93 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "FolderProperties", "FolderViewPopup/FolderProperties", GTK_UI_MANAGER_MENUITEM)
94 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
95 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM)
96 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
97 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "NewFolder", "FolderViewPopup/NewFolder", GTK_UI_MANAGER_MENUITEM)
98 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RemoveFolder", "FolderViewPopup/RemoveFolder", GTK_UI_MANAGER_MENUITEM)
99 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
100 }
101
102 static void vfolder_set_sensitivity(GtkUIManager *ui_manager, FolderItem *item) {
103 #define SET_SENS(name, sens) \
104 cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
105
106 VFolderItem *ritem = (VFolderItem *)item;
107 SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL && ! ritem->frozen);
108 SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL && ! ritem->frozen);
109 SET_SENS("FolderViewPopup/FolderProperties", folder_item_parent(item) != NULL);
110 SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(item) != NULL);
111 SET_SENS("FolderViewPopup/NewFolder", TRUE);
112 SET_SENS("FolderViewPopup/RemoveFolder", folder_item_parent(item) != NULL);
113
114 #undef SET_SENS
115 }
116
117 static FolderViewPopup vfolder_popup = {
118 "vfolder",
119 "<vfolder>",
120 vfolder_popup_entries,
121 G_N_ELEMENTS(vfolder_popup_entries),
122 NULL, 0,
123 NULL, 0, 0, NULL,
124 vfolder_add_menuitems,
125 vfolder_set_sensitivity
126 };
127
128 static void vfolder_fill_popup_menu_labels(void) {
129 gint i;
130
131 for (i = 0; vfolder_popup_menu_labels[i] != NULL; i++) {
132 (vfolder_popup_entries[i]).label = _(vfolder_popup_menu_labels[i]);
133 }
134 }
135
136 static void gslist_menu_item_free(GSList** menu_list) {
137 GSList* list;
138
139 if (! menu_list || ! *menu_list)
140 return;
141
142 for (list = *menu_list; list; list = g_slist_next(list)) {
143 MenuItem* menu = (MenuItem *) list->data;
144 g_free(menu);
145 }
146
147 g_slist_free(*menu_list);
148 *menu_list = NULL;
149 }
150
151 static MsgBridge* vfolder_split_file_id(gchar* id) {
152 MsgBridge* resp = NULL;
153
154 if (! id)
155 return NULL;
156
157 gchar** tokens = g_strsplit(id, ":", 0);
158 if (g_strv_length(tokens) != 2)
159 goto bail;
160
161 resp = g_new0(MsgBridge, 1);
162 resp->my_num = to_number(tokens[0]);
163 resp->claws_num = to_number(tokens[1]);
164
165 bail:
166 g_strfreev(tokens);
167 return resp;
168 }
169
170 static gboolean get_menu_widgets() {
171 MainWindow* mainwindow;
172 MenuItem* menuitem = NULL;
173 GtkWidget* widget;
174
175 mainwindow = mainwindow_get_mainwindow();
176 if (mainwindow && mainwindow->ui_manager) {
177 widget = gtk_ui_manager_get_widget(
178 mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/");
179 if (widget) {
180 menuitem = g_new0(MenuItem, 1);
181 menuitem->widget = widget;
182 menuitem->action = gtk_ui_manager_get_action(
183 mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/");
184 widgets = g_slist_prepend(widgets, menuitem);
185 }
186 else
187 return FALSE;
188
189 widget = gtk_ui_manager_get_widget(
190 mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/");
191 if (widget) {
192 menuitem = g_new0(MenuItem, 1);
193 menuitem->widget = widget;
194 menuitem->action = gtk_ui_manager_get_action(
195 mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/");
196 widgets = g_slist_prepend(widgets, menuitem);
197 }
198 else {
199 gslist_menu_item_free(&widgets);
200 return FALSE;
201 }
202
203 widget = gtk_ui_manager_get_widget(
204 mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/");
205 if (widget) {
206 menuitem = g_new0(MenuItem, 1);
207 menuitem->widget = widget;
208 menuitem->action = gtk_ui_manager_get_action(
209 mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/");
210 widgets = g_slist_prepend(widgets, menuitem);
211 }
212 else {
213 gslist_menu_item_free(&widgets);
214 return FALSE;
215 }
216
217 widget = gtk_ui_manager_get_widget(
218 mainwindow->ui_manager, "/Menu/Message/Move/");
219 if (widget) {
220 menuitem = g_new0(MenuItem, 1);
221 menuitem->widget = widget;
222 menuitem->action = gtk_ui_manager_get_action(
223 mainwindow->ui_manager, "/Menu/Message/Move/");
224 widgets = g_slist_prepend(widgets, menuitem);
225 }
226 else {
227 gslist_menu_item_free(&widgets);
228 return FALSE;
229 }
230
231 widget = gtk_ui_manager_get_widget(
232 mainwindow->ui_manager, "/Menu/Message/Trash/");
233 if (widget) {
234 menuitem = g_new0(MenuItem, 1);
235 menuitem->widget = widget;
236 menuitem->action = gtk_ui_manager_get_action(
237 mainwindow->ui_manager, "/Menu/Message/Trash/");
238 widgets = g_slist_prepend(widgets, menuitem);
239 }
240 else {
241 gslist_menu_item_free(&widgets);
242 return FALSE;
243 }
244
245 widget = gtk_ui_manager_get_widget(
246 mainwindow->ui_manager, "/Menu/Message/Delete/");
247 if (widget) {
248 menuitem = g_new0(MenuItem, 1);
249 menuitem->widget = widget;
250 menuitem->action = gtk_ui_manager_get_action(
251 mainwindow->ui_manager, "/Menu/Message/Delete/");
252 widgets = g_slist_prepend(widgets, menuitem);
253 }
254 else {
255 gslist_menu_item_free(&widgets);
256 return FALSE;
257 }
258
259 }
260 else
261 return FALSE;
262
263 return TRUE;
264 }
265 /*
266 static gboolean vfolder_widgets_is_visible() {
267 gboolean visible = TRUE;
268
269 if (widgets && widgets->data) {
270 MenuItem* menu = (MenuItem *) widgets->data;
271 visible = gtk_widget_get_visible(menu->widget);
272 }
273
274 return visible;
275 }
276
277 static gboolean vfolder_hide_widgets(VFolderItem* item) {
278 GSList* list;
279 MainWindow* mainwindow;
280
281 // if (! item->deep_copy) {
282 for (list = widgets; list; list = g_slist_next(list)) {
283 MenuItem* menu = (MenuItem *) list->data;
284 gtk_widget_hide(menu->widget);
285 gtk_action_block_activate(menu->action);
286 }
287
288 mainwindow = mainwindow_get_mainwindow();
289 if (mainwindow && mainwindow->toolbar) {
290 if (mainwindow->toolbar->trash_btn)
291 gtk_widget_hide(mainwindow->toolbar->trash_btn);
292 if (mainwindow->toolbar->delete_btn)
293 gtk_widget_hide(mainwindow->toolbar->delete_btn);
294 }
295 // }
296 return TRUE;
297 }
298 */
299 static gboolean vfolder_show_widgets(VFolderItem* item) {
300 GSList* list;
301 MainWindow* mainwindow;
302
303 // if (! item->deep_copy) {
304 for (list = widgets; list; list = g_slist_next(list)) {
305 MenuItem* menu = (MenuItem *) list->data;
306 gtk_widget_show(menu->widget);
307 gtk_action_unblock_activate(menu->action);
308 }
309
310 mainwindow = mainwindow_get_mainwindow();
311 if (mainwindow && mainwindow->toolbar) {
312 if (mainwindow->toolbar->trash_btn)
313 gtk_widget_show(mainwindow->toolbar->trash_btn);
314 if (mainwindow->toolbar->delete_btn)
315 gtk_widget_show(mainwindow->toolbar->delete_btn);
316 }
317 // }
318 return TRUE;
319 }
320 /*
321 static gchar* vfolder_get_message_file_path(VFolderItem* item, MsgInfo* msg) {
322 gchar* path;
323 GSList* list = NULL, *cur;
324 Folder* folder;
325 gboolean old_uid;
326 guint last = 0;
327
328 if (item->deep_copy) {
329 path = procmsg_get_message_file_path(msg);
330 }
331 else {
332 gchar* root = folder_item_get_path(msg->to_folder);
333 folder = msg->to_folder->folder;
334 guint num = folder->klass->get_num_list(folder, msg->to_folder, &list, &old_uid);
335 if (num >= 0) {
336 for (cur = list, last = 0; cur; cur = g_slist_next(cur)) {
337 guint tmp = GPOINTER_TO_UINT(cur->data);
338 if (tmp > last)
339 last = tmp;
340 }
341 }
342 g_slist_free(list);
343
344 path = g_strdup_printf("%s%s%u", root, G_DIR_SEPARATOR_S, last + 1);
345 g_free(root);
346 }
347 return path;
348 }
349 */
350
351 /*
352 static void vfolder_item_update(AddMsgData* msgdata) {
353 MsgInfoList* cur;
354 GSList update;
355 MsgFileInfo fileinfo;
356
357 if (!msgdata->item || !msgdata->list->data)
358 return;
359
360 for (cur = msgdata->list; cur; cur = g_slist_next(cur)) {
361 MsgInfo* msg = (MsgInfo *) cur->data;
362 if (MSG_IS_DELETED(msg->flags)) {
363 folder_item_remove_msg(FOLDER_ITEM(msgdata->item), msg->msgnum);
364 }
365 else {
366 fileinfo.msginfo = msg;
367 fileinfo.flags = &msg->flags;
368 fileinfo.file = msgdata->file;
369 update.data = &fileinfo;
370 update.next = NULL;
371 folder_item_scan(msg->folder);
372 gint n = folder_item_add_msgs(FOLDER_ITEM(msgdata->item), &update, FALSE);
373 gchar* p = strrchr(fileinfo.file, G_DIR_SEPARATOR);
374 p += 1;
375 guint num = to_number((const gchar *) p);
376 vfolder_replace_key_in_bridge(msgdata->item, msg->msgnum, num);
377 FOLDER_ITEM(msgdata->item)->last_num = n;
378 }
379 }
380
381 //procmsg_message_file_list_free(list);
382 //item->msginfos = folder_item_get_msg_list(FOLDER_ITEM(item));
383 }
384 */
385 /*
386 static void add_msg_data_free(AddMsgData** rec) {
387 if (rec && *rec) {
388 AddMsgData* data = *rec;
389 g_slist_free(data->list);
390 g_free(data->file);
391 g_free(data);
392 *rec = NULL;
393 }
394 }
395 */
396 /*
397 static void vfolder_update_affected_folder_items(MsgInfo* msginfo) {
398 GList *vfolders, *cur;
399 GSList* cur_msg;
400 gchar* src;
401 AddMsgData* data;
402 MsgInfo* msg;
403
404 if (! msginfo)
405 return;
406
407 if (MSG_IS_NEW(msginfo->flags) ||
408 MSG_IS_MOVE(msginfo->flags) ||
409 MSG_IS_COPY(msginfo->flags) ||
410 MSG_IS_DELETED(msginfo->flags)) {
411 vfolders = vfolder_get_vfolder_items();
412 for (cur = vfolders; cur; cur = g_list_next(cur)) {
413 data = g_new0(AddMsgData, 1);
414 VFolderItem* vitem = VFOLDER_ITEM(cur->data);
415 if (MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))
416 src = folder_item_get_identifier(msginfo->to_folder);
417 else
418 src = folder_item_get_identifier(msginfo->folder);
419 gchar* shadow = folder_item_get_identifier(vitem->source);
420 debug_print("cmp %s : %s\n", src, shadow);
421 if (src && shadow && strcmp(src, shadow) == 0) {
422 if (MSG_IS_DELETED(msginfo->flags)) {
423 msg = vfolder_find_msg_from_claws_num(vitem, msginfo->msgnum);
424 if (msg)
425 data->list = g_slist_append(data->list, msg);
426 else {
427 add_msg_data_free(&data);
428 g_slist_free(add_msg_data);
429 add_msg_data = NULL;
430 g_free(src);
431 g_free(shadow);
432 return;
433 }
434 }
435 else {
436 data->list = g_slist_append(data->list, msginfo);
437 data->item = vitem;
438 data->file = vfolder_get_message_file_path(vitem, msginfo);
439 add_msg_data = g_slist_prepend(add_msg_data, data);
440 }
441 if (data->list && MSG_IS_DELETED(msginfo->flags)) {
442 GSList* list = vfolder_filter_msgs_list(data->list, vitem);
443 if (list && list->data) {
444 MsgInfo* msg = (MsgInfo *) list->data;
445 MSG_SET_PERM_FLAGS(msg->flags, MSG_DELETED);
446 }
447 g_slist_free(data->list);
448 data->list = list;
449 data->item = vitem;
450 vfolder_item_update(data);
451 add_msg_data_free(&data);
452 g_slist_free(add_msg_data);
453 add_msg_data = NULL;
454 }
455 }
456 g_free(src);
457 g_free(shadow);
458 }
459 }
460 if (add_msg_data) {
461 for (cur_msg = add_msg_data; cur_msg; cur_msg = g_slist_next(cur_msg)) {
462 data = (AddMsgData *) cur_msg->data;
463 GSList* list = vfolder_filter_msgs_list(data->list, data->item);
464 g_slist_free(data->list);
465 data->list = list;
466 vfolder_item_update(data);
467 add_msg_data_free(&data);
468 }
469 g_slist_free(add_msg_data);
470 add_msg_data = NULL;
471 }
472 }
473 */
474 static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
475 FolderUpdateData* hookdata;
476
477 g_return_val_if_fail(source != NULL, FALSE);
478 hookdata = (FolderUpdateData *) source;
479
480 if (! hookdata->folder || IS_VFOLDER_FOLDER(hookdata->folder))
481 return FALSE;
482
483 if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) {
484 /* TODO: check if the removed folder item is foundation for vfolder */
485 debug_print("FOLDER_REMOVE_FOLDERITEM\n");
486 }
487
488 if (hookdata->update_flags & FOLDER_REMOVE_FOLDER) {
489 /* TODO: check if the removed folder is foundation for vfolder */
490 debug_print("FOLDER_REMOVE_FOLDER\n");
491 }
492
493 if (hookdata->update_flags & FOLDER_TREE_CHANGED) {
494 /* TODO: check if the removed folder is foundation for vfolder */
495 debug_print("FOLDER_TREE_CHANGED\n");
496 }
497
498 if (hookdata->update_flags & FOLDER_RENAME_FOLDERITEM) {
499 /* TODO: check if the removed folder is foundation for vfolder */
500 debug_print("FOLDER_RENAME_FOLDERITEM\n");
501 }
502
503 return FALSE;
504 }
505
506 static gboolean vfolder_folder_item_update_hook(gpointer source, gpointer data) {
507 FolderItemUpdateData* hookdata;
508 // gint save_state = -1;
509 GList *items, *cur;
510 // gboolean r;
511 // MainWindow* mainwindow;
512
513 g_return_val_if_fail(source != NULL, FALSE);
514 hookdata = (FolderItemUpdateData *) source;
515
516 if (! hookdata->item || IS_VFOLDER_FOLDER_ITEM(hookdata->item))
517 return FALSE;
518
519 if (hookdata->update_flags & F_ITEM_UPDATE_REMOVEMSG ) {
520 debug_print("F_ITEM_UPDATE_REMOVEMSG\n");
521 items = vfolder_get_vfolder_from_source(hookdata->item);
522 if (items) {
523 for (cur = items; cur; cur = g_list_next(cur)) {
524 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_REMOVEMSG);
525 }
526 g_list_free(items);
527 }
528 }
529
530 else if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT) {
531 debug_print("F_ITEM_UPDATE_CONTENT\n");
532 items = vfolder_get_vfolder_from_source(hookdata->item);
533 if (items) {
534 for (cur = items; cur; cur = g_list_next(cur)) {
535 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_CONTENT);
536 }
537 g_list_free(items);
538 }
539 //mainwindow = mainwindow_get_mainwindow();
540 //summary_execute(mainwindow->summaryview);
541 }
542
543 else if (hookdata->update_flags & F_ITEM_UPDATE_ADDMSG) {
544 debug_print("F_ITEM_UPDATE_ADDMSG\n");
545 items = vfolder_get_vfolder_from_source(hookdata->item);
546 if (items) {
547 for (cur = items; cur; cur = g_list_next(cur)) {
548 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_ADDMSG);
549 }
550 g_list_free(items);
551 }
552 }
553
554 else if (hookdata->update_flags & F_ITEM_UPDATE_MSGCNT) {
555 debug_print("F_ITEM_UPDATE_MSGCNT\n");
556 /* if (IS_VFOLDER_FOLDER_ITEM(item)) {
557
558 if (! (VFOLDER_ITEM(item))->deep_copy) {
559 if (! (VFOLDER_ITEM(item))->active) {
560 r = vfolder_hide_widgets(VFOLDER_ITEM(item));
561 if (r)
562 VFOLDER_ITEM(item)->active = TRUE;
563 }
564 else {
565 r = vfolder_show_widgets(VFOLDER_ITEM(item));
566 if (r)
567 VFOLDER_ITEM(item)->active = FALSE;
568 }
569
570 if (r)
571 save_state = 1;
572 else
573 save_state = 0;
574 }
575 else
576 vfolder_show_widgets(VFOLDER_ITEM(item));
577 }
578 else {
579 if (!vfolder_widgets_is_visible())
580 vfolder_show_widgets(VFOLDER_ITEM(item));
581 }*/
582 /*
583 items = vfolder_get_vfolder_from_source(hookdata->item);
584 if (items) {
585 for (cur = items; cur; cur = g_list_next(cur)) {
586 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_MSGCNT);
587 }
588 g_list_free(items);
589 }
590 */
591 }
592
593 else if (hookdata->update_flags & F_ITEM_UPDATE_NAME) {
594 /* TODO: need update? */
595 debug_print("F_ITEM_UPDATE_NAME\n");
596 items = vfolder_get_vfolder_from_source(hookdata->item);
597 if (items) {
598 for (cur = items; cur; cur = g_list_next(cur)) {
599 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_NAME);
600 }
601 g_list_free(items);
602 }
603 }
604
605 else {
606 /* Unhandled callback */
607 debug_print("Unhandled FolderItem callback\n");
608 }
609 /*
610 if (!save_state) {
611 MainWindow* mainwindow = mainwindow_get_mainwindow();
612 alertpanel_error(_("%s: Could not hide dangerous actions"), hookdata->item->name);
613 summary_lock(mainwindow->summaryview);
614 }
615 */
616 return FALSE;
617 }
618 /*
619 static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
620 MsgInfoUpdate* hookdata;
621 MainWindow* mainwindow;
622 MsgInfo* msginfo;
623
624 g_return_val_if_fail(source != NULL, FALSE);
625 hookdata = (MsgInfoUpdate *) source;
626 msginfo = hookdata->msginfo;
627
628 g_return_val_if_fail(msginfo != NULL, TRUE);
629
630 if (IS_VFOLDER_MSGINFO(msginfo))
631 return FALSE;
632
633 debug_print("\n\nPermflag: %u Tmpflag: %u (scanned: %u)\n\n\n",
634 (guint32) msginfo->flags.perm_flags, (guint32) msginfo->flags.tmp_flags, 1U << 31);
635 if (MSG_IS_NEW(msginfo->flags)) {
636 debug_print("MSG_IS_NEW\n");
637 vfolder_update_affected_folder_items(msginfo);
638 mainwindow = mainwindow_get_mainwindow();
639 summary_execute(mainwindow->summaryview);
640 }
641
642 if (MSG_IS_DELETED(msginfo->flags)) {
643 debug_print("MSG_IS_DELETED\n");
644 vfolder_update_affected_folder_items(msginfo);
645 mainwindow = mainwindow_get_mainwindow();
646 summary_execute(mainwindow->summaryview);
647 }
648
649 if (MSG_IS_MOVE(msginfo->flags)) {
650 debug_print("MSG_IS_MOVE\n");
651 vfolder_update_affected_folder_items(msginfo);
652 mainwindow = mainwindow_get_mainwindow();
653 summary_execute(mainwindow->summaryview);
654 }
655
656 if (MSG_IS_COPY(msginfo->flags)) {
657 debug_print("MSG_IS_COPY\n");
658 vfolder_update_affected_folder_items(msginfo);
659 mainwindow = mainwindow_get_mainwindow();
660 summary_execute(mainwindow->summaryview);
661 }
662
663 // if (MSG_IS_POSTFILTERED(msginfo->flags)) {
664 // debug_print("MSG_IS_POSTFILTERED\n");
665 // vfolder_update_affected_folder_items(msginfo);
666 // mainwindow = mainwindow_get_mainwindow();
667 // summary_execute(mainwindow->summaryview);
668 // }
669
670
671 return FALSE;
672 }
673 */
674 static gchar* vfolder_get_rc_file(VFolderItem* item) {
675 gchar* (*item_get_path) (Folder* folder, FolderItem* item);
676 gchar* path;
677 gchar* rc_file;
678
679 item_get_path = FOLDER_ITEM(item)->folder->klass->item_get_path;
680
681 path = item_get_path(FOLDER_ITEM(item)->folder, FOLDER_ITEM(item));
682 rc_file = g_strconcat(path, G_DIR_SEPARATOR_S, "folderitemrc", NULL);
683 g_free(path);
684
685 return rc_file;
686 }
687
688 FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item) {
689 gchar* rc_file;
690 GKeyFile* config;
691 gchar* id;
692 gchar* data = NULL;
693 FILE* fp;
694 gsize len = 0;
695 FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM;
696 gchar* numstr;
697 GHashTableIter iter;
698 gpointer key, value;
699
700 g_return_val_if_fail(item != NULL, resp);
701
702 rc_file = vfolder_get_rc_file(item);
703 config = g_key_file_new();
704
705 if (item->filter)
706 g_key_file_set_string(config, CONFIG_GROUP, "filter", item->filter);
707
708 g_key_file_set_integer(config, CONFIG_GROUP, "searchtype", item->search);
709 g_key_file_set_boolean(config, CONFIG_GROUP, "frozen", item->frozen);
710 g_key_file_set_boolean(config, CONFIG_GROUP, "deep_copy", item->deep_copy);
711
712 if (item->source) {
713 id = folder_item_get_identifier(item->source);
714 if (id) {
715 g_key_file_set_string(config, CONFIG_GROUP, "source", id);
716 g_free(id);
717 }
718 }
719
720 if (item->claws_to_me && item->me_to_claws) {
721 numstr = NULL;
722 g_hash_table_iter_init(&iter, item->claws_to_me);
723 while (g_hash_table_iter_next(&iter, &key, &value)) {
724 len++;
725 MsgBridge* bridge = value;
726 if (numstr) {
727 gchar* tmp = g_strdup(numstr);
728 g_free(numstr);
729 numstr = g_strdup_printf("%s, %u:%u",
730 tmp, bridge->my_num, bridge->claws_num);
731 g_free(tmp);
732 }
733 else
734 numstr = g_strdup_printf("%u:%u", bridge->my_num, bridge->claws_num);
735 }
736
737 g_key_file_set_string(config, CONFIG_GROUP, "file_id_list", numstr);
738 g_free(numstr);
739 }
740
741 if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) {
742 gchar* bakpath = g_strconcat(rc_file, ".bak", NULL);
743 if (g_rename(rc_file, bakpath) < 0) {
744 g_warning("%s: Could not create", bakpath);
745 resp = FOLDER_ITEM_PROPS_BACKUP_FAIL;
746 }
747 g_free(bakpath);
748 }
749
750 // g_key_file_set_integer(config, CONFIG_GROUP, "filter-function", item->filter_func);
751
752 data = g_key_file_to_data(config, &len, NULL);
753 if (len < 1) {
754 g_warning("Could not get config data");
755 resp = FOLDER_ITEM_PROPS_READ_DATA_FAIL;
756 }
757 else {
758 fp = g_fopen(rc_file, "w");
759 if (fp == NULL) {
760 gchar* dir_path_end = g_strrstr(rc_file, G_DIR_SEPARATOR_S);
761 gchar* rc_dir = g_strndup(rc_file, dir_path_end - rc_file);
762 debug_print("rc_dir: %s\n", rc_dir);
763 int r = g_mkdir_with_parents(rc_dir, 0700);
764 if (r != 0)
765 resp = FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL;
766 g_free(rc_dir);
767 if (resp == FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL)
768 goto error;
769 fp = g_fopen(rc_file, "w");
770 if (fp == NULL) {
771 resp = FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL;
772 goto error;
773 }
774 }
775 fwrite(data, len, 1, fp);
776 fclose(fp);
777 resp = FOLDER_ITEM_PROPS_OK;
778 }
779
780 error:
781 g_free(data);
782
783 g_key_file_free(config);
784 g_free(rc_file);
785
786 return resp;
787 }
788
789 FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item) {
790 gchar* rc_file;
791 GKeyFile* config;
792 GError* error = NULL;
793 gchar *id, *msgnums;
794 gchar **list, **head;
795 FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM;
796 gint lastnum;
797
798 g_return_val_if_fail(item != NULL, resp);
799
800 rc_file = vfolder_get_rc_file(item);
801 config = g_key_file_new();
802
803 if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) {
804 g_key_file_load_from_file(config, rc_file, G_KEY_FILE_KEEP_COMMENTS, &error);
805 if (error) {
806 g_warning("%s. Using defaults", error->message);
807 g_error_free(error);
808 resp = FOLDER_ITEM_PROPS_READ_USING_DEFAULT;
809 }
810 else {
811 item->filter = g_key_file_get_string(config, CONFIG_GROUP, "filter", NULL);
812 item->search = g_key_file_get_integer(config, CONFIG_GROUP, "searchtype", NULL);
813 item->frozen = g_key_file_get_boolean(config, CONFIG_GROUP, "frozen", NULL);
814 item->deep_copy = g_key_file_get_boolean(config, CONFIG_GROUP, "deep_copy", NULL);
815 // item->filter_func = g_key_file_get_integer(config, CONFIG_GROUP, "filter_function", NULL);
816
817 id = g_key_file_get_string(config, CONFIG_GROUP, "source", NULL);
818 if (id) {
819 item->source = folder_find_item_from_identifier(id);
820 g_free(id);
821 }
822 msgnums = g_key_file_get_string(config, CONFIG_GROUP, "file_id_list", NULL);
823 if (msgnums) {
824 list = g_strsplit(msgnums, ",", 0);
825 head = list;
826 lastnum = -1;
827 while (*list) {
828 gchar* anum = g_strdup(*list++);
829 g_strstrip(anum);
830 MsgBridge* bridge = vfolder_split_file_id(anum);
831 g_free(anum);
832 if (lastnum < (gint) bridge->my_num)
833 lastnum = bridge->my_num;
834 if (bridge->my_num > 0) {
835 vfolder_add_message_to_bridge(item, bridge);
836 }
837 g_free(bridge);
838 }
839 FOLDER_ITEM(item)->last_num = lastnum;
840 g_strfreev(head);
841 g_free(msgnums);
842 }
843 resp = FOLDER_ITEM_PROPS_OK;
844 }
845 }
846
847 g_key_file_free(config);
848 g_free(rc_file);
849
850 return resp;
851 }
852
853 gboolean vfolder_gtk_init(gchar** error) {
854 vfolder_fill_popup_menu_labels();
855 folderview_register_popup(&vfolder_popup);
856
857 folder_hook_id = hooks_register_hook(FOLDER_UPDATE_HOOKLIST,
858 vfolder_folder_update_hook, NULL);
859 if (folder_hook_id == -1) {
860 *error = g_strdup(_("Failed to register folder update hook"));
861 return FALSE;
862 }
863
864 item_hook_id = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
865 vfolder_folder_item_update_hook, NULL);
866 if (item_hook_id == -1) {
867 *error = g_strdup(_("Failed to register folder item update hook"));
868 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
869 return FALSE;
870 }
871
872 /* msginfo_hook_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
873 vfolder_msg_info_update_hook, NULL);
874 if (msginfo_hook_id == -1) {
875 *error = g_strdup(_("Failed to register message info update hook"));
876 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
877 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
878 return FALSE;
879 }*/
880
881 if (! get_menu_widgets()) {
882 *error = g_strdup(_("Failed to get menu widgets"));
883 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
884 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
885 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
886 return FALSE;
887 }
888
889 return TRUE;
890 }
891
892 void vfolder_gtk_done(void) {
893 MainWindow *mainwin = mainwindow_get_mainwindow();
894 FolderView *folderview = NULL;
895 FolderItem *fitem = NULL;
896
897 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
898 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
899 //hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
900
901 if (mainwin == NULL || claws_is_exiting())
902 return;
903
904 folderview = mainwin->folderview;
905 fitem = folderview->summaryview->folder_item;
906
907 if (fitem && IS_VFOLDER_FOLDER_ITEM(fitem)) {
908 vfolder_show_widgets(VFOLDER_ITEM(fitem));
909 gslist_menu_item_free(&widgets);
910
911 folderview_unselect(folderview);
912 summary_clear_all(folderview->summaryview);
913 }
914
915 folderview_unregister_popup(&vfolder_popup);
916 }
917
918 void vfolder_properties_cb(GtkAction* action, gpointer data) {
919 FolderView *folderview = (FolderView *)data;
920 FolderItem *item;
921
922 g_return_if_fail(folderview != NULL);
923
924 item = folderview_get_selected_item(folderview);
925
926 g_return_if_fail(item != NULL);
927 g_return_if_fail(item->path != NULL);
928 g_return_if_fail(item->folder != NULL);
929
930 if (vfolder_edit_item_dialog(VFOLDER_ITEM(item))) {
931 /* TODO: update */
932 if (debug_get_mode()) {
933 GHashTableIter iter;
934 gpointer key, value;
935
936 g_hash_table_iter_init(&iter, VFOLDER_ITEM(item)->me_to_claws);
937 while (g_hash_table_iter_next(&iter, &key, &value)) {
938 gchar* buf = g_new0(gchar, BUFSIZ);
939 MsgInfo* msginfo = vfolder_find_msg_from_vfolder_num(
940 VFOLDER_ITEM(item), GPOINTER_TO_UINT(key));
941 FILE* msg = procmsg_open_message(msginfo);
942 while (fread(buf, 1, BUFSIZ - 1, msg) > 0) {
943 fprintf(stderr, "%s", buf);
944 g_free(buf);
945 buf = g_new0(gchar, BUFSIZ);
946 }
947 fprintf(stderr, "\n");
948 if (buf)
949 g_free(buf);
950 fclose(msg);
951 }
952 }
953 vfolder_folder_item_props_write(VFOLDER_ITEM(item));
954 }
955 }
956
957 void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
958 FolderView *folderview = (FolderView *)data;
959 GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
960 FolderItem *item;
961 FolderItem *new_item;
962 gchar *new_folder;
963 gchar *name;
964 gchar *p;
965
966 if (!folderview->selected) return;
967
968 item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
969 if (! item) {
970 item = FOLDER_ITEM(vfolder_get_vfolder_item(NULL));
971 }
972
973 g_return_if_fail(item != NULL);
974 g_return_if_fail(item->folder != NULL);
975
976 if (item->no_sub) {
977 alertpanel_error(N_("Virtual folders cannot contain subfolders"));
978 return;
979 }
980
981 new_folder = input_dialog(_("New folder"),
982 _("Input the name of new folder:"),
983 _("NewFolder"));
984 if (!new_folder) return;
985 AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
986
987 p = strchr(new_folder, G_DIR_SEPARATOR);
988 if (p) {
989 alertpanel_error(_("'%c' can't be included in folder name."),
990 G_DIR_SEPARATOR);
991 return;
992 }
993
994 name = trim_string(new_folder, 32);
995 AUTORELEASE_STR(name, {g_free(name); return;});
996
997 /* find whether the directory already exists */
998 if (folder_find_child_item_by_name(item, new_folder)) {
999 alertpanel_error(_("The folder '%s' already exists."), name);
1000 return;
1001 }
1002
1003 new_item = folder_create_folder(item, new_folder);
1004 if (!new_item) {
1005 alertpanel_error(_("Can't create the folder '%s'."), name);
1006 return;
1007 }
1008
1009 if (! vfolder_create_item_dialog(new_item)) {
1010 //VFolderItem* vitem = VFOLDER_ITEM(new_item);
1011 new_item->folder->klass->remove_folder(new_item->folder, new_item);
1012 new_item = NULL;
1013 return;
1014 }
1015
1016 folder_write_list();
1017 }
1018
1019 void vfolder_remove_folder_cb(GtkAction* action, gpointer data) {
1020 FolderView *folderview = (FolderView *)data;
1021 GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
1022 FolderItem *item;
1023 gchar *message, *name;
1024 AlertValue avalue;
1025 gchar *old_path = NULL;
1026 gchar *old_id;
1027
1028 /* Silence lame warnings */
1029 old_id = (old_path) ? NULL : old_path;
1030
1031 item = folderview_get_selected_item(folderview);
1032 g_return_if_fail(item != NULL);
1033 g_return_if_fail(item->path != NULL);
1034 g_return_if_fail(item->folder != NULL);
1035
1036 name = trim_string(item->name, 32);
1037 AUTORELEASE_STR(name, {g_free(name); return;});
1038 message = g_strdup_printf
1039 (_("All folders and messages under '%s' will be permanently deleted. "
1040 "Recovery will not be possible.\n\n"
1041 "Do you really want to delete?"), name);
1042 avalue = alertpanel_full(_("Delete folder"), message,
1043 GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
1044 NULL, ALERT_WARNING, G_ALERTDEFAULT);
1045 g_free(message);
1046 if (avalue != G_ALERTALTERNATE) return;
1047
1048 Xstrdup_a(old_path, item->path, return);
1049 old_id = folder_item_get_identifier(item);
1050
1051 if (folderview->opened == folderview->selected ||
1052 gtk_cmctree_is_ancestor(ctree,
1053 folderview->selected,
1054 folderview->opened)) {
1055 summary_clear_all(folderview->summaryview);
1056 folderview->opened = NULL;
1057 }
1058
1059 if (item->folder->klass->remove_folder(item->folder, item) < 0) {
1060 folder_item_scan(item);
1061 alertpanel_error(_("Can't remove the folder '%s'."), name);
1062 g_free(old_id);
1063 return;
1064 }
1065
1066 folder_write_list();
1067
1068 g_free(old_id);
1069 }
This page took 0.184451 seconds and 6 git commands to generate.