aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-07-01 10:42:15 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-07-01 10:42:15 +0000
commit0ada6c15f7eef4e46d8f1b8964dad1193692a10a (patch)
treee767d7b49be640a123d3bf49ae751fa2af7ba441 /src
parent0839e124a6910f5d134ec3b229466cd470b0c7ea (diff)
implemented folder move.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@389 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src')
-rw-r--r--src/folder.c8
-rw-r--r--src/folder.h3
-rw-r--r--src/foldersel.c32
-rw-r--r--src/foldersel.h5
-rw-r--r--src/folderview.c112
-rw-r--r--src/folderview.h1
-rw-r--r--src/imap.c1
-rw-r--r--src/mainwindow.c25
-rw-r--r--src/mh.c82
-rw-r--r--src/news.c1
10 files changed, 238 insertions, 32 deletions
diff --git a/src/folder.c b/src/folder.c
index 00c43c6a..c4645fe3 100644
--- a/src/folder.c
+++ b/src/folder.c
@@ -659,7 +659,13 @@ gchar *folder_item_get_identifier(FolderItem *item)
gchar *folder_id;
g_return_val_if_fail(item != NULL, NULL);
- g_return_val_if_fail(item->path != NULL, NULL);
+
+ if (!item->path) {
+ if (!item->parent)
+ return folder_get_identifier(item->folder);
+ else
+ return NULL;
+ }
folder_id = folder_get_identifier(item->folder);
id = g_strconcat(folder_id, "/", item->path, NULL);
diff --git a/src/folder.h b/src/folder.h
index 0d241a13..0908e241 100644
--- a/src/folder.h
+++ b/src/folder.h
@@ -200,6 +200,9 @@ struct _FolderClass
gint (*rename_folder) (Folder *folder,
FolderItem *item,
const gchar *name);
+ gint (*move_folder) (Folder *folder,
+ FolderItem *item,
+ FolderItem *new_parent);
gint (*remove_folder) (Folder *folder,
FolderItem *item);
};
diff --git a/src/foldersel.c b/src/foldersel.c
index 89f43cf1..0f93bb58 100644
--- a/src/foldersel.c
+++ b/src/foldersel.c
@@ -84,10 +84,12 @@ static GtkWidget *ok_button;
static GtkWidget *cancel_button;
static GtkWidget *new_button;
+static GtkTreeStore *tree_store;
+
static FolderItem *folder_item;
static FolderItem *selected_item;
-static GtkTreeStore *tree_store;
+FolderSelectionType sel_type;
static gboolean cancelled;
static gboolean finished;
@@ -100,8 +102,7 @@ static void foldersel_append_item (GtkTreeStore *store,
GtkTreeIter *iter,
GtkTreeIter *parent);
-static void foldersel_set_tree (Folder *cur_folder,
- FolderSelectionType type);
+static void foldersel_set_tree (Folder *cur_folder);
static gboolean foldersel_selected (GtkTreeSelection *selection,
GtkTreeModel *model,
@@ -145,13 +146,14 @@ FolderItem *foldersel_folder_sel(Folder *cur_folder, FolderSelectionType type,
const gchar *default_folder)
{
selected_item = NULL;
+ sel_type = type;
if (!window) {
foldersel_create();
foldersel_init();
}
- foldersel_set_tree(cur_folder, type);
+ foldersel_set_tree(cur_folder);
/* select current */
if (folder_item) {
@@ -199,12 +201,16 @@ FolderItem *foldersel_folder_sel(Folder *cur_folder, FolderSelectionType type,
gtk_entry_set_text(GTK_ENTRY(entry), "");
gtk_tree_store_clear(tree_store);
- if (!cancelled &&
- selected_item && selected_item->path && !selected_item->no_select) {
+ if (cancelled || !selected_item)
+ return NULL;
+
+ if (type == FOLDER_SEL_MOVE_FOLDER ||
+ (selected_item->path && !selected_item->no_select)) {
folder_item = selected_item;
return folder_item;
- } else
- return NULL;
+ }
+
+ return NULL;
}
static void foldersel_create(void)
@@ -410,7 +416,7 @@ static void foldersel_insert_gnode_in_store(GtkTreeStore *store, GNode *node,
foldersel_insert_gnode_in_store(store, iter, &child);
}
-static void foldersel_set_tree(Folder *cur_folder, FolderSelectionType type)
+static void foldersel_set_tree(Folder *cur_folder)
{
Folder *folder;
GList *list;
@@ -419,10 +425,12 @@ static void foldersel_set_tree(Folder *cur_folder, FolderSelectionType type)
folder = FOLDER(list->data);
g_return_if_fail(folder != NULL);
- if (type != FOLDER_SEL_ALL) {
+ if (sel_type != FOLDER_SEL_ALL) {
if (FOLDER_TYPE(folder) == F_NEWS)
continue;
}
+ if (sel_type == FOLDER_SEL_MOVE_FOLDER && folder != cur_folder)
+ continue;
foldersel_insert_gnode_in_store(tree_store, folder->node, NULL);
}
@@ -451,7 +459,9 @@ static gboolean foldersel_selected(GtkTreeSelection *selection,
FOLDERSEL_FOLDERITEM, &item, -1);
selected_item = item;
- if (selected_item && selected_item->path && !selected_item->no_select) {
+ if (selected_item &&
+ (sel_type == FOLDER_SEL_MOVE_FOLDER ||
+ (selected_item->path && !selected_item->no_select))) {
gchar *id;
id = folder_item_get_identifier(selected_item);
gtk_entry_set_text(GTK_ENTRY(entry), id);
diff --git a/src/foldersel.h b/src/foldersel.h
index 802bb50e..e1b065b2 100644
--- a/src/foldersel.h
+++ b/src/foldersel.h
@@ -1,6 +1,6 @@
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
*
* 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
@@ -29,7 +29,8 @@ typedef enum
{
FOLDER_SEL_ALL,
FOLDER_SEL_MOVE,
- FOLDER_SEL_COPY
+ FOLDER_SEL_COPY,
+ FOLDER_SEL_MOVE_FOLDER
} FolderSelectionType;
FolderItem *foldersel_folder_sel(Folder *cur_folder,
diff --git a/src/folderview.c b/src/folderview.c
index 27020fae..2cbd85e2 100644
--- a/src/folderview.c
+++ b/src/folderview.c
@@ -48,6 +48,7 @@
#include "summary_search.h"
#include "inputdialog.h"
#include "grouplistdialog.h"
+#include "foldersel.h"
#include "manage_window.h"
#include "alertpanel.h"
#include "menu.h"
@@ -165,6 +166,9 @@ static void folderview_new_folder_cb (FolderView *folderview,
static void folderview_rename_folder_cb (FolderView *folderview,
guint action,
GtkWidget *widget);
+static void folderview_move_folder_cb (FolderView *folderview,
+ guint action,
+ GtkWidget *widget);
static void folderview_delete_folder_cb (FolderView *folderview,
guint action,
GtkWidget *widget);
@@ -223,8 +227,9 @@ GtkTargetEntry folderview_drag_types[] =
static GtkItemFactoryEntry folderview_mail_popup_entries[] =
{
- {N_("/Create _new folder..."), NULL, folderview_new_folder_cb, 0, NULL},
+ {N_("/Create _new folder..."), NULL, folderview_new_folder_cb, 0, NULL},
{N_("/_Rename folder..."), NULL, folderview_rename_folder_cb, 0, NULL},
+ {N_("/_Move folder..."), NULL, folderview_move_folder_cb, 0, NULL},
{N_("/_Delete folder"), NULL, folderview_delete_folder_cb, 0, NULL},
{N_("/---"), NULL, NULL, 0, "<Separator>"},
{N_("/Empty _trash"), NULL, folderview_empty_trash_cb, 0, NULL},
@@ -1252,32 +1257,37 @@ void folderview_update_all_updated(gboolean update_summary)
}
}
-static void folderview_insert_item_recursive(FolderView *folderview,
- FolderItem *item)
+static gboolean folderview_insert_item_recursive(FolderView *folderview,
+ FolderItem *item,
+ GtkTreeIter *iter)
{
GNode *node;
- GtkTreeIter iter;
+ GtkTreeIter iter_;
gboolean valid;
- g_return_if_fail(item != NULL);
+ g_return_val_if_fail(item != NULL, FALSE);
- valid = folderview_append_item(folderview, &iter, item, FALSE);
- g_return_if_fail(valid == TRUE);
+ valid = folderview_append_item(folderview, &iter_, item, FALSE);
+ g_return_val_if_fail(valid == TRUE, FALSE);
for (node = item->node->children; node != NULL; node = node->next) {
FolderItem *child_item = FOLDER_ITEM(node->data);
- folderview_insert_item_recursive(folderview, child_item);
+ folderview_insert_item_recursive(folderview, child_item, NULL);
}
if (item->node->children && !item->collapsed) {
GtkTreePath *path;
path = gtk_tree_model_get_path
- (GTK_TREE_MODEL(folderview->store), &iter);
+ (GTK_TREE_MODEL(folderview->store), &iter_);
gtk_tree_view_expand_row(GTK_TREE_VIEW(folderview->treeview),
path, FALSE);
gtk_tree_path_free(path);
}
+
+ if (iter)
+ *iter = iter_;
+ return TRUE;
}
static void folderview_append_folder(FolderView *folderview, Folder *folder)
@@ -1285,7 +1295,7 @@ static void folderview_append_folder(FolderView *folderview, Folder *folder)
g_return_if_fail(folder != NULL);
folderview_insert_item_recursive
- (folderview, FOLDER_ITEM(folder->node->data));
+ (folderview, FOLDER_ITEM(folder->node->data), NULL);
}
void folderview_new_folder(FolderView *folderview)
@@ -1321,6 +1331,23 @@ void folderview_rename_folder(FolderView *folderview)
folderview_rename_folder_cb(folderview, 0, NULL);
}
+void folderview_move_folder(FolderView *folderview)
+{
+ FolderItem *item;
+
+ item = folderview_get_selected_item(folderview);
+ if (!item)
+ return;
+
+ g_return_if_fail(item->folder != NULL);
+
+ if (!item->path) return;
+ if (item->stype != F_NORMAL) return;
+
+ if (item->folder->klass->move_folder)
+ folderview_move_folder_cb(folderview, 0, NULL);
+}
+
void folderview_delete_folder(FolderView *folderview)
{
FolderItem *item;
@@ -1406,6 +1433,7 @@ static gboolean folderview_menu_popup(FolderView *folderview,
GtkTreeIter iter;
gboolean new_folder = FALSE;
gboolean rename_folder = FALSE;
+ gboolean move_folder = FALSE;
gboolean delete_folder = FALSE;
gboolean empty_trash = FALSE;
gboolean download_msg = FALSE;
@@ -1444,9 +1472,11 @@ static gboolean folderview_menu_popup(FolderView *folderview,
if (FOLDER_IS_LOCAL(folder) || FOLDER_TYPE(folder) == F_IMAP) {
if (item->parent == NULL)
update_tree = rescan_tree = TRUE;
- else if (item->stype == F_NORMAL)
+ else if (item->stype == F_NORMAL) {
rename_folder = delete_folder = TRUE;
- else if (item->stype == F_TRASH)
+ if (folder->klass->move_folder)
+ move_folder = TRUE;
+ } else if (item->stype == F_TRASH)
empty_trash = TRUE;
} else if (FOLDER_TYPE(folder) == F_NEWS) {
if (item->parent != NULL)
@@ -1467,6 +1497,7 @@ static gboolean folderview_menu_popup(FolderView *folderview,
menu_set_insensitive_all(GTK_MENU_SHELL(popup));
SET_SENS(mail_factory, "/Create new folder...", new_folder);
SET_SENS(mail_factory, "/Rename folder...", rename_folder);
+ SET_SENS(mail_factory, "/Move folder...", move_folder);
SET_SENS(mail_factory, "/Delete folder", delete_folder);
SET_SENS(mail_factory, "/Empty trash", empty_trash);
SET_SENS(mail_factory, "/Check for new messages", update_tree);
@@ -1994,6 +2025,63 @@ static void folderview_rename_folder_cb(FolderView *folderview, guint action,
folder_write_list();
}
+static void folderview_move_folder_cb(FolderView *folderview, guint action,
+ GtkWidget *widget)
+{
+ FolderItem *item;
+ FolderItem *new_parent;
+ GtkTreePath *sel_path;
+ GtkTreePath *open_path;
+ GtkTreeIter iter;
+
+ item = folderview_get_selected_item(folderview);
+ if (!item)
+ return;
+
+ g_return_if_fail(item->path != NULL);
+ g_return_if_fail(item->folder != NULL);
+
+ new_parent = foldersel_folder_sel(item->folder, FOLDER_SEL_MOVE_FOLDER,
+ NULL);
+ if (!new_parent)
+ return;
+ if (new_parent->folder != item->folder)
+ return;
+ if (new_parent == item->parent)
+ return;
+
+ if (item->folder->klass->move_folder
+ (item->folder, item, new_parent) < 0) {
+ alertpanel_error(_("Can't move the folder `%s'."), item->name);
+ return;
+ }
+
+ /* rename filter paths */
+
+ sel_path = gtk_tree_row_reference_get_path(folderview->selected);
+ open_path = gtk_tree_row_reference_get_path(folderview->opened);
+ g_return_if_fail(sel_path != NULL);
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(folderview->store), &iter,
+ sel_path);
+ if (sel_path && open_path &&
+ (gtk_tree_path_compare(open_path, sel_path) == 0 ||
+ gtk_tree_path_is_ancestor(sel_path, open_path))) {
+ summary_clear_all(folderview->summaryview);
+ gtk_tree_row_reference_free(folderview->opened);
+ folderview->opened = NULL;
+ }
+ gtk_tree_path_free(open_path);
+ gtk_tree_path_free(sel_path);
+
+ gtk_tree_store_remove(folderview->store, &iter);
+ if (folderview_insert_item_recursive(folderview, item, &iter)) {
+ gtkut_tree_view_expand_parent_all
+ (GTK_TREE_VIEW(folderview->treeview), &iter);
+ }
+
+ folder_write_list();
+}
+
static void folderview_delete_folder_cb(FolderView *folderview, guint action,
GtkWidget *widget)
{
diff --git a/src/folderview.h b/src/folderview.h
index 352ea6c7..5fb251f2 100644
--- a/src/folderview.h
+++ b/src/folderview.h
@@ -100,6 +100,7 @@ void folderview_update_all_updated (gboolean update_summary);
void folderview_new_folder (FolderView *folderview);
void folderview_rename_folder (FolderView *folderview);
+void folderview_move_folder (FolderView *folderview);
void folderview_delete_folder (FolderView *folderview);
void folderview_check_new_selected (FolderView *folderview);
diff --git a/src/imap.c b/src/imap.c
index 423c40b0..bf523e62 100644
--- a/src/imap.c
+++ b/src/imap.c
@@ -391,6 +391,7 @@ static FolderClass imap_class =
imap_create_folder,
imap_rename_folder,
+ NULL,
imap_remove_folder
};
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 3af7d2dc..98180364 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -194,6 +194,9 @@ static void new_folder_cb (MainWindow *mainwin,
static void rename_folder_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
+static void move_folder_cb (MainWindow *mainwin,
+ guint action,
+ GtkWidget *widget);
static void delete_folder_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
@@ -469,6 +472,7 @@ static GtkItemFactoryEntry mainwin_entries[] =
{N_("/_File/_Folder/Create _new folder..."),
NULL, new_folder_cb, 0, NULL},
{N_("/_File/_Folder/_Rename folder..."),NULL, rename_folder_cb, 0, NULL},
+ {N_("/_File/_Folder/_Move folder..."), NULL, move_folder_cb, 0, NULL},
{N_("/_File/_Folder/_Delete folder"), NULL, delete_folder_cb, 0, NULL},
{N_("/_File/_Mailbox"), NULL, NULL, 0, "<Branch>"},
{N_("/_File/_Mailbox/Add _mailbox..."), NULL, add_mailbox_cb, 0, NULL},
@@ -1622,12 +1626,13 @@ typedef enum
M_FOLDER_NEWOK = 1 << 17,
M_FOLDER_RENOK = 1 << 18,
- M_FOLDER_DELOK = 1 << 19,
- M_MBOX_ADDOK = 1 << 20,
- M_MBOX_RMOK = 1 << 21,
- M_MBOX_CHKOK = 1 << 22,
- M_MBOX_CHKALLOK = 1 << 23,
- M_MBOX_REBUILDOK = 1 << 24
+ M_FOLDER_MOVEOK = 1 << 19,
+ M_FOLDER_DELOK = 1 << 20,
+ M_MBOX_ADDOK = 1 << 21,
+ M_MBOX_RMOK = 1 << 22,
+ M_MBOX_CHKOK = 1 << 23,
+ M_MBOX_CHKALLOK = 1 << 24,
+ M_MBOX_REBUILDOK = 1 << 25
} SensitiveCond;
static SensitiveCond main_window_get_current_state(MainWindow *mainwin)
@@ -1684,6 +1689,8 @@ static SensitiveCond main_window_get_current_state(MainWindow *mainwin)
else if (item->stype == F_NORMAL) {
state |= M_FOLDER_RENOK;
state |= M_FOLDER_DELOK;
+ if (item->folder->klass->move_folder)
+ state |= M_FOLDER_MOVEOK;
}
} else if (FOLDER_TYPE(item->folder) == F_NEWS) {
if (item->parent != NULL)
@@ -1766,6 +1773,7 @@ void main_window_set_menu_sensitive(MainWindow *mainwin)
} entry[] = {
{"/File/Folder/Create new folder...", M_UNLOCKED|M_FOLDER_NEWOK},
{"/File/Folder/Rename folder..." , M_UNLOCKED|M_FOLDER_RENOK},
+ {"/File/Folder/Move folder..." , M_UNLOCKED|M_FOLDER_MOVEOK},
{"/File/Folder/Delete folder" , M_UNLOCKED|M_FOLDER_DELOK},
{"/File/Mailbox/Add mailbox..." , M_UNLOCKED|M_MBOX_ADDOK},
{"/File/Mailbox/Remove mailbox" , M_UNLOCKED|M_MBOX_RMOK},
@@ -2638,6 +2646,11 @@ static void rename_folder_cb(MainWindow *mainwin, guint action,
folderview_rename_folder(mainwin->folderview);
}
+static void move_folder_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
+{
+ folderview_move_folder(mainwin->folderview);
+}
+
static void delete_folder_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
diff --git a/src/mh.c b/src/mh.c
index 843802b2..eb7af852 100644
--- a/src/mh.c
+++ b/src/mh.c
@@ -108,6 +108,9 @@ static FolderItem *mh_create_folder (Folder *folder,
static gint mh_rename_folder (Folder *folder,
FolderItem *item,
const gchar *name);
+static gint mh_move_folder (Folder *folder,
+ FolderItem *item,
+ FolderItem *new_parent);
static gint mh_remove_folder (Folder *folder,
FolderItem *item);
@@ -156,6 +159,7 @@ static FolderClass mh_class =
mh_create_folder,
mh_rename_folder,
+ mh_move_folder,
mh_remove_folder,
};
@@ -931,6 +935,84 @@ static gint mh_rename_folder(Folder *folder, FolderItem *item,
g_free(paths[0]);
g_free(paths[1]);
+
+ return 0;
+}
+
+static gint mh_move_folder(Folder *folder, FolderItem *item,
+ FolderItem *new_parent)
+{
+ gchar *oldpath;
+ gchar *newpath;
+ gchar *new_dir;
+ gchar *name;
+ gchar *utf8_name;
+ gchar *paths[2];
+
+ g_return_val_if_fail(folder != NULL, -1);
+ g_return_val_if_fail(item != NULL, -1);
+ g_return_val_if_fail(item->path != NULL, -1);
+ g_return_val_if_fail(new_parent != NULL, -1);
+ g_return_val_if_fail(item != new_parent, -1);
+ g_return_val_if_fail(item->parent != new_parent, -1);
+ g_return_val_if_fail(folder == item->folder, -1);
+ g_return_val_if_fail(item->folder == new_parent->folder, -1);
+
+ if (g_node_is_ancestor(item->node, new_parent->node)) {
+ g_warning("folder to be moved is ancestor of new parent\n");
+ return -1;
+ }
+
+ oldpath = folder_item_get_path(item);
+ name = g_path_get_basename(oldpath);
+ utf8_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
+ if (!utf8_name)
+ utf8_name = g_strdup(name);
+ new_dir = folder_item_get_path(new_parent);
+ newpath = g_strconcat(new_dir, G_DIR_SEPARATOR_S, name, NULL);
+ g_free(new_dir);
+
+ if (is_file_entry_exist(newpath)) {
+ g_warning("%s already exists\n", newpath);
+ g_free(oldpath);
+ g_free(newpath);
+ g_free(utf8_name);
+ return -1;
+ }
+
+ debug_print("mh_move_folder: rename(%s, %s)\n", oldpath, newpath);
+ g_free(name);
+
+ if (rename(oldpath, newpath) < 0) {
+ FILE_OP_ERROR(oldpath, "rename");
+ g_free(oldpath);
+ g_free(newpath);
+ g_free(utf8_name);
+ return -1;
+ }
+
+ g_free(oldpath);
+ g_free(newpath);
+
+ g_node_unlink(item->node);
+ g_node_append(new_parent->node, item->node);
+ item->parent = new_parent;
+
+ if (new_parent->path != NULL) {
+ newpath = g_strconcat(new_parent->path, G_DIR_SEPARATOR_S,
+ utf8_name, NULL);
+ g_free(utf8_name);
+ } else
+ newpath = utf8_name;
+
+ paths[0] = g_strdup(item->path);
+ paths[1] = newpath;
+ g_node_traverse(item->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+ mh_rename_folder_func, paths);
+
+ g_free(paths[0]);
+ g_free(paths[1]);
+
return 0;
}
diff --git a/src/news.c b/src/news.c
index 5c6e1911..02891c64 100644
--- a/src/news.c
+++ b/src/news.c
@@ -153,6 +153,7 @@ static FolderClass news_class =
NULL,
NULL,
+ NULL,
NULL
};