"Fossies" - the Fresh Open Source Software archive 
Member "balsa-2.5.0/src/folder-conf.c" of archive balsa-2.5.0.tar.gz:
/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
/* Balsa E-Mail Client
* Copyright (C) 1997-2013 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.
*/
#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include "folder-conf.h"
#include <string.h>
#include "balsa-app.h"
#include "balsa-icons.h"
#include "mailbox-conf.h"
#include "mailbox-node.h"
#include "save-restore.h"
#include "pref-manager.h"
#include "imap-server.h"
#include <glib/gi18n.h>
#if HAVE_MACOSX_DESKTOP
# include "macosx-helpers.h"
#endif
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, *anonymous, *remember,
*password, *subscribed, *list_inbox, *prefix;
GtkWidget *use_ssl, *tls_mode;
GtkWidget *connection_limit, *enable_persistent,
*use_idle, *has_bugs, *use_status;
};
/* 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 void
folder_conf_response(GtkDialog * dialog, int response,
CommonDialogData * cdd)
{
GdkScreen *screen;
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:
screen = gtk_widget_get_screen(GTK_WIDGET(dialog));
gtk_show_uri(screen, "ghelp:balsa?folder-config",
gtk_get_current_event_time(), &err);
if (err) {
balsa_information(LIBBALSA_INFORMATION_WARNING,
_("Error displaying config help: %s\n"),
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
anonymous_cb(GtkToggleButton * button, FolderDialogData * fcw)
{
gtk_widget_set_sensitive(fcw->anonymous,
gtk_toggle_button_get_active(button));
}
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_use_idle
(LIBBALSA_IMAP_SERVER(s),
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->use_idle)));
libbalsa_imap_server_set_bug
(LIBBALSA_IMAP_SERVER(s), ISBUG_FETCH,
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->has_bugs)));
libbalsa_imap_server_set_use_status
(LIBBALSA_IMAP_SERVER(s),
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->use_status)));
libbalsa_server_set_username(s, username);
s->try_anonymous =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->anonymous));
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));
libbalsa_server_set_host(s, host,
balsa_server_conf_get_use_ssl(&fcw->bsc));
libbalsa_server_config_changed(s); /* trigger config save */
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, "config-changed",
G_CALLBACK(config_folder_update),
fcw->mbnode);
update_mail_servers();
} else {
balsa_mailbox_node_rescan(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, *grid, *label, *advanced;
FolderDialogData *fcw;
static FolderDialogData *fcw_new;
LibBalsaServer *s;
gchar *default_server;
int r = 0;
#if defined(HAVE_LIBSECRET)
static const gchar *remember_password_message =
N_("_Remember password in Secret Service");
#elif defined (HAVE_GNOME_KEYRING)
static const gchar *remember_password_message =
N_("_Remember password in keyring");
#else
static const gchar *remember_password_message =
N_("_Remember password");
#endif /* defined(HAVE_LIBSECRET) */
/* 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) {
gtk_window_present(GTK_WINDOW(fcw->dialog));
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));
#if HAVE_MACOSX_DESKTOP
libbalsa_macosx_menu_for_parent(GTK_WIDGET(fcw->dialog), GTK_WINDOW(balsa_app.main_window));
#endif
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(gtk_dialog_get_content_area(fcw->dialog)),
notebook, TRUE, TRUE, 0);
grid = libbalsa_create_grid();
gtk_container_set_border_width(GTK_CONTAINER(grid), 12);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), grid,
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->use_idle =
balsa_server_conf_add_checkbox(&fcw->bsc,
_("Use IDLE command"));
if(s &&
libbalsa_imap_server_get_use_idle(LIBBALSA_IMAP_SERVER(s)))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcw->use_idle),
TRUE);
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);
fcw->use_status =
balsa_server_conf_add_checkbox(&fcw->bsc,
_("Use STATUS for mailbox checking"));
if(s &&
libbalsa_imap_server_get_use_status(LIBBALSA_IMAP_SERVER(s)))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcw->use_status),
TRUE);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced,
gtk_label_new_with_mnemonic(_("_Advanced")));
/* INPUT FIELD CREATION */
label = libbalsa_create_grid_label(_("Descriptive _name:"), grid, 0);
fcw->folder_name =
libbalsa_create_grid_entry(grid, G_CALLBACK(validate_folder),
fcw, r++, mn ? mn->name : NULL,
label);
default_server = libbalsa_guess_imap_server();
label = libbalsa_create_grid_label(_("_Server:"), grid, 1);
fcw->bsc.server =
libbalsa_create_grid_entry(grid, G_CALLBACK(validate_folder),
fcw, r++, s ? s->host : default_server,
label);
fcw->bsc.default_ports = IMAP_DEFAULT_PORTS;
g_free(default_server);
label= libbalsa_create_grid_label(_("Use_r name:"), grid, r);
fcw->username =
libbalsa_create_grid_entry(grid, G_CALLBACK(validate_folder),
fcw, r++, s ? s->user : g_get_user_name(),
label);
label = libbalsa_create_grid_label(_("_Password:"), grid, r);
fcw->password =
libbalsa_create_grid_entry(grid, NULL, NULL, r++,
s ? s->passwd : NULL, label);
gtk_entry_set_visibility(GTK_ENTRY(fcw->password), FALSE);
fcw->anonymous =
libbalsa_create_grid_check(_("_Anonymous access"), grid, r++,
s ? s->try_anonymous : FALSE);
g_signal_connect(G_OBJECT(fcw->anonymous), "toggled",
G_CALLBACK(anonymous_cb), fcw);
fcw->remember =
libbalsa_create_grid_check(_(remember_password_message), grid, r++,
s ? s->remember_passwd : TRUE);
g_signal_connect(G_OBJECT(fcw->remember), "toggled",
G_CALLBACK(remember_cb), fcw);
fcw->subscribed =
libbalsa_create_grid_check(_("Subscribed _folders only"), grid, r++,
mn ? mn->subscribed : FALSE);
fcw->list_inbox =
libbalsa_create_grid_check(_("Always show _INBOX"), grid, r++,
mn ? mn->list_inbox : TRUE);
label = libbalsa_create_grid_label(_("Pr_efix:"), grid, r);
fcw->prefix =
libbalsa_create_grid_entry(grid, NULL, NULL, r++,
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 && LIBBALSA_IS_IMAP_SERVER(mn->server));
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 = (LIBBALSA_IS_IMAP_SERVER(mbnode->server)
&& (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);
#if HAVE_MACOSX_DESKTOP
libbalsa_macosx_menu_for_parent(dialog, GTK_WINDOW(sdd->dialog));
#endif
scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_box_pack_start(GTK_BOX
(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
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_get_preferred_size(tree_view, NULL, &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);
#if HAVE_MACOSX_DESKTOP
libbalsa_macosx_menu_for_parent(ask, GTK_WINDOW(sdd->dialog));
#endif
gtk_container_add(GTK_CONTAINER
(gtk_dialog_get_content_area
(GTK_DIALOG(ask))), 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.
*/
static void
set_ok_sensitive(GtkDialog * dialog)
{
gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_OK, TRUE);
}
void
folder_conf_imap_sub_node(BalsaMailboxNode * mn)
{
GtkWidget *content, *grid, *button, *label, *hbox;
SubfolderDialogData *sdd;
static SubfolderDialogData *sdd_new = NULL;
guint row;
/* 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) {
gtk_window_present(GTK_WINDOW(sdd->dialog));
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."));
g_free(sdd);
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));
#if HAVE_MACOSX_DESKTOP
libbalsa_macosx_menu_for_parent(GTK_WIDGET(sdd->dialog), GTK_WINDOW(balsa_app.main_window));
#endif
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);
}
grid = libbalsa_create_grid();
#if GTK_CHECK_VERSION(3, 2, 0)
gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
gtk_grid_set_column_spacing(GTK_GRID(grid), 12);
#else /* GTK_CHECK_VERSION(3, 2, 0) */
gtk_grid_set_row_spacing(GTK_GRID(grid), 12);
gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
#endif /* GTK_CHECK_VERSION(3, 2, 0) */
gtk_container_set_border_width(GTK_CONTAINER(grid), 12);
if (mn)
content = grid;
else {
content = gtk_frame_new(_("Create subfolder"));
gtk_container_add(GTK_CONTAINER(content), grid);
}
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(sdd->dialog)),
content, TRUE, TRUE, 0);
row = 0;
/* INPUT FIELD CREATION */
label= libbalsa_create_grid_label(_("_Folder name:"), grid, row);
sdd->folder_name =
libbalsa_create_grid_entry(grid, G_CALLBACK(validate_sub_folder),
sdd, row, sdd->old_folder, label);
++row;
label = libbalsa_create_grid_label(_("Host:"), grid, row);
sdd->host_label =
gtk_label_new(sdd->mbnode && sdd->mbnode->server
? sdd->mbnode->server->host : "");
gtk_widget_set_halign(sdd->host_label, GTK_ALIGN_START);
gtk_widget_set_hexpand(sdd->host_label, TRUE);
gtk_grid_attach(GTK_GRID(grid), sdd->host_label, 1, row, 1, 1);
++row;
label = libbalsa_create_grid_label(_("Subfolder of:"), grid, row);
sdd->parent_folder = gtk_entry_new();
gtk_editable_set_editable(GTK_EDITABLE(sdd->parent_folder), FALSE);
gtk_entry_set_text(GTK_ENTRY(sdd->parent_folder), sdd->old_parent);
button = gtk_button_new_with_mnemonic(_("_Browse..."));
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(browse_button_cb), (gpointer) sdd);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
gtk_widget_set_hexpand(hbox, TRUE);
gtk_box_pack_start(GTK_BOX(hbox), sdd->parent_folder, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
gtk_grid_attach(GTK_GRID(grid), hbox, 1, row, 1, 1);
if (!mn)
validate_sub_folder(NULL, sdd);
else {
static const char *std_acls[] = {
"lrs", N_("read-only"),
"lrswipkxte", N_("read-write"),
"lrswipkxtea", N_("admin"),
"lrsp", N_("post"),
"lrsip", N_("append"),
"lrxte", N_("delete"),
NULL, N_("special") };
GString *rights_str;
gchar * rights;
gchar * quotas;
++row;
label = libbalsa_create_grid_label(_("Permissions:"), grid, row);
/* mailbox closed: no detailed permissions available */
if (!libbalsa_mailbox_imap_is_connected(LIBBALSA_MAILBOX_IMAP(mn->mailbox))) {
rights_str = g_string_new(std_acls[mn->mailbox->readonly ? 1 : 3]);
rights_str =
g_string_append(rights_str,
_("\ndetailed permissions are available only for open folders"));
} else {
rights = libbalsa_imap_get_rights(LIBBALSA_MAILBOX_IMAP(mn->mailbox));
if (!rights) {
rights_str = g_string_new(std_acls[mn->mailbox->readonly ? 1 : 3]);
rights_str =
g_string_append(rights_str,
_("\nthe server does not support ACL's"));
} else {
gint n;
gchar **acls;
/* my rights */
for (n = 0;
std_acls[n] && strcmp(std_acls[n], rights);
n += 2);
rights_str = g_string_new(_("mine: "));
if (std_acls[n])
rights_str = g_string_append(rights_str, std_acls[n + 1]);
else
g_string_append_printf(rights_str, "%s (%s)",
std_acls[n + 1], rights);
/* acl's - only available if I have admin privileges */
if ((acls =
libbalsa_imap_get_acls(LIBBALSA_MAILBOX_IMAP(mn->mailbox)))) {
int uid;
for (uid = 0; acls[uid]; uid += 2) {
for (n = 0;
std_acls[n] && strcmp(std_acls[n], acls[uid + 1]);
n += 2);
if (std_acls[n])
g_string_append_printf(rights_str,
"\nuid '%s': %s",
acls[uid], std_acls[n + 1]);
else
g_string_append_printf(rights_str,
"\nuid '%s': %s (%s)",
acls[uid], std_acls[n + 1],
acls[uid + 1]);
}
g_strfreev(acls);
}
g_free(rights);
}
}
rights = g_string_free(rights_str, FALSE);
label = gtk_label_new(rights);
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_grid_attach(GTK_GRID(grid), label, 1, row, 1, 1);
g_free(rights);
++row;
label = libbalsa_create_grid_label(_("Quota:"), grid, row);
/* mailbox closed: no quota available */
if (!libbalsa_mailbox_imap_is_connected(LIBBALSA_MAILBOX_IMAP(mn->mailbox)))
quotas = g_strdup(_("quota information available only for open folders"));
else {
gulong max, used;
if (!libbalsa_imap_get_quota(LIBBALSA_MAILBOX_IMAP(mn->mailbox), &max, &used))
quotas = g_strdup(_("the server does not support quotas"));
else if (max == 0 && used == 0)
quotas = g_strdup(_("no limits"));
else {
gchar *use_str = libbalsa_size_to_gchar(used * G_GUINT64_CONSTANT(1024));
gchar *max_str = libbalsa_size_to_gchar(max * G_GUINT64_CONSTANT(1024));
quotas = g_strdup_printf(_("%s of %s (%.1f%%) used"), use_str, max_str,
100.0 * (float) used / (float) max);
g_free(use_str);
g_free(max_str);
}
}
label = gtk_label_new(quotas);
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_widget_set_hexpand(label, TRUE);
gtk_grid_attach(GTK_GRID(grid), label, 1, row, 1, 1);
g_free(quotas);
sdd->mcv = mailbox_conf_view_new(mn->mailbox,
GTK_WINDOW(sdd->dialog),
grid, 5,
G_CALLBACK(set_ok_sensitive));
}
gtk_widget_show_all(GTK_WIDGET(sdd->dialog));
gtk_widget_grab_focus(sdd->folder_name);
g_signal_connect(G_OBJECT(sdd->dialog), "response",
G_CALLBACK(folder_conf_response), sdd);
gtk_dialog_set_response_sensitive(GTK_DIALOG(sdd->dialog),
GTK_RESPONSE_OK, FALSE);
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);
#if HAVE_MACOSX_DESKTOP
libbalsa_macosx_menu_for_parent(ask, GTK_WINDOW(balsa_app.main_window));
#endif
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));
}