[Commits] [SCM] claws branch, vfolder, created. 3.10.1-105-g56525de

miras at claws-mail.org miras at claws-mail.org
Sat Jun 21 20:30:27 CEST 2014


The branch vfolder of project "claws" (Claws Mail) has been created
        at  56525de819a32955ed283dccafce200a2bc5de0b (commit)

- Log -----------------------------------------------------------------
commit 56525de819a32955ed283dccafce200a2bc5de0b
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sat Jun 21 20:19:05 2014 +0200

    Add tool tip to virtual folder properties window

diff --git a/src/plugins/vfolder/vfolder_gtk.c b/src/plugins/vfolder/vfolder_gtk.c
index 2f4e488..25b88a2 100644
--- a/src/plugins/vfolder/vfolder_gtk.c
+++ b/src/plugins/vfolder/vfolder_gtk.c
@@ -486,9 +486,9 @@ void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
 			return;
 		}
 	}
-	new_folder = input_dialog(_("New folder"),
-				  _("Input the name of new folder:"),
-				  _("NewFolder"));
+	new_folder = input_dialog(_("New virtual folder"),
+				  _("Input the name of the folder:"),
+				  _("Virtual Folder"));
 	if (!new_folder) return;
 	AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
 
diff --git a/src/plugins/vfolder/vfolder_prop.c b/src/plugins/vfolder/vfolder_prop.c
index 2f08d8b..203a0c0 100644
--- a/src/plugins/vfolder/vfolder_prop.c
+++ b/src/plugins/vfolder/vfolder_prop.c
@@ -300,16 +300,22 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item) {
 	MainWindow *mainwin = mainwindow_get_mainwindow();
 	props_dialog = g_new0(PropsDialog, 1);
 	props_dialog->filter = gtk_entry_new();
+	CLAWS_SET_TIP(props_dialog->filter, _("Glob filter. '*' or '?' for wildcard"));
 	props_dialog->frozen = gtk_check_button_new();
+	CLAWS_SET_TIP(props_dialog->frozen, _("Disable automatic update. Manual refresh is not affected"));
 	props_dialog->source = gtk_entry_new();
+	CLAWS_SET_TIP(props_dialog->source, _("Folder to watch"));
 	props_dialog->label_btn =
 		gtk_radio_button_new_with_mnemonic(NULL, HEADERS);
+	CLAWS_SET_TIP(props_dialog->label_btn, _("Only scan message headers"));
 	props_dialog->message_btn =
 		gtk_radio_button_new_with_mnemonic_from_widget(
 			GTK_RADIO_BUTTON(props_dialog->label_btn), BODY);
+	CLAWS_SET_TIP(props_dialog->message_btn, _("Only scan message body"));
 	props_dialog->both_btn =
 		gtk_radio_button_new_with_mnemonic_from_widget(
 			GTK_RADIO_BUTTON(props_dialog->label_btn), BOTH);
+	CLAWS_SET_TIP(props_dialog->both_btn, _("Scan both message headers and message body"));
 	gtk_widget_set_name(props_dialog->source, "source");
 	add_current_config(vitem, props_dialog);
 

commit a64dce323775ee34919c45021ba6549fd14ba19c
Merge: 008682b 82866a2
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sat Jun 21 20:00:26 2014 +0200

    Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws into vfolder


commit 008682b19a6d627434c9580a3161d20c68255e7e
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sat Jun 21 19:59:53 2014 +0200

    Ready for release in the wild

diff --git a/src/plugins/vfolder/Makefile.am b/src/plugins/vfolder/Makefile.am
index 0808e93..eb51703 100644
--- a/src/plugins/vfolder/Makefile.am
+++ b/src/plugins/vfolder/Makefile.am
@@ -12,13 +12,11 @@ vfolder_la_SOURCES = \
 		vfolder.c \
 		vfolder_init.c \
 		vfolder_gtk.c \
-		vfolder_prop.c
-
-nodist_include_HEADERS = \
+		vfolder_prop.c \
 		vfolder_gtk.h \
 		vfolder_prop.h
 
-vfolderincludedir = $(pkgincludedir)/plugins/@PACKAGE@
+vfolderincludedir = $(includedir)/claws-mail/vfolder
 vfolderinclude_HEADERS = \
 			vfolder.h
 
diff --git a/src/plugins/vfolder/TODO b/src/plugins/vfolder/TODO
index 8b13789..d6fca1e 100644
--- a/src/plugins/vfolder/TODO
+++ b/src/plugins/vfolder/TODO
@@ -1 +1,7 @@
-
+- enable recursive behavior. Since filenames are not unique outside of a
+folder item this will require a lot of code.
+- use claws' built-in quick search. Add button to create a virtual folder
+using the result of search. Since quick search has the ability to make recursive
+searches this whish depends on whether recursive behavior is implemented
+in the VFolder plugin.
+- add 'Create virtual folder' to main context menu.
diff --git a/src/plugins/vfolder/vfolder.c b/src/plugins/vfolder/vfolder.c
index ea56977..c821a28 100644
--- a/src/plugins/vfolder/vfolder.c
+++ b/src/plugins/vfolder/vfolder.c
@@ -6,7 +6,8 @@
 /*
  * Virtual folder plugin for claws-mail
  *
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -43,6 +44,8 @@
 #include "main.h"
 #include "localfolder.h"
 #include "statusbar.h"
+#include "mainwindow.h"
+#include "folderview.h"
 
 #include "vfolder.h"
 #include "vfolder_gtk.h"
@@ -94,6 +97,20 @@ static GHashTable* vfolder_vfolders_new() {
 			g_str_equal, g_free, vfolder_free_hashtable);
 }
 
+static void vfolder_vfolders_config_save() {
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_hash_table_iter_init (&iter, vfolders);
+	while (g_hash_table_iter_next(&iter, &key, &value)) {
+		if (value) {
+			VFolderItem* vitem = VFOLDER_ITEM(value);
+			FolderPropsResponse resp = vfolder_folder_item_props_write(vitem);
+			vfolder_item_props_response(resp);
+		}
+	}
+}
+
 static void vfolder_msgvault_add_msg(MsgPair* msgpair) {
 	VFolderItem* vitem = msgpair->vitem;
 	guint* snum = GUINT_TO_POINTER(msgpair->src);
@@ -147,9 +164,11 @@ static void vfolder_init_read_func(FolderItem* item, gpointer data) {
 
 	vfolder_set_msgs_filter(VFOLDER_ITEM(item));
 
-/*	if (! IS_VFOLDER_FROZEN(VFOLDER_ITEM(item))) {
+/*
+	if (! VFOLDER_ITEM(item)->frozen) {
 		folder_item_scan(VFOLDER_ITEM(item)->source);
-	}*/
+	}
+*/
 }
 
 static void vfolder_make_rc_dir(void) {
@@ -555,6 +574,8 @@ static gint vfolder_add_msg(Folder* folder, FolderItem* dest, const gchar* file,
 }
 
 static gchar* vfolder_fetch_msg(Folder* folder, FolderItem* item, gint num) {
+	if (num < 0) return NULL;
+
 	gchar* snum = g_strdup_printf("%d", num);
 	gchar* file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, VFOLDER_DIR,
 			G_DIR_SEPARATOR_S, item->path, G_DIR_SEPARATOR_S, snum, NULL);
@@ -608,11 +629,11 @@ static gint vfolder_remove_msg(Folder* folder, FolderItem* item, gint num) {
 	file = vfolder_fetch_msg(folder, item, num);
 	if (! is_file_exist(file)) {
 		/* num relates to source */
-		vnum = vfolder_get_virtual_msg_num(VFOLDER_ITEM(item), num);
 		g_free(file);
+		vnum = vfolder_get_virtual_msg_num(VFOLDER_ITEM(item), num);
 		file = vfolder_fetch_msg(folder, item, vnum);
 	}
-	cm_return_val_if_fail(file != NULL, -1);
+	if (! file) return -1;
 
 	if (claws_unlink(file) < 0) {
 		FILE_OP_ERROR(file, "unlink");
@@ -658,6 +679,16 @@ static gboolean vfolder_subscribe_uri(Folder* folder, const gchar* uri) {
 	return FALSE;
 }
 
+static gint vfolder_folder_rename(Folder *folder, FolderItem *item, const gchar	*name) {
+	cm_return_val_if_fail(item != NULL, -1);
+
+	if (item->name)
+		g_free(item->name);
+	item->name = g_strdup(name);
+
+	return 0;
+}
+
 FolderClass* vfolder_folder_get_class() {
 	if (vfolder_class.idstr == NULL ) {
 		vfolder_class.type = F_UNKNOWN;
@@ -673,14 +704,11 @@ FolderClass* vfolder_folder_get_class() {
 		vfolder_class.create_tree = vfolder_create_tree;
 
 		/* FolderItem functions */
-/*
-		vfolder_class.rename_folder = NULL;
-*/
 		vfolder_class.item_new = vfolder_item_new;
 		vfolder_class.item_destroy = vfolder_item_destroy;
 		vfolder_class.item_get_path = vfolder_item_get_path;
 		vfolder_class.create_folder = vfolder_folder_create;
-		vfolder_class.rename_folder = NULL;
+		vfolder_class.rename_folder = vfolder_folder_rename;
 		vfolder_class.remove_folder = vfolder_folder_remove;
 		vfolder_class.get_num_list = vfolder_get_num_list;
 		vfolder_class.scan_required = vfolder_scan_required;
@@ -734,7 +762,9 @@ void vfolder_done(void) {
 
 	vfolder_gtk_done();
 
-    g_hash_table_destroy(vfolders);
+	vfolder_vfolders_config_save();
+
+	g_hash_table_destroy(vfolders);
 
 	if (!claws_is_exiting())
 		folder_unregister_class(vfolder_folder_get_class());
@@ -1001,3 +1031,41 @@ VFolderItem* vfolder_folder_item_watch(FolderItem* item) {
 
 	return match;
 }
+
+void vfolder_source_path_change(VFolderItem* vitem, FolderItem* newItem) {
+	VFolderItem* newVitem = NULL;
+	gpointer key, value;
+
+	cm_return_if_fail(vitem != NULL);
+
+	if (g_hash_table_lookup_extended(vfolders, vitem->source_id, &key, &value)) {
+		g_hash_table_steal(vfolders, vitem->source_id);
+		g_free(key);
+		newVitem = VFOLDER_ITEM(value);
+		newVitem->source = newItem;
+		g_free(newVitem->source_id);
+		newVitem->source_id = folder_item_get_identifier(newItem);
+		g_hash_table_replace(vfolders, g_strdup(newVitem->source_id), newVitem);
+	}
+}
+
+void vfolder_source_folder_remove(VFolderItem* vitem) {
+	cm_return_if_fail(vitem != NULL);
+
+	MainWindow* mainwindow = mainwindow_get_mainwindow();
+	FolderView* folderview = mainwindow->folderview;
+	gchar *id1, *id2;
+
+	if (! vitem->frozen) {
+		FolderItem* item = folderview_get_selected_item(folderview);
+		if (item) {
+			id1 = folder_item_get_identifier(item);
+			id2 = folder_item_get_identifier(FOLDER_ITEM(vitem));
+			if (strcmp(id1, id2) == 0)
+				folderview_close_opened(folderview);
+			g_free(id1);
+			g_free(id2);
+		}
+		vfolder_folder_remove(FOLDER_ITEM(vitem)->folder, FOLDER_ITEM(vitem));
+	}
+}
diff --git a/src/plugins/vfolder/vfolder.h b/src/plugins/vfolder/vfolder.h
index 8a2406e..41655d0 100644
--- a/src/plugins/vfolder/vfolder.h
+++ b/src/plugins/vfolder/vfolder.h
@@ -6,7 +6,9 @@
 
 /*
  * Virtual folder plugin for claws-mail
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -63,7 +65,7 @@ typedef MsgInfoList* (*MSGFILTERFUNC) (MsgInfoList* msgs, VFolderItem* item);
 struct _VFolderItem {
 	FolderItem		item;
 
-	gchar*			filter;				/* Regex used to select messages */
+	gchar*			filter;				/* Glob used to select messages */
 	gboolean		frozen;				/* Automatic update or not */
 	gboolean		updating;			/* Is this VFolder currently updating */
 	gboolean		changed;
@@ -101,6 +103,8 @@ void vfolder_scan_source_folder(VFolderItem * vitem);
 void vfolder_scan_source_folder_list(GSList* vitems);
 void vfolder_scan_source_folder_all();
 VFolderItem* vfolder_folder_item_watch(FolderItem* item);
+void vfolder_source_path_change(VFolderItem* vitem, FolderItem* newItem);
+void vfolder_source_folder_remove(VFolderItem* vitem);
 
 G_END_DECLS
 
diff --git a/src/plugins/vfolder/vfolder_gtk.c b/src/plugins/vfolder/vfolder_gtk.c
index ffaa320..2f4e488 100644
--- a/src/plugins/vfolder/vfolder_gtk.c
+++ b/src/plugins/vfolder/vfolder_gtk.c
@@ -6,7 +6,8 @@
 /*
  * Virtual folder plugin for claws-mail
  *
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -60,7 +61,6 @@
 static guint folder_hook_id;
 static guint item_hook_id;
 static guint msginfo_hook_id;
-//static GSList* widgets = NULL;
 
 typedef struct {
 	MsgInfoList*	list;
@@ -89,7 +89,7 @@ static GtkActionEntry vfolder_popup_entries[] = {
 
 	{"FolderViewPopup/FolderProperties",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_properties_cb) },
 
-	{"FolderViewPopup/RenameFolder",	NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
+	{"FolderViewPopup/RenameFolder",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_rename_cb) },
 
 	{"FolderViewPopup/NewFolder",		NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_new_folder_cb) },
 	{"FolderViewPopup/RemoveFolder",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_remove_folder_cb) },
@@ -112,9 +112,8 @@ static void vfolder_set_sensitivity(GtkUIManager *ui_manager, FolderItem *item)
 #define SET_SENS(name, sens) \
 	cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
 
-	VFolderItem* vitem = VFOLDER_ITEM(item);
-	SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL && ! vitem->frozen);
-	SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL && ! vitem->frozen);
+	SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL);
+	SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL);
 	SET_SENS("FolderViewPopup/FolderProperties", folder_item_parent(item) != NULL);
 	SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(item) != NULL);
 	SET_SENS("FolderViewPopup/NewFolder", TRUE);
@@ -144,6 +143,7 @@ static void vfolder_fill_popup_menu_labels(void) {
 
 static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
 	FolderUpdateData* hookdata;
+	VFolderItem* vitem;
 
 	g_return_val_if_fail(source != NULL, FALSE);
 	hookdata = (FolderUpdateData *) source;
@@ -151,39 +151,21 @@ static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
 	if (! hookdata->folder || IS_VFOLDER_FOLDER(hookdata->folder))
 		return FALSE;
 
-	if (hookdata->update_flags & FOLDER_ADD_FOLDER) {
-		/* TODO: check if the added folder is foundation for vfolder */
-		debug_print("FOLDER_ADD_FOLDER\n");
-	}
-
-	if (hookdata->update_flags & FOLDER_REMOVE_FOLDER) {
-		/* TODO: check if the removed folder is foundation for vfolder */
-		debug_print("FOLDER_REMOVE_FOLDER\n");
-	}
-
-	if (hookdata->update_flags & FOLDER_TREE_CHANGED) {
-		/* TODO: check if the changed folder tree affects any vfolder */
-		debug_print("FOLDER_TREE_CHANGED\n");
-	}
-
-	if (hookdata->update_flags & FOLDER_ADD_FOLDERITEM) {
-		/* TODO: check if the added folder item affects any vfolder */
-		debug_print("FOLDER_ADD_FOLDERITEM\n");
-	}
-
 	if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) {
 		/* TODO: check if the removed folder item is foundation for vfolder */
 		debug_print("FOLDER_REMOVE_FOLDERITEM\n");
-	}
-
-	if (hookdata->update_flags & FOLDER_RENAME_FOLDERITEM) {
-		/* TODO: can renaming a folder item affect any vfolder? */
-		debug_print("FOLDER_RENAME_FOLDERITEM\n");
+		vitem = vfolder_folder_item_watch(hookdata->item);
+		if (vitem) {
+			vfolder_source_folder_remove(vitem);
+		}
 	}
 
 	if (hookdata->update_flags & FOLDER_MOVE_FOLDERITEM) {
-		/* TODO: check if the moved folder item is foundation for vfolder */
 		debug_print("FOLDER_MOVE_FOLDERITEM\n");
+		/* item = from item2 = to */
+		vitem = vfolder_folder_item_watch(hookdata->item);
+		if (vitem)
+			vfolder_source_path_change(vitem, hookdata->item2);
 	}
 
 	return FALSE;
@@ -199,35 +181,13 @@ static gboolean vfolder_folder_item_update_hook(gpointer source, gpointer data)
 	if (! hookdata->item || IS_VFOLDER_FOLDER_ITEM(hookdata->item))
 		return FALSE;
 
-	if (hookdata->update_flags & F_ITEM_UPDATE_MSGCNT &&
-	    ~ hookdata->update_flags & (F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT)) {
-		debug_print("F_ITEM_UPDATE_MSGCNT\n");
-/*		vitem = vfolder_folder_item_watch(hookdata->item);
-		if (vitem && ! vitem->updating)
-			vfolder_scan_source_folder(vitem);*/
-	}
-
-	if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT /*&&
-		~ hookdata->update_flags & (F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT)*/) {
+	if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT) {
 		debug_print("F_ITEM_UPDATE_CONTENT\n");
 		vitem = vfolder_folder_item_watch(hookdata->item);
-		if (vitem && ! vitem->updating)
+		if (vitem && ! vitem->updating && ! vitem->frozen)
 			vfolder_scan_source_folder(vitem);
 	}
 
-	if (hookdata->update_flags & F_ITEM_UPDATE_ADDMSG) {
-		debug_print("F_ITEM_UPDATE_ADDMSG\n");
-	}
-
-	if (hookdata->update_flags & F_ITEM_UPDATE_REMOVEMSG ) {
-		debug_print("F_ITEM_UPDATE_REMOVEMSG\n");
-	}
-
-	if (hookdata->update_flags & F_ITEM_UPDATE_NAME) {
-		/* TODO: need update? */
-		debug_print("F_ITEM_UPDATE_NAME\n");
-	}
-
 	return FALSE;
 }
 
@@ -246,13 +206,6 @@ static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
 	if (IS_VFOLDER_MSGINFO(msginfo))
 		return FALSE;
 
-	if (MSG_IS_NEW(msginfo->flags)) {
-		vitem = vfolder_folder_item_watch(msginfo->folder);
-		if (vitem) {
-			debug_print("MSG_IS_NEW\n");
-		}
-	}
-
 	if (MSG_IS_DELETED(msginfo->flags)) {
 		vitem = vfolder_folder_item_watch(msginfo->folder);
 		if (vitem) {
@@ -271,8 +224,8 @@ static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
 			g_free(msg);
 			return FALSE;
 		}
-		vitem = vfolder_folder_item_watch(msginfo->to_folder);
-		if (! vitem) {
+		vitem = vfolder_folder_item_watch(msginfo->folder);
+		if (vitem && ! vitem->frozen) {
 			/*
 			 * if folder we move to is already monitored we need not
 			 * do anything since distination folder will be automatically
@@ -282,14 +235,6 @@ static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
 		}
 	}
 
-	if (MSG_IS_MOVE_DONE(msginfo->flags)) {
-		vitem = vfolder_folder_item_watch(msginfo->to_folder);
-		if (vitem) {
-			return FALSE;
-		}
-		debug_print("MSG_IS_MOVE\n");
-	}
-
 	if (MSG_IS_COPY(msginfo->flags)) {
 		debug_print("MSG_IS_COPY\n");
 		if (IS_VFOLDER_FOLDER_ITEM(msginfo->to_folder)) {
@@ -498,49 +443,49 @@ void vfolder_properties_cb(GtkAction* action, gpointer data) {
 	g_return_if_fail(item->folder != NULL);
 
 	if (vfolder_edit_item_dialog(VFOLDER_ITEM(item), NULL)) {
-		/* TODO: update */
-		if (debug_get_mode()) {
-//			GHashTableIter iter;
-//			gpointer key, value;
-
-/*			g_hash_table_iter_init(&iter, VFOLDER_ITEM(item)->me_to_claws);
-			while (g_hash_table_iter_next(&iter, &key, &value)) {
-				gchar* buf = g_new0(gchar, BUFSIZ);
-				MsgInfo* msginfo = vfolder_find_msg_from_vfolder_num(
-					VFOLDER_ITEM(item), GPOINTER_TO_UINT(key));
-				FILE* msg = procmsg_open_message(msginfo);
-				while (fread(buf, 1, BUFSIZ - 1, msg) > 0) {
-					fprintf(stderr, "%s", buf);
-					g_free(buf);
-					buf = g_new0(gchar, BUFSIZ);
-				}
-				fprintf(stderr, "\n");
-				if (buf)
-					g_free(buf);
-				fclose(msg);
-			}*/
-		}
+		FolderPropsResponse resp = vfolder_folder_item_props_write(VFOLDER_ITEM(item));
+		vfolder_item_props_response(resp);
 	}
 }
 
+void vfolder_rename_cb(GtkAction* action, gpointer data) {
+	FolderView *folderview = (FolderView *)data;
+	FolderItem *item;
+	gchar *new_name, *old_name;
+
+    item = folderview_get_selected_item(folderview);
+	cm_return_if_fail(item != NULL);
+	cm_return_if_fail(item->path != NULL);
+	cm_return_if_fail(item->folder != NULL);
+
+	old_name = folder_item_get_name(item);
+	new_name = input_dialog(_("Rename folder"),
+					_("Input the new name for folder:"),
+					old_name);
+	g_free(old_name);
+	if (!new_name) return;
+	AUTORELEASE_STR(new_name, {g_free(new_name); return;});
+
+	folder_item_rename(item, new_name);
+}
+
 void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
 	FolderView *folderview = (FolderView *)data;
 	FolderItem *item, *new_item, *parent;
 	gchar* new_folder;
 	gchar* name;
 	gchar* p;
-	gchar* id;
 
     item = folderview_get_selected_item(folderview);
-	cm_return_if_fail(item != NULL);
-	cm_return_if_fail(item->path != NULL);
-	cm_return_if_fail(item->folder != NULL);
+    if (item) {
+		cm_return_if_fail(item->path != NULL);
+		cm_return_if_fail(item->folder != NULL);
 
-	if (item->no_sub) {
-		alertpanel_error(N_("Virtual folders cannot contain subfolders"));
-		return;
+		if (item->no_sub) {
+			alertpanel_error(N_("Virtual folders cannot contain subfolders"));
+			return;
+		}
 	}
-
 	new_folder = input_dialog(_("New folder"),
 				  _("Input the name of new folder:"),
 				  _("NewFolder"));
@@ -577,16 +522,12 @@ void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
 		return;
 	}
 
-	id = folder_item_get_identifier(item);
 	if (vfolder_msgvault_add(VFOLDER_ITEM(new_item))) {
 		new_item->folder->klass->remove_folder(new_item->folder, new_item);
 		new_item = NULL;
-		g_free(id);
 		return;
 	}
 
-	g_free(id);
-
 	folder_write_list();
 }
 
diff --git a/src/plugins/vfolder/vfolder_gtk.h b/src/plugins/vfolder/vfolder_gtk.h
index 270f337..d6270eb 100644
--- a/src/plugins/vfolder/vfolder_gtk.h
+++ b/src/plugins/vfolder/vfolder_gtk.h
@@ -6,7 +6,9 @@
 
 /*
  * Virtual folder plugin for claws-mail
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,6 +44,7 @@ GtkResponseType vfolder_msg_dialog(GtkMessageType msgtype, GtkButtonsType btntyp
 
 /* Callback functions */
 void vfolder_new_folder_cb(GtkAction* action, gpointer data);
+void vfolder_rename_cb(GtkAction* action, gpointer data);
 void vfolder_remove_folder_cb(GtkAction* action, gpointer data);
 void vfolder_properties_cb(GtkAction* action, gpointer data);
 void vfolder_refresh_cb(GtkAction* action, gpointer data);
diff --git a/src/plugins/vfolder/vfolder_init.c b/src/plugins/vfolder/vfolder_init.c
index 568f468..0b06023 100644
--- a/src/plugins/vfolder/vfolder_init.c
+++ b/src/plugins/vfolder/vfolder_init.c
@@ -2,11 +2,11 @@
  * $Id: $
  */
 /* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
-
 /*
  * Virtual folder plugin for claws-mail
  *
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/plugins/vfolder/vfolder_prop.c b/src/plugins/vfolder/vfolder_prop.c
index e7485f2..2f08d8b 100644
--- a/src/plugins/vfolder/vfolder_prop.c
+++ b/src/plugins/vfolder/vfolder_prop.c
@@ -2,11 +2,11 @@
  * $Id: $
  */
 /* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
-
 /*
  * Virtual folder plugin for claws-mail
  *
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -129,7 +129,7 @@ static GtkWidget* vfolder_prop_row(GtkWidget* widget,
 	return row;
 }
 
-static gboolean vfolder_set_search_type(VFolderItem* item, GtkWidget* list) {
+static gboolean vfolder_set_search_type(VFolderItem* item, GtkWidget* list, gboolean* update) {
 	GSList *btn_list, *btns;
 	gboolean active = FALSE;
 	GtkToggleButton* btn = NULL;
@@ -166,6 +166,16 @@ static gboolean vfolder_set_search_type(VFolderItem* item, GtkWidget* list) {
 	return FALSE;
 }
 
+static gboolean vfolder_change_source(VFolderItem* vitem, const gchar* str) {
+	if (! vitem->source_id && ! str)
+		return FALSE;
+	if (! vitem->source_id && str)
+		return TRUE;
+	if (vitem->source_id && ! str)
+		return TRUE;
+	return (strcmp(vitem->source_id, str)) ? TRUE : FALSE;
+}
+
 static gboolean vfolder_search_headers(MsgInfo* msg, GPatternSpec* pattern) {
 	return ((msg->cc && g_pattern_match_string(pattern, msg->cc)) ||
 			(msg->from && g_pattern_match_string(pattern, msg->from)) ||
@@ -252,7 +262,7 @@ static gboolean vfolder_create_msgs_list(VFolderItem* item) {
 }
 
 void vfolder_set_msgs_filter(VFolderItem* vfolder_item) {
-	g_return_if_fail(vfolder_item != NULL);
+	cm_return_if_fail(vfolder_item != NULL);
 
 	vfolder_item->msg_filter_func = vfolder_filter_msgs_list;
 }
@@ -260,8 +270,7 @@ void vfolder_set_msgs_filter(VFolderItem* vfolder_item) {
 gboolean vfolder_create_item_dialog(VFolderItem* vitem, FolderItem* item) {
 	gboolean created = FALSE;
 
-	g_return_val_if_fail(vitem != NULL, created);
-	g_return_val_if_fail(item != NULL, created);
+	cm_return_val_if_fail(vitem != NULL, created);
 
 	vitem->msg_filter_func = vfolder_filter_msgs_list;
 
@@ -284,9 +293,9 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item) {
 	gboolean frozen;
 	gchar* old_filter = NULL;
 	FolderItem* old_source;
+	gboolean update = TRUE;
 
-	g_return_val_if_fail(vitem != NULL, ok);
-	g_return_val_if_fail(item != NULL || vitem->source != NULL, ok);
+	cm_return_val_if_fail(vitem != NULL, ok);
 
 	MainWindow *mainwin = mainwindow_get_mainwindow();
 	props_dialog = g_new0(PropsDialog, 1);
@@ -319,13 +328,15 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item) {
 	row = vfolder_prop_row(props_dialog->source, N_("_Source folder"), 130, FALSE);
 	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
 
-	if (!item)
-		id = folder_item_get_identifier(vitem->source);
-	else
-		id = folder_item_get_identifier(item);
-	gtk_entry_set_text(GTK_ENTRY(props_dialog->source), id);
-	gtk_widget_set_sensitive(props_dialog->source, FALSE);
-	g_free(id);
+	if (item || vitem->source) {
+		if (!item)
+			id = folder_item_get_identifier(vitem->source);
+		else
+			id = folder_item_get_identifier(item);
+		gtk_entry_set_text(GTK_ENTRY(props_dialog->source), id);
+		gtk_widget_set_sensitive(props_dialog->source, FALSE);
+		g_free(id);
+	}
 
 	GtkWidget* frame1 = gtk_frame_new(_("Message filter"));
 	GtkWidget* vbox1 = gtk_vbox_new(TRUE, 2);
@@ -368,18 +379,26 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item) {
 				}
 			}
 			else {
-				if (!vitem->filter || strcmp(vitem->filter, str) != 0) {
+				if (vitem->filter && strcmp(vitem->filter, str) == 0)
+					update = FALSE;
+				else {
 					g_free(vitem->filter);
 					vitem->filter = g_strdup(str);
 					ok = TRUE;
 				}
 			}
 		}
-		if (vfolder_set_search_type(vitem, props_dialog->label_btn))
+
+		if (vfolder_set_search_type(vitem, props_dialog->label_btn, &update)) {
+			update = TRUE;
 			ok = TRUE;
+		} else {
+			update = FALSE;
+		}
+
 
 		str = gtk_entry_get_text(GTK_ENTRY(props_dialog->source));
-		if (str) {
+		if (vfolder_change_source(vitem, str)) {
 			if (item) {
 				vitem->source = item;
 			} else {
@@ -426,13 +445,14 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item) {
 				vitem->changed = TRUE;
 			}
 		} else {
-			ok = FALSE;
-			goto error;
+			ok = TRUE;
+			update = FALSE;
 		}
 
 		if (vitem->frozen != frozen) {
 			vitem->frozen = frozen;
 			ok = TRUE;
+			vitem->changed = TRUE;
 		}
 
 	}
diff --git a/src/plugins/vfolder/vfolder_prop.h b/src/plugins/vfolder/vfolder_prop.h
index 4a3e11f..c1fbe06 100644
--- a/src/plugins/vfolder/vfolder_prop.h
+++ b/src/plugins/vfolder/vfolder_prop.h
@@ -1,12 +1,12 @@
 /*
  * $Id: $
- */
-
-/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
-
+* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
+*/
 /*
  * Virtual folder plugin for claws-mail
- * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * Claws Mail is Copyright (C) 1999-2014 by Michael Rasmussen and
+ * the Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by

commit e86757a0887f5fda93fb757f93dd1297dbd26025
Author: Michael Rasmussen <mir at datanom.net>
Date:   Thu Jun 19 02:42:58 2014 +0200

    Framework finished

diff --git a/src/plugins/vfolder/Makefile.am b/src/plugins/vfolder/Makefile.am
index 0d79537..0808e93 100644
--- a/src/plugins/vfolder/Makefile.am
+++ b/src/plugins/vfolder/Makefile.am
@@ -35,3 +35,5 @@ vfolder_la_CPPFLAGS = \
 		-I$(top_srcdir)/src/gtk \
 		$(GLIB_CFLAGS) \
 		$(GTK_CFLAGS)
+
+EXTRA_DIST = TODO
diff --git a/src/plugins/vfolder/TODO b/src/plugins/vfolder/TODO
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/plugins/vfolder/TODO
@@ -0,0 +1 @@
+
diff --git a/src/plugins/vfolder/vfolder.c b/src/plugins/vfolder/vfolder.c
index 330252c..ea56977 100644
--- a/src/plugins/vfolder/vfolder.c
+++ b/src/plugins/vfolder/vfolder.c
@@ -52,29 +52,87 @@ typedef struct {
 	LocalFolder folder;
 } VFolder;
 
+typedef struct {
+	gint			src;
+	gint			dest;
+	VFolderItem*	vitem;
+} MsgPair;
+
+struct _MsgVault {
+	GHashTable*	src_to_virt;
+	GHashTable*	virt_to_src;
+};
+
 FolderClass vfolder_class;
 GHashTable* vfolders;
 static gboolean existing_tree_found = FALSE;
 
-static void free_vfolder_hashtable(gpointer data) {
-	g_return_if_fail(data!= NULL);
+static MsgInfo* vfolder_msgvault_get_msginfo(VFolderItem* vitem, gint num, gboolean vmsginfo) {
+	if (! vitem || ! vitem->msgvault) return NULL;
 
-    GHashTable* vfolder = (GHashTable *) data;
-    g_hash_table_destroy(vfolder);
+	if (vmsginfo) {
+		debug_print("src->dest: Look up [%d] from %s\n", num, vitem->source_id);
+		return g_hash_table_lookup(vitem->msgvault->src_to_virt, GINT_TO_POINTER(num));
+	} else {
+		gchar* id = folder_item_get_identifier(FOLDER_ITEM(vitem));
+		debug_print("dest->src: Look up [%d] from %s\n", num, id);
+		g_free(id);
+		return g_hash_table_lookup(vitem->msgvault->virt_to_src, GINT_TO_POINTER(num));
+	}
 }
 
-static GHashTable* vfolders_hashtable_new() {
-	return g_hash_table_new_full(g_str_hash,
-			g_str_equal, g_free, free_vfolder_hashtable);
+static void vfolder_free_hashtable(gpointer data) {
+	cm_return_if_fail(data!= NULL);
+
+    VFolderItem* vfolder = (VFolderItem *) data;
+    debug_print("%s: Removing virtual folder from folders\n", vfolder->source_id);
+    vfolder_msgvault_free(vfolder->msgvault);
 }
 
-static GHashTable* vfolder_hashtable_new() {
+static GHashTable* vfolder_vfolders_new() {
 	return g_hash_table_new_full(g_str_hash,
-			g_str_equal, g_free, (GDestroyNotify) procmsg_msginfo_free);
+			g_str_equal, g_free, vfolder_free_hashtable);
+}
+
+static void vfolder_msgvault_add_msg(MsgPair* msgpair) {
+	VFolderItem* vitem = msgpair->vitem;
+	guint* snum = GUINT_TO_POINTER(msgpair->src);
+	guint* dnum = GUINT_TO_POINTER(msgpair->dest);
+
+	debug_print("Adding message: src->%d dest->%d\n", GPOINTER_TO_INT(snum), GPOINTER_TO_INT(dnum));
+	if (! vitem->msgvault)
+		vitem->msgvault = vfolder_msgvault_new();
+	g_hash_table_replace(vitem->msgvault->src_to_virt, snum, dnum);
+	g_hash_table_replace(vitem->msgvault->virt_to_src, dnum, snum);
+}
+
+static gboolean vfolder_msgvault_remove_msg(VFolderItem* vitem, gint msgnum) {
+	gboolean ret;
+	MsgVault* msgvault = vitem->msgvault;
+	guint* num = GUINT_TO_POINTER(msgnum);
+	gpointer key;
+
+	if (! msgvault) return FALSE;
+
+	if ((key = g_hash_table_lookup(msgvault->src_to_virt, num)) != NULL) {
+		debug_print("Removing message: src->%d dest->%d\n", msgnum, GPOINTER_TO_INT(key));
+		g_hash_table_remove(msgvault->virt_to_src, key);
+		g_hash_table_remove(msgvault->src_to_virt, num);
+		ret = FALSE;
+	} else if ((key = g_hash_table_lookup(msgvault->virt_to_src, num)) != NULL) {
+		debug_print("Removing message: src->%d dest->%d\n", GPOINTER_TO_INT(key), msgnum);
+		g_hash_table_remove(msgvault->virt_to_src, num);
+		g_hash_table_remove(msgvault->src_to_virt, key);
+		ret = FALSE;
+	} else
+		ret = TRUE;
+
+	return ret;
 }
 
 static void vfolder_init_read_func(FolderItem* item, gpointer data) {
-	g_return_if_fail(item != NULL);
+	cm_return_if_fail(item != NULL);
+	FolderPropsResponse resp;
 
 	if (! IS_VFOLDER_FOLDER_ITEM(item))
 		return;
@@ -84,7 +142,9 @@ static void vfolder_init_read_func(FolderItem* item, gpointer data) {
 	if (folder_item_parent(item) == NULL)
 		return;
 
-	vfolder_folder_item_props_read(VFOLDER_ITEM(item));
+	resp = vfolder_folder_item_props_read(VFOLDER_ITEM(item));
+	vfolder_item_props_response(resp);
+
 	vfolder_set_msgs_filter(VFOLDER_ITEM(item));
 
 /*	if (! IS_VFOLDER_FROZEN(VFOLDER_ITEM(item))) {
@@ -113,12 +173,13 @@ static void vfolder_create_default_mailbox(void) {
 
 	root = folder_new(vfolder_folder_get_class(), VFOLDER_DEFAULT_MAILBOX, NULL);
 
-	g_return_if_fail(root != NULL);
+	cm_return_if_fail(root != NULL);
 
 	folder_add(root);
 }
 
-static Folder* vfolder_new_folder(const gchar* name, const gchar* path) {
+/* Folder functions */
+static Folder* vfolder_folder_new(const gchar* name, const gchar* path) {
 	VFolder* folder;
 
 	debug_print("VFolder: new_folder\n");
@@ -128,11 +189,12 @@ static Folder* vfolder_new_folder(const gchar* name, const gchar* path) {
 	folder = g_new0(VFolder, 1);
 	FOLDER(folder)->klass = &vfolder_class;
 	folder_init(FOLDER(folder), name);
+	FOLDER(folder)->klass->create_tree(FOLDER(folder));
 
 	return FOLDER(folder);
 }
 
-static void vfolder_destroy_folder(Folder* _folder)
+static void vfolder_folder_destroy(Folder* _folder)
 {
 	VFolder* folder = VFOLDER(_folder);
 
@@ -161,8 +223,9 @@ static gint vfolder_create_tree(Folder* folder) {
 }
 
 static gint vfolder_scan_tree(Folder *folder) {
-	g_return_val_if_fail(folder != NULL, -1);
+	cm_return_val_if_fail(folder != NULL, -1);
 
+	folder->inbox = NULL;
 	folder->outbox = NULL;
 	folder->draft = NULL;
 	folder->queue = NULL;
@@ -174,6 +237,427 @@ static gint vfolder_scan_tree(Folder *folder) {
 	return 0;
 }
 
+/* FolderItem functions */
+static gboolean vfolder_scan_required(Folder* folder, FolderItem* item) {
+	cm_return_val_if_fail(item != NULL, FALSE);
+	FolderItem* src = VFOLDER_ITEM(item)->source;
+
+	debug_print("%s: Check if scan is required\n", item->path);
+	cm_return_val_if_fail(src != NULL, FALSE);
+
+	debug_print("mtime src [%ld] mtime VFolder [%ld]\n", src->mtime, item->mtime);
+	if (src->mtime > item->mtime)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static FolderItem* vfolder_item_new(Folder* folder) {
+	VFolderItem* vitem;
+
+	debug_print("VFolder: item_new\n");
+
+	vitem = g_new0(VFolderItem, 1);
+
+	vitem->filter = NULL;
+	vitem->frozen = FALSE;
+	vitem->updating = FALSE;
+	vitem->changed = TRUE;
+	vitem->source_id = NULL;
+	vitem->search = SEARCH_HEADERS;
+	vitem->source = NULL;
+	vitem->msgvault = vfolder_msgvault_new();
+
+	return FOLDER_ITEM(vitem);
+}
+
+static void vfolder_item_destroy(Folder* folder, FolderItem* item) {
+	VFolderItem* vitem = VFOLDER_ITEM(item);
+
+	cm_return_if_fail(vitem != NULL);
+
+	if (vitem->source_id) {
+		debug_print("%s: Removing virtual folder from message store\n", vitem->source_id);
+		g_hash_table_remove(vfolders, vitem->source_id);
+		g_free(vitem->source_id);
+		vitem->source_id = NULL;
+	}
+
+	g_free(vitem->filter);
+	vitem->filter = NULL;
+	vitem->msgvault = NULL;
+	vitem->source = NULL;
+
+	g_free(item);
+	item = NULL;
+}
+
+static gchar* vfolder_item_get_path(Folder* folder, FolderItem* item) {
+	gchar* result;
+
+	cm_return_val_if_fail(item != NULL, NULL);
+
+	result = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, VFOLDER_DIR,
+			G_DIR_SEPARATOR_S, item->path, NULL);
+	return result;
+}
+
+static gint vfolder_folder_remove(Folder* folder, FolderItem* item) {
+	GDir* dp;
+	const gchar* name;
+	gchar* cwd;
+	gint ret = -1;
+
+	cm_return_val_if_fail(folder != NULL, -1);
+	cm_return_val_if_fail(item != NULL, -1);
+	cm_return_val_if_fail(item->path != NULL, -1);
+	cm_return_val_if_fail(item->stype == F_NORMAL, -1);
+
+	debug_print("VFolder: removing folder item %s\n", item->path);
+
+	gchar* path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+		VFOLDER_DIR, G_DIR_SEPARATOR_S, item->path, NULL);
+	remove_numbered_files(path, item->last_num - item->total_msgs + 1, item->last_num);
+
+	folder_item_remove(item);
+
+	cwd = g_get_current_dir();
+
+	if (change_dir(path) < 0 ) {
+		g_free(path);
+		return ret;
+	}
+
+	if( (dp = g_dir_open(".", 0, NULL)) == NULL ) {
+		FILE_OP_ERROR(path, "g_dir_open");
+		change_dir(cwd);
+		g_free(cwd);
+		g_free(path);
+		return ret;
+	}
+
+	while ((name = g_dir_read_name(dp)) != NULL) {
+		debug_print("Removing: %s\n", name);
+		claws_unlink(name);
+	}
+
+	g_dir_close(dp);
+	change_dir(cwd);
+	if (g_rmdir(path) == 0)
+		ret = 0;
+
+	g_free(cwd);
+	g_free(path);
+
+	return ret;
+}
+
+static FolderItem* vfolder_folder_create(Folder* folder,
+									   	 FolderItem* parent,
+									   	 const gchar* name) {
+	gchar* path = NULL;
+	FolderItem* newitem = NULL;
+
+	cm_return_val_if_fail(folder != NULL, NULL);
+	cm_return_val_if_fail(parent != NULL, NULL);
+	cm_return_val_if_fail(name != NULL, NULL);
+
+	if (parent->no_sub)
+		return NULL;
+
+	path = g_strconcat((parent->path != NULL) ? parent->path : "", name, NULL);
+	newitem = folder_item_new(folder, name, path);
+	newitem->no_sub = TRUE;
+
+	folder_item_append(parent, newitem);
+	g_free(path);
+
+	return newitem;
+}
+
+static gint vfolder_get_num_list(Folder* folder, FolderItem* item,
+		MsgNumberList** list, gboolean* old_uids_valid) {
+	gchar* path;
+	DIR* dp;
+	struct dirent* d;
+	gint num, nummsgs = 0;
+
+	cm_return_val_if_fail(item != NULL, -1);
+
+	debug_print("VFolder: scanning '%s'...\n", item->path);
+
+	if (vfolder_scan_required(folder, item))
+		vfolder_scan_source_folder(VFOLDER_ITEM(item));
+	else
+		item->mtime = time(NULL);
+
+	*old_uids_valid = TRUE;
+
+	path = folder_item_get_path(item);
+	cm_return_val_if_fail(path != NULL, -1);
+	if (change_dir(path) < 0 ) {
+		g_free(path);
+		return -1;
+	}
+	g_free(path);
+
+	if( (dp = opendir(".")) == NULL ) {
+		FILE_OP_ERROR(item->path, "opendir");
+		return -1;
+	}
+
+	while ((d = readdir(dp)) != NULL ) {
+		if( (num = to_number(d->d_name)) > 0 ) {
+			debug_print("Adding %d to list\n", num);
+			*list = g_slist_prepend(*list, GINT_TO_POINTER(num));
+			nummsgs++;
+		}
+	}
+	closedir(dp);
+
+	return nummsgs;
+}
+
+/* Message functions */
+static void vfolder_get_last_num(Folder *folder, FolderItem *item) {
+	gchar *path;
+	DIR *dp;
+	struct dirent *d;
+	gint max = 0;
+	gint num;
+
+	cm_return_if_fail(item != NULL);
+
+	debug_print("vfolder_get_last_num(): Scanning %s ...\n", item->path);
+	path = folder_item_get_path(item);
+	cm_return_if_fail(path != NULL);
+
+	if (! is_dir_exist(path)) return;
+
+	if (change_dir(path) < 0) {
+		g_free(path);
+		return;
+	}
+	g_free(path);
+
+	if ((dp = opendir(".")) == NULL) {
+		FILE_OP_ERROR(item->path, "opendir");
+		return;
+	}
+
+	while ((d = readdir(dp)) != NULL) {
+		if ((num = to_number(d->d_name)) > 0 && dirent_is_regular_file(d)) {
+			if( max < num )
+				max = num;
+		}
+	}
+	closedir(dp);
+
+	debug_print("Last number in dir %s = %d\n", item->path, max);
+	item->last_num = max;
+}
+
+static gchar* vfolder_get_new_msg_filename(FolderItem* dest) {
+	gchar* destfile;
+	gchar* destpath;
+
+	destpath = folder_item_get_path(dest);
+	cm_return_val_if_fail(destpath != NULL, NULL);
+
+	if (!is_dir_exist(destpath))
+		make_dir_hier(destpath);
+
+	for( ; ; ) {
+		destfile = g_strdup_printf("%s%c%d", destpath, G_DIR_SEPARATOR,
+				dest->last_num + 1);
+		if (is_file_entry_exist(destfile)) {
+			dest->last_num++;
+			g_free(destfile);
+		} else
+			break;
+	}
+
+	g_free(destpath);
+
+	return destfile;
+}
+
+static gint vfolder_add_msgs(Folder* folder, FolderItem* dest, GSList* file_list,
+		GHashTable* relation) {
+	gchar* destfile;
+	GSList* cur;
+	MsgFileInfo* fileinfo;
+	VFolderItem* vitem;
+
+	cm_return_val_if_fail(dest != NULL, -1);
+	cm_return_val_if_fail(file_list != NULL, -1);
+
+	vitem = VFOLDER_ITEM(dest);
+	if (dest->last_num < 0) {
+		vfolder_get_last_num(folder, dest);
+		if (dest->last_num < 0)
+			dest->last_num = 0;
+	}
+
+	for( cur = file_list; cur != NULL; cur = cur->next ) {
+		fileinfo = (MsgFileInfo *)cur->data;
+
+		destfile = vfolder_get_new_msg_filename(dest);
+		if (! destfile)
+			goto bail;
+
+		if (copy_file(fileinfo->file, destfile, TRUE) < 0) {
+			g_warning("can't copy message %s to %s\n", fileinfo->file, destfile);
+			g_free(destfile);
+			destfile = NULL;
+			goto bail;
+		}
+
+		if( relation != NULL )
+			g_hash_table_insert(relation, fileinfo,
+					GINT_TO_POINTER(dest->last_num + 1) );
+		g_free(destfile);
+
+		MsgPair* pair = g_new0(MsgPair, 1);
+		pair->src = fileinfo->msginfo->msgnum;
+		pair->dest = dest->last_num + 1;
+		pair->vitem = vitem;
+		vfolder_msgvault_add_msg(pair);
+		g_free(pair);
+		dest->last_num++;
+		vitem->changed = TRUE;
+	}
+
+	FolderPropsResponse resp = vfolder_folder_item_props_write(VFOLDER_ITEM(dest));
+	vfolder_item_props_response(resp);
+
+bail:
+
+	return (destfile) ? dest->last_num : -1;
+}
+
+static gint vfolder_add_msg(Folder* folder, FolderItem* dest, const gchar* file,
+		MsgFlags* flags) {
+	gint ret;
+	GSList file_list;
+	MsgFileInfo fileinfo;
+
+	cm_return_val_if_fail(file != NULL, -1);
+
+	fileinfo.msginfo = NULL;
+	fileinfo.file = (gchar *)file;
+	fileinfo.flags = flags;
+	file_list.data = &fileinfo;
+	file_list.next = NULL;
+
+	ret = vfolder_add_msgs(folder, dest, &file_list, NULL);
+	return ret;
+}
+
+static gchar* vfolder_fetch_msg(Folder* folder, FolderItem* item, gint num) {
+	gchar* snum = g_strdup_printf("%d", num);
+	gchar* file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, VFOLDER_DIR,
+			G_DIR_SEPARATOR_S, item->path, G_DIR_SEPARATOR_S, snum, NULL);
+
+	debug_print("VFolder: fetch_msg: '%s'\n", file);
+
+	g_free(snum);
+
+	return file;
+}
+
+static MsgInfo* vfolder_get_msginfo(Folder* folder, FolderItem* item, gint num) {
+	MsgInfo* msginfo = NULL;
+	gchar* file;
+	MsgFlags flags;
+
+	debug_print("VFolder: get_msginfo: %d\n", num);
+
+	cm_return_val_if_fail(folder != NULL, NULL);
+	cm_return_val_if_fail(item != NULL, NULL);
+	cm_return_val_if_fail(num > 0, NULL);
+
+	file = vfolder_fetch_msg(folder, item, num);
+	if (! g_file_test(file, G_FILE_TEST_EXISTS)) {
+		g_free(file);
+		return NULL;
+	}
+
+	flags.perm_flags = MSG_NEW | MSG_UNREAD;
+	flags.tmp_flags = 0;
+
+	msginfo = procheader_parse_file(file, flags, TRUE, TRUE);
+
+	if (msginfo)
+		msginfo->msgnum = num;
+
+	if (!msginfo->folder)
+		msginfo->folder = item;
+
+	g_free(file);
+
+	return msginfo;
+}
+
+static gint vfolder_remove_msg(Folder* folder, FolderItem* item, gint num) {
+	gchar* file;
+	gint vnum;
+
+	cm_return_val_if_fail(item != NULL, -1);
+
+	file = vfolder_fetch_msg(folder, item, num);
+	if (! is_file_exist(file)) {
+		/* num relates to source */
+		vnum = vfolder_get_virtual_msg_num(VFOLDER_ITEM(item), num);
+		g_free(file);
+		file = vfolder_fetch_msg(folder, item, vnum);
+	}
+	cm_return_val_if_fail(file != NULL, -1);
+
+	if (claws_unlink(file) < 0) {
+		FILE_OP_ERROR(file, "unlink");
+		g_free(file);
+		return -1;
+	}
+
+	vfolder_msgvault_remove_msg(VFOLDER_ITEM(item), num);
+	VFOLDER_ITEM(item)->changed = TRUE;
+
+	FolderPropsResponse resp = vfolder_folder_item_props_write(VFOLDER_ITEM(item));
+	vfolder_item_props_response(resp);
+
+	folder_item_scan(item);
+
+	g_free(file);
+
+	return 0;
+}
+
+static gint vfolder_remove_all_msg(Folder* folder, FolderItem* item) {
+	GSList *msg_list, *list;
+
+	cm_return_val_if_fail(item != NULL, -1);
+
+	msg_list = folder_item_get_msg_list(item);
+	if (msg_list) {
+		for (list = msg_list; list; list = g_slist_next(list)) {
+			MsgInfo* msginfo = (MsgInfo *) list->data;
+			folder_item_remove_msg(item, msginfo->msgnum);
+		}
+	}
+	g_slist_free(msg_list);
+
+	return 0;
+}
+
+static gint vfolder_copy_msg (Folder* folder, FolderItem* dest, MsgInfo* msginfo) {
+	return -1;
+}
+
+static gboolean vfolder_subscribe_uri(Folder* folder, const gchar* uri) {
+	return FALSE;
+}
+
 FolderClass* vfolder_folder_get_class() {
 	if (vfolder_class.idstr == NULL ) {
 		vfolder_class.type = F_UNKNOWN;
@@ -181,35 +665,33 @@ FolderClass* vfolder_folder_get_class() {
 		vfolder_class.uistr = "VFolder";
 
 		/* Folder functions */
-		vfolder_class.new_folder = vfolder_new_folder;
-		vfolder_class.destroy_folder = vfolder_destroy_folder;
+		vfolder_class.new_folder = vfolder_folder_new;
+		vfolder_class.destroy_folder = vfolder_folder_destroy;
 		vfolder_class.set_xml = folder_set_xml;
 		vfolder_class.get_xml = folder_get_xml;
 		vfolder_class.scan_tree = vfolder_scan_tree;
 		vfolder_class.create_tree = vfolder_create_tree;
 
 		/* FolderItem functions */
-/*		vfolder_class.item_new = vfolder_item_new;
+/*
+		vfolder_class.rename_folder = NULL;
+*/
+		vfolder_class.item_new = vfolder_item_new;
 		vfolder_class.item_destroy = vfolder_item_destroy;
 		vfolder_class.item_get_path = vfolder_item_get_path;
-		vfolder_class.create_folder = vfolder_create_folder;
+		vfolder_class.create_folder = vfolder_folder_create;
 		vfolder_class.rename_folder = NULL;
-		vfolder_class.remove_folder = vfolder_remove_folder;
+		vfolder_class.remove_folder = vfolder_folder_remove;
 		vfolder_class.get_num_list = vfolder_get_num_list;
-		vfolder_class.scan_required = vfolder_scan_required;*/
-		vfolder_class.item_new = NULL;
-		vfolder_class.item_destroy = NULL;
-		vfolder_class.item_get_path = NULL;
-		vfolder_class.create_folder = NULL;
-		vfolder_class.rename_folder = NULL;
-		vfolder_class.remove_folder = NULL;
-		vfolder_class.get_num_list = NULL;
-		vfolder_class.scan_required = NULL;
+		vfolder_class.scan_required = vfolder_scan_required;
 
 		/* Message functions */
-/*		vfolder_class.get_msginfo = vfolder_get_msginfo;
-		vfolder_class.fetch_msg = vfolder_fetch_msg;
+/*
 		vfolder_class.copy_msgs = vfolder_copy_msgs;
+*/
+		vfolder_class.get_msginfo = vfolder_get_msginfo;
+		vfolder_class.fetch_msg = vfolder_fetch_msg;
+		vfolder_class.copy_msgs = NULL;
 		vfolder_class.copy_msg = vfolder_copy_msg;
 		vfolder_class.add_msg = vfolder_add_msg;
 		vfolder_class.add_msgs = vfolder_add_msgs;
@@ -217,18 +699,7 @@ FolderClass* vfolder_folder_get_class() {
 		vfolder_class.remove_msgs = NULL;
 		vfolder_class.remove_all_msg = vfolder_remove_all_msg;
 		vfolder_class.change_flags = NULL;
-		vfolder_class.subscribe = vfolder_subscribe_uri;*/
-		vfolder_class.get_msginfo = NULL;
-		vfolder_class.fetch_msg = NULL;
-		vfolder_class.copy_msgs = NULL;
-		vfolder_class.copy_msg = NULL;
-		vfolder_class.add_msg = NULL;
-		vfolder_class.add_msgs = NULL;
-		vfolder_class.remove_msg = NULL;
-		vfolder_class.remove_msgs = NULL;
-		vfolder_class.remove_all_msg = NULL;
-		vfolder_class.change_flags = NULL;
-		vfolder_class.subscribe = NULL;
+		vfolder_class.subscribe = vfolder_subscribe_uri;
 
 		debug_print("VFolder: registered folderclass\n");
 	}
@@ -249,9 +720,9 @@ gboolean vfolder_init(void) {
 		return FALSE;
 	}
 
-	folder_func_to_all_folders((FolderItemFunc)vfolder_init_read_func, NULL);
+    vfolders = vfolder_vfolders_new();
 
-    vfolders = vfolders_hashtable_new();
+	folder_func_to_all_folders((FolderItemFunc)vfolder_init_read_func, NULL);
 
     if (existing_tree_found == FALSE)
         vfolder_create_default_mailbox();
@@ -268,3 +739,265 @@ void vfolder_done(void) {
 	if (!claws_is_exiting())
 		folder_unregister_class(vfolder_folder_get_class());
 }
+
+void vfolder_set_last_num(Folder *folder, FolderItem *item) {
+	gchar *path;
+	DIR *dp;
+	struct dirent *d;
+	gint max = 0;
+	gint num;
+
+	cm_return_if_fail(item != NULL);
+
+	debug_print("vfolder_get_last_num(): Scanning %s ...\n", item->path);
+	path = folder_item_get_path(item);
+	cm_return_if_fail(path != NULL);
+	if( change_dir(path) < 0 ) {
+		g_free(path);
+		return;
+	}
+	g_free(path);
+
+	if( (dp = opendir(".")) == NULL ) {
+		FILE_OP_ERROR(item->path, "opendir");
+		return;
+	}
+
+	while( (d = readdir(dp)) != NULL ) {
+		if( (num = to_number(d->d_name)) > 0 && dirent_is_regular_file(d) ) {
+			if( max < num )
+				max = num;
+		}
+	}
+	closedir(dp);
+
+	debug_print("Last number in dir %s = %d\n", item->path, max);
+	item->last_num = max;
+}
+
+gint vfolder_get_virtual_msg_num(VFolderItem* vitem, gint srcnum) {
+	gpointer val;
+
+	cm_return_val_if_fail(vitem != NULL, -1);
+
+	val = g_hash_table_lookup(vitem->msgvault->src_to_virt, GINT_TO_POINTER(srcnum));
+
+	if (val)
+		return GPOINTER_TO_INT(val);
+	else
+		return -1;
+}
+
+gint vfolder_get_source_msg_num(VFolderItem* vitem, gint virtnum) {
+	gpointer val;
+
+	cm_return_val_if_fail(vitem != NULL, -1);
+
+	val = g_hash_table_lookup(vitem->msgvault->virt_to_src, GINT_TO_POINTER(virtnum));
+
+	if (val)
+		return GPOINTER_TO_INT(val);
+	else
+		return -1;
+}
+
+gboolean vfolder_msgvault_add(VFolderItem* vitem) {
+	cm_return_val_if_fail(vitem != NULL, TRUE);
+	cm_return_val_if_fail(vitem->source_id != NULL, TRUE);
+
+	g_hash_table_replace(vfolders, g_strdup(vitem->source_id), vitem);
+
+	return FALSE;
+}
+
+#define MSGVAULT_GROUP "message vault"
+gboolean vfolder_msgvault_serialize(VFolderItem* vitem, GKeyFile* config) {
+	MsgVault* msgvault;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	cm_return_val_if_fail(vitem != NULL, TRUE);
+	cm_return_val_if_fail(vitem->msgvault != NULL, TRUE);
+	cm_return_val_if_fail(config != NULL, TRUE);
+
+	msgvault = vitem->msgvault;
+	g_hash_table_iter_init (&iter, msgvault->virt_to_src);
+	// Save each key / value pair to file
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		gchar* k = itos(GPOINTER_TO_INT(key));
+		g_key_file_set_integer(config, MSGVAULT_GROUP, g_strdup(k), GPOINTER_TO_INT(value));
+		debug_print("Vault to config: src->%s dest->%d\n", k, GPOINTER_TO_INT(value));
+	}
+
+	return FALSE;
+}
+
+gboolean vfolder_msgvault_restore(VFolderItem* vitem, GKeyFile* config) {
+	MsgVault* msgvault;
+	gchar **keys;
+	gchar **keys_it;
+
+	cm_return_val_if_fail(vitem != NULL, TRUE);
+	cm_return_val_if_fail(config != NULL, TRUE);
+
+	if (!vitem->msgvault)
+		vitem->msgvault = vfolder_msgvault_new();
+	msgvault = vitem->msgvault;
+
+	keys = g_key_file_get_keys (config, MSGVAULT_GROUP, NULL, NULL);
+	keys_it = keys;
+	// Add each key / value pair from file
+	while (keys_it != NULL && (*keys_it) != NULL) {
+		gint value = g_key_file_get_integer(config, MSGVAULT_GROUP, (*keys_it), NULL);
+		gint key = to_number(*keys_it);
+		debug_print("Insert into vault: src->%d dest->%d\n", value, key);
+		g_hash_table_insert(msgvault->virt_to_src, GINT_TO_POINTER(key), GINT_TO_POINTER(value));
+		g_hash_table_insert(msgvault->src_to_virt, GINT_TO_POINTER(value), GINT_TO_POINTER(key));
+		++keys_it;
+	}
+	if (keys != NULL)
+		g_strfreev (keys);
+
+	return FALSE;
+}
+
+MsgVault* vfolder_msgvault_new() {
+	MsgVault* msgvault = g_new0(MsgVault, 1);
+	msgvault->src_to_virt = g_hash_table_new(g_direct_hash, g_direct_equal);
+	msgvault->virt_to_src = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	return msgvault;
+}
+
+void vfolder_msgvault_free(MsgVault* data) {
+	cm_return_if_fail(data != NULL);
+
+	debug_print("Removing message vault\n");
+
+    g_hash_table_destroy(data->src_to_virt);
+    g_hash_table_destroy(data->virt_to_src);
+    g_free(data);
+}
+
+void vfolder_scan_source_folder(VFolderItem * vitem) {
+	MsgInfoList *mlist, *cur, *unfiltered = NULL, *filtered;
+	GSList* filelist = NULL, *tmp;
+	GHashTableIter iter;
+	gpointer key, value;
+	MsgInfo* msginfo;
+	FolderItem* item;
+
+	cm_return_if_fail(vitem != NULL);
+
+	if (! vitem->source) return;
+
+	debug_print("%s: Scanning source [%s]\n", FOLDER_ITEM(vitem)->path, vitem->source_id);
+
+	item = folder_find_item_from_identifier(vitem->source_id);
+	if (! item) return;
+
+	vitem->updating = TRUE;
+	folder_item_scan(item);
+
+	folder_item_update_freeze();
+	mlist = folder_item_get_msg_list(item);
+
+	/* find new messages */
+	for (cur = mlist; cur; cur = g_slist_next(cur)) {
+		msginfo = (MsgInfo *) cur->data;
+		MsgInfo* vmsginfo = vfolder_msgvault_get_msginfo(vitem, msginfo->msgnum, TRUE);
+		if (! vmsginfo)
+			unfiltered = g_slist_append(unfiltered, msginfo);
+		else
+			procmsg_msginfo_free(msginfo);
+	}
+	filtered = vitem->msg_filter_func(unfiltered, vitem);
+	if (filtered) {
+		filelist = procmsg_get_message_file_list(filtered);
+		if (filelist) {
+			gint n = folder_item_add_msgs(FOLDER_ITEM(vitem), filelist, FALSE);
+			FOLDER_ITEM(vitem)->last_num = n;
+			procmsg_message_file_list_free(filelist);
+		}
+		g_slist_free(filtered);
+	}
+	procmsg_msg_list_free(unfiltered);
+
+	/* find removed messages */
+	filelist = NULL;
+	g_hash_table_iter_init (&iter, vitem->msgvault->virt_to_src);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		gint num = GPOINTER_TO_INT(value);
+		msginfo = folder_item_get_msginfo(vitem->source, num);
+		if (! msginfo)
+			filelist = g_slist_prepend(filelist, value);
+		else
+			procmsg_msginfo_free(msginfo);
+	}
+
+	for (tmp = filelist; tmp; tmp = g_slist_next(tmp)) {
+		gint num = GPOINTER_TO_INT(tmp->data);
+		folder_item_remove_msg(FOLDER_ITEM(vitem), num);
+	}
+
+	if (filelist)
+		g_slist_free(filelist);
+
+	if (mlist)
+			g_slist_free(mlist);
+
+	folder_item_update_thaw();
+
+	FOLDER_ITEM(vitem)->mtime = time(NULL);
+	vitem->updating = FALSE;
+}
+
+void vfolder_scan_source_folder_list(GSList* vitems) {
+	GSList* cur;
+	VFolderItem* vitem;
+
+	if (! vitems) return;
+
+	for (cur = vitems; cur; cur = g_slist_next(cur)) {
+		vitem = (VFolderItem *) cur->data;
+		vfolder_scan_source_folder(vitem);
+	}
+}
+
+void vfolder_scan_source_folder_all() {
+	GHashTableIter iter;
+	gpointer key, value;
+	VFolderItem* vitem;
+	GSList* vitems = NULL;
+
+	g_hash_table_iter_init (&iter, vfolders);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		vitem = VFOLDER_ITEM(value);
+		vitems = g_slist_prepend(vitems, vitem);
+	}
+
+	vfolder_scan_source_folder_list(vitems);
+	g_slist_free(vitems);
+}
+
+VFolderItem* vfolder_folder_item_watch(FolderItem* item) {
+	GHashTableIter iter;
+	gpointer key, value;
+	VFolderItem* match = NULL;
+
+	cm_return_val_if_fail(item != NULL, FALSE);
+
+	gchar* id = folder_item_get_identifier(item);
+	if (!id) return FALSE;
+
+	g_hash_table_iter_init (&iter, vfolders);
+	while (g_hash_table_iter_next (&iter, &key, &value) && ! match) {
+		VFolderItem* vitem = VFOLDER_ITEM(value);
+		if (g_utf8_collate(id, vitem->source_id) == 0)
+			match = vitem;
+	}
+
+	g_free(id);
+
+	return match;
+}
diff --git a/src/plugins/vfolder/vfolder.h b/src/plugins/vfolder/vfolder.h
index 51f394d..8a2406e 100644
--- a/src/plugins/vfolder/vfolder.h
+++ b/src/plugins/vfolder/vfolder.h
@@ -41,6 +41,22 @@ G_BEGIN_DECLS
 #define VFOLDER_DEFAULT_MAILBOX	_("Virtual folders")
 
 typedef struct _VFolderItem VFolderItem;
+typedef struct _MsgVault MsgVault;
+
+typedef enum {
+	FOLDER_ITEM_PROPS_OK,
+	FOLDER_ITEM_PROPS_NO_ITEM,
+	FOLDER_ITEM_PROPS_BACKUP_FAIL,
+	FOLDER_ITEM_PROPS_READ_DATA_FAIL,
+	FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL,
+	FOLDER_ITEM_PROPS_READ_USING_DEFAULT
+} FolderPropsResponse;
+
+typedef enum {
+	SEARCH_HEADERS	= 1,				/* from/to/subject */
+	SEARCH_BODY		= 2,				/* message */
+	SEARCH_BOTH		= 4					/* both */
+} SearchType;
 
 typedef MsgInfoList* (*MSGFILTERFUNC) (MsgInfoList* msgs, VFolderItem* item);
 
@@ -50,9 +66,12 @@ struct _VFolderItem {
 	gchar*			filter;				/* Regex used to select messages */
 	gboolean		frozen;				/* Automatic update or not */
 	gboolean		updating;			/* Is this VFolder currently updating */
+	gboolean		changed;
 
+	SearchType		search;
 	FolderItem*		source;				/* Source folder for virtual folder */
-	GHashTable*		msg_store;		    /* Hashtable containing MsgInfo. Key is msginfo_identifier */
+	gchar*			source_id;
+	MsgVault*		msgvault;		    /* Message store */
 	MSGFILTERFUNC	msg_filter_func;	/* Active filter function */
 };
 
@@ -70,6 +89,18 @@ gboolean vfolder_init(void);
 void vfolder_done(void);
 
 FolderClass* vfolder_folder_get_class(void);
+gint vfolder_get_virtual_msg_num(VFolderItem* vitem, gint srcnum);
+gint vfolder_get_source_msg_num(VFolderItem* vitem, gint virtnum);
+void vfolder_set_last_num(Folder *folder, FolderItem *item);
+gboolean vfolder_msgvault_add(VFolderItem* vitem);
+void vfolder_msgvault_free(MsgVault* data);
+MsgVault* vfolder_msgvault_new();
+gboolean vfolder_msgvault_serialize(VFolderItem* vitem, GKeyFile* config);
+gboolean vfolder_msgvault_restore(VFolderItem* vitem, GKeyFile* config);
+void vfolder_scan_source_folder(VFolderItem * vitem);
+void vfolder_scan_source_folder_list(GSList* vitems);
+void vfolder_scan_source_folder_all();
+VFolderItem* vfolder_folder_item_watch(FolderItem* item);
 
 G_END_DECLS
 
diff --git a/src/plugins/vfolder/vfolder_gtk.c b/src/plugins/vfolder/vfolder_gtk.c
index eb037c5..ffaa320 100644
--- a/src/plugins/vfolder/vfolder_gtk.c
+++ b/src/plugins/vfolder/vfolder_gtk.c
@@ -60,7 +60,7 @@
 static guint folder_hook_id;
 static guint item_hook_id;
 static guint msginfo_hook_id;
-static GSList* widgets = NULL;
+//static GSList* widgets = NULL;
 
 typedef struct {
 	MsgInfoList*	list;
@@ -84,8 +84,8 @@ static char* vfolder_popup_menu_labels[] = {
 };
 
 static GtkActionEntry vfolder_popup_entries[] = {
-	{"FolderViewPopup/RefreshFolder",		NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
-	{"FolderViewPopup/RefreshAllFolders",	NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
+	{"FolderViewPopup/RefreshFolder",		NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_refresh_cb) },
+	{"FolderViewPopup/RefreshAllFolders",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_refresh_all_cb) },
 
 	{"FolderViewPopup/FolderProperties",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_properties_cb) },
 
@@ -112,9 +112,9 @@ static void vfolder_set_sensitivity(GtkUIManager *ui_manager, FolderItem *item)
 #define SET_SENS(name, sens) \
 	cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
 
-	VFolderItem *ritem = (VFolderItem *)item;
-	SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL && ! ritem->frozen);
-	SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL && ! ritem->frozen);
+	VFolderItem* vitem = VFOLDER_ITEM(item);
+	SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL && ! vitem->frozen);
+	SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL && ! vitem->frozen);
 	SET_SENS("FolderViewPopup/FolderProperties", folder_item_parent(item) != NULL);
 	SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(item) != NULL);
 	SET_SENS("FolderViewPopup/NewFolder", TRUE);
@@ -142,325 +142,6 @@ static void vfolder_fill_popup_menu_labels(void) {
 	}
 }
 
-static void gslist_menu_item_free(GSList** menu_list) {
-	GSList* list;
-
-	if (! menu_list || ! *menu_list)
-		return;
-
-	for (list = *menu_list; list; list = g_slist_next(list)) {
-		MenuItem* menu = (MenuItem *) list->data;
-		g_free(menu);
-	}
-
-	g_slist_free(*menu_list);
-	*menu_list = NULL;
-}
-
-static gboolean get_menu_widgets() {
-	MainWindow* mainwindow;
-	MenuItem* menuitem = NULL;
-	GtkWidget* widget;
-
-	mainwindow = mainwindow_get_mainwindow();
-	if (mainwindow && mainwindow->ui_manager) {
-		widget = gtk_ui_manager_get_widget(
-			mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/");
-		if (widget) {
-			menuitem = g_new0(MenuItem, 1);
-			menuitem->widget = widget;
-			menuitem->action = gtk_ui_manager_get_action(
-				mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/");
-			widgets = g_slist_prepend(widgets, menuitem);
-		}
-		else
-			return FALSE;
-
-		widget = gtk_ui_manager_get_widget(
-			mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/");
-		if (widget) {
-			menuitem = g_new0(MenuItem, 1);
-			menuitem->widget = widget;
-			menuitem->action = gtk_ui_manager_get_action(
-				mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/");
-			widgets = g_slist_prepend(widgets, menuitem);
-		}
-		else {
-			gslist_menu_item_free(&widgets);
-			return FALSE;
-		}
-
-		widget = gtk_ui_manager_get_widget(
-			mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/");
-		if (widget) {
-			menuitem = g_new0(MenuItem, 1);
-			menuitem->widget = widget;
-			menuitem->action = gtk_ui_manager_get_action(
-				mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/");
-			widgets = g_slist_prepend(widgets, menuitem);
-		}
-		else {
-			gslist_menu_item_free(&widgets);
-			return FALSE;
-		}
-
-		widget = gtk_ui_manager_get_widget(
-			mainwindow->ui_manager, "/Menu/Message/Move/");
-		if (widget) {
-			menuitem = g_new0(MenuItem, 1);
-			menuitem->widget = widget;
-			menuitem->action = gtk_ui_manager_get_action(
-				mainwindow->ui_manager, "/Menu/Message/Move/");
-			widgets = g_slist_prepend(widgets, menuitem);
-		}
-		else {
-			gslist_menu_item_free(&widgets);
-			return FALSE;
-		}
-
-		widget = gtk_ui_manager_get_widget(
-			mainwindow->ui_manager, "/Menu/Message/Trash/");
-		if (widget) {
-			menuitem = g_new0(MenuItem, 1);
-			menuitem->widget = widget;
-			menuitem->action = gtk_ui_manager_get_action(
-				mainwindow->ui_manager, "/Menu/Message/Trash/");
-			widgets = g_slist_prepend(widgets, menuitem);
-		}
-		else {
-			gslist_menu_item_free(&widgets);
-			return FALSE;
-		}
-
-		widget = gtk_ui_manager_get_widget(
-			mainwindow->ui_manager, "/Menu/Message/Delete/");
-		if (widget) {
-			menuitem = g_new0(MenuItem, 1);
-			menuitem->widget = widget;
-			menuitem->action = gtk_ui_manager_get_action(
-				mainwindow->ui_manager, "/Menu/Message/Delete/");
-			widgets = g_slist_prepend(widgets, menuitem);
-		}
-		else {
-			gslist_menu_item_free(&widgets);
-			return FALSE;
-		}
-
-	}
-	else
-		return FALSE;
-
-	return TRUE;
-}
-/*
-static gboolean vfolder_widgets_is_visible() {
-	gboolean visible = TRUE;
-
-	if (widgets && widgets->data) {
-		MenuItem* menu = (MenuItem *) widgets->data;
-		visible = gtk_widget_get_visible(menu->widget);
-	}
-
-	return visible;
-}
-
-static gboolean vfolder_hide_widgets(VFolderItem* item) {
-	GSList* list;
-	MainWindow* mainwindow;
-
-//	if (! item->deep_copy) {
-		for (list = widgets; list; list = g_slist_next(list)) {
-			MenuItem* menu = (MenuItem *) list->data;
-			gtk_widget_hide(menu->widget);
-			gtk_action_block_activate(menu->action);
-		}
-
-		mainwindow = mainwindow_get_mainwindow();
-		if (mainwindow && mainwindow->toolbar) {
-			if (mainwindow->toolbar->trash_btn)
-				gtk_widget_hide(mainwindow->toolbar->trash_btn);
-			if (mainwindow->toolbar->delete_btn)
-				gtk_widget_hide(mainwindow->toolbar->delete_btn);
-		}
-//	}
-	return TRUE;
-}
-*/
-static gboolean vfolder_show_widgets(VFolderItem* item) {
-	GSList* list;
-	MainWindow* mainwindow;
-
-//	if (! item->deep_copy) {
-		for (list = widgets; list; list = g_slist_next(list)) {
-			MenuItem* menu = (MenuItem *) list->data;
-			gtk_widget_show(menu->widget);
-			gtk_action_unblock_activate(menu->action);
-		}
-
-		mainwindow = mainwindow_get_mainwindow();
-		if (mainwindow && mainwindow->toolbar) {
-			if (mainwindow->toolbar->trash_btn)
-				gtk_widget_show(mainwindow->toolbar->trash_btn);
-			if (mainwindow->toolbar->delete_btn)
-				gtk_widget_show(mainwindow->toolbar->delete_btn);
-		}
-//	}
-	return TRUE;
-}
-/*
-static gchar* vfolder_get_message_file_path(VFolderItem* item, MsgInfo* msg) {
-	gchar* path;
-	GSList* list = NULL, *cur;
-	Folder* folder;
-	gboolean old_uid;
-	guint last = 0;
-
-	if (item->deep_copy) {
-		path = procmsg_get_message_file_path(msg);
-	}
-	else {
-		gchar* root = folder_item_get_path(msg->to_folder);
-		folder = msg->to_folder->folder;
-		guint num = folder->klass->get_num_list(folder, msg->to_folder, &list, &old_uid);
-		if (num >= 0) {
-			for (cur = list, last = 0; cur; cur = g_slist_next(cur)) {
-				guint tmp = GPOINTER_TO_UINT(cur->data);
-				if (tmp > last)
-					last = tmp;
-			}
-		}
-		g_slist_free(list);
-
-		path = g_strdup_printf("%s%s%u", root, G_DIR_SEPARATOR_S, last + 1);
-		g_free(root);
-	}
-	return path;
-}
-*/
-
-/*
-static void vfolder_item_update(AddMsgData* msgdata) {
-	MsgInfoList* cur;
-	GSList update;
-	MsgFileInfo fileinfo;
-
-	if (!msgdata->item || !msgdata->list->data)
-		return;
-
-	for (cur = msgdata->list; cur; cur = g_slist_next(cur)) {
-		MsgInfo* msg = (MsgInfo *) cur->data;
-		if (MSG_IS_DELETED(msg->flags)) {
-			folder_item_remove_msg(FOLDER_ITEM(msgdata->item), msg->msgnum);
-		}
-		else {
-			fileinfo.msginfo = msg;
-			fileinfo.flags = &msg->flags;
-			fileinfo.file = msgdata->file;
-			update.data = &fileinfo;
-			update.next = NULL;
-			folder_item_scan(msg->folder);
-			gint n = folder_item_add_msgs(FOLDER_ITEM(msgdata->item), &update, FALSE);
-			gchar* p = strrchr(fileinfo.file, G_DIR_SEPARATOR);
-			p += 1;
-			guint num = to_number((const gchar *) p);
-			vfolder_replace_key_in_bridge(msgdata->item, msg->msgnum, num);
-			FOLDER_ITEM(msgdata->item)->last_num = n;
-		}
-	}
-
-	//procmsg_message_file_list_free(list);
-	//item->msginfos = folder_item_get_msg_list(FOLDER_ITEM(item));
-}
-*/
-/*
-static void add_msg_data_free(AddMsgData** rec) {
-	if (rec && *rec) {
-		AddMsgData* data = *rec;
-		g_slist_free(data->list);
-		g_free(data->file);
-		g_free(data);
-		*rec = NULL;
-	}
-}
-*/
-/*
-static void vfolder_update_affected_folder_items(MsgInfo* msginfo) {
-	GList *vfolders, *cur;
-	GSList* cur_msg;
-	gchar* src;
-	AddMsgData* data;
-	MsgInfo* msg;
-
-	if (! msginfo)
-		return;
-
-	if (MSG_IS_NEW(msginfo->flags) ||
-		MSG_IS_MOVE(msginfo->flags) ||
-		MSG_IS_COPY(msginfo->flags) ||
-		MSG_IS_DELETED(msginfo->flags)) {
-		vfolders = vfolder_get_vfolder_items();
-		for (cur = vfolders; cur; cur = g_list_next(cur)) {
-			data = g_new0(AddMsgData, 1);
-			VFolderItem* vitem = VFOLDER_ITEM(cur->data);
-			if (MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))
-				src = folder_item_get_identifier(msginfo->to_folder);
-			else
-				src = folder_item_get_identifier(msginfo->folder);
-			gchar* shadow = folder_item_get_identifier(vitem->source);
-			debug_print("cmp %s : %s\n", src, shadow);
-			if (src && shadow && strcmp(src, shadow) == 0) {
-				if (MSG_IS_DELETED(msginfo->flags)) {
-					msg = vfolder_find_msg_from_claws_num(vitem, msginfo->msgnum);
-					if (msg)
-						data->list = g_slist_append(data->list, msg);
-					else {
-						add_msg_data_free(&data);
-						g_slist_free(add_msg_data);
-						add_msg_data = NULL;
-						g_free(src);
-						g_free(shadow);
-						return;
-					}
-				}
-				else {
-					data->list = g_slist_append(data->list, msginfo);
-					data->item = vitem;
-					data->file = vfolder_get_message_file_path(vitem, msginfo);
-					add_msg_data = g_slist_prepend(add_msg_data, data);
-				}
-				if (data->list && MSG_IS_DELETED(msginfo->flags)) {
-					GSList* list = vfolder_filter_msgs_list(data->list, vitem);
-					if (list && list->data) {
-						MsgInfo* msg = (MsgInfo *) list->data;
-						MSG_SET_PERM_FLAGS(msg->flags, MSG_DELETED);
-					}
-					g_slist_free(data->list);
-					data->list = list;
-					data->item = vitem;
-					vfolder_item_update(data);
-					add_msg_data_free(&data);
-					g_slist_free(add_msg_data);
-					add_msg_data = NULL;
-				}
-			}
-			g_free(src);
-			g_free(shadow);
-		}
-	}
-	if (add_msg_data) {
-		for (cur_msg = add_msg_data; cur_msg; cur_msg = g_slist_next(cur_msg)) {
-			data = (AddMsgData *) cur_msg->data;
-			GSList* list = vfolder_filter_msgs_list(data->list, data->item);
-			g_slist_free(data->list);
-			data->list = list;
-			vfolder_item_update(data);
-			add_msg_data_free(&data);
-		}
-		g_slist_free(add_msg_data);
-		add_msg_data = NULL;
-	}
-}
-*/
 static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
 	FolderUpdateData* hookdata;
 
@@ -470,9 +151,9 @@ static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
 	if (! hookdata->folder || IS_VFOLDER_FOLDER(hookdata->folder))
 		return FALSE;
 
-	if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) {
-		/* TODO: check if the removed folder item is foundation for vfolder */
-		debug_print("FOLDER_REMOVE_FOLDERITEM\n");
+	if (hookdata->update_flags & FOLDER_ADD_FOLDER) {
+		/* TODO: check if the added folder is foundation for vfolder */
+		debug_print("FOLDER_ADD_FOLDER\n");
 	}
 
 	if (hookdata->update_flags & FOLDER_REMOVE_FOLDER) {
@@ -481,24 +162,36 @@ static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
 	}
 
 	if (hookdata->update_flags & FOLDER_TREE_CHANGED) {
-		/* TODO: check if the removed folder is foundation for vfolder */
+		/* TODO: check if the changed folder tree affects any vfolder */
 		debug_print("FOLDER_TREE_CHANGED\n");
 	}
 
+	if (hookdata->update_flags & FOLDER_ADD_FOLDERITEM) {
+		/* TODO: check if the added folder item affects any vfolder */
+		debug_print("FOLDER_ADD_FOLDERITEM\n");
+	}
+
+	if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) {
+		/* TODO: check if the removed folder item is foundation for vfolder */
+		debug_print("FOLDER_REMOVE_FOLDERITEM\n");
+	}
+
 	if (hookdata->update_flags & FOLDER_RENAME_FOLDERITEM) {
-		/* TODO: check if the removed folder is foundation for vfolder */
+		/* TODO: can renaming a folder item affect any vfolder? */
 		debug_print("FOLDER_RENAME_FOLDERITEM\n");
 	}
 
+	if (hookdata->update_flags & FOLDER_MOVE_FOLDERITEM) {
+		/* TODO: check if the moved folder item is foundation for vfolder */
+		debug_print("FOLDER_MOVE_FOLDERITEM\n");
+	}
+
 	return FALSE;
 }
 
 static gboolean vfolder_folder_item_update_hook(gpointer source, gpointer data) {
 	FolderItemUpdateData* hookdata;
-//	gint save_state = -1;
-	GList *items = NULL, *cur;
-//	gboolean r;
-//	MainWindow* mainwindow;
+	VFolderItem* vitem;
 
 	g_return_val_if_fail(source != NULL, FALSE);
 	hookdata = (FolderItemUpdateData *) source;
@@ -506,161 +199,112 @@ static gboolean vfolder_folder_item_update_hook(gpointer source, gpointer data)
 	if (! hookdata->item || IS_VFOLDER_FOLDER_ITEM(hookdata->item))
 		return FALSE;
 
-	if (hookdata->update_flags & F_ITEM_UPDATE_REMOVEMSG ) {
-		debug_print("F_ITEM_UPDATE_REMOVEMSG\n");
-		//items = vfolder_get_vfolder_from_source(hookdata->item);
-		if (items) {
-			for (cur = items; cur; cur = g_list_next(cur)) {
-				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_REMOVEMSG);
-			}
-			g_list_free(items);
-		}
+	if (hookdata->update_flags & F_ITEM_UPDATE_MSGCNT &&
+	    ~ hookdata->update_flags & (F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT)) {
+		debug_print("F_ITEM_UPDATE_MSGCNT\n");
+/*		vitem = vfolder_folder_item_watch(hookdata->item);
+		if (vitem && ! vitem->updating)
+			vfolder_scan_source_folder(vitem);*/
 	}
 
-	else if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT) {
+	if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT /*&&
+		~ hookdata->update_flags & (F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT)*/) {
 		debug_print("F_ITEM_UPDATE_CONTENT\n");
-		//items = vfolder_get_vfolder_from_source(hookdata->item);
-		if (items) {
-			for (cur = items; cur; cur = g_list_next(cur)) {
-				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_CONTENT);
-			}
-			g_list_free(items);
-		}
-		//mainwindow = mainwindow_get_mainwindow();
-		//summary_execute(mainwindow->summaryview);
+		vitem = vfolder_folder_item_watch(hookdata->item);
+		if (vitem && ! vitem->updating)
+			vfolder_scan_source_folder(vitem);
 	}
 
-	else if (hookdata->update_flags & F_ITEM_UPDATE_ADDMSG) {
+	if (hookdata->update_flags & F_ITEM_UPDATE_ADDMSG) {
 		debug_print("F_ITEM_UPDATE_ADDMSG\n");
-		//items = vfolder_get_vfolder_from_source(hookdata->item);
-		if (items) {
-			for (cur = items; cur; cur = g_list_next(cur)) {
-				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_ADDMSG);
-			}
-			g_list_free(items);
-		}
 	}
 
-	else if (hookdata->update_flags & F_ITEM_UPDATE_MSGCNT) {
-		debug_print("F_ITEM_UPDATE_MSGCNT\n");
-/*		if (IS_VFOLDER_FOLDER_ITEM(item)) {
-
-			if (! (VFOLDER_ITEM(item))->deep_copy) {
-				if (! (VFOLDER_ITEM(item))->active) {
-					r = vfolder_hide_widgets(VFOLDER_ITEM(item));
-					if (r)
-						VFOLDER_ITEM(item)->active = TRUE;
-				}
-				else {
-					r = vfolder_show_widgets(VFOLDER_ITEM(item));
-					if (r)
-						VFOLDER_ITEM(item)->active = FALSE;
-				}
-
-				if (r)
-					save_state = 1;
-				else
-					save_state = 0;
-			}
-			else
-				vfolder_show_widgets(VFOLDER_ITEM(item));
-		}
-		else {
-			if (!vfolder_widgets_is_visible())
-				vfolder_show_widgets(VFOLDER_ITEM(item));
-		}*/
-/*
-		items = vfolder_get_vfolder_from_source(hookdata->item);
-		if (items) {
-			for (cur = items; cur; cur = g_list_next(cur)) {
-				vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_MSGCNT);
-			}
-			g_list_free(items);
-		}
-*/
+	if (hookdata->update_flags & F_ITEM_UPDATE_REMOVEMSG ) {
+		debug_print("F_ITEM_UPDATE_REMOVEMSG\n");
 	}
 
-	else if (hookdata->update_flags & F_ITEM_UPDATE_NAME) {
+	if (hookdata->update_flags & F_ITEM_UPDATE_NAME) {
 		/* TODO: need update? */
 		debug_print("F_ITEM_UPDATE_NAME\n");
-		//items = vfolder_get_vfolder_from_source(hookdata->item);
-		if (items) {
-			for (cur = items; cur; cur = g_list_next(cur)) {
-				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_NAME);
-			}
-			g_list_free(items);
-		}
 	}
 
-	else {
-		/* Unhandled callback */
-		debug_print("Unhandled FolderItem callback\n");
-	}
-/*
-	if (!save_state) {
-		MainWindow* mainwindow = mainwindow_get_mainwindow();
-		alertpanel_error(_("%s: Could not hide dangerous actions"), hookdata->item->name);
-		summary_lock(mainwindow->summaryview);
-	}
-*/
 	return FALSE;
 }
-/*
+
 static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
 	MsgInfoUpdate* hookdata;
-	MainWindow* mainwindow;
 	MsgInfo* msginfo;
+	VFolderItem* vitem;
+
+	cm_return_val_if_fail(source != NULL, FALSE);
 
-	g_return_val_if_fail(source != NULL, FALSE);
 	hookdata = (MsgInfoUpdate *) source;
 	msginfo = hookdata->msginfo;
 
-	g_return_val_if_fail(msginfo != NULL, TRUE);
+	cm_return_val_if_fail(msginfo != NULL, FALSE);
 
 	if (IS_VFOLDER_MSGINFO(msginfo))
 		return FALSE;
 
-	debug_print("\n\nPermflag: %u Tmpflag: %u (scanned: %u)\n\n\n",
-		(guint32) msginfo->flags.perm_flags, (guint32) msginfo->flags.tmp_flags, 1U << 31);
 	if (MSG_IS_NEW(msginfo->flags)) {
-		debug_print("MSG_IS_NEW\n");
-		vfolder_update_affected_folder_items(msginfo);
-		mainwindow = mainwindow_get_mainwindow();
-		summary_execute(mainwindow->summaryview);
+		vitem = vfolder_folder_item_watch(msginfo->folder);
+		if (vitem) {
+			debug_print("MSG_IS_NEW\n");
+		}
 	}
 
 	if (MSG_IS_DELETED(msginfo->flags)) {
-		debug_print("MSG_IS_DELETED\n");
-		vfolder_update_affected_folder_items(msginfo);
-		mainwindow = mainwindow_get_mainwindow();
-		summary_execute(mainwindow->summaryview);
+		vitem = vfolder_folder_item_watch(msginfo->folder);
+		if (vitem) {
+			debug_print("MSG_IS_DELETED\n");
+			folder_item_remove_msg(FOLDER_ITEM(vitem), msginfo->msgnum);
+		}
 	}
 
 	if (MSG_IS_MOVE(msginfo->flags)) {
+		debug_print("MSG_IS_MOVE to VFolder\n");
+		if (IS_VFOLDER_FOLDER_ITEM(msginfo->to_folder)) {
+			vitem = VFOLDER_ITEM(msginfo->to_folder);
+			gchar* msg = g_strconcat(vitem->source_id, ":\n",
+							_("Cannot move to VFolder"), NULL);
+			alertpanel_error(msg);
+			g_free(msg);
+			return FALSE;
+		}
+		vitem = vfolder_folder_item_watch(msginfo->to_folder);
+		if (! vitem) {
+			/*
+			 * if folder we move to is already monitored we need not
+			 * do anything since distination folder will be automatically
+			 * scanned when F_ITEM_UPDATE_MSGCNT is invoked
+			 */
+			 folder_item_remove_msg(FOLDER_ITEM(vitem), msginfo->msgnum);
+		}
+	}
+
+	if (MSG_IS_MOVE_DONE(msginfo->flags)) {
+		vitem = vfolder_folder_item_watch(msginfo->to_folder);
+		if (vitem) {
+			return FALSE;
+		}
 		debug_print("MSG_IS_MOVE\n");
-		vfolder_update_affected_folder_items(msginfo);
-		mainwindow = mainwindow_get_mainwindow();
-		summary_execute(mainwindow->summaryview);
 	}
 
 	if (MSG_IS_COPY(msginfo->flags)) {
 		debug_print("MSG_IS_COPY\n");
-		vfolder_update_affected_folder_items(msginfo);
-		mainwindow = mainwindow_get_mainwindow();
-		summary_execute(mainwindow->summaryview);
+		if (IS_VFOLDER_FOLDER_ITEM(msginfo->to_folder)) {
+			vitem = VFOLDER_ITEM(msginfo->to_folder);
+			gchar* msg = g_strconcat(vitem->source_id, ":\n",
+							_("Cannot copy to VFolder"), NULL);
+			alertpanel_error(msg);
+			g_free(msg);
+			return FALSE;
+		}
 	}
 
-//	if (MSG_IS_POSTFILTERED(msginfo->flags)) {
-//		debug_print("MSG_IS_POSTFILTERED\n");
-//		vfolder_update_affected_folder_items(msginfo);
-//		mainwindow = mainwindow_get_mainwindow();
-//		summary_execute(mainwindow->summaryview);
-//	}
-
-
 	return FALSE;
 }
-*/
+
 static gchar* vfolder_get_rc_file(VFolderItem* item) {
 	gchar* (*item_get_path)	(Folder* folder, FolderItem* item);
 	gchar* path;
@@ -675,56 +319,32 @@ static gchar* vfolder_get_rc_file(VFolderItem* item) {
 	return rc_file;
 }
 
-FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item) {
+FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* vitem) {
 	gchar* rc_file;
 	GKeyFile* config;
-	gchar* id;
 	gchar* data = NULL;
 	FILE* fp;
 	gsize len = 0;
 	FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM;
-/*	gchar* numstr;
-	GHashTableIter iter;
-	gpointer key, value;*/
 
-	g_return_val_if_fail(item != NULL, resp);
+	g_return_val_if_fail(vitem != NULL, resp);
 
-	rc_file = vfolder_get_rc_file(item);
-	config = g_key_file_new();
+	if (! vitem->changed) return FOLDER_ITEM_PROPS_OK;
 
-	if (item->filter)
-		g_key_file_set_string(config, CONFIG_GROUP, "filter", item->filter);
+	debug_print("%s: Writing configuration\n", vitem->source_id);
 
-	g_key_file_set_boolean(config, CONFIG_GROUP, "frozen", item->frozen);
+	rc_file = vfolder_get_rc_file(vitem);
+	config = g_key_file_new();
 
-	if (item->source) {
-		id = folder_item_get_identifier(item->source);
-		if (id) {
-			g_key_file_set_string(config, CONFIG_GROUP, "source", id);
-			g_free(id);
-		}
-	}
+	if (vitem->filter)
+		g_key_file_set_string(config, CONFIG_GROUP, "filter", vitem->filter);
+	if (vitem->source_id)
+		g_key_file_set_string(config, CONFIG_GROUP, "source_id", vitem->source_id);
+	g_key_file_set_boolean(config, CONFIG_GROUP, "frozen", vitem->frozen);
+	g_key_file_set_integer(config, CONFIG_GROUP, "searchtype", vitem->search);
 
-/*	if (item->claws_to_me && item->me_to_claws) {
-		numstr = NULL;
-		g_hash_table_iter_init(&iter, item->claws_to_me);
-		while (g_hash_table_iter_next(&iter, &key, &value)) {
-			len++;
-			MsgBridge* bridge = value;
-			if (numstr) {
-				gchar* tmp = g_strdup(numstr);
-				g_free(numstr);
-				numstr = g_strdup_printf("%s, %u:%u",
-					tmp, bridge->my_num, bridge->claws_num);
-				g_free(tmp);
-			}
-			else
-				numstr = g_strdup_printf("%u:%u", bridge->my_num, bridge->claws_num);
-		}
-
-		g_key_file_set_string(config, CONFIG_GROUP, "file_id_list", numstr);
-		g_free(numstr);
-	}*/
+	if (vitem->msgvault)
+		vfolder_msgvault_serialize(vitem, config);
 
 	if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) {
 		gchar* bakpath = g_strconcat(rc_file, ".bak", NULL);
@@ -735,8 +355,6 @@ FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item) {
 		g_free(bakpath);
 	}
 
-//	g_key_file_set_integer(config, CONFIG_GROUP, "filter-function", item->filter_func);
-
 	data = g_key_file_to_data(config, &len, NULL);
 	if (len < 1) {
 		g_warning("Could not get config data");
@@ -762,6 +380,7 @@ FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item) {
 		}
 		fwrite(data, len, 1, fp);
 		fclose(fp);
+		vitem->changed = FALSE;
 		resp = FOLDER_ITEM_PROPS_OK;
 	}
 
@@ -774,18 +393,17 @@ error:
 	return resp;
 }
 
-FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item) {
+FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* vitem) {
 	gchar* rc_file;
 	GKeyFile* config;
 	GError* error = NULL;
-	gchar *id, *msgnums;
-	gchar **list, **head;
 	FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM;
-	gint lastnum;
 
-	g_return_val_if_fail(item != NULL, resp);
+	g_return_val_if_fail(vitem != NULL, resp);
+
+	if (! vitem->changed) return FOLDER_ITEM_PROPS_OK;
 
-	rc_file = vfolder_get_rc_file(item);
+	rc_file = vfolder_get_rc_file(vitem);
 	config = g_key_file_new();
 
 	if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) {
@@ -796,39 +414,24 @@ FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item) {
 			resp = FOLDER_ITEM_PROPS_READ_USING_DEFAULT;
 		}
 		else {
-			item->filter = g_key_file_get_string(config, CONFIG_GROUP, "filter", NULL);
-//			item->search = g_key_file_get_integer(config, CONFIG_GROUP, "searchtype", NULL);
-			item->frozen = g_key_file_get_boolean(config, CONFIG_GROUP, "frozen", NULL);
-//			item->deep_copy = g_key_file_get_boolean(config, CONFIG_GROUP, "deep_copy", NULL);
-//			item->filter_func = g_key_file_get_integer(config, CONFIG_GROUP, "filter_function", NULL);
-
-			id = g_key_file_get_string(config, CONFIG_GROUP, "source", NULL);
-			if (id) {
-				item->source = folder_find_item_from_identifier(id);
-				g_free(id);
-			}
-			msgnums = g_key_file_get_string(config, CONFIG_GROUP, "file_id_list", NULL);
-			if (msgnums) {
-				list = g_strsplit(msgnums, ",", 0);
-				head = list;
-				lastnum = -1;
-				while (*list) {
-					/*gchar* anum = g_strdup(*list++);
-					g_strstrip(anum);
-					MsgBridge* bridge = vfolder_split_file_id(anum);
-					g_free(anum);
-					if (lastnum < (gint) bridge->my_num)
-						lastnum = bridge->my_num;
-					if (bridge->my_num > 0) {
-						vfolder_add_message_to_bridge(item, bridge);
-					}
-					g_free(bridge);*/
-				}
-				FOLDER_ITEM(item)->last_num = lastnum;
-				g_strfreev(head);
-				g_free(msgnums);
-			}
+			vitem->filter = g_key_file_get_string(config, CONFIG_GROUP, "filter", NULL);
+			vitem->search = g_key_file_get_integer(config, CONFIG_GROUP, "searchtype", NULL);
+			vitem->frozen = g_key_file_get_boolean(config, CONFIG_GROUP, "frozen", NULL);
+			vitem->source_id = g_key_file_get_string(config, CONFIG_GROUP, "source_id", NULL);
+			if (vitem->source_id)
+				vitem->source = folder_find_item_from_identifier(vitem->source_id);
+			vfolder_msgvault_restore(vitem, config);
+
+			FolderItem* item = FOLDER_ITEM(vitem);
+			vfolder_set_last_num(item->folder, item);
+
+			vfolder_msgvault_add(vitem);
+
 			resp = FOLDER_ITEM_PROPS_OK;
+
+			vitem->changed = FALSE;
+
+			debug_print("%s: Read configuration\n", vitem->source_id);
 		}
 	}
 
@@ -857,21 +460,13 @@ gboolean vfolder_gtk_init(gchar** error) {
 		return FALSE;
 	}
 
-/*	msginfo_hook_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
+	msginfo_hook_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
 		vfolder_msg_info_update_hook, NULL);
 	if (msginfo_hook_id == -1) {
 		*error = g_strdup(_("Failed to register message info update hook"));
 		hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
 		hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
 		return FALSE;
-	}*/
-
-	if (! get_menu_widgets()) {
-		*error = g_strdup(_("Failed to get menu widgets"));
-		hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
-		hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
-		hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
-		return FALSE;
 	}
 
 	return TRUE;
@@ -879,27 +474,14 @@ gboolean vfolder_gtk_init(gchar** error) {
 
 void vfolder_gtk_done(void) {
 	MainWindow *mainwin = mainwindow_get_mainwindow();
-	FolderView *folderview = NULL;
-	FolderItem *fitem = NULL;
 
 	hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
 	hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
-	//hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
+	hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
 
 	if (mainwin == NULL || claws_is_exiting())
 		return;
 
-	folderview = mainwin->folderview;
-	fitem = folderview->summaryview->folder_item;
-
-	if (fitem && IS_VFOLDER_FOLDER_ITEM(fitem)) {
-		vfolder_show_widgets(VFOLDER_ITEM(fitem));
-		gslist_menu_item_free(&widgets);
-
-		folderview_unselect(folderview);
-		summary_clear_all(folderview->summaryview);
-	}
-
 	folderview_unregister_popup(&vfolder_popup);
 }
 
@@ -915,7 +497,7 @@ void vfolder_properties_cb(GtkAction* action, gpointer data) {
 	g_return_if_fail(item->path != NULL);
 	g_return_if_fail(item->folder != NULL);
 
-	if (vfolder_edit_item_dialog(VFOLDER_ITEM(item))) {
+	if (vfolder_edit_item_dialog(VFOLDER_ITEM(item), NULL)) {
 		/* TODO: update */
 		if (debug_get_mode()) {
 //			GHashTableIter iter;
@@ -938,31 +520,21 @@ void vfolder_properties_cb(GtkAction* action, gpointer data) {
 				fclose(msg);
 			}*/
 		}
-		vfolder_folder_item_props_write(VFOLDER_ITEM(item));
 	}
 }
 
 void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
 	FolderView *folderview = (FolderView *)data;
-	GtkCMCTree *ctree = NULL;
-	FolderItem *item;
-	FolderItem *new_item;
-	gchar *new_folder;
-	gchar *name;
-	gchar *p;
-
-	if (!folderview->selected) return;
-    if (!GTK_IS_CMCTREE(folderview->ctree)) return;
-
-    ctree = GTK_CMCTREE(folderview->ctree);
-	item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
-    //item = folderview_get_selected_item(folderview);
-	if (! item) {
-		//item = FOLDER_ITEM(vfolder_get_vfolder_item(NULL));
-	}
+	FolderItem *item, *new_item, *parent;
+	gchar* new_folder;
+	gchar* name;
+	gchar* p;
+	gchar* id;
 
-    cm_return_if_fail(item != NULL);
-    cm_return_if_fail(item->folder != NULL);
+    item = folderview_get_selected_item(folderview);
+	cm_return_if_fail(item != NULL);
+	cm_return_if_fail(item->path != NULL);
+	cm_return_if_fail(item->folder != NULL);
 
 	if (item->no_sub) {
 		alertpanel_error(N_("Virtual folders cannot contain subfolders"));
@@ -985,49 +557,76 @@ void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
 	name = trim_string(new_folder, 32);
 	AUTORELEASE_STR(name, {g_free(name); return;});
 
+	Folder* folder = folder_find_from_name(VFOLDER_DEFAULT_MAILBOX, vfolder_folder_get_class());
+	parent = FOLDER_ITEM(folder->node->data);
 	/* find whether the directory already exists */
-	if (folder_find_child_item_by_name(item, new_folder)) {
+	if (folder_find_child_item_by_name(parent, new_folder)) {
 		alertpanel_error(_("The folder '%s' already exists."), name);
 		return;
 	}
 
-	new_item = folder_create_folder(item, new_folder);
+	new_item = folder_create_folder(parent, new_folder);
 	if (!new_item) {
 		alertpanel_error(_("Can't create the folder '%s'."), name);
 		return;
 	}
 
-	if (! vfolder_create_item_dialog(new_item)) {
-		//VFolderItem* vitem = VFOLDER_ITEM(new_item);
+	if (! vfolder_create_item_dialog(VFOLDER_ITEM(new_item), item)) {
+		new_item->folder->klass->remove_folder(new_item->folder, new_item);
+		new_item = NULL;
+		return;
+	}
+
+	id = folder_item_get_identifier(item);
+	if (vfolder_msgvault_add(VFOLDER_ITEM(new_item))) {
 		new_item->folder->klass->remove_folder(new_item->folder, new_item);
 		new_item = NULL;
+		g_free(id);
 		return;
 	}
 
+	g_free(id);
+
 	folder_write_list();
 }
 
+void vfolder_refresh_cb(GtkAction* action, gpointer data) {
+	FolderView *folderview = (FolderView *)data;
+	FolderItem *item;
+
+	g_return_if_fail(folderview != NULL);
+
+	item = folderview_get_selected_item(folderview);
+
+	g_return_if_fail(item != NULL);
+	g_return_if_fail(item->path != NULL);
+	g_return_if_fail(item->folder != NULL);
+
+	vfolder_scan_source_folder(VFOLDER_ITEM(item));
+}
+
+void vfolder_refresh_all_cb(GtkAction* action, gpointer data) {
+	vfolder_scan_source_folder_all();
+}
+
 void vfolder_remove_folder_cb(GtkAction* action, gpointer data) {
 	FolderView *folderview = (FolderView *)data;
-	GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
+	GtkCMCTree *ctree;
 	FolderItem *item;
 	gchar *message, *name;
 	AlertValue avalue;
-	gchar *old_path = NULL;
-	gchar *old_id;
-
-	/* Silence lame warnings */
-	old_id = (old_path) ? NULL : old_path;
 
 	item = folderview_get_selected_item(folderview);
 	g_return_if_fail(item != NULL);
 	g_return_if_fail(item->path != NULL);
 	g_return_if_fail(item->folder != NULL);
 
+	ctree = GTK_CMCTREE(folderview->ctree);
+
 	name = trim_string(item->name, 32);
 	AUTORELEASE_STR(name, {g_free(name); return;});
 	message = g_strdup_printf
-		(_("All folders and messages under '%s' will be permanently deleted. "
+		(_("All messages under '%s' will be permanently deleted. "
 		   "Recovery will not be possible.\n\n"
 		   "Do you really want to delete?"), name);
 	avalue = alertpanel_full(_("Delete folder"), message,
@@ -1036,9 +635,6 @@ void vfolder_remove_folder_cb(GtkAction* action, gpointer data) {
 	g_free(message);
 	if (avalue != G_ALERTALTERNATE) return;
 
-	Xstrdup_a(old_path, item->path, return);
-	old_id = folder_item_get_identifier(item);
-
 	if (folderview->opened == folderview->selected ||
 	    gtk_cmctree_is_ancestor(ctree,
 				  folderview->selected,
@@ -1050,11 +646,24 @@ void vfolder_remove_folder_cb(GtkAction* action, gpointer data) {
 	if (item->folder->klass->remove_folder(item->folder, item) < 0) {
 		folder_item_scan(item);
 		alertpanel_error(_("Can't remove the folder '%s'."), name);
-		g_free(old_id);
 		return;
 	}
 
 	folder_write_list();
+}
+
+GtkResponseType vfolder_msg_dialog(GtkMessageType msgtype, GtkButtonsType btntype,
+								   const gchar* message) {
+	GtkResponseType ret;
+	GtkWidget* dialog;
+
+	MainWindow* mainwin = mainwindow_get_mainwindow();
+	dialog = gtk_message_dialog_new (GTK_WINDOW(mainwin->window),
+									 GTK_DIALOG_DESTROY_WITH_PARENT,
+									 msgtype, btntype, message);
+
+	ret = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
 
-	g_free(old_id);
+	return ret;
 }
diff --git a/src/plugins/vfolder/vfolder_gtk.h b/src/plugins/vfolder/vfolder_gtk.h
index 5b41ee4..270f337 100644
--- a/src/plugins/vfolder/vfolder_gtk.h
+++ b/src/plugins/vfolder/vfolder_gtk.h
@@ -33,24 +33,19 @@ G_BEGIN_DECLS
 #include "vfolder.h"
 #include <gtk/gtk.h>
 
-typedef enum {
-	FOLDER_ITEM_PROPS_OK,
-	FOLDER_ITEM_PROPS_NO_ITEM,
-	FOLDER_ITEM_PROPS_BACKUP_FAIL,
-	FOLDER_ITEM_PROPS_READ_DATA_FAIL,
-	FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL,
-	FOLDER_ITEM_PROPS_READ_USING_DEFAULT
-} FolderPropsResponse;
-
 gboolean vfolder_gtk_init(gchar** error);
 void vfolder_gtk_done(void);
 FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item);
 FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item);
+GtkResponseType vfolder_msg_dialog(GtkMessageType msgtype, GtkButtonsType btntype,
+								   const gchar* message);
 
 /* Callback functions */
 void vfolder_new_folder_cb(GtkAction* action, gpointer data);
 void vfolder_remove_folder_cb(GtkAction* action, gpointer data);
 void vfolder_properties_cb(GtkAction* action, gpointer data);
+void vfolder_refresh_cb(GtkAction* action, gpointer data);
+void vfolder_refresh_all_cb(GtkAction* action, gpointer data);
 
 G_END_DECLS
 
diff --git a/src/plugins/vfolder/vfolder_init.c b/src/plugins/vfolder/vfolder_init.c
index b000514..568f468 100644
--- a/src/plugins/vfolder/vfolder_init.c
+++ b/src/plugins/vfolder/vfolder_init.c
@@ -55,23 +55,14 @@ static GtkActionEntry vfolder_main_menu[] = {{
 static gint main_menu_id = 0;
 
 gint plugin_init(gchar** error) {
-	debug_set_mode(TRUE);
 	MainWindow *mainwin = mainwindow_get_mainwindow();
 
-/*
-#ifdef G_OS_UNIX
-	bindtextdomain(TEXTDOMAIN, LOCALEDIR);
-#else
-	bindtextdomain(TEXTDOMAIN, get_locale_dir());
-#endif
-	bind_textdomain_codeset(TEXTDOMAIN, "UTF-8");
-*/
 	if (!check_plugin_version(MAKE_NUMERIC_VERSION(0,0,1,0),
 				VERSION_NUMERIC, PLUGIN_NAME, error))
 		return -1;
 
 	gtk_action_group_add_actions(mainwin->action_group, vfolder_main_menu,
-			1, (gpointer)mainwin);
+			1, (gpointer)mainwin->folderview);
 	MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/View", "CreateVfolder",
 			  "View/CreateVfolder", GTK_UI_MANAGER_MENUITEM,
 			  main_menu_id)
@@ -92,15 +83,13 @@ gboolean plugin_done(void) {
 
 	vfolder_done();
 
-	if (mainwin == NULL)
-		return FALSE;
-
-	MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "View/CreateVfolder", main_menu_id);
-	main_menu_id = 0;
+	if (mainwin) {
+		MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "View/CreateVfolder", main_menu_id);
+		main_menu_id = 0;
+	}
 
 	debug_print("vfolder plugin unloaded\n");
 
-	debug_set_mode(FALSE);
 	return TRUE;
 }
 
diff --git a/src/plugins/vfolder/vfolder_prop.c b/src/plugins/vfolder/vfolder_prop.c
index c7187aa..e7485f2 100644
--- a/src/plugins/vfolder/vfolder_prop.c
+++ b/src/plugins/vfolder/vfolder_prop.c
@@ -52,7 +52,6 @@
 typedef struct {
 	GtkWidget* filter;
 	GtkWidget* frozen;
-	GtkWidget* deep_copy;
 	GtkWidget* source;
 	GtkWidget* label_btn;
 	GtkWidget* message_btn;
@@ -70,7 +69,6 @@ static void add_current_config(VFolderItem* item, PropsDialog* props) {
 		}
 	}
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->frozen), item->frozen);
-/*	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->deep_copy), item->deep_copy);
 	switch (item->search) {
 		case SEARCH_BODY:
 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->message_btn), TRUE);
@@ -78,7 +76,7 @@ static void add_current_config(VFolderItem* item, PropsDialog* props) {
 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->both_btn), TRUE);
 		case SEARCH_HEADERS:
 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->label_btn), TRUE);
-	}*/
+	}
 }
 
 static gboolean is_source_widget(GtkWidget* widget) {
@@ -144,7 +142,7 @@ static gboolean vfolder_set_search_type(VFolderItem* item, GtkWidget* list) {
 	if (active) {
 		const gchar* label = gtk_button_get_label(GTK_BUTTON(btn));
 		if (label) {
-/*			if (strcmp(BOTH, label) == 0) {
+			if (strcmp(BOTH, label) == 0) {
 				if (item->search != SEARCH_BOTH) {
 					item->search = SEARCH_BOTH;
 					return TRUE;
@@ -161,24 +159,12 @@ static gboolean vfolder_set_search_type(VFolderItem* item, GtkWidget* list) {
 					item->search = SEARCH_HEADERS;
 					return TRUE;
 				}
-			}*/
+			}
 		}
 	}
 
 	return FALSE;
 }
-/*
-static void vfolder_copy_msginfo_list(gpointer data, gpointer user_data) {
-	MsgInfo* msg = (MsgInfo *) data;
-	MsgInfo* new_msg;
-	VFolderItem* item = (VFolderItem *) user_data;
-
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(item != NULL);
-
-	new_msg = procmsg_msginfo_copy(msg);
-	item->msginfos = g_slist_prepend(item->msginfos, new_msg);
-}
 
 static gboolean vfolder_search_headers(MsgInfo* msg, GPatternSpec* pattern) {
 	return ((msg->cc && g_pattern_match_string(pattern, msg->cc)) ||
@@ -201,7 +187,7 @@ static gboolean vfolder_search_body(MsgInfo* msg, GPatternSpec* pattern) {
 
 	return found;
 }
-*/
+
 static MsgInfoList* vfolder_filter_msgs_list(MsgInfoList* msgs, VFolderItem* item) {
 	MsgInfoList *list = NULL, *tmp;
 	GPatternSpec* pattern;
@@ -214,7 +200,7 @@ static MsgInfoList* vfolder_filter_msgs_list(MsgInfoList* msgs, VFolderItem* ite
 
 	for (tmp = msgs; tmp; tmp = g_slist_next(tmp)) {
 		msg = (MsgInfo *) tmp->data;
-/*		switch (item->search) {
+		switch (item->search) {
 			case SEARCH_HEADERS:
 				if (vfolder_search_headers(msg, pattern))
 					list = g_slist_prepend(list, msg);
@@ -231,21 +217,23 @@ static MsgInfoList* vfolder_filter_msgs_list(MsgInfoList* msgs, VFolderItem* ite
 				if (vfolder_search_body(msg, pattern))
 					list = g_slist_prepend(list, msg);
 				break;
-		}*/
+		}
 	}
 
+	if (list)
+		list = g_slist_reverse(list);
+
 	g_pattern_spec_free(pattern);
 
 	return list;
 }
 
-static gboolean vfolder_create_msgs_list(VFolderItem* item, gboolean copy) {
+static gboolean vfolder_create_msgs_list(VFolderItem* item) {
 	MsgInfoList *msgs = NULL, *filtered = NULL;
 	gboolean ok = FALSE;
 	GSList* filelist = NULL;
 
 	if (item->filter && item->msg_filter_func) {
-//		item->deep_copy = copy;
 		ok = TRUE;
 		msgs = folder_item_get_msg_list(item->source);
 		filtered = item->msg_filter_func(msgs, item);
@@ -258,7 +246,7 @@ static gboolean vfolder_create_msgs_list(VFolderItem* item, gboolean copy) {
 			}
 			g_slist_free(filtered);
 		}
-		g_slist_free(msgs);
+		procmsg_msg_list_free(msgs);
 	}
 	return ok;
 }
@@ -269,28 +257,21 @@ void vfolder_set_msgs_filter(VFolderItem* vfolder_item) {
 	vfolder_item->msg_filter_func = vfolder_filter_msgs_list;
 }
 
-gboolean vfolder_create_item_dialog(FolderItem* folder_item) {
+gboolean vfolder_create_item_dialog(VFolderItem* vitem, FolderItem* item) {
 	gboolean created = FALSE;
-	VFolderItem* item = NULL;
 
-	g_return_val_if_fail(folder_item != NULL, created);
-	g_return_val_if_fail(IS_VFOLDER_FOLDER_ITEM(folder_item), created);
+	g_return_val_if_fail(vitem != NULL, created);
+	g_return_val_if_fail(item != NULL, created);
 
-	item = VFOLDER_ITEM(folder_item);
-	item->msg_filter_func = vfolder_filter_msgs_list;
+	vitem->msg_filter_func = vfolder_filter_msgs_list;
 
-	if (vfolder_edit_item_dialog(item)) {
-		/* save properties */
-		if (FOLDER_ITEM_PROPS_OK != vfolder_folder_item_props_write(item))
-			created = FALSE;
-		else
-			created = TRUE;
-	}
+	if (vfolder_edit_item_dialog(vitem, item))
+		created = TRUE;
 
 	return created;
 }
 
-gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item) {
+gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item) {
 	gboolean ok = FALSE;
 	PropsDialog* props_dialog;
 	GtkWidget* dialog;
@@ -298,19 +279,19 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item) {
 	GtkWidget* row;
 	GtkWidget* box;
 	gint response;
-	gchar* name;
+	gchar *name, *id;
 	const gchar* str;
-	gboolean frozen, deep_copy;
-	FolderItem* source;
+	gboolean frozen;
 	gchar* old_filter = NULL;
+	FolderItem* old_source;
 
-	g_return_val_if_fail(vfolder_item != NULL, ok);
+	g_return_val_if_fail(vitem != NULL, ok);
+	g_return_val_if_fail(item != NULL || vitem->source != NULL, ok);
 
 	MainWindow *mainwin = mainwindow_get_mainwindow();
 	props_dialog = g_new0(PropsDialog, 1);
 	props_dialog->filter = gtk_entry_new();
 	props_dialog->frozen = gtk_check_button_new();
-	props_dialog->deep_copy = gtk_check_button_new();
 	props_dialog->source = gtk_entry_new();
 	props_dialog->label_btn =
 		gtk_radio_button_new_with_mnemonic(NULL, HEADERS);
@@ -321,7 +302,7 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item) {
 		gtk_radio_button_new_with_mnemonic_from_widget(
 			GTK_RADIO_BUTTON(props_dialog->label_btn), BOTH);
 	gtk_widget_set_name(props_dialog->source, "source");
-	add_current_config(vfolder_item, props_dialog);
+	add_current_config(vitem, props_dialog);
 
 	dialog = gtk_dialog_new_with_buttons(
 			N_("Edit VFolder Properties"),
@@ -335,9 +316,17 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item) {
 
 	GtkWidget* vbox = gtk_vbox_new(FALSE, 5);
 
-	row = vfolder_prop_row(props_dialog->source, N_("_Source folder"), 110, FALSE);
+	row = vfolder_prop_row(props_dialog->source, N_("_Source folder"), 130, FALSE);
 	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
 
+	if (!item)
+		id = folder_item_get_identifier(vitem->source);
+	else
+		id = folder_item_get_identifier(item);
+	gtk_entry_set_text(GTK_ENTRY(props_dialog->source), id);
+	gtk_widget_set_sensitive(props_dialog->source, FALSE);
+	g_free(id);
+
 	GtkWidget* frame1 = gtk_frame_new(_("Message filter"));
 	GtkWidget* vbox1 = gtk_vbox_new(TRUE, 2);
 	gtk_container_add(GTK_CONTAINER(frame1), vbox1);
@@ -356,95 +345,96 @@ gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item) {
 	row = vfolder_prop_row(props_dialog->frozen, N_("F_reeze content"), 110, TRUE);
 	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
 
-	row = vfolder_prop_row(props_dialog->deep_copy, N_("Co_py messages"), 110, TRUE);
-	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
-
-	name = g_strconcat(FOLDER_ITEM(vfolder_item)->name, N_(": settings"), NULL);
+	name = g_strconcat(FOLDER_ITEM(vitem)->name, N_(": settings"), NULL);
 	GtkWidget* frame = gtk_frame_new(name);
 	g_free(name);
 	gtk_container_add(GTK_CONTAINER(frame), vbox);
-	gtk_widget_show_all(frame);
 
 	gtk_container_add(GTK_CONTAINER(content), frame);
+	gtk_widget_show_all(content);
 
 	response = gtk_dialog_run(GTK_DIALOG(dialog));
 	if (response == GTK_RESPONSE_ACCEPT) {
 		frozen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(props_dialog->frozen));
-		deep_copy = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(props_dialog->deep_copy));
 
 		str = gtk_entry_get_text(GTK_ENTRY(props_dialog->filter));
 		if (str) {
-			old_filter = g_strdup(vfolder_item->filter);
+			old_filter = g_strdup(vitem->filter);
 			if (strlen(str) == 0) {
-				if (vfolder_item->filter) {
-					g_free(vfolder_item->filter);
-					vfolder_item->filter = NULL;
+				if (vitem->filter) {
+					g_free(vitem->filter);
+					vitem->filter = NULL;
 					ok = TRUE;
 				}
 			}
 			else {
-				if (!vfolder_item->filter || strcmp(vfolder_item->filter, str) != 0) {
-					g_free(vfolder_item->filter);
-					vfolder_item->filter = g_strdup(str);
+				if (!vitem->filter || strcmp(vitem->filter, str) != 0) {
+					g_free(vitem->filter);
+					vitem->filter = g_strdup(str);
 					ok = TRUE;
 				}
 			}
 		}
-		if (vfolder_set_search_type(vfolder_item, props_dialog->label_btn))
+		if (vfolder_set_search_type(vitem, props_dialog->label_btn))
 			ok = TRUE;
 
 		str = gtk_entry_get_text(GTK_ENTRY(props_dialog->source));
 		if (str) {
-			source = folder_find_item_from_identifier(str);
-			if (source && (source->stype != F_NORMAL && source->stype != F_INBOX)) {
-				alertpanel_error(_("%s: Not suitable for virtual folders\n"
-								   "Use only folder type: Normal or Inbox\n"), str);
-				g_free(vfolder_item->filter);
-				vfolder_item->filter = g_strdup(old_filter);
-				ok = FALSE;
-				goto error;
+			if (item) {
+				vitem->source = item;
+			} else {
+				/* remove msgvault */
+				vfolder_msgvault_free(vitem->msgvault);
+				vitem->msgvault = vfolder_msgvault_new();
 			}
 
 			if (strlen(str) == 0) {
-				if (vfolder_item->source) {
-					vfolder_item->source = NULL;
-					folder_item_remove_all_msg(FOLDER_ITEM(vfolder_item));
+				if (vitem->source) {
+					vitem->source = NULL;
+					folder_item_remove_all_msg(FOLDER_ITEM(vitem));
 					ok = TRUE;
 				}
-			}
-			else {
-				folder_item_remove_all_msg(FOLDER_ITEM(vfolder_item));
-				gchar* id = (vfolder_item->source) ?
-					folder_item_get_identifier(vfolder_item->source) : NULL;
-				if (!id || strcmp(id, str) != 0)
-					vfolder_item->source = source;
-				if (vfolder_item->source) {
-					ok =  vfolder_create_msgs_list(vfolder_item, deep_copy);
-					if (ok == FALSE) {
-						g_free(vfolder_item->filter);
-						vfolder_item->filter = g_strdup(old_filter);
-						goto error;
-					}
+			} else {
+				old_source = NULL;
+				id = (vitem->source) ? folder_item_get_identifier(vitem->source) : NULL;
+				if (!id || strcmp(id, str) != 0) {
+					old_source = vitem->source;
+					vitem->source = folder_get_item_from_identifier(str);
 				}
-				else {
-					g_free(vfolder_item->filter);
-					vfolder_item->filter = g_strdup(old_filter);
+				g_free(id);
+				if (vitem->source && (vitem->source->stype != F_NORMAL && vitem->source->stype != F_INBOX)) {
+					alertpanel_error(_("%s: Not suitable for virtual folders\n"
+									   "Use only folder type: Normal or Inbox\n"), str);
+					g_free(vitem->filter);
+					vitem->filter = g_strdup(old_filter);
+					if (old_source)
+						vitem->source = old_source;
 					ok = FALSE;
 					goto error;
 				}
+				if (vitem->source_id)
+					g_free(vitem->source_id);
+				vitem->source_id = folder_item_get_identifier(vitem->source);
+				if (FOLDER_ITEM(vitem)->total_msgs > 0)
+					folder_item_remove_all_msg(FOLDER_ITEM(vitem));
+				ok =  vfolder_create_msgs_list(vitem);
+				if (ok == FALSE) {
+					g_free(vitem->filter);
+					vitem->filter = g_strdup(old_filter);
+					goto error;
+				}
+				vitem->changed = TRUE;
 			}
+		} else {
+			ok = FALSE;
+			goto error;
 		}
 
-		if (vfolder_item->frozen != frozen) {
-			vfolder_item->frozen = frozen;
+		if (vitem->frozen != frozen) {
+			vitem->frozen = frozen;
 			ok = TRUE;
 		}
 
-/*		if (vfolder_item->deep_copy != deep_copy) {
-			vfolder_item->deep_copy = deep_copy;
-			ok = TRUE;
-		}*/
-
 	}
 
 error:
@@ -454,3 +444,35 @@ error:
 
 	return ok;
 }
+
+void vfolder_item_props_response(FolderPropsResponse resp) {
+	GtkResponseType ret;
+
+	switch (resp) {
+		case FOLDER_ITEM_PROPS_OK: break;
+		case FOLDER_ITEM_PROPS_BACKUP_FAIL:
+			vfolder_msg_dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
+							   "Making backup of config failed");
+			break;
+		case FOLDER_ITEM_PROPS_READ_USING_DEFAULT:
+			vfolder_msg_dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
+							   "Missing config file. Using defaults");
+			break;
+		case FOLDER_ITEM_PROPS_NO_ITEM:
+			ret = vfolder_msg_dialog(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+									 "Writing config failed\nContinue?");
+			if (ret != GTK_RESPONSE_YES)
+				vfolder_done();
+			break;
+		case FOLDER_ITEM_PROPS_READ_DATA_FAIL:
+			vfolder_msg_dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+							   "Reading config failed. Unloading plugin");
+			vfolder_done();
+			break;
+		case FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL:
+			vfolder_msg_dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+							   "Creating top folder failed. Unloading plugin");
+			vfolder_done();
+			break;
+	}
+}
diff --git a/src/plugins/vfolder/vfolder_prop.h b/src/plugins/vfolder/vfolder_prop.h
index 04fb493..4a3e11f 100644
--- a/src/plugins/vfolder/vfolder_prop.h
+++ b/src/plugins/vfolder/vfolder_prop.h
@@ -34,9 +34,10 @@ G_BEGIN_DECLS
 #include "vfolder.h"
 #include <gtk/gtk.h>
 
-gboolean vfolder_create_item_dialog(FolderItem* folder_item);
-gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item);
+gboolean vfolder_create_item_dialog(VFolderItem* vitem, FolderItem* item);
+gboolean vfolder_edit_item_dialog(VFolderItem* vitem, FolderItem* item);
 void vfolder_set_msgs_filter(VFolderItem* vfolder_item);
+void vfolder_item_props_response(FolderPropsResponse resp);
 
 G_END_DECLS
 

commit e0b729908766b15202d118b6eb95cf12f050e83a
Merge: 628da7d 8e65767
Author: Michael Rasmussen <mir at datanom.net>
Date:   Wed Jun 18 23:43:01 2014 +0200

    Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws into vfolder

diff --cc configure.ac
index f6c2c5d,1cc5e25..d67ad8f
--- a/configure.ac
+++ b/configure.ac
@@@ -1060,10 -1069,9 +1073,10 @@@ dnl PGP/Mime:		pgpcore libgpgm
  dnl PGP/Inline:		pgpcore libgpgme
  dnl S/Mime:		pgpcore libgpgme
  dnl Python:		Python
- dnl RSSyl:		libxml2 libcurl
+ dnl RSSyl:		expat libcurl
  dnl SpamReport:		libcurl
  dnl vCalendar:		libcurl
 +dnl VFolder:		none
  
  dnl libcurl ********************************************************************
  PKG_CHECK_MODULES(CURL, libcurl, HAVE_CURL=yes, HAVE_CURL=no)

commit 628da7de6c4542e64357fc281555f6ac81547430
Merge: 8da1959 c981e7a
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sun Jun 15 17:51:35 2014 +0200

    Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws into vfolder


commit 8da1959fb498002c2de9b0b37ca5d1d68777ada8
Merge: d863d99 eaf1e7a
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sat Jun 14 17:53:39 2014 +0200

    Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws into vfolder


commit d863d9937e2718b51f6d7cac54fc9da01e5fe0d6
Merge: c4ae33d 89b7b7a
Author: Michael Rasmussen <mir at datanom.net>
Date:   Thu Jun 12 02:16:58 2014 +0200

    Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws into vfolder


commit c4ae33dd424ccaf4f23702fe75131902f3b2a5c7
Merge: 113f951 06ce560
Author: Michael Rasmussen <mir at datanom.net>
Date:   Tue Jun 10 17:17:26 2014 +0200

    Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws into vfolder


commit 113f951660dcf06b86ef75a840e4f49508277b39
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sun Jun 8 18:53:52 2014 +0200

    Initial commit of vfolder

diff --git a/src/plugins/vfolder/Makefile.am b/src/plugins/vfolder/Makefile.am
new file mode 100644
index 0000000..0d79537
--- /dev/null
+++ b/src/plugins/vfolder/Makefile.am
@@ -0,0 +1,37 @@
+# Makefile.am for "src/plugins/vfolder" directory
+# This file is part of Claws Mail package.
+# See COPYING file for license details.
+
+plugindir = $(pkglibdir)/plugins
+
+if BUILD_VFOLDER_PLUGIN
+plugin_LTLIBRARIES = vfolder.la
+endif
+
+vfolder_la_SOURCES = \
+		vfolder.c \
+		vfolder_init.c \
+		vfolder_gtk.c \
+		vfolder_prop.c
+
+nodist_include_HEADERS = \
+		vfolder_gtk.h \
+		vfolder_prop.h
+
+vfolderincludedir = $(pkgincludedir)/plugins/@PACKAGE@
+vfolderinclude_HEADERS = \
+			vfolder.h
+
+vfolder_la_LDFLAGS = \
+		-avoid-version -module \
+		$(GTK_LIBS)
+
+vfolder_la_LIBADD =
+
+vfolder_la_CPPFLAGS = \
+		-I$(top_srcdir)/src \
+		-I$(top_srcdir)/src/common \
+		-I$(top_builddir)/src/common \
+		-I$(top_srcdir)/src/gtk \
+		$(GLIB_CFLAGS) \
+		$(GTK_CFLAGS)
diff --git a/src/plugins/vfolder/vfolder.c b/src/plugins/vfolder/vfolder.c
new file mode 100644
index 0000000..330252c
--- /dev/null
+++ b/src/plugins/vfolder/vfolder.c
@@ -0,0 +1,270 @@
+/*
+ * $Id: $
+ */
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ *
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "common/claws.h"
+#include "common/version.h"
+#include "plugin.h"
+#include "defs.h"
+
+#include "procmsg.h"
+#include "procheader.h"
+#include "folder.h"
+#include "alertpanel.h"
+#include "main.h"
+#include "localfolder.h"
+#include "statusbar.h"
+
+#include "vfolder.h"
+#include "vfolder_gtk.h"
+#include "vfolder_prop.h"
+
+typedef struct {
+	LocalFolder folder;
+} VFolder;
+
+FolderClass vfolder_class;
+GHashTable* vfolders;
+static gboolean existing_tree_found = FALSE;
+
+static void free_vfolder_hashtable(gpointer data) {
+	g_return_if_fail(data!= NULL);
+
+    GHashTable* vfolder = (GHashTable *) data;
+    g_hash_table_destroy(vfolder);
+}
+
+static GHashTable* vfolders_hashtable_new() {
+	return g_hash_table_new_full(g_str_hash,
+			g_str_equal, g_free, free_vfolder_hashtable);
+}
+
+static GHashTable* vfolder_hashtable_new() {
+	return g_hash_table_new_full(g_str_hash,
+			g_str_equal, g_free, (GDestroyNotify) procmsg_msginfo_free);
+}
+
+static void vfolder_init_read_func(FolderItem* item, gpointer data) {
+	g_return_if_fail(item != NULL);
+
+	if (! IS_VFOLDER_FOLDER_ITEM(item))
+		return;
+
+    existing_tree_found = TRUE;
+
+	if (folder_item_parent(item) == NULL)
+		return;
+
+	vfolder_folder_item_props_read(VFOLDER_ITEM(item));
+	vfolder_set_msgs_filter(VFOLDER_ITEM(item));
+
+/*	if (! IS_VFOLDER_FROZEN(VFOLDER_ITEM(item))) {
+		folder_item_scan(VFOLDER_ITEM(item)->source);
+	}*/
+}
+
+static void vfolder_make_rc_dir(void) {
+	gchar* vfolder_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, VFOLDER_DIR, NULL);
+
+	if (! is_dir_exist(vfolder_dir)) {
+		if (make_dir(vfolder_dir) < 0) {
+			g_warning("couldn't create directory %s\n", vfolder_dir);
+		}
+
+		debug_print("created directorty %s\n", vfolder_dir);
+	}
+
+	g_free(vfolder_dir);
+}
+
+static void vfolder_create_default_mailbox(void) {
+	Folder* root = NULL;
+
+	vfolder_make_rc_dir();
+
+	root = folder_new(vfolder_folder_get_class(), VFOLDER_DEFAULT_MAILBOX, NULL);
+
+	g_return_if_fail(root != NULL);
+
+	folder_add(root);
+}
+
+static Folder* vfolder_new_folder(const gchar* name, const gchar* path) {
+	VFolder* folder;
+
+	debug_print("VFolder: new_folder\n");
+
+	vfolder_make_rc_dir();
+
+	folder = g_new0(VFolder, 1);
+	FOLDER(folder)->klass = &vfolder_class;
+	folder_init(FOLDER(folder), name);
+
+	return FOLDER(folder);
+}
+
+static void vfolder_destroy_folder(Folder* _folder)
+{
+	VFolder* folder = VFOLDER(_folder);
+
+	folder_local_folder_destroy(LOCAL_FOLDER(folder));
+}
+
+static gint vfolder_create_tree(Folder* folder) {
+	FolderItem* rootitem;
+	GNode* rootnode;
+
+	vfolder_make_rc_dir();
+
+	if (!folder->node) {
+		rootitem = folder_item_new(folder, folder->name, NULL);
+		rootitem->folder = folder;
+		rootnode = g_node_new(rootitem);
+		folder->node = rootnode;
+		rootitem->node = rootnode;
+	} else {
+		rootitem = FOLDER_ITEM(folder->node->data);
+		rootnode = folder->node;
+	}
+
+	debug_print("VFolder: created new vfolder tree\n");
+	return 0;
+}
+
+static gint vfolder_scan_tree(Folder *folder) {
+	g_return_val_if_fail(folder != NULL, -1);
+
+	folder->outbox = NULL;
+	folder->draft = NULL;
+	folder->queue = NULL;
+	folder->trash = NULL;
+
+	debug_print("VFolder: scanning tree\n");
+	vfolder_create_tree(folder);
+
+	return 0;
+}
+
+FolderClass* vfolder_folder_get_class() {
+	if (vfolder_class.idstr == NULL ) {
+		vfolder_class.type = F_UNKNOWN;
+		vfolder_class.idstr = "vfolder";
+		vfolder_class.uistr = "VFolder";
+
+		/* Folder functions */
+		vfolder_class.new_folder = vfolder_new_folder;
+		vfolder_class.destroy_folder = vfolder_destroy_folder;
+		vfolder_class.set_xml = folder_set_xml;
+		vfolder_class.get_xml = folder_get_xml;
+		vfolder_class.scan_tree = vfolder_scan_tree;
+		vfolder_class.create_tree = vfolder_create_tree;
+
+		/* FolderItem functions */
+/*		vfolder_class.item_new = vfolder_item_new;
+		vfolder_class.item_destroy = vfolder_item_destroy;
+		vfolder_class.item_get_path = vfolder_item_get_path;
+		vfolder_class.create_folder = vfolder_create_folder;
+		vfolder_class.rename_folder = NULL;
+		vfolder_class.remove_folder = vfolder_remove_folder;
+		vfolder_class.get_num_list = vfolder_get_num_list;
+		vfolder_class.scan_required = vfolder_scan_required;*/
+		vfolder_class.item_new = NULL;
+		vfolder_class.item_destroy = NULL;
+		vfolder_class.item_get_path = NULL;
+		vfolder_class.create_folder = NULL;
+		vfolder_class.rename_folder = NULL;
+		vfolder_class.remove_folder = NULL;
+		vfolder_class.get_num_list = NULL;
+		vfolder_class.scan_required = NULL;
+
+		/* Message functions */
+/*		vfolder_class.get_msginfo = vfolder_get_msginfo;
+		vfolder_class.fetch_msg = vfolder_fetch_msg;
+		vfolder_class.copy_msgs = vfolder_copy_msgs;
+		vfolder_class.copy_msg = vfolder_copy_msg;
+		vfolder_class.add_msg = vfolder_add_msg;
+		vfolder_class.add_msgs = vfolder_add_msgs;
+		vfolder_class.remove_msg = vfolder_remove_msg;
+		vfolder_class.remove_msgs = NULL;
+		vfolder_class.remove_all_msg = vfolder_remove_all_msg;
+		vfolder_class.change_flags = NULL;
+		vfolder_class.subscribe = vfolder_subscribe_uri;*/
+		vfolder_class.get_msginfo = NULL;
+		vfolder_class.fetch_msg = NULL;
+		vfolder_class.copy_msgs = NULL;
+		vfolder_class.copy_msg = NULL;
+		vfolder_class.add_msg = NULL;
+		vfolder_class.add_msgs = NULL;
+		vfolder_class.remove_msg = NULL;
+		vfolder_class.remove_msgs = NULL;
+		vfolder_class.remove_all_msg = NULL;
+		vfolder_class.change_flags = NULL;
+		vfolder_class.subscribe = NULL;
+
+		debug_print("VFolder: registered folderclass\n");
+	}
+
+	return &vfolder_class;
+}
+
+/* Local functions */
+
+gboolean vfolder_init(void) {
+	gchar* error = g_new0(gchar, 1);
+
+	folder_register_class(vfolder_folder_get_class());
+
+	if (! vfolder_gtk_init(&error)) {
+		alertpanel_error("%s", error);
+		vfolder_done();
+		return FALSE;
+	}
+
+	folder_func_to_all_folders((FolderItemFunc)vfolder_init_read_func, NULL);
+
+    vfolders = vfolders_hashtable_new();
+
+    if (existing_tree_found == FALSE)
+        vfolder_create_default_mailbox();
+
+	return TRUE;
+}
+
+void vfolder_done(void) {
+
+	vfolder_gtk_done();
+
+    g_hash_table_destroy(vfolders);
+
+	if (!claws_is_exiting())
+		folder_unregister_class(vfolder_folder_get_class());
+}
diff --git a/src/plugins/vfolder/vfolder.h b/src/plugins/vfolder/vfolder.h
new file mode 100644
index 0000000..51f394d
--- /dev/null
+++ b/src/plugins/vfolder/vfolder.h
@@ -0,0 +1,76 @@
+/*
+ * $Id: $
+ */
+
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VFOLDER_H__
+#define __VFOLDER_H__
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+G_BEGIN_DECLS
+
+#include "folder.h"
+#include "procmsg.h"
+
+/* Name of directory in rcdir where VFolder will store its data. */
+#define VFOLDER_DIR "vfolder"
+
+/* Parent mailbox name */
+#define VFOLDER_DEFAULT_MAILBOX	_("Virtual folders")
+
+typedef struct _VFolderItem VFolderItem;
+
+typedef MsgInfoList* (*MSGFILTERFUNC) (MsgInfoList* msgs, VFolderItem* item);
+
+struct _VFolderItem {
+	FolderItem		item;
+
+	gchar*			filter;				/* Regex used to select messages */
+	gboolean		frozen;				/* Automatic update or not */
+	gboolean		updating;			/* Is this VFolder currently updating */
+
+	FolderItem*		source;				/* Source folder for virtual folder */
+	GHashTable*		msg_store;		    /* Hashtable containing MsgInfo. Key is msginfo_identifier */
+	MSGFILTERFUNC	msg_filter_func;	/* Active filter function */
+};
+
+#define VFOLDER_ITEM(obj) ((VFolderItem *)obj)
+#define VFOLDER(obj) ((VFolder *)obj)
+
+#define IS_VFOLDER_FOLDER(folder) \
+	((folder) && (folder->klass == vfolder_folder_get_class()))
+#define IS_VFOLDER_FOLDER_ITEM(item) \
+	((item) && (item->folder->klass == vfolder_folder_get_class()))
+#define IS_VFOLDER_MSGINFO(msginfo) \
+	((msginfo) && (msginfo->folder) && IS_VFOLDER_FOLDER_ITEM(msginfo->folder))
+
+gboolean vfolder_init(void);
+void vfolder_done(void);
+
+FolderClass* vfolder_folder_get_class(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/plugins/vfolder/vfolder_gtk.c b/src/plugins/vfolder/vfolder_gtk.c
new file mode 100644
index 0000000..eb037c5
--- /dev/null
+++ b/src/plugins/vfolder/vfolder_gtk.c
@@ -0,0 +1,1060 @@
+/*
+ * $Id: $
+ */
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ *
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#include "claws-features.h"
+#endif
+
+#include "menu.h"
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "common/claws.h"
+#include "common/version.h"
+#include "plugin.h"
+#include "defs.h"
+
+#include "mainwindow.h"
+#include "inputdialog.h"
+#include "folder.h"
+#include "folderview.h"
+#include "folder_item_prefs.h"
+#include "alertpanel.h"
+#include "hooks.h"
+#include "utils.h"
+#include "summaryview.h"
+
+#include "main.h"
+#include "gtkutils.h"
+
+#include "vfolder_gtk.h"
+#include "vfolder.h"
+#include "vfolder_prop.h"
+
+#define CONFIG_GROUP "VFolder"
+
+static guint folder_hook_id;
+static guint item_hook_id;
+static guint msginfo_hook_id;
+static GSList* widgets = NULL;
+
+typedef struct {
+	MsgInfoList*	list;
+	VFolderItem*	item;
+	gchar*			file;
+} AddMsgData;
+
+typedef struct {
+	GtkWidget*	widget;
+	GtkAction*	action;
+} MenuItem;
+
+static char* vfolder_popup_menu_labels[] = {
+	N_("_Refresh folder"),
+	N_("Refresh _all folders"),
+	N_("Folder pr_operties..."),
+	N_("Rena_me..."),
+	N_("_Create new folder..."),
+	N_("_Delete folder..."),
+	NULL
+};
+
+static GtkActionEntry vfolder_popup_entries[] = {
+	{"FolderViewPopup/RefreshFolder",		NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
+	{"FolderViewPopup/RefreshAllFolders",	NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
+
+	{"FolderViewPopup/FolderProperties",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_properties_cb) },
+
+	{"FolderViewPopup/RenameFolder",	NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ },
+
+	{"FolderViewPopup/NewFolder",		NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_new_folder_cb) },
+	{"FolderViewPopup/RemoveFolder",	NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_remove_folder_cb) },
+};
+
+static void vfolder_add_menuitems(GtkUIManager *ui_manager, FolderItem *item) {
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RefreshFolder", "FolderViewPopup/RefreshFolder", GTK_UI_MANAGER_MENUITEM)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RefreshAllFolders", "FolderViewPopup/RefreshAllFolders", GTK_UI_MANAGER_MENUITEM)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "FolderProperties", "FolderViewPopup/FolderProperties", GTK_UI_MANAGER_MENUITEM)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "NewFolder", "FolderViewPopup/NewFolder", GTK_UI_MANAGER_MENUITEM)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RemoveFolder", "FolderViewPopup/RemoveFolder", GTK_UI_MANAGER_MENUITEM)
+	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+}
+
+static void vfolder_set_sensitivity(GtkUIManager *ui_manager, FolderItem *item) {
+#define SET_SENS(name, sens) \
+	cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
+
+	VFolderItem *ritem = (VFolderItem *)item;
+	SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL && ! ritem->frozen);
+	SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL && ! ritem->frozen);
+	SET_SENS("FolderViewPopup/FolderProperties", folder_item_parent(item) != NULL);
+	SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(item) != NULL);
+	SET_SENS("FolderViewPopup/NewFolder", TRUE);
+	SET_SENS("FolderViewPopup/RemoveFolder", folder_item_parent(item) != NULL);
+
+#undef SET_SENS
+}
+
+static FolderViewPopup vfolder_popup = {
+	"vfolder",
+	"<vfolder>",
+	vfolder_popup_entries,
+	G_N_ELEMENTS(vfolder_popup_entries),
+	NULL, 0,
+	NULL, 0, 0, NULL,
+	vfolder_add_menuitems,
+	vfolder_set_sensitivity
+};
+
+static void vfolder_fill_popup_menu_labels(void) {
+	gint i;
+
+	for (i = 0; vfolder_popup_menu_labels[i] != NULL; i++) {
+		(vfolder_popup_entries[i]).label = _(vfolder_popup_menu_labels[i]);
+	}
+}
+
+static void gslist_menu_item_free(GSList** menu_list) {
+	GSList* list;
+
+	if (! menu_list || ! *menu_list)
+		return;
+
+	for (list = *menu_list; list; list = g_slist_next(list)) {
+		MenuItem* menu = (MenuItem *) list->data;
+		g_free(menu);
+	}
+
+	g_slist_free(*menu_list);
+	*menu_list = NULL;
+}
+
+static gboolean get_menu_widgets() {
+	MainWindow* mainwindow;
+	MenuItem* menuitem = NULL;
+	GtkWidget* widget;
+
+	mainwindow = mainwindow_get_mainwindow();
+	if (mainwindow && mainwindow->ui_manager) {
+		widget = gtk_ui_manager_get_widget(
+			mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/");
+		if (widget) {
+			menuitem = g_new0(MenuItem, 1);
+			menuitem->widget = widget;
+			menuitem->action = gtk_ui_manager_get_action(
+				mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/");
+			widgets = g_slist_prepend(widgets, menuitem);
+		}
+		else
+			return FALSE;
+
+		widget = gtk_ui_manager_get_widget(
+			mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/");
+		if (widget) {
+			menuitem = g_new0(MenuItem, 1);
+			menuitem->widget = widget;
+			menuitem->action = gtk_ui_manager_get_action(
+				mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/");
+			widgets = g_slist_prepend(widgets, menuitem);
+		}
+		else {
+			gslist_menu_item_free(&widgets);
+			return FALSE;
+		}
+
+		widget = gtk_ui_manager_get_widget(
+			mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/");
+		if (widget) {
+			menuitem = g_new0(MenuItem, 1);
+			menuitem->widget = widget;
+			menuitem->action = gtk_ui_manager_get_action(
+				mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/");
+			widgets = g_slist_prepend(widgets, menuitem);
+		}
+		else {
+			gslist_menu_item_free(&widgets);
+			return FALSE;
+		}
+
+		widget = gtk_ui_manager_get_widget(
+			mainwindow->ui_manager, "/Menu/Message/Move/");
+		if (widget) {
+			menuitem = g_new0(MenuItem, 1);
+			menuitem->widget = widget;
+			menuitem->action = gtk_ui_manager_get_action(
+				mainwindow->ui_manager, "/Menu/Message/Move/");
+			widgets = g_slist_prepend(widgets, menuitem);
+		}
+		else {
+			gslist_menu_item_free(&widgets);
+			return FALSE;
+		}
+
+		widget = gtk_ui_manager_get_widget(
+			mainwindow->ui_manager, "/Menu/Message/Trash/");
+		if (widget) {
+			menuitem = g_new0(MenuItem, 1);
+			menuitem->widget = widget;
+			menuitem->action = gtk_ui_manager_get_action(
+				mainwindow->ui_manager, "/Menu/Message/Trash/");
+			widgets = g_slist_prepend(widgets, menuitem);
+		}
+		else {
+			gslist_menu_item_free(&widgets);
+			return FALSE;
+		}
+
+		widget = gtk_ui_manager_get_widget(
+			mainwindow->ui_manager, "/Menu/Message/Delete/");
+		if (widget) {
+			menuitem = g_new0(MenuItem, 1);
+			menuitem->widget = widget;
+			menuitem->action = gtk_ui_manager_get_action(
+				mainwindow->ui_manager, "/Menu/Message/Delete/");
+			widgets = g_slist_prepend(widgets, menuitem);
+		}
+		else {
+			gslist_menu_item_free(&widgets);
+			return FALSE;
+		}
+
+	}
+	else
+		return FALSE;
+
+	return TRUE;
+}
+/*
+static gboolean vfolder_widgets_is_visible() {
+	gboolean visible = TRUE;
+
+	if (widgets && widgets->data) {
+		MenuItem* menu = (MenuItem *) widgets->data;
+		visible = gtk_widget_get_visible(menu->widget);
+	}
+
+	return visible;
+}
+
+static gboolean vfolder_hide_widgets(VFolderItem* item) {
+	GSList* list;
+	MainWindow* mainwindow;
+
+//	if (! item->deep_copy) {
+		for (list = widgets; list; list = g_slist_next(list)) {
+			MenuItem* menu = (MenuItem *) list->data;
+			gtk_widget_hide(menu->widget);
+			gtk_action_block_activate(menu->action);
+		}
+
+		mainwindow = mainwindow_get_mainwindow();
+		if (mainwindow && mainwindow->toolbar) {
+			if (mainwindow->toolbar->trash_btn)
+				gtk_widget_hide(mainwindow->toolbar->trash_btn);
+			if (mainwindow->toolbar->delete_btn)
+				gtk_widget_hide(mainwindow->toolbar->delete_btn);
+		}
+//	}
+	return TRUE;
+}
+*/
+static gboolean vfolder_show_widgets(VFolderItem* item) {
+	GSList* list;
+	MainWindow* mainwindow;
+
+//	if (! item->deep_copy) {
+		for (list = widgets; list; list = g_slist_next(list)) {
+			MenuItem* menu = (MenuItem *) list->data;
+			gtk_widget_show(menu->widget);
+			gtk_action_unblock_activate(menu->action);
+		}
+
+		mainwindow = mainwindow_get_mainwindow();
+		if (mainwindow && mainwindow->toolbar) {
+			if (mainwindow->toolbar->trash_btn)
+				gtk_widget_show(mainwindow->toolbar->trash_btn);
+			if (mainwindow->toolbar->delete_btn)
+				gtk_widget_show(mainwindow->toolbar->delete_btn);
+		}
+//	}
+	return TRUE;
+}
+/*
+static gchar* vfolder_get_message_file_path(VFolderItem* item, MsgInfo* msg) {
+	gchar* path;
+	GSList* list = NULL, *cur;
+	Folder* folder;
+	gboolean old_uid;
+	guint last = 0;
+
+	if (item->deep_copy) {
+		path = procmsg_get_message_file_path(msg);
+	}
+	else {
+		gchar* root = folder_item_get_path(msg->to_folder);
+		folder = msg->to_folder->folder;
+		guint num = folder->klass->get_num_list(folder, msg->to_folder, &list, &old_uid);
+		if (num >= 0) {
+			for (cur = list, last = 0; cur; cur = g_slist_next(cur)) {
+				guint tmp = GPOINTER_TO_UINT(cur->data);
+				if (tmp > last)
+					last = tmp;
+			}
+		}
+		g_slist_free(list);
+
+		path = g_strdup_printf("%s%s%u", root, G_DIR_SEPARATOR_S, last + 1);
+		g_free(root);
+	}
+	return path;
+}
+*/
+
+/*
+static void vfolder_item_update(AddMsgData* msgdata) {
+	MsgInfoList* cur;
+	GSList update;
+	MsgFileInfo fileinfo;
+
+	if (!msgdata->item || !msgdata->list->data)
+		return;
+
+	for (cur = msgdata->list; cur; cur = g_slist_next(cur)) {
+		MsgInfo* msg = (MsgInfo *) cur->data;
+		if (MSG_IS_DELETED(msg->flags)) {
+			folder_item_remove_msg(FOLDER_ITEM(msgdata->item), msg->msgnum);
+		}
+		else {
+			fileinfo.msginfo = msg;
+			fileinfo.flags = &msg->flags;
+			fileinfo.file = msgdata->file;
+			update.data = &fileinfo;
+			update.next = NULL;
+			folder_item_scan(msg->folder);
+			gint n = folder_item_add_msgs(FOLDER_ITEM(msgdata->item), &update, FALSE);
+			gchar* p = strrchr(fileinfo.file, G_DIR_SEPARATOR);
+			p += 1;
+			guint num = to_number((const gchar *) p);
+			vfolder_replace_key_in_bridge(msgdata->item, msg->msgnum, num);
+			FOLDER_ITEM(msgdata->item)->last_num = n;
+		}
+	}
+
+	//procmsg_message_file_list_free(list);
+	//item->msginfos = folder_item_get_msg_list(FOLDER_ITEM(item));
+}
+*/
+/*
+static void add_msg_data_free(AddMsgData** rec) {
+	if (rec && *rec) {
+		AddMsgData* data = *rec;
+		g_slist_free(data->list);
+		g_free(data->file);
+		g_free(data);
+		*rec = NULL;
+	}
+}
+*/
+/*
+static void vfolder_update_affected_folder_items(MsgInfo* msginfo) {
+	GList *vfolders, *cur;
+	GSList* cur_msg;
+	gchar* src;
+	AddMsgData* data;
+	MsgInfo* msg;
+
+	if (! msginfo)
+		return;
+
+	if (MSG_IS_NEW(msginfo->flags) ||
+		MSG_IS_MOVE(msginfo->flags) ||
+		MSG_IS_COPY(msginfo->flags) ||
+		MSG_IS_DELETED(msginfo->flags)) {
+		vfolders = vfolder_get_vfolder_items();
+		for (cur = vfolders; cur; cur = g_list_next(cur)) {
+			data = g_new0(AddMsgData, 1);
+			VFolderItem* vitem = VFOLDER_ITEM(cur->data);
+			if (MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))
+				src = folder_item_get_identifier(msginfo->to_folder);
+			else
+				src = folder_item_get_identifier(msginfo->folder);
+			gchar* shadow = folder_item_get_identifier(vitem->source);
+			debug_print("cmp %s : %s\n", src, shadow);
+			if (src && shadow && strcmp(src, shadow) == 0) {
+				if (MSG_IS_DELETED(msginfo->flags)) {
+					msg = vfolder_find_msg_from_claws_num(vitem, msginfo->msgnum);
+					if (msg)
+						data->list = g_slist_append(data->list, msg);
+					else {
+						add_msg_data_free(&data);
+						g_slist_free(add_msg_data);
+						add_msg_data = NULL;
+						g_free(src);
+						g_free(shadow);
+						return;
+					}
+				}
+				else {
+					data->list = g_slist_append(data->list, msginfo);
+					data->item = vitem;
+					data->file = vfolder_get_message_file_path(vitem, msginfo);
+					add_msg_data = g_slist_prepend(add_msg_data, data);
+				}
+				if (data->list && MSG_IS_DELETED(msginfo->flags)) {
+					GSList* list = vfolder_filter_msgs_list(data->list, vitem);
+					if (list && list->data) {
+						MsgInfo* msg = (MsgInfo *) list->data;
+						MSG_SET_PERM_FLAGS(msg->flags, MSG_DELETED);
+					}
+					g_slist_free(data->list);
+					data->list = list;
+					data->item = vitem;
+					vfolder_item_update(data);
+					add_msg_data_free(&data);
+					g_slist_free(add_msg_data);
+					add_msg_data = NULL;
+				}
+			}
+			g_free(src);
+			g_free(shadow);
+		}
+	}
+	if (add_msg_data) {
+		for (cur_msg = add_msg_data; cur_msg; cur_msg = g_slist_next(cur_msg)) {
+			data = (AddMsgData *) cur_msg->data;
+			GSList* list = vfolder_filter_msgs_list(data->list, data->item);
+			g_slist_free(data->list);
+			data->list = list;
+			vfolder_item_update(data);
+			add_msg_data_free(&data);
+		}
+		g_slist_free(add_msg_data);
+		add_msg_data = NULL;
+	}
+}
+*/
+static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) {
+	FolderUpdateData* hookdata;
+
+	g_return_val_if_fail(source != NULL, FALSE);
+	hookdata = (FolderUpdateData *) source;
+
+	if (! hookdata->folder || IS_VFOLDER_FOLDER(hookdata->folder))
+		return FALSE;
+
+	if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) {
+		/* TODO: check if the removed folder item is foundation for vfolder */
+		debug_print("FOLDER_REMOVE_FOLDERITEM\n");
+	}
+
+	if (hookdata->update_flags & FOLDER_REMOVE_FOLDER) {
+		/* TODO: check if the removed folder is foundation for vfolder */
+		debug_print("FOLDER_REMOVE_FOLDER\n");
+	}
+
+	if (hookdata->update_flags & FOLDER_TREE_CHANGED) {
+		/* TODO: check if the removed folder is foundation for vfolder */
+		debug_print("FOLDER_TREE_CHANGED\n");
+	}
+
+	if (hookdata->update_flags & FOLDER_RENAME_FOLDERITEM) {
+		/* TODO: check if the removed folder is foundation for vfolder */
+		debug_print("FOLDER_RENAME_FOLDERITEM\n");
+	}
+
+	return FALSE;
+}
+
+static gboolean vfolder_folder_item_update_hook(gpointer source, gpointer data) {
+	FolderItemUpdateData* hookdata;
+//	gint save_state = -1;
+	GList *items = NULL, *cur;
+//	gboolean r;
+//	MainWindow* mainwindow;
+
+	g_return_val_if_fail(source != NULL, FALSE);
+	hookdata = (FolderItemUpdateData *) source;
+
+	if (! hookdata->item || IS_VFOLDER_FOLDER_ITEM(hookdata->item))
+		return FALSE;
+
+	if (hookdata->update_flags & F_ITEM_UPDATE_REMOVEMSG ) {
+		debug_print("F_ITEM_UPDATE_REMOVEMSG\n");
+		//items = vfolder_get_vfolder_from_source(hookdata->item);
+		if (items) {
+			for (cur = items; cur; cur = g_list_next(cur)) {
+				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_REMOVEMSG);
+			}
+			g_list_free(items);
+		}
+	}
+
+	else if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT) {
+		debug_print("F_ITEM_UPDATE_CONTENT\n");
+		//items = vfolder_get_vfolder_from_source(hookdata->item);
+		if (items) {
+			for (cur = items; cur; cur = g_list_next(cur)) {
+				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_CONTENT);
+			}
+			g_list_free(items);
+		}
+		//mainwindow = mainwindow_get_mainwindow();
+		//summary_execute(mainwindow->summaryview);
+	}
+
+	else if (hookdata->update_flags & F_ITEM_UPDATE_ADDMSG) {
+		debug_print("F_ITEM_UPDATE_ADDMSG\n");
+		//items = vfolder_get_vfolder_from_source(hookdata->item);
+		if (items) {
+			for (cur = items; cur; cur = g_list_next(cur)) {
+				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_ADDMSG);
+			}
+			g_list_free(items);
+		}
+	}
+
+	else if (hookdata->update_flags & F_ITEM_UPDATE_MSGCNT) {
+		debug_print("F_ITEM_UPDATE_MSGCNT\n");
+/*		if (IS_VFOLDER_FOLDER_ITEM(item)) {
+
+			if (! (VFOLDER_ITEM(item))->deep_copy) {
+				if (! (VFOLDER_ITEM(item))->active) {
+					r = vfolder_hide_widgets(VFOLDER_ITEM(item));
+					if (r)
+						VFOLDER_ITEM(item)->active = TRUE;
+				}
+				else {
+					r = vfolder_show_widgets(VFOLDER_ITEM(item));
+					if (r)
+						VFOLDER_ITEM(item)->active = FALSE;
+				}
+
+				if (r)
+					save_state = 1;
+				else
+					save_state = 0;
+			}
+			else
+				vfolder_show_widgets(VFOLDER_ITEM(item));
+		}
+		else {
+			if (!vfolder_widgets_is_visible())
+				vfolder_show_widgets(VFOLDER_ITEM(item));
+		}*/
+/*
+		items = vfolder_get_vfolder_from_source(hookdata->item);
+		if (items) {
+			for (cur = items; cur; cur = g_list_next(cur)) {
+				vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_MSGCNT);
+			}
+			g_list_free(items);
+		}
+*/
+	}
+
+	else if (hookdata->update_flags & F_ITEM_UPDATE_NAME) {
+		/* TODO: need update? */
+		debug_print("F_ITEM_UPDATE_NAME\n");
+		//items = vfolder_get_vfolder_from_source(hookdata->item);
+		if (items) {
+			for (cur = items; cur; cur = g_list_next(cur)) {
+				//vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_NAME);
+			}
+			g_list_free(items);
+		}
+	}
+
+	else {
+		/* Unhandled callback */
+		debug_print("Unhandled FolderItem callback\n");
+	}
+/*
+	if (!save_state) {
+		MainWindow* mainwindow = mainwindow_get_mainwindow();
+		alertpanel_error(_("%s: Could not hide dangerous actions"), hookdata->item->name);
+		summary_lock(mainwindow->summaryview);
+	}
+*/
+	return FALSE;
+}
+/*
+static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
+	MsgInfoUpdate* hookdata;
+	MainWindow* mainwindow;
+	MsgInfo* msginfo;
+
+	g_return_val_if_fail(source != NULL, FALSE);
+	hookdata = (MsgInfoUpdate *) source;
+	msginfo = hookdata->msginfo;
+
+	g_return_val_if_fail(msginfo != NULL, TRUE);
+
+	if (IS_VFOLDER_MSGINFO(msginfo))
+		return FALSE;
+
+	debug_print("\n\nPermflag: %u Tmpflag: %u (scanned: %u)\n\n\n",
+		(guint32) msginfo->flags.perm_flags, (guint32) msginfo->flags.tmp_flags, 1U << 31);
+	if (MSG_IS_NEW(msginfo->flags)) {
+		debug_print("MSG_IS_NEW\n");
+		vfolder_update_affected_folder_items(msginfo);
+		mainwindow = mainwindow_get_mainwindow();
+		summary_execute(mainwindow->summaryview);
+	}
+
+	if (MSG_IS_DELETED(msginfo->flags)) {
+		debug_print("MSG_IS_DELETED\n");
+		vfolder_update_affected_folder_items(msginfo);
+		mainwindow = mainwindow_get_mainwindow();
+		summary_execute(mainwindow->summaryview);
+	}
+
+	if (MSG_IS_MOVE(msginfo->flags)) {
+		debug_print("MSG_IS_MOVE\n");
+		vfolder_update_affected_folder_items(msginfo);
+		mainwindow = mainwindow_get_mainwindow();
+		summary_execute(mainwindow->summaryview);
+	}
+
+	if (MSG_IS_COPY(msginfo->flags)) {
+		debug_print("MSG_IS_COPY\n");
+		vfolder_update_affected_folder_items(msginfo);
+		mainwindow = mainwindow_get_mainwindow();
+		summary_execute(mainwindow->summaryview);
+	}
+
+//	if (MSG_IS_POSTFILTERED(msginfo->flags)) {
+//		debug_print("MSG_IS_POSTFILTERED\n");
+//		vfolder_update_affected_folder_items(msginfo);
+//		mainwindow = mainwindow_get_mainwindow();
+//		summary_execute(mainwindow->summaryview);
+//	}
+
+
+	return FALSE;
+}
+*/
+static gchar* vfolder_get_rc_file(VFolderItem* item) {
+	gchar* (*item_get_path)	(Folder* folder, FolderItem* item);
+	gchar* path;
+	gchar* rc_file;
+
+	item_get_path = FOLDER_ITEM(item)->folder->klass->item_get_path;
+
+	path = item_get_path(FOLDER_ITEM(item)->folder, FOLDER_ITEM(item));
+	rc_file = g_strconcat(path, G_DIR_SEPARATOR_S, "folderitemrc", NULL);
+	g_free(path);
+
+	return rc_file;
+}
+
+FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item) {
+	gchar* rc_file;
+	GKeyFile* config;
+	gchar* id;
+	gchar* data = NULL;
+	FILE* fp;
+	gsize len = 0;
+	FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM;
+/*	gchar* numstr;
+	GHashTableIter iter;
+	gpointer key, value;*/
+
+	g_return_val_if_fail(item != NULL, resp);
+
+	rc_file = vfolder_get_rc_file(item);
+	config = g_key_file_new();
+
+	if (item->filter)
+		g_key_file_set_string(config, CONFIG_GROUP, "filter", item->filter);
+
+	g_key_file_set_boolean(config, CONFIG_GROUP, "frozen", item->frozen);
+
+	if (item->source) {
+		id = folder_item_get_identifier(item->source);
+		if (id) {
+			g_key_file_set_string(config, CONFIG_GROUP, "source", id);
+			g_free(id);
+		}
+	}
+
+/*	if (item->claws_to_me && item->me_to_claws) {
+		numstr = NULL;
+		g_hash_table_iter_init(&iter, item->claws_to_me);
+		while (g_hash_table_iter_next(&iter, &key, &value)) {
+			len++;
+			MsgBridge* bridge = value;
+			if (numstr) {
+				gchar* tmp = g_strdup(numstr);
+				g_free(numstr);
+				numstr = g_strdup_printf("%s, %u:%u",
+					tmp, bridge->my_num, bridge->claws_num);
+				g_free(tmp);
+			}
+			else
+				numstr = g_strdup_printf("%u:%u", bridge->my_num, bridge->claws_num);
+		}
+
+		g_key_file_set_string(config, CONFIG_GROUP, "file_id_list", numstr);
+		g_free(numstr);
+	}*/
+
+	if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) {
+		gchar* bakpath = g_strconcat(rc_file, ".bak", NULL);
+		if (g_rename(rc_file, bakpath) < 0) {
+			g_warning("%s: Could not create", bakpath);
+			resp = FOLDER_ITEM_PROPS_BACKUP_FAIL;
+		}
+		g_free(bakpath);
+	}
+
+//	g_key_file_set_integer(config, CONFIG_GROUP, "filter-function", item->filter_func);
+
+	data = g_key_file_to_data(config, &len, NULL);
+	if (len < 1) {
+		g_warning("Could not get config data");
+		resp = FOLDER_ITEM_PROPS_READ_DATA_FAIL;
+	}
+	else {
+		fp = g_fopen(rc_file, "w");
+		if (fp == NULL) {
+			gchar* dir_path_end = g_strrstr(rc_file, G_DIR_SEPARATOR_S);
+			gchar* rc_dir = g_strndup(rc_file, dir_path_end - rc_file);
+			debug_print("rc_dir: %s\n", rc_dir);
+			int r = g_mkdir_with_parents(rc_dir, 0700);
+			if (r != 0)
+				resp = FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL;
+			g_free(rc_dir);
+			if (resp == FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL)
+				goto error;
+			fp = g_fopen(rc_file, "w");
+			if (fp == NULL) {
+				resp = FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL;
+				goto error;
+			}
+		}
+		fwrite(data, len, 1, fp);
+		fclose(fp);
+		resp = FOLDER_ITEM_PROPS_OK;
+	}
+
+error:
+	g_free(data);
+
+	g_key_file_free(config);
+	g_free(rc_file);
+
+	return resp;
+}
+
+FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item) {
+	gchar* rc_file;
+	GKeyFile* config;
+	GError* error = NULL;
+	gchar *id, *msgnums;
+	gchar **list, **head;
+	FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM;
+	gint lastnum;
+
+	g_return_val_if_fail(item != NULL, resp);
+
+	rc_file = vfolder_get_rc_file(item);
+	config = g_key_file_new();
+
+	if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) {
+		g_key_file_load_from_file(config, rc_file, G_KEY_FILE_KEEP_COMMENTS, &error);
+		if (error) {
+			g_warning("%s. Using defaults", error->message);
+			g_error_free(error);
+			resp = FOLDER_ITEM_PROPS_READ_USING_DEFAULT;
+		}
+		else {
+			item->filter = g_key_file_get_string(config, CONFIG_GROUP, "filter", NULL);
+//			item->search = g_key_file_get_integer(config, CONFIG_GROUP, "searchtype", NULL);
+			item->frozen = g_key_file_get_boolean(config, CONFIG_GROUP, "frozen", NULL);
+//			item->deep_copy = g_key_file_get_boolean(config, CONFIG_GROUP, "deep_copy", NULL);
+//			item->filter_func = g_key_file_get_integer(config, CONFIG_GROUP, "filter_function", NULL);
+
+			id = g_key_file_get_string(config, CONFIG_GROUP, "source", NULL);
+			if (id) {
+				item->source = folder_find_item_from_identifier(id);
+				g_free(id);
+			}
+			msgnums = g_key_file_get_string(config, CONFIG_GROUP, "file_id_list", NULL);
+			if (msgnums) {
+				list = g_strsplit(msgnums, ",", 0);
+				head = list;
+				lastnum = -1;
+				while (*list) {
+					/*gchar* anum = g_strdup(*list++);
+					g_strstrip(anum);
+					MsgBridge* bridge = vfolder_split_file_id(anum);
+					g_free(anum);
+					if (lastnum < (gint) bridge->my_num)
+						lastnum = bridge->my_num;
+					if (bridge->my_num > 0) {
+						vfolder_add_message_to_bridge(item, bridge);
+					}
+					g_free(bridge);*/
+				}
+				FOLDER_ITEM(item)->last_num = lastnum;
+				g_strfreev(head);
+				g_free(msgnums);
+			}
+			resp = FOLDER_ITEM_PROPS_OK;
+		}
+	}
+
+	g_key_file_free(config);
+	g_free(rc_file);
+
+	return resp;
+}
+
+gboolean vfolder_gtk_init(gchar** error) {
+	vfolder_fill_popup_menu_labels();
+	folderview_register_popup(&vfolder_popup);
+
+	folder_hook_id = hooks_register_hook(FOLDER_UPDATE_HOOKLIST,
+		vfolder_folder_update_hook, NULL);
+	if (folder_hook_id == -1) {
+		*error = g_strdup(_("Failed to register folder update hook"));
+		return FALSE;
+	}
+
+	item_hook_id = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
+		vfolder_folder_item_update_hook, NULL);
+	if (item_hook_id == -1) {
+		*error = g_strdup(_("Failed to register folder item update hook"));
+		hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
+		return FALSE;
+	}
+
+/*	msginfo_hook_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
+		vfolder_msg_info_update_hook, NULL);
+	if (msginfo_hook_id == -1) {
+		*error = g_strdup(_("Failed to register message info update hook"));
+		hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
+		hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
+		return FALSE;
+	}*/
+
+	if (! get_menu_widgets()) {
+		*error = g_strdup(_("Failed to get menu widgets"));
+		hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
+		hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
+		hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void vfolder_gtk_done(void) {
+	MainWindow *mainwin = mainwindow_get_mainwindow();
+	FolderView *folderview = NULL;
+	FolderItem *fitem = NULL;
+
+	hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
+	hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
+	//hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
+
+	if (mainwin == NULL || claws_is_exiting())
+		return;
+
+	folderview = mainwin->folderview;
+	fitem = folderview->summaryview->folder_item;
+
+	if (fitem && IS_VFOLDER_FOLDER_ITEM(fitem)) {
+		vfolder_show_widgets(VFOLDER_ITEM(fitem));
+		gslist_menu_item_free(&widgets);
+
+		folderview_unselect(folderview);
+		summary_clear_all(folderview->summaryview);
+	}
+
+	folderview_unregister_popup(&vfolder_popup);
+}
+
+void vfolder_properties_cb(GtkAction* action, gpointer data) {
+	FolderView *folderview = (FolderView *)data;
+	FolderItem *item;
+
+	g_return_if_fail(folderview != NULL);
+
+	item = folderview_get_selected_item(folderview);
+
+	g_return_if_fail(item != NULL);
+	g_return_if_fail(item->path != NULL);
+	g_return_if_fail(item->folder != NULL);
+
+	if (vfolder_edit_item_dialog(VFOLDER_ITEM(item))) {
+		/* TODO: update */
+		if (debug_get_mode()) {
+//			GHashTableIter iter;
+//			gpointer key, value;
+
+/*			g_hash_table_iter_init(&iter, VFOLDER_ITEM(item)->me_to_claws);
+			while (g_hash_table_iter_next(&iter, &key, &value)) {
+				gchar* buf = g_new0(gchar, BUFSIZ);
+				MsgInfo* msginfo = vfolder_find_msg_from_vfolder_num(
+					VFOLDER_ITEM(item), GPOINTER_TO_UINT(key));
+				FILE* msg = procmsg_open_message(msginfo);
+				while (fread(buf, 1, BUFSIZ - 1, msg) > 0) {
+					fprintf(stderr, "%s", buf);
+					g_free(buf);
+					buf = g_new0(gchar, BUFSIZ);
+				}
+				fprintf(stderr, "\n");
+				if (buf)
+					g_free(buf);
+				fclose(msg);
+			}*/
+		}
+		vfolder_folder_item_props_write(VFOLDER_ITEM(item));
+	}
+}
+
+void vfolder_new_folder_cb(GtkAction* action, gpointer data) {
+	FolderView *folderview = (FolderView *)data;
+	GtkCMCTree *ctree = NULL;
+	FolderItem *item;
+	FolderItem *new_item;
+	gchar *new_folder;
+	gchar *name;
+	gchar *p;
+
+	if (!folderview->selected) return;
+    if (!GTK_IS_CMCTREE(folderview->ctree)) return;
+
+    ctree = GTK_CMCTREE(folderview->ctree);
+	item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
+    //item = folderview_get_selected_item(folderview);
+	if (! item) {
+		//item = FOLDER_ITEM(vfolder_get_vfolder_item(NULL));
+	}
+
+    cm_return_if_fail(item != NULL);
+    cm_return_if_fail(item->folder != NULL);
+
+	if (item->no_sub) {
+		alertpanel_error(N_("Virtual folders cannot contain subfolders"));
+		return;
+	}
+
+	new_folder = input_dialog(_("New folder"),
+				  _("Input the name of new folder:"),
+				  _("NewFolder"));
+	if (!new_folder) return;
+	AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
+
+	p = strchr(new_folder, G_DIR_SEPARATOR);
+	if (p) {
+		alertpanel_error(_("'%c' can't be included in folder name."),
+				 G_DIR_SEPARATOR);
+		return;
+	}
+
+	name = trim_string(new_folder, 32);
+	AUTORELEASE_STR(name, {g_free(name); return;});
+
+	/* find whether the directory already exists */
+	if (folder_find_child_item_by_name(item, new_folder)) {
+		alertpanel_error(_("The folder '%s' already exists."), name);
+		return;
+	}
+
+	new_item = folder_create_folder(item, new_folder);
+	if (!new_item) {
+		alertpanel_error(_("Can't create the folder '%s'."), name);
+		return;
+	}
+
+	if (! vfolder_create_item_dialog(new_item)) {
+		//VFolderItem* vitem = VFOLDER_ITEM(new_item);
+		new_item->folder->klass->remove_folder(new_item->folder, new_item);
+		new_item = NULL;
+		return;
+	}
+
+	folder_write_list();
+}
+
+void vfolder_remove_folder_cb(GtkAction* action, gpointer data) {
+	FolderView *folderview = (FolderView *)data;
+	GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
+	FolderItem *item;
+	gchar *message, *name;
+	AlertValue avalue;
+	gchar *old_path = NULL;
+	gchar *old_id;
+
+	/* Silence lame warnings */
+	old_id = (old_path) ? NULL : old_path;
+
+	item = folderview_get_selected_item(folderview);
+	g_return_if_fail(item != NULL);
+	g_return_if_fail(item->path != NULL);
+	g_return_if_fail(item->folder != NULL);
+
+	name = trim_string(item->name, 32);
+	AUTORELEASE_STR(name, {g_free(name); return;});
+	message = g_strdup_printf
+		(_("All folders and messages under '%s' will be permanently deleted. "
+		   "Recovery will not be possible.\n\n"
+		   "Do you really want to delete?"), name);
+	avalue = alertpanel_full(_("Delete folder"), message,
+				 GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
+				 NULL, ALERT_WARNING, G_ALERTDEFAULT);
+	g_free(message);
+	if (avalue != G_ALERTALTERNATE) return;
+
+	Xstrdup_a(old_path, item->path, return);
+	old_id = folder_item_get_identifier(item);
+
+	if (folderview->opened == folderview->selected ||
+	    gtk_cmctree_is_ancestor(ctree,
+				  folderview->selected,
+				  folderview->opened)) {
+		summary_clear_all(folderview->summaryview);
+		folderview->opened = NULL;
+	}
+
+	if (item->folder->klass->remove_folder(item->folder, item) < 0) {
+		folder_item_scan(item);
+		alertpanel_error(_("Can't remove the folder '%s'."), name);
+		g_free(old_id);
+		return;
+	}
+
+	folder_write_list();
+
+	g_free(old_id);
+}
diff --git a/src/plugins/vfolder/vfolder_gtk.h b/src/plugins/vfolder/vfolder_gtk.h
new file mode 100644
index 0000000..5b41ee4
--- /dev/null
+++ b/src/plugins/vfolder/vfolder_gtk.h
@@ -0,0 +1,57 @@
+/*
+ * $Id: $
+ */
+
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VFOLDER_GTK_H__
+#define __VFOLDER_GTK_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#include "vfolder.h"
+#include <gtk/gtk.h>
+
+typedef enum {
+	FOLDER_ITEM_PROPS_OK,
+	FOLDER_ITEM_PROPS_NO_ITEM,
+	FOLDER_ITEM_PROPS_BACKUP_FAIL,
+	FOLDER_ITEM_PROPS_READ_DATA_FAIL,
+	FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL,
+	FOLDER_ITEM_PROPS_READ_USING_DEFAULT
+} FolderPropsResponse;
+
+gboolean vfolder_gtk_init(gchar** error);
+void vfolder_gtk_done(void);
+FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item);
+FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item);
+
+/* Callback functions */
+void vfolder_new_folder_cb(GtkAction* action, gpointer data);
+void vfolder_remove_folder_cb(GtkAction* action, gpointer data);
+void vfolder_properties_cb(GtkAction* action, gpointer data);
+
+G_END_DECLS
+
+#endif
diff --git a/src/plugins/vfolder/vfolder_init.c b/src/plugins/vfolder/vfolder_init.c
new file mode 100644
index 0000000..b000514
--- /dev/null
+++ b/src/plugins/vfolder/vfolder_init.c
@@ -0,0 +1,150 @@
+/*
+ * $Id: $
+ */
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ *
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "common/claws.h"
+#include "common/version.h"
+#include "plugin.h"
+
+#include "mimeview.h"
+#include "utils.h"
+#include "alertpanel.h"
+#include "statusbar.h"
+#include "menu.h"
+#include "vfolder.h"
+#include "vfolder_gtk.h"
+
+#define PLUGIN_NAME (_("VFolder"))
+
+static GtkActionEntry vfolder_main_menu[] = {{
+	"View/CreateVfolder",
+	NULL, N_("Create virtual folder..."),
+	"<Control>v", N_("Create a virtual folder"),
+	G_CALLBACK(vfolder_new_folder_cb)
+}};
+
+static gint main_menu_id = 0;
+
+gint plugin_init(gchar** error) {
+	debug_set_mode(TRUE);
+	MainWindow *mainwin = mainwindow_get_mainwindow();
+
+/*
+#ifdef G_OS_UNIX
+	bindtextdomain(TEXTDOMAIN, LOCALEDIR);
+#else
+	bindtextdomain(TEXTDOMAIN, get_locale_dir());
+#endif
+	bind_textdomain_codeset(TEXTDOMAIN, "UTF-8");
+*/
+	if (!check_plugin_version(MAKE_NUMERIC_VERSION(0,0,1,0),
+				VERSION_NUMERIC, PLUGIN_NAME, error))
+		return -1;
+
+	gtk_action_group_add_actions(mainwin->action_group, vfolder_main_menu,
+			1, (gpointer)mainwin);
+	MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/View", "CreateVfolder",
+			  "View/CreateVfolder", GTK_UI_MANAGER_MENUITEM,
+			  main_menu_id)
+
+	if (! vfolder_init()) {
+		debug_print("vfolder plugin unloading due to init errors\n");
+		plugin_done();
+		return -1;
+	}
+
+	debug_print("vfolder plugin loaded\n");
+
+	return 0;
+}
+
+gboolean plugin_done(void) {
+	MainWindow *mainwin = mainwindow_get_mainwindow();
+
+	vfolder_done();
+
+	if (mainwin == NULL)
+		return FALSE;
+
+	MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "View/CreateVfolder", main_menu_id);
+	main_menu_id = 0;
+
+	debug_print("vfolder plugin unloaded\n");
+
+	debug_set_mode(FALSE);
+	return TRUE;
+}
+
+const gchar* plugin_licence(void) {
+	return "GPL3+";
+}
+
+const gchar* plugin_version(void) {
+	return VERSION;
+}
+
+const gchar* plugin_type(void) {
+	return "GTK2";
+}
+
+const gchar* plugin_name(void) {
+	return PLUGIN_NAME;
+}
+
+const gchar* plugin_desc(void) {
+	return _("This plugin adds virtual folder support to Claws Mail.\n"
+			"\n"
+			"1) Select one or more mail folder(s) to use as the basic mail pool\n"
+			"2) Define a filter\n"
+			"3) Specify name for virtual folder\n"
+			"4) Press create and wait until the scanning of the mail pool finishes\n"
+			"\n"
+			"The VFolder will be updated periodically and when claws-mail is initially opened\n"
+			"Manual update is available from the context menu of the VFolder.\n"
+			"\n"
+			"The supported folder types are MH and IMAP.\n"
+			"Messages in a VFolder cannot be updated.\n"
+			"\n"
+			"To activate the archiving feature go to /View/Create virtual folder\n"
+			"\n"
+			"Default options can be set in /Configuration/Preferences/Plugins"
+			"/vfolder"
+			);
+}
+
+struct PluginFeature* plugin_provides(void) {
+	static struct PluginFeature features[] =
+	{ {PLUGIN_UTILITY, N_("VFolder")},
+	  {PLUGIN_FOLDERCLASS, N_("VFolder")},
+	  {PLUGIN_NOTHING, NULL} };
+	return features;
+}
diff --git a/src/plugins/vfolder/vfolder_prop.c b/src/plugins/vfolder/vfolder_prop.c
new file mode 100644
index 0000000..c7187aa
--- /dev/null
+++ b/src/plugins/vfolder/vfolder_prop.c
@@ -0,0 +1,456 @@
+/*
+ * $Id: $
+ */
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ *
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "common/claws.h"
+#include "common/version.h"
+#include "plugin.h"
+
+#include "gtkutils.h"
+#include "mainwindow.h"
+#include "foldersel.h"
+#include "alertpanel.h"
+
+#include "vfolder_gtk.h"
+#include "vfolder.h"
+#include "vfolder_prop.h"
+
+#define HEADERS	N_("Message _Headers")
+#define BODY	N_("_Message body")
+#define BOTH	N_("_Both")
+
+typedef struct {
+	GtkWidget* filter;
+	GtkWidget* frozen;
+	GtkWidget* deep_copy;
+	GtkWidget* source;
+	GtkWidget* label_btn;
+	GtkWidget* message_btn;
+	GtkWidget* both_btn;
+} PropsDialog;
+
+static void add_current_config(VFolderItem* item, PropsDialog* props) {
+	if (item->filter)
+		gtk_entry_set_text(GTK_ENTRY(props->filter), item->filter);
+	if (item->source) {
+		gchar* id = folder_item_get_identifier(item->source);
+		if (id) {
+			gtk_entry_set_text(GTK_ENTRY(props->source), id);
+			g_free(id);
+		}
+	}
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->frozen), item->frozen);
+/*	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->deep_copy), item->deep_copy);
+	switch (item->search) {
+		case SEARCH_BODY:
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->message_btn), TRUE);
+		case SEARCH_BOTH:
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->both_btn), TRUE);
+		case SEARCH_HEADERS:
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(props->label_btn), TRUE);
+	}*/
+}
+
+static gboolean is_source_widget(GtkWidget* widget) {
+	const gchar* name = gtk_widget_get_name(widget);
+
+	return (name && strcmp("source", name) == 0);
+}
+
+static void foldersel_cb(GtkWidget *widget, gpointer data) {
+	FolderItem *item;
+	gchar *item_id;
+	gint newpos = 0;
+	GtkWidget* entry = GTK_WIDGET(data);
+
+	item = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL, FALSE);
+	if (item && IS_VFOLDER_FOLDER_ITEM(item)) {
+		/* Cannot create virtual folder from virtual folder */
+		alertpanel_error(_("%s: Cannot create virtual folder from virtual folder"), item->name);
+		return;
+	}
+	else {
+		if (item && (item_id = folder_item_get_identifier(item)) != NULL) {
+			gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1);
+			gtk_editable_insert_text(GTK_EDITABLE(entry),
+						item_id, strlen(item_id), &newpos);
+			g_free(item_id);
+		}
+		debug_print("Source Folder: %s\n", gtk_entry_get_text(GTK_ENTRY(entry)));
+	}
+}
+
+static GtkWidget* vfolder_prop_row(GtkWidget* widget,
+								   const gchar* label_markup,
+								   gint width, gboolean center) {
+	GtkWidget* row = gtk_hbox_new(FALSE, 5);
+	GtkWidget* label = gtk_label_new(NULL);
+
+	gtk_widget_set_size_request(label, width, -1);
+	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), label_markup);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget);
+	gtk_box_pack_start(GTK_BOX(row), label, FALSE, FALSE, 5);
+	gtk_box_pack_start(GTK_BOX(row), widget, TRUE, FALSE, 5);
+
+	if (is_source_widget(widget)) {
+		GtkWidget* btn = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+		g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(foldersel_cb), widget);
+		gtk_box_pack_start(GTK_BOX(row), btn, FALSE, FALSE, 5);
+	}
+
+	return row;
+}
+
+static gboolean vfolder_set_search_type(VFolderItem* item, GtkWidget* list) {
+	GSList *btn_list, *btns;
+	gboolean active = FALSE;
+	GtkToggleButton* btn = NULL;
+
+	btn_list = gtk_radio_button_get_group(GTK_RADIO_BUTTON(list));
+	for (btns = btn_list; btns && !active; btns = g_slist_next(btns)) {
+		btn = GTK_TOGGLE_BUTTON(btns->data);
+		active = gtk_toggle_button_get_active(btn);
+	}
+	if (active) {
+		const gchar* label = gtk_button_get_label(GTK_BUTTON(btn));
+		if (label) {
+/*			if (strcmp(BOTH, label) == 0) {
+				if (item->search != SEARCH_BOTH) {
+					item->search = SEARCH_BOTH;
+					return TRUE;
+				}
+			}
+			else if (strcmp(BODY, label) == 0) {
+				if (item->search != SEARCH_BODY) {
+					item->search = SEARCH_BODY;
+					return TRUE;
+				}
+			}
+			else {
+				if (item->search != SEARCH_HEADERS) {
+					item->search = SEARCH_HEADERS;
+					return TRUE;
+				}
+			}*/
+		}
+	}
+
+	return FALSE;
+}
+/*
+static void vfolder_copy_msginfo_list(gpointer data, gpointer user_data) {
+	MsgInfo* msg = (MsgInfo *) data;
+	MsgInfo* new_msg;
+	VFolderItem* item = (VFolderItem *) user_data;
+
+	g_return_if_fail(msg != NULL);
+	g_return_if_fail(item != NULL);
+
+	new_msg = procmsg_msginfo_copy(msg);
+	item->msginfos = g_slist_prepend(item->msginfos, new_msg);
+}
+
+static gboolean vfolder_search_headers(MsgInfo* msg, GPatternSpec* pattern) {
+	return ((msg->cc && g_pattern_match_string(pattern, msg->cc)) ||
+			(msg->from && g_pattern_match_string(pattern, msg->from)) ||
+			(msg->fromname && g_pattern_match_string(pattern, msg->fromname)) ||
+			(msg->inreplyto && g_pattern_match_string(pattern, msg->inreplyto)) ||
+			(msg->subject && g_pattern_match_string(pattern, msg->subject)) ||
+			(msg->to && g_pattern_match_string(pattern, msg->to)));
+}
+
+static gboolean vfolder_search_body(MsgInfo* msg, GPatternSpec* pattern) {
+	gchar* body;
+	gboolean found = FALSE;
+
+	body = procmsg_get_message_file(msg);
+	if (body) {
+		found = g_pattern_match_string(pattern, body);
+		g_free(body);
+	}
+
+	return found;
+}
+*/
+static MsgInfoList* vfolder_filter_msgs_list(MsgInfoList* msgs, VFolderItem* item) {
+	MsgInfoList *list = NULL, *tmp;
+	GPatternSpec* pattern;
+	MsgInfo* msg;
+
+	if (!item || item->filter == NULL)
+		return list;
+
+	pattern = g_pattern_spec_new(item->filter);
+
+	for (tmp = msgs; tmp; tmp = g_slist_next(tmp)) {
+		msg = (MsgInfo *) tmp->data;
+/*		switch (item->search) {
+			case SEARCH_HEADERS:
+				if (vfolder_search_headers(msg, pattern))
+					list = g_slist_prepend(list, msg);
+				break;
+			case SEARCH_BODY:
+				if (vfolder_search_body(msg, pattern))
+					list = g_slist_prepend(list, msg);
+				break;
+			case SEARCH_BOTH:
+				if (vfolder_search_headers(msg, pattern)) {
+					list = g_slist_prepend(list, msg);
+					continue;
+				}
+				if (vfolder_search_body(msg, pattern))
+					list = g_slist_prepend(list, msg);
+				break;
+		}*/
+	}
+
+	g_pattern_spec_free(pattern);
+
+	return list;
+}
+
+static gboolean vfolder_create_msgs_list(VFolderItem* item, gboolean copy) {
+	MsgInfoList *msgs = NULL, *filtered = NULL;
+	gboolean ok = FALSE;
+	GSList* filelist = NULL;
+
+	if (item->filter && item->msg_filter_func) {
+//		item->deep_copy = copy;
+		ok = TRUE;
+		msgs = folder_item_get_msg_list(item->source);
+		filtered = item->msg_filter_func(msgs, item);
+		if (filtered) {
+			filelist = procmsg_get_message_file_list(filtered);
+			if (filelist) {
+				gint n = folder_item_add_msgs(FOLDER_ITEM(item), filelist, FALSE);
+				FOLDER_ITEM(item)->last_num = n;
+				procmsg_message_file_list_free(filelist);
+			}
+			g_slist_free(filtered);
+		}
+		g_slist_free(msgs);
+	}
+	return ok;
+}
+
+void vfolder_set_msgs_filter(VFolderItem* vfolder_item) {
+	g_return_if_fail(vfolder_item != NULL);
+
+	vfolder_item->msg_filter_func = vfolder_filter_msgs_list;
+}
+
+gboolean vfolder_create_item_dialog(FolderItem* folder_item) {
+	gboolean created = FALSE;
+	VFolderItem* item = NULL;
+
+	g_return_val_if_fail(folder_item != NULL, created);
+	g_return_val_if_fail(IS_VFOLDER_FOLDER_ITEM(folder_item), created);
+
+	item = VFOLDER_ITEM(folder_item);
+	item->msg_filter_func = vfolder_filter_msgs_list;
+
+	if (vfolder_edit_item_dialog(item)) {
+		/* save properties */
+		if (FOLDER_ITEM_PROPS_OK != vfolder_folder_item_props_write(item))
+			created = FALSE;
+		else
+			created = TRUE;
+	}
+
+	return created;
+}
+
+gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item) {
+	gboolean ok = FALSE;
+	PropsDialog* props_dialog;
+	GtkWidget* dialog;
+	GtkWidget* content;
+	GtkWidget* row;
+	GtkWidget* box;
+	gint response;
+	gchar* name;
+	const gchar* str;
+	gboolean frozen, deep_copy;
+	FolderItem* source;
+	gchar* old_filter = NULL;
+
+	g_return_val_if_fail(vfolder_item != NULL, ok);
+
+	MainWindow *mainwin = mainwindow_get_mainwindow();
+	props_dialog = g_new0(PropsDialog, 1);
+	props_dialog->filter = gtk_entry_new();
+	props_dialog->frozen = gtk_check_button_new();
+	props_dialog->deep_copy = gtk_check_button_new();
+	props_dialog->source = gtk_entry_new();
+	props_dialog->label_btn =
+		gtk_radio_button_new_with_mnemonic(NULL, HEADERS);
+	props_dialog->message_btn =
+		gtk_radio_button_new_with_mnemonic_from_widget(
+			GTK_RADIO_BUTTON(props_dialog->label_btn), BODY);
+	props_dialog->both_btn =
+		gtk_radio_button_new_with_mnemonic_from_widget(
+			GTK_RADIO_BUTTON(props_dialog->label_btn), BOTH);
+	gtk_widget_set_name(props_dialog->source, "source");
+	add_current_config(vfolder_item, props_dialog);
+
+	dialog = gtk_dialog_new_with_buttons(
+			N_("Edit VFolder Properties"),
+			GTK_WINDOW(mainwin->window),
+			GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+			NULL);
+	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_REJECT);
+	content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+	GtkWidget* vbox = gtk_vbox_new(FALSE, 5);
+
+	row = vfolder_prop_row(props_dialog->source, N_("_Source folder"), 110, FALSE);
+	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
+
+	GtkWidget* frame1 = gtk_frame_new(_("Message filter"));
+	GtkWidget* vbox1 = gtk_vbox_new(TRUE, 2);
+	gtk_container_add(GTK_CONTAINER(frame1), vbox1);
+
+	row = vfolder_prop_row(props_dialog->filter, N_("_Filter"), 110, FALSE);
+	gtk_box_pack_start(GTK_BOX(vbox1), row, FALSE, FALSE, 5);
+
+	box = gtk_hbox_new(TRUE, 2);
+	gtk_box_pack_start(GTK_BOX(box), props_dialog->label_btn, TRUE, TRUE, 2);
+	gtk_box_pack_start(GTK_BOX(box), props_dialog->message_btn, TRUE, TRUE, 2);
+	gtk_box_pack_start(GTK_BOX(box), props_dialog->both_btn, TRUE, TRUE, 2);
+	gtk_box_pack_start(GTK_BOX(vbox1), box, FALSE, FALSE, 5);
+
+	gtk_box_pack_start(GTK_BOX(vbox), frame1, FALSE, FALSE, 5);
+
+	row = vfolder_prop_row(props_dialog->frozen, N_("F_reeze content"), 110, TRUE);
+	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
+
+	row = vfolder_prop_row(props_dialog->deep_copy, N_("Co_py messages"), 110, TRUE);
+	gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 5);
+
+	name = g_strconcat(FOLDER_ITEM(vfolder_item)->name, N_(": settings"), NULL);
+	GtkWidget* frame = gtk_frame_new(name);
+	g_free(name);
+	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	gtk_widget_show_all(frame);
+
+	gtk_container_add(GTK_CONTAINER(content), frame);
+
+	response = gtk_dialog_run(GTK_DIALOG(dialog));
+	if (response == GTK_RESPONSE_ACCEPT) {
+		frozen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(props_dialog->frozen));
+		deep_copy = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(props_dialog->deep_copy));
+
+		str = gtk_entry_get_text(GTK_ENTRY(props_dialog->filter));
+		if (str) {
+			old_filter = g_strdup(vfolder_item->filter);
+			if (strlen(str) == 0) {
+				if (vfolder_item->filter) {
+					g_free(vfolder_item->filter);
+					vfolder_item->filter = NULL;
+					ok = TRUE;
+				}
+			}
+			else {
+				if (!vfolder_item->filter || strcmp(vfolder_item->filter, str) != 0) {
+					g_free(vfolder_item->filter);
+					vfolder_item->filter = g_strdup(str);
+					ok = TRUE;
+				}
+			}
+		}
+		if (vfolder_set_search_type(vfolder_item, props_dialog->label_btn))
+			ok = TRUE;
+
+		str = gtk_entry_get_text(GTK_ENTRY(props_dialog->source));
+		if (str) {
+			source = folder_find_item_from_identifier(str);
+			if (source && (source->stype != F_NORMAL && source->stype != F_INBOX)) {
+				alertpanel_error(_("%s: Not suitable for virtual folders\n"
+								   "Use only folder type: Normal or Inbox\n"), str);
+				g_free(vfolder_item->filter);
+				vfolder_item->filter = g_strdup(old_filter);
+				ok = FALSE;
+				goto error;
+			}
+
+			if (strlen(str) == 0) {
+				if (vfolder_item->source) {
+					vfolder_item->source = NULL;
+					folder_item_remove_all_msg(FOLDER_ITEM(vfolder_item));
+					ok = TRUE;
+				}
+			}
+			else {
+				folder_item_remove_all_msg(FOLDER_ITEM(vfolder_item));
+				gchar* id = (vfolder_item->source) ?
+					folder_item_get_identifier(vfolder_item->source) : NULL;
+				if (!id || strcmp(id, str) != 0)
+					vfolder_item->source = source;
+				if (vfolder_item->source) {
+					ok =  vfolder_create_msgs_list(vfolder_item, deep_copy);
+					if (ok == FALSE) {
+						g_free(vfolder_item->filter);
+						vfolder_item->filter = g_strdup(old_filter);
+						goto error;
+					}
+				}
+				else {
+					g_free(vfolder_item->filter);
+					vfolder_item->filter = g_strdup(old_filter);
+					ok = FALSE;
+					goto error;
+				}
+			}
+		}
+
+		if (vfolder_item->frozen != frozen) {
+			vfolder_item->frozen = frozen;
+			ok = TRUE;
+		}
+
+/*		if (vfolder_item->deep_copy != deep_copy) {
+			vfolder_item->deep_copy = deep_copy;
+			ok = TRUE;
+		}*/
+
+	}
+
+error:
+	gtk_widget_destroy(dialog);
+	g_free(props_dialog);
+	g_free(old_filter);
+
+	return ok;
+}
diff --git a/src/plugins/vfolder/vfolder_prop.h b/src/plugins/vfolder/vfolder_prop.h
new file mode 100644
index 0000000..04fb493
--- /dev/null
+++ b/src/plugins/vfolder/vfolder_prop.h
@@ -0,0 +1,43 @@
+/*
+ * $Id: $
+ */
+
+/* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
+
+/*
+ * Virtual folder plugin for claws-mail
+ * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VFOLDER_PROP_H__
+#define __VFOLDER_PROP_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#include "folder.h"
+#include "vfolder.h"
+#include <gtk/gtk.h>
+
+gboolean vfolder_create_item_dialog(FolderItem* folder_item);
+gboolean vfolder_edit_item_dialog(VFolderItem* vfolder_item);
+void vfolder_set_msgs_filter(VFolderItem* vfolder_item);
+
+G_END_DECLS
+
+#endif

commit e1f0f7f3918e1c778199165a971eb2863c86ad70
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sun Jun 8 18:50:28 2014 +0200

    Prepare vfolder

diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 6912a84..5576571 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -31,4 +31,5 @@ SUBDIRS = \
 	spamassassin \
 	spam_report \
 	tnef_parse \
-	vcalendar
+	vcalendar \
+	vfolder

commit a6c14cf0bed0460dadf246bcf6d72e5c6ff32eee
Author: Michael Rasmussen <mir at datanom.net>
Date:   Sun Jun 8 18:21:35 2014 +0200

    Prepare for vfolder plugin

diff --git a/configure.ac b/configure.ac
index 771a313..2e8ee4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1029,6 +1029,10 @@ AC_ARG_ENABLE(vcalendar-plugin,
 		[  --disable-vcalendar-plugin      Do not build vcalendar plugin],
 		[enable_vcalendar_plugin=$enableval], [enable_vcalendar_plugin=auto])
 
+AC_ARG_ENABLE(vfolder-plugin,
+		[  --disable-vfolder-plugin      Do not build vfolder plugin],
+		[enable_vfolder_plugin=$enableval], [enable_vfolder_plugin=auto])
+
 dnl disabled by default
 AC_ARG_ENABLE(demo-plugin,
 		[  --enable-demo-plugin		Build demo plugin],
@@ -1058,6 +1062,7 @@ dnl Python:		Python
 dnl RSSyl:		libxml2 libcurl
 dnl SpamReport:		libcurl
 dnl vCalendar:		libcurl
+dnl VFolder:		none
 
 dnl libcurl ********************************************************************
 PKG_CHECK_MODULES(CURL, libcurl, HAVE_CURL=yes, HAVE_CURL=no)
@@ -1158,9 +1163,9 @@ if test x"$HAVE_PERL" = xyes; then
 	PERL_LDFLAGS=`echo $PERL_LDFLAGS |sed 's/-lc//'`
 	AC_MSG_RESULT(ok)
 	AC_MSG_NOTICE([Adding perl LIBS ${PERL_CFLAGS}])
-	
+
 	if test x"$HAVE_PERL" = xyes; then
-		AC_CHECK_LIB(perl,perl_alloc,[AC_DEFINE(HAVE_LIBPERL, 1, Check for libperl.)], 
+		AC_CHECK_LIB(perl,perl_alloc,[AC_DEFINE(HAVE_LIBPERL, 1, Check for libperl.)],
 			 		     [ HAVE_LIBPERL=no ])
 	fi
 	if test x"$HAVE_LIBPERL" = xno; then
@@ -1172,7 +1177,7 @@ if test x"$HAVE_PERL" = xyes; then
 			HAVE_LIBPERL=yes
 		else
 			AC_MSG_RESULT(no)
-		fi	
+		fi
 	fi
 	PERL="perl"
 	AC_SUBST(PERL)
@@ -1817,32 +1822,24 @@ else
 	AC_MSG_RESULT(no)
 fi
 
-AC_MSG_CHECKING([whether to build vcalendar plugin])
-if test x"$enable_vcalendar_plugin" != xno; then
+AC_MSG_CHECKING([whether to build vfolder plugin])
+if test x"$enable_vfolder_plugin" != xno; then
 	dependencies_missing=""
 
-	if test x"$HAVE_CURL" = xno; then
-		dependencies_missing="libcurl $dependencies_missing"
-	fi
-
-	if test x"$HAVE_PERL" = xno; then
-		dependencies_missing="perl $dependencies_missing"
-	fi
-
 	if test x"$dependencies_missing" = x; then
-		PLUGINS="$PLUGINS vcalendar"
+		PLUGINS="$PLUGINS vfolder"
 		AC_MSG_RESULT(yes)
-	elif test x"$enable_vcalendar_plugin" = xauto; then
+	elif test x"$enable_vfolder_plugin" = xauto; then
 		AC_MSG_RESULT(no)
-		AC_MSG_WARN("Plugin vcalendar will not be built; missing $dependencies_missing")
-		enable_vcalendar_plugin=no
-		MISSING_DEPS_PLUGINS="$MISSING_DEPS_PLUGINS vcalendar"
+		AC_MSG_WARN("Plugin vfolder will not be built; missing $dependencies_missing")
+		enable_vfolder_plugin=no
+		MISSING_DEPS_PLUGINS="$MISSING_DEPS_PLUGINS vfolder"
 	else
 		AC_MSG_RESULT(no)
-		AC_MSG_ERROR("Plugin vcalendar cannot be built; missing $dependencies_missing")
+		AC_MSG_ERROR("Plugin vfolder cannot be built; missing $dependencies_missing")
 	fi
 else
-	DISABLED_PLUGINS="$DISABLED_PLUGINS vcalendar"
+	DISABLED_PLUGINS="$DISABLED_PLUGINS vfolder"
 	AC_MSG_RESULT(no)
 fi
 
@@ -1878,6 +1875,7 @@ AM_CONDITIONAL(BUILD_SPAMASSASSIN_PLUGIN,	test x"$enable_spamassassin_plugin" !=
 AM_CONDITIONAL(BUILD_SPAM_REPORT_PLUGIN,	test x"$enable_spam_report_plugin" != xno)
 AM_CONDITIONAL(BUILD_TNEF_PARSE_PLUGIN,		test x"$enable_tnef_parse_plugin" != xno)
 AM_CONDITIONAL(BUILD_VCALENDAR_PLUGIN,		test x"$enable_vcalendar_plugin" != xno)
+AM_CONDITIONAL(BUILD_VFOLDER_PLUGIN,		test x"$enable_vfolder_plugin" != xno)
 
 
 dnl ****************************
@@ -1933,6 +1931,7 @@ src/plugins/vcalendar/libical/libical/icalversion.h
 src/plugins/vcalendar/libical/libical/Makefile
 src/plugins/vcalendar/libical/design-data/Makefile
 src/plugins/vcalendar/libical/scripts/Makefile
+src/plugins/vfolder/Makefile
 doc/Makefile
 doc/man/Makefile
 tools/Makefile

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list