Logo Search packages:      
Sourcecode: balsa version File versions

folder-conf.c

/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
/* Balsa E-Mail Client
 * Copyright (C) 1997-2003 Stuart Parmenter and others,
 *                         See the file AUTHORS for a list.
 *
 * 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 2, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  
 * 02111-1307, USA.
 */

#include "config.h"
#include <gnome.h>
#include <string.h>
#include "balsa-app.h"
#include "balsa-icons.h"
#include "folder-conf.h"
#include "mailbox-conf.h"
#include "mailbox-node.h"
#include "save-restore.h"
#include "pref-manager.h"
#include "imap-server.h"
#include "i18n.h"

typedef struct _CommonDialogData CommonDialogData;
typedef struct _FolderDialogData FolderDialogData;
typedef struct _SubfolderDialogData SubfolderDialogData;

typedef gboolean (*CommonDialogFunc)(CommonDialogData * cdd);

#define FOLDER_CONF_COMMON \
    GtkDialog *dialog; \
    BalsaMailboxNode *mbnode; \
    CommonDialogFunc ok

#define BALSA_FOLDER_CONF_IMAP_KEY "balsa-folder-conf-imap"

struct _CommonDialogData {
    FOLDER_CONF_COMMON;
};

struct _FolderDialogData {
    FOLDER_CONF_COMMON;
    BalsaServerConf bsc;
    GtkWidget *folder_name, *port, *username, *remember,
        *password, *subscribed, *list_inbox, *prefix;
    GtkWidget *use_ssl, *tls_mode;
    GtkWidget *connection_limit, *enable_persistent, *has_bugs;
};

/* FIXME: identity_name will leak on cancelled folder edition */

struct _SubfolderDialogData {
    FOLDER_CONF_COMMON;
    BalsaMailboxConfView *mcv;
    GtkWidget *parent_folder, *folder_name, *host_label;
    gchar *old_folder, *old_parent;
    BalsaMailboxNode *parent;   /* (new) parent of the mbnode.  */
    /* Used for renaming and creation */
};

/* Destroy notification */
static void
folder_conf_destroy_cdd(CommonDialogData * cdd)
{
    if (cdd->dialog) {
        /* The mailbox node was destroyed. Close the dialog, but don't
         * trigger further calls to folder_conf_destroy_cdd. */
        cdd->mbnode = NULL;
        gtk_dialog_response(cdd->dialog, GTK_RESPONSE_NONE);
    } else
        g_free(cdd);
}

static const gchar folder_config_section[] = "folder-config";

static void
folder_conf_response(GtkDialog * dialog, int response,
                     CommonDialogData * cdd)
{
    GError *err = NULL;

    /* If mbnode's parent gets rescanned, mbnode will be finalized,
     * which triggers folder_conf_destroy_cdd, and recursively calls
     * folder_conf_response, which results in cdd being freed before
     * we're done with it; we ref mbnode to avoid that. */
    if (cdd->mbnode)
      g_object_ref(cdd->mbnode);
    switch (response) {
    case GTK_RESPONSE_HELP:
        gnome_help_display("balsa", folder_config_section, &err);
        if (err) {
            balsa_information(LIBBALSA_INFORMATION_WARNING,
                _("Error displaying %s: %s\n"), folder_config_section,
                    err->message);
            g_error_free(err);
        }
      if (cdd->mbnode)
          g_object_unref(cdd->mbnode);
        return;
    case GTK_RESPONSE_OK:
        if(!cdd->ok(cdd))
            break;
        /* ...or fall over */
    default:
        gtk_widget_destroy(GTK_WIDGET(cdd->dialog));
        cdd->dialog = NULL;
        if (cdd->mbnode) {
            /* Clearing the data signifies that the dialog has been
             * destroyed. It also triggers a call to
             * folder_conf_destroy_cdd, which will free cdd, so we cache
             * cdd->mbnode. */
          BalsaMailboxNode *mbnode = cdd->mbnode;
            g_object_set_data(G_OBJECT(mbnode),
                              BALSA_FOLDER_CONF_IMAP_KEY, NULL);
          g_object_unref(mbnode);
      } else
            /* Cancelling, without creating a mailbox node. Nobody owns
             * the xDialogData, so we'll free it here. */
            g_free(cdd);
        break;
    }
}

/* folder_conf_imap_node:
   show configuration widget for given mailbox node, allow user to 
   modify it and update mailbox node accordingly.
   Creates the node when mn == NULL.
*/
static void 
validate_folder(GtkWidget *w, FolderDialogData * fcw)
{
    gboolean sensitive = TRUE;
    if (!*gtk_entry_get_text(GTK_ENTRY(fcw->folder_name)))
      sensitive = FALSE;
    else if (!*gtk_entry_get_text(GTK_ENTRY(fcw->bsc.server)))
      sensitive = FALSE;

    gtk_dialog_set_response_sensitive(fcw->dialog, GTK_RESPONSE_OK, sensitive);
}

static void
remember_cb(GtkToggleButton * button, FolderDialogData * fcw)
{
    gtk_widget_set_sensitive(fcw->password,
                             gtk_toggle_button_get_active(button));
}

static gboolean
folder_conf_clicked_ok(FolderDialogData * fcw)
{
    gboolean insert;
    LibBalsaServer *s;
    const gchar *username;
    const gchar *host;

    host = gtk_entry_get_text(GTK_ENTRY(fcw->bsc.server));
    username = gtk_entry_get_text(GTK_ENTRY(fcw->username));

    if (fcw->mbnode) {
        insert = FALSE;
        s = fcw->mbnode->server;
    } else {
        insert = TRUE;
      s = LIBBALSA_SERVER(libbalsa_imap_server_new(username, host));
        g_signal_connect(G_OBJECT(s), "get-password",
                         G_CALLBACK(ask_password), NULL);
    }

    s->tls_mode = balsa_server_conf_get_tls_mode(&fcw->bsc);
    libbalsa_imap_server_set_max_connections
        (LIBBALSA_IMAP_SERVER(s),
         gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON
                                          (fcw->connection_limit)));
#if !defined(ENABLE_TOUCH_UI)
    libbalsa_imap_server_enable_persistent_cache
        (LIBBALSA_IMAP_SERVER(s),
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->enable_persistent)));
#endif
    libbalsa_imap_server_set_bug
        (LIBBALSA_IMAP_SERVER(s), ISBUG_FETCH,
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->has_bugs)));
    libbalsa_server_set_username(s, username);
    s->remember_passwd =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->remember));
    libbalsa_server_set_password(s,
                                 gtk_entry_get_text(GTK_ENTRY
                                                    (fcw->password)));
    if (!fcw->mbnode) {
        fcw->mbnode = balsa_mailbox_node_new_imap_folder(s, NULL);
      /* mbnode will be unrefed in folder_conf_response. */
      g_object_ref(fcw->mbnode);
        /* The mailbox node takes over ownership of the
         * FolderDialogData. */
        g_object_set_data_full(G_OBJECT(fcw->mbnode),
                               BALSA_FOLDER_CONF_IMAP_KEY, fcw,
                               (GDestroyNotify) folder_conf_destroy_cdd);
    }

    g_free(fcw->mbnode->dir);
    fcw->mbnode->dir = g_strdup(gtk_entry_get_text(GTK_ENTRY(fcw->prefix)));
    g_free(fcw->mbnode->name);
    fcw->mbnode->name =
        g_strdup(gtk_entry_get_text(GTK_ENTRY(fcw->folder_name)));
    fcw->mbnode->subscribed =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->subscribed));
    fcw->mbnode->list_inbox =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->list_inbox));

    /* Set host after all other server changes, as it triggers
     * save-to-config for any folder or mailbox using this server. */
    libbalsa_server_set_host(s, host, 
                             balsa_server_conf_get_use_ssl(&fcw->bsc));

    if (insert) {
      balsa_mblist_mailbox_node_append(NULL, fcw->mbnode);
        balsa_mailbox_node_append_subtree(fcw->mbnode);
        config_folder_add(fcw->mbnode, NULL);
      g_signal_connect_swapped(s, "set-host",
                             G_CALLBACK(config_folder_update),
                         fcw->mbnode);
        update_mail_servers();
    } else {
        balsa_mailbox_node_rescan(fcw->mbnode);
      /* Calling libbalsa_server_set_host already triggered an update,
       * so we do not need to here:
       * config_folder_update(fcw->mbnode); */
      balsa_mblist_mailbox_node_redraw(fcw->mbnode);
    }
    return TRUE;
}

/* folder_conf_imap_node:
   show the IMAP Folder configuration dialog for given mailbox node.
   If mn is NULL, setup it with default values for folder creation.
*/
void
folder_conf_imap_node(BalsaMailboxNode *mn)
{
    GtkWidget *notebook, *table, *label, *advanced;
    FolderDialogData *fcw;
    static FolderDialogData *fcw_new;
    LibBalsaServer *s;
    gchar *default_server;

    /* Allow only one dialog per mailbox node, and one with mn == NULL
     * for creating a new folder. */
    fcw = mn ? g_object_get_data(G_OBJECT(mn), BALSA_FOLDER_CONF_IMAP_KEY)
             : fcw_new;
    if (fcw) {
        gdk_window_raise(GTK_WIDGET(fcw->dialog)->window);
        return;
    }

    s = mn ? mn->server : NULL;

    fcw = g_new(FolderDialogData, 1);
    fcw->ok = (CommonDialogFunc) folder_conf_clicked_ok;
    fcw->mbnode = mn;
    fcw->dialog =
        GTK_DIALOG(gtk_dialog_new_with_buttons
                   (_("Remote IMAP folder"),
                    GTK_WINDOW(balsa_app.main_window),
                    GTK_DIALOG_DESTROY_WITH_PARENT,
                    mn ? _("_Update") : _("C_reate"), GTK_RESPONSE_OK,
                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                    GTK_STOCK_HELP, GTK_RESPONSE_HELP, NULL));
    g_object_add_weak_pointer(G_OBJECT(fcw->dialog),
                              (gpointer) &fcw->dialog);
    gtk_window_set_wmclass(GTK_WINDOW(fcw->dialog), 
                     "folder_config_dialog", "Balsa");
    if (mn) {
        g_object_set_data_full(G_OBJECT(mn),
                               BALSA_FOLDER_CONF_IMAP_KEY, fcw, 
                               (GDestroyNotify) folder_conf_destroy_cdd);
    } else {
        fcw_new = fcw;
        g_object_add_weak_pointer(G_OBJECT(fcw->dialog),
                                  (gpointer) &fcw_new);
    }

    notebook = gtk_notebook_new();
    gtk_box_pack_start(GTK_BOX(fcw->dialog->vbox),
                       notebook, TRUE, TRUE, 0);
    table = gtk_table_new(9, 2, FALSE);
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table,
                             gtk_label_new_with_mnemonic(_("_Basic")));
    advanced = balsa_server_conf_get_advanced_widget(&fcw->bsc, s, 3);
    /* Limit number of connections */
    fcw->connection_limit = 
        balsa_server_conf_add_spinner
        (&fcw->bsc, _("_Max number of connections"), 1, 40, 1,
         s 
         ? libbalsa_imap_server_get_max_connections(LIBBALSA_IMAP_SERVER(s))
         : 20);
#if !defined(ENABLE_TOUCH_UI)
    fcw->enable_persistent = 
        balsa_server_conf_add_checkbox(&fcw->bsc,
                                       _("Enable _persistent cache"));
    if(!s || 
       libbalsa_imap_server_has_persistent_cache(LIBBALSA_IMAP_SERVER(s)))
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcw->enable_persistent),
                                     TRUE);
#endif
    fcw->has_bugs = 
        balsa_server_conf_add_checkbox(&fcw->bsc,
                                       _("Enable _bug workarounds"));
    if(s &&
       libbalsa_imap_server_has_bug(LIBBALSA_IMAP_SERVER(s), ISBUG_FETCH))
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcw->has_bugs),
                                     TRUE);
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced,
                             gtk_label_new_with_mnemonic(_("_Advanced")));

    /* INPUT FIELD CREATION */
    label = create_label(_("Descriptive _Name:"), table, 0);
    fcw->folder_name = create_entry(fcw->dialog, table,
                                   GTK_SIGNAL_FUNC(validate_folder),
                                   fcw, 0, mn ? mn->name : NULL, 
                           label);

    default_server = libbalsa_guess_imap_server();
    label = create_label(_("_Server:"), table, 1);
    fcw->bsc.server = create_entry(fcw->dialog, table,
                              GTK_SIGNAL_FUNC(validate_folder),
                              fcw, 1, s ? s->host : default_server,
                        label);
    fcw->bsc.default_ports = IMAP_DEFAULT_PORTS;
    g_free(default_server);

    label= create_label(_("Use_r name:"), table, 3);
    fcw->username = create_entry(fcw->dialog, table,
                                GTK_SIGNAL_FUNC(validate_folder),
                                fcw, 3, s ? s->user : g_get_user_name(), 
                          label);

    fcw->remember = create_check(fcw->dialog, _("_Remember password"), 
                                table, 4, s ? s->remember_passwd : TRUE);
    g_signal_connect(G_OBJECT(fcw->remember), "toggled",
                     G_CALLBACK(remember_cb), fcw);

    label = create_label(_("_Password:"), table, 5);
    fcw->password = create_entry(fcw->dialog, table, NULL, NULL, 5,
                        s ? s->passwd : NULL, label);
    gtk_entry_set_visibility(GTK_ENTRY(fcw->password), FALSE);

    fcw->subscribed = create_check(fcw->dialog, _("Subscribed _folders only"), 
                                  table, 6, mn ? mn->subscribed : FALSE);
    fcw->list_inbox = create_check(fcw->dialog, _("Always show _INBOX"), 
                                  table, 7, mn ? mn->list_inbox : TRUE); 

    label = create_label(_("Pr_efix"), table, 8);
    fcw->prefix = create_entry(fcw->dialog, table, NULL, NULL, 8,
                        mn ? mn->dir : NULL, label);
    
    gtk_widget_show_all(GTK_WIDGET(fcw->dialog));

    validate_folder(NULL, fcw);
    gtk_widget_grab_focus(fcw->folder_name);

    gtk_dialog_set_default_response(fcw->dialog, 
                                    mn ? GTK_RESPONSE_OK 
                                    : GTK_RESPONSE_CANCEL);
    gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);

    g_signal_connect(G_OBJECT(fcw->dialog), "response",
                     G_CALLBACK(folder_conf_response), fcw);
    gtk_widget_show_all(GTK_WIDGET(fcw->dialog));
}

/* folder_conf_imap_sub_node:
   Show name and path for an existing subfolder,
   or create a new one.
*/

static void
validate_sub_folder(GtkWidget * w, SubfolderDialogData * sdd)
{
    BalsaMailboxNode *mn = sdd->parent;
    /*
     * Allow typing in the parent_folder entry box only if we already
     * have the server information in mn:
     */
    gboolean have_server = (mn && mn->server
                      && mn->server->type == LIBBALSA_SERVER_IMAP);
    gtk_editable_set_editable(GTK_EDITABLE(sdd->parent_folder),
                        have_server);
    /*
     * We'll allow a null parent name, although some IMAP servers
     * will deny permission:
     */
    gtk_dialog_set_response_sensitive(sdd->dialog, GTK_RESPONSE_OK, 
                                      have_server &&
                                      *gtk_entry_get_text(GTK_ENTRY
                                                          (sdd->folder_name)));
}

/* callbacks for a `Browse...' button: */

typedef struct _BrowseButtonData BrowseButtonData;
struct _BrowseButtonData {
    SubfolderDialogData *sdd;
    GtkDialog *dialog;
    GtkWidget *button;
    BalsaMailboxNode *mbnode;
};

static void
browse_button_select_row_cb(GtkTreeSelection * selection,
                            BrowseButtonData * bbd)
{
    GtkTreeModel *model;
    GtkTreeIter iter;
    gboolean selected =
        gtk_tree_selection_get_selected(selection, &model, &iter);

    gtk_dialog_set_response_sensitive(bbd->dialog,
                                      GTK_RESPONSE_OK, selected);
    if (selected)
        gtk_tree_model_get(model, &iter, 0, &bbd->mbnode, -1);
    /* bbd->mbnode is unreffed when bbd is freed. */
}

static void
browse_button_row_activated(GtkTreeView * tree_view, GtkTreePath * path,
                            GtkTreeViewColumn * column,
                            BrowseButtonData * bbd)
{
    gtk_dialog_response(bbd->dialog, GTK_RESPONSE_OK);
}

static void
browse_button_response(GtkDialog * dialog, gint response,
                       BrowseButtonData * bbd)
{
    if (response == GTK_RESPONSE_OK) {
        BalsaMailboxNode *mbnode = bbd->mbnode;
        if (!mbnode)
            return;

        bbd->sdd->parent = mbnode;
        if (mbnode->dir)
            gtk_entry_set_text(GTK_ENTRY(bbd->sdd->parent_folder),
                               mbnode->dir);
        if(mbnode->server)
            gtk_label_set_label(GTK_LABEL(bbd->sdd->host_label),
                                mbnode->server->host);
    }
    validate_sub_folder(NULL, bbd->sdd);
    gtk_widget_set_sensitive(bbd->button, TRUE);
    gtk_widget_destroy(GTK_WIDGET(dialog));
}

static gboolean
folder_selection_func(GtkTreeSelection * selection, GtkTreeModel * model,
                  GtkTreePath * path, gboolean path_currently_selected,
                  SubfolderDialogData * sdd)
{
    GtkTreeIter iter;
    BalsaMailboxNode *mbnode;
    gboolean retval;

    gtk_tree_model_get_iter(model, &iter, path);
    gtk_tree_model_get(model, &iter, 0, &mbnode, -1);
    retval = (mbnode->server
            && mbnode->server->type == LIBBALSA_SERVER_IMAP
            && (sdd->mbnode == NULL
              || sdd->mbnode->server == mbnode->server));
    g_object_unref(mbnode);

    return retval;
}

static void
browse_button_data_free(BrowseButtonData *bbd)
{
    if (bbd->mbnode)
      g_object_unref(bbd->mbnode);
    g_free(bbd);
}

static void
browse_button_cb(GtkWidget * widget, SubfolderDialogData * sdd)
{
    GtkWidget *scroll, *dialog;
    GtkRequisition req;
    GtkWidget *tree_view = balsa_mblist_new();
    GtkTreeSelection *selection =
        gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
    BrowseButtonData *bbd;
    /*
     * Make only IMAP nodes selectable:
     */
    gtk_tree_selection_set_select_function(selection,
                                           (GtkTreeSelectionFunc) 
                                           folder_selection_func, sdd,
                                           NULL);

    dialog =
        gtk_dialog_new_with_buttons(_("Select parent folder"),
                                    GTK_WINDOW(sdd->dialog),
                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                    GTK_STOCK_OK, GTK_RESPONSE_OK,
                                    NULL);
    
    scroll = gtk_scrolled_window_new(NULL, NULL);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scroll,
                       TRUE, TRUE, 0);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
                                   GTK_POLICY_AUTOMATIC,
                                   GTK_POLICY_ALWAYS);
    gtk_container_add(GTK_CONTAINER(scroll), tree_view);
    gtk_widget_grab_focus(tree_view);

    bbd = g_new(BrowseButtonData, 1);
    bbd->sdd = sdd;
    bbd->dialog = GTK_DIALOG(dialog);
    bbd->button = widget;
    bbd->mbnode = NULL;
    g_object_weak_ref(G_OBJECT(dialog),
                  (GWeakNotify) browse_button_data_free, bbd);
    g_signal_connect(G_OBJECT(selection), "changed",
                     G_CALLBACK(browse_button_select_row_cb), bbd);
    g_signal_connect(G_OBJECT(tree_view), "row-activated",
                     G_CALLBACK(browse_button_row_activated), bbd);

    /* Force the mailbox list to be a reasonable size. */
    gtk_widget_size_request(tree_view, &req);
    /* don't mess with the width, it gets saved! */
    if (req.height > balsa_app.mw_height)
        req.height = balsa_app.mw_height;
    else if (req.height < balsa_app.mw_height / 2)
        req.height = balsa_app.mw_height / 2;
    gtk_window_set_default_size(GTK_WINDOW(dialog), req.width, req.height);

    /* To prevent multiple dialogs, desensitize the browse button. */
    gtk_widget_set_sensitive(widget, FALSE);
    /* OK button is insensitive until some row is selected. */
    gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
                                      GTK_RESPONSE_OK, FALSE);

    g_signal_connect(G_OBJECT(dialog), "response",
                     G_CALLBACK(browse_button_response), bbd);
    gtk_widget_show_all(GTK_WIDGET(dialog));
}

static gboolean
subfolder_conf_clicked_ok(SubfolderDialogData * sdd)
{
    gchar *parent, *folder;
    gboolean ret = TRUE;

    parent =
        gtk_editable_get_chars(GTK_EDITABLE(sdd->parent_folder), 0, -1);
    folder = gtk_editable_get_chars(GTK_EDITABLE(sdd->folder_name), 0, -1);
    if(balsa_app.debug)
      g_print("sdd->old_parent=%s\nsdd->old_folder=%s\n",
            sdd->old_parent, sdd->old_folder);

    if (sdd->mbnode) {
        /* Views stuff. */
        if (sdd->mbnode->mailbox)
            mailbox_conf_view_check(sdd->mcv, sdd->mbnode->mailbox);
        
        /* rename */
        if ((sdd->old_parent && strcmp(parent, sdd->old_parent)) ||
            (sdd->old_folder && strcmp(folder, sdd->old_folder))) {
            gint button = GTK_RESPONSE_OK;
            if (sdd->old_folder && !strcmp(sdd->old_folder, "INBOX") &&
                (!sdd->old_parent || !*sdd->old_parent)) {
                gchar *msg =
                    g_strdup_printf(_
                                    ("Renaming INBOX is special!\n"
                                     "You will create a subfolder %s in %s\n"
                                     "containing the messages from INBOX.\n"
                                     "INBOX and its subfolders will remain.\n"
                                     "What would you like to do?"),
folder, parent);
                GtkWidget *ask = gtk_dialog_new_with_buttons(_("Question"),
                                                             GTK_WINDOW
                                                             (sdd->dialog),
                                                             GTK_DIALOG_MODAL,
                                                             _
                                                             ("Rename INBOX"),
                                                             GTK_RESPONSE_OK,
                                                             _("Cancel"),
                                                             GTK_RESPONSE_CANCEL,
                                                             NULL);
                gtk_container_add(GTK_CONTAINER(GTK_DIALOG(ask)->vbox),
                                  gtk_label_new(msg));
                g_free(msg);
                button = gtk_dialog_run(GTK_DIALOG(ask));
                gtk_widget_destroy(ask);
            }
            if (button == GTK_RESPONSE_OK) {
                GError* err = NULL;
                /* Close the mailbox before renaming,
                 * otherwise the rescan will try to close it
                 * under its old name.
                 */
                balsa_window_close_mbnode(balsa_app.main_window,
                                          sdd->mbnode);
                if(!libbalsa_imap_rename_subfolder
                   (LIBBALSA_MAILBOX_IMAP(sdd->mbnode->mailbox),
                    parent, folder, sdd->mbnode->subscribed, &err)) {
                    balsa_information(LIBBALSA_INFORMATION_ERROR,
                                      _("Folder rename failed. Reason: %s"),
                                      err ? err->message : "unknown");
                    g_clear_error(&err);
                    ret = FALSE;
                    goto error;
                }
                g_free(sdd->mbnode->dir);
                sdd->mbnode->dir = g_strdup(parent);

                /*  Rescan as little of the tree as possible. */
                if (sdd->old_parent
                    && !strncmp(parent, sdd->old_parent, strlen(parent))) {
                    /* moved it up the tree */
                BalsaMailboxNode *mbnode =
                        balsa_find_dir(sdd->parent->server, parent);
                    if (mbnode) {
                        balsa_mailbox_node_rescan(mbnode);
                  g_object_unref(mbnode);
                } else
                        printf("Parent not found!?\n");
                } else if (sdd->old_parent
                           && !strncmp(parent, sdd->old_parent,
                                       strlen(sdd->old_parent))) {
                    /* moved it down the tree */
                BalsaMailboxNode *mbnode =
                  balsa_find_dir(sdd->parent->server, sdd->old_parent);
                    if (mbnode) {
                        balsa_mailbox_node_rescan(mbnode);
                  g_object_unref(mbnode);
                }
                } else {
                    /* moved it sideways: a chain of folders might
                     * go away, so we'd better rescan from higher up
                     */
                    BalsaMailboxNode *mb = sdd->mbnode->parent;
                    while (!mb->mailbox && mb->parent)
                        mb = mb->parent;
                    balsa_mailbox_node_rescan(mb);
                    balsa_mailbox_node_rescan(sdd->mbnode);
                }
            }
        }
    } else {
        GError *err = NULL;
        /* create and subscribe, if parent was. */
        if(libbalsa_imap_new_subfolder(parent, folder,
                                       sdd->parent->subscribed,
                                       sdd->parent->server, &err)) {
            /* see it as server sees it: */
            balsa_mailbox_node_rescan(sdd->parent);
        } else {
            balsa_information(LIBBALSA_INFORMATION_ERROR,
                              _("Folder creation failed. Reason: %s"),
                              err ? err->message : "unknown");
            g_clear_error(&err);
            ret = FALSE;
        }
    }
 error:
    g_free(parent);
    g_free(folder);
    return ret;
}

/* folder_conf_imap_sub_node:
   show the IMAP Folder configuration dialog for given mailbox node
   representing a sub-folder.
   If mn is NULL, setup it with default values for folder creation.
*/
void
folder_conf_imap_sub_node(BalsaMailboxNode * mn)
{
    GtkWidget *frame, *table, *subtable, *button, *label;
    SubfolderDialogData *sdd;
    static SubfolderDialogData *sdd_new = NULL;

    /* Allow only one dialog per mailbox node, and one with mn == NULL
     * for creating a new subfolder. */
    sdd = mn ? g_object_get_data(G_OBJECT(mn), BALSA_FOLDER_CONF_IMAP_KEY)
             : sdd_new;
    if (sdd) {
        gdk_window_raise(GTK_WIDGET(sdd->dialog)->window);
        return;
    }

    sdd = g_new(SubfolderDialogData, 1);
    sdd->ok = (CommonDialogFunc) subfolder_conf_clicked_ok;

    if ((sdd->mbnode = mn)) {
      /* update */
      if (!mn->mailbox) {
            balsa_information(LIBBALSA_INFORMATION_ERROR,
                              _("An IMAP folder that is not a mailbox\n"
                                "has no properties that can be changed."));
          return;
      }
      sdd->parent = mn->parent;
      sdd->old_folder = mn->mailbox->name;
    } else {
      /* create */
        sdd->old_folder = NULL;
        sdd->parent = NULL;
    }
    sdd->old_parent = sdd->mbnode ? sdd->mbnode->parent->dir : NULL;

    sdd->dialog = 
        GTK_DIALOG(gtk_dialog_new_with_buttons
                   (_("Remote IMAP subfolder"), 
                    GTK_WINDOW(balsa_app.main_window),
                    GTK_DIALOG_DESTROY_WITH_PARENT, /* must NOT be modal */
                    mn ? _("_Update") : _("_Create"), GTK_RESPONSE_OK,
                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 
                    GTK_STOCK_HELP,   GTK_RESPONSE_HELP,
                    NULL));
    g_object_add_weak_pointer(G_OBJECT(sdd->dialog),
                              (gpointer) &sdd->dialog);
    /* `Enter' key => Create: */
    gtk_dialog_set_default_response(GTK_DIALOG(sdd->dialog), GTK_RESPONSE_OK);
    gtk_window_set_wmclass(GTK_WINDOW(sdd->dialog), 
                     "subfolder_config_dialog", "Balsa");

    if (sdd->mbnode) {
        g_object_set_data_full(G_OBJECT(sdd->mbnode),
                               BALSA_FOLDER_CONF_IMAP_KEY, sdd, 
                               (GDestroyNotify) folder_conf_destroy_cdd);
        } else {
        sdd_new = sdd;
        g_object_add_weak_pointer(G_OBJECT(sdd->dialog),
                                  (gpointer) &sdd_new);
    }

    frame = gtk_frame_new(mn ? _("Rename or move subfolder") :
                         _("Create subfolder"));
    gtk_box_pack_start(GTK_BOX(sdd->dialog->vbox),
                       frame, TRUE, TRUE, 0);
    table = gtk_table_new(3, 3, FALSE);
    gtk_container_add(GTK_CONTAINER(frame), table);
 
    /* INPUT FIELD CREATION */
    label= create_label(_("_Folder name:"), table, 0);
    sdd->folder_name = create_entry(sdd->dialog, table,
                                   GTK_SIGNAL_FUNC(validate_sub_folder),
                           sdd, 0, sdd->old_folder, label);

    subtable = gtk_table_new(1, 3, FALSE);
    label = create_label(_("Host:"), table, 1);
    sdd->host_label = 
        gtk_label_new(sdd->mbnode && sdd->mbnode->server
                      ? sdd->mbnode->server->host : "");
    gtk_table_attach(GTK_TABLE(subtable), sdd->host_label, 1, 2, 0, 1,
                 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 5);
    button = gtk_button_new_with_mnemonic(_("_Browse..."));
    g_signal_connect(G_OBJECT(button), "clicked",
                 G_CALLBACK(browse_button_cb), (gpointer) sdd);
    gtk_table_attach(GTK_TABLE(subtable), button, 2, 3, 0, 1,
      GTK_FILL, GTK_FILL, 5, 5);
    gtk_table_attach(GTK_TABLE(table), subtable, 1, 2, 1, 2,
      GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 5);

    label = create_label(_("_Subfolder of:"), table, 2);
    sdd->parent_folder = create_entry(sdd->dialog, table,
                                     GTK_SIGNAL_FUNC(validate_sub_folder),
                             sdd, 2, sdd->old_parent, label);


    if (mn)
        sdd->mcv = mailbox_conf_view_new(mn->mailbox,
                                         GTK_WINDOW(sdd->dialog),
                                         table, 3);

    gtk_widget_show_all(GTK_WIDGET(sdd->dialog));

    validate_sub_folder(NULL, sdd);
    gtk_widget_grab_focus(sdd->folder_name);

    g_signal_connect(G_OBJECT(sdd->dialog), "response",
                     G_CALLBACK(folder_conf_response), sdd);
    gtk_widget_show_all(GTK_WIDGET(sdd->dialog));
}

void
folder_conf_delete(BalsaMailboxNode* mbnode)
{
    GtkWidget* ask;
    gint response;

    if(!mbnode->config_prefix) {
        balsa_information(LIBBALSA_INFORMATION_ERROR,
                        _("This folder is not stored in configuration. "
                          "I do not yet know how to remove it "
                            "from remote server."));
      return;
    }
      
    ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), 0,
                                 GTK_MESSAGE_QUESTION,
                                 GTK_BUTTONS_OK_CANCEL,
                                 _("This will remove the folder "
                                   "\"%s\" from the list.\n"
                                   "You may use \"New IMAP Folder\" "
                                   "later to add this folder again.\n"),
                                 mbnode->name);
    gtk_window_set_title(GTK_WINDOW(ask), _("Confirm"));

    response = gtk_dialog_run(GTK_DIALOG(ask));
    gtk_widget_destroy(ask);
    if(response != GTK_RESPONSE_OK)
      return;

    /* Delete it from the config file and internal nodes */
    config_folder_delete(mbnode);

    /* Remove the node from balsa's mailbox list */
    balsa_mblist_mailbox_node_remove(mbnode);
    update_mail_servers();
}

void
folder_conf_add_imap_cb(GtkWidget * widget, gpointer data)
{
    folder_conf_imap_node(NULL);
}

void
folder_conf_add_imap_sub_cb(GtkWidget * widget, gpointer data)
{
    folder_conf_imap_sub_node(NULL);
}

void
folder_conf_edit_imap_cb(GtkWidget * widget, gpointer data)
{
    folder_conf_imap_node(BALSA_MAILBOX_NODE(data));
}

void
folder_conf_delete_cb(GtkWidget * widget, gpointer data)
{
    folder_conf_delete(BALSA_MAILBOX_NODE(data));
}

Generated by  Doxygen 1.6.0   Back to index