With unintrusive error dialogs gone, we can cut some unnecessary bits
out of EActivity.
I'm also adding a new enum property called "state", which is one of:
E_ACTIVITY_RUNNING
E_ACTIVITY_WAITING
E_ACTIVITY_CANCELLED
E_ACTIVITY_COMPLETED
The state of an activity must be explicitly changed. In particular,
when the user cancels an activity the state should be set only after
confirming the operation has been cancelled and not when cancellation
is requested (e.g. after receiving a G_IO_ERROR_CANCELLED, not when
the GCancellable emits "cancelled"). EActivityBar and EActivityProxy
widgets have been updated to make this distinction clearer in the UI.
E_ACTIVITY_WAITING will be used when activities have to be queued and
dispatched in sequence, which I haven't written yet.
511 lines
14 KiB
C
511 lines
14 KiB
C
/*
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) version 3.
|
|
*
|
|
* 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*
|
|
* Authors:
|
|
* Vivek Jain <jvivek@novell.com>
|
|
*
|
|
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
#include <string.h>
|
|
#include <glib.h>
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n.h>
|
|
#include <e-util/e-config.h>
|
|
#include <e-util/e-account-utils.h>
|
|
#include <mail/e-mail-backend.h>
|
|
#include <mail/em-config.h>
|
|
#include <mail/em-folder-properties.h>
|
|
#include <mail/em-folder-tree.h>
|
|
#include <mail/em-folder-selector.h>
|
|
#include <mail/mail-mt.h>
|
|
#include <mail/mail-vfolder.h>
|
|
#include <mail/em-utils.h>
|
|
#include <mail/em-vfolder-rule.h>
|
|
#include <filter/e-filter-rule.h>
|
|
#include <e-gw-container.h>
|
|
#include <e-gw-connection.h>
|
|
#include <shell/e-shell-sidebar.h>
|
|
#include "share-folder.h"
|
|
#include "gw-ui.h"
|
|
|
|
#define d(x)
|
|
|
|
ShareFolder *common = NULL;
|
|
CamelSession *session;
|
|
struct ShareInfo {
|
|
GtkWidget *d;
|
|
ShareFolder *sf;
|
|
EMFolderTreeModel *model;
|
|
EMFolderSelector *emfs;
|
|
};
|
|
|
|
GtkWidget * org_gnome_shared_folder_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data);
|
|
void shared_folder_commit (EPlugin *ep, EConfigTarget *tget);
|
|
void shared_folder_abort (EPlugin *ep, EConfigTarget *target);
|
|
|
|
static void refresh_folder_tree (EMFolderTreeModel *model, CamelStore *store);
|
|
|
|
static void
|
|
refresh_folder_tree (EMFolderTreeModel *model, CamelStore *store)
|
|
{
|
|
gchar *uri;
|
|
EAccount *account;
|
|
CamelProvider *provider;
|
|
|
|
uri = camel_url_to_string (((CamelService *) store)->url, CAMEL_URL_HIDE_ALL);
|
|
account = e_get_account_by_source_url (uri);
|
|
if (!account) {
|
|
return;
|
|
}
|
|
|
|
uri = account->source->url;
|
|
em_folder_tree_model_remove_store (model, store);
|
|
|
|
provider = camel_provider_get (uri, NULL);
|
|
if (provider == NULL)
|
|
return;
|
|
|
|
if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
|
|
return;
|
|
em_folder_tree_model_add_store (model, store, account->name);
|
|
/* g_object_unref (store); */
|
|
}
|
|
|
|
void
|
|
shared_folder_commit (EPlugin *ep, EConfigTarget *tget)
|
|
{
|
|
EMConfigTargetFolder *target = (EMConfigTargetFolder *)tget->config->target;
|
|
CamelStore *parent_store;
|
|
EMFolderTreeModel *model = em_folder_tree_model_new (); /*mail_component_peek_tree_model (mail_component_peek ());*/
|
|
|
|
parent_store = camel_folder_get_parent_store (target->folder);
|
|
|
|
if (common) {
|
|
share_folder (common);
|
|
refresh_folder_tree (model, parent_store);
|
|
g_object_run_dispose ((GObject *)common);
|
|
common = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
shared_folder_abort (EPlugin *ep, EConfigTarget *target)
|
|
{
|
|
if (common) {
|
|
g_object_run_dispose ((GObject *)common);
|
|
common = NULL;
|
|
}
|
|
}
|
|
|
|
struct _EMCreateFolder {
|
|
MailMsg base;
|
|
|
|
/* input data */
|
|
CamelStore *store;
|
|
gchar *full_name;
|
|
gchar *parent;
|
|
gchar *name;
|
|
|
|
/* output data */
|
|
CamelFolderInfo *fi;
|
|
|
|
/* callback data */
|
|
void (* done) (struct _EMCreateFolder *m, gpointer user_data);
|
|
gpointer user_data;
|
|
};
|
|
|
|
static gchar *
|
|
create_folder_desc (struct _EMCreateFolder *m)
|
|
{
|
|
return g_strdup_printf (_("Creating folder '%s'"), m->full_name);
|
|
}
|
|
|
|
static void
|
|
create_folder_exec (struct _EMCreateFolder *m,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name));
|
|
|
|
if ((m->fi = camel_store_create_folder_sync (
|
|
m->store, m->parent, m->name, cancellable, error))) {
|
|
|
|
if (camel_store_supports_subscriptions (m->store))
|
|
camel_store_subscribe_folder_sync (
|
|
m->store, m->full_name,
|
|
cancellable, error);
|
|
}
|
|
}
|
|
|
|
static void
|
|
create_folder_done (struct _EMCreateFolder *m)
|
|
{
|
|
struct ShareInfo *ssi = (struct ShareInfo *) m->user_data;
|
|
CamelStore *store = CAMEL_STORE (m->store);
|
|
EGwConnection *ccnc;
|
|
|
|
if (m->done) {
|
|
ccnc = get_cnc (store);
|
|
if (E_IS_GW_CONNECTION (ccnc)) {
|
|
(ssi->sf)->cnc = ccnc;
|
|
|
|
(ssi->sf)->container_id = g_strdup (get_container_id ((ssi->sf)->cnc, m->full_name));
|
|
share_folder (ssi->sf);
|
|
}
|
|
|
|
m->done (m, m->user_data);
|
|
}
|
|
}
|
|
|
|
static void
|
|
create_folder_free (struct _EMCreateFolder *m)
|
|
{
|
|
camel_store_free_folder_info (m->store, m->fi);
|
|
g_object_unref (m->store);
|
|
g_free (m->full_name);
|
|
g_free (m->parent);
|
|
g_free (m->name);
|
|
}
|
|
|
|
static MailMsgInfo create_folder_info = {
|
|
sizeof (struct _EMCreateFolder),
|
|
(MailMsgDescFunc) create_folder_desc,
|
|
(MailMsgExecFunc) create_folder_exec,
|
|
(MailMsgDoneFunc) create_folder_done,
|
|
(MailMsgFreeFunc) create_folder_free
|
|
};
|
|
|
|
static void
|
|
new_folder_created_cb (struct _EMCreateFolder *m, gpointer user_data)
|
|
{
|
|
struct ShareInfo *ssi = (struct ShareInfo *) user_data;
|
|
EMFolderSelector *emfs = ssi->emfs;
|
|
if (m->fi) {
|
|
refresh_folder_tree (ssi->model, m->store);
|
|
gtk_widget_destroy ((GtkWidget *) emfs);
|
|
gtk_widget_destroy ((GtkWidget *) ssi->d);
|
|
}
|
|
|
|
g_object_unref (emfs);
|
|
}
|
|
|
|
static gint
|
|
create_folder (CamelStore *store, const gchar *full_name, void (* done) (struct _EMCreateFolder *m, gpointer user_data), gpointer user_data)
|
|
{
|
|
gchar *name, *namebuf = NULL;
|
|
struct _EMCreateFolder *m;
|
|
const gchar *parent;
|
|
gint id;
|
|
|
|
namebuf = g_strdup (full_name);
|
|
if (!(name = strrchr (namebuf, '/'))) {
|
|
name = namebuf;
|
|
parent = "";
|
|
} else {
|
|
*name++ = '\0';
|
|
parent = namebuf;
|
|
}
|
|
|
|
m = mail_msg_new (&create_folder_info);
|
|
g_object_ref (store);
|
|
m->store = store;
|
|
m->full_name = g_strdup (full_name);
|
|
m->parent = g_strdup (parent);
|
|
m->name = g_strdup (name);
|
|
m->user_data = (struct ShareInfo *) user_data;
|
|
m->done = done;
|
|
g_free (namebuf);
|
|
id = m->base.seq;
|
|
mail_msg_unordered_push (m);
|
|
|
|
return id;
|
|
}
|
|
|
|
static void
|
|
users_dialog_response (GtkWidget *dialog, gint response, struct ShareInfo *ssi)
|
|
{
|
|
struct _EMFolderTreeModelStoreInfo *si;
|
|
EMFolderSelector *emfs = ssi->emfs;
|
|
const gchar *uri, *path;
|
|
EMailSession *session;
|
|
CamelStore *store;
|
|
|
|
if (response != GTK_RESPONSE_OK) {
|
|
gtk_widget_destroy ((GtkWidget *) emfs);
|
|
gtk_widget_destroy (dialog);
|
|
return;
|
|
}
|
|
|
|
uri = em_folder_selector_get_selected_uri (emfs);
|
|
path = em_folder_selector_get_selected_path (emfs);
|
|
session = em_folder_tree_get_session (emfs->emft);
|
|
|
|
d(printf ("Creating new folder: %s (%s)\n", path, uri));
|
|
|
|
store = (CamelStore *) camel_session_get_service (
|
|
CAMEL_SESSION (session), uri, CAMEL_PROVIDER_STORE, NULL);
|
|
if (store == NULL)
|
|
return;
|
|
|
|
if (!(si = em_folder_tree_model_lookup_store_info (ssi->model, store))) {
|
|
g_assert_not_reached ();
|
|
g_object_unref (store);
|
|
return;
|
|
}
|
|
|
|
if (CAMEL_IS_VEE_STORE (store)) {
|
|
EFilterRule *rule;
|
|
|
|
rule = em_vfolder_rule_new (session);
|
|
e_filter_rule_set_name (rule, path);
|
|
vfolder_gui_add_rule (EM_VFOLDER_RULE (rule));
|
|
gtk_widget_destroy ((GtkWidget *)emfs);
|
|
} else {
|
|
g_object_ref (emfs);
|
|
ssi->d = dialog;
|
|
create_folder (si->store, path, new_folder_created_cb, ssi);
|
|
|
|
}
|
|
g_object_unref (store);
|
|
}
|
|
|
|
static void
|
|
new_folder_response (EMFolderSelector *emfs, gint response, EMFolderTreeModel *model)
|
|
{
|
|
GtkWidget *users_dialog;
|
|
GtkWidget *content_area;
|
|
GtkWidget *w;
|
|
struct ShareInfo *ssi;
|
|
const gchar *uri;
|
|
EGwConnection *cnc;
|
|
CamelStore *store;
|
|
|
|
ssi = g_new0 (struct ShareInfo, 1);
|
|
if (response != GTK_RESPONSE_OK) {
|
|
gtk_widget_destroy ((GtkWidget *) emfs);
|
|
return;
|
|
}
|
|
|
|
/* i want store at this point to get cnc not sure proper or not*/
|
|
uri = em_folder_selector_get_selected_uri (emfs);
|
|
store = (CamelStore *) camel_session_get_service (
|
|
session, uri, CAMEL_PROVIDER_STORE, NULL);
|
|
if (store == NULL)
|
|
return;
|
|
|
|
cnc = get_cnc (store);
|
|
users_dialog = gtk_dialog_new_with_buttons (
|
|
_("Users"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
|
|
w = gtk_label_new_with_mnemonic (_("Enter the users and set permissions"));
|
|
gtk_widget_show (w);
|
|
content_area = gtk_dialog_get_content_area (GTK_DIALOG (users_dialog));
|
|
gtk_box_pack_start (GTK_BOX (content_area), (GtkWidget *) w, TRUE, TRUE, 6);
|
|
ssi->sf = share_folder_new (cnc, NULL);
|
|
gtk_widget_set_sensitive (GTK_WIDGET ((ssi->sf)->table), TRUE);
|
|
ssi->model = model;
|
|
ssi->emfs = emfs;
|
|
gtk_widget_reparent (GTK_WIDGET ((ssi->sf)->table), content_area);
|
|
gtk_widget_hide ((GtkWidget*) emfs);
|
|
gtk_window_resize (GTK_WINDOW (users_dialog), 350, 300);
|
|
gtk_widget_show (users_dialog);
|
|
g_signal_connect (users_dialog, "response", G_CALLBACK (users_dialog_response), ssi);
|
|
|
|
g_object_unref (store);
|
|
return;
|
|
|
|
}
|
|
|
|
void
|
|
gw_new_shared_folder_cb (GtkAction *action, EShellView *shell_view)
|
|
{
|
|
EMFolderTree *folder_tree;
|
|
EShellBackend *shell_backend;
|
|
EMailSession *session;
|
|
GtkWidget *dialog;
|
|
gchar *uri;
|
|
gpointer parent;
|
|
|
|
parent = e_shell_view_get_shell_window (shell_view);
|
|
shell_backend = e_shell_view_get_shell_backend (shell_view);
|
|
session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
|
|
|
|
folder_tree = (EMFolderTree *) em_folder_tree_new (session);
|
|
emu_restore_folder_tree_state (folder_tree);
|
|
|
|
dialog = em_folder_selector_create_new (parent, folder_tree, 0, _("Create folder"), _("Specify where to create the folder:"));
|
|
uri = em_folder_tree_get_selected_uri (folder_tree);
|
|
if (uri != NULL)
|
|
em_folder_selector_set_selected ((EMFolderSelector *) dialog, uri);
|
|
g_free (uri);
|
|
|
|
g_signal_connect (dialog, "response", G_CALLBACK (new_folder_response), gtk_tree_view_get_model (GTK_TREE_VIEW (folder_tree)));
|
|
gtk_window_set_title (GTK_WINDOW (dialog), "New Shared Folder" );
|
|
gtk_widget_show (dialog);
|
|
}
|
|
|
|
GtkWidget *
|
|
org_gnome_shared_folder_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
|
|
{
|
|
|
|
gchar *folderuri = NULL;
|
|
gchar *account = NULL;
|
|
gchar *id = NULL;
|
|
gchar *folder_name = NULL;
|
|
EGwConnection *cnc;
|
|
ShareFolder *sharing_tab;
|
|
EMConfigTargetFolder *target= (EMConfigTargetFolder *)hook_data->config->target;
|
|
CamelFolder *folder = target->folder;
|
|
|
|
folder_name = g_strdup (camel_folder_get_full_name (folder));
|
|
folderuri = g_strdup (target->uri);
|
|
if (folderuri && folder_name)
|
|
account = g_strrstr(folderuri, "groupwise");
|
|
else
|
|
return NULL;
|
|
|
|
/* This is kind of bad..but we don't have types for all these folders.*/
|
|
|
|
if ( !( strcmp (folder_name, "Mailbox")
|
|
&& strcmp (folder_name, "Calendar")
|
|
&& strcmp (folder_name, "Contacts")
|
|
&& strcmp (folder_name, "Documents")
|
|
&& strcmp (folder_name, "Authored")
|
|
&& strcmp (folder_name, "Default Library")
|
|
&& strcmp (folder_name, "Work In Progress")
|
|
&& strcmp (folder_name, "Cabinet")
|
|
&& strcmp (folder_name, "Sent Items")
|
|
&& strcmp (folder_name, "Trash")
|
|
&& strcmp (folder_name, "Checklist"))) {
|
|
|
|
g_free (folderuri);
|
|
return NULL;
|
|
}
|
|
|
|
if (account) {
|
|
CamelStore *parent_store;
|
|
|
|
parent_store = camel_folder_get_parent_store (folder);
|
|
cnc = get_cnc (parent_store);
|
|
|
|
if (E_IS_GW_CONNECTION (cnc))
|
|
id = get_container_id (cnc, folder_name);
|
|
else
|
|
g_warning("Could not Connnect\n");
|
|
|
|
if (cnc && id)
|
|
sharing_tab = share_folder_new (cnc, id);
|
|
else
|
|
return NULL;
|
|
|
|
gtk_notebook_append_page((GtkNotebook *) hook_data->parent, (GtkWidget *) sharing_tab->vbox, gtk_label_new_with_mnemonic N_("Sharing"));
|
|
common = sharing_tab;
|
|
g_free (folderuri);
|
|
return GTK_WIDGET (sharing_tab);
|
|
} else
|
|
return NULL;
|
|
}
|
|
|
|
EGwConnection *
|
|
get_cnc (CamelStore *store)
|
|
{
|
|
EGwConnection *cnc;
|
|
const gchar *uri, *property_value, *server_name, *user, *port;
|
|
gchar *use_ssl;
|
|
CamelService *service;
|
|
CamelURL *url;
|
|
|
|
if (!store)
|
|
return NULL;
|
|
|
|
service = CAMEL_SERVICE (store);
|
|
url = service->url;
|
|
server_name = g_strdup (url->host);
|
|
user = g_strdup (url->user);
|
|
property_value = camel_url_get_param (url, "soap_port");
|
|
use_ssl = g_strdup (camel_url_get_param (url, "use_ssl"));
|
|
if (property_value == NULL)
|
|
port = g_strdup ("7191");
|
|
else if (strlen (property_value) == 0)
|
|
port = g_strdup ("7191");
|
|
else
|
|
port = g_strdup (property_value);
|
|
|
|
if (use_ssl && !g_str_equal (use_ssl, "never"))
|
|
uri = g_strconcat ("https://", server_name, ":", port, "/soap", NULL);
|
|
else
|
|
uri = g_strconcat ("http://", server_name, ":", port, "/soap", NULL);
|
|
|
|
cnc = e_gw_connection_new (uri, user, service->url->passwd);
|
|
if (!E_IS_GW_CONNECTION(cnc) && use_ssl && g_str_equal (use_ssl, "when-possible")) {
|
|
gchar *http_uri = g_strconcat ("http://", uri + 8, NULL);
|
|
cnc = e_gw_connection_new (http_uri, user, service->url->passwd);
|
|
g_free (http_uri);
|
|
}
|
|
g_free (use_ssl);
|
|
use_ssl = NULL;
|
|
|
|
return cnc;
|
|
|
|
}
|
|
|
|
gchar *
|
|
get_container_id (EGwConnection *cnc, const gchar *fname)
|
|
{
|
|
GList *container_list = NULL;
|
|
gchar *id = NULL;
|
|
gchar *name;
|
|
gchar **names;
|
|
gint i = 0, parts = 0;
|
|
|
|
names = g_strsplit (fname, "/", -1);
|
|
if (names) {
|
|
while (names[parts])
|
|
parts++;
|
|
fname = names[i];
|
|
}
|
|
|
|
/* get list of containers */
|
|
if (e_gw_connection_get_container_list (cnc, "folders", &(container_list)) == E_GW_CONNECTION_STATUS_OK) {
|
|
GList *container = NULL;
|
|
|
|
for (container = container_list; container != NULL; container = container->next) {
|
|
name = g_strdup (e_gw_container_get_name (container->data));
|
|
/* if Null is passed as name then we return top lavel id*/
|
|
if (fname == NULL) {
|
|
id = g_strdup (e_gw_container_get_id (container->data));
|
|
break;
|
|
} else if (!strcmp (name, fname)) {
|
|
if (i == parts - 1) {
|
|
id = g_strdup (e_gw_container_get_id (container->data));
|
|
break;
|
|
} else
|
|
fname = names[++i];
|
|
}
|
|
g_free (name);
|
|
}
|
|
e_gw_connection_free_container_list (container_list);
|
|
}
|
|
|
|
if (names)
|
|
g_strfreev (names);
|
|
return id;
|
|
}
|