Re: [Fwd: [evolution-patches] [resend] patches for #20672 (gtkhtml and mailer)]
- From: Michel Dänzer <michel daenzer net>
- To: Radek Doulík <rodo ximian com>
- Cc: Patches <evolution-patches ximian com>
- Subject: Re: [Fwd: [evolution-patches] [resend] patches for #20672 (gtkhtml and mailer)]
- Date: Sun, 09 Nov 2003 02:04:44 +0100
On Thu, 2003-11-06 at 16:02, Radek Doul�wrote:
>
> I thought about that bug again and I think we don't need any change on
> gtkhtml's side. I am attaching composer fix (autosave.fix) and your
> evolution-changed.diff patch. Could you test that the fix works for you?
It doesn't work very well; e.g. it doesn't autosave once after a
composer is created, and it degrades to autosaving every time after a
header change.
However, I was intrigued by the idea, and after a lot of thinking,
fiddling and testing, I've finally arrived at a solution which works
very well even without changing gtkhtml. :) The only minor caveat is
that if you e.g.
* save the message (as a draft or file)
* make changes
* let it autosave
* undo the changes
* close the composer
it will no longer realise that the message is actually saved and prompt
about unsaved changes; similarly for autosave-change-save-undo-autosave,
but that's even less of an issue. Negligible corner cases IMHO.
I'm curious what you guys think about this.
The other patch you posted again is as obviously correct as ever. :)
--
Earthling Michel D�er | Debian (powerpc), X and DRI developer
Software libre enthusiast | http://svcs.affero.net/rm.php?r=daenzer
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/composer/ChangeLog,v
retrieving revision 1.544.2.16
diff -p -u -r1.544.2.16 ChangeLog
--- ChangeLog 6 Oct 2003 17:07:16 -0000 1.544.2.16
+++ ChangeLog 9 Nov 2003 00:38:15 -0000
@@ -0,0 +0,28 @@
+2003-11-08 Michel D�er <michel daenzer net>
+
+ * e-msg-composer.h: e_msg_composer_is_dirty prototype removed.
+ (struct _EMsgComposerSaveState): Added.
+ (enum _EMsgComposerState): Added.
+ (struct _EMsgComposer): Replace has_changed field by array of
+ _EMsgComposerSaveState structs.
+
+ * e-msg-composer.c (e_msg_composer_do_unset_changed): Added, clear
+ the has_changed flag and set the had_undo flag to whether the
+ editor engine has an undo queue for the specified state.
+ (e_msg_composer_is_dirty): Make static; don't just test for the
+ presence of an undo queue in the editor engine but compare to
+ remembered state.
+ (save): Preserve autosave state.
+ (autosave_save_draft): Call e_msg_composer_is_dirty() for
+ STATE_AUTOSAVE to only autosave when necessary. Fixes bug #20672.
+ Preserve save state.
+ (menu_file_save_draft_cb): Preserve autosave state.
+ (do_exit): Call e_msg_composer_is_dirty() for STATE_SAVE to only
+ prompt about unsaved changes when necessary. Preserve autosave
+ state.
+ (init): Initialize save and autosave states.
+ (e_msg_composer_set_changed): Set save and autosave has_changed
+ flags.
+ (e_msg_composer_unset_changed): Call new
+ e_msg_composer_do_unset_changed() function for STATE_SAVE.
+
Index: e-msg-composer.c
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.c,v
retrieving revision 1.395.2.8
diff -p -u -r1.395.2.8 e-msg-composer.c
--- e-msg-composer.c 6 Oct 2003 17:07:16 -0000 1.395.2.8
+++ e-msg-composer.c 9 Nov 2003 00:38:16 -0000
@@ -1142,6 +1142,41 @@ set_editor_text (EMsgComposer *composer,
bonobo_object_unref (BONOBO_OBJECT (stream));
}
+static void
+e_msg_composer_do_unset_changed (EMsgComposer *composer, _EMsgComposerState state)
+{
+ CORBA_Environment ev;
+
+ if (state >= STATE_LAST)
+ return;
+
+ CORBA_exception_init (&ev);
+ composer->state[state].had_undo = GNOME_GtkHTML_Editor_Engine_hasUndo (composer->editor_engine, &ev);
+ CORBA_exception_free (&ev);
+
+ composer->state[state].has_changed = FALSE;
+}
+
+static gboolean
+e_msg_composer_is_dirty (EMsgComposer *composer, _EMsgComposerState state)
+{
+ CORBA_Environment ev;
+ gboolean rv;
+
+ if (state >= STATE_LAST || composer->state[state].has_changed)
+ return TRUE;
+
+ CORBA_exception_init (&ev);
+ if (GNOME_GtkHTML_Editor_Engine_hasUndo (composer->editor_engine, &ev))
+ rv = !composer->state[state].had_undo ||
+ !GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "is-saved", &ev);
+ else
+ rv = composer->state[state].had_undo;
+ CORBA_exception_free (&ev);
+
+ return rv;
+}
+
/* Commands. */
static void
@@ -1218,9 +1253,14 @@ save (EMsgComposer *composer, const char
e_notice (composer, GTK_MESSAGE_ERROR, _("Error saving file: %s"), tmp);
g_free(tmp);
- } else
+ } else {
+ gboolean dirty_autosave = e_msg_composer_is_dirty (composer, STATE_AUTOSAVE);
GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "saved", &ev);
-
+ e_msg_composer_do_unset_changed (composer, STATE_SAVE);
+ /* Restore autosave state */
+ if (dirty_autosave)
+ composer->state[STATE_AUTOSAVE].has_changed = TRUE;
+ }
CORBA_exception_free (&ev);
g_free (filename);
@@ -1269,7 +1309,7 @@ autosave_save_draft (EMsgComposer *compo
int fd, camelfd;
gboolean success = TRUE;
- if (!e_msg_composer_is_dirty (composer))
+ if (!e_msg_composer_is_dirty (composer, STATE_AUTOSAVE))
return TRUE;
fd = composer->autosave_fd;
@@ -1320,6 +1360,16 @@ autosave_save_draft (EMsgComposer *compo
_("Error autosaving message: %s\n %s"), file, strerror(errno));
success = FALSE;
+ } else {
+ gboolean dirty_save = e_msg_composer_is_dirty (composer, STATE_SAVE);
+ CORBA_Environment ev;
+ CORBA_exception_init (&ev);
+ GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "saved", &ev);
+ CORBA_exception_free (&ev);
+ e_msg_composer_do_unset_changed (composer, STATE_AUTOSAVE);
+ /* Restore save state */
+ if (dirty_save)
+ composer->state[STATE_SAVE].has_changed = TRUE;
}
camel_object_unref (stream);
@@ -1552,8 +1602,13 @@ autosave_manager_unregister (AutosaveMan
static void
menu_file_save_draft_cb (BonoboUIComponent *uic, void *data, const char *path)
{
+ EMsgComposer *composer = E_MSG_COMPOSER (data);
+ gboolean dirty_autosave = e_msg_composer_is_dirty (composer, STATE_AUTOSAVE);
g_signal_emit (data, signals[SAVE_DRAFT], 0, FALSE);
- e_msg_composer_unset_changed (E_MSG_COMPOSER (data));
+ e_msg_composer_do_unset_changed (composer, STATE_SAVE);
+ /* Restore autosave state */
+ if (dirty_autosave)
+ composer->state[STATE_AUTOSAVE].has_changed = TRUE;
}
/* Exit dialog. (Displays a "Save composition to 'Drafts' before exiting?" warning before actually exiting.) */
@@ -1565,7 +1620,7 @@ do_exit (EMsgComposer *composer)
GtkWidget *dialog;
int button;
- if (!e_msg_composer_is_dirty (composer)) {
+ if (!e_msg_composer_is_dirty (composer, STATE_SAVE)) {
gtk_widget_destroy (GTK_WIDGET (composer));
return;
}
@@ -1594,8 +1649,14 @@ do_exit (EMsgComposer *composer)
switch (button) {
case GTK_RESPONSE_YES:
/* Save */
- g_signal_emit (GTK_OBJECT (composer), signals[SAVE_DRAFT], 0, TRUE);
- e_msg_composer_unset_changed (composer);
+ {
+ gboolean dirty_autosave = e_msg_composer_is_dirty (composer, STATE_AUTOSAVE);
+ g_signal_emit (GTK_OBJECT (composer), signals[SAVE_DRAFT], 0, TRUE);
+ e_msg_composer_do_unset_changed (composer, STATE_SAVE);
+ /* Restore autosave state */
+ if (dirty_autosave)
+ composer->state[STATE_AUTOSAVE].has_changed = TRUE;
+ }
break;
case GTK_RESPONSE_NO:
/* Don't save */
@@ -2706,7 +2772,10 @@ init (EMsgComposer *composer)
composer->smime_sign = FALSE;
composer->smime_encrypt = FALSE;
- composer->has_changed = FALSE;
+ composer->state[STATE_SAVE].has_changed = FALSE;
+ composer->state[STATE_SAVE].had_undo = FALSE;
+ composer->state[STATE_AUTOSAVE].has_changed = TRUE;
+ composer->state[STATE_AUTOSAVE].had_undo = FALSE;
composer->redirect = FALSE;
@@ -4884,14 +4953,16 @@ e_msg_composer_guess_mime_type (const ch
* @composer: An EMsgComposer object.
*
* Mark the composer as changed, so before the composer gets destroyed
- * the user will be prompted about unsaved changes.
+ * the user will be prompted about unsaved changes, and the message will be
+ * autosaved.
**/
void
e_msg_composer_set_changed (EMsgComposer *composer)
{
g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
- composer->has_changed = TRUE;
+
+ composer->state[STATE_SAVE].has_changed = TRUE;
+ composer->state[STATE_AUTOSAVE].has_changed = TRUE;
}
@@ -4906,24 +4977,8 @@ void
e_msg_composer_unset_changed (EMsgComposer *composer)
{
g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
- composer->has_changed = FALSE;
-}
-
-
-gboolean
-e_msg_composer_is_dirty (EMsgComposer *composer)
-{
- CORBA_Environment ev;
- gboolean rv;
-
- CORBA_exception_init (&ev);
- rv = composer->has_changed
- || (GNOME_GtkHTML_Editor_Engine_hasUndo (composer->editor_engine, &ev) &&
- !GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "is-saved", &ev));
- CORBA_exception_free (&ev);
- return rv;
+ e_msg_composer_do_unset_changed (composer, STATE_SAVE);
}
Index: e-msg-composer.h
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.h,v
retrieving revision 1.83
diff -p -u -r1.83 e-msg-composer.h
--- e-msg-composer.h 20 May 2003 18:26:09 -0000 1.83
+++ e-msg-composer.h 9 Nov 2003 00:38:16 -0000
@@ -50,6 +50,16 @@ extern "C" {
#define E_IS_MSG_COMPOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER))
+struct _EMsgComposerSaveState {
+ guint32 has_changed : 1;
+ guint32 had_undo : 1;
+};
+
+typedef enum {
+ STATE_SAVE,
+ STATE_AUTOSAVE,
+ STATE_LAST
+} _EMsgComposerState;
struct _EMsgComposer {
BonoboWindow parent;
@@ -93,7 +103,8 @@ struct _EMsgComposer {
guint32 view_bcc : 1;
guint32 view_cc : 1;
guint32 view_subject : 1;
- guint32 has_changed : 1;
+
+ struct _EMsgComposerSaveState state[STATE_LAST];
guint32 mode_post : 1;
@@ -180,7 +191,6 @@ void e_msg_composer_
char *e_msg_composer_guess_mime_type (const char *file_name);
void e_msg_composer_set_changed (EMsgComposer *composer);
void e_msg_composer_unset_changed (EMsgComposer *composer);
-gboolean e_msg_composer_is_dirty (EMsgComposer *composer);
void e_msg_composer_set_enable_autosave (EMsgComposer *composer,
gboolean enabled);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]