Big patch. Evolution-services rewrite, services updated for new system, Fixes to Executive Summary and other things. See some changelogs svn path=/trunk/; revision=6644
1260 lines
31 KiB
C
1260 lines
31 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
/* e-summary.c
|
|
*
|
|
* Authors: Iain Holmes <iain@helixcode.com>
|
|
*
|
|
* Copyright (C) 2000 Helix Code, Inc.
|
|
*
|
|
* 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., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <gnome.h>
|
|
#include <bonobo.h>
|
|
|
|
#include <gtkhtml/gtkhtml.h>
|
|
#include <gtkhtml/gtkhtml-embedded.h>
|
|
#include <gtkhtml/gtkhtml-stream.h>
|
|
#include <gtkhtml/htmlengine.h>
|
|
#include <gtkhtml/htmlselection.h>
|
|
#include <gal/util/e-util.h>
|
|
#include <gal/widgets/e-gui-utils.h>
|
|
#include <libgnomevfs/gnome-vfs.h>
|
|
|
|
#include "e-summary.h"
|
|
#include "e-summary-factory.h"
|
|
#include "e-summary-util.h"
|
|
#include "e-summary-url.h"
|
|
|
|
#define PARENT_TYPE (gtk_vbox_get_type ())
|
|
|
|
#define STORAGE_TYPE "efs"
|
|
#define IID_FILE "oaf.id"
|
|
#define DATA_FILE "data"
|
|
|
|
/* From component-factory.c */
|
|
extern char *evolution_dir;
|
|
|
|
static GtkObjectClass *e_summary_parent_class;
|
|
|
|
struct _ESummaryPrivate {
|
|
GNOME_Evolution_Shell shell;
|
|
GNOME_Evolution_ShellView shell_view_interface;
|
|
|
|
GtkWidget *html_scroller;
|
|
GtkWidget *html;
|
|
|
|
guint idle;
|
|
|
|
GtkHTMLStream *stream;
|
|
gboolean grabbed;
|
|
|
|
GList *window_list;
|
|
|
|
char *header;
|
|
int header_len;
|
|
char *footer;
|
|
int footer_len;
|
|
};
|
|
|
|
static gboolean on_object_requested (GtkHTML *html,
|
|
GtkHTMLEmbedded *eb,
|
|
ESummary *summary);
|
|
static void e_summary_save_state (ESummary *esummary,
|
|
const char *path);
|
|
static void e_summary_load_state (ESummary *esummary,
|
|
const char *path);
|
|
|
|
/* Used to distinguish dead windows */
|
|
static ESummaryWindow dead_window = {
|
|
CORBA_OBJECT_NIL,
|
|
CORBA_OBJECT_NIL,
|
|
CORBA_OBJECT_NIL,
|
|
CORBA_OBJECT_NIL,
|
|
CORBA_OBJECT_NIL,
|
|
CORBA_OBJECT_NIL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
/* GtkObject methods */
|
|
|
|
static void
|
|
e_summary_destroy (GtkObject *object)
|
|
{
|
|
ESummary *esummary = E_SUMMARY (object);
|
|
ESummaryPrivate *priv;
|
|
GList *l;
|
|
char *prefix;
|
|
|
|
priv = esummary->private;
|
|
if (priv == NULL)
|
|
return;
|
|
|
|
prefix = g_concat_dir_and_file (evolution_dir, "config/Executive-Summary");
|
|
e_summary_save_state (esummary, prefix);
|
|
g_free (prefix);
|
|
|
|
for (l = priv->window_list; l; l = l->next)
|
|
e_summary_window_free (l->data);
|
|
g_list_free (priv->window_list);
|
|
|
|
g_free (priv->header);
|
|
g_free (priv->footer);
|
|
g_free (esummary->private);
|
|
esummary->private = NULL;
|
|
|
|
e_summary_parent_class->destroy (object);
|
|
}
|
|
|
|
static void
|
|
e_summary_class_init (GtkObjectClass *object_class)
|
|
{
|
|
object_class->destroy = e_summary_destroy;
|
|
|
|
e_summary_parent_class = gtk_type_class (PARENT_TYPE);
|
|
}
|
|
|
|
static void
|
|
e_summary_start_load (ESummary *esummary)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
priv->stream = gtk_html_begin (GTK_HTML (priv->html));
|
|
|
|
/* Hack to stop page returning to the top */
|
|
GTK_HTML (priv->html)->engine->newPage = FALSE;
|
|
}
|
|
|
|
static void
|
|
load_default_header (ESummary *esummary)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
char *def = "<html><body bgcolor=\"#ffffff\">"
|
|
"<table width=\"100%\"><tr><td align=\"right\">"
|
|
"<img src=\"ccsplash.png\"></td></tr></table>"
|
|
"<table><tr><td><a href=\"exec://bug-buddy\"><img src=\"file://gnome-spider.png\" width=\"24\" height=\"24\" border=\"0\">"
|
|
"</a></td><td><a href=\"exec://bug-buddy\">Submit a bug report"
|
|
"</a></td></tr></table><hr>";
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
g_return_if_fail (priv->stream != NULL);
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream, def, strlen (def));
|
|
}
|
|
static void
|
|
load_default_footer (ESummary *esummary)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
char *footer = "<hr><p align=\"right\">All Executive Summary comments to <a href=\"mailto:iain@helixcode.com\">Iain Holmes (iain@helixcode.com)</a></p></body></html>";
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
footer, strlen (footer));
|
|
}
|
|
|
|
static void
|
|
e_summary_end_load (ESummary *esummary)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
gtk_html_end (GTK_HTML (priv->html), priv->stream, GTK_HTML_STREAM_OK);
|
|
|
|
priv->stream = NULL;
|
|
}
|
|
|
|
static void
|
|
e_summary_init (ESummary *esummary)
|
|
{
|
|
GdkColor bgcolour = {0, 0xdfff, 0xdfff, 0xffff};
|
|
ESummaryPrivate *priv;
|
|
|
|
esummary->private = g_new0 (ESummaryPrivate, 1);
|
|
priv = esummary->private;
|
|
|
|
priv->window_list = NULL;
|
|
priv->idle = 0;
|
|
|
|
/* HTML widget */
|
|
priv->html_scroller = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->html_scroller),
|
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
priv->html = gtk_html_new ();
|
|
gtk_html_set_editable (GTK_HTML (priv->html), FALSE);
|
|
gtk_html_set_default_background_color (GTK_HTML (priv->html), &bgcolour);
|
|
gtk_signal_connect (GTK_OBJECT (priv->html), "url-requested",
|
|
GTK_SIGNAL_FUNC (e_summary_url_request), esummary);
|
|
gtk_signal_connect (GTK_OBJECT (priv->html), "object-requested",
|
|
GTK_SIGNAL_FUNC (on_object_requested), esummary);
|
|
gtk_signal_connect (GTK_OBJECT (priv->html), "link-clicked",
|
|
GTK_SIGNAL_FUNC (e_summary_url_click), esummary);
|
|
gtk_signal_connect (GTK_OBJECT (priv->html), "on-url",
|
|
GTK_SIGNAL_FUNC (e_summary_url_over), esummary);
|
|
|
|
gtk_container_add (GTK_CONTAINER (priv->html_scroller), priv->html);
|
|
gtk_widget_show_all (priv->html_scroller);
|
|
|
|
e_summary_rebuild_page (esummary);
|
|
|
|
/* Pack stuff */
|
|
gtk_box_pack_start (GTK_BOX (esummary), priv->html_scroller,
|
|
TRUE, TRUE, 0);
|
|
}
|
|
|
|
E_MAKE_TYPE (e_summary, "ESummary", ESummary, e_summary_class_init,
|
|
e_summary_init, PARENT_TYPE);
|
|
|
|
GtkWidget *
|
|
e_summary_new (const GNOME_Evolution_Shell shell)
|
|
{
|
|
ESummary *esummary;
|
|
ESummaryPrivate *priv;
|
|
char *path;
|
|
|
|
esummary = gtk_type_new (e_summary_get_type ());
|
|
priv = esummary->private;
|
|
|
|
priv->shell = shell;
|
|
|
|
/* Restore services */
|
|
path = g_concat_dir_and_file (evolution_dir,
|
|
"config/Executive-Summary");
|
|
e_summary_load_state (esummary, path);
|
|
g_free (path);
|
|
|
|
return GTK_WIDGET (esummary);
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
control_unrealize (GtkHTMLEmbedded *eb,
|
|
GtkWidget *widget)
|
|
{
|
|
g_print ("Removing\n");
|
|
}
|
|
|
|
static void
|
|
being_unrealized (GtkWidget *widget,
|
|
GtkHTMLEmbedded *eb)
|
|
{
|
|
g_warning ("Widget is being unrealized");
|
|
gtk_container_remove (GTK_CONTAINER (eb), widget);
|
|
}
|
|
|
|
static void
|
|
being_realized (GtkWidget *widget,
|
|
gpointer user_data)
|
|
{
|
|
gdk_window_ref (widget->window);
|
|
}
|
|
#endif
|
|
|
|
static gboolean
|
|
on_object_requested (GtkHTML *html,
|
|
GtkHTMLEmbedded *eb,
|
|
ESummary *esummary)
|
|
{
|
|
#if 0
|
|
static GtkWidget *widget = NULL;
|
|
int id;
|
|
|
|
if (sscanf (eb->classid, "cid:%d", &id) != 1) {
|
|
g_warning ("Could not get the view id: eb->classid = %s",
|
|
eb->classid);
|
|
return FALSE;
|
|
}
|
|
|
|
if (widget == NULL || !GTK_IS_WIDGET (widget)) {
|
|
g_print ("Create new\n");
|
|
widget = executive_summary_component_view_get_widget (view);
|
|
/* widget = gtk_button_new_with_label ("Hello?"); */
|
|
gtk_signal_connect (GTK_OBJECT (widget), "realize",
|
|
GTK_SIGNAL_FUNC (being_realized), NULL);
|
|
gtk_signal_connect (GTK_OBJECT (widget), "unrealize",
|
|
GTK_SIGNAL_FUNC (being_unrealized), eb);
|
|
g_print ("New widget: %p\n", GTK_BIN (widget)->child);
|
|
} else {
|
|
g_print ("No new\n");
|
|
}
|
|
|
|
if (widget == NULL) {
|
|
g_warning ("View %d has no GtkWidget.", id);
|
|
return FALSE;
|
|
}
|
|
|
|
gtk_signal_connect (GTK_OBJECT (eb), "unrealize",
|
|
GTK_SIGNAL_FUNC (control_unrealize), widget);
|
|
gtk_widget_show_all (widget);
|
|
gtk_widget_ref (widget);
|
|
|
|
if (widget->parent == NULL)
|
|
gtk_container_add (GTK_CONTAINER (eb), widget);
|
|
|
|
return TRUE;
|
|
#endif
|
|
}
|
|
|
|
/* Generates the window controls and works out
|
|
if they should be disabled or not */
|
|
static char *
|
|
make_control_html (ESummaryWindow *window,
|
|
int row,
|
|
int col,
|
|
int numwindows)
|
|
{
|
|
char *html, *tmp;
|
|
int id = GPOINTER_TO_INT (window);
|
|
gboolean u, d, l, r, config;
|
|
|
|
u = d = l = r = config = TRUE;
|
|
|
|
if (window->propertycontrol == CORBA_OBJECT_NIL)
|
|
config = FALSE;
|
|
|
|
if (row == 0) /* Top row */
|
|
u = FALSE;
|
|
|
|
if (row >= numwindows - 3) /* Bottom row */
|
|
d = FALSE;
|
|
|
|
if (col == 0) /* Leftmost column */
|
|
l = FALSE;
|
|
|
|
if (col == 2 || ((row * 3) + col) == numwindows - 1) /* Rightmost column */
|
|
r = FALSE;
|
|
|
|
html = g_strdup_printf ("<table><tr><td><a href=\"close://%d\">"
|
|
"<img src=\"service-close.png\" border=\"0\">"
|
|
"</a></td><td>", id);
|
|
|
|
tmp = html;
|
|
if (!config) {
|
|
html = g_strdup_printf ("%s<img src=\"service-configure.png\">"
|
|
"</td></tr><tr><td>", tmp);
|
|
} else {
|
|
html = g_strdup_printf ("%s<a href=\"configure://%d\">"
|
|
"<img src=\"service-configure.png\" border=\"0\">"
|
|
"</a></td></tr><tr><td>", tmp, id);
|
|
}
|
|
g_free (tmp);
|
|
|
|
tmp = html;
|
|
if (!l) {
|
|
html = g_strdup_printf ("%s<img src=\"service-left-disabled.png\">"
|
|
"</td><td>", tmp);
|
|
} else {
|
|
html = g_strdup_printf ("%s<a href=\"left://%d\">"
|
|
"<img src=\"service-left.png\" border=\"0\">"
|
|
"</a></td><td>", tmp, id);
|
|
}
|
|
g_free (tmp);
|
|
|
|
tmp = html;
|
|
if (!r) {
|
|
html = g_strdup_printf ("%s<img src=\"service-right-disabled.png\">"
|
|
"</td></tr><tr><td>", tmp);
|
|
} else {
|
|
html = g_strdup_printf ("%s<a href=\"right://%d\">"
|
|
"<img src=\"service-right.png\" border=\"0\">"
|
|
"</a></td></tr><tr><td>", tmp, id);
|
|
}
|
|
g_free (tmp);
|
|
|
|
tmp = html;
|
|
if (!d) {
|
|
html = g_strdup_printf ("%s<img src=\"service-down-disabled.png\">"
|
|
"</td><td>", tmp);
|
|
} else {
|
|
html = g_strdup_printf ("%s<a href=\"down://%d\">"
|
|
"<img src=\"service-down.png\" border=\"0\">"
|
|
"</a></td><td>", tmp, id);
|
|
}
|
|
g_free (tmp);
|
|
|
|
tmp = html;
|
|
if (!u) {
|
|
html = g_strdup_printf ("%s<img src=\"service-up-disabled.png\">"
|
|
"</td></tr></table>", tmp);
|
|
} else {
|
|
html = g_strdup_printf ("%s<a href=\"up://%d\">"
|
|
"<img src=\"service-up.png\" border=\"0\">"
|
|
"</a></td></tr></table>", tmp, id);
|
|
}
|
|
g_free (tmp);
|
|
|
|
return html;
|
|
}
|
|
|
|
static void
|
|
e_summary_display_window (ESummary *esummary,
|
|
ESummaryWindow *window,
|
|
int row,
|
|
int col,
|
|
int numwindows)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
char *footer = "</td></tr></table>";
|
|
char *title_html;
|
|
char *control_html;
|
|
char *colour[2] = {"e6e8e4",
|
|
"edeeeb"};
|
|
char *title_colour[2] = {"bac1b6",
|
|
"cdd1c7"};
|
|
|
|
priv = esummary->private;
|
|
|
|
control_html = make_control_html (window, row, col, numwindows);
|
|
title_html = g_strdup_printf ("<table cellspacing=\"0\" "
|
|
"cellpadding=\"0\" border=\"0\" width=\"100%%\" height=\"100%%\">"
|
|
"<tr><td bgcolor=\"#%s\">"
|
|
"<table width=\"100%%\" height=\"100%%\"><tr><td>"
|
|
"<img src=\"%s\"></td>"
|
|
"<td nowrap align=\"center\" width=\"100%%\">"
|
|
"<b>%s</b></td><td>%s</td></tr></table></td></tr><tr>"
|
|
"<td bgcolor=\"#%s\" height=\"100%%\">",
|
|
title_colour[col % 2], window->icon,
|
|
window->title, control_html,
|
|
colour[col % 2]);
|
|
g_free (control_html);
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream, title_html,
|
|
strlen (title_html));
|
|
g_free (title_html);
|
|
|
|
if (window->html != CORBA_OBJECT_NIL) {
|
|
char *html;
|
|
CORBA_Environment ev;
|
|
|
|
CORBA_exception_init (&ev);
|
|
html = GNOME_Evolution_Summary_HTMLView_getHtml (window->html,
|
|
&ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION) {
|
|
g_warning ("Cannot get HTML.");
|
|
return;
|
|
}
|
|
CORBA_exception_free (&ev);
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
html, strlen (html));
|
|
} else {
|
|
#if 0
|
|
char *body_cid;
|
|
|
|
body_cid = g_strdup_printf ("<object classid=\"cid:%d\"></object>", id);
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
body_cid, strlen (body_cid));
|
|
g_free (body_cid);
|
|
#endif
|
|
}
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
footer, strlen (footer));
|
|
}
|
|
|
|
int
|
|
e_summary_rebuild_page (ESummary *esummary)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GList *windows;
|
|
char *service_table = "<table numcols=\"3\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" height=\"100%\">";
|
|
int loc;
|
|
int numwindows;
|
|
|
|
g_return_val_if_fail (esummary != NULL, FALSE);
|
|
g_return_val_if_fail (IS_E_SUMMARY (esummary), FALSE);
|
|
|
|
priv = esummary->private;
|
|
|
|
/* If there is a selection, don't redraw the page so that the selection
|
|
isn't cleared */
|
|
if (GTK_HTML (priv->html)->in_selection == TRUE ||
|
|
html_engine_is_selection_active (GTK_HTML (priv->html)->engine) == TRUE)
|
|
return TRUE;
|
|
|
|
gtk_layout_freeze (GTK_LAYOUT (priv->html));
|
|
e_summary_start_load (esummary);
|
|
|
|
if (priv->header == NULL) {
|
|
load_default_header (esummary);
|
|
} else {
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
priv->header, priv->header_len);
|
|
}
|
|
|
|
/* Load the start of the services */
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream, service_table,
|
|
strlen (service_table));
|
|
/* Load each of the services */
|
|
loc = 0;
|
|
numwindows = g_list_length (priv->window_list);
|
|
for (windows = priv->window_list; windows; windows = windows->next) {
|
|
ESummaryWindow *window;
|
|
char *td = "<td height=\"100%\" width=\"33%\" valign=\"top\">";
|
|
|
|
window = windows->data;
|
|
|
|
if (loc % 3 == 0) {
|
|
if (loc != 0) {
|
|
gtk_html_write (GTK_HTML (priv->html),
|
|
priv->stream, "</tr>", 5);
|
|
}
|
|
gtk_html_write (GTK_HTML (priv->html),
|
|
priv->stream, "<tr height=\"100%\">", 18);
|
|
}
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
td, strlen (td));
|
|
|
|
e_summary_display_window (esummary, window,
|
|
(loc / 3), (loc % 3), numwindows);
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream, "</td>", 5);
|
|
loc++;
|
|
}
|
|
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream, "</tr></table>",
|
|
13);
|
|
|
|
if (priv->footer == NULL) {
|
|
load_default_footer (esummary);
|
|
} else {
|
|
gtk_html_write (GTK_HTML (priv->html), priv->stream,
|
|
priv->footer, priv->footer_len);
|
|
}
|
|
|
|
e_summary_end_load (esummary);
|
|
gtk_layout_thaw (GTK_LAYOUT (priv->html));
|
|
|
|
priv->idle = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
prop_changed_cb (BonoboPropertyListener *listener,
|
|
char *name,
|
|
BonoboArg *arg,
|
|
ESummaryWindow *window)
|
|
{
|
|
if (strcmp (name, "window_title") == 0) {
|
|
if (window->title != NULL)
|
|
g_free (window->title);
|
|
window->title = g_strdup (BONOBO_ARG_GET_STRING (arg));
|
|
return;
|
|
}
|
|
|
|
if (strcmp (name, "window_icon") == 0) {
|
|
if (window->icon != NULL)
|
|
g_free (window->icon);
|
|
window->icon = g_strdup (BONOBO_ARG_GET_STRING (arg));
|
|
return;
|
|
}
|
|
}
|
|
|
|
ESummaryWindow *
|
|
e_summary_add_service (ESummary *esummary,
|
|
GNOME_Evolution_Summary_Component component,
|
|
const char *iid)
|
|
{
|
|
ESummaryWindow *window;
|
|
ESummaryPrivate *priv;
|
|
Bonobo_Unknown unknown = CORBA_OBJECT_NIL;
|
|
Bonobo_PropertyListener corba_listener;
|
|
CORBA_Environment ev;
|
|
|
|
g_return_val_if_fail (esummary != NULL, NULL);
|
|
g_return_val_if_fail (IS_E_SUMMARY (esummary), NULL);
|
|
g_return_val_if_fail (component != CORBA_OBJECT_NIL, NULL);
|
|
|
|
priv = esummary->private;
|
|
|
|
window = g_new0 (ESummaryWindow, 1);
|
|
window->component = component;
|
|
window->iid = g_strdup (iid);
|
|
|
|
/* See what interfaces our component supports */
|
|
CORBA_exception_init (&ev);
|
|
unknown = Bonobo_Unknown_queryInterface (component,
|
|
"IDL:Bonobo/Control:1.0", &ev);
|
|
window->control = (Bonobo_Control) unknown;
|
|
|
|
unknown = Bonobo_Unknown_queryInterface (component,
|
|
"IDL:GNOME/Evolution/Summary/HTMLView:1.0",
|
|
&ev);
|
|
window->html = (GNOME_Evolution_Summary_HTMLView) unknown;
|
|
|
|
/* Check at least one of the above interfaces was supported */
|
|
if (window->html == CORBA_OBJECT_NIL &&
|
|
window->control == CORBA_OBJECT_NIL) {
|
|
CORBA_Environment ev2;
|
|
g_warning ("This component does not support either"
|
|
"Bonobo/Control:1.0 or GNOME/Evolution/Summary/HTMLView:1.0");
|
|
|
|
CORBA_exception_init (&ev2);
|
|
CORBA_Object_release (component, &ev2);
|
|
CORBA_exception_free (&ev2);
|
|
|
|
g_free (window);
|
|
return NULL;
|
|
}
|
|
|
|
unknown = Bonobo_Unknown_queryInterface (component,
|
|
"IDL:Bonobo/PropertyBag:1.0",
|
|
&ev);
|
|
window->propertybag = (Bonobo_PropertyBag) unknown;
|
|
|
|
unknown = Bonobo_Unknown_queryInterface (component,
|
|
"IDL:Bonobo/PersistStream:1.0",
|
|
&ev);
|
|
window->persiststream = (Bonobo_PersistStream) unknown;
|
|
|
|
unknown = Bonobo_Unknown_queryInterface (component,
|
|
"IDL:Bonobo/PropertyControl:1.0",
|
|
&ev);
|
|
window->propertycontrol = (Bonobo_PropertyControl) unknown;
|
|
|
|
/* Cache the title and icon */
|
|
window->title = g_strdup (bonobo_property_bag_client_get_value_string (
|
|
window->propertybag,
|
|
"window_title",
|
|
NULL));
|
|
window->icon = g_strdup (bonobo_property_bag_client_get_value_string (
|
|
window->propertybag,
|
|
"window_icon", NULL));
|
|
/* Listen to changes */
|
|
window->listener = bonobo_property_listener_new ();
|
|
gtk_signal_connect (GTK_OBJECT (window->listener), "prop_changed",
|
|
GTK_SIGNAL_FUNC (prop_changed_cb), window);
|
|
corba_listener = bonobo_object_corba_objref (BONOBO_OBJECT (window->listener));
|
|
Bonobo_PropertyBag_addChangeListener (window->propertybag,
|
|
"window_title",
|
|
corba_listener, &ev);
|
|
|
|
Bonobo_PropertyBag_addChangeListener (window->propertybag,
|
|
"window_icon",
|
|
corba_listener, &ev);
|
|
CORBA_exception_free (&ev);
|
|
|
|
priv->window_list = g_list_append (priv->window_list, window);
|
|
|
|
return window;
|
|
}
|
|
|
|
void
|
|
e_summary_window_free (ESummaryWindow *window)
|
|
{
|
|
CORBA_Environment ev;
|
|
|
|
g_return_if_fail (window != NULL);
|
|
|
|
g_free (window->iid);
|
|
g_free (window->icon);
|
|
g_free (window->title);
|
|
|
|
CORBA_exception_init (&ev);
|
|
Bonobo_Unknown_unref (window->component, &ev);
|
|
CORBA_Object_release (window->component, &ev);
|
|
|
|
if (window->control != CORBA_OBJECT_NIL) {
|
|
CORBA_Object_release (window->control, &ev);
|
|
}
|
|
|
|
if (window->html != CORBA_OBJECT_NIL) {
|
|
CORBA_Object_release (window->html, &ev);
|
|
}
|
|
|
|
if (window->propertybag != CORBA_OBJECT_NIL) {
|
|
CORBA_Object_release (window->propertybag, &ev);
|
|
}
|
|
|
|
if (window->persiststream != CORBA_OBJECT_NIL) {
|
|
CORBA_Object_release (window->persiststream, &ev);
|
|
}
|
|
|
|
if (window->propertycontrol != CORBA_OBJECT_NIL) {
|
|
CORBA_Object_release (window->propertycontrol, &ev);
|
|
}
|
|
|
|
CORBA_exception_free (&ev);
|
|
|
|
g_free (window);
|
|
|
|
/* The contents of window are set to dead_window
|
|
so we know if we're trying to access a window
|
|
that no longer exists */
|
|
*window = dead_window;
|
|
}
|
|
|
|
void
|
|
e_summary_remove_window (ESummary *esummary,
|
|
ESummaryWindow *window)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
g_return_if_fail (window != NULL);
|
|
|
|
priv = esummary->private;
|
|
priv->window_list = g_list_remove (priv->window_list, window);
|
|
e_summary_window_free (window);
|
|
}
|
|
|
|
void
|
|
e_summary_set_shell_view_interface (ESummary *esummary,
|
|
GNOME_Evolution_ShellView svi)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
g_return_if_fail (svi != CORBA_OBJECT_NIL);
|
|
|
|
priv = esummary->private;
|
|
priv->shell_view_interface = svi;
|
|
}
|
|
|
|
/* Wrappers for GNOME_Evolution_ShellView */
|
|
void
|
|
e_summary_set_message (ESummary *esummary,
|
|
const char *message,
|
|
gboolean busy)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GNOME_Evolution_ShellView svi;
|
|
CORBA_Environment ev;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
svi = priv->shell_view_interface;
|
|
if (svi == NULL)
|
|
return;
|
|
|
|
CORBA_exception_init (&ev);
|
|
if (message != NULL)
|
|
GNOME_Evolution_ShellView_setMessage (svi, message, busy, &ev);
|
|
else
|
|
GNOME_Evolution_ShellView_setMessage (svi, "", busy, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
void
|
|
e_summary_unset_message (ESummary *esummary)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GNOME_Evolution_ShellView svi;
|
|
CORBA_Environment ev;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
svi = priv->shell_view_interface;
|
|
if (svi == NULL)
|
|
return;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellView_unsetMessage (svi, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
void
|
|
e_summary_change_current_view (ESummary *esummary,
|
|
const char *uri)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GNOME_Evolution_ShellView svi;
|
|
CORBA_Environment ev;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
svi = priv->shell_view_interface;
|
|
if (svi == NULL)
|
|
return;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellView_changeCurrentView (svi, uri, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
void
|
|
e_summary_set_title (ESummary *esummary,
|
|
const char *title)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GNOME_Evolution_ShellView svi;
|
|
CORBA_Environment ev;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
svi = priv->shell_view_interface;
|
|
if (svi == NULL)
|
|
return;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellView_setTitle (svi, title, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
load_html_page (ESummary *esummary,
|
|
const char *filename)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GnomeVFSHandle *handle = NULL;
|
|
GnomeVFSResult result;
|
|
GtkWidget *toplevel;
|
|
GString *string;
|
|
char *str, *comment;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
/* Pass NULL to reset the page to the default */
|
|
if (filename == NULL || *filename == '\0') {
|
|
g_free (priv->header);
|
|
g_free (priv->footer);
|
|
return;
|
|
}
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (esummary));
|
|
string = g_string_new ("");
|
|
result = gnome_vfs_open (&handle, filename, GNOME_VFS_OPEN_READ);
|
|
if (result != GNOME_VFS_OK) {
|
|
e_notice (GTK_WINDOW (toplevel), GNOME_MESSAGE_BOX_WARNING,
|
|
_("Cannot open the HTML file:\n%s"), filename);
|
|
return;
|
|
}
|
|
|
|
while (1) {
|
|
char buffer[4096];
|
|
GnomeVFSFileSize size;
|
|
|
|
memset (buffer, 0x00, 4096);
|
|
result = gnome_vfs_read (handle, buffer, 4096, &size);
|
|
if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) {
|
|
e_notice (GTK_WINDOW (toplevel), GNOME_MESSAGE_BOX_WARNING,
|
|
_("Error reading data:\n%s"),
|
|
gnome_vfs_result_to_string (result));
|
|
gnome_vfs_close (handle);
|
|
return;
|
|
}
|
|
if (size == 0)
|
|
break; /* EOF */
|
|
|
|
string = g_string_append (string, buffer);
|
|
}
|
|
|
|
gnome_vfs_close (handle);
|
|
str = string->str;
|
|
g_string_free (string, FALSE);
|
|
|
|
comment = strstr (str, "<!-- EVOLUTION EXECUTIVE SUMMARY SERVICES DO NOT REMOVE -->");
|
|
if (comment == NULL) {
|
|
e_notice (GTK_WINDOW (toplevel), GNOME_MESSAGE_BOX_WARNING,
|
|
_("File does not have a place for the services.\n"));
|
|
g_free (str);
|
|
return;
|
|
}
|
|
|
|
priv->header = g_strndup (str, comment - str);
|
|
priv->header_len = strlen (priv->header);
|
|
priv->footer = g_strdup (comment);
|
|
priv->footer_len = strlen (priv->footer);
|
|
g_free (str);
|
|
}
|
|
|
|
static char *
|
|
load_component_id_stream_read (Bonobo_Stream stream,
|
|
CORBA_Environment *ev)
|
|
{
|
|
Bonobo_Stream_iobuf *buffer;
|
|
GString *str;
|
|
char *ans;
|
|
|
|
str = g_string_sized_new (256);
|
|
#define READ_CHUNK_SIZE 65536
|
|
do {
|
|
int i;
|
|
Bonobo_Stream_read (stream, READ_CHUNK_SIZE, &buffer, ev);
|
|
if (ev->_major != CORBA_NO_EXCEPTION)
|
|
return NULL;
|
|
|
|
/* FIXME: make better PLEASE!!!*/
|
|
for (i = 0; i < buffer->_length; i++)
|
|
g_string_append_c (str, buffer->_buffer[i]);
|
|
|
|
if (buffer->_length <= 0)
|
|
break;
|
|
CORBA_free (buffer);
|
|
} while (1);
|
|
#undef READ_CHUNK_SIZE
|
|
CORBA_free (buffer);
|
|
|
|
ans = str->str;
|
|
g_string_free (str, FALSE);
|
|
|
|
return ans;
|
|
}
|
|
|
|
static char *
|
|
load_component_id (Bonobo_Storage corba_storage,
|
|
CORBA_Environment *ev)
|
|
{
|
|
Bonobo_Stream corba_stream;
|
|
char *iid;
|
|
|
|
corba_stream = Bonobo_Storage_openStream (corba_storage, IID_FILE,
|
|
Bonobo_Storage_READ, ev);
|
|
if (ev->_major != CORBA_NO_EXCEPTION)
|
|
return NULL;
|
|
|
|
if (corba_stream) {
|
|
iid = load_component_id_stream_read (corba_stream, ev);
|
|
Bonobo_Unknown_unref (corba_stream, ev);
|
|
CORBA_Object_release (corba_stream, ev);
|
|
} else {
|
|
g_warning ("Cannot find `%s'", IID_FILE);
|
|
return NULL;
|
|
}
|
|
|
|
return iid;
|
|
}
|
|
|
|
static void
|
|
load_component (ESummary *esummary,
|
|
BonoboStorage *storage,
|
|
int index)
|
|
{
|
|
char *curdir;
|
|
char *iid;
|
|
Bonobo_Storage corba_subdir;
|
|
Bonobo_Storage corba_storage;
|
|
ESummaryWindow *window;
|
|
CORBA_Environment ev;
|
|
|
|
curdir = g_strdup_printf ("%08d", index);
|
|
corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage));
|
|
CORBA_exception_init (&ev);
|
|
|
|
corba_subdir = Bonobo_Storage_openStorage (corba_storage, curdir,
|
|
Bonobo_Storage_READ, &ev);
|
|
iid = load_component_id (corba_subdir, &ev);
|
|
|
|
if (iid) {
|
|
Bonobo_Stream corba_stream;
|
|
|
|
window = e_summary_factory_embed_service_from_id (esummary, iid);
|
|
if (window) {
|
|
if (window->persiststream) {
|
|
corba_stream = Bonobo_Storage_openStream
|
|
(corba_subdir,
|
|
DATA_FILE,
|
|
Bonobo_Storage_READ, &ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION)
|
|
return;
|
|
|
|
Bonobo_PersistStream_load (window->persiststream,
|
|
corba_stream,
|
|
"", &ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION)
|
|
g_warning ("Could not load `%s'", iid);
|
|
|
|
}
|
|
}
|
|
|
|
g_free (iid);
|
|
}
|
|
|
|
CORBA_exception_free (&ev);
|
|
g_free (curdir);
|
|
}
|
|
|
|
static void
|
|
e_summary_load_state (ESummary *esummary,
|
|
const char *path)
|
|
{
|
|
char *fullpath;
|
|
char *htmlpage = NULL;
|
|
BonoboStorage *storage;
|
|
Bonobo_Storage corba_storage;
|
|
Bonobo_Storage_DirectoryList *list;
|
|
CORBA_Environment ev;
|
|
int i;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
fullpath = g_strdup_printf ("%s", path);
|
|
storage = bonobo_storage_open (STORAGE_TYPE, fullpath,
|
|
Bonobo_Storage_READ |
|
|
Bonobo_Storage_WRITE,
|
|
0664);
|
|
if (storage != NULL) {
|
|
CORBA_exception_init (&ev);
|
|
|
|
corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage));
|
|
list = Bonobo_Storage_listContents (corba_storage, "/", 0, &ev);
|
|
if (!list) {
|
|
CORBA_exception_free (&ev);
|
|
bonobo_object_unref (BONOBO_OBJECT (storage));
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < list->_length; i++)
|
|
load_component (esummary, storage, i);
|
|
|
|
CORBA_free (list);
|
|
bonobo_object_unref (BONOBO_OBJECT (storage));
|
|
}
|
|
|
|
g_free (fullpath);
|
|
|
|
/* Load the html page */
|
|
fullpath = g_strdup_printf ("=%s=/executive-summary/page", path);
|
|
htmlpage = gnome_config_get_string (fullpath);
|
|
g_print ("htmlpage: %s\n", htmlpage);
|
|
if (htmlpage) {
|
|
load_html_page (esummary, htmlpage);
|
|
}
|
|
g_free (fullpath);
|
|
g_free (htmlpage);
|
|
}
|
|
|
|
static void
|
|
save_component (BonoboStorage *storage,
|
|
ESummaryWindow *window,
|
|
int index)
|
|
{
|
|
char *curdir = g_strdup_printf ("%08d", index);
|
|
Bonobo_Storage corba_storage;
|
|
Bonobo_Storage corba_subdir;
|
|
CORBA_Environment ev;
|
|
|
|
corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage));
|
|
CORBA_exception_init (&ev);
|
|
|
|
corba_subdir = Bonobo_Storage_openStorage (corba_storage, curdir,
|
|
Bonobo_Storage_CREATE, &ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION) {
|
|
g_warning ("Cannot create '%s'", curdir);
|
|
} else {
|
|
Bonobo_Stream corba_stream;
|
|
|
|
corba_stream = Bonobo_Storage_openStream
|
|
(corba_subdir, IID_FILE, Bonobo_Storage_CREATE, &ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION) {
|
|
g_warning ("EEk: %s", CORBA_exception_id (&ev));
|
|
return;
|
|
}
|
|
|
|
bonobo_stream_client_write_string (corba_stream,
|
|
window->iid, TRUE, &ev);
|
|
Bonobo_Unknown_unref (corba_stream, &ev);
|
|
CORBA_Object_release (corba_stream, &ev);
|
|
|
|
corba_stream = Bonobo_Storage_openStream (corba_subdir, DATA_FILE,
|
|
Bonobo_Storage_CREATE,
|
|
&ev);
|
|
if (window->persiststream != CORBA_OBJECT_NIL) {
|
|
Bonobo_PersistStream_save (window->persiststream,
|
|
corba_stream, "", &ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION) {
|
|
g_warning ("Unable to save %s", window->iid);
|
|
}
|
|
}
|
|
|
|
Bonobo_Unknown_unref (corba_stream, &ev);
|
|
CORBA_Object_release (corba_stream, &ev);
|
|
|
|
Bonobo_Unknown_unref (corba_subdir, &ev);
|
|
CORBA_Object_release (corba_subdir, &ev);
|
|
}
|
|
|
|
g_free (curdir);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
e_summary_save_state (ESummary *esummary,
|
|
const char *path)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
BonoboStorage *storage;
|
|
Bonobo_Storage corba_storage;
|
|
CORBA_Environment ev;
|
|
GList *windows;
|
|
char *fullpath;
|
|
int i;
|
|
|
|
g_return_if_fail (esummary != NULL);
|
|
g_return_if_fail (IS_E_SUMMARY (esummary));
|
|
|
|
priv = esummary->private;
|
|
|
|
#if 0
|
|
fullpath = g_strdup_printf("%s", path);
|
|
g_print ("fullpath: %s\n", fullpath);
|
|
unlink (fullpath);
|
|
|
|
storage = bonobo_storage_open (STORAGE_TYPE, fullpath,
|
|
Bonobo_Storage_READ |
|
|
Bonobo_Storage_WRITE |
|
|
Bonobo_Storage_CREATE, 0660);
|
|
g_return_if_fail (storage);
|
|
|
|
CORBA_exception_init (&ev);
|
|
corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage));
|
|
|
|
i = 0;
|
|
for (windows = priv->window_list; windows; windows = windows->next) {
|
|
save_component (storage, windows->data, i);
|
|
i++;
|
|
}
|
|
|
|
Bonobo_Storage_commit (corba_storage, &ev);
|
|
CORBA_exception_free (&ev);
|
|
bonobo_object_unref (BONOBO_OBJECT (storage));
|
|
|
|
g_free (fullpath);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
e_summary_window_move_left (ESummary *esummary,
|
|
ESummaryWindow *window)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GList *win_item, *grandparent;
|
|
int position;
|
|
|
|
priv = esummary->private;
|
|
|
|
/* Need to cache this location */
|
|
win_item = g_list_find (priv->window_list, window);
|
|
|
|
/* Find the item 2 previous. */
|
|
if (win_item->prev == NULL)
|
|
return; /* Item was first, can't be moved left */
|
|
|
|
grandparent = win_item->prev->prev;
|
|
|
|
/* Remove it from the list */
|
|
priv->window_list = g_list_remove_link (priv->window_list, win_item);
|
|
|
|
/* Insert it after the grandparent */
|
|
position = g_list_position (priv->window_list, grandparent);
|
|
priv->window_list = g_list_insert (priv->window_list, win_item->data,
|
|
position + 1);
|
|
g_list_free_1 (win_item);
|
|
}
|
|
|
|
void
|
|
e_summary_window_move_right (ESummary *esummary,
|
|
ESummaryWindow *window)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GList *win_item, *child;
|
|
int position;
|
|
|
|
priv = esummary->private;
|
|
|
|
win_item = g_list_find (priv->window_list, window);
|
|
|
|
if (win_item->next == NULL)
|
|
return;
|
|
|
|
child = win_item->next;
|
|
|
|
priv->window_list = g_list_remove_link (priv->window_list, win_item);
|
|
|
|
position = g_list_position (priv->window_list, child);
|
|
priv->window_list = g_list_insert (priv->window_list, win_item->data,
|
|
position + 1);
|
|
g_list_free_1 (win_item);
|
|
}
|
|
|
|
void
|
|
e_summary_window_move_up (ESummary *esummary,
|
|
ESummaryWindow *window)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GList *win_item;
|
|
int position;
|
|
|
|
priv = esummary->private;
|
|
|
|
win_item = g_list_find (priv->window_list, window);
|
|
|
|
position = g_list_position (priv->window_list, win_item);
|
|
priv->window_list = g_list_remove_link (priv->window_list, win_item);
|
|
|
|
priv->window_list = g_list_insert (priv->window_list, win_item->data,
|
|
position - 3);
|
|
g_list_free_1 (win_item);
|
|
}
|
|
|
|
void
|
|
e_summary_window_move_down (ESummary *esummary,
|
|
ESummaryWindow *window)
|
|
{
|
|
ESummaryPrivate *priv;
|
|
GList *win_item;
|
|
int position;
|
|
|
|
priv = esummary->private;
|
|
|
|
win_item = g_list_find (priv->window_list, window);
|
|
|
|
position = g_list_position (priv->window_list, win_item);
|
|
priv->window_list = g_list_remove_link (priv->window_list, win_item);
|
|
|
|
priv->window_list = g_list_insert (priv->window_list, win_item->data,
|
|
position + 3);
|
|
}
|