[Commits] [SCM] claws branch, master, updated. 3.13.2-121-g3f96e45

ticho at claws-mail.org ticho at claws-mail.org
Sat Apr 16 21:30:40 CEST 2016


The branch, master has been updated
       via  3f96e4596d7812fa51fcf93dfaf710bf9eaa715d (commit)
      from  e630ef9df0b19c3bc97b79f949fbbf3dc32d0af0 (commit)

Summary of changes:
 src/gtk/Makefile.am   |    8 +-
 src/gtk/w32_filesel.c |  363 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 370 insertions(+), 1 deletion(-)
 create mode 100644 src/gtk/w32_filesel.c


- Log -----------------------------------------------------------------
commit 3f96e4596d7812fa51fcf93dfaf710bf9eaa715d
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Sat Apr 16 18:04:31 2016 +0200

    Use native file and folder selection dialogs on Windows.
    
    This is done by compiling in src/gtk/w32_filesel.c instead of
    filesel.c on Windows. The Makefile.am logic mirrors the one from
    src/common/.

diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am
index da36309..a2bcae0 100644
--- a/src/gtk/Makefile.am
+++ b/src/gtk/Makefile.am
@@ -16,13 +16,19 @@ gtk2_sources = \
 	gtkcmoptionmenu.c
 endif
 
+if OS_WIN32
+arch_sources = w32_filesel.c
+else
+arch_sources = filesel.c
+endif
+
 libclawsgtk_la_SOURCES = \
 	about.c \
 	colorlabel.c \
 	colorsel.c \
 	combobox.c \
 	description_window.c \
-	filesel.c \
+	$(arch_sources) \
 	foldersort.c \
 	gtkaspell.c \
 	gtkcmctree.c \
diff --git a/src/gtk/w32_filesel.c b/src/gtk/w32_filesel.c
new file mode 100644
index 0000000..3b47456
--- /dev/null
+++ b/src/gtk/w32_filesel.c
@@ -0,0 +1,363 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2016 The Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <glib.h>
+#include <gdk/gdkwin32.h>
+#include <pthread.h>
+
+#include <windows.h>
+#include <shlobj.h>
+
+#include "claws.h"
+#include "manage_window.h"
+#include "utils.h"
+
+static OPENFILENAME o;
+static BROWSEINFO b;
+
+/* Since running the native dialogs in the same thread stops GTK+
+ * loop from redrawing other windows on the background, we need
+ * to run the dialogs in a separate thread. */
+
+/* TODO: There's a lot of code repeat in this file, it could be
+ * refactored to be neater. */
+
+struct _WinChooserCtx {
+	void *data;
+	gboolean return_value;
+	PIDLIST_ABSOLUTE return_value_pidl;
+	gboolean done;
+};
+
+typedef struct _WinChooserCtx WinChooserCtx;
+
+static void *threaded_GetOpenFileName(void *arg)
+{
+	WinChooserCtx *ctx = (WinChooserCtx *)arg;
+
+	g_return_val_if_fail(ctx != NULL, NULL);
+	g_return_val_if_fail(ctx->data != NULL, NULL);
+
+	ctx->return_value = GetOpenFileName(ctx->data);
+	ctx->done = TRUE;
+
+	return NULL;
+}
+
+static void *threaded_GetSaveFileName(void *arg)
+{
+	WinChooserCtx *ctx = (WinChooserCtx *)arg;
+
+	g_return_val_if_fail(ctx != NULL, NULL);
+	g_return_val_if_fail(ctx->data != NULL, NULL);
+
+	ctx->return_value = GetSaveFileName(ctx->data);
+	ctx->done = TRUE;
+
+	return NULL;
+}
+
+static void *threaded_SHBrowseForFolder(void *arg)
+{
+	WinChooserCtx *ctx = (WinChooserCtx *)arg;
+
+	g_return_val_if_fail(ctx != NULL, NULL);
+	g_return_val_if_fail(ctx->data != NULL, NULL);
+
+	ctx->return_value_pidl = SHBrowseForFolder(ctx->data);
+
+	ctx->done = TRUE;
+
+	return NULL;
+}
+
+gchar *filesel_select_file_open(const gchar *title, const gchar *path)
+{
+	gboolean ret;
+	gchar *str;
+	WinChooserCtx *ctx;
+#ifdef USE_PTHREAD
+	pthread_t pt;
+#endif
+
+	o.lStructSize = sizeof(OPENFILENAME);
+	if (focus_window != NULL)
+		o.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
+	else
+		o.hwndOwner = NULL;
+	o.hInstance = NULL;
+	o.lpstrFilter = NULL;
+	o.lpstrCustomFilter = NULL;
+	o.nFilterIndex = 0;
+	o.lpstrFile = g_malloc0(MAXPATHLEN);
+	o.nMaxFile = MAXPATHLEN;
+	o.lpstrFileTitle = NULL;
+	o.lpstrInitialDir = path;
+	o.lpstrTitle = title;
+	o.Flags = OFN_LONGNAMES;
+
+	ctx = g_new0(WinChooserCtx, 1);
+	ctx->data = &o;
+	ctx->done = FALSE;
+
+#ifdef USE_PTHREAD
+	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_GetOpenFileName,
+				(void *)ctx) != 0) {
+		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
+		threaded_GetOpenFileName(ctx);
+	} else {
+		while (!ctx->done) {
+			claws_do_idle();
+		}
+		pthread_join(pt, NULL);
+	}
+	ret = ctx->return_value;
+#else
+	debug_print("No threads available, continuing unthreaded.\n");
+	ret = GetOpenFileName(&o);
+#endif
+
+	g_free(ctx);
+
+	if (!ret) {
+		g_free(o.lpstrFile);
+		return NULL;
+	}
+
+	str = g_strndup(o.lpstrFile, strlen(o.lpstrFile));
+	g_free(o.lpstrFile);
+	return str;
+}
+
+/* TODO: Allow selecting of multiple files with OFN_ALLOWMULTISELECT
+ * flag and parsing the long string with returned file names. */
+GList *filesel_select_multiple_files_open(const gchar *title)
+{
+	GList *file_list = NULL;
+	gchar *ret = filesel_select_file_open(title, NULL);
+
+	if (ret != NULL)
+		file_list = g_list_append(file_list, ret);
+
+	return file_list;
+}
+
+gchar *filesel_select_file_open_with_filter(const gchar *title, const gchar *path,
+		              const gchar *filter)
+{
+	gboolean ret;
+	gchar *win_filter = NULL, *str;
+	WinChooserCtx *ctx;
+#ifdef USE_PTHREAD
+	pthread_t pt;
+#endif
+
+	o.lStructSize = sizeof(OPENFILENAME);
+	if (focus_window != NULL)
+		o.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
+	else
+		o.hwndOwner = NULL;
+	o.lpstrFilter = NULL;
+	o.lpstrCustomFilter = NULL;
+	o.nFilterIndex = 0;
+	o.lpstrFile = g_malloc0(MAXPATHLEN);
+	o.nMaxFile = MAXPATHLEN;
+	o.lpstrFileTitle = NULL;
+	o.lpstrInitialDir = path;
+	o.lpstrTitle = title;
+	o.Flags = OFN_LONGNAMES;
+
+	if (filter != NULL && strlen(filter) > 0) {
+		win_filter = g_strdup_printf("%s%c%s%c", filter, '\0', filter, '\0');
+		o.lpstrFilter = win_filter;
+		o.nFilterIndex = 1;
+	}
+
+	ctx = g_new0(WinChooserCtx, 1);
+	ctx->data = &o;
+	ctx->done = FALSE;
+
+#ifdef USE_PTHREAD
+	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_GetOpenFileName,
+				(void *)ctx) != 0) {
+		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
+		threaded_GetOpenFileName(ctx);
+	} else {
+		while (!ctx->done) {
+			claws_do_idle();
+		}
+		pthread_join(pt, NULL);
+	}
+	ret = ctx->return_value;
+#else
+	debug_print("No threads available, continuing unthreaded.\n");
+	ret = GetOpenFileName(&o);
+#endif
+
+	g_free(win_filter);
+	g_free(ctx);
+
+	if (!ret) {
+		g_free(o.lpstrFile);
+		return NULL;
+	}
+
+	str = g_strndup(o.lpstrFile, strlen(o.lpstrFile));
+	g_free(o.lpstrFile);
+	return str;
+}
+
+/* TODO: Allow selecting of multiple files with OFN_ALLOWMULTISELECT
+ * flag and parsing the long string with returned file names. */
+GList *filesel_select_multiple_files_open_with_filter(const gchar *title,
+		const gchar *path, const gchar *filter)
+{
+	GList *file_list = NULL;
+	gchar *ret = filesel_select_file_open_with_filter(title, path, filter);
+
+	if (ret != NULL)
+		file_list = g_list_append(file_list, ret);
+
+	return file_list;
+}
+
+gchar *filesel_select_file_save(const gchar *title, const gchar *path)
+{
+	gboolean ret;
+	gchar *str;
+	WinChooserCtx *ctx;
+#ifdef USE_PTHREAD
+	pthread_t pt;
+#endif
+
+	o.lStructSize = sizeof(OPENFILENAME);
+	if (focus_window != NULL)
+		o.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
+	else
+		o.hwndOwner = NULL;
+	o.lpstrFilter = NULL;
+	o.lpstrCustomFilter = NULL;
+	o.lpstrFile = g_malloc0(MAXPATHLEN);
+	o.nMaxFile = MAXPATHLEN;
+	o.lpstrFileTitle = NULL;
+	o.lpstrInitialDir = path;
+	o.lpstrTitle = title;
+	o.Flags = OFN_LONGNAMES;
+
+	ctx = g_new0(WinChooserCtx, 1);
+	ctx->data = &o;
+	ctx->return_value = FALSE;
+	ctx->done = FALSE;
+
+#ifdef USE_PTHREAD
+	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_GetSaveFileName,
+				(void *)ctx) != 0) {
+		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
+		threaded_GetSaveFileName(ctx);
+	} else {
+		while (!ctx->done) {
+			claws_do_idle();
+		}
+		pthread_join(pt, NULL);
+	}
+	ret = ctx->return_value;
+#else
+	debug_print("No threads available, continuing unthreaded.\n");
+	ret = GetSaveFileName(&o);
+#endif
+
+	g_free(ctx);
+
+	if (!ret) {
+		g_free(o.lpstrFile);
+		return NULL;
+	}
+
+	str = g_strndup(o.lpstrFile, strlen(o.lpstrFile));
+	g_free(o.lpstrFile);
+	return str;
+}
+
+gchar *filesel_select_file_open_folder(const gchar *title, const gchar *path)
+{
+	PIDLIST_ABSOLUTE pidl;
+	gchar *str;
+	WinChooserCtx *ctx;
+#ifdef USE_PTHREAD
+	pthread_t pt;
+#endif
+
+	if (focus_window != NULL)
+		b.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
+	else
+		b.hwndOwner = NULL;
+	b.pidlRoot = NULL; /* TODO: get a PIDLIST from path and use it. */
+	b.pszDisplayName = g_malloc(MAXPATHLEN);
+	b.lpszTitle = title;
+	b.ulFlags = 0;
+	b.lpfn = NULL;
+
+	CoInitialize(NULL);
+
+	ctx = g_new0(WinChooserCtx, 1);
+	ctx->data = &b;
+	ctx->done = FALSE;
+
+#ifdef USE_PTHREAD
+	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_SHBrowseForFolder,
+				(void *)ctx) != 0) {
+		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
+		threaded_SHBrowseForFolder(ctx);
+	} else {
+		while (!ctx->done) {
+			claws_do_idle();
+		}
+		pthread_join(pt, NULL);
+	}
+	pidl = ctx->return_value_pidl;
+#else
+	debug_print("No threads available, continuing unthreaded.\n");
+	pidl = SHBrowseForFolder(&b);
+#endif
+
+	if (pidl == NULL) {
+		CoUninitialize();
+		g_free(b.pszDisplayName);
+		g_free(ctx);
+		return NULL;
+	}
+
+	str = g_strndup(b.pszDisplayName, strlen(b.pszDisplayName));
+	g_free(b.pszDisplayName);
+
+	CoTaskMemFree(pidl);
+	CoUninitialize();
+	g_free(ctx);
+
+	return str;
+}
+
+gchar *filesel_select_file_save_folder(const gchar *title, const gchar *path)
+{
+	return filesel_select_file_open_folder(title, path);
+}

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list