[glade/composite-templates-new: 6/10] Implemented autosave and backups
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glade/composite-templates-new: 6/10] Implemented autosave and backups
- Date: Sat, 6 Apr 2013 14:17:43 +0000 (UTC)
commit b669bff33127341378dbab176ab87614c71f7ef0
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sat Apr 6 17:32:52 2013 +0900
Implemented autosave and backups
Whenever the user saves, the last version of the file is backed up.
Whenever the project is modified and idle for a configurable amount of
seconds, the project is automatically saved.
At load time, if the automatically saved file is newer than the proposed
Glade file, Glade will popup a dialog and let the user choose to load
the autosaved version instead
src/glade-preferences.c | 66 ++++++++++++
src/glade-preferences.h | 5 +
src/glade-window.c | 148 ++++++++++++++++++++-------
src/glade.glade | 259 +++++++++++++++++++++++++++++++----------------
4 files changed, 354 insertions(+), 124 deletions(-)
---
diff --git a/src/glade-preferences.c b/src/glade-preferences.c
index 6e25b5f..35865f1 100644
--- a/src/glade-preferences.c
+++ b/src/glade-preferences.c
@@ -26,11 +26,20 @@ struct _GladePreferences
{
GObject *toplevel;
GtkComboBoxText *catalog_path_combo;
+
+ GtkWidget *create_backups_toggle;
+ GtkWidget *autosave_toggle;
+ GtkWidget *autosave_spin;
};
#define CONFIG_GROUP "Preferences"
#define CONFIG_KEY_CATALOG_PATHS "catalog-paths"
+#define CONFIG_GROUP_LOAD_SAVE "Load and Save"
+#define CONFIG_KEY_BACKUP "backup"
+#define CONFIG_KEY_AUTOSAVE "autosave"
+#define CONFIG_KEY_AUTOSAVE_SECONDS "autosave-seconds"
+
static void
combo_box_text_init_cell (GtkCellLayout *cell)
{
@@ -49,6 +58,14 @@ combo_box_text_init_cell (GtkCellLayout *cell)
g_list_free (cels);
}
+static void
+autosave_toggled (GtkToggleButton *button,
+ GladePreferences *prefs)
+{
+ gtk_widget_set_sensitive (prefs->autosave_spin,
+ gtk_toggle_button_get_active (button));
+}
+
GladePreferences *
glade_preferences_new (GtkBuilder *builder)
{
@@ -57,6 +74,13 @@ glade_preferences_new (GtkBuilder *builder)
prefs->toplevel = gtk_builder_get_object (builder, "preferences_dialog");
prefs->catalog_path_combo = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder,
"catalog_path_comboboxtext"));
combo_box_text_init_cell (GTK_CELL_LAYOUT (prefs->catalog_path_combo));
+
+ prefs->create_backups_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "create_backups_toggle"));
+ prefs->autosave_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "autosave_toggle"));
+ prefs->autosave_spin = GTK_WIDGET (gtk_builder_get_object (builder, "autosave_spin"));
+
+ g_signal_connect (G_OBJECT (prefs->autosave_toggle), "toggled",
+ G_CALLBACK (autosave_toggled), prefs);
return prefs;
}
@@ -93,6 +117,13 @@ glade_preferences_config_save (GladePreferences *prefs, GKeyFile *config)
g_key_file_set_string (config, CONFIG_GROUP, CONFIG_KEY_CATALOG_PATHS, string->str);
+ g_key_file_set_boolean (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_BACKUP,
+ glade_preferences_backup (prefs));
+ g_key_file_set_boolean (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_AUTOSAVE,
+ glade_preferences_autosave (prefs));
+ g_key_file_set_integer (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_AUTOSAVE_SECONDS,
+ glade_preferences_autosave_seconds (prefs));
+
g_string_free (string, TRUE);
}
@@ -100,6 +131,9 @@ void
glade_preferences_config_load (GladePreferences *prefs, GKeyFile *config)
{
gchar *string;
+ gboolean backups = TRUE;
+ gboolean autosave = TRUE;
+ gint autosave_seconds = 30;
string = g_key_file_get_string (config, CONFIG_GROUP, CONFIG_KEY_CATALOG_PATHS, NULL);
@@ -124,9 +158,41 @@ glade_preferences_config_load (GladePreferences *prefs, GKeyFile *config)
g_strfreev (paths);
}
+ if (g_key_file_has_key (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_BACKUP, NULL))
+ backups = g_key_file_get_boolean (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_BACKUP, NULL);
+
+ if (g_key_file_has_key (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_AUTOSAVE, NULL))
+ autosave = g_key_file_get_boolean (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_AUTOSAVE, NULL);
+
+ if (g_key_file_has_key (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_AUTOSAVE_SECONDS, NULL))
+ autosave_seconds = g_key_file_get_integer (config, CONFIG_GROUP_LOAD_SAVE, CONFIG_KEY_AUTOSAVE_SECONDS,
NULL);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->create_backups_toggle), backups);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->autosave_toggle), autosave);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (prefs->autosave_spin), autosave_seconds);
+ gtk_widget_set_sensitive (prefs->autosave_spin, autosave);
+
g_free (string);
}
+gboolean
+glade_preferences_backup (GladePreferences *prefs)
+{
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prefs->create_backups_toggle));
+}
+
+gboolean
+glade_preferences_autosave (GladePreferences *prefs)
+{
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prefs->autosave_toggle));
+}
+
+gint
+glade_preferences_autosave_seconds (GladePreferences *prefs)
+{
+ return (gint)gtk_spin_button_get_value (GTK_SPIN_BUTTON (prefs->autosave_spin));
+}
+
/* Callbacks */
static gboolean
diff --git a/src/glade-preferences.h b/src/glade-preferences.h
index 7abc0ba..cb47b5b 100644
--- a/src/glade-preferences.h
+++ b/src/glade-preferences.h
@@ -34,6 +34,10 @@ void glade_preferences_config_save (GladePreferences *prefs,
void glade_preferences_config_load (GladePreferences *prefs,
GKeyFile *config);
+gboolean glade_preferences_backup (GladePreferences *prefs);
+gboolean glade_preferences_autosave (GladePreferences *prefs);
+gint glade_preferences_autosave_seconds (GladePreferences *prefs);
+
/* Callbacks */
void on_preferences_filechooserdialog_response (GtkDialog *dialog,
@@ -42,4 +46,5 @@ void on_preferences_filechooserdialog_response (GtkDialog *dialog,
void on_catalog_path_remove_button_clicked (GtkButton *button,
GtkComboBoxText *combo);
+
#endif /* __GLADE_PREFERENCES_H__ */
diff --git a/src/glade-window.c b/src/glade-window.c
index b1d3360..280c61a 100644
--- a/src/glade-window.c
+++ b/src/glade-window.c
@@ -71,6 +71,11 @@
#define CONFIG_KEY_SHOW_STATUS "show-statusbar"
#define CONFIG_KEY_EDITOR_HEADER "show-editor-header"
+#define CONFIG_GROUP_LOAD_SAVE "Load and Save"
+#define CONFIG_KEY_BACKUP "backup"
+#define CONFIG_KEY_AUTOSAVE "autosave"
+#define CONFIG_KEY_AUTOSAVE_SECONDS "autosave-seconds"
+
#define GLADE_WINDOW_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
GLADE_TYPE_WINDOW, \
GladeWindowPrivate))
@@ -669,15 +674,76 @@ refresh_undo_redo (GladeWindow *window, GladeProject *project)
}
static void
+cancel_autosave (gpointer data)
+{
+ guint autosave_id = GPOINTER_TO_UINT (data);
+
+ g_source_remove (autosave_id);
+}
+
+static gboolean
+autosave_project (gpointer data)
+{
+ GladeProject *project = (GladeProject *)data;
+ GladeWindow *window = GLADE_WINDOW (glade_app_get_window ());
+ gchar *display_name;
+
+ display_name = glade_project_get_name (project);
+
+ if (glade_project_autosave (project, NULL))
+ glade_util_flash_message (window->priv->statusbar,
+ window->priv->statusbar_actions_context_id,
+ _("Autosaving '%s'"), display_name);
+ else
+ /* This is problematic, should we be more intrusive and popup a dialog ? */
+ glade_util_flash_message (window->priv->statusbar,
+ window->priv->statusbar_actions_context_id,
+ _("Error autosaving '%s'"), display_name);
+
+ g_free (display_name);
+
+ /* This will remove the source id */
+ g_object_set_data (G_OBJECT (project), "glade-autosave-id", NULL);
+ return FALSE;
+}
+
+static void
+project_queue_autosave (GladeWindow *window,
+ GladeProject *project)
+{
+ if (glade_project_get_path (project) != NULL &&
+ glade_project_get_modified (project) &&
+ glade_preferences_autosave (window->priv->preferences))
+ {
+ guint autosave_id =
+ g_timeout_add_seconds (glade_preferences_autosave_seconds (window->priv->preferences),
+ autosave_project, project);
+
+ g_object_set_data_full (G_OBJECT (project), "glade-autosave-id",
+ GUINT_TO_POINTER (autosave_id), cancel_autosave);
+ }
+ else
+ g_object_set_data (G_OBJECT (project), "glade-autosave-id", NULL);
+}
+
+static void
+project_cancel_autosave (GladeProject *project)
+{
+ g_object_set_data (G_OBJECT (project), "glade-autosave-id", NULL);
+}
+
+static void
project_changed_cb (GladeProject *project,
GladeCommand *command,
gboolean execute,
GladeWindow *window)
{
GladeProject *active_project = get_active_project (window);
-
+
if (project == active_project)
refresh_undo_redo (window, project);
+
+ project_queue_autosave (window, project);
}
static void
@@ -1079,11 +1145,48 @@ check_loading_project_for_save (GladeProject *project)
return FALSE;
}
+static gboolean
+do_save (GladeWindow *window, GladeProject *project, const gchar *path)
+{
+ GError *error = NULL;
+ gchar *display_path = g_strdup (path);
+
+ if (glade_preferences_backup (window->priv->preferences) &&
+ !glade_project_backup (project, path, NULL))
+ {
+ if (!glade_util_ui_message (GTK_WIDGET (window),
+ GLADE_UI_ARE_YOU_SURE, NULL,
+ _("Failed to backup existing file, continue saving ?")))
+ {
+ g_free (display_path);
+ return FALSE;
+ }
+ }
+
+ if (!glade_project_save (project, path, &error))
+ {
+ /* Reset path so future saves will prompt the file chooser */
+ glade_project_reset_path (project);
+
+ if (error)
+ {
+ glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_ERROR, NULL,
+ _("Failed to save %s: %s"),
+ display_path, error->message);
+ g_error_free (error);
+ }
+ g_free (display_path);
+ return FALSE;
+ }
+
+ g_free (display_path);
+ return TRUE;
+}
+
static void
save (GladeWindow *window, GladeProject *project, const gchar *path)
{
- GError *error = NULL;
- gchar *display_name, *display_path = g_strdup (path);
+ gchar *display_name;
time_t mtime;
GtkWidget *dialog;
GtkWidget *button;
@@ -1132,31 +1235,15 @@ save (GladeWindow *window, GladeProject *project, const gchar *path)
gtk_widget_destroy (dialog);
if (response == GTK_RESPONSE_REJECT)
- {
- g_free (display_path);
- return;
- }
+ return;
}
}
/* Interestingly; we cannot use `path' after glade_project_reset_path
* because we are getting called with glade_project_get_path (project) as an argument.
*/
- if (!glade_project_save (project, path, &error))
- {
- /* Reset path so future saves will prompt the file chooser */
- glade_project_reset_path (project);
-
- if (error)
- {
- glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_ERROR, NULL,
- _("Failed to save %s: %s"),
- display_path, error->message);
- g_error_free (error);
- }
- g_free (display_path);
- return;
- }
+ if (!do_save (window, project, path))
+ return;
/* Get display_name here, it could have changed with "Save As..." */
display_name = glade_project_get_name (project);
@@ -1173,7 +1260,6 @@ save (GladeWindow *window, GladeProject *project, const gchar *path)
window->priv->statusbar_actions_context_id,
_("Project '%s' saved"), display_name);
- g_free (display_path);
g_free (display_name);
}
@@ -1320,7 +1406,6 @@ confirm_close_project (GladeWindow *window, GladeProject *project)
gboolean close = FALSE;
gchar *msg, *project_name = NULL;
gint ret;
- GError *error = NULL;
project_name = glade_project_get_name (project);
@@ -1357,17 +1442,7 @@ confirm_close_project (GladeWindow *window, GladeProject *project)
*/
if (glade_project_get_path (project) != NULL)
{
- if ((close = glade_project_save
- (project, glade_project_get_path (project), &error)) == FALSE)
- {
-
- glade_util_ui_message
- (GTK_WIDGET (window), GLADE_UI_ERROR, NULL,
- _("Failed to save %s to %s: %s"),
- project_name, glade_project_get_path (project),
- error->message);
- g_error_free (error);
- }
+ close = do_save (window, project, glade_project_get_path (project));
}
else
{
@@ -1459,6 +1534,9 @@ do_close (GladeWindow *window, GladeProject *project)
view = glade_design_view_get_from_project (project);
+ /* Cancel any queued autosave activity */
+ project_cancel_autosave (project);
+
if (glade_project_is_loading (project))
{
glade_project_cancel_load (project);
diff --git a/src/glade.glade b/src/glade.glade
index 2eb54a6..bf337be 100644
--- a/src/glade.glade
+++ b/src/glade.glade
@@ -2,6 +2,13 @@
<interface>
<!-- interface-requires gtk+ 3.8 -->
<object class="GtkAccelGroup" id="accelgroup"/>
+ <object class="GtkAdjustment" id="autosave_seconds_adjustment">
+ <property name="lower">1</property>
+ <property name="upper">60</property>
+ <property name="value">1</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
<object class="GtkActionGroup" id="pointer_mode_actiongroup">
<property name="accel_group">accelgroup</property>
<child>
@@ -1193,124 +1200,198 @@ Andreas Nilsson <andreas andreasn se></property>
</packing>
</child>
<child>
- <object class="GtkNotebook" id="notebook1">
+ <object class="GtkBox" id="box1">
<property name="visible">True</property>
- <property name="can_focus">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">7</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkBox" id="box1">
+ <object class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="border_width">7</property>
- <property name="orientation">vertical</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0</property>
+ <property name="shadow_type">none</property>
<child>
- <object class="GtkFrame" id="frame1">
+ <object class="GtkGrid" id="grid2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label_xalign">0</property>
+ <property name="margin_left">12</property>
+ <property name="margin_top">6</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
<child>
- <object class="GtkGrid" id="grid1">
+ <object class="GtkCheckButton" id="create_backups_toggle">
+ <property name="label" translatable="yes">Create Backups</property>
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="border_width">6</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">6</property>
- <child>
- <object class="GtkButton" id="catalog_path_remove_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Removes the selected catalog
path</property>
- <signal name="clicked" handler="on_catalog_path_remove_button_clicked"
object="catalog_path_comboboxtext" swapped="no"/>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-remove</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Create a backup of the last version
of the project every time the project is saved</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="autosave_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">•</property>
+ <property name="adjustment">autosave_seconds_adjustment</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="autosave_toggle">
+ <property name="label" translatable="yes">Autosave after timeout:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Automatically save the project
after the specified timeout passes
+whenever the project is modified</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Load and Save</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="margin_top">6</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkButton" id="catalog_path_remove_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Removes the selected catalog
path</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <signal name="clicked" handler="on_catalog_path_remove_button_clicked"
object="catalog_path_comboboxtext" swapped="no"/>
<child>
- <object class="GtkComboBoxText" id="catalog_path_comboboxtext">
+ <object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="entry_text_column">0</property>
- <property name="id_column">1</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="catalog_path_add_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Add a new catalog
path</property>
- <signal name="clicked" handler="gtk_widget_show"
object="preferences_filechooserdialog" swapped="yes"/>
- <child>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-add</property>
- </object>
- </child>
+ <property name="icon_name">list-remove-symbolic</property>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
</object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
</child>
- <child type="label">
- <object class="GtkLabel" id="label2">
+ <child>
+ <object class="GtkComboBoxText" id="catalog_path_comboboxtext">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Extra catalog paths</property>
- <property name="use_markup">True</property>
+ <property name="hexpand">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="catalog_path_add_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Add a new catalog path</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <signal name="clicked" handler="gtk_widget_show"
object="preferences_filechooserdialog" swapped="yes"/>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">list-add-symbolic</property>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <placeholder/>
</child>
- <child>
- <placeholder/>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Extra catalog paths</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
</child>
</object>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">General</property>
- </object>
<packing>
- <property name="tab_fill">False</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
- <property name="expand">True</property>
+ <property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]