summaryrefslogtreecommitdiff
path: root/src/foldersel.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-26 11:23:00 +0100
committerSimeon Simeonov2018-02-26 11:23:00 +0100
commit0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch)
treeaf916a30553c78ce9d4f2d8658656a175c5b6921 /src/foldersel.c
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/foldersel.c')
-rw-r--r--src/foldersel.c765
1 files changed, 765 insertions, 0 deletions
diff --git a/src/foldersel.c b/src/foldersel.c
new file mode 100644
index 0000000..cc5076d
--- /dev/null
+++ b/src/foldersel.c
@@ -0,0 +1,765 @@
1/*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2014 Hiroyuki Yamamoto
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include "defs.h"
21
22#include <glib.h>
23#include <glib/gi18n.h>
24#include <gdk/gdkkeysyms.h>
25#include <gtk/gtkmain.h>
26#include <gtk/gtkwidget.h>
27#include <gtk/gtktreestore.h>
28#include <gtk/gtktreeview.h>
29#include <gtk/gtktreeselection.h>
30#include <gtk/gtkcellrendererpixbuf.h>
31#include <gtk/gtkcellrenderertext.h>
32#include <gtk/gtkwindow.h>
33#include <gtk/gtkvbox.h>
34#include <gtk/gtkscrolledwindow.h>
35#include <gtk/gtklabel.h>
36#include <gtk/gtkentry.h>
37#include <gtk/gtkhbbox.h>
38#include <gtk/gtksignal.h>
39#include <gtk/gtkstock.h>
40#include <stdio.h>
41#include <unistd.h>
42#include <string.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <fcntl.h>
46#include <errno.h>
47
48#include "main.h"
49#include "utils.h"
50#include "gtkutils.h"
51#include "stock_pixmap.h"
52#include "foldersel.h"
53#include "alertpanel.h"
54#include "manage_window.h"
55#include "folderview.h"
56#include "inputdialog.h"
57#include "folder.h"
58#include "prefs_common.h"
59
60enum {
61 FOLDERSEL_FOLDERNAME,
62 FOLDERSEL_FOLDERITEM,
63 FOLDERSEL_PIXBUF,
64 FOLDERSEL_PIXBUF_OPEN,
65 FOLDERSEL_FOREGROUND,
66 FOLDERSEL_BOLD,
67 N_FOLDERSEL_COLUMNS
68};
69
70typedef struct _FolderItemSearch FolderItemSearch;
71
72struct _FolderItemSearch
73{
74 FolderItem *item;
75 GtkTreePath *path;
76 GtkTreeIter iter;
77};
78
79static GdkPixbuf *folder_pixbuf;
80static GdkPixbuf *folderopen_pixbuf;
81static GdkPixbuf *foldernoselect_pixbuf;
82
83static GtkWidget *window;
84static GtkWidget *label;
85static GtkWidget *scrolledwin;
86static GtkWidget *treeview;
87static GtkWidget *entry;
88static GtkWidget *confirm_area;
89static GtkWidget *ok_button;
90static GtkWidget *cancel_button;
91static GtkWidget *new_button;
92
93static GtkTreeStore *tree_store;
94
95static FolderItem *folder_item;
96static FolderItem *selected_item;
97
98FolderSelectionType sel_type;
99
100static gboolean cancelled;
101static gboolean finished;
102
103static void foldersel_create (void);
104static void foldersel_init (void);
105
106static void foldersel_append_item (GtkTreeStore *store,
107 FolderItem *item,
108 GtkTreeIter *iter,
109 GtkTreeIter *parent);
110
111static void foldersel_set_tree (Folder *cur_folder);
112
113static gboolean foldersel_selected (GtkTreeSelection *selection,
114 GtkTreeModel *model,
115 GtkTreePath *path,
116 gboolean currently_selected,
117 gpointer data);
118
119static void foldersel_ok (GtkButton *button,
120 gpointer data);
121static void foldersel_cancel (GtkButton *button,
122 gpointer data);
123static void foldersel_new_folder (GtkButton *button,
124 gpointer data);
125
126static void foldersel_entry_activated (GtkEntry *entry,
127 gpointer data);
128
129static void foldersel_tree_activated (GtkTreeView *treeview,
130 GtkTreePath *path,
131 GtkTreeViewColumn *column,
132 gpointer data);
133
134static gboolean foldersel_tree_key_pressed (GtkWidget *widget,
135 GdkEventKey *event,
136 gpointer data);
137
138static gint delete_event (GtkWidget *widget,
139 GdkEventAny *event,
140 gpointer data);
141static gboolean key_pressed (GtkWidget *widget,
142 GdkEventKey *event,
143 gpointer data);
144
145static gint foldersel_folder_name_compare (GtkTreeModel *model,
146 GtkTreeIter *a,
147 GtkTreeIter *b,
148 gpointer context);
149
150static gboolean tree_view_folder_item_func (GtkTreeModel *model,
151 GtkTreePath *path,
152 GtkTreeIter *iter,
153 FolderItemSearch *data);
154
155FolderItem *foldersel_folder_sel(Folder *cur_folder, FolderSelectionType type,
156 const gchar *default_folder)
157{
158 return foldersel_folder_sel_full(cur_folder, type, default_folder,
159 NULL);
160}
161
162FolderItem *foldersel_folder_sel_full(Folder *cur_folder,
163 FolderSelectionType type,
164 const gchar *default_folder,
165 const gchar *message)
166{
167 selected_item = NULL;
168 sel_type = type;
169
170 if (!window) {
171 foldersel_create();
172 foldersel_init();
173 }
174
175 if (message) {
176 gtk_widget_show(label);
177 gtk_label_set_text(GTK_LABEL(label), message);
178 } else
179 gtk_widget_hide(label);
180
181 foldersel_set_tree(cur_folder);
182
183 /* select current */
184 if (folder_item) {
185 FolderItemSearch fis;
186
187 fis.item = folder_item;
188 fis.path = NULL;
189
190 /* find matching model entry */
191 gtk_tree_model_foreach
192 (GTK_TREE_MODEL(tree_store),
193 (GtkTreeModelForeachFunc)tree_view_folder_item_func,
194 &fis);
195
196 if (fis.path) {
197 GtkTreeSelection *selection;
198
199 selection = gtk_tree_view_get_selection
200 (GTK_TREE_VIEW(treeview));
201 gtkut_tree_view_expand_parent_all
202 (GTK_TREE_VIEW(treeview), &fis.iter);
203 gtk_tree_selection_select_iter(selection, &fis.iter);
204 gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview),
205 fis.path, NULL, FALSE);
206 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeview),
207 fis.path,
208 NULL, TRUE, 0.5, 0.0);
209 gtk_tree_path_free(fis.path);
210 } else
211 gtk_tree_view_scroll_to_point
212 (GTK_TREE_VIEW(treeview), 0, 0);
213 } else
214 gtk_tree_view_scroll_to_point(GTK_TREE_VIEW(treeview), 0, 0);
215
216 gtkut_box_set_reverse_order(GTK_BOX(confirm_area),
217 !prefs_common.comply_gnome_hig);
218 gtk_widget_grab_focus(ok_button);
219 gtk_widget_grab_focus(treeview);
220
221 manage_window_set_transient(GTK_WINDOW(window));
222 gtk_widget_show(window);
223
224 cancelled = finished = FALSE;
225
226 while (finished == FALSE)
227 gtk_main_iteration();
228
229 gtk_widget_hide(window);
230 gtk_label_set_text(GTK_LABEL(label), "");
231 gtk_entry_set_text(GTK_ENTRY(entry), "");
232 gtk_tree_store_clear(tree_store);
233
234 if (cancelled || !selected_item)
235 return NULL;
236
237 if (type == FOLDER_SEL_ALL ||
238 (selected_item->stype != F_VIRTUAL &&
239 (sel_type == FOLDER_SEL_MOVE_FOLDER ||
240 (selected_item->path && !selected_item->no_select)))) {
241 folder_item = selected_item;
242 return folder_item;
243 }
244
245 return NULL;
246}
247
248static void foldersel_create(void)
249{
250 GtkWidget *vbox;
251 GtkTreeViewColumn *column;
252 GtkCellRenderer *renderer;
253 GtkTreeSelection *selection;
254
255 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
256 gtk_window_set_title(GTK_WINDOW(window), _("Select folder"));
257 gtk_container_set_border_width(GTK_CONTAINER(window), 4);
258 gtk_window_set_position(GTK_WINDOW(window),
259 GTK_WIN_POS_CENTER_ON_PARENT);
260 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
261 gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
262 gtk_window_set_wmclass
263 (GTK_WINDOW(window), "folder_selection", "Sylpheed");
264 gtk_widget_realize(window);
265 g_signal_connect(G_OBJECT(window), "delete_event",
266 G_CALLBACK(delete_event), NULL);
267 g_signal_connect(G_OBJECT(window), "key_press_event",
268 G_CALLBACK(key_pressed), NULL);
269 MANAGE_WINDOW_SIGNALS_CONNECT(window);
270
271 vbox = gtk_vbox_new(FALSE, 4);
272 gtk_widget_set_size_request(vbox, -1, 460 * gtkut_get_dpi_multiplier());
273 gtk_container_add(GTK_CONTAINER(window), vbox);
274
275 label = gtk_label_new("");
276 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
277 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 2);
278
279 scrolledwin = gtk_scrolled_window_new(NULL, NULL);
280 gtk_widget_set_size_request(scrolledwin, 320 * gtkut_get_dpi_multiplier(), -1);
281 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
282 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
283 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
284 GTK_SHADOW_IN);
285 gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, TRUE, TRUE, 0);
286
287 tree_store = gtk_tree_store_new(N_FOLDERSEL_COLUMNS,
288 G_TYPE_STRING,
289 G_TYPE_POINTER,
290 GDK_TYPE_PIXBUF,
291 GDK_TYPE_PIXBUF,
292 GDK_TYPE_COLOR,
293 G_TYPE_INT);
294 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree_store),
295 FOLDERSEL_FOLDERNAME,
296 foldersel_folder_name_compare,
297 NULL, NULL);
298
299 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_store));
300 g_object_unref(G_OBJECT(tree_store));
301 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
302 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
303 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview),
304 FOLDERSEL_FOLDERNAME);
305
306 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
307 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
308 gtk_tree_selection_set_select_function(selection, foldersel_selected,
309 NULL, NULL);
310
311 g_signal_connect(G_OBJECT(treeview), "row-activated",
312 G_CALLBACK(foldersel_tree_activated), NULL);
313 g_signal_connect(G_OBJECT(treeview), "key_press_event",
314 G_CALLBACK(foldersel_tree_key_pressed), NULL);
315
316 gtk_container_add(GTK_CONTAINER(scrolledwin), treeview);
317
318 column = gtk_tree_view_column_new();
319 gtk_tree_view_column_set_spacing(column, 1);
320 renderer = gtk_cell_renderer_pixbuf_new();
321 g_object_set(renderer, "ypad", 0, NULL);
322 gtk_tree_view_column_pack_start(column, renderer, FALSE);
323 gtk_tree_view_column_set_attributes
324 (column, renderer,
325 "pixbuf", FOLDERSEL_PIXBUF,
326 "pixbuf-expander-open", FOLDERSEL_PIXBUF_OPEN,
327 "pixbuf-expander-closed", FOLDERSEL_PIXBUF,
328 NULL);
329
330 /* create text renderer */
331 renderer = gtk_cell_renderer_text_new();
332 g_object_set(renderer, "ypad", 0, NULL);
333 gtk_tree_view_column_pack_start(column, renderer, TRUE);
334 gtk_tree_view_column_set_attributes
335 (column, renderer,
336 "text", FOLDERSEL_FOLDERNAME,
337 "foreground-gdk", FOLDERSEL_FOREGROUND,
338 "weight", FOLDERSEL_BOLD,
339 NULL);
340 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
341
342 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
343
344 entry = gtk_entry_new();
345 gtk_entry_set_editable(GTK_ENTRY(entry), FALSE);
346 gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
347 g_signal_connect(G_OBJECT(entry), "activate",
348 G_CALLBACK(foldersel_entry_activated), NULL);
349
350 gtkut_stock_button_set_create(&confirm_area,
351 &ok_button, GTK_STOCK_OK,
352 &cancel_button, GTK_STOCK_CANCEL,
353 NULL, NULL);
354
355 gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
356 gtk_widget_grab_default(ok_button);
357
358 new_button = gtk_button_new_from_stock(GTK_STOCK_NEW);
359 gtk_widget_show(new_button);
360 gtk_box_pack_start(GTK_BOX(confirm_area), new_button, FALSE, FALSE, 0);
361 gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(confirm_area),
362 new_button, TRUE);
363
364 g_signal_connect(G_OBJECT(ok_button), "clicked",
365 G_CALLBACK(foldersel_ok), NULL);
366 g_signal_connect(G_OBJECT(cancel_button), "clicked",
367 G_CALLBACK(foldersel_cancel), NULL);
368 g_signal_connect(G_OBJECT(new_button), "clicked",
369 G_CALLBACK(foldersel_new_folder), NULL);
370
371 gtk_widget_show_all(vbox);
372}
373
374static void foldersel_init(void)
375{
376 stock_pixbuf_gdk(treeview, STOCK_PIXMAP_FOLDER_CLOSE,
377 &folder_pixbuf);
378 stock_pixbuf_gdk(treeview, STOCK_PIXMAP_FOLDER_OPEN,
379 &folderopen_pixbuf);
380 stock_pixbuf_gdk(treeview, STOCK_PIXMAP_FOLDER_NOSELECT,
381 &foldernoselect_pixbuf);
382}
383
384static void foldersel_append_item(GtkTreeStore *store, FolderItem *item,
385 GtkTreeIter *iter, GtkTreeIter *parent)
386{
387 gchar *name;
388 gchar *sub = "";
389 GdkPixbuf *pixbuf, *pixbuf_open;
390 gboolean use_color;
391 gboolean no_select;
392 PangoWeight weight = PANGO_WEIGHT_NORMAL;
393 GdkColor *foreground = NULL;
394 static GdkColor color_noselect = {0, COLOR_DIM, COLOR_DIM, COLOR_DIM};
395 static GdkColor color_new = {0, (guint16)55000, 15000, 15000};
396
397 name = item->name;
398
399 if (item->stype != F_NORMAL && FOLDER_IS_LOCAL(item->folder)) {
400 switch (item->stype) {
401 case F_INBOX:
402 if (!strcmp2(item->name, INBOX_DIR))
403 name = _("Inbox");
404 break;
405 case F_OUTBOX:
406 if (!strcmp2(item->name, OUTBOX_DIR))
407 name = _("Sent");
408 break;
409 case F_QUEUE:
410 if (!strcmp2(item->name, QUEUE_DIR))
411 name = _("Queue");
412 break;
413 case F_TRASH:
414 if (!strcmp2(item->name, TRASH_DIR))
415 name = _("Trash");
416 break;
417 case F_DRAFT:
418 if (!strcmp2(item->name, DRAFT_DIR))
419 name = _("Drafts");
420 break;
421 case F_JUNK:
422 if (!strcmp2(item->name, JUNK_DIR))
423 name = _("Junk");
424 break;
425 default:
426 break;
427 }
428 }
429
430 if (!item->parent) {
431 switch (FOLDER_TYPE(item->folder)) {
432 case F_MH:
433 sub = " (MH)"; break;
434 case F_IMAP:
435 sub = " (IMAP4)"; break;
436 case F_NEWS:
437 sub = " (News)"; break;
438 default:
439 break;
440 }
441 }
442
443 if (item->stype == F_QUEUE && item->total > 0) {
444 name = g_strdup_printf("%s%s (%d)", name, sub, item->total);
445 } else if (item->unread > 0) {
446 name = g_strdup_printf("%s%s (%d)", name, sub, item->unread);
447 } else
448 name = g_strdup_printf("%s%s", name, sub);
449
450 no_select = item->no_select ||
451 (sel_type != FOLDER_SEL_ALL && item->stype == F_VIRTUAL);
452
453 pixbuf = no_select ? foldernoselect_pixbuf : folder_pixbuf;
454 pixbuf_open = no_select ? foldernoselect_pixbuf : folderopen_pixbuf;
455
456 if (item->stype == F_OUTBOX || item->stype == F_DRAFT ||
457 item->stype == F_TRASH || item->stype == F_JUNK) {
458 use_color = FALSE;
459 } else if (item->stype == F_QUEUE) {
460 use_color = (item->total > 0);
461 if (item->total > 0)
462 weight = PANGO_WEIGHT_BOLD;
463 } else {
464 use_color = (item->new > 0);
465 if (item->unread > 0)
466 weight = PANGO_WEIGHT_BOLD;
467 }
468
469 if (no_select)
470 foreground = &color_noselect;
471 else if (use_color)
472 foreground = &color_new;
473
474 /* insert this node */
475 gtk_tree_store_append(store, iter, parent);
476 gtk_tree_store_set(store, iter,
477 FOLDERSEL_FOLDERNAME, name,
478 FOLDERSEL_FOLDERITEM, item,
479 FOLDERSEL_PIXBUF, pixbuf,
480 FOLDERSEL_PIXBUF_OPEN, pixbuf_open,
481 FOLDERSEL_FOREGROUND, foreground,
482 FOLDERSEL_BOLD, weight,
483 -1);
484 g_free(name);
485}
486
487static void foldersel_insert_gnode_in_store(GtkTreeStore *store, GNode *node,
488 GtkTreeIter *parent)
489{
490 FolderItem *item;
491 GtkTreeIter child;
492 GNode *iter;
493
494 g_return_if_fail(node != NULL);
495 g_return_if_fail(node->data != NULL);
496 g_return_if_fail(store != NULL);
497
498 item = FOLDER_ITEM(node->data);
499 foldersel_append_item(store, item, &child, parent);
500
501 if (parent && item->parent && node->parent->children == node &&
502 !item->parent->collapsed) {
503 GtkTreePath *path;
504
505 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), parent);
506 gtk_tree_view_expand_row(GTK_TREE_VIEW(treeview), path, FALSE);
507 gtk_tree_path_free(path);
508 }
509
510 /* insert its children (this node as parent) */
511 for (iter = node->children; iter != NULL; iter = iter->next)
512 foldersel_insert_gnode_in_store(store, iter, &child);
513}
514
515static void foldersel_set_tree(Folder *cur_folder)
516{
517 Folder *folder;
518 GList *list;
519
520 for (list = folder_get_list(); list != NULL; list = list->next) {
521 folder = FOLDER(list->data);
522 g_return_if_fail(folder != NULL);
523
524 if (sel_type != FOLDER_SEL_ALL) {
525 if (FOLDER_TYPE(folder) == F_NEWS)
526 continue;
527 }
528 if (sel_type == FOLDER_SEL_MOVE_FOLDER && folder != cur_folder)
529 continue;
530
531 foldersel_insert_gnode_in_store(tree_store, folder->node, NULL);
532 }
533
534 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tree_store),
535 FOLDERSEL_FOLDERNAME,
536 GTK_SORT_ASCENDING);
537}
538
539static gboolean foldersel_selected(GtkTreeSelection *selection,
540 GtkTreeModel *model, GtkTreePath *path,
541 gboolean currently_selected, gpointer data)
542{
543 GtkTreeIter iter;
544 FolderItem *item = NULL;
545
546 if (currently_selected)
547 return TRUE;
548
549 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
550 return TRUE;
551
552 gtk_tree_model_get(GTK_TREE_MODEL(tree_store), &iter,
553 FOLDERSEL_FOLDERITEM, &item, -1);
554
555 selected_item = item;
556 if (selected_item &&
557 (sel_type == FOLDER_SEL_ALL ||
558 (selected_item->stype != F_VIRTUAL &&
559 (sel_type == FOLDER_SEL_MOVE_FOLDER ||
560 (selected_item->path && !selected_item->no_select))))) {
561 gchar *id;
562 id = folder_item_get_identifier(selected_item);
563 gtk_entry_set_text(GTK_ENTRY(entry), id);
564 g_free(id);
565 } else
566 gtk_entry_set_text(GTK_ENTRY(entry), "");
567
568 return TRUE;
569}
570
571static void foldersel_ok(GtkButton *button, gpointer data)
572{
573 finished = TRUE;
574}
575
576static void foldersel_cancel(GtkButton *button, gpointer data)
577{
578 cancelled = TRUE;
579 finished = TRUE;
580}
581
582static void foldersel_new_folder(GtkButton *button, gpointer data)
583{
584 FolderItem *new_item;
585 gchar *new_folder;
586 gchar *disp_name;
587 gchar *p;
588 GtkTreeIter selected, new_child;
589 GtkTreePath *selected_p, *new_child_p;
590 GtkTreeStore *store;
591 GtkTreeModel *model;
592 GtkTreeSelection *selection;
593
594 if (!selected_item || FOLDER_TYPE(selected_item->folder) == F_NEWS)
595 return;
596
597 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
598 if (!gtk_tree_selection_get_selected(selection, &model, &selected))
599 return;
600 store = GTK_TREE_STORE(model);
601
602 new_folder = input_dialog(_("New folder"),
603 _("Input the name of new folder:"),
604 _("NewFolder"));
605 if (!new_folder) return;
606 AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
607
608 p = strchr(new_folder, G_DIR_SEPARATOR);
609 if ((p && FOLDER_TYPE(selected_item->folder) != F_IMAP) ||
610 (p && FOLDER_TYPE(selected_item->folder) == F_IMAP &&
611 *(p + 1) != '\0')) {
612 alertpanel_error(_("`%c' can't be included in folder name."),
613 G_DIR_SEPARATOR);
614 return;
615 }
616
617 disp_name = trim_string(new_folder, 32);
618 AUTORELEASE_STR(disp_name, {g_free(disp_name); return;});
619
620 /* find whether the directory already exists */
621 if (folder_find_child_item_by_name(selected_item, new_folder)) {
622 alertpanel_error(_("The folder `%s' already exists."),
623 disp_name);
624 return;
625 }
626
627 new_item = selected_item->folder->klass->create_folder
628 (selected_item->folder, selected_item, new_folder);
629 if (!new_item) {
630 alertpanel_error(_("Can't create the folder `%s'."), disp_name);
631 return;
632 }
633
634 /* add new child */
635 foldersel_append_item(store, new_item, &new_child, &selected);
636 selected_p = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &selected);
637 new_child_p = gtk_tree_model_get_path(GTK_TREE_MODEL(store),
638 &new_child);
639
640 gtk_tree_view_expand_row(GTK_TREE_VIEW(treeview), selected_p, FALSE);
641 gtk_tree_selection_select_iter(selection, &new_child);
642 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeview), new_child_p,
643 NULL, TRUE, 0.5, 0.0);
644 gtk_tree_path_free(new_child_p);
645 gtk_tree_path_free(selected_p);
646
647 folderview_append_item(folderview_get(), NULL, new_item, TRUE);
648 folder_write_list();
649}
650
651static void foldersel_entry_activated(GtkEntry *entry, gpointer data)
652{
653 gtk_button_clicked(GTK_BUTTON(ok_button));
654}
655
656static void foldersel_tree_activated(GtkTreeView *treeview, GtkTreePath *path,
657 GtkTreeViewColumn *column, gpointer data)
658{
659 gtk_button_clicked(GTK_BUTTON(ok_button));
660}
661
662static gboolean foldersel_tree_key_pressed(GtkWidget *widget,
663 GdkEventKey *event, gpointer data)
664{
665 GtkTreeSelection *selection;
666 GtkTreeModel *model;
667 GtkTreeIter iter;
668 GtkTreePath *selected;
669 GtkAdjustment *adj;
670 gboolean moved;
671
672 if (!event)
673 return FALSE;
674
675 switch (event->keyval) {
676 case GDK_Left:
677 case GDK_KP_Left:
678 if ((event->state &
679 (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0)
680 return FALSE;
681 adj = gtk_scrolled_window_get_hadjustment
682 (GTK_SCROLLED_WINDOW(scrolledwin));
683 if (adj->lower < adj->value)
684 return FALSE;
685 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
686 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
687 return FALSE;
688 selected = gtk_tree_model_get_path(model, &iter);
689 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(treeview), selected)) {
690 gtk_tree_view_collapse_row(GTK_TREE_VIEW(treeview), selected);
691 gtk_tree_path_free(selected);
692 return TRUE;
693 }
694 gtk_tree_path_free(selected);
695 g_signal_emit_by_name(G_OBJECT(treeview),
696 "select-cursor-parent", &moved);
697 return TRUE;
698 case GDK_Right:
699 case GDK_KP_Right:
700 if ((event->state &
701 (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0)
702 return FALSE;
703 adj = gtk_scrolled_window_get_hadjustment
704 (GTK_SCROLLED_WINDOW(scrolledwin));
705 if (adj->lower - adj->page_size > adj->value)
706 return FALSE;
707 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
708 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
709 return FALSE;
710 selected = gtk_tree_model_get_path(model, &iter);
711 if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(treeview), selected)) {
712 gtk_tree_view_expand_row(GTK_TREE_VIEW(treeview), selected, FALSE);
713 gtk_tree_path_free(selected);
714 return TRUE;
715 }
716 gtk_tree_path_free(selected);
717 break;
718 default:
719 break;
720 }
721
722 return FALSE;
723}
724
725static gint delete_event(GtkWidget *widget, GdkEventAny *event, gpointer data)
726{
727 foldersel_cancel(NULL, NULL);
728 return TRUE;
729}
730
731static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
732{
733 if (event && event->keyval == GDK_Escape)
734 foldersel_cancel(NULL, NULL);
735 return FALSE;
736}
737
738static gint foldersel_folder_name_compare(GtkTreeModel *model, GtkTreeIter *a,
739 GtkTreeIter *b, gpointer context)
740{
741 FolderItem *item_a = NULL, *item_b = NULL;
742
743 gtk_tree_model_get(model, a, FOLDERSEL_FOLDERITEM, &item_a, -1);
744 gtk_tree_model_get(model, b, FOLDERSEL_FOLDERITEM, &item_b, -1);
745
746 return folder_item_compare(item_a, item_b);
747}
748
749static gboolean tree_view_folder_item_func(GtkTreeModel *model,
750 GtkTreePath *path,
751 GtkTreeIter *iter,
752 FolderItemSearch *data)
753{
754 FolderItem *item = NULL;
755
756 gtk_tree_model_get(model, iter, FOLDERSEL_FOLDERITEM, &item, -1);
757
758 if (data->item == item) {
759 data->path = gtk_tree_path_copy(path);
760 data->iter = *iter;
761 return TRUE;
762 }
763
764 return FALSE;
765}