aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivasa Ragavan <sragavan@novell.com>2007-12-17 04:19:53 +0800
committerSrinivasa Ragavan <sragavan@src.gnome.org>2007-12-17 04:19:53 +0800
commit5b89cbe4f598387a56d22627558b5308da6044bc (patch)
tree620d37062cec0df7cbfa107d8317b62fb28ce9ee
parent9bf01a179e346a25967a0898c900c863ed7b95db (diff)
downloadgsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.tar
gsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.tar.gz
gsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.tar.bz2
gsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.tar.lz
gsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.tar.xz
gsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.tar.zst
gsoc2013-evolution-5b89cbe4f598387a56d22627558b5308da6044bc.zip
** Non-intrusive errror reporting and basic logging support.
2007-12-17 Srinivasa Ragavan <sragavan@novell.com> ** Non-intrusive errror reporting and basic logging support. * em-folder-browser.c: (emfb_help_debug): Invoke the debug menu. * evolution-mail.schemas.in: Schema for error timeout and level. * mail-component.c: (mail_component_init), (render_pixbuf), (render_level), (render_date), (append_logs), (spin_value_changed), (mail_component_show_logger): Handle the lifecycle of the logger. * mail-component.h: Api to show the logger. * mail-config.c: (gconf_error_time_changed), (gconf_error_level_changed), (mail_config_init), (mail_config_get_error_timeout), (mail_config_get_error_level): Load and get the error time and level. * mail-config.h: * mail-mt.c: (mail_msg_set_cancelable), (mail_msg_new), (end_event_callback), (mail_msg_free), (mail_msg_check_error), (operation_cancel), (do_op_status): Revamp the error handling. * mail-mt.h: * mail-ops.c: (send_queue_send), (mail_send_queue): Handle the send/receive case of error reporting separately. * mail-send-recv.c: (free_send_info), (mail_send): 2007-12-17 Srinivasa Ragavan <sragavan@novell.com> ** Revamped Activity handler and task bar/widget for non-intrusive error reporting * e-activity-handler.c: (activity_info_new), (activity_info_free), (task_widget_new_from_activity_info), (setup_task_bar), (e_activity_handler_init), (e_activity_handler_set_error_flush_time), (e_activity_handler_set_logger), (cancel_wrapper), (e_activity_handler_cancelable_operation_started), (e_activity_handler_operation_started), (handle_error), (error_cleanup), (e_activity_handler_make_error), (e_activity_handler_operation_set_error), (e_activity_handler_operation_progressing), (e_activity_handler_operation_finished): * e-activity-handler.h: * e-task-bar.c: (e_task_bar_prepend_task), (e_task_bar_remove_task_from_id), (e_task_bar_remove_task), (e_task_bar_get_task_widget_from_id): * e-task-bar.h: * e-task-widget.c: (e_task_widget_init), (button_press_event_cb), (prepare_popup), (e_task_widget_construct), (e_task_widget_new_with_cancel), (e_task_widget_new), (e_task_widget_update_image): * e-task-widget.h: 2007-12-17 Srinivasa Ragavan <sragavan@novell.com> * Makefile.am: Add e-logger.[ch] to compilation * e-error.c: (e_error_newv): Add primary/secondary text to the error dialog to the gobject as data. * e-logger.[ch]: A new logger provision Evolution. 2007-12-17 Srinivasa Ragavan <sragavan@novell.com> * evolution-mail-global.xml: Add Debug Log menu item for mailer. * evolution.xml: Add place holder for Debug menu item. svn path=/trunk/; revision=34712
-rw-r--r--e-util/ChangeLog7
-rw-r--r--e-util/Makefile.am2
-rw-r--r--e-util/e-error.c22
-rw-r--r--e-util/e-logger.c173
-rw-r--r--e-util/e-logger.h64
-rw-r--r--mail/ChangeLog23
-rw-r--r--mail/em-folder-browser.c7
-rw-r--r--mail/evolution-mail.schemas.in28
-rw-r--r--mail/mail-component.c229
-rw-r--r--mail/mail-component.h1
-rw-r--r--mail/mail-config.c44
-rw-r--r--mail/mail-config.h2
-rw-r--r--mail/mail-mt.c44
-rw-r--r--mail/mail-mt.h1
-rw-r--r--mail/mail-ops.c17
-rw-r--r--mail/mail-send-recv.c5
-rw-r--r--ui/ChangeLog5
-rw-r--r--ui/evolution-mail-global.xml8
-rw-r--r--ui/evolution.xml1
-rw-r--r--widgets/misc/ChangeLog27
-rw-r--r--widgets/misc/e-activity-handler.c300
-rw-r--r--widgets/misc/e-activity-handler.h21
-rw-r--r--widgets/misc/e-task-bar.c59
-rw-r--r--widgets/misc/e-task-bar.h4
-rw-r--r--widgets/misc/e-task-widget.c101
-rw-r--r--widgets/misc/e-task-widget.h14
26 files changed, 1166 insertions, 43 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index 3d07500de2..f33a5bef7a 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -1,3 +1,10 @@
+2007-12-17 Srinivasa Ragavan <sragavan@novell.com>
+
+ * Makefile.am: Add e-logger.[ch] to compilation
+ * e-error.c: (e_error_newv): Add primary/secondary text to the error
+ dialog to the gobject as data.
+ * e-logger.[ch]: A new logger provision Evolution.
+
2007-12-05 Srinivasa Ragavan <sragavan@novell.com>
* e-util.h: Fix a compiler warning
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index 8ae7c41aa8..3031358452 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -56,6 +56,7 @@ eutilinclude_HEADERS = \
e-html-utils.h \
e-icon-factory.h \
e-import.h \
+ e-logger.h \
e-menu.h \
e-mktemp.h \
e-print.h \
@@ -94,6 +95,7 @@ libeutil_la_SOURCES = \
e-html-utils.c \
e-icon-factory.c \
e-import.c \
+ e-logger.c \
e-menu.c \
e-mktemp.c \
e-plugin.c \
diff --git a/e-util/e-error.c b/e-util/e-error.c
index 94ad35f31a..007d910f0d 100644
--- a/e-util/e-error.c
+++ b/e-util/e-error.c
@@ -419,10 +419,10 @@ e_error_newv(GtkWindow *parent, const char *tag, const char *arg0, va_list ap)
struct _e_error_button *b;
GtkWidget *hbox, *w, *scroll=NULL;
char *tmp, *domain, *id;
- GString *out;
+ GString *out, *oerr;
GPtrArray *args;
GtkDialog *dialog;
- gchar *str;
+ gchar *str, *perr=NULL, *serr=NULL;
if (error_table == NULL)
ee_load_tables();
@@ -529,11 +529,19 @@ e_error_newv(GtkWindow *parent, const char *tag, const char *arg0, va_list ap)
g_string_append(out, "<span weight=\"bold\" size=\"larger\">");
ee_build_label(out, dgettext(table->translation_domain, e->primary), args);
g_string_append(out, "</span>\n\n");
+ oerr = g_string_new("");
+ ee_build_label(oerr, dgettext(table->translation_domain, e->primary), args);
+ perr = g_strdup (oerr->str);
+ g_string_free (oerr, TRUE);
}
-
- if (e->secondary)
+
+ if (e->secondary) {
ee_build_label(out, dgettext(table->translation_domain, e->secondary), args);
-
+ oerr = g_string_new("");
+ ee_build_label(oerr, dgettext(table->translation_domain, e->secondary), args);
+ serr = g_strdup (oerr->str);
+ g_string_free (oerr, TRUE);
+ }
g_ptr_array_free(args, TRUE);
if (e->scroll) {
@@ -556,7 +564,9 @@ e_error_newv(GtkWindow *parent, const char *tag, const char *arg0, va_list ap)
gtk_widget_show_all(hbox);
gtk_box_pack_start((GtkBox *)dialog->vbox, hbox, TRUE, TRUE, 0);
-
+ g_object_set_data_full ((GObject *) dialog, "primary", perr, g_free);
+ g_object_set_data_full ((GObject *) dialog, "secondary", serr, g_free);
+
return (GtkWidget *)dialog;
}
diff --git a/e-util/e-logger.c b/e-util/e-logger.c
new file mode 100644
index 0000000000..369f7ea90d
--- /dev/null
+++ b/e-util/e-logger.c
@@ -0,0 +1,173 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Srinivasa Ragavan <sragavan@gnome.org>
+ *
+ *
+ * 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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "e-logger.h"
+#include "e-mktemp.h"
+
+/* 5 Minutes */
+#define TIMEOUT_INTERVAL 300000
+
+static GObjectClass *parent;
+
+struct _ELoggerPrivate {
+ char *component;
+ char *logfile;
+ FILE *fp;
+
+ guint timer;
+};
+
+static gboolean
+flush_logfile (ELogger *el)
+{
+ fflush (el->priv->fp);
+ el->priv->timer = 0;
+
+ return FALSE;
+}
+
+static void
+el_init(GObject *o)
+{
+ ELogger *l = (ELogger *) o;
+ ELoggerPrivate *priv;
+
+ priv = g_new (ELoggerPrivate, 1);
+ priv->logfile = NULL;
+ priv->fp = NULL;
+ l->priv=priv;
+}
+
+static void
+el_finalise(GObject *o)
+{
+ ELogger *el = (ELogger *) o;
+ ELoggerPrivate *priv = el->priv;
+
+ if (priv->timer)
+ g_source_remove (priv->timer);
+ flush_logfile (el);
+ fclose (el->priv->fp);
+ g_free (el->priv);
+ ((GObjectClass *)parent)->finalize(o);
+}
+
+static void
+el_class_init(GObjectClass *klass)
+{
+ klass->finalize = el_finalise;
+
+}
+
+GType
+e_logger_get_type(void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof(ELoggerClass),
+ NULL, NULL,
+ (GClassInitFunc)el_class_init,
+ NULL, NULL,
+ sizeof(ELogger), 0,
+ (GInstanceInitFunc)el_init
+ };
+ parent = g_type_class_ref(G_TYPE_OBJECT);
+ type = g_type_register_static(G_TYPE_OBJECT, "ELogger", &info, 0);
+ }
+
+ return type;
+}
+
+
+ELogger *e_logger_create(char *component)
+{
+ ELogger *el = g_object_new(e_logger_get_type(), 0);
+ ELoggerPrivate *priv;
+ char *tmp;
+
+ tmp = g_strdup_printf("%s.log.XXXXXX", component);
+ priv = el->priv;
+ priv->component = g_strdup (component);
+ priv->logfile = e_mktemp (tmp);
+ g_free (tmp);
+ priv->fp = g_fopen (priv->logfile, "w");
+
+ priv->timer = 0;
+ return el;
+}
+
+
+
+static void set_dirty (ELogger *el)
+{
+ if (el->priv->timer)
+ return;
+
+ el->priv->timer = g_timeout_add (TIMEOUT_INTERVAL, (GSourceFunc) flush_logfile, el);
+}
+
+void
+e_logger_log (ELogger *el, int level, char *primary, char *secondary)
+{
+ time_t t = time (NULL);
+
+ fprintf(el->priv->fp, "%d:%ld:%s\n", level, t, primary);
+ fprintf(el->priv->fp, "%d:%ld:%s\n", level, t, secondary);
+ set_dirty (el);
+}
+
+void
+e_logger_get_logs (ELogger *el, ELogFunction func, gpointer data)
+{
+ FILE *fp;
+ char buf[250];
+ gboolean error = FALSE;
+
+ /* Flush everything before we get the logs */
+ fflush (el->priv->fp);
+ fp = g_fopen (el->priv->logfile, "r");
+ while (!error || feof(fp)) {
+ char *tmp;
+ tmp = fgets (buf, 250, fp);
+ if (!tmp)
+ break;
+#if 0
+ if (strlen(tmp) == 249) {
+ /* FIXME: There may be more */
+ }
+#endif
+ func (tmp, data);
+ }
+ fclose(fp);
+}
+
diff --git a/e-util/e-logger.h b/e-util/e-logger.h
new file mode 100644
index 0000000000..0dc8b53921
--- /dev/null
+++ b/e-util/e-logger.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Srinivasa Ragavan <sragavan@gnome.org>
+ *
+ *
+ * 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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __E_LOGGER_H__
+#define __E_LOGGER_H__
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+typedef struct _ELogger ELogger;
+typedef struct _ELoggerClass ELoggerClass;
+typedef struct _ELoggerPrivate ELoggerPrivate;
+
+typedef void (* ELogFunction) (char *line, gpointer data);
+
+enum e_log_level_t {
+ E_LOG_ERROR,
+ E_LOG_WARNINGS,
+ E_LOG_DEBUG
+};
+
+/* The object */
+struct _ELogger {
+ GObject parent;
+
+ struct _ELoggerPrivate *priv;
+};
+
+struct _ELoggerClass {
+ GObjectClass popup_class;
+};
+
+GType e_logger_get_type(void);
+ELogger *e_logger_create(char *component);
+void e_logger_log (ELogger *el, int level, char *primary, char *secondary);
+void e_logger_get_logs (ELogger *el, ELogFunction func, gpointer data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __E_LOGGER_H__ */
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 5228a70f7e..6e488e1ee7 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,26 @@
+2007-12-17 Srinivasa Ragavan <sragavan@novell.com>
+
+ ** Non-intrusive errror reporting and basic logging support.
+
+ * em-folder-browser.c: (emfb_help_debug): Invoke the debug menu.
+ * evolution-mail.schemas.in: Schema for error timeout and level.
+ * mail-component.c: (mail_component_init), (render_pixbuf),
+ (render_level), (render_date), (append_logs), (spin_value_changed),
+ (mail_component_show_logger): Handle the lifecycle of the logger.
+ * mail-component.h: Api to show the logger.
+ * mail-config.c: (gconf_error_time_changed),
+ (gconf_error_level_changed), (mail_config_init),
+ (mail_config_get_error_timeout), (mail_config_get_error_level): Load
+ and get the error time and level.
+ * mail-config.h:
+ * mail-mt.c: (mail_msg_set_cancelable), (mail_msg_new),
+ (end_event_callback), (mail_msg_free), (mail_msg_check_error),
+ (operation_cancel), (do_op_status): Revamp the error handling.
+ * mail-mt.h:
+ * mail-ops.c: (send_queue_send), (mail_send_queue): Handle the send/receive
+ case of error reporting separately.
+ * mail-send-recv.c: (free_send_info), (mail_send):
+
2007-12-15 Matthew Barnes <mbarnes@redhat.com>
* em-folder-tree-model.c (emft_model_unread_count_changed),
diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c
index 83193f42e8..e3e35ab3c0 100644
--- a/mail/em-folder-browser.c
+++ b/mail/em-folder-browser.c
@@ -1550,6 +1550,12 @@ emfb_focus_search(BonoboUIComponent *uid, void *data, const char *path)
}
static void
+emfb_help_debug (BonoboUIComponent *uid, void *data, const char *path)
+{
+ mail_component_show_logger ((GtkWidget *) data);
+}
+
+static void
emfb_tools_vfolders(BonoboUIComponent *uid, void *data, const char *path)
{
/* FIXME: rename/refactor this */
@@ -1583,6 +1589,7 @@ static BonoboUIVerb emfb_verbs[] = {
BONOBO_UI_UNSAFE_VERB ("FolderRefresh", emfb_folder_refresh),
BONOBO_UI_UNSAFE_VERB ("FolderRename", emfb_folder_rename),
BONOBO_UI_UNSAFE_VERB ("FolderCreate", emfb_folder_create),
+ BONOBO_UI_UNSAFE_VERB ("HelpDebug", emfb_help_debug),
BONOBO_UI_UNSAFE_VERB ("MailPost", emfb_mail_post),
BONOBO_UI_UNSAFE_VERB ("MailStop", emfb_mail_stop),
diff --git a/mail/evolution-mail.schemas.in b/mail/evolution-mail.schemas.in
index ffba439eb9..d4fc65a618 100644
--- a/mail/evolution-mail.schemas.in
+++ b/mail/evolution-mail.schemas.in
@@ -918,6 +918,34 @@
</locale>
</schema>
+ <schema>
+ <key>/schemas/apps/evolution/mail/display/error_timeout</key>
+ <applyto>/apps/evolution/mail/display/error_timeout</applyto>
+ <owner>evolution-mail</owner>
+ <type>int</type>
+ <default>60</default>
+ <locale name="C">
+ <short>Amount of time in seconds the error should be showed on the status bar.</short>
+ <long>
+ Amount of time in seconds the error should be showed on the status bar.
+ </long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/evolution/mail/display/error_level</key>
+ <applyto>/apps/evolution/mail/display/error_level</applyto>
+ <owner>evolution-mail</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>Level beyond which it should the message should be logged.</short>
+ <long> This can have three possible values. 0 for errors. 1 for warnings.
+ 2 for debug messages.
+ </long>
+ </locale>
+ </schema>
+
+
<!-- Labels and Colours -->
<schema>
diff --git a/mail/mail-component.c b/mail/mail-component.c
index 9c2fd80524..b8ff1c2df9 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -46,10 +46,12 @@
#include "em-folder-selection.h"
#include "em-folder-utils.h"
#include "em-migrate.h"
+#include "e-util/e-icon-factory.h"
#include "misc/e-info-label.h"
#include "e-util/e-error.h"
#include "e-util/e-util-private.h"
+#include "e-util/e-logger.h"
#include "em-search-context.h"
#include "mail-config.h"
@@ -139,6 +141,7 @@ struct _MailComponentPrivate {
char *context_path; /* current path for right-click menu */
CamelStore *local_store;
+ ELogger *logger;
EComponentView *component_view;
};
@@ -481,6 +484,7 @@ impl_finalize (GObject *object)
g_free (priv->context_path);
g_mutex_free(priv->lock);
+ g_object_unref (priv->logger);
g_free (priv);
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
@@ -1205,8 +1209,10 @@ mail_component_init (MailComponent *component)
abort ();
priv->model = em_folder_tree_model_new (priv->base_directory);
-
+ priv->logger = e_logger_create ("mail");
priv->activity_handler = e_activity_handler_new ();
+ e_activity_handler_set_logger (priv->activity_handler, priv->logger);
+ e_activity_handler_set_error_flush_time (priv->activity_handler, mail_config_get_error_timeout ()*1000);
mail_session_init (priv->base_directory);
@@ -1495,4 +1501,225 @@ mail_indicate_new_mail (gboolean have_new_mail)
e_component_view_set_button_icon (mc->priv->component_view, icon);
}
+struct _log_data {
+ int level;
+ char *key;
+ char *text;
+ char *icon;
+ GdkPixbuf *pbuf;
+} ldata [] = {
+ { E_LOG_ERROR, N_("Error"), N_("Errors"), "stock_dialog-error" },
+ { E_LOG_WARNINGS, N_("Warning"), N_("Warnings and Errors"), "stock_dialog-warning" },
+ { E_LOG_DEBUG, N_("Debug"), N_("Error, Warnings and Debug messages"), "stock_dialog-info" }
+};
+
+enum
+{
+ COL_LEVEL = 0,
+ COL_TIME,
+ COL_DATA
+};
+
+static void
+render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
+{
+ static gboolean initialised = FALSE;
+ gint level;
+ int i;
+
+ if (!initialised) {
+ for (i=E_LOG_ERROR; i<=E_LOG_DEBUG; i++) {
+ ldata[i].pbuf = e_icon_factory_get_icon (ldata[i].icon, E_ICON_SIZE_MENU);
+ }
+ initialised = TRUE;
+ }
+
+ gtk_tree_model_get (model, iter, COL_LEVEL, &level, -1);
+ g_object_set (renderer, "pixbuf", ldata[level].pbuf, "visible", TRUE, NULL);
+}
+
+static void
+render_level (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
+{
+ gint level;
+
+ gtk_tree_model_get (model, iter, COL_LEVEL, &level, -1);
+ g_object_set (renderer, "text", ldata[level].key, NULL);
+}
+
+static void
+render_date (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
+{
+ time_t t;
+ char sdt[100]; /* Should be sufficient? */
+
+ gtk_tree_model_get (model, iter, COL_TIME, &t, -1);
+ strftime (sdt, 100, "%x %X", localtime (&t));
+ g_object_set (renderer, "text", sdt, NULL);
+}
+
+
+
+static void
+append_logs (const char *txt, GtkListStore *store)
+{
+ char **str;
+
+ str = g_strsplit (txt, ":", 3);
+ if (str[0] && str[1] && str[2]) {
+ int level;
+ time_t time;
+ char *data;
+ GtkTreeIter iter;
+
+ level = atoi (str[0]);
+ time = atol (str[1]);
+ data = strrchr (str[2], '\n');
+ *data = 0;
+ data = str[2];
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ COL_LEVEL, level,
+ COL_TIME, time,
+ COL_DATA, data,
+ -1);
+ } else
+ printf("Unable to decode error log: %s\n", txt);
+
+ g_strfreev (str);
+
+
+}
+
+static void
+spin_value_changed (GtkSpinButton *b, gpointer data)
+{
+ int value = gtk_spin_button_get_value_as_int (b);
+ GConfClient *client = mail_config_get_gconf_client ();
+
+ gconf_client_set_int (client, "/apps/evolution/mail/display/error_timeout", value, NULL);
+}
+
+void
+mail_component_show_logger (gpointer top)
+{
+ MailComponent *mc = mail_component_peek ();
+ GtkWidget *window, *hbox, *vbox, *spin, *label, *combo, *scrolled;
+ ELogger *logger = mc->priv->logger;
+ int i;
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+ GtkTreeView *treeview;
+ GtkTreeViewColumn *column;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_transient_for ((GtkWindow *) window, (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) top));
+ gtk_container_set_border_width ((GtkContainer *) window, 6);
+
+ gtk_window_set_title ((GtkWindow *) window, _("Debug Logs"));
+ vbox = gtk_vbox_new (FALSE, 6);
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_container_add ((GtkContainer *) window, vbox);
+ label = gtk_label_new_with_mnemonic (_("Show _errors in the status bar for"));
+ gtk_box_pack_start ((GtkBox *) hbox, label, FALSE, FALSE, 6);
+ spin = gtk_spin_button_new_with_range(1.0, 60.0, 1.0);
+ gtk_spin_button_set_value ((GtkSpinButton *) spin, (double) mail_config_get_error_timeout ());
+ g_signal_connect (spin, "value-changed", G_CALLBACK (spin_value_changed), NULL);
+ gtk_label_set_mnemonic_widget ((GtkLabel *) label, spin);
+ gtk_box_pack_start ((GtkBox *) hbox, spin, FALSE, FALSE, 6);
+ label = gtk_label_new_with_mnemonic (_("seconds."));
+ gtk_box_pack_start ((GtkBox *) hbox, label, FALSE, FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 6);
+
+ combo = gtk_combo_box_new_text ();
+ for (i = E_LOG_ERROR; i <=E_LOG_DEBUG; i++)
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), ldata[i].text);
+ gtk_combo_box_set_active ((GtkComboBox *) combo, mail_config_get_error_level ());
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ label = gtk_label_new_with_mnemonic (_("Log Messages:"));
+ gtk_label_set_mnemonic_widget ((GtkLabel *) label, combo);
+ gtk_box_pack_start ((GtkBox *) hbox, label, FALSE, FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) hbox, combo, FALSE, FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 6);
+
+ store = gtk_list_store_new(3, G_TYPE_INT, G_TYPE_LONG, G_TYPE_STRING);
+ e_logger_get_logs (logger, (ELogFunction) append_logs, store);
+ if (0)
+ {
+ GtkTreeIter iter;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ COL_LEVEL, 0,
+ COL_TIME, "21/12/07 10:55 PM",
+ COL_DATA, "Error Refreshing Folder",
+ -1);
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ COL_LEVEL, 1,
+ COL_TIME, "21/12/07 10:55 PM",
+ COL_DATA, "Error refreshing folder",
+ -1);
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ COL_LEVEL, 2,
+ COL_TIME, "21/12/07 10:55 PM",
+ COL_DATA, "Error refreshing folder",
+ -1);
+ }
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (store),
+ COL_TIME, GTK_SORT_DESCENDING);
+
+
+ treeview = (GtkTreeView *)gtk_tree_view_new();
+ gtk_tree_view_set_rules_hint ((GtkTreeView *) treeview, TRUE);
+ gtk_tree_view_set_reorderable(GTK_TREE_VIEW(treeview), FALSE);
+ gtk_tree_view_set_model(treeview, GTK_TREE_MODEL (store));
+ gtk_tree_view_set_search_column(treeview, COL_DATA);
+ gtk_tree_view_set_headers_visible(treeview, TRUE);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column ((GtkTreeView *) treeview, column);
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, render_pixbuf, NULL, NULL);
+
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column ((GtkTreeView *) treeview, column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_title (column, _("Log Level"));
+ gtk_tree_view_column_set_cell_data_func (column, renderer, render_level, NULL, NULL);
+
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column ((GtkTreeView *) treeview, column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_set_title (column, _("Time"));
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, render_date, NULL, NULL);
+
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1, _("Messages"),
+ renderer, "text", COL_DATA,
+ NULL);
+
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
+
+ gtk_container_add (GTK_CONTAINER (scrolled), (GtkWidget *) treeview);
+
+ gtk_box_pack_start ((GtkBox *) vbox, (GtkWidget *) scrolled, TRUE, TRUE, 6);
+ gtk_widget_show_all (window);
+}
+
BONOBO_TYPE_FUNC_FULL (MailComponent, GNOME_Evolution_MailComponent, PARENT_TYPE, mail_component)
diff --git a/mail/mail-component.h b/mail/mail-component.h
index e5c5a29e6f..b2d96d1761 100644
--- a/mail/mail-component.h
+++ b/mail/mail-component.h
@@ -101,5 +101,6 @@ const char *mail_component_get_folder_uri(MailComponent *mc, enum _mail_componen
int status_check (GNOME_Evolution_ShellState shell_state);
void mail_indicate_new_mail (gboolean have_new_mail);
+void mail_component_show_logger (gpointer);
#endif /* _MAIL_COMPONENT_H_ */
diff --git a/mail/mail-config.c b/mail/mail-config.c
index f10ac3e868..a59128b9f1 100644
--- a/mail/mail-config.c
+++ b/mail/mail-config.c
@@ -112,6 +112,10 @@ typedef struct {
gint mlimit_size;
guint magic_spacebar_notify_id;
gboolean magic_spacebar;
+ guint error_time;
+ guint error_notify_id;
+ guint error_level;
+ guint error_level_id;
GPtrArray *mime_types;
guint mime_types_notify_id;
@@ -340,6 +344,20 @@ gconf_address_count_changed (GConfClient *client, guint cnxn_id,
}
static void
+gconf_error_time_changed (GConfClient *client, guint cnxn_id,
+ GConfEntry *entry, gpointer user_data)
+{
+ config->error_time = gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/error_timeout", NULL);
+}
+
+static void
+gconf_error_level_changed (GConfClient *client, guint cnxn_id,
+ GConfEntry *entry, gpointer user_data)
+{
+ config->error_level = gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/error_level", NULL);
+}
+
+static void
gconf_address_compress_changed (GConfClient *client, guint cnxn_id,
GConfEntry *entry, gpointer user_data)
{
@@ -403,6 +421,11 @@ mail_config_init (void)
gconf_address_compress_changed, NULL, NULL, NULL);
config->font_notify_id = gconf_client_notify_add (config->gconf, "/apps/evolution/mail/display/address_count",
gconf_address_count_changed, NULL, NULL, NULL);
+ config->error_notify_id = gconf_client_notify_add (config->gconf, "/apps/evolution/mail/display/error_timeout",
+ gconf_error_time_changed, NULL, NULL, NULL);
+ config->error_level_id = gconf_client_notify_add (config->gconf, "/apps/evolution/mail/display/error_level",
+ gconf_error_level_changed, NULL, NULL, NULL);
+
config->mlimit_notify_id = gconf_client_notify_add (config->gconf, "/apps/evolution/mail/display/force_message_limit",
gconf_mlimit_changed, NULL, NULL, NULL);
config->mlimit_size_notify_id = gconf_client_notify_add (config->gconf, "/apps/evolution/mail/display/message_text_part_limit",
@@ -432,6 +455,9 @@ mail_config_init (void)
config_cache_mime_types ();
config->address_compress = gconf_client_get_bool (config->gconf, "/apps/evolution/mail/display/address_compress", NULL);
config->address_count = gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/address_count", NULL);
+ config->error_time = gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/error_timeout", NULL);
+ config->error_level= gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/error_level", NULL);
+
config->mlimit = gconf_client_get_bool (config->gconf, "/apps/evolution/mail/display/force_message_limit", NULL);
config->mlimit_size = gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/message_text_part_limit", NULL);
config->magic_spacebar = gconf_client_get_bool (config->gconf, "/apps/evolution/mail/display/magic_spacebar", NULL);
@@ -576,6 +602,24 @@ mail_config_get_address_count (void)
return config->address_count;
}
+guint
+mail_config_get_error_timeout (void)
+{
+ if (!config)
+ mail_config_init ();
+
+ return config->error_time;
+}
+
+guint
+mail_config_get_error_level (void)
+{
+ if (!config)
+ mail_config_init ();
+
+ return config->error_level;
+}
+
int
mail_config_get_message_limit (void)
{
diff --git a/mail/mail-config.h b/mail/mail-config.h
index 698cb74399..3d159fe7e1 100644
--- a/mail/mail-config.h
+++ b/mail/mail-config.h
@@ -162,6 +162,8 @@ void mail_config_uri_deleted (GCompareFunc uri_cmp, const char *uri);
/* static utility functions */
char *mail_config_folder_to_cachename (struct _CamelFolder *folder, const char *prefix);
char *mail_config_folder_to_safe_url (struct _CamelFolder *folder);
+guint mail_config_get_error_timeout (void);
+guint mail_config_get_error_level (void);
GType evolution_mail_config_get_type (void);
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index 9572d3cd3f..af5dfd741d 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -67,6 +67,8 @@ struct _mail_msg_priv {
int activity_state; /* sigh sigh sigh, we need to keep track of the state external to the
pointer itself for locking/race conditions */
int activity_id;
+ GtkWidget *error;
+ gboolean cancelable;
};
static GdkPixbuf *progress_icon = NULL;
@@ -88,6 +90,11 @@ MailAsyncEvent *mail_async_event;
static void mail_msg_destroy(EThread *e, EMsg *msg, void *data);
+void mail_msg_set_cancelable (struct _mail_msg *msg, gboolean status)
+{
+ msg->priv->cancelable = status;
+}
+
void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
{
struct _mail_msg *msg;
@@ -129,6 +136,7 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
msg->cancel = camel_operation_new(mail_operation_status, GINT_TO_POINTER(msg->seq));
camel_exception_init(&msg->ex);
msg->priv = g_malloc0(sizeof(*msg->priv));
+ msg->priv->cancelable = TRUE;
g_hash_table_insert(mail_msg_active_table, GINT_TO_POINTER(msg->seq), msg);
@@ -144,12 +152,18 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
}
-static void end_event_callback (CamelObject *o, void *event_data, void *data)
+static void end_event_callback (CamelObject *o, void *event_data, void *error)
{
EActivityHandler *activity_handler = mail_component_peek_activity_handler (mail_component_peek ());
guint activity_id = GPOINTER_TO_INT (event_data);
- e_activity_handler_operation_finished (activity_handler, activity_id);
+ if (!error) {
+ e_activity_handler_operation_finished (activity_handler, activity_id);
+ } else {
+ d(printf("Yahooooo, we got it nonintrusively\n"));
+ e_activity_handler_operation_set_error (activity_handler, activity_id, error);
+
+ }
}
@@ -181,6 +195,7 @@ void mail_msg_free(void *msg)
{
struct _mail_msg *m = msg;
int activity_id;
+ GtkWidget *error = NULL;
#ifdef MALLOC_CHECK
checkmem(m);
@@ -212,11 +227,18 @@ void mail_msg_free(void *msg)
return;
} else {
activity_id = m->priv->activity_id;
+ error = m->priv->error;
+ if (error && !activity_id) {
+ e_activity_handler_make_error (mail_component_peek_activity_handler (mail_component_peek ()), "mail",
+ g_object_get_data ((GObject *) error, "primary"), error);
+ printf("Making error\n");
+ }
+
}
MAIL_MT_UNLOCK(mail_msg_lock);
- if (m->cancel) {
+ if (m->cancel && m->cancel != -1) {
camel_operation_mute(m->cancel);
camel_operation_unref(m->cancel);
}
@@ -228,7 +250,7 @@ void mail_msg_free(void *msg)
if (activity_id != 0)
mail_async_event_emit(mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback,
- NULL, GINT_TO_POINTER (activity_id), NULL);
+ NULL, GINT_TO_POINTER (activity_id), error);
}
/* hash table of ops->dialogue of active errors */
@@ -286,7 +308,10 @@ void mail_msg_check_error(void *msg)
g_hash_table_insert(active_errors, m->ops, gd);
g_signal_connect(gd, "response", G_CALLBACK(error_response), m->ops);
g_signal_connect(gd, "destroy", G_CALLBACK(error_destroy), m->ops);
- gtk_widget_show((GtkWidget *)gd);
+ if (m->priv->cancelable)
+ m->priv->error = gd;
+ else
+ gtk_widget_show((GtkWidget *)gd);
}
void mail_msg_cancel(unsigned int msgid)
@@ -927,6 +952,12 @@ void mail_disable_stop(void)
MAIL_MT_UNLOCK(status_lock);
}
+static void
+operation_cancel (CamelOperation *p)
+{
+ camel_operation_cancel (p);
+}
+
/* ******************************************************************************** */
struct _op_status_msg {
@@ -995,8 +1026,7 @@ static void do_op_status(struct _mail_msg *mm)
what = g_strdup("");
}
-
- data->activity_id = e_activity_handler_operation_started (activity_handler, "evolution-mail", progress_icon, what, TRUE);
+ data->activity_id = e_activity_handler_cancelable_operation_started (activity_handler, "evolution-mail", progress_icon, what, TRUE, operation_cancel, msg->cancel);
g_free (what);
MAIL_MT_LOCK (mail_msg_lock);
diff --git a/mail/mail-mt.h b/mail/mail-mt.h
index 61a8aedf50..a508b87d46 100644
--- a/mail/mail-mt.h
+++ b/mail/mail-mt.h
@@ -64,6 +64,7 @@ int mail_msg_active(unsigned int msgid);
void *mail_cancel_hook_add(GDestroyNotify func, void *data);
void mail_cancel_hook_remove(void *handle);
void mail_cancel_all(void);
+void mail_msg_set_cancelable (struct _mail_msg *msg, gboolean status);
/* request a string/password */
char *mail_get_password (CamelService *service, const char *prompt,
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 6d02a3108d..46a781f9ac 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -724,6 +724,11 @@ send_queue_send(struct _mail_msg *mm)
if (m->cancel)
camel_operation_register (m->cancel);
+ else
+ camel_operation_register (mm->cancel);
+
+ if (!m->cancel)
+ camel_operation_start (NULL, _("Sending message"));
camel_exception_init (&ex);
@@ -734,6 +739,8 @@ send_queue_send(struct _mail_msg *mm)
int pc = (100 * i) / send_uids->len;
report_status (m, CAMEL_FILTER_STATUS_START, pc, _("Sending message %d of %d"), i+1, send_uids->len);
+ if (!m->cancel)
+ camel_operation_progress (NULL, (i+1) * 100 / send_uids->len);
mail_send_message (m->queue, send_uids->pdata[i], m->destination, m->driver, &ex);
if (camel_exception_is_set (&ex)) {
@@ -779,9 +786,15 @@ send_queue_send(struct _mail_msg *mm)
camel_folder_sync (sent_folder, FALSE, &ex);
camel_exception_clear (&ex);
}
+
+ if (!m->cancel)
+ camel_operation_end (NULL);
if (m->cancel)
camel_operation_unregister (m->cancel);
+ else
+ camel_operation_unregister (mm->cancel);
+
}
static void
@@ -830,6 +843,10 @@ mail_send_queue(CamelFolder *queue, const char *destination,
if (cancel) {
m->cancel = cancel;
camel_operation_ref(cancel);
+ camel_operation_unref (((struct _mail_msg *) m)->cancel);
+ mail_msg_set_cancelable ((struct _mail_msg *)m, FALSE);
+
+ ((struct _mail_msg *) m)->cancel = NULL;
}
m->status = status;
m->status_data = status_data;
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index 9ed205087b..9c20da4634 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -149,7 +149,8 @@ static void
free_send_info(struct _send_info *info)
{
g_free(info->uri);
- camel_operation_unref(info->cancel);
+ if (info->cancel)
+ camel_operation_unref(info->cancel);
if (info->timeout_id != 0)
g_source_remove(info->timeout_id);
g_free(info->what);
@@ -1187,7 +1188,7 @@ mail_send (void)
info->status_label = NULL;
info->uri = g_strdup (transport->url);
info->keep = FALSE;
- info->cancel = camel_operation_new (operation_status, info);
+ info->cancel = NULL;
info->cancel_button = NULL;
info->data = data;
info->state = SEND_ACTIVE;
diff --git a/ui/ChangeLog b/ui/ChangeLog
index ffd5e04441..5cb22f0872 100644
--- a/ui/ChangeLog
+++ b/ui/ChangeLog
@@ -1,3 +1,8 @@
+2007-12-17 Srinivasa Ragavan <sragavan@novell.com>
+
+ * evolution-mail-global.xml: Add Debug Log menu item for mailer.
+ * evolution.xml: Add place holder for Debug menu item.
+
2007-12-15 Matthew Barnes <mbarnes@redhat.com>
* evolution.xml:
diff --git a/ui/evolution-mail-global.xml b/ui/evolution-mail-global.xml
index a2c00fae50..4da50367cd 100644
--- a/ui/evolution-mail-global.xml
+++ b/ui/evolution-mail-global.xml
@@ -42,6 +42,8 @@
type="radio" group="preview_display" _tip="Show message preview side-by-side with the message list"/>
<cmd name="PrepareForOffline" _label="_Download Messages for Offline Usage" _tip="Download messages of accounts/folders marked for offline"/>
+ <cmd name="HelpDebug" _tip="View the debug console for log messages"/>
+
</commands>
<keybindings>
@@ -124,7 +126,11 @@
</submenu>
</placeholder>
-
+ <submenu name="Help" _label="_Help">
+ <placeholder name="PlaceHolderDebug">
+ <menuitem name="HelpDebug" verb="" _label="_Debug Logs"/>
+ </placeholder>
+ </submenu>
</menu>
<dockitem name="Toolbar">
diff --git a/ui/evolution.xml b/ui/evolution.xml
index b232097a31..b17f6050ce 100644
--- a/ui/evolution.xml
+++ b/ui/evolution.xml
@@ -161,6 +161,7 @@
_label="_Quick Reference"/>
<separator f="" name="eshell2"/>
+ <placeholder name="PlaceHolderDebug"/>
<menuitem name="HelpOpenFAQ" verb=""
_label="Evolution _FAQ"/>
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog
index 78e8a29da4..bc3cef32dd 100644
--- a/widgets/misc/ChangeLog
+++ b/widgets/misc/ChangeLog
@@ -1,3 +1,30 @@
+2007-12-17 Srinivasa Ragavan <sragavan@novell.com>
+
+ ** Revamped Activity handler and task bar/widget for non-intrusive
+ error reporting
+
+ * e-activity-handler.c: (activity_info_new), (activity_info_free),
+ (task_widget_new_from_activity_info), (setup_task_bar),
+ (e_activity_handler_init),
+ (e_activity_handler_set_error_flush_time),
+ (e_activity_handler_set_logger), (cancel_wrapper),
+ (e_activity_handler_cancelable_operation_started),
+ (e_activity_handler_operation_started), (handle_error),
+ (error_cleanup), (e_activity_handler_make_error),
+ (e_activity_handler_operation_set_error),
+ (e_activity_handler_operation_progressing),
+ (e_activity_handler_operation_finished):
+ * e-activity-handler.h:
+ * e-task-bar.c: (e_task_bar_prepend_task),
+ (e_task_bar_remove_task_from_id), (e_task_bar_remove_task),
+ (e_task_bar_get_task_widget_from_id):
+ * e-task-bar.h:
+ * e-task-widget.c: (e_task_widget_init), (button_press_event_cb),
+ (prepare_popup), (e_task_widget_construct),
+ (e_task_widget_new_with_cancel), (e_task_widget_new),
+ (e_task_widget_update_image):
+ * e-task-widget.h:
+
2007-12-05 Matthew Barnes <mbarnes@redhat.com>
** Fixes part of bug #392747 (extra cleanup work)
diff --git a/widgets/misc/e-activity-handler.c b/widgets/misc/e-activity-handler.c
index b9351878a6..305d2cc5f3 100644
--- a/widgets/misc/e-activity-handler.c
+++ b/widgets/misc/e-activity-handler.c
@@ -45,6 +45,10 @@ struct _ActivityInfo {
gboolean cancellable;
double progress;
GtkWidget *menu;
+ void (*cancel_func) (gpointer data);
+ gpointer data;
+ gpointer error;
+ time_t error_time;
};
typedef struct _ActivityInfo ActivityInfo;
@@ -52,12 +56,18 @@ struct _EActivityHandlerPrivate {
guint next_activity_id;
GList *activity_infos;
GSList *task_bars;
+ ELogger *logger;
+ guint error_timer;
+ guint error_flush_interval;
+
};
G_DEFINE_TYPE (EActivityHandler, e_activity_handler, G_TYPE_OBJECT)
/* Utility functions. */
+static void handle_error (ETaskWidget *task);
+
static unsigned int
get_new_activity_id (EActivityHandler *activity_handler)
{
@@ -126,12 +136,14 @@ activity_info_new (const char *component_id,
info = g_new (ActivityInfo, 1);
info->component_id = g_strdup (component_id);
info->id = id;
- info->icon_pixbuf = g_object_ref (icon);
+ info->icon_pixbuf = icon ? g_object_ref (icon): NULL;
info->information = g_strdup (information);
info->cancellable = cancellable;
info->progress = -1.0; /* (Unknown) */
info->menu = NULL;
-
+ info->error = NULL;
+ info->cancel_func = NULL;
+
return info;
}
@@ -140,7 +152,8 @@ activity_info_free (ActivityInfo *info)
{
g_free (info->component_id);
- g_object_unref (info->icon_pixbuf);
+ if (info->icon_pixbuf)
+ g_object_unref (info->icon_pixbuf);
g_free (info->information);
if (info->menu != NULL)
@@ -153,10 +166,13 @@ static ETaskWidget *
task_widget_new_from_activity_info (ActivityInfo *activity_info)
{
GtkWidget *widget;
+ ETaskWidget *etw;
- widget = e_task_widget_new (activity_info->icon_pixbuf,
+ widget = e_task_widget_new_with_cancel (activity_info->icon_pixbuf,
activity_info->component_id,
- activity_info->information);
+ activity_info->information, activity_info->cancel_func, activity_info->data);
+ etw = (ETaskWidget *) widget;
+ etw->id = activity_info->id;
gtk_widget_show (widget);
g_signal_connect (widget, "button_press_event",
@@ -179,8 +195,21 @@ setup_task_bar (EActivityHandler *activity_handler,
priv = activity_handler->priv;
for (p = g_list_last (priv->activity_infos); p != NULL; p = p->prev) {
- e_task_bar_prepend_task (task_bar,
- task_widget_new_from_activity_info ((ActivityInfo *) p->data));
+ ActivityInfo *info = p->data;
+ ETaskWidget *task_widget = task_widget_new_from_activity_info (info);
+ task_widget->id = info->id;
+ e_task_bar_prepend_task (task_bar, task_widget);
+ if (info->error) {
+ /* Prepare to handle existing errors*/
+ GtkWidget *tool;
+
+ tool = e_task_widget_update_image (task_widget, "stock_dialog-warning", g_object_get_data (info->error, "error"));
+ g_object_set_data ((GObject *) task_widget, "tool", tool);
+ g_object_set_data ((GObject *) task_widget, "error", info->error);
+ g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler);
+ g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(info->id));
+ g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget);
+ }
}
}
@@ -260,7 +289,9 @@ e_activity_handler_init (EActivityHandler *activity_handler)
priv->next_activity_id = 1;
priv->activity_infos = NULL;
priv->task_bars = NULL;
-
+ priv->logger = NULL;
+ priv->error_timer = 0;
+ priv->error_flush_interval = 0;
activity_handler->priv = priv;
}
@@ -272,6 +303,17 @@ e_activity_handler_new (void)
}
void
+e_activity_handler_set_error_flush_time (EActivityHandler *handler, int time)
+{
+ handler->priv->error_flush_interval = time;
+}
+void
+e_activity_handler_set_logger (EActivityHandler *handler, ELogger *logger)
+{
+ handler->priv->logger = logger;
+}
+
+void
e_activity_handler_set_message (EActivityHandler *activity_handler,
const char *message)
{
@@ -316,7 +358,93 @@ e_activity_handler_attach_task_bar (EActivityHandler *activity_handler,
setup_task_bar (activity_handler, task_bar);
}
+struct _cancel_wdata {
+ EActivityHandler *handler;
+ ActivityInfo *info;
+ guint id;
+ void (*cancel)(gpointer);
+ gpointer data;
+};
+
+static void
+cancel_wrapper (gpointer pdata)
+{
+ struct _cancel_wdata *data = (struct _cancel_wdata *) pdata;
+ /* This can be invoked in two scenario. Either to cancel or to hide error */
+ if (data->info->error) {
+ /* Hide the error */
+ EActivityHandler *handler = data->handler;
+ int order, len;
+ GSList *sp;
+ GList *p = lookup_activity (handler->priv->activity_infos, data->id, &order);
+ e_logger_log (handler->priv->logger, E_LOG_ERROR, g_object_get_data (data->info->error, "primary"),
+ g_object_get_data (data->info->error, "secondary"));
+ gtk_widget_destroy (data->info->error);
+ printf("%p %p %d\n", data->info->error, data->info, data->info->id);
+ data->info->error = NULL;
+ for (sp = handler->priv->task_bars; sp != NULL; sp = sp->next) {
+ ETaskBar *task_bar;
+
+ task_bar = E_TASK_BAR (sp->data);
+ e_task_bar_remove_task_from_id (task_bar, data->info->id);
+ }
+ activity_info_free (data->info);
+ len = g_list_length (handler->priv->activity_infos);
+ handler->priv->activity_infos = g_list_remove_link (handler->priv->activity_infos, p);
+ if (len == 1)
+ handler->priv->activity_infos = NULL;
+ } else {
+ /* Cancel the operation */
+ data->cancel (data->data);
+ }
+ /* No need to free the data. It will be freed as part of the task widget destroy */
+}
+
/* CORBA methods. */
+guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler,
+ const char *component_id,
+ GdkPixbuf *icon_pixbuf,
+ const char *information,
+ gboolean cancellable,
+ void (*cancel_func)(gpointer),
+ gpointer user_data)
+{
+ EActivityHandlerPrivate *priv;
+ ActivityInfo *activity_info;
+ unsigned int activity_id;
+ GSList *p;
+ struct _cancel_wdata *data;
+ gboolean bfree = FALSE;
+ priv = activity_handler->priv;
+
+ activity_id = get_new_activity_id (activity_handler);
+ activity_info = activity_info_new (component_id, activity_id, icon_pixbuf, information, cancellable);
+
+ data = g_new(struct _cancel_wdata, 1);
+ data->handler = activity_handler;
+ data->id = activity_id;
+ data->info = activity_info;
+ data->cancel = cancel_func;
+ data->data = user_data;
+
+ activity_info->cancel_func = cancel_wrapper;
+ activity_info->data = data;
+ for (p = priv->task_bars; p != NULL; p = p->next) {
+ ETaskWidget *tw = task_widget_new_from_activity_info (activity_info);
+ tw->id = activity_id;
+ if (!bfree) {
+ /* The data will be freed part of the widget destroy */
+ g_object_set_data_full ((GObject *) tw, "free-data", data, g_free);
+ bfree = TRUE;
+ }
+ e_task_bar_prepend_task (E_TASK_BAR (p->data), tw);
+ }
+
+ priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
+
+ return activity_id;
+
+}
guint
e_activity_handler_operation_started (EActivityHandler *activity_handler,
@@ -337,16 +465,162 @@ e_activity_handler_operation_started (EActivityHandler *activity_handler,
activity_info = activity_info_new (component_id, activity_id, icon_pixbuf, information, cancellable);
for (p = priv->task_bars; p != NULL; p = p->next) {
- e_task_bar_prepend_task (E_TASK_BAR (p->data),
- task_widget_new_from_activity_info (activity_info));
+ ETaskWidget *tw = task_widget_new_from_activity_info (activity_info);
+ tw->id = activity_id;
+ e_task_bar_prepend_task (E_TASK_BAR (p->data), tw);
+ }
+
+ priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
+
+ return activity_id;
+}
+
+static void
+handle_error (ETaskWidget *task)
+{
+ GtkWidget *tool, *error;
+ EActivityHandler *activity_handler;
+ guint id;
+
+ tool = g_object_get_data ((GObject *) task, "tool");
+ error = g_object_get_data ((GObject *) task, "error");
+ activity_handler = g_object_get_data ((GObject *) task, "activity-handler");
+ id = GPOINTER_TO_UINT (g_object_get_data ((GObject *) task, "activity"));
+ e_activity_handler_operation_finished (activity_handler, id);
+ gtk_widget_show (error);
+ e_logger_log (activity_handler->priv->logger, E_LOG_ERROR, g_object_get_data ((GObject *) error, "primary"),
+ g_object_get_data ((GObject *) error, "secondary"));
+}
+
+static gboolean
+error_cleanup (EActivityHandler *activity_handler)
+{
+ EActivityHandlerPrivate *priv = activity_handler->priv;
+ GList *p, *node;
+ GSList *sp;
+ int i;
+ time_t now = time (NULL);
+ gboolean berror = FALSE;
+
+ for (p = priv->activity_infos, i = 0; p != NULL; i++) {
+ ActivityInfo *info;
+
+ info = (ActivityInfo *) p->data;
+ if (info->error)
+ berror = TRUE;
+ if (info->error && info->error_time && (now - info->error_time) > 5 ) {
+ /* Error older than wanted time. So cleanup */
+ e_logger_log (priv->logger, E_LOG_ERROR, g_object_get_data (info->error, "primary"),
+ g_object_get_data (info->error, "secondary"));
+ gtk_widget_destroy (info->error);
+ node = p;
+ p = p->next;
+
+ for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
+ ETaskBar *task_bar;
+
+ task_bar = E_TASK_BAR (sp->data);
+ e_task_bar_remove_task_from_id (task_bar, info->id);
+ }
+ activity_info_free (info);
+ priv->activity_infos = g_list_remove_link (priv->activity_infos, node);
+
+ } else
+ p = p->next;
+ }
+ if (!berror)
+ priv->error_timer = 0;
+ return berror;
+}
+
+guint
+e_activity_handler_make_error (EActivityHandler *activity_handler,
+ const char *component_id,
+ const char *information,
+ GtkWidget *error)
+{
+ EActivityHandlerPrivate *priv;
+ ActivityInfo *activity_info;
+ unsigned int activity_id;
+ GSList *p;
+
+ priv = activity_handler->priv;
+
+ activity_id = get_new_activity_id (activity_handler);
+
+ activity_info = activity_info_new (component_id, activity_id, NULL, information, TRUE);
+ activity_info->error = error;
+ activity_info->error_time = time (NULL);
+
+ for (p = priv->task_bars; p != NULL; p = p->next) {
+ ETaskBar *task_bar;
+ ETaskWidget *task_widget;
+ GtkWidget *tool;
+
+ task_bar = E_TASK_BAR (p->data);
+ task_widget = task_widget_new_from_activity_info (activity_info);
+ task_widget->id = activity_id;
+ e_task_bar_prepend_task (E_TASK_BAR (p->data), task_widget);
+
+ tool = e_task_widget_update_image (task_widget, "stock_dialog-warning", g_object_get_data ((GObject *) error, "primary"));
+ g_object_set_data ((GObject *) task_widget, "tool", tool);
+ g_object_set_data ((GObject *) task_widget, "error", error);
+ g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler);
+ g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(activity_id));
+ g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget);
}
priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
+ if (!activity_handler->priv->error_timer)
+ activity_handler->priv->error_timer = g_timeout_add (activity_handler->priv->error_flush_interval, (GSourceFunc)error_cleanup, activity_handler);
+
return activity_id;
}
void
+e_activity_handler_operation_set_error(EActivityHandler *activity_handler,
+ guint activity_id,
+ GtkWidget *error)
+{
+ EActivityHandlerPrivate *priv = activity_handler->priv;
+ ActivityInfo *activity_info;
+ GList *p;
+ GSList *sp;
+ int order_number;
+
+ p = lookup_activity (priv->activity_infos, activity_id, &order_number);
+ if (p == NULL) {
+ g_warning ("EActivityHandler: unknown operation %d", activity_id);
+ return;
+ }
+
+ activity_info = (ActivityInfo *) p->data;
+ activity_info->error = error;
+ activity_info->error_time = time (NULL);
+ for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
+ ETaskBar *task_bar;
+ ETaskWidget *task_widget;
+ GtkWidget *tool;
+
+ task_bar = E_TASK_BAR (sp->data);
+ task_widget = e_task_bar_get_task_widget_from_id (task_bar, activity_info->id);
+ if (!task_widget)
+ continue;
+
+ tool = e_task_widget_update_image (task_widget, "stock_dialog-warning", g_object_get_data ((GObject *) error, "primary"));
+ g_object_set_data ((GObject *) task_widget, "tool", tool);
+ g_object_set_data ((GObject *) task_widget, "error", error);
+ g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler);
+ g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(activity_id));
+ g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget);
+ }
+
+ if (!activity_handler->priv->error_timer)
+ activity_handler->priv->error_timer = g_timeout_add (activity_handler->priv->error_flush_interval, (GSourceFunc) error_cleanup, activity_handler);
+}
+
+void
e_activity_handler_operation_progressing (EActivityHandler *activity_handler,
guint activity_id,
const char *information,
@@ -376,7 +650,9 @@ e_activity_handler_operation_progressing (EActivityHandler *activity_handler,
ETaskWidget *task_widget;
task_bar = E_TASK_BAR (sp->data);
- task_widget = e_task_bar_get_task_widget (task_bar, order_number);
+ task_widget = e_task_bar_get_task_widget_from_id (task_bar, activity_info->id);
+ if (!task_widget)
+ continue;
e_task_widget_update (task_widget, information, progress);
}
@@ -404,7 +680,7 @@ e_activity_handler_operation_finished (EActivityHandler *activity_handler,
ETaskBar *task_bar;
task_bar = E_TASK_BAR (sp->data);
- e_task_bar_remove_task (task_bar, order_number);
+ e_task_bar_remove_task_from_id (task_bar, activity_id);
}
}
diff --git a/widgets/misc/e-activity-handler.h b/widgets/misc/e-activity-handler.h
index 304882fe57..619359bf28 100644
--- a/widgets/misc/e-activity-handler.h
+++ b/widgets/misc/e-activity-handler.h
@@ -24,7 +24,7 @@
#define _E_ACTIVITY_HANDLER_H_
#include "e-task-bar.h"
-
+#include "e-util/e-logger.h"
#include <glib-object.h>
#ifdef __cplusplus
@@ -71,6 +71,13 @@ guint e_activity_handler_operation_started (EActivityHandler *activity_handler
GdkPixbuf *icon_pixbuf,
const char *information,
gboolean cancellable);
+guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler,
+ const char *component_id,
+ GdkPixbuf *icon_pixbuf,
+ const char *information,
+ gboolean cancellable,
+ void (*cancel_func)(gpointer),
+ gpointer user_data);
void e_activity_handler_operation_progressing (EActivityHandler *activity_handler,
guint activity_id,
@@ -80,6 +87,18 @@ void e_activity_handler_operation_progressing (EActivityHandler *activity_hand
void e_activity_handler_operation_finished (EActivityHandler *activity_handler,
guint activity_id);
+void e_activity_handler_set_logger (EActivityHandler *handler, ELogger *logger);
+guint e_activity_handler_make_error (EActivityHandler *activity_handler,
+ const char *component_id,
+ const char *information,
+ GtkWidget *error);
+void
+e_activity_handler_operation_set_error (EActivityHandler *activity_handler,
+ guint activity_id,
+ GtkWidget *error);
+
+void
+e_activity_handler_set_error_flush_time (EActivityHandler *handler, int time);
#ifdef __cplusplus
}
diff --git a/widgets/misc/e-task-bar.c b/widgets/misc/e-task-bar.c
index 075322dd97..ff18cf7bdb 100644
--- a/widgets/misc/e-task-bar.c
+++ b/widgets/misc/e-task-bar.c
@@ -40,6 +40,7 @@ struct _ETaskBarPrivate
G_DEFINE_TYPE (ETaskBar, e_task_bar, GTK_TYPE_HBOX)
+#if 0
static void
reduce_displayed_activities_per_component (ETaskBar *task_bar)
{
@@ -82,7 +83,7 @@ reduce_displayed_activities_per_component (ETaskBar *task_bar)
g_hash_table_destroy (component_ids_hash);
}
-
+#endif
static void
e_task_bar_class_init (ETaskBarClass *klass)
@@ -185,12 +186,37 @@ e_task_bar_prepend_task (ETaskBar *task_bar,
gtk_widget_queue_resize (GTK_WIDGET (task_widget));
}
- reduce_displayed_activities_per_component (task_bar);
+ /* We don't restrict */
+ /* reduce_displayed_activities_per_component (task_bar);*/
gtk_widget_show (GTK_WIDGET (task_bar->priv->hbox));
}
void
+e_task_bar_remove_task_from_id (ETaskBar *task_bar,
+ guint id)
+{
+ ETaskWidget *task_widget;
+
+ g_return_if_fail (task_bar != NULL);
+ g_return_if_fail (E_IS_TASK_BAR (task_bar));
+
+ task_widget = e_task_bar_get_task_widget_from_id (task_bar, id);
+ if (!task_widget) {
+ printf("Failed...\n");
+ return;
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (task_widget));
+
+ /* We don't restrict here on */
+ /* reduce_displayed_activities_per_component (task_bar); */
+
+ if (g_list_length (GTK_BOX (task_bar->priv->hbox)->children) == 0)
+ gtk_widget_hide (GTK_WIDGET (task_bar->priv->hbox));
+}
+
+void
e_task_bar_remove_task (ETaskBar *task_bar,
int n)
{
@@ -203,13 +229,40 @@ e_task_bar_remove_task (ETaskBar *task_bar,
task_widget = e_task_bar_get_task_widget (task_bar, n);
gtk_widget_destroy (GTK_WIDGET (task_widget));
- reduce_displayed_activities_per_component (task_bar);
+ /* We don't restrict here on */
+ /* reduce_displayed_activities_per_component (task_bar); */
if (g_list_length (GTK_BOX (task_bar->priv->hbox)->children) == 0)
gtk_widget_hide (GTK_WIDGET (task_bar->priv->hbox));
}
ETaskWidget *
+e_task_bar_get_task_widget_from_id (ETaskBar *task_bar,
+ guint id)
+{
+ GtkBoxChild *child_info;
+ ETaskWidget *w = NULL;
+ GList *list;
+
+ g_return_val_if_fail (task_bar != NULL, NULL);
+ g_return_val_if_fail (E_IS_TASK_BAR (task_bar), NULL);
+
+ list = GTK_BOX (task_bar->priv->hbox)->children;
+ while (list) {
+ child_info = list->data;
+ w = (ETaskWidget *) child_info->widget;
+ if (w && w->id == id)
+ break;
+
+ w = NULL;
+ list = list->next;
+ }
+
+ return w;
+}
+
+ETaskWidget *
+
e_task_bar_get_task_widget (ETaskBar *task_bar,
int n)
{
diff --git a/widgets/misc/e-task-bar.h b/widgets/misc/e-task-bar.h
index 50301326d6..4cacf4cf79 100644
--- a/widgets/misc/e-task-bar.h
+++ b/widgets/misc/e-task-bar.h
@@ -66,7 +66,11 @@ void e_task_bar_prepend_task (ETaskBar *task_bar,
ETaskWidget *task_widget);
void e_task_bar_remove_task (ETaskBar *task_bar,
int n);
+ETaskWidget * e_task_bar_get_task_widget_from_id (ETaskBar *task_bar,
+ guint id);
+void e_task_bar_remove_task_from_id (ETaskBar *task_bar,
+ guint id);
ETaskWidget *e_task_bar_get_task_widget (ETaskBar *task_bar,
int n);
diff --git a/widgets/misc/e-task-widget.c b/widgets/misc/e-task-widget.c
index 50d459d3f0..bb9a6026d9 100644
--- a/widgets/misc/e-task-widget.c
+++ b/widgets/misc/e-task-widget.c
@@ -26,12 +26,15 @@
#include "e-task-widget.h"
#include "e-spinner.h"
+#include <e-util/e-icon-factory.h>
#include <gtk/gtkframe.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkimage.h>
#include <gtk/gtktooltips.h>
+#include <gtk/gtktoolbutton.h>
+#include <gtk/gtkbox.h>
#include <glib/gi18n.h>
@@ -45,7 +48,11 @@ struct _ETaskWidgetPrivate {
GdkPixbuf *icon_pixbuf;
GtkWidget *label;
+ GtkWidget *box;
GtkWidget *image;
+
+ void (*cancel_func) (gpointer data);
+ gpointer data;
};
G_DEFINE_TYPE (ETaskWidget, e_task_widget, GTK_TYPE_EVENT_BOX)
@@ -112,8 +119,35 @@ e_task_widget_init (ETaskWidget *task_widget)
priv->icon_pixbuf = NULL;
priv->label = NULL;
priv->image = NULL;
+ priv->box = NULL;
task_widget->priv = priv;
+ task_widget->id = 0;
+}
+
+static gboolean
+button_press_event_cb (GtkWidget *w, gpointer data)
+{
+ ETaskWidget *tw = (ETaskWidget *) data;
+ ETaskWidgetPrivate *priv = tw->priv;
+
+ priv->cancel_func (priv->data);
+
+ return TRUE;
+}
+
+static gboolean
+prepare_popup (ETaskWidget *widget, GdkEventButton *event)
+{
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ if (event->button != 3)
+ return FALSE;
+
+ /* FIXME: Implement Cancel */
+
+ return TRUE;
}
@@ -121,17 +155,20 @@ void
e_task_widget_construct (ETaskWidget *task_widget,
GdkPixbuf *icon_pixbuf,
const char *component_id,
- const char *information)
+ const char *information,
+ void (*cancel_func) (gpointer data),
+ gpointer data)
{
ETaskWidgetPrivate *priv;
/*GdkPixmap *pixmap;
GdkBitmap *mask;*/
GtkWidget *box;
GtkWidget *frame;
+ GtkWidget *image = e_icon_factory_get_image ("gtk-stop", E_ICON_SIZE_MENU);
+ GtkWidget *tool;
g_return_if_fail (task_widget != NULL);
g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
- g_return_if_fail (icon_pixbuf != NULL);
g_return_if_fail (component_id != NULL);
g_return_if_fail (information != NULL);
@@ -154,22 +191,34 @@ e_task_widget_construct (ETaskWidget *task_widget,
/* priv->icon_pixbuf = g_object_ref (icon_pixbuf); */
/* gdk_pixbuf_render_pixmap_and_mask (icon_pixbuf, &pixmap, &mask, 128); */
-
+ priv->box = gtk_hbox_new (FALSE, 0);
priv->image = e_spinner_new ();
e_spinner_set_size (E_SPINNER (priv->image), GTK_ICON_SIZE_SMALL_TOOLBAR);
e_spinner_start (E_SPINNER (priv->image));
/* gtk_image_new_from_pixmap (pixmap, mask); */
gtk_widget_show (priv->image);
- gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, TRUE, 0);
-
+ gtk_widget_show (priv->box);
+ gtk_box_pack_start (GTK_BOX (priv->box), priv->image, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (box), priv->box, FALSE, TRUE, 0);
priv->label = gtk_label_new ("");
gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
gtk_widget_show (priv->label);
gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0);
+ if (cancel_func) {
+ tool = (GtkWidget *) gtk_tool_button_new (image, NULL);
+ gtk_box_pack_end (GTK_BOX (box), tool, FALSE, TRUE, 0);
+ gtk_widget_show_all (tool);
+
+ gtk_widget_set_sensitive (tool, cancel_func != NULL);
+ priv->cancel_func = cancel_func;
+ priv->data = data;
+ g_signal_connect (tool, "clicked", G_CALLBACK (button_press_event_cb), task_widget);
+ /* g_object_unref (pixmap);
+ if (mask)
+ g_object_unref (mask); */
+ g_signal_connect (task_widget, "button-press-event", G_CALLBACK (prepare_popup), task_widget);
- /* g_object_unref (pixmap);
- if (mask)
- g_object_unref (mask); */
+ }
priv->tooltips = gtk_tooltips_new ();
g_object_ref_sink (priv->tooltips);
@@ -178,6 +227,23 @@ e_task_widget_construct (ETaskWidget *task_widget,
}
GtkWidget *
+e_task_widget_new_with_cancel (GdkPixbuf *icon_pixbuf,
+ const char *component_id,
+ const char *information,
+ void (*cancel_func) (gpointer data),
+ gpointer data)
+{
+ ETaskWidget *task_widget;
+
+ g_return_val_if_fail (information != NULL, NULL);
+
+ task_widget = g_object_new (e_task_widget_get_type (), NULL);
+ e_task_widget_construct (task_widget, icon_pixbuf, component_id, information, cancel_func, data);
+
+ return GTK_WIDGET (task_widget);
+}
+
+GtkWidget *
e_task_widget_new (GdkPixbuf *icon_pixbuf,
const char *component_id,
const char *information)
@@ -188,11 +254,28 @@ e_task_widget_new (GdkPixbuf *icon_pixbuf,
g_return_val_if_fail (information != NULL, NULL);
task_widget = g_object_new (e_task_widget_get_type (), NULL);
- e_task_widget_construct (task_widget, icon_pixbuf, component_id, information);
+ e_task_widget_construct (task_widget, icon_pixbuf, component_id, information, NULL, NULL);
return GTK_WIDGET (task_widget);
}
+GtkWidget *
+e_task_widget_update_image (ETaskWidget *task_widget,
+ char *stock, char *text)
+{
+ GtkWidget *img, *tool;
+
+ img = e_icon_factory_get_image ("stock_dialog-warning", E_ICON_SIZE_MENU);
+ tool = (GtkWidget *) gtk_tool_button_new (img, NULL);
+ gtk_box_pack_start (GTK_BOX(task_widget->priv->box), tool, FALSE, TRUE, 0);
+ gtk_widget_destroy (task_widget->priv->image);
+ gtk_widget_show_all (task_widget->priv->box);
+ task_widget->priv->image = img;
+ gtk_label_set_text (GTK_LABEL (task_widget->priv->label), text);
+
+ return tool;
+}
+
void
e_task_widget_update (ETaskWidget *task_widget,
diff --git a/widgets/misc/e-task-widget.h b/widgets/misc/e-task-widget.h
index 0eb4fbb167..fb47b95095 100644
--- a/widgets/misc/e-task-widget.h
+++ b/widgets/misc/e-task-widget.h
@@ -46,6 +46,7 @@ struct _ETaskWidget {
GtkEventBox parent;
ETaskWidgetPrivate *priv;
+ guint id;
};
struct _ETaskWidgetClass {
@@ -57,14 +58,25 @@ GtkType e_task_widget_get_type (void);
void e_task_widget_construct (ETaskWidget *task_widget,
GdkPixbuf *icon_pixbuf,
const char *component_id,
- const char *information);
+ const char *information,
+ void (*cancel_func) (gpointer data),
+ gpointer data);
GtkWidget *e_task_widget_new (GdkPixbuf *icon_pixbuf,
const char *component_id,
const char *information);
+GtkWidget *
+e_task_widget_new_with_cancel (GdkPixbuf *icon_pixbuf,
+ const char *component_id,
+ const char *information,
+ void (*cancel_func) (gpointer data),
+ gpointer data);
void e_task_widget_update (ETaskWidget *task_widget,
const char *information,
double completion);
+GtkWidget *
+e_task_widget_update_image (ETaskWidget *task_widget,
+ char *stock, char *text);
void e_task_wiget_alert (ETaskWidget *task_widget);
void e_task_wiget_unalert (ETaskWidget *task_widget);