Files
evolution/plugins/groupwise-features/share-folder-common.c
Matthew Barnes c881b5bc5e Simplify EActivity.
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.
2010-10-22 14:21:22 -04:00

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;
}