mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
35d9460997
commit
9812cec1c2
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user