changeset 2670:ec21b78a088c

Fix #543: Size of dialog windows in the GTK3 version is too small https://github.com/BestImageViewer/geeqie/issues/543 Additional option in Preferences/Windows to preserve size and location of dialog windows
author Colin Clark <colin.clark@cclark.uk>
date Thu, 23 Nov 2017 20:44:03 +0000
parents 598aadefd022
children 43b8d416a674
files doc/docbook/GuideOptionsWindow.xml src/layout.c src/options.c src/options.h src/preferences.c src/rcfile.c src/ui_utildlg.c src/ui_utildlg.h
diffstat 8 files changed, 201 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docbook/GuideOptionsWindow.xml	Fri Nov 17 16:46:18 2017 +0000
+++ b/doc/docbook/GuideOptionsWindow.xml	Thu Nov 23 20:44:03 2017 +0000
@@ -59,6 +59,16 @@
         </listitem>
       </varlistentry>
     </variablelist>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <guilabel>Remember dialog window positions</guilabel>
+        </term>
+        <listitem>
+          <para>This will maintain dialog windows size and position between Geeqie sessions.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
   </section>
   <section id="Size">
     <title>Size</title>
--- a/src/layout.c	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/layout.c	Thu Nov 23 20:44:03 2017 +0000
@@ -2489,6 +2489,10 @@
 	bar_sort_write_config(lw->bar_sort, outstr, indent + 1);
 	bar_write_config(lw->bar, outstr, indent + 1);
 
+	WRITE_SEPARATOR();
+	generic_dialog_windows_write_config(outstr, indent + 1);
+
+	WRITE_SEPARATOR();
 	layout_toolbar_write_config(lw, TOOLBAR_MAIN, outstr, indent + 1);
 
 	WRITE_NL(); WRITE_STRING("</layout>");
--- a/src/options.c	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/options.c	Thu Nov 23 20:44:03 2017 +0000
@@ -59,6 +59,7 @@
 	options->save_window_positions = TRUE;
 	options->use_saved_window_positions_for_new_windows = FALSE;
 	options->tools_restore_state = TRUE;
+	options->save_dialog_window_positions = FALSE;
 
 	options->file_ops.confirm_delete = TRUE;
 	options->file_ops.enable_delete_key = TRUE;
--- a/src/options.h	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/options.h	Thu Nov 23 20:44:03 2017 +0000
@@ -56,6 +56,7 @@
 	gboolean save_window_positions;
 	gboolean use_saved_window_positions_for_new_windows;
 	gboolean tools_restore_state;
+	gboolean save_dialog_window_positions;
 
 	gint log_window_lines;
 
--- a/src/preferences.c	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/preferences.c	Thu Nov 23 20:44:03 2017 +0000
@@ -255,6 +255,7 @@
 	options->tools_restore_state = c_options->tools_restore_state;
 	options->save_window_positions = c_options->save_window_positions;
 	options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
+	options->save_dialog_window_positions = c_options->save_dialog_window_positions;
 	options->image.scroll_reset_method = c_options->image.scroll_reset_method;
 	options->image.zoom_2pass = c_options->image.zoom_2pass;
 	options->image.fit_window_to_image = c_options->image.fit_window_to_image;
@@ -1792,6 +1793,9 @@
 	pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
 			      options->tools_restore_state, &c_options->tools_restore_state);
 
+	pref_checkbox_new_int(group, _("Remember dialog window positions"),
+			      options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
+
 	group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
 
 	pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
--- a/src/rcfile.c	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/rcfile.c	Thu Nov 23 20:44:03 2017 +0000
@@ -44,7 +44,7 @@
 #include "metadata.h"
 #include "bar_gps.h"
 #include "dupe.h"
-
+#include "ui_utildlg.h"
 
 /*
  *-----------------------------------------------------------------------------
@@ -337,6 +337,7 @@
 	WRITE_NL(); WRITE_BOOL(*options, save_window_positions);
 	WRITE_NL(); WRITE_BOOL(*options, use_saved_window_positions_for_new_windows);
 	WRITE_NL(); WRITE_BOOL(*options, tools_restore_state);
+	WRITE_NL(); WRITE_BOOL(*options, save_dialog_window_positions);
 
 	WRITE_NL(); WRITE_UINT(*options, log_window_lines);
 	WRITE_NL(); WRITE_BOOL(*options, log_window.timer_data);
@@ -637,6 +638,7 @@
 		if (READ_BOOL(*options, save_window_positions)) continue;
 		if (READ_BOOL(*options, use_saved_window_positions_for_new_windows)) continue;
 		if (READ_BOOL(*options, tools_restore_state)) continue;
+		if (READ_BOOL(*options, save_dialog_window_positions)) continue;
 
 		if (READ_INT(*options, log_window_lines)) continue;
 		if (READ_BOOL(*options, log_window.timer_data)) continue;
@@ -1098,6 +1100,19 @@
 		options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
 		}
 }
+static void options_parse_dialogs(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
+{
+	if (g_ascii_strcasecmp(element_name, "window") == 0)
+		{
+		generic_dialog_windows_load_config(attribute_names, attribute_values);
+		options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+		}
+	else
+		{
+		log_printf("unexpected in <dialogs>: <%s>\n", element_name);
+		options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+		}
+}
 
 static void options_parse_layout(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
 {
@@ -1129,6 +1144,10 @@
 		{
 		options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
 		}
+	else if (g_ascii_strcasecmp(element_name, "dialogs") == 0)
+		{
+		options_parse_func_push(parser_data, options_parse_dialogs, NULL, NULL);
+		}
 	else
 		{
 		log_printf("unexpected in <layout>: <%s>\n", element_name);
--- a/src/ui_utildlg.c	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/ui_utildlg.c	Thu Nov 23 20:44:03 2017 +0000
@@ -36,6 +36,7 @@
 #include "ui_utildlg.h"
 
 #include "filedata.h"
+#include "rcfile.h"
 #include "ui_fileops.h"
 #include "ui_misc.h"
 #include "ui_pathsel.h"
@@ -48,10 +49,96 @@
  *-----------------------------------------------------------------------------
  */
 
+typedef struct _DialogWindow DialogWindow;
+struct _DialogWindow
+{
+	gint x;
+	gint y;
+	gint w;
+	gint h;
+	gchar *title;
+	gchar *role;
+};
+
+static GList *dialog_windows = NULL;
+
+static void generic_dialog_save_window(const gchar *title, const gchar *role, gint x, gint y, gint h, gint w)
+{
+	GList *work;
+
+	work = g_list_first(dialog_windows);
+	while (work)
+		{
+		DialogWindow *dw = work->data;
+		if (g_strcmp0(dw->title ,title) == 0 && g_strcmp0(dw->role, role) == 0)
+			{
+			dw->x = x;
+			dw->y = y;
+			dw->w = w;
+			dw->h = h;
+			return;
+			}
+		work = work->next;
+		}
+
+	DialogWindow *dw = g_new0(DialogWindow, 1);
+	dw->title = g_strdup(title);
+	dw->role = g_strdup(role);
+	dw->x = x;
+	dw->y = y;
+	dw->w = w;
+	dw->h = h;
+
+	dialog_windows = g_list_append(dialog_windows, dw);
+}
+
+static gboolean generic_dialog_find_window(const gchar *title, const gchar *role, gint *x, gint *y, gint *h, gint *w)
+{
+	GList *work;
+
+	work = g_list_first(dialog_windows);
+	while (work)
+		{
+		DialogWindow *dw = work->data;
+
+		if (g_strcmp0(dw->title,title) == 0 && g_strcmp0(dw->role, role) == 0)
+			{
+			*x = dw->x;
+			*y = dw->y;
+			*w = dw->w;
+			*h = dw->h;
+			return TRUE;
+			}
+		work = work->next;
+		}
+	return FALSE;
+}
+
 void generic_dialog_close(GenericDialog *gd)
 {
+	gchar *ident_string;
+	gchar *full_title;
+	gchar *actual_title;
+	gint x, y, h, w;
+
+	gdk_window_get_root_origin(gtk_widget_get_window (gd->dialog), &x, &y);
+	w = gdk_window_get_width(gtk_widget_get_window (gd->dialog));
+	h = gdk_window_get_height(gtk_widget_get_window (gd->dialog));
+
+	/* The window title is modified in window.c: window_new()
+	 * by appending the string " - Geeqie"
+	 */
+	ident_string = g_strconcat(" - ", GQ_APPNAME, NULL);
+	full_title = g_strdup(gtk_window_get_title(GTK_WINDOW(gd->dialog)));
+	actual_title = strndup(full_title, g_strrstr(full_title, ident_string) - full_title);
+
+	generic_dialog_save_window(actual_title, gtk_window_get_role(GTK_WINDOW(gd->dialog)), x, y, w, h);
+
 	gtk_widget_destroy(gd->dialog);
 	g_free(gd);
+	g_free(ident_string);
+	g_free(full_title);
+	g_free(actual_title);
 }
 
 static void generic_dialog_click_cb(GtkWidget *widget, gpointer data)
@@ -227,6 +314,68 @@
 	return vbox;
 }
 
+void generic_dialog_windows_load_config(const gchar **attribute_names, const gchar **attribute_values)
+{
+	DialogWindow *dw =  g_new0(DialogWindow, 1);
+	gchar *title = NULL;
+	gchar *role = NULL;
+	gint x = 0;
+	gint y = 0;
+	gint w = 0;
+	gint h = 0;
+
+	while (*attribute_names)
+		{
+		const gchar *option = *attribute_names++;
+		const gchar *value = *attribute_values++;
+		if (READ_CHAR_FULL("title", title)) continue;
+		if (READ_CHAR_FULL("role", role)) continue;
+		if (READ_INT_FULL("x", x)) continue;
+		if (READ_INT_FULL("y", y)) continue;
+		if (READ_INT_FULL("w", w)) continue;
+		if (READ_INT_FULL("h", h)) continue;
+
+		log_printf("unknown attribute %s = %s\n", option, value);
+		}
+
+	if (title && title[0] != 0)
+		{
+		dw->title = g_strdup(title);
+		dw->role = g_strdup(role);
+		dw->x = x;
+		dw->y = y;
+		dw->w = w;
+		dw->h = h;
+
+		dialog_windows = g_list_append(dialog_windows, dw);
+		}
+}
+
+void generic_dialog_windows_write_config(GString *outstr, gint indent)
+{
+	GList *work;
+
+	WRITE_NL(); WRITE_STRING("<%s>", "dialogs");
+	indent++;
+
+	work = g_list_first(dialog_windows);
+	while (work)
+		{
+		DialogWindow *dw = work->data;
+		WRITE_NL(); WRITE_STRING("<window ");
+		write_char_option(outstr, indent + 1, "title", dw->title);
+		write_char_option(outstr, indent + 1, "role", dw->role);
+		WRITE_INT(*dw, x);
+		WRITE_INT(*dw, y);
+		WRITE_INT(*dw, w);
+		WRITE_INT(*dw, h);
+		WRITE_STRING("/>");
+		work = work->next;
+		}
+	indent--;
+	WRITE_NL(); WRITE_STRING("</%s>", "dialogs");
+}
+
 static void generic_dialog_setup(GenericDialog *gd,
 				 const gchar *title,
 				 const gchar *role,
@@ -234,6 +383,7 @@
 				 void (*cancel_cb)(GenericDialog *, gpointer), gpointer data)
 {
 	GtkWidget *vbox;
+	gint x, y, w, h;
 
 	gd->auto_close = auto_close;
 	gd->data = data;
@@ -242,6 +392,15 @@
 	gd->dialog = window_new(GTK_WINDOW_TOPLEVEL, role, NULL, NULL, title);
 	gtk_window_set_type_hint(GTK_WINDOW(gd->dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
 
+	if (options->save_dialog_window_positions)
+		{
+		if (generic_dialog_find_window(title, role, &x, &y, &w, &h))
+			{
+			gtk_window_set_default_size(GTK_WINDOW(gd->dialog), w, h);
+			gtk_window_move(GTK_WINDOW(gd->dialog), x, y);
+			}
+		}
+
 	if (parent)
 		{
 		GtkWindow *window = NULL;
--- a/src/ui_utildlg.h	Fri Nov 17 16:46:18 2017 +0000
+++ b/src/ui_utildlg.h	Thu Nov 23 20:44:03 2017 +0000
@@ -99,6 +99,7 @@
 void file_dialog_clear_filter(FileDialog *fd);
 void file_dialog_sync_history(FileDialog *fd, gboolean dir_only);
 
-
+void generic_dialog_windows_load_config(const gchar **window_attributes, const gchar **attribute_values);
+void generic_dialog_windows_write_config(GString *outstr, gint indent);
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */