Initial autosave feature

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16226 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Christian Stimming 2007-06-30 10:31:14 +00:00
parent 35d9460997
commit 9812cec1c2
3 changed files with 256 additions and 13 deletions

View File

@ -1640,7 +1640,7 @@
<widget class="GtkTable" id="table2">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="n_rows">16</property>
<property name="n_rows">17</property>
<property name="n_columns">4</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
@ -1776,8 +1776,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">12</property>
<property name="bottom_attach">13</property>
<property name="top_attach">13</property>
<property name="bottom_attach">14</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
@ -1805,8 +1805,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">12</property>
<property name="bottom_attach">13</property>
<property name="top_attach">13</property>
<property name="bottom_attach">14</property>
<property name="x_padding">12</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
@ -2071,8 +2071,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">13</property>
<property name="bottom_attach">14</property>
<property name="top_attach">14</property>
<property name="bottom_attach">15</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
@ -2099,8 +2099,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">14</property>
<property name="bottom_attach">15</property>
<property name="top_attach">15</property>
<property name="bottom_attach">16</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
@ -2128,8 +2128,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">15</property>
<property name="bottom_attach">16</property>
<property name="top_attach">16</property>
<property name="bottom_attach">17</property>
<property name="x_padding">12</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
@ -2152,8 +2152,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">15</property>
<property name="bottom_attach">16</property>
<property name="top_attach">16</property>
<property name="bottom_attach">17</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
@ -2182,6 +2182,97 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label119">
<property name="visible">True</property>
<property name="label" translatable="yes">Auto-save time _interval:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">gconf/general/autosave_interval_minutes</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">12</property>
<property name="bottom_attach">13</property>
<property name="x_padding">12</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<widget class="GtkSpinButton" id="gconf/general/autosave_interval_minutes">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">The number of minutes until saving of the data file to harddisk will be started automatically. If zero, no saving will be started automatically.</property>
<property name="can_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">0</property>
<property name="numeric">False</property>
<property name="update_policy">GTK_UPDATE_ALWAYS</property>
<property name="snap_to_ticks">False</property>
<property name="wrap">False</property>
<property name="adjustment">3 0 99999 1 10 10</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label120">
<property name="visible">True</property>
<property name="label" translatable="yes">minutes</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">12</property>
<property name="bottom_attach">13</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>

View File

@ -1271,12 +1271,140 @@ gnc_main_window_update_all_titles (void)
NULL);
}
#define KEY_AUTOSAVE_SHOW_EXPLANATION "autosave_show_explanation"
#define KEY_AUTOSAVE_INTERVAL "autosave_interval_minutes"
#define AUTOSAVE_SOURCE_ID "autosave_source_id"
/* Here's how autosave works:
*
* Initially, the book is in state "undirty". Once the book changes
* state to "dirty", hence calling
* gnc_main_window_autosave_dirty(true), the auto-save timer is added
* and started. Now one out of two state changes can occur (well,
* three actually), depending on which event occurs first:
*
* - Either the book changes state to "undirty", hence calling
* gnc_main_window_autosave_dirty(false). In this case the auto-save
* timer is removed and all returns to the initial state with the book
* "undirty".
*
* - Or the auto-save timer hits its timeout, hence calling
* autosave_timeout_cb(). In this case gnc_file_save() is invoked, the
* auto-save timer is removed, and all returns to the initial state
* with the book "undirty". (As an exceptional addition to this, on
* the very first call to autosave_timeout_cb, if the key
* autosave_show_explanation is true, an explanation dialog of this
* feature is shown to the user, and the key autosave_show_explanation
* is set to false to not show this dialog again.)
*
* - As a third possibility, the book can also change state to
* "closing", in which case the autosave_remove_timer_cb is called
* that removes the auto-save timer and all returns to the initial
* state with the book "undirty".
*/
static gboolean autosave_timeout_cb(gpointer user_data)
{
/* QofBook *book = user_data; */
gboolean show_explanation;
/* Is there already a save in progress? If yes, return FALSE so that
the timeout is automatically destroyed and the function will not
be called again. */
if (gnc_file_save_in_progress() || !gnc_current_session_exist())
return FALSE;
/* Lookup gconf key to show an explanatory dialog the very first
time this becomes active. */
show_explanation =
gnc_gconf_get_bool(GCONF_GENERAL, KEY_AUTOSAVE_SHOW_EXPLANATION, NULL);
if (show_explanation) {
guint interval_mins =
gnc_gconf_get_float(GCONF_GENERAL, KEY_AUTOSAVE_INTERVAL, NULL);
/* The autosave timeout has occurred for the very first
time. Explain this feature. */
gnc_info_dialog(NULL,
_("Your data file needs to be saved to your harddisk to save your changes. GnuCash has a feature to save the file automatically every %d minutes. This feature is being activated the very first time right now. \n\n"
"If you like to change the time interval, you can do so under Edit -> Preferences -> General -> Auto-save time interval. If you like to switch off this feature, set the time interval to zero and no auto-save will occur anymore.\n\n"
"Press \"Close\" now so that your file will be saved."),
interval_mins);
/* Don't show this explanation again. */
gnc_gconf_set_bool(GCONF_GENERAL, KEY_AUTOSAVE_SHOW_EXPLANATION, FALSE, NULL);
}
/* Timeout has passed - save the file. */
gnc_file_save();
/* Return FALSE so that the timeout is automatically destroyed and
the function will not be called again. */
return FALSE;
}
static void
autosave_remove_timer_cb(QofBook *book, gpointer key, gpointer user_data)
{
guint autosave_source_id = GPOINTER_TO_UINT(user_data);
/* Remove the timer that would have triggered the next autosave */
if (autosave_source_id > 0)
g_source_remove (autosave_source_id);
}
static void autosave_remove_timer(QofBook *book)
{
autosave_remove_timer_cb(book, AUTOSAVE_SOURCE_ID,
qof_book_get_data(book, AUTOSAVE_SOURCE_ID));
}
static void autosave_add_timer(QofBook *book)
{
guint interval_mins =
gnc_gconf_get_float(GCONF_GENERAL, KEY_AUTOSAVE_INTERVAL, NULL);
/* Interval zero means auto-save is turned off. */
if (interval_mins > 0) {
/* Add a new timer (timeout) that runs until the next autosave
timeout. */
guint autosave_source_id =
#if GLIB_CHECK_VERSION(2, 14, 0)
/* g_timeout_add_seconds is much more suitable here, but is new in
glib-2.14. */
g_timeout_add_seconds(interval_mins * 60,
autosave_timeout_cb, book);
#else
g_timeout_add(interval_mins * 60 * 1000,
autosave_timeout_cb, book);
#endif
g_debug("Added new auto save timer with id %d\n", autosave_source_id);
/* Save the event source id for a potential removal, and also
set the callback upon book closing */
qof_book_set_data_fin(book, AUTOSAVE_SOURCE_ID,
GUINT_TO_POINTER(autosave_source_id),
autosave_remove_timer_cb);
}
}
static void gnc_main_window_autosave_dirty (QofBook *book, gboolean dirty)
{
if (dirty) {
/* Book state changed from non-dirty to dirty. Start the autosave
timer. */
/* First stop a potentially running old timer. */
autosave_remove_timer(book);
/* Add a new timer (timeout) that runs until the next autosave
timeout. */
autosave_add_timer(book);
} else {
/* Book state changed from dirty to non-dirty (probably due to
saving). Delete the running autosave timer. */
autosave_remove_timer(book);
}
}
static void
gnc_main_window_book_dirty_cb (QofBook *book,
gboolean dirty,
gpointer user_data)
{
gnc_main_window_update_all_titles();
/* Auto-save feature */
gnc_main_window_autosave_dirty(book, dirty);
}
static void

View File

@ -43,6 +43,30 @@
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/general/autosave_show_explanation</key>
<applyto>/apps/gnucash/general/autosave_show_explanation</applyto>
<owner>gnucash</owner>
<type>bool</type>
<default>TRUE</default>
<locale name="C">
<short>Show auto-save explanation</short>
<long>If active, GnuCash shows an explanation of the auto-save feature the first time that feature is started. Otherwise no extra explanation is shown.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/general/autosave_interval_minutes</key>
<applyto>/apps/gnucash/general/autosave_interval_minutes</applyto>
<owner>gnucash</owner>
<type>float</type>
<default>3</default>
<locale name="C">
<short>Auto-save time interval</short>
<long>The number of minutes until saving of the data file to harddisk will be started automatically. If zero, no saving will be started automatically.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/general/negative_in_red</key>
<applyto>/apps/gnucash/general/negative_in_red</applyto>