source: trunk/third/evolution/shell/e-shell-folder-commands.c @ 18142

Revision 18142, 17.5 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18141, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* e-shell-folder-commands.h
3 *
4 * Copyright (C) 2001  Ximian, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
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 GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Ettore Perazzoli
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include "e-shell-folder-commands.h"
28
29#include "e-util/e-request.h"
30
31#include <gal/widgets/e-gui-utils.h>
32#include <gal/widgets/e-unicode.h>
33
34#include <libgnome/gnome-i18n.h>
35#include <libgnome/gnome-util.h>
36#include <libgnomeui/gnome-dialog.h>
37#include <libgnomeui/gnome-stock.h>
38
39#include <gtk/gtklabel.h>
40#include <gtk/gtksignal.h>
41#include <gtk/gtkentry.h>
42
43#include "e-shell-constants.h"
44#include "e-shell-folder-creation-dialog.h"
45#include "e-shell-folder-selection-dialog.h"
46#include "e-shell-utils.h"
47
48
49/* Utility functions.  */
50
51static const char *
52get_folder_name (EShell *shell,
53                 const char *path)
54{
55        EStorageSet *storage_set;
56        EFolder *folder;
57
58        storage_set = e_shell_get_storage_set (shell);
59        folder = e_storage_set_get_folder (storage_set, path);
60
61        return e_folder_get_name (folder);
62}
63
64static int
65get_folder_unread (EShell *shell,
66                   const char *path)
67{
68        EStorageSet *storage_set;
69        EFolder *folder;
70
71        storage_set = e_shell_get_storage_set (shell);
72        folder = e_storage_set_get_folder (storage_set, path);
73
74        return e_folder_get_unread_count (folder);
75}
76
77
78/* The data passed to the signals handled during the execution of the folder
79   commands.  */
80
81enum _FolderCommand {
82        FOLDER_COMMAND_COPY,
83        FOLDER_COMMAND_MOVE
84};
85typedef enum _FolderCommand FolderCommand;
86
87struct _FolderCommandData {
88        EShell *shell;
89        EShellView *shell_view;
90        FolderCommand command;
91        char *source_path;
92        char *destination_path;
93};
94typedef struct _FolderCommandData FolderCommandData;
95
96static FolderCommandData *
97folder_command_data_new (EShell *shell,
98                         EShellView *shell_view,
99                         FolderCommand command,
100                         const char *source_path,
101                         const char *destination_path)
102{
103        FolderCommandData *new;
104
105        new = g_new (FolderCommandData, 1);
106        new->shell            = shell;
107        new->shell_view       = shell_view;
108        new->command          = command;
109        new->source_path      = g_strdup (source_path);
110        new->destination_path = g_strdup (destination_path);
111
112        return new;
113}
114
115static void
116folder_command_data_free (FolderCommandData *folder_command_data)
117{
118        g_free (folder_command_data->source_path);
119        g_free (folder_command_data->destination_path);
120
121        g_free (folder_command_data);
122}
123
124
125/* Callback for the storage result.  */
126
127static void
128xfer_result_callback (EStorageSet *storage_set,
129                      EStorageResult result,
130                      void *data)
131{
132        FolderCommandData *folder_command_data;
133
134        folder_command_data = (FolderCommandData *) data;
135
136        if (result != E_STORAGE_OK) {
137                char *msg;
138
139                if (folder_command_data->command == FOLDER_COMMAND_COPY)
140                        msg = g_strdup_printf (_("Cannot copy folder: %s"),
141                                               e_storage_result_to_string (result));
142                else
143                        msg = g_strdup_printf (_("Cannot move folder: %s"),
144                                               e_storage_result_to_string (result));
145
146                e_notice (GTK_WINDOW (folder_command_data->shell_view),
147                          GNOME_MESSAGE_BOX_ERROR, msg);
148
149                g_free (msg);
150        }
151
152        folder_command_data_free (folder_command_data);
153}
154
155
156/* The signals for the folder selection dialog.  This used for the copy and
157   move commands.  */
158
159static void
160folder_selection_dialog_folder_selected_callback (EShellFolderSelectionDialog *folder_selection_dialog,
161                                                  const char *path,
162                                                  void *data)
163{
164        FolderCommandData *folder_command_data;
165        EStorageSet *storage_set;
166        gboolean remove_source;
167
168        folder_command_data = (FolderCommandData *) data;
169
170        folder_command_data->destination_path = g_concat_dir_and_file (path,
171                                                                       g_basename (folder_command_data->source_path));
172
173        switch (folder_command_data->command) {
174        case FOLDER_COMMAND_COPY:
175                remove_source = FALSE;
176                break;
177        case FOLDER_COMMAND_MOVE:
178                remove_source = TRUE;
179                break;
180        default:
181                g_assert_not_reached ();
182                return;
183        }
184
185        if (strcmp (folder_command_data->destination_path,
186                    folder_command_data->source_path) == 0) {
187                const char *msg;
188
189                if (remove_source)
190                        msg = _("Cannot move a folder over itself.");
191                else
192                        msg = _("Cannot copy a folder over itself.");
193
194                e_notice (GTK_WINDOW (folder_selection_dialog), GNOME_MESSAGE_BOX_ERROR, msg);
195                return;
196        }
197
198        if (remove_source) {
199                int source_len;
200
201                source_len = strlen (folder_command_data->source_path);
202                if (strncmp (folder_command_data->destination_path,
203                             folder_command_data->source_path,
204                             source_len) == 0) {
205                        e_notice (GTK_WINDOW (folder_selection_dialog), GNOME_MESSAGE_BOX_ERROR,
206                                  _("Cannot move a folder into one of its descendants."));
207                        return;
208                }
209        }
210
211        storage_set = e_shell_get_storage_set (folder_command_data->shell);
212
213        e_storage_set_async_xfer_folder (storage_set,
214                                         folder_command_data->source_path,
215                                         folder_command_data->destination_path,
216                                         remove_source,
217                                         xfer_result_callback,
218                                         folder_command_data);
219
220        gtk_widget_destroy (GTK_WIDGET (folder_selection_dialog));
221}
222
223static void
224folder_selection_dialog_cancelled_callback (EShellFolderSelectionDialog *folder_selection_dialog,
225                                            void *data)
226{
227        folder_command_data_free ((FolderCommandData *) data);
228}
229
230static void
231connect_folder_selection_dialog_signals (EShellFolderSelectionDialog *folder_selection_dialog,
232                                         FolderCommandData *folder_command_data)
233{
234        g_assert (folder_command_data != NULL);
235
236        gtk_signal_connect (GTK_OBJECT (folder_selection_dialog), "folder_selected",
237                            GTK_SIGNAL_FUNC (folder_selection_dialog_folder_selected_callback),
238                            folder_command_data);
239
240        gtk_signal_connect (GTK_OBJECT (folder_selection_dialog), "cancelled",
241                            GTK_SIGNAL_FUNC (folder_selection_dialog_cancelled_callback),
242                            folder_command_data);
243}
244
245
246/* Create new folder.  */
247
248void
249e_shell_command_create_new_folder (EShell *shell,
250                                   EShellView *shell_view,
251                                   const char *parent_folder_path)
252{
253        g_return_if_fail (shell != NULL);
254        g_return_if_fail (E_IS_SHELL (shell));
255        g_return_if_fail (shell_view != NULL || parent_folder_path != NULL);
256        g_return_if_fail (shell_view != NULL && E_IS_SHELL_VIEW (shell_view));
257        g_return_if_fail (parent_folder_path != NULL || g_path_is_absolute (parent_folder_path));
258
259        if (parent_folder_path == NULL)
260                parent_folder_path = e_shell_view_get_current_path (shell_view);
261
262        /* FIXME: Should handle the result stuff.  */
263        e_shell_show_folder_creation_dialog (shell, GTK_WINDOW (shell_view),
264                                             e_shell_view_get_current_path (shell_view),
265                                             NULL /* Default type. Take it from parent */,
266                                             NULL /* result_callback */,
267                                             NULL /* result_callback_data */);
268}
269
270
271/* Open folder in other window.   */
272
273void
274e_shell_command_open_folder_in_other_window (EShell *shell,
275                                             EShellView *shell_view,
276                                             const char *folder_path)
277{
278        EShellView *view;
279        char *uri;
280
281        g_return_if_fail (shell != NULL);
282        g_return_if_fail (E_IS_SHELL (shell));
283        g_return_if_fail (shell_view != NULL && E_IS_SHELL_VIEW (shell_view));
284
285        if (folder_path == NULL)
286                folder_path = e_shell_view_get_current_path (shell_view);
287
288        uri = g_strconcat (E_SHELL_URI_PREFIX, folder_path, NULL);
289        view = e_shell_create_view (shell, uri, shell_view);
290        g_free (uri);
291
292        gtk_widget_show (GTK_WIDGET (view));
293}
294
295
296/* Copy folder.  */
297
298void
299e_shell_command_copy_folder (EShell *shell,
300                             EShellView *shell_view,
301                             const char *folder_path)
302{
303        GtkWidget *folder_selection_dialog;
304        FolderCommandData *data;
305        char *uri;
306        char *caption;
307
308        g_return_if_fail (shell != NULL);
309        g_return_if_fail (E_IS_SHELL (shell));
310        g_return_if_fail (shell_view != NULL && E_IS_SHELL_VIEW (shell_view));
311        g_return_if_fail (folder_path == NULL || g_path_is_absolute (folder_path));
312
313        if (folder_path == NULL)
314                folder_path = e_shell_view_get_current_path (shell_view);
315
316        if (folder_path == NULL) {
317                g_warning ("Called `e_shell_command_copy_folder()' without a valid displayed folder");
318                return;
319        }
320
321        caption = g_strdup_printf (_("Specify a folder to copy folder \"%s\" into:"),
322                                   get_folder_name (shell, folder_path));
323
324        uri = g_strconcat (E_SHELL_URI_PREFIX, folder_path, NULL);
325        folder_selection_dialog = e_shell_folder_selection_dialog_new (shell, _("Copy folder"),
326                                                                       caption, uri, NULL);
327
328        g_free (caption);
329        g_free (uri);
330
331        data = folder_command_data_new (shell, shell_view, FOLDER_COMMAND_COPY, folder_path, NULL);
332        connect_folder_selection_dialog_signals (E_SHELL_FOLDER_SELECTION_DIALOG (folder_selection_dialog),
333                                                 data);
334
335        gtk_widget_show (folder_selection_dialog);
336}
337
338
339/* Move folder.  */
340
341void
342e_shell_command_move_folder (EShell *shell,
343                             EShellView *shell_view,
344                             const char *folder_path)
345{
346        GtkWidget *folder_selection_dialog;
347        FolderCommandData *data;
348        char *uri;
349        char *caption;
350
351        g_return_if_fail (shell != NULL);
352        g_return_if_fail (E_IS_SHELL (shell));
353        g_return_if_fail (shell_view != NULL);
354        g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
355        g_return_if_fail (folder_path == NULL || g_path_is_absolute (folder_path));
356
357        if (folder_path == NULL)
358                folder_path = e_shell_view_get_current_path (shell_view);
359
360        if (folder_path == NULL) {
361                g_warning ("Called `e_shell_command_move_folder()' without a valid displayed folder");
362                return;
363        }
364
365        caption = g_strdup_printf (_("Specify a folder to move folder \"%s\" into:"),
366                                   get_folder_name (shell, folder_path));
367
368        uri = g_strconcat (E_SHELL_URI_PREFIX, folder_path, NULL);
369        folder_selection_dialog = e_shell_folder_selection_dialog_new (shell, _("Move folder"),
370                                                                       caption, uri, NULL);
371
372        g_free (caption);
373        g_free (uri);
374
375        data = folder_command_data_new (shell, shell_view, FOLDER_COMMAND_MOVE, folder_path, NULL);
376        connect_folder_selection_dialog_signals (E_SHELL_FOLDER_SELECTION_DIALOG (folder_selection_dialog),
377                                                 data);
378
379        gtk_widget_show (folder_selection_dialog);
380}
381
382static void
383delete_cb (EStorageSet *storage_set,
384           EStorageResult result,
385           void *data)
386{
387        EShellView *shell_view;
388
389        shell_view = E_SHELL_VIEW (data);
390
391        if (result != E_STORAGE_OK)
392                e_notice (GTK_WINDOW (shell_view), GNOME_MESSAGE_BOX_ERROR,
393                          _("Cannot delete folder:\n%s"), e_storage_result_to_string (result));
394}
395
396static int
397delete_dialog (EShellView *shell_view, const char *utf8_folder)
398{
399        GtkWidget *dialog;
400        char *title;
401        char *question;
402        char *folder_name;
403
404        folder_name = e_utf8_to_gtk_string (GTK_WIDGET (shell_view), (char *) utf8_folder);
405
406        title = g_strdup_printf (_("Delete \"%s\""), folder_name);
407        question = g_strdup_printf (_("Really delete folder \"%s\"?"), folder_name);
408
409        dialog = gnome_message_box_new (question,
410                                        GNOME_MESSAGE_BOX_QUESTION,
411                                        _("Delete"),
412                                        GNOME_STOCK_BUTTON_CANCEL,
413                                        NULL);
414        gtk_window_set_title (GTK_WINDOW (dialog), title);
415        gnome_dialog_set_parent (GNOME_DIALOG (dialog), GTK_WINDOW (shell_view));
416        gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);
417
418        g_free (title);
419        g_free (folder_name);
420        g_free (question);
421
422        return gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
423}
424
425void
426e_shell_command_delete_folder (EShell *shell,
427                               EShellView *shell_view,
428                               const char *folder_path)
429{
430        EStorageSet *storage_set;
431
432        g_return_if_fail (shell != NULL);
433        g_return_if_fail (E_IS_SHELL (shell));
434        g_return_if_fail (shell_view != NULL || folder_path != NULL);
435        g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
436        g_return_if_fail (folder_path != NULL || g_path_is_absolute (folder_path));
437
438        storage_set = e_shell_get_storage_set (shell);
439
440        if (folder_path == NULL)
441                folder_path = e_shell_view_get_current_path (shell_view);
442
443        if (delete_dialog (shell_view, get_folder_name (shell, folder_path)) == 0)
444                e_storage_set_async_remove_folder (storage_set, folder_path, delete_cb, shell_view);
445}
446
447
448struct _RenameCallbackData {
449        EShellView *shell_view;
450        char *new_path;
451};
452typedef struct _RenameCallbackData RenameCallbackData;
453
454static RenameCallbackData *
455rename_callback_data_new (EShellView *shell_view,
456                          const char *new_path)
457{
458        RenameCallbackData *callback_data;
459
460        callback_data = g_new (RenameCallbackData, 1);
461
462        gtk_object_ref (GTK_OBJECT (shell_view));
463        callback_data->shell_view = shell_view;
464
465        callback_data->new_path = g_strdup (new_path);
466
467        return callback_data;
468}
469
470static void
471rename_callback_data_free (RenameCallbackData *callback_data)
472{
473        gtk_object_unref (GTK_OBJECT (callback_data->shell_view));
474        g_free (callback_data->new_path);
475
476        g_free (callback_data);
477}
478
479static void
480rename_cb (EStorageSet *storage_set, EStorageResult result, void *data)
481{
482        RenameCallbackData *callback_data;
483
484        callback_data = (RenameCallbackData *) data;
485
486        if (result != E_STORAGE_OK) {
487                e_notice (GTK_WINDOW (callback_data->shell_view), GNOME_MESSAGE_BOX_ERROR,
488                          _("Cannot rename folder:\n%s"), e_storage_result_to_string (result));
489        } else {
490                EFolder *folder;
491                EShell *shell;
492                EStorageSet *storage_set;
493
494                shell = e_shell_view_get_shell (callback_data->shell_view);
495                storage_set = e_shell_get_storage_set (shell);
496                folder = e_storage_set_get_folder (storage_set, callback_data->new_path);
497
498                if (folder != NULL)
499                        e_folder_set_name (folder, g_basename (callback_data->new_path));
500        }
501
502        rename_callback_data_free (callback_data);
503}
504
505void
506e_shell_command_rename_folder (EShell *shell,
507                               EShellView *shell_view,
508                               const char *folder_path)
509{
510        EStorageSet *storage_set;
511        EFolder *folder;
512        RenameCallbackData *callback_data;
513        const char *old_name;
514        char *old_name_locale;
515        char *prompt;
516        char *new_name;
517        char *old_base_path;
518        char *new_path;
519
520        g_return_if_fail (shell != NULL);
521        g_return_if_fail (E_IS_SHELL (shell));
522        g_return_if_fail (shell_view != NULL);
523        g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
524
525        storage_set = e_shell_get_storage_set (shell);
526
527        if (folder_path == NULL)
528                folder_path = e_shell_view_get_current_path (shell_view);
529
530        folder = e_storage_set_get_folder (storage_set, folder_path);
531        g_return_if_fail (folder != NULL);
532
533        old_name = e_folder_get_name (folder);
534        old_name_locale = e_utf8_to_locale_string (old_name);
535        prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), old_name_locale);
536        g_free (old_name_locale);
537
538        while (1) {
539                const char *reason;
540
541                new_name = e_request_string (shell_view != NULL ? GTK_WINDOW (shell_view) : NULL,
542                                             _("Rename folder"), prompt, old_name);
543
544                if (new_name == NULL)
545                        return;
546
547                if (e_shell_folder_name_is_valid (new_name, &reason))
548                        break;
549
550                e_notice (shell_view != NULL ? GTK_WINDOW (shell_view) : NULL,
551                          GNOME_MESSAGE_BOX_ERROR,
552                          _("The specified folder name is not valid: %s"), reason);
553        }
554
555        g_free (prompt);
556
557        if (strcmp (old_name, new_name) == 0) {
558                g_free (new_name);
559                return;
560        }
561
562        old_base_path = g_dirname (folder_path);
563        new_path = g_concat_dir_and_file (old_base_path, new_name);
564
565        callback_data = rename_callback_data_new (shell_view, new_path);
566        e_storage_set_async_xfer_folder (storage_set, folder_path, new_path, TRUE, rename_cb, callback_data);
567
568        g_free (old_base_path);
569        g_free (new_path);
570        g_free (new_name);
571}
572
573
574static void
575remove_shared_cb (EStorageSet *storage_set,
576                  EStorageResult result,
577                  void *data)
578{
579        EShellView *shell_view;
580
581        shell_view = E_SHELL_VIEW (data);
582
583        if (result == E_STORAGE_NOTIMPLEMENTED ||
584            result == E_STORAGE_UNSUPPORTEDOPERATION)
585                e_notice (GTK_WINDOW (shell_view), GNOME_MESSAGE_BOX_ERROR,
586                          _("Selected folder does not belong to another user"));
587        else if (result != E_STORAGE_OK)
588                e_notice (GTK_WINDOW (shell_view), GNOME_MESSAGE_BOX_ERROR,
589                          _("Cannot remove folder:\n%s"), e_storage_result_to_string (result));
590}
591
592void
593e_shell_command_remove_shared_folder (EShell *shell,
594                                      EShellView *shell_view,
595                                      const char *folder_path)
596{
597        EStorageSet *storage_set;
598
599        g_return_if_fail (shell != NULL);
600        g_return_if_fail (E_IS_SHELL (shell));
601        g_return_if_fail (shell_view != NULL || folder_path != NULL);
602        g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
603        g_return_if_fail (folder_path != NULL || g_path_is_absolute (folder_path));
604
605        storage_set = e_shell_get_storage_set (shell);
606
607        if (folder_path == NULL)
608                folder_path = e_shell_view_get_current_path (shell_view);
609
610        e_storage_set_async_remove_shared_folder (storage_set, folder_path,
611                                                  remove_shared_cb, shell_view);
612}
613
614
615void
616e_shell_command_add_to_shortcut_bar (EShell *shell,
617                                     EShellView *shell_view,
618                                     const char *folder_path)
619{
620        EShortcuts *shortcuts;
621        EStorageSet *storage_set;
622        EFolder *folder;
623        int group_num;
624        char *uri;
625        int unread_count;
626
627        g_return_if_fail (shell != NULL);
628        g_return_if_fail (E_IS_SHELL (shell));
629        g_return_if_fail (shell_view != NULL);
630        g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
631        g_return_if_fail (folder_path == NULL || g_path_is_absolute (folder_path));
632
633        shortcuts = e_shell_get_shortcuts (shell);
634        group_num = e_shell_view_get_current_shortcuts_group_num (shell_view);
635
636        if (folder_path == NULL)
637                uri = g_strdup (e_shell_view_get_current_uri (shell_view));
638        else
639                uri = g_strconcat (E_SHELL_URI_PREFIX, folder_path, NULL);
640
641        unread_count = get_folder_unread (shell, e_shell_view_get_current_path (shell_view));
642
643        storage_set = e_shell_get_storage_set (shell);
644        folder = e_storage_set_get_folder (storage_set, e_shell_view_get_current_path (shell_view));
645
646        e_shortcuts_add_shortcut (shortcuts, group_num, -1, uri, NULL,
647                                  unread_count,
648                                  e_folder_get_type_string (folder),
649                                  e_folder_get_custom_icon_name (folder));
650
651        g_free (uri);
652}
Note: See TracBrowser for help on using the repository browser.