[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