diff options
author | Ettore Perazzoli <ettore@src.gnome.org> | 1999-11-06 07:06:09 +0800 |
---|---|---|
committer | Ettore Perazzoli <ettore@src.gnome.org> | 1999-11-06 07:06:09 +0800 |
commit | b681ec2b9a98684ef821f9b6fbdb9a231a58d4b5 (patch) | |
tree | 6dc964528b9db296aa1dfedde9a2b2122fd0db8e | |
parent | c8fce201dc8b14505f2e0387689947922e08f956 (diff) | |
download | gsoc2013-evolution-b681ec2b9a98684ef821f9b6fbdb9a231a58d4b5.tar.gz gsoc2013-evolution-b681ec2b9a98684ef821f9b6fbdb9a231a58d4b5.tar.zst gsoc2013-evolution-b681ec2b9a98684ef821f9b6fbdb9a231a58d4b5.zip |
Here is my initial Evolution work: message composition widget and some
installation fixes for Camel.
svn path=/trunk/; revision=1369
37 files changed, 3325 insertions, 53 deletions
@@ -1,3 +1,41 @@ +1999-11-05 Ettore Perazzoli <ettore@gnu.org> + + * tests/ui-tests/msg-composer-test.c: New file for testing the + `EMsgComposer' widget. + * tests/ui-tests/Makefile.am (noinst_PROGRAMS): Compile it. Do + not compile `store_listing' for now because it's currently broken. + (INCLUDES): Added the `widgets' source directory to the include + path list. + (LDADD): Removed the MH dependency; link with + `libevolutionwidgets.la' from the `widgets' directory. + + * configure.in: Create `widgets/Makefile'. + + * camel/gmime-rfc2047.c (rfc2047_clean): Removed C++-like comment. + * camel/camel-folder.c (camel_folder_get_message_uid_by_number): + Likewise. + * camel/gmime-content-field.c (gmime_content_field_get_parameter): + Likewise. + * camel/camel.c (camel_init): Likewise. + * camel/camel-provider.c (camel_provider_register): Likewise. + * camel/camel-multipart.c (_construct_from_stream): Likewise. + * camel/camel-mime-part.c (_write_content_to_stream): Likewise. + * camel/camel-medium.c (camel_medium_class_init): Likewise. + + * camel/camel-data-wrapper.h (camel_data_wrapper_get_type): Make + prototype non-static. + + * camel/Makefile.am (libcamelinclude_HEADERS): Move + `camel-exception-list.def' from `EXTRA_DIST' to + `libcamelinclude_HEADERS'. + + * camel/camel.h: Do not #include <config.h>. + * camel/data-wrapper-repository.h: Likewise. + +1999-11-05 Ettore Perazzoli <ettore@gnu.org> + + * tests/Makefile.am (INCLUDES): Add `-I$(top_srcdir)'. + 1999-10-13 bertrand <Bertrand.Guiheneuf@aful.org> * camel/camel-folder.c (camel_folder_close): the diff --git a/camel/Makefile.am b/camel/Makefile.am index b9316d1fca..0f5a4227b2 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -98,6 +98,7 @@ libcamelinclude_HEADERS = \ md5-utils.h \ string-utils.h \ url-util.h \ + camel-exception-list.def \ $(pthread_HDR) libcamel_extra_sources = \ @@ -106,4 +107,4 @@ libcamel_extra_sources = \ libcamel_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir) -EXTRA_DIST = README camel-exception-list.def +EXTRA_DIST = README diff --git a/camel/camel-data-wrapper.h b/camel/camel-data-wrapper.h index bc98f85c7e..2f56ed2000 100644 --- a/camel/camel-data-wrapper.h +++ b/camel/camel-data-wrapper.h @@ -79,7 +79,7 @@ GtkType camel_data_wrapper_get_type (void); void camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); void camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); void camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper, gchar *mime_type); -static gchar *camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper); +gchar *camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper); GMimeContentField *camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper); void camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper, GMimeContentField *mime_type); diff --git a/camel/camel-folder.c b/camel/camel-folder.c index d890ffd69d..cacfa318e0 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -1128,8 +1128,8 @@ _get_message_uid_by_number (CamelFolder *folder, gint message_number, CamelExcep const gchar * camel_folder_get_message_uid_by_number (CamelFolder *folder, gint message_number, CamelException *ex) { - //if (!folder->has_uid_capability) return NULL; - //return CF_CLASS (folder)->get_message_uid_by_number (folder, message_number, ex); + /* if (!folder->has_uid_capability) return NULL; */ + /* return CF_CLASS (folder)->get_message_uid_by_number (folder, message_number, ex); */ } diff --git a/camel/camel-medium.c b/camel/camel-medium.c index d26b64a246..01aa440f84 100644 --- a/camel/camel-medium.c +++ b/camel/camel-medium.c @@ -67,11 +67,9 @@ camel_medium_class_init (CamelMediumClass *camel_medium_class) camel_medium_class->set_content_object = _set_content_object; camel_medium_class->get_content_object = _get_content_object; - - /* virtual method overload */ - // camel_data_wrapper_class->write_to_stream = _write_to_stream; - //camel_data_wrapper_class->construct_from_stream = _construct_from_stream; + /* camel_data_wrapper_class->write_to_stream = _write_to_stream; */ + /* camel_data_wrapper_class->construct_from_stream = _construct_from_stream; */ gtk_object_class->finalize = _finalize; } diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index 71a4c80643..180a843c02 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -628,10 +628,13 @@ _write_content_to_stream (CamelMimePart *mime_part, CamelStream *stream) CAMEL_LOG_FULL_DEBUG ( "Entering CamelMimePart::_write_content_to_stream\n"); CAMEL_LOG_FULL_DEBUG ( "CamelMimePart::_write_content_to_stream, content=%p\n", content); if (!content) return; - // buffer_size = camel_data_wrapper_size (content); - //buffer = g_malloc (buffer_size); + + /* buffer_size = camel_data_wrapper_size (content); */ + /* buffer = g_malloc (buffer_size); */ + camel_data_wrapper_write_to_stream (content, stream); - + +#if 0 //if (mime_part->encoding) { // encoded_buffer_size = gmime_encoded_size(buffer, buffer_size, encoding); // encoded_buffer = g_malloc (encoded_buffer_size); @@ -642,6 +645,8 @@ _write_content_to_stream (CamelMimePart *mime_part, CamelStream *stream) //fwrite (buffer, buffer_size, 1, file); //camel_stream_write (stream, buffer, buffer_size); //g_free (buffer); +#endif + CAMEL_LOG_FULL_DEBUG ( "Leaving CamelMimePart::_write_content_to_stream\n"); } diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c index 7df44b6cb2..f3128be9e7 100644 --- a/camel/camel-multipart.c +++ b/camel/camel-multipart.c @@ -474,7 +474,8 @@ _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) CAMEL_LOG_FULL_DEBUG ("CamelMultipart::construct_from_stream freeing new_part_stream:%p\n", new_part_stream); gtk_object_unref (GTK_OBJECT (new_part_stream)); if (multipart->preface) g_free (multipart->preface); - //if ( (new_part->str)[0] != '\0') multipart->preface = g_strdup (new_part->str); + + /* if ( (new_part->str)[0] != '\0') multipart->preface = g_strdup (new_part->str); */ /* read all the real parts */ while (!end_of_multipart) { @@ -490,12 +491,14 @@ _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) } - //g_string_assign (new_part, ""); - //_read_part (new_part, stream, real_boundary_line, end_boundary_line); + /* g_string_assign (new_part, ""); */ + /* _read_part (new_part, stream, real_boundary_line, end_boundary_line); */ + if (multipart->postface) g_free (multipart->postface); - //if ( (new_part->str)[0] != '\0') multipart->postface = g_strdup (new_part->str); + /* if ( (new_part->str)[0] != '\0') multipart->postface = g_strdup (new_part->str); */ + + /* g_string_free (new_part, TRUE); */ - //g_string_free (new_part, TRUE); g_free (real_boundary_line); g_free (end_boundary_line); CAMEL_LOG_FULL_DEBUG ("Leaving CamelMultipart::_construct_from_stream\n"); diff --git a/camel/camel-provider.c b/camel/camel-provider.c index 362ad087bc..7664838975 100644 --- a/camel/camel-provider.c +++ b/camel/camel-provider.c @@ -72,15 +72,14 @@ camel_provider_register (CamelProvider *provider) old_provider_node = g_list_find_custom (_provider_list, provider, _provider_name_cmp); if (old_provider_node != NULL) { - // camel_provider_unref (CAMEL_PROVIDER (old_provider_node->data)); + /* camel_provider_unref (CAMEL_PROVIDER (old_provider_node->data)); */ old_provider_node->data = provider; } else { /* be careful, we use prepend here, so that last registered providers come first */ _provider_list = g_list_prepend (_provider_list, provider); } - // camel_provider_ref (provider); - + /* camel_provider_ref (provider); */ } diff --git a/camel/camel.c b/camel/camel.c index 51bf4ca8ee..68d0a54407 100644 --- a/camel/camel.c +++ b/camel/camel.c @@ -35,6 +35,5 @@ camel_init() printf ("Threads are not supported by glib\n"); #endif /* G_THREADS_ENABLED */ - //return data_wrapper_repository_init (); - + /* return data_wrapper_repository_init (); */ } diff --git a/camel/camel.h b/camel/camel.h index 9a3898e055..b21ccf5e78 100644 --- a/camel/camel.h +++ b/camel/camel.h @@ -34,7 +34,6 @@ extern "C" { #endif /* __cplusplus }*/ #include <gtk/gtk.h> -#include <config.h> #include <camel/data-wrapper-repository.h> #include <camel/data-wrapper-repository.h> #include <camel/camel-log.h> diff --git a/camel/data-wrapper-repository.h b/camel/data-wrapper-repository.h index 8999467175..27f782878a 100644 --- a/camel/data-wrapper-repository.h +++ b/camel/data-wrapper-repository.h @@ -34,7 +34,6 @@ extern "C" { #endif /* __cplusplus }*/ #include <glib.h> -#include <config.h> #include "camel-data-wrapper.h" diff --git a/camel/gmime-content-field.c b/camel/gmime-content-field.c index 79d4d1bdca..43691f0d62 100644 --- a/camel/gmime-content-field.c +++ b/camel/gmime-content-field.c @@ -261,7 +261,7 @@ gmime_content_field_get_parameter (GMimeContentField *content_field, const gchar g_assert (content_field->parameters); g_assert (name); CAMEL_LOG_FULL_DEBUG ("GMimeContentField::get_parameter looking for parameter \"%s\"\n", name); - //parameter = (const gchar *)g_hash_table_lookup (content_field->parameters, name); + /* parameter = (const gchar *)g_hash_table_lookup (content_field->parameters, name); */ parameter_exists = g_hash_table_lookup_extended (content_field->parameters, name, (gpointer *) &old_name, diff --git a/camel/gmime-rfc2047.c b/camel/gmime-rfc2047.c index 587c654d9f..7da12450b6 100644 --- a/camel/gmime-rfc2047.c +++ b/camel/gmime-rfc2047.c @@ -240,8 +240,9 @@ gmime_rfc2047_decode (const gchar *data, const gchar *into_what) #define isnt_ascii(a) ((a) <= 0x1f || (a) >= 0x7f) static int -rfc2047_clean (const gchar *string, const gchar *max) { - // if (strstr (string, "?=")) return 1; +rfc2047_clean (const gchar *string, const gchar *max) +{ + /* if (strstr (string, "?=")) return 1; */ while (string < max) { if (isnt_ascii ((unsigned char)*string)) return 0; diff --git a/configure.in b/configure.in index cb7fbe60b2..e59611e040 100644 --- a/configure.in +++ b/configure.in @@ -106,4 +106,5 @@ devel-docs/Makefile devel-docs/camel/Makefile tests/Makefile tests/ui-tests/Makefile +widgets/Makefile ]) diff --git a/tests/Makefile.am b/tests/Makefile.am index be6523dfbd..85ee40b3a1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ # process this file with automake to create Makefile.in -INCLUDES = -I$(top_srcdir)/intl -I$(top_srcdir)/camel \ +INCLUDES = -I$(top_srcdir)/intl -I$(top_srcdir) -I$(top_srcdir)/camel \ -I$(includedir) -I$(top_srcdir)/camel/providers/MH LDADD = \ $(top_builddir)/camel/libcamel.la \ diff --git a/tests/ui-tests/.cvsignore b/tests/ui-tests/.cvsignore index be569b9c4c..10c9ca5909 100644 --- a/tests/ui-tests/.cvsignore +++ b/tests/ui-tests/.cvsignore @@ -3,3 +3,4 @@ Makefile .deps .libs store_listing +msg-composer-test diff --git a/tests/ui-tests/Makefile.am b/tests/ui-tests/Makefile.am index c4849e7c3c..24d62047db 100644 --- a/tests/ui-tests/Makefile.am +++ b/tests/ui-tests/Makefile.am @@ -1,17 +1,19 @@ # process this file with automake to create Makefile.in -INCLUDES = -I$(top_srcdir)/intl -I$(top_srcdir)/camel \ - -I$(includedir) -I$(top_srcdir)/camel/providers/MH \ +INCLUDES = \ + -I$(top_srcdir)/intl \ + -I$(top_srcdir)/camel \ + -I$(includedir) \ + -I$(top_srcdir)/camel/providers/MH \ + -I$(top_srcdir)/widgets \ $(EXTRA_GNOME_CFLAGS) -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/camel/providers/MH/libcamelmh.la \ - $(INTLLIBS) $(EXTRA_GNOME_LIBS) $(PTHREAD_LIB) +LDADD = \ + $(top_builddir)/widgets/libevolutionwidgets.la \ + $(top_builddir)/camel/libcamel.la \ + $(INTLLIBS) \ + $(EXTRA_GNOME_LIBS) \ + $(PTHREAD_LIB) - - - - -noinst_PROGRAMS = \ - store_listing
\ No newline at end of file +noinst_PROGRAMS = \ + msg-composer-test
\ No newline at end of file diff --git a/tests/ui-tests/msg-composer-test.c b/tests/ui-tests/msg-composer-test.c new file mode 100644 index 0000000000..8fbf01b5e8 --- /dev/null +++ b/tests/ui-tests/msg-composer-test.c @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +#include <gnome.h> + +#include <camel/camel-data-wrapper.h> +#include <camel/camel-stream-fs.h> +#include <camel/camel-stream.h> + +#include "e-msg-composer.h" + +static void +send_cb (EMsgComposer *composer, + gpointer data) +{ + CamelMimeMessage *message; + CamelStream *stream; + gint stdout_dup; + + message = e_msg_composer_get_message (composer); + + stdout_dup = dup (1); + stream = camel_stream_fs_new_with_fd (stdout_dup); + camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), + stream); + camel_stream_close (stream); + + gtk_object_unref (GTK_OBJECT (message)); + +#if 0 + gtk_widget_destroy (GTK_WIDGET (composer)); + gtk_main_quit (); +#endif +} + +int +main (int argc, char **argv) +{ + GtkWidget *composer; + + gnome_init ("test", "0.0", argc, argv); + glade_gnome_init (); + + composer = e_msg_composer_new (); + gtk_widget_show (composer); + + gtk_signal_connect (GTK_OBJECT (composer), "send", + GTK_SIGNAL_FUNC (send_cb), NULL); + + gtk_main (); + + return 0; +} diff --git a/widgets/.cvsignore b/widgets/.cvsignore new file mode 100644 index 0000000000..09980ae6ba --- /dev/null +++ b/widgets/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.la diff --git a/widgets/ChangeLog b/widgets/ChangeLog index e8d0c8e9ed..77a6c36c61 100644 --- a/widgets/ChangeLog +++ b/widgets/ChangeLog @@ -1,3 +1,26 @@ +1999-11-05 Ettore Perazzoli <ettore@gnu.org> + + * Makefile.am: Compile the new files in a `libevolutionwidgets' + library. + (CPPFLAGS): #define `E_GUIDIR'. + + * e-msg-composer.c, e-msg-composer.h: New files implementing an + initial version of the Evolution message composer widget. + + * e-msg-composer-address-entry.c, e-msg-composer-address-entry.h: + New files implementing a GtkEntry customized for entering email + address lists. + + * e-msg-composer-attachment-bar.c, e-msg-composer-attachment-bar.h: + New files implementing a widget for editing mail attachments. + + * e-msg-composer-attachment.c, e-msg-composer-attachment.h: New + files implementing file attachment objects for the message + composer. + + * e-msg-composer-hdrs.c, e-msg-composer-hdrs.h: New files + implementing a widget for editing of email message headers. + 1999-10-31 Miguel de Icaza <miguel@gnu.org> * widgets/e-table-column.c, e-table-column.h: New file, implements the diff --git a/widgets/Makefile.am b/widgets/Makefile.am index d6aa94fb90..35d1bc64a4 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -1,7 +1,29 @@ -noinst_LIBRARIES = \ - e-table-simple.c \ - e-table-simple.h \ - e-table-model.c \ - e-table-model.h \ - e-table-column-model.c \ - e-table-column-model.h \ +guidir = $(datadir)/evolution/gui + +gui_DATA = \ + e-msg-composer-attachment.glade \ + e-msg-composer.glade + +INCLUDES = \ + -I$(top_srcdir)/camel \ + -I$(top_builddir)/camel \ + $(GNOME_INCLUDEDIR) + +CPPFLAGS = \ + -DE_GUIDIR=\"$(guidir)\" + +noinst_LTLIBRARIES = \ + libevolutionwidgets.la + +libevolutionwidgets_la_SOURCES = \ + e-msg-composer-address-entry.c \ + e-msg-composer-address-entry.h \ + e-msg-composer-attachment-bar.c \ + e-msg-composer-attachment-bar.h \ + e-msg-composer-attachment.c \ + e-msg-composer-attachment.h \ + e-msg-composer-hdrs.c \ + e-msg-composer-hdrs.h \ + e-msg-composer.c \ + e-msg-composer.h + diff --git a/widgets/e-msg-composer-address-entry.c b/widgets/e-msg-composer-address-entry.c new file mode 100644 index 0000000000..071730eef2 --- /dev/null +++ b/widgets/e-msg-composer-address-entry.c @@ -0,0 +1,142 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-address-entry.c + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +/* This is a custom GtkEntry for entering address lists. For now, it does not + have any fancy features, but in the future we might want to make it + cooler. */ + +#include <gnome.h> + +#include "e-msg-composer-address-entry.h" + + +static GtkEntryClass *parent_class = NULL; + + +/* Initialization. */ + +static void +class_init (EMsgComposerAddressEntryClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + + parent_class = gtk_type_class (gtk_entry_get_type ()); +} + +static void +init (EMsgComposerAddressEntry *msg_composer_address_entry) +{ +} + +GtkType +e_msg_composer_address_entry_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposerAddressEntry", + sizeof (EMsgComposerAddressEntry), + sizeof (EMsgComposerAddressEntryClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_entry_get_type (), &info); + } + + return type; +} + + +GtkWidget * +e_msg_composer_address_entry_new (void) +{ + GtkWidget *new; + + new = gtk_type_new (e_msg_composer_address_entry_get_type ()); + + return new; +} + + +/** + * e_msg_composer_address_entry_get_addresses: + * @entry: An address entry widget + * + * Retrieve the list of addresses stored in @entry. + * + * Return value: A GList of pointers to strings representing the addresses. + * Notice that the strings must be freed by the caller when not needed anymore. + **/ +GList * +e_msg_composer_address_entry_get_addresses (EMsgComposerAddressEntry *entry) +{ + GList *list; + const gchar *s; + const gchar *p, *oldp; + gboolean in_quotes; + + s = gtk_entry_get_text (GTK_ENTRY (entry)); + + in_quotes = FALSE; + list = NULL; + + p = s; + oldp = s; + + while (1) { + if (*p == '"') { + in_quotes = ! in_quotes; + p++; + } else if ((! in_quotes && *p == ',') || *p == 0) { + if (p != oldp) { + gchar *new_addr; + + new_addr = g_strndup (oldp, p - oldp); + new_addr = g_strstrip (new_addr); + if (*new_addr != '\0') + list = g_list_prepend (list, new_addr); + else + g_free (new_addr); + } + + while (*p == ',' || *p == ' ' || *p == '\t') + p++; + + if (*p == 0) + break; + + oldp = p; + } else { + p++; + } + } + + return g_list_reverse (list); +} diff --git a/widgets/e-msg-composer-address-entry.h b/widgets/e-msg-composer-address-entry.h new file mode 100644 index 0000000000..d4ab46797d --- /dev/null +++ b/widgets/e-msg-composer-address-entry.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-address-entry.h + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#ifndef __E_MSG_COMPOSER_ADDRESS_ENTRY_H__ +#define __E_MSG_COMPOSER_ADDRESS_ENTRY_H__ + +#include <gnome.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_MSG_COMPOSER_ADDRESS_ENTRY (e_msg_composer_address_entry_get_type ()) +#define E_MSG_COMPOSER_ADDRESS_ENTRY(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_ADDRESS_ENTRY, EMsgComposerAddressEntry)) +#define E_MSG_COMPOSER_ADDRESS_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_ADDRESS_ENTRY, EMsgComposerAddressEntryClass)) +#define E_IS_MSG_COMPOSER_ADDRESS_ENTRY(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_ADDRESS_ENTRY)) +#define E_IS_MSG_COMPOSER_ADDRESS_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_ADDRESS_ENTRY)) + + +typedef struct _EMsgComposerAddressEntry EMsgComposerAddressEntry; +typedef struct _EMsgComposerAddressEntryClass EMsgComposerAddressEntryClass; + +struct _EMsgComposerAddressEntry { + GtkEntry parent; +}; + +struct _EMsgComposerAddressEntryClass { + GtkEntryClass parent_class; +}; + + +GtkType e_msg_composer_address_entry_get_type (void); +GtkWidget *e_msg_composer_address_entry_new (void); +GList *e_msg_composer_address_entry_get_addresses (EMsgComposerAddressEntry *entry); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_MSG_COMPOSER_ADDRESS_ENTRY_H__ */ diff --git a/widgets/e-msg-composer-attachment-bar.c b/widgets/e-msg-composer-attachment-bar.c new file mode 100644 index 0000000000..25cc2ff138 --- /dev/null +++ b/widgets/e-msg-composer-attachment-bar.c @@ -0,0 +1,602 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-attachment-bar.c + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#include <gnome.h> +#include <glade/glade.h> + +#include "e-msg-composer-attachment.h" +#include "e-msg-composer-attachment-bar.h" + + +#define ICON_WIDTH 64 +#define ICON_SEPARATORS " /-_." +#define ICON_SPACING 2 +#define ICON_ROW_SPACING ICON_SPACING +#define ICON_COL_SPACING ICON_SPACING +#define ICON_BORDER 2 +#define ICON_TEXT_SPACING 2 + + +static GnomeIconListClass *parent_class = NULL; + +struct _EMsgComposerAttachmentBarPrivate { + GList *attachments; + guint num_attachments; + + GtkWidget *context_menu; + GtkWidget *icon_context_menu; +}; + + +enum { + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +static void update (EMsgComposerAttachmentBar *bar); + + +/* Sorting. */ + +static gint +attachment_sort_func (gconstpointer a, gconstpointer b) +{ + const EMsgComposerAttachment *attachment_a, *attachment_b; + + attachment_a = (EMsgComposerAttachment *) a; + attachment_b = (EMsgComposerAttachment *) b; + + return strcmp (attachment_a->description, attachment_b->description); +} + +static void +sort (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + + priv = bar->priv; + + priv->attachments = g_list_sort (priv->attachments, + attachment_sort_func); +} + + +/* Attachment handling functions. */ + +static void +free_attachment_list (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + GList *p; + + priv = bar->priv; + + for (p = priv->attachments; p != NULL; p = p->next) + gtk_object_unref (GTK_OBJECT (p->data)); +} + +static void +attachment_changed_cb (EMsgComposerAttachment *attachment, + gpointer data) +{ + update (E_MSG_COMPOSER_ATTACHMENT_BAR (data)); +} + +static void +add_from_file (EMsgComposerAttachmentBar *bar, + const gchar *file_name) +{ + EMsgComposerAttachment *attachment; + + attachment = e_msg_composer_attachment_new (file_name); + + gtk_signal_connect (GTK_OBJECT (attachment), "changed", + GTK_SIGNAL_FUNC (attachment_changed_cb), + bar); + + bar->priv->attachments = g_list_append (bar->priv->attachments, + attachment); + bar->priv->num_attachments++; + + sort (bar); + update (bar); + + gtk_signal_emit (GTK_OBJECT (bar), signals[CHANGED]); +} + +static void +remove_attachment (EMsgComposerAttachmentBar *bar, + EMsgComposerAttachment *attachment) +{ + bar->priv->attachments = g_list_remove (bar->priv->attachments, + attachment); + bar->priv->num_attachments--; + + gtk_object_unref (GTK_OBJECT (attachment)); + + gtk_signal_emit (GTK_OBJECT (bar), signals[CHANGED]); +} + + +/* Icon list contents handling. */ + +static void +update (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + GnomeIconList *icon_list; + GList *p; + + priv = bar->priv; + icon_list = GNOME_ICON_LIST (bar); + + gnome_icon_list_freeze (icon_list); + + gnome_icon_list_clear (icon_list); + + /* FIXME could be faster, but we don't care. */ + + for (p = priv->attachments; p != NULL; p = p->next) { + EMsgComposerAttachment *attachment; + const gchar *icon_name; + + attachment = p->data; + icon_name = gnome_mime_get_value (attachment->mime_type, + "icon-filename"); + + /* FIXME we need some better default icon. */ + if (icon_name == NULL) + icon_name = gnome_mime_get_value ("text/plain", + "icon-filename"); + + gnome_icon_list_append (icon_list, icon_name, + attachment->description); + } + + gnome_icon_list_thaw (icon_list); +} + +static void +remove_selected (EMsgComposerAttachmentBar *bar) +{ + GnomeIconList *icon_list; + EMsgComposerAttachment *attachment; + gint num; + + icon_list = GNOME_ICON_LIST (bar); + num = GPOINTER_TO_INT (icon_list->selection->data); + + /* FIXME do this with icon data. */ + + attachment = E_MSG_COMPOSER_ATTACHMENT + (g_list_nth (bar->priv->attachments, num)->data); + + remove_attachment (bar, attachment); + update (bar); +} + +static void +edit_selected (EMsgComposerAttachmentBar *bar) +{ + GnomeIconList *icon_list; + EMsgComposerAttachment *attachment; + gint num; + + icon_list = GNOME_ICON_LIST (bar); + + num = GPOINTER_TO_INT (icon_list->selection->data); + attachment = g_list_nth (bar->priv->attachments, num)->data; + + e_msg_composer_attachment_edit (attachment, GTK_WIDGET (bar)); +} + + +/* "Attach" dialog. */ + +static void +attach_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachmentBar *bar; + GtkWidget *file_selection; + const gchar *file_name; + + file_selection = gtk_widget_get_toplevel (widget); + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); + + file_name = gtk_file_selection_get_filename + (GTK_FILE_SELECTION (file_selection)); + add_from_file (bar, file_name); + + gtk_widget_hide (file_selection); +} + +static void +add_from_user (EMsgComposerAttachmentBar *bar) +{ + GtkWidget *file_selection; + GtkWidget *cancel_button; + GtkWidget *ok_button; + + file_selection = gtk_file_selection_new (_("Add attachment")); + gtk_window_set_position (GTK_WINDOW (file_selection), + GTK_WIN_POS_MOUSE); + + ok_button = GTK_FILE_SELECTION (file_selection)->ok_button; + gtk_signal_connect (GTK_OBJECT (ok_button), + "clicked", GTK_SIGNAL_FUNC (attach_cb), bar); + + cancel_button = GTK_FILE_SELECTION (file_selection)->cancel_button; + gtk_signal_connect_object (GTK_OBJECT (cancel_button), + "clicked", + GTK_SIGNAL_FUNC (gtk_widget_hide), + GTK_OBJECT (file_selection)); + + gtk_widget_show (GTK_WIDGET (file_selection)); +} + + +/* Callbacks. */ + +static void +add_cb (GtkWidget *widget, + gpointer data) +{ + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); + + add_from_user (E_MSG_COMPOSER_ATTACHMENT_BAR (data)); +} + +static void +properties_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachmentBar *bar; + + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); + edit_selected (data); +} + +static void +remove_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachmentBar *bar; + + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); + remove_selected (bar); +} + + +/* Popup menu handling. */ + +static GnomeUIInfo icon_context_menu_info[] = { + GNOMEUIINFO_ITEM (N_("Remove"), + N_("Remove this item from the attachment list"), + remove_cb, NULL), + GNOMEUIINFO_MENU_PROPERTIES_ITEM (properties_cb, NULL), + GNOMEUIINFO_END +}; + +static GtkWidget * +get_icon_context_menu (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + + priv = bar->priv; + if (priv->icon_context_menu == NULL) + priv->icon_context_menu = gnome_popup_menu_new + (icon_context_menu_info); + + return priv->icon_context_menu; +} + +static void +popup_icon_context_menu (EMsgComposerAttachmentBar *bar, + gint num, + GdkEventButton *event) +{ + GtkWidget *menu; + + menu = get_icon_context_menu (bar); + gnome_popup_menu_do_popup (menu, NULL, NULL, event, bar); +} + +static GnomeUIInfo context_menu_info[] = { + GNOMEUIINFO_ITEM (N_("Add attachment..."), + N_("Attach a file to the message"), + add_cb, NULL), + GNOMEUIINFO_END +}; + +static GtkWidget * +get_context_menu (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + + priv = bar->priv; + if (priv->context_menu == NULL) + priv->context_menu = gnome_popup_menu_new (context_menu_info); + + return priv->context_menu; +} + +static void +popup_context_menu (EMsgComposerAttachmentBar *bar, + GdkEventButton *event) +{ + GtkWidget *menu; + + menu = get_context_menu (bar); + gnome_popup_menu_do_popup (menu, NULL, NULL, event, bar); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EMsgComposerAttachmentBar *bar; + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (object); + + free_attachment_list (bar); +} + + +/* GtkWidget methods. */ + +static gint +button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + EMsgComposerAttachmentBar *bar; + GnomeIconList *icon_list; + gint icon_number; + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (widget); + icon_list = GNOME_ICON_LIST (widget); + + if (event->button != 3) + return GTK_WIDGET_CLASS (parent_class)->button_press_event + (widget, event); + + icon_number = gnome_icon_list_get_icon_at (icon_list, + event->x, event->y); + + if (icon_number >= 0) { + gnome_icon_list_select_icon (icon_list, icon_number); + popup_icon_context_menu (bar, icon_number, event); + } else { + popup_context_menu (bar, event); + } + + return TRUE; +} + + +/* GnomeIconList methods. */ + +static gboolean +text_changed (GnomeIconList *gil, + gint num, + const gchar *new_text) +{ + EMsgComposerAttachmentBar *bar; + EMsgComposerAttachment *attachment; + GList *p; + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (gil); + p = g_list_nth (bar->priv->attachments, num); + attachment = p->data; + + g_free (attachment->description); + attachment->description = g_strdup (new_text); + + return TRUE; +} + + +/* Initialization. */ + +static void +class_init (EMsgComposerAttachmentBarClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GnomeIconListClass *icon_list_class; + + object_class = GTK_OBJECT_CLASS (class); + widget_class = GTK_WIDGET_CLASS (class); + icon_list_class = GNOME_ICON_LIST_CLASS (class); + + parent_class = gtk_type_class (gnome_icon_list_get_type ()); + + object_class->destroy = destroy; + + widget_class->button_press_event = button_press_event; + + icon_list_class->text_changed = text_changed; + + /* Setup signals. */ + + signals[CHANGED] = + gtk_signal_new ("changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EMsgComposerAttachmentBarClass, + changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + guint icon_size; + + priv = g_new (EMsgComposerAttachmentBarPrivate, 1); + + priv->attachments = NULL; + priv->context_menu = NULL; + priv->icon_context_menu = NULL; + + priv->num_attachments = 0; + + bar->priv = priv; + + /* FIXME partly hardcoded. We should compute height from the font, and + allow at least 2 lines for every item. */ + icon_size = ICON_WIDTH + ICON_SPACING + ICON_BORDER + ICON_TEXT_SPACING + 24; + + gtk_widget_set_usize (GTK_WIDGET (bar), icon_size * 4, icon_size); +} + + +GtkType +e_msg_composer_attachment_bar_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposerAttachmentBar", + sizeof (EMsgComposerAttachmentBar), + sizeof (EMsgComposerAttachmentBarClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gnome_icon_list_get_type (), &info); + } + + return type; +} + +GtkWidget * +e_msg_composer_attachment_bar_new (GtkAdjustment *adj) +{ + EMsgComposerAttachmentBar *new; + GnomeIconList *icon_list; + + gtk_widget_push_visual (gdk_imlib_get_visual ()); + gtk_widget_push_colormap (gdk_imlib_get_colormap ()); + new = gtk_type_new (e_msg_composer_attachment_bar_get_type ()); + gtk_widget_pop_visual (); + gtk_widget_pop_colormap (); + + icon_list = GNOME_ICON_LIST (new); + + gnome_icon_list_construct (icon_list, ICON_WIDTH, adj, + GNOME_ICON_LIST_IS_EDITABLE); + + gnome_icon_list_set_separators (icon_list, ICON_SEPARATORS); + gnome_icon_list_set_row_spacing (icon_list, ICON_ROW_SPACING); + gnome_icon_list_set_col_spacing (icon_list, ICON_COL_SPACING); + gnome_icon_list_set_icon_border (icon_list, ICON_BORDER); + gnome_icon_list_set_text_spacing (icon_list, ICON_TEXT_SPACING); + gnome_icon_list_set_selection_mode (icon_list, GTK_SELECTION_SINGLE); + + return GTK_WIDGET (new); +} + + +static void +attach_to_multipart (CamelMultipart *multipart, + EMsgComposerAttachment *attachment) +{ + CamelMimeBodyPart *part; + + /* FIXME encoding etc. etc. ? */ + /* FIXME I am not sure how to add an attachment through the Camel + API. :-/ */ + + part = camel_mime_body_part_new (); + camel_mime_part_set_disposition (CAMEL_MIME_PART (part), "attachment"); + camel_mime_part_set_filename (CAMEL_MIME_PART (part), + g_strdup (g_basename (attachment->file_name))); + camel_mime_part_set_description (CAMEL_MIME_PART (part), + g_strdup (attachment->description)); + camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (part), + g_strdup (attachment->mime_type)); +} + +void +e_msg_composer_attachment_bar_to_multipart (EMsgComposerAttachmentBar *bar, + CamelMultipart *multipart) +{ + EMsgComposerAttachmentBarPrivate *priv; + GList *p; + + g_return_if_fail (bar != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); + g_return_if_fail (multipart != NULL); + g_return_if_fail (IS_CAMEL_MULTIPART (multipart)); + + priv = bar->priv; + + for (p = priv->attachments; p != NULL; p = p->next) { + EMsgComposerAttachment *attachment; + + attachment = E_MSG_COMPOSER_ATTACHMENT (p->data); + attach_to_multipart (multipart, attachment); + } +} + + +guint +e_msg_composer_attachment_bar_get_num_attachments (EMsgComposerAttachmentBar *bar) +{ + g_return_val_if_fail (bar != NULL, 0); + g_return_val_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar), 0); + + return bar->priv->num_attachments; +} + + +void +e_msg_composer_attachment_bar_attach (EMsgComposerAttachmentBar *bar, + const gchar *file_name) +{ + g_return_if_fail (bar != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); + + if (file_name == NULL) + add_from_user (bar); + else + add_from_file (bar, file_name); +} diff --git a/widgets/e-msg-composer-attachment-bar.h b/widgets/e-msg-composer-attachment-bar.h new file mode 100644 index 0000000000..803b51a954 --- /dev/null +++ b/widgets/e-msg-composer-attachment-bar.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* msg-composer-attachment-bar.h + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#ifndef __E_MSG_COMPOSER_ATTACHMENT_BAR_H__ +#define __E_MSG_COMPOSER_ATTACHMENT_BAR_H__ + +#include <gnome.h> +#include <camel/camel-multipart.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR \ + (e_msg_composer_attachment_bar_get_type ()) +#define E_MSG_COMPOSER_ATTACHMENT_BAR(obj) \ + (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR, EMsgComposerAttachmentBar)) +#define E_MSG_COMPOSER_ATTACHMENT_BAR_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR, EMsgComposerAttachmentBarClass)) +#define E_IS_MSG_COMPOSER_ATTACHMENT_BAR(obj) \ + (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR)) +#define E_IS_MSG_COMPOSER_ATTACHMENT_BAR_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR)) + + +typedef struct _EMsgComposerAttachmentBarPrivate EMsgComposerAttachmentBarPrivate; + +struct _EMsgComposerAttachmentBar { + GnomeIconList parent; + + EMsgComposerAttachmentBarPrivate *priv; +}; +typedef struct _EMsgComposerAttachmentBar EMsgComposerAttachmentBar; + +struct _EMsgComposerAttachmentBarClass { + GnomeIconListClass parent_class; + + void (* changed) (EMsgComposerAttachmentBar *bar); +}; +typedef struct _EMsgComposerAttachmentBarClass EMsgComposerAttachmentBarClass; + + +GtkType e_msg_composer_attachment_bar_get_type (void); +GtkWidget *e_msg_composer_attachment_bar_new (GtkAdjustment *adj); +void e_msg_composer_attachment_bar_to_multipart (EMsgComposerAttachmentBar *bar, CamelMultipart *multipart); +guint e_msg_composer_attachment_bar_get_num_attachments (EMsgComposerAttachmentBar *bar); +void e_msg_composer_attachment_bar_attach (EMsgComposerAttachmentBar *bar, const gchar *file_name); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_MSG_COMPOSER_ATTACHMENT_BAR_H__ */ diff --git a/widgets/e-msg-composer-attachment.c b/widgets/e-msg-composer-attachment.c new file mode 100644 index 0000000000..9e0f7e218e --- /dev/null +++ b/widgets/e-msg-composer-attachment.c @@ -0,0 +1,461 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-attachment.c + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#include <gnome.h> +#include "e-msg-composer-attachment.h" + + +enum { + CHANGED, + LAST_SIGNAL +}; +guint signals[LAST_SIGNAL] = { 0 }; + +static GtkObjectClass *parent_class = NULL; + + +/* Utility functions. */ + +static const gchar * +get_mime_type (const gchar *file_name) +{ + const gchar *mime_type; + + mime_type = gnome_mime_type_of_file (file_name); + if (mime_type == NULL) + mime_type = "application/octet-stream"; + + return mime_type; +} + +static void +init_mime_type (EMsgComposerAttachment *attachment) +{ + attachment->mime_type = g_strdup (get_mime_type (attachment->file_name)); +} + +static void +set_mime_type (EMsgComposerAttachment *attachment) +{ + g_free (attachment->mime_type); + init_mime_type (attachment); +} + +static void +changed (EMsgComposerAttachment *attachment) +{ + gtk_signal_emit (GTK_OBJECT (attachment), signals[CHANGED]); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EMsgComposerAttachment *attachment; + + attachment = E_MSG_COMPOSER_ATTACHMENT (object); + + g_free (attachment->file_name); + g_free (attachment->description); + g_free (attachment->mime_type); +} + + +/* Signals. */ + +static void +real_changed (EMsgComposerAttachment *msg_composer_attachment) +{ + g_return_if_fail (msg_composer_attachment != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT (msg_composer_attachment)); + +} + + +static void +class_init (EMsgComposerAttachmentClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + + parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class->destroy = destroy; + + signals[CHANGED] = gtk_signal_new ("changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET + (EMsgComposerAttachmentClass, + changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); + + klass->changed = real_changed; +} + +static void +init (EMsgComposerAttachment *msg_composer_attachment) +{ +} + +GtkType +e_msg_composer_attachment_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposerAttachment", + sizeof (EMsgComposerAttachment), + sizeof (EMsgComposerAttachmentClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_object_get_type (), &info); + } + + return type; +} + + +/** + * e_msg_composer_attachment_new: + * @file_name: + * + * Return value: + **/ +EMsgComposerAttachment * +e_msg_composer_attachment_new (const gchar *file_name) +{ + EMsgComposerAttachment *new; + + g_return_val_if_fail (file_name != NULL, NULL); + + new = gtk_type_new (e_msg_composer_attachment_get_type ()); + + new->editor_gui = NULL; + + new->file_name = g_strdup (file_name); + new->description = g_strdup (g_basename (new->file_name)); + + init_mime_type (new); + + return new; +} + + +/* The attachment property dialog. */ + +struct _DialogData { + GtkWidget *dialog; + GtkEntry *file_name_entry; + GtkEntry *description_entry; + GtkEntry *mime_type_entry; + GtkWidget *browse_widget; + EMsgComposerAttachment *attachment; +}; +typedef struct _DialogData DialogData; + +static void +destroy_dialog_data (DialogData *data) +{ + if (data->browse_widget != NULL) + gtk_widget_destroy (data->browse_widget); + g_free (data); +} + +static void +update_mime_type (DialogData *data) +{ + const gchar *mime_type; + const gchar *file_name; + + file_name = gtk_entry_get_text (data->file_name_entry); + mime_type = get_mime_type (file_name); + + gtk_entry_set_text (data->mime_type_entry, mime_type); +} + +static void +browse_ok_cb (GtkWidget *widget, + gpointer data) +{ + GtkWidget *file_selection; + DialogData *dialog_data; + const gchar *file_name; + + dialog_data = (DialogData *) data; + file_selection = gtk_widget_get_toplevel (widget); + + file_name = gtk_file_selection_get_filename + (GTK_FILE_SELECTION (file_selection)); + + gtk_entry_set_text (dialog_data->file_name_entry, file_name); + + update_mime_type (dialog_data); + + gtk_widget_hide (file_selection); +} + +static void +browse (DialogData *data) +{ + if (data->browse_widget == NULL) { + GtkWidget *file_selection; + GtkWidget *cancel_button; + GtkWidget *ok_button; + + file_selection + = gtk_file_selection_new (_("Select attachment")); + gtk_window_set_position (GTK_WINDOW (file_selection), + GTK_WIN_POS_MOUSE); + gtk_window_set_transient_for (GTK_WINDOW (file_selection), + GTK_WINDOW (data->dialog)); + + ok_button = GTK_FILE_SELECTION (file_selection)->ok_button; + gtk_signal_connect (GTK_OBJECT (ok_button), + "clicked", GTK_SIGNAL_FUNC (browse_ok_cb), + data); + + cancel_button + = GTK_FILE_SELECTION (file_selection)->cancel_button; + gtk_signal_connect_object (GTK_OBJECT (cancel_button), + "clicked", + GTK_SIGNAL_FUNC (gtk_widget_hide), + GTK_OBJECT (file_selection)); + + data->browse_widget = file_selection; + } + + gtk_widget_show (GTK_WIDGET (data->browse_widget)); +} + +static void +set_entry (GladeXML *xml, + const gchar *widget_name, + const gchar *value) +{ + GtkEntry *entry; + + entry = GTK_ENTRY (glade_xml_get_widget (xml, widget_name)); + if (entry == NULL) + g_warning ("Entry for `%s' not found.", widget_name); + gtk_entry_set_text (entry, value); +} + +static void +connect_entry_changed (GladeXML *gui, + const gchar *name, + GtkSignalFunc func, + gpointer data) +{ + GtkWidget *widget; + + widget = glade_xml_get_widget (gui, name); + gtk_signal_connect (GTK_OBJECT (widget), "changed", func, data); +} + +static void +connect_widget (GladeXML *gui, + const gchar *name, + const gchar *signal_name, + GtkSignalFunc func, + gpointer data) +{ + GtkWidget *widget; + + widget = glade_xml_get_widget (gui, name); + gtk_signal_connect (GTK_OBJECT (widget), signal_name, func, data); +} + +static void +apply (DialogData *data) +{ + EMsgComposerAttachment *attachment; + + attachment = data->attachment; + + g_free (attachment->file_name); + attachment->file_name = g_strdup (gtk_entry_get_text + (data->file_name_entry)); + + g_free (attachment->description); + attachment->description = g_strdup (gtk_entry_get_text + (data->description_entry)); + + g_free (attachment->mime_type); + attachment->mime_type = g_strdup (gtk_entry_get_text + (data->mime_type_entry)); + + changed (attachment); +} + +static void +entry_changed_cb (GtkWidget *widget, gpointer data) +{ + DialogData *dialog_data; + GladeXML *gui; + GtkWidget *apply_button; + + dialog_data = (DialogData *) data; + gui = dialog_data->attachment->editor_gui; + + apply_button = glade_xml_get_widget (gui, "apply_button"); + gtk_widget_set_sensitive (apply_button, TRUE); +} + +static void +close_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachment *attachment; + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + attachment = dialog_data->attachment; + + gtk_widget_destroy (glade_xml_get_widget (attachment->editor_gui, + "dialog")); + gtk_object_unref (GTK_OBJECT (attachment->editor_gui)); + attachment->editor_gui = NULL; + + destroy_dialog_data (dialog_data); +} + +static void +apply_cb (GtkWidget *widget, + gpointer data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + apply (dialog_data); +} + +static void +ok_cb (GtkWidget *widget, + gpointer data) +{ + apply_cb (widget, data); + close_cb (widget, data); +} + +static void +browse_cb (GtkWidget *widget, + gpointer data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + browse (dialog_data); +} + +static void +file_name_focus_out_cb (GtkWidget *widget, + GdkEventFocus *event, + gpointer data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + update_mime_type (dialog_data); +} + + +void +e_msg_composer_attachment_edit (EMsgComposerAttachment *attachment, + GtkWidget *parent) +{ + DialogData *dialog_data; + GladeXML *editor_gui; + + g_return_if_fail (attachment != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT (attachment)); + + if (attachment->editor_gui != NULL) { + GtkWidget *window; + + window = glade_xml_get_widget (attachment->editor_gui, + "dialog"); + gdk_window_show (window->window); + return; + } + + editor_gui = glade_xml_new (E_GUIDIR "/e-msg-composer-attachment.glade", + NULL); + if (editor_gui == NULL) { + g_warning ("Cannot load `e-msg-composer-attachment.glade'"); + return; + } + + attachment->editor_gui = editor_gui; + + gtk_window_set_transient_for + (GTK_WINDOW (glade_xml_get_widget (editor_gui, "dialog")), + GTK_WINDOW (gtk_widget_get_toplevel (parent))); + + dialog_data = g_new (DialogData, 1); + dialog_data->browse_widget = NULL; + dialog_data->attachment = attachment; + dialog_data->dialog = glade_xml_get_widget (editor_gui, "dialog"); + dialog_data->file_name_entry = GTK_ENTRY (glade_xml_get_widget + (editor_gui, + "file_name_entry")); + dialog_data->description_entry = GTK_ENTRY (glade_xml_get_widget + (editor_gui, + "description_entry")); + dialog_data->mime_type_entry = GTK_ENTRY (glade_xml_get_widget + (editor_gui, + "mime_type_entry")); + + if (attachment != NULL) { + set_entry (editor_gui, "file_name_entry", attachment->file_name); + set_entry (editor_gui, "description_entry", attachment->description); + set_entry (editor_gui, "mime_type_entry", attachment->mime_type); + } + + connect_entry_changed (editor_gui, "file_name_entry", + entry_changed_cb, dialog_data); + connect_entry_changed (editor_gui, "description_entry", + entry_changed_cb, dialog_data); + + connect_widget (editor_gui, "ok_button", "clicked", ok_cb, dialog_data); + connect_widget (editor_gui, "apply_button", "clicked", apply_cb, dialog_data); + connect_widget (editor_gui, "close_button", "clicked", close_cb, dialog_data); + + connect_widget (editor_gui, "browse_button", "clicked", browse_cb, dialog_data); + + connect_widget (editor_gui, "file_name_entry", "focus_out_event", + file_name_focus_out_cb, dialog_data); +} diff --git a/widgets/e-msg-composer-attachment.glade b/widgets/e-msg-composer-attachment.glade new file mode 100644 index 0000000000..72c0132639 --- /dev/null +++ b/widgets/e-msg-composer-attachment.glade @@ -0,0 +1,290 @@ +<?xml version="1.0"?> +<GTK-Interface> + +<project> + <name>e-msg-composer-attachment</name> + <program_name>e-msg-composer-attachment</program_name> + <directory></directory> + <source_directory>src</source_directory> + <pixmaps_directory>pixmaps</pixmaps_directory> + <language>C</language> + <gnome_support>True</gnome_support> + <gettext_support>True</gettext_support> + <use_widget_names>False</use_widget_names> + <output_main_file>True</output_main_file> + <output_support_files>True</output_support_files> + <output_build_files>True</output_build_files> + <backup_source_files>True</backup_source_files> + <main_source_file>interface.c</main_source_file> + <main_header_file>interface.h</main_header_file> + <handler_source_file>callbacks.c</handler_source_file> + <handler_header_file>callbacks.h</handler_header_file> + <support_source_file>support.c</support_source_file> + <support_header_file>support.h</support_header_file> + <translatable_strings_file></translatable_strings_file> +</project> + +<widget> + <class>GnomeDialog</class> + <name>dialog</name> + <title>Attachment properties</title> + <type>GTK_WINDOW_TOPLEVEL</type> + <position>GTK_WIN_POS_NONE</position> + <modal>False</modal> + <allow_shrink>False</allow_shrink> + <allow_grow>False</allow_grow> + <auto_shrink>False</auto_shrink> + <auto_close>False</auto_close> + <hide_on_close>False</hide_on_close> + + <widget> + <class>GtkVBox</class> + <child_name>GnomeDialog:vbox</child_name> + <name>dialog-vbox1</name> + <homogeneous>False</homogeneous> + <spacing>8</spacing> + <child> + <padding>4</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GtkTable</class> + <name>table1</name> + <rows>3</rows> + <columns>2</columns> + <homogeneous>False</homogeneous> + <row_spacing>10</row_spacing> + <column_spacing>5</column_spacing> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GtkLabel</class> + <name>label1</name> + <label>Description:</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <child> + <left_attach>0</left_attach> + <right_attach>1</right_attach> + <top_attach>1</top_attach> + <bottom_attach>2</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>False</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>False</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkLabel</class> + <name>label3</name> + <label>MIME type:</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <child> + <left_attach>0</left_attach> + <right_attach>1</right_attach> + <top_attach>2</top_attach> + <bottom_attach>3</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>False</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>False</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkEntry</class> + <name>description_entry</name> + <can_focus>True</can_focus> + <editable>True</editable> + <text_visible>True</text_visible> + <text_max_length>0</text_max_length> + <text></text> + <child> + <left_attach>1</left_attach> + <right_attach>2</right_attach> + <top_attach>1</top_attach> + <bottom_attach>2</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>True</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkLabel</class> + <name>label2</name> + <label>File name:</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <child> + <left_attach>0</left_attach> + <right_attach>1</right_attach> + <top_attach>0</top_attach> + <bottom_attach>1</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>False</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>False</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkHBox</class> + <name>hbox3</name> + <homogeneous>False</homogeneous> + <spacing>10</spacing> + <child> + <left_attach>1</left_attach> + <right_attach>2</right_attach> + <top_attach>0</top_attach> + <bottom_attach>1</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>True</xexpand> + <yexpand>True</yexpand> + <xshrink>True</xshrink> + <yshrink>True</yshrink> + <xfill>True</xfill> + <yfill>True</yfill> + </child> + + <widget> + <class>GtkEntry</class> + <name>file_name_entry</name> + <width>290</width> + <can_focus>True</can_focus> + <editable>True</editable> + <text_visible>True</text_visible> + <text_max_length>0</text_max_length> + <text></text> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + </widget> + + <widget> + <class>GtkButton</class> + <name>browse_button</name> + <width>80</width> + <can_focus>True</can_focus> + <label>Browse...</label> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + </widget> + + <widget> + <class>GtkEntry</class> + <name>mime_type_entry</name> + <sensitive>False</sensitive> + <can_focus>True</can_focus> + <editable>False</editable> + <text_visible>True</text_visible> + <text_max_length>0</text_max_length> + <text></text> + <child> + <left_attach>1</left_attach> + <right_attach>2</right_attach> + <top_attach>2</top_attach> + <bottom_attach>3</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>True</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + </widget> + </widget> + + <widget> + <class>GtkHButtonBox</class> + <child_name>GnomeDialog:action_area</child_name> + <name>dialog-action_area1</name> + <layout_style>GTK_BUTTONBOX_END</layout_style> + <spacing>8</spacing> + <child_min_width>85</child_min_width> + <child_min_height>27</child_min_height> + <child_ipad_x>7</child_ipad_x> + <child_ipad_y>0</child_ipad_y> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>True</fill> + <pack>GTK_PACK_END</pack> + </child> + + <widget> + <class>GtkButton</class> + <name>ok_button</name> + <can_default>True</can_default> + <has_default>True</has_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_OK</stock_button> + </widget> + + <widget> + <class>GtkButton</class> + <name>apply_button</name> + <sensitive>False</sensitive> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button> + </widget> + + <widget> + <class>GtkButton</class> + <name>close_button</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_CLOSE</stock_button> + </widget> + </widget> + </widget> +</widget> + +</GTK-Interface> diff --git a/widgets/e-msg-composer-attachment.h b/widgets/e-msg-composer-attachment.h new file mode 100644 index 0000000000..07dd7f247d --- /dev/null +++ b/widgets/e-msg-composer-attachment.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-attachment.h + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ +#ifndef __E_MSG_COMPOSER_ATTACHMENT_H__ +#define __E_MSG_COMPOSER_ATTACHMENT_H__ + +#include <gnome.h> +#include <glade/glade-xml.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_MSG_COMPOSER_ATTACHMENT (e_msg_composer_attachment_get_type ()) +#define E_MSG_COMPOSER_ATTACHMENT(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT, EMsgComposerAttachment)) +#define E_MSG_COMPOSER_ATTACHMENT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_ATTACHMENT, EMsgComposerAttachmentClass)) +#define E_IS_MSG_COMPOSER_ATTACHMENT(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT)) +#define E_IS_MSG_COMPOSER_ATTACHMENT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT)) + + +typedef struct _EMsgComposerAttachment EMsgComposerAttachment; +typedef struct _EMsgComposerAttachmentClass EMsgComposerAttachmentClass; + +struct _EMsgComposerAttachment { + GtkObject parent; + + GladeXML *editor_gui; + + gchar *file_name; + gchar *description; + gchar *mime_type; +}; + +struct _EMsgComposerAttachmentClass { + GtkObjectClass parent_class; + + /* Signals go here */ + void (*changed) (EMsgComposerAttachment *msg_composer_attachment); +}; + + +GtkType e_msg_composer_attachment_get_type (void); +EMsgComposerAttachment *e_msg_composer_attachment_new (const gchar *file_name); +void e_msg_composer_attachment_edit (EMsgComposerAttachment *attachment, + GtkWidget *parent); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_MSG_COMPOSER_ATTACHMENT_H__ */ diff --git a/widgets/e-msg-composer-hdrs.c b/widgets/e-msg-composer-hdrs.c new file mode 100644 index 0000000000..7269b0da8b --- /dev/null +++ b/widgets/e-msg-composer-hdrs.c @@ -0,0 +1,196 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* msg-composer-hdrs.c + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#ifdef _HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome.h> +#include <camel/camel.h> + +#include "e-msg-composer-address-entry.h" +#include "e-msg-composer-hdrs.h" + + +struct _EMsgComposerHdrsPrivate { + /* Total number of headers that we have. */ + guint num_hdrs; + + /* Standard headers. */ + GtkWidget *to_entry; + GtkWidget *cc_entry; + GtkWidget *bcc_entry; + GtkWidget *subject_entry; +}; + + +static GtkTableClass *parent_class = NULL; + + +static GtkWidget * +add_address_header (EMsgComposerHdrs *hdrs, + const gchar *name) +{ + EMsgComposerHdrsPrivate *priv; + GtkWidget *label; + GtkWidget *entry; + + priv = hdrs->priv; + + label = gtk_label_new (name); + gtk_table_attach (GTK_TABLE (hdrs), label, + 0, 1, priv->num_hdrs, priv->num_hdrs + 1, + GTK_FILL, GTK_FILL, + GNOME_PAD, GNOME_PAD); + gtk_widget_show (label); + + entry = e_msg_composer_address_entry_new (); + gtk_table_attach (GTK_TABLE (hdrs), entry, + 1, 2, priv->num_hdrs, priv->num_hdrs + 1, + GTK_FILL | GTK_EXPAND, GTK_FILL, + GNOME_PAD, GNOME_PAD); + gtk_widget_show (entry); + + priv->num_hdrs++; + + return entry; +} + +static void +setup_headers (EMsgComposerHdrs *hdrs) +{ + EMsgComposerHdrsPrivate *priv; + + priv = hdrs->priv; + + priv->subject_entry = add_address_header (hdrs, _("Subject:")); + priv->to_entry = add_address_header (hdrs, _("To:")); + priv->cc_entry = add_address_header (hdrs, _("Cc:")); + priv->bcc_entry = add_address_header (hdrs, _("Bcc:")); +} + + +static void +class_init (EMsgComposerHdrsClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + + parent_class = gtk_type_class (gtk_table_get_type ()); +} + +static void +init (EMsgComposerHdrs *hdrs) +{ + EMsgComposerHdrsPrivate *priv; + + priv = g_new (EMsgComposerHdrsPrivate, 1); + + priv->to_entry = NULL; + priv->cc_entry = NULL; + priv->bcc_entry = NULL; + priv->subject_entry = NULL; + + priv->num_hdrs = 0; + + hdrs->priv = priv; +} + + +GtkType +e_msg_composer_hdrs_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposerHdrs", + sizeof (EMsgComposerHdrs), + sizeof (EMsgComposerHdrsClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_table_get_type (), &info); + } + + return type; +} + +GtkWidget * +e_msg_composer_hdrs_new (void) +{ + EMsgComposerHdrs *new; + + new = gtk_type_new (e_msg_composer_hdrs_get_type ()); + + setup_headers (E_MSG_COMPOSER_HDRS (new)); + + return GTK_WIDGET (new); +} + + +static void +set_recipients (CamelMimeMessage *msg, + GtkWidget *entry_widget, + const gchar *type) +{ + EMsgComposerAddressEntry *entry; + GList *list; + GList *p; + + entry = E_MSG_COMPOSER_ADDRESS_ENTRY (entry_widget); + list = e_msg_composer_address_entry_get_addresses (entry); + + /* FIXME leak? */ + + for (p = list; p != NULL; p = p->next) { + printf ("Adding `%s:' header: %s\n", type, (gchar *) p->data); + camel_mime_message_add_recipient (msg, type, (gchar *) p->data); + } + + g_list_free (list); +} + +void +e_msg_composer_hdrs_to_message (EMsgComposerHdrs *hdrs, + CamelMimeMessage *msg) +{ + const gchar *s; + + g_return_if_fail (hdrs != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); + g_return_if_fail (msg != NULL); + g_return_if_fail (IS_CAMEL_MIME_MESSAGE (msg)); + + s = gtk_entry_get_text (GTK_ENTRY (hdrs->priv->subject_entry)); + camel_mime_message_set_subject (msg, g_strdup (s)); + + set_recipients (msg, hdrs->priv->to_entry, RECIPIENT_TYPE_TO); + set_recipients (msg, hdrs->priv->cc_entry, RECIPIENT_TYPE_CC); + set_recipients (msg, hdrs->priv->bcc_entry, RECIPIENT_TYPE_BCC); +} diff --git a/widgets/e-msg-composer-hdrs.h b/widgets/e-msg-composer-hdrs.h new file mode 100644 index 0000000000..de8ac4ac13 --- /dev/null +++ b/widgets/e-msg-composer-hdrs.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* msg-composer-hdrs.h + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#ifndef ___E_MSG_COMPOSER_HDRS_H__ +#define ___E_MSG_COMPOSER_HDRS_H__ + +#include <gnome.h> +#include <camel/camel-mime-message.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_MSG_COMPOSER_HDRS (e_msg_composer_hdrs_get_type ()) +#define E_MSG_COMPOSER_HDRS(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrs)) +#define E_MSG_COMPOSER_HDRS_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrsClass)) +#define E_IS_MSG_COMPOSER_HDRS(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_HDRS)) +#define E_IS_MSG_COMPOSER_HDRS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_HDRS)) + + +typedef struct _EMsgComposerHdrs EMsgComposerHdrs; +typedef struct _EMsgComposerHdrsClass EMsgComposerHdrsClass; +typedef struct _EMsgComposerHdrsPrivate EMsgComposerHdrsPrivate; + +struct _EMsgComposerHdrs { + GtkTable parent; + + EMsgComposerHdrsPrivate *priv; +}; + +struct _EMsgComposerHdrsClass { + GtkTableClass parent_class; +}; + + +GtkType e_msg_composer_hdrs_get_type (void); +GtkWidget *e_msg_composer_hdrs_new (void); +void e_msg_composer_hdrs_to_message (EMsgComposerHdrs *hdrs, + CamelMimeMessage *msg); + +#ifdef _cplusplus +} +#endif /* _cplusplus */ + + +#endif /* __E_MSG_COMPOSER_HDRS_H__ */ diff --git a/widgets/e-msg-composer.c b/widgets/e-msg-composer.c new file mode 100644 index 0000000000..70602c0018 --- /dev/null +++ b/widgets/e-msg-composer.c @@ -0,0 +1,441 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer.c + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +/* + + TODO + + - Somehow users should be able to see if any file(s) are attached even when + the attachment bar is not shown. + +*/ + +#ifdef _HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome.h> +#include <glade/glade.h> +#include <camel/camel.h> + +#include "e-msg-composer.h" +#include "e-msg-composer-attachment-bar.h" +#include "e-msg-composer-hdrs.h" + + +#define DEFAULT_WIDTH 600 +#define DEFAULT_HEIGHT 500 + + +enum { + SEND, + POSTPONE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static GnomeAppClass *parent_class = NULL; + + +/* This functions builds a CamelMimeMessage for the message that the user has + composed in `composer'. */ +static CamelMimeMessage * +build_message (EMsgComposer *composer) +{ + CamelMimeMessage *new; + CamelMimeBodyPart *body_part; + CamelMultipart *multipart; + gchar *text; + + new = camel_mime_message_new_with_session (NULL); + + e_msg_composer_hdrs_to_message (E_MSG_COMPOSER_HDRS (composer->hdrs), + new); + + multipart = camel_multipart_new (); + body_part = camel_mime_body_part_new (); + + text = gtk_editable_get_chars (GTK_EDITABLE (composer->text), 0, -1); + camel_mime_part_set_text (CAMEL_MIME_PART (body_part), text); + camel_multipart_add_part (multipart, body_part); + + e_msg_composer_attachment_bar_to_multipart + (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar), + multipart); + + camel_medium_set_content_object (CAMEL_MEDIUM (new), + CAMEL_DATA_WRAPPER (multipart)); + + /* FIXME refcounting is most certainly wrong. We want all the stuff to + be destroyed when we unref() the message. */ + + return new; +} + + +static void +show_attachments (EMsgComposer *composer, + gboolean show) +{ + if (show) { + gtk_widget_show (composer->attachment_scrolled_window); + gtk_widget_show (composer->attachment_bar); + } else { + gtk_widget_hide (composer->attachment_scrolled_window); + gtk_widget_hide (composer->attachment_bar); + } + + composer->attachment_bar_visible = show; + + /* Update the GUI. */ + + gtk_check_menu_item_set_active + (GTK_CHECK_MENU_ITEM + (glade_xml_get_widget (composer->menubar_gui, + "menu_view_attachments")), + show); + + /* XXX we should update the toggle toolbar item as well. At + this point, it is not a toggle because Glade is broken. */ +} + + +/* Callbacks. */ + +static void +send_cb (GtkWidget *widget, + gpointer data) +{ + gtk_signal_emit (GTK_OBJECT (data), signals[SEND]); +} + +static void +menu_view_attachments_activate_cb (GtkWidget *widget, + gpointer data) +{ + e_msg_composer_show_attachments (E_MSG_COMPOSER (data), + GTK_CHECK_MENU_ITEM (widget)->active); +} + +static void +toolbar_view_attachments_clicked_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposer *composer; + + composer = E_MSG_COMPOSER (data); + + e_msg_composer_show_attachments (composer, + ! composer->attachment_bar_visible); +} + +static void +add_attachment_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposer *composer; + + composer = E_MSG_COMPOSER (data); + + e_msg_composer_attachment_bar_attach + (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar), + NULL); +} + +static void +glade_connect (GladeXML *gui, + const gchar *widget_name, + const gchar *signal_name, + GtkSignalFunc callback, + gpointer callback_data) +{ + GtkWidget *widget; + + widget = glade_xml_get_widget (gui, widget_name); + if (widget == NULL) + g_warning ("Widget `%s' was not found.", widget_name); + else + gtk_signal_connect (GTK_OBJECT (widget), signal_name, + GTK_SIGNAL_FUNC (callback), callback_data); +} + +static void +attachment_bar_changed (EMsgComposerAttachmentBar *bar, + gpointer data) +{ + EMsgComposer *composer; + + composer = E_MSG_COMPOSER (data); + + if (e_msg_composer_attachment_bar_get_num_attachments (bar) > 0) + e_msg_composer_show_attachments (composer, TRUE); + else + e_msg_composer_show_attachments (composer, FALSE); +} + +static void +setup_signals (EMsgComposer *composer) +{ + glade_connect (composer->menubar_gui, "menu_send", + "activate", GTK_SIGNAL_FUNC (send_cb), composer); + glade_connect (composer->toolbar_gui, "toolbar_send", + "clicked", GTK_SIGNAL_FUNC (send_cb), composer); + + glade_connect (composer->menubar_gui, "menu_view_attachments", + "activate", + GTK_SIGNAL_FUNC (menu_view_attachments_activate_cb), + composer); + glade_connect (composer->toolbar_gui, "toolbar_view_attachments", + "clicked", + GTK_SIGNAL_FUNC (toolbar_view_attachments_clicked_cb), + composer); + + glade_connect (composer->menubar_gui, "menu_add_attachment", + "activate", + GTK_SIGNAL_FUNC (add_attachment_cb), composer); + glade_connect (composer->toolbar_gui, "toolbar_add_attachment", + "clicked", + GTK_SIGNAL_FUNC (add_attachment_cb), composer); + + gtk_signal_connect (GTK_OBJECT (composer->attachment_bar), + "changed", + GTK_SIGNAL_FUNC (attachment_bar_changed), + composer); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EMsgComposer *composer; + + composer = E_MSG_COMPOSER (object); + + gtk_object_unref (GTK_OBJECT (composer->menubar_gui)); + gtk_object_unref (GTK_OBJECT (composer->toolbar_gui)); + gtk_object_unref (GTK_OBJECT (composer->appbar_gui)); + + if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (EMsgComposerClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *) klass; + + object_class->destroy = destroy; + + parent_class = gtk_type_class (gnome_app_get_type ()); + + signals[SEND] = + gtk_signal_new ("send", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EMsgComposerClass, send), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + signals[POSTPONE] = + gtk_signal_new ("postpone", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EMsgComposerClass, postpone), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EMsgComposer *composer) +{ + composer->menubar_gui = NULL; + composer->toolbar_gui = NULL; + composer->appbar_gui = NULL; + + composer->hdrs = NULL; + + composer->text = NULL; + composer->text_scrolled_window = NULL; + + composer->attachment_bar = NULL; + composer->attachment_scrolled_window = NULL; +} + + +GtkType +e_msg_composer_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposer", + sizeof (EMsgComposer), + sizeof (EMsgComposerClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gnome_app_get_type (), &info); + } + + return type; +} + + +void +e_msg_composer_construct (EMsgComposer *composer) +{ + GtkWidget *vbox; + + gtk_window_set_default_size (GTK_WINDOW (composer), + DEFAULT_WIDTH, DEFAULT_HEIGHT); + + gnome_app_construct (GNOME_APP (composer), "e-msg-composer", + "Compose a message"); + + composer->menubar_gui = glade_xml_new (E_GUIDIR "/e-msg-composer.glade", + "menubar"); + gnome_app_set_menus (GNOME_APP (composer), + GTK_MENU_BAR (glade_xml_get_widget (composer->menubar_gui, + "menubar"))); + + composer->toolbar_gui = glade_xml_new (E_GUIDIR "/e-msg-composer.glade", + "toolbar"); + gnome_app_set_toolbar (GNOME_APP (composer), + GTK_TOOLBAR (glade_xml_get_widget (composer->toolbar_gui, + "toolbar"))); + + composer->appbar_gui = glade_xml_new (E_GUIDIR "/e-msg-composer.glade", + "appbar"); + gnome_app_set_statusbar (GNOME_APP (composer), + glade_xml_get_widget (composer->appbar_gui, + "appbar")); + + vbox = gtk_vbox_new (FALSE, GNOME_PAD); + + composer->hdrs = e_msg_composer_hdrs_new (); + gtk_box_pack_start (GTK_BOX (vbox), composer->hdrs, FALSE, TRUE, 0); + gtk_widget_show (composer->hdrs); + + /* GtkText for message body editing, wrapped into a + GtkScrolledWindow. */ + + composer->text_scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy + (GTK_SCROLLED_WINDOW (composer->text_scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + composer->text = gtk_text_new (NULL, NULL); + gtk_text_set_word_wrap (GTK_TEXT (composer->text), FALSE); + gtk_text_set_editable (GTK_TEXT (composer->text), TRUE); + gtk_container_add (GTK_CONTAINER (composer->text_scrolled_window), + composer->text); + gtk_widget_show (composer->text); + gtk_box_pack_start (GTK_BOX (vbox), composer->text_scrolled_window, + TRUE, TRUE, 0); + gtk_widget_show (composer->text_scrolled_window); + + /* Attachment editor, wrapped into a GtkScrolledWindow. We don't + show it for now. */ + + composer->attachment_scrolled_window = gtk_scrolled_window_new (NULL, + NULL); + gtk_scrolled_window_set_policy + (GTK_SCROLLED_WINDOW (composer->attachment_scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + composer->attachment_bar = e_msg_composer_attachment_bar_new (NULL); + GTK_WIDGET_SET_FLAGS (composer->attachment_bar, GTK_CAN_FOCUS); + gtk_container_add (GTK_CONTAINER (composer->attachment_scrolled_window), + composer->attachment_bar); + gtk_box_pack_start (GTK_BOX (vbox), + composer->attachment_scrolled_window, + FALSE, TRUE, 0); + + gnome_app_set_contents (GNOME_APP (composer), vbox); + gtk_widget_show (vbox); + + e_msg_composer_show_attachments (composer, FALSE); + + setup_signals (composer); +} + +GtkWidget * +e_msg_composer_new (void) +{ + GtkWidget *new; + + new = gtk_type_new (e_msg_composer_get_type ()); + e_msg_composer_construct (E_MSG_COMPOSER (new)); + + return new; +} + + +/** + * e_msg_composer_show_attachments: + * @composer: A message composer widget + * @show: A boolean specifying whether the attachment bar should be shown or + * not + * + * If @show is %FALSE, hide the attachment bar. Otherwise, show it. + **/ +void +e_msg_composer_show_attachments (EMsgComposer *composer, + gboolean show) +{ + g_return_if_fail (composer != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + + show_attachments (composer, show); +} + + +/** + * e_msg_composer_get_message: + * @composer: A message composer widget + * + * Retrieve the message edited by the user as a CamelMimeMessage. The + * CamelMimeMessage object is created on the fly; subsequent calls to this + * function will always create new objects from scratch. + * + * Return value: A pointer to the new CamelMimeMessage object + **/ +CamelMimeMessage * +e_msg_composer_get_message (EMsgComposer *composer) +{ + g_return_val_if_fail (composer != NULL, NULL); + g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); + + return build_message (composer); +} diff --git a/widgets/e-msg-composer.glade b/widgets/e-msg-composer.glade new file mode 100644 index 0000000000..c2d18b8125 --- /dev/null +++ b/widgets/e-msg-composer.glade @@ -0,0 +1,576 @@ +<?xml version="1.0"?> +<GTK-Interface> + +<project> + <name>Message Composer</name> + <program_name>e-msg-composer</program_name> + <directory></directory> + <source_directory>src</source_directory> + <pixmaps_directory>pixmaps</pixmaps_directory> + <language>C</language> + <gnome_support>True</gnome_support> + <gettext_support>True</gettext_support> + <use_widget_names>False</use_widget_names> + <output_main_file>True</output_main_file> + <output_support_files>True</output_support_files> + <output_build_files>True</output_build_files> + <backup_source_files>True</backup_source_files> + <main_source_file>interface.c</main_source_file> + <main_header_file>interface.h</main_header_file> + <handler_source_file>callbacks.c</handler_source_file> + <handler_header_file>callbacks.h</handler_header_file> + <support_source_file>support.c</support_source_file> + <support_header_file>support.h</support_header_file> + <translatable_strings_file></translatable_strings_file> +</project> + +<widget> + <class>GnomeApp</class> + <name>app1</name> + <title>Message Composer</title> + <type>GTK_WINDOW_TOPLEVEL</type> + <position>GTK_WIN_POS_NONE</position> + <modal>False</modal> + <allow_shrink>False</allow_shrink> + <allow_grow>True</allow_grow> + <auto_shrink>False</auto_shrink> + <enable_layout_config>True</enable_layout_config> + + <widget> + <class>GnomeDock</class> + <child_name>GnomeApp:dock</child_name> + <name>dock1</name> + <allow_floating>True</allow_floating> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GnomeDockItem</class> + <name>dockitem1</name> + <border_width>2</border_width> + <placement>GNOME_DOCK_TOP</placement> + <band>0</band> + <position>0</position> + <offset>0</offset> + <locked>False</locked> + <exclusive>True</exclusive> + <never_floating>False</never_floating> + <never_vertical>True</never_vertical> + <never_horizontal>False</never_horizontal> + <shadow_type>GTK_SHADOW_OUT</shadow_type> + + <widget> + <class>GtkMenuBar</class> + <name>menubar</name> + <shadow_type>GTK_SHADOW_NONE</shadow_type> + + <widget> + <class>GtkMenuItem</class> + <name>file</name> + <stock_item>GNOMEUIINFO_MENU_FILE_TREE</stock_item> + + <widget> + <class>GtkMenu</class> + <name>file_menu</name> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>open</name> + <signal> + <name>activate</name> + <handler>on_open_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:08 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_OPEN_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>save</name> + <signal> + <name>activate</name> + <handler>on_save_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:13 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_SAVE_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>save_as</name> + <signal> + <name>activate</name> + <handler>on_save_as_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:16 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_SAVE_AS_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>save_in_folder</name> + <signal> + <name>activate</name> + <handler>on_save_in_folder_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:20 GMT</last_modification_time> + </signal> + <label>Save in _Folder...</label> + <right_justify>False</right_justify> + <stock_icon>GNOME_STOCK_MENU_SAVE_AS</stock_icon> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator8</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>menu_send</name> + <signal> + <name>activate</name> + <handler>on_send_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:29 GMT</last_modification_time> + </signal> + <label>S_end</label> + <right_justify>False</right_justify> + <stock_icon>GNOME_STOCK_MENU_MAIL_SND</stock_icon> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>postpone</name> + <signal> + <name>activate</name> + <handler>on_postpone_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:37 GMT</last_modification_time> + </signal> + <label>_Postpone</label> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator1</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>exit</name> + <signal> + <name>activate</name> + <handler>on_exit_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:25:59 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_EXIT_ITEM</stock_item> + </widget> + </widget> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>edit</name> + <stock_item>GNOMEUIINFO_MENU_EDIT_TREE</stock_item> + + <widget> + <class>GtkMenu</class> + <name>edit_menu</name> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>undo</name> + <signal> + <name>activate</name> + <handler>on_undo_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:10 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_UNDO_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>redo</name> + <signal> + <name>activate</name> + <handler>on_redo_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:15 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_REDO_ITEM</stock_item> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator3</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>cut</name> + <signal> + <name>activate</name> + <handler>on_cut_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:21 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_CUT_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>copy</name> + <signal> + <name>activate</name> + <handler>on_copy_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:26 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_COPY_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>paste</name> + <signal> + <name>activate</name> + <handler>on_paste_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:31 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_PASTE_ITEM</stock_item> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator2</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>select_all</name> + <signal> + <name>activate</name> + <handler>on_select_all_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:37 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_SELECT_ALL_ITEM</stock_item> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator5</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>find</name> + <signal> + <name>activate</name> + <handler>on_find_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:42 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_FIND_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>find_again</name> + <signal> + <name>activate</name> + <handler>on_find_again_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:47 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_FIND_AGAIN_ITEM</stock_item> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>replace</name> + <signal> + <name>activate</name> + <handler>on_replace_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:53 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_REPLACE_ITEM</stock_item> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator6</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>properties</name> + <signal> + <name>activate</name> + <handler>on_properties_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:26:58 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_PROPERTIES_ITEM</stock_item> + </widget> + </widget> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>view1</name> + <stock_item>GNOMEUIINFO_MENU_VIEW_TREE</stock_item> + + <widget> + <class>GtkMenu</class> + <name>view1_menu</name> + + <widget> + <class>GtkCheckMenuItem</class> + <name>menu_view_attachments</name> + <signal> + <name>activate</name> + <handler>on_view_attachments_activate</handler> + <last_modification_time>Fri, 05 Nov 1999 18:31:16 GMT</last_modification_time> + </signal> + <label>Attachments</label> + <active>False</active> + <always_show_toggle>False</always_show_toggle> + </widget> + </widget> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>insert</name> + <label>_Insert</label> + <right_justify>False</right_justify> + + <widget> + <class>GtkMenu</class> + <name>insert_menu</name> + + <widget> + <class>GtkMenuItem</class> + <name>menu_add_attachment</name> + <signal> + <name>activate</name> + <handler>on_attachment_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:05 GMT</last_modification_time> + </signal> + <label>Attachment...</label> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>text_from_file</name> + <signal> + <name>activate</name> + <handler>on_text_from_file_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:16 GMT</last_modification_time> + </signal> + <label>Text from file...</label> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator6</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>hypertext_link</name> + <signal> + <name>activate</name> + <handler>on_hypertext_link_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:21 GMT</last_modification_time> + </signal> + <label>Hypertext link...</label> + <right_justify>False</right_justify> + </widget> + </widget> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>settings</name> + <stock_item>GNOMEUIINFO_MENU_SETTINGS_TREE</stock_item> + + <widget> + <class>GtkMenu</class> + <name>settings_menu</name> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>preferences</name> + <signal> + <name>activate</name> + <handler>on_preferences_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:37 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_PREFERENCES_ITEM</stock_item> + </widget> + </widget> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>tools</name> + <label>_Tools</label> + <right_justify>False</right_justify> + + <widget> + <class>GtkMenu</class> + <name>tools_menu</name> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>spell_check1</name> + <signal> + <name>activate</name> + <handler>on_spell_check_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:44 GMT</last_modification_time> + </signal> + <label>_Spell check</label> + <right_justify>False</right_justify> + <stock_icon>GNOME_STOCK_MENU_SPELLCHECK</stock_icon> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>separator7</name> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>check_names</name> + <signal> + <name>activate</name> + <handler>on_check_names_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:49 GMT</last_modification_time> + </signal> + <label>Check names</label> + <right_justify>False</right_justify> + </widget> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>address_book</name> + <signal> + <name>activate</name> + <handler>on_address_book_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:27:53 GMT</last_modification_time> + </signal> + <label>Address book...</label> + <right_justify>False</right_justify> + <stock_icon>GNOME_STOCK_MENU_BOOK_RED</stock_icon> + </widget> + </widget> + </widget> + + <widget> + <class>GtkMenuItem</class> + <name>help</name> + <stock_item>GNOMEUIINFO_MENU_HELP_TREE</stock_item> + + <widget> + <class>GtkMenu</class> + <name>help_menu</name> + + <widget> + <class>GtkPixmapMenuItem</class> + <name>about</name> + <signal> + <name>activate</name> + <handler>on_about_activate</handler> + <last_modification_time>Wed, 27 Oct 1999 22:28:01 GMT</last_modification_time> + </signal> + <stock_item>GNOMEUIINFO_MENU_ABOUT_ITEM</stock_item> + </widget> + </widget> + </widget> + </widget> + </widget> + + <widget> + <class>GnomeDockItem</class> + <name>dockitem2</name> + <border_width>1</border_width> + <placement>GNOME_DOCK_TOP</placement> + <band>1</band> + <position>0</position> + <offset>0</offset> + <locked>False</locked> + <exclusive>True</exclusive> + <never_floating>False</never_floating> + <never_vertical>False</never_vertical> + <never_horizontal>False</never_horizontal> + <shadow_type>GTK_SHADOW_OUT</shadow_type> + + <widget> + <class>GtkToolbar</class> + <name>toolbar</name> + <border_width>1</border_width> + <orientation>GTK_ORIENTATION_HORIZONTAL</orientation> + <type>GTK_TOOLBAR_BOTH</type> + <space_size>16</space_size> + <space_style>GTK_TOOLBAR_SPACE_LINE</space_style> + <relief>GTK_RELIEF_NONE</relief> + <tooltips>True</tooltips> + + <widget> + <class>GtkButton</class> + <child_name>Toolbar:button</child_name> + <name>toolbar_send</name> + <tooltip>Send this message</tooltip> + <label>Send</label> + <stock_pixmap>GNOME_STOCK_PIXMAP_MAIL_SND</stock_pixmap> + </widget> + + <widget> + <class>GtkToggleButton</class> + <child_name>Toolbar:button</child_name> + <name>toolbar_view_attachments</name> + <tooltip>Show attachments for this message</tooltip> + <label>Show +attachments</label> + <active>False</active> + </widget> + + <widget> + <class>GtkButton</class> + <child_name>Toolbar:button</child_name> + <name>toolbar_add_attachment</name> + <tooltip>Attach a file</tooltip> + <label>Attach +file</label> + </widget> + </widget> + </widget> + + <widget> + <class>Placeholder</class> + <child_name>GnomeDock:contents</child_name> + </widget> + </widget> + + <widget> + <class>GnomeAppBar</class> + <child_name>GnomeApp:appbar</child_name> + <name>appbar</name> + <has_progress>True</has_progress> + <has_status>True</has_status> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + </widget> +</widget> + +</GTK-Interface> diff --git a/widgets/e-msg-composer.h b/widgets/e-msg-composer.h new file mode 100644 index 0000000000..46657479a3 --- /dev/null +++ b/widgets/e-msg-composer.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer.h + * + * Copyright (C) 1999 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. + * + * Author: Ettore Perazzoli + */ + +#ifndef ___E_MSG_COMPOSER_H__ +#define ___E_MSG_COMPOSER_H__ + +#include <gnome.h> +#include <glade/glade.h> + +#include "e-msg-composer-attachment-bar.h" +#include "e-msg-composer-hdrs.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + + +#define E_TYPE_MSG_COMPOSER (e_msg_composer_get_type ()) +#define E_MSG_COMPOSER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER, EMsgComposer)) +#define E_MSG_COMPOSER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER, EMsgComposerClass)) +#define E_IS_MSG_COMPOSER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER)) +#define E_IS_MSG_COMPOSER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER)) + + +typedef struct _EMsgComposer EMsgComposer; +typedef struct _EMsgComposerClass EMsgComposerClass; + +struct _EMsgComposer { + GnomeApp parent; + + GladeXML *menubar_gui; + GladeXML *toolbar_gui; + GladeXML *appbar_gui; + + GtkWidget *hdrs; + + GtkWidget *text; + GtkWidget *text_scrolled_window; + + GtkWidget *attachment_bar; + GtkWidget *attachment_scrolled_window; + + gboolean attachment_bar_visible : 1; +}; + +struct _EMsgComposerClass { + GnomeAppClass parent_class; + + void (* send) (EMsgComposer *composer); + void (* postpone) (EMsgComposer *composer); +}; + + +GtkType e_msg_composer_get_type (void); +void e_msg_composer_construct (EMsgComposer *composer); +GtkWidget *e_msg_composer_new (void); +void e_msg_composer_show_attachments (EMsgComposer *composer, gboolean show); +CamelMimeMessage *e_msg_composer_get_message (EMsgComposer *composer); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ___E_MSG_COMPOSER_H__ */ diff --git a/widgets/e-table/.cvsignore b/widgets/e-table/.cvsignore new file mode 100644 index 0000000000..09980ae6ba --- /dev/null +++ b/widgets/e-table/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.la diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index e8d0c8e9ed..77a6c36c61 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,26 @@ +1999-11-05 Ettore Perazzoli <ettore@gnu.org> + + * Makefile.am: Compile the new files in a `libevolutionwidgets' + library. + (CPPFLAGS): #define `E_GUIDIR'. + + * e-msg-composer.c, e-msg-composer.h: New files implementing an + initial version of the Evolution message composer widget. + + * e-msg-composer-address-entry.c, e-msg-composer-address-entry.h: + New files implementing a GtkEntry customized for entering email + address lists. + + * e-msg-composer-attachment-bar.c, e-msg-composer-attachment-bar.h: + New files implementing a widget for editing mail attachments. + + * e-msg-composer-attachment.c, e-msg-composer-attachment.h: New + files implementing file attachment objects for the message + composer. + + * e-msg-composer-hdrs.c, e-msg-composer-hdrs.h: New files + implementing a widget for editing of email message headers. + 1999-10-31 Miguel de Icaza <miguel@gnu.org> * widgets/e-table-column.c, e-table-column.h: New file, implements the diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index d6aa94fb90..35d1bc64a4 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -1,7 +1,29 @@ -noinst_LIBRARIES = \ - e-table-simple.c \ - e-table-simple.h \ - e-table-model.c \ - e-table-model.h \ - e-table-column-model.c \ - e-table-column-model.h \ +guidir = $(datadir)/evolution/gui + +gui_DATA = \ + e-msg-composer-attachment.glade \ + e-msg-composer.glade + +INCLUDES = \ + -I$(top_srcdir)/camel \ + -I$(top_builddir)/camel \ + $(GNOME_INCLUDEDIR) + +CPPFLAGS = \ + -DE_GUIDIR=\"$(guidir)\" + +noinst_LTLIBRARIES = \ + libevolutionwidgets.la + +libevolutionwidgets_la_SOURCES = \ + e-msg-composer-address-entry.c \ + e-msg-composer-address-entry.h \ + e-msg-composer-attachment-bar.c \ + e-msg-composer-attachment-bar.h \ + e-msg-composer-attachment.c \ + e-msg-composer-attachment.h \ + e-msg-composer-hdrs.c \ + e-msg-composer-hdrs.h \ + e-msg-composer.c \ + e-msg-composer.h + diff --git a/widgets/table/.cvsignore b/widgets/table/.cvsignore new file mode 100644 index 0000000000..09980ae6ba --- /dev/null +++ b/widgets/table/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.la |