[evolution-data-server] Add a new WebDAV discover widget and dialog into libedataserverui
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Add a new WebDAV discover widget and dialog into libedataserverui
- Date: Mon, 23 Mar 2015 16:44:39 +0000 (UTC)
commit 9c74f22a3760083935065eea27298d8908b7495d
Author: Milan Crha <mcrha redhat com>
Date: Mon Mar 23 17:39:57 2015 +0100
Add a new WebDAV discover widget and dialog into libedataserverui
This widget, and dialog, can be used to discover WebDAV sources
and give a user a unified widget to select one, or multiple, sources
from those found.
libedataserverui/Makefile.am | 4 +
libedataserverui/e-cell-renderer-color.c | 225 ++++++
libedataserverui/e-cell-renderer-color.h | 77 ++
libedataserverui/e-webdav-discover-widget.c | 1134 +++++++++++++++++++++++++++
libedataserverui/e-webdav-discover-widget.h | 81 ++
libedataserverui/libedataserverui.h | 2 +
po/POTFILES.in | 1 +
7 files changed, 1524 insertions(+), 0 deletions(-)
---
diff --git a/libedataserverui/Makefile.am b/libedataserverui/Makefile.am
index cf625b3..51578fd 100644
--- a/libedataserverui/Makefile.am
+++ b/libedataserverui/Makefile.am
@@ -41,18 +41,22 @@ libedataserveruiincludedir = $(privincludedir)/libedataserverui
libedataserveruiinclude_HEADERS = \
libedataserverui.h \
+ e-cell-renderer-color.h \
e-credentials-prompter.h \
e-credentials-prompter-impl.h \
e-credentials-prompter-impl-password.h \
e-trust-prompt.h \
+ e-webdav-discover-widget.h \
$(NULL)
libedataserverui_1_2_la_SOURCES = \
$(BUILT_SOURCES) \
+ e-cell-renderer-color.c \
e-credentials-prompter.c \
e-credentials-prompter-impl.c \
e-credentials-prompter-impl-password.c \
e-trust-prompt.c \
+ e-webdav-discover-widget.c \
$(NULL)
%-$(API_VERSION).pc: %.pc
diff --git a/libedataserverui/e-cell-renderer-color.c b/libedataserverui/e-cell-renderer-color.c
new file mode 100644
index 0000000..761afa5
--- /dev/null
+++ b/libedataserverui/e-cell-renderer-color.c
@@ -0,0 +1,225 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-cell-renderer-color.c
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-cell-renderer-color.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#define E_CELL_RENDERER_COLOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColorPrivate))
+
+enum {
+ PROP_0,
+ PROP_RGBA
+};
+
+struct _ECellRendererColorPrivate {
+ GdkRGBA rgba;
+};
+
+G_DEFINE_TYPE (
+ ECellRendererColor,
+ e_cell_renderer_color,
+ GTK_TYPE_CELL_RENDERER)
+
+static void
+cell_renderer_color_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ const GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height)
+{
+ gint color_width = 16;
+ gint color_height = 16;
+ gint calc_width;
+ gint calc_height;
+ gfloat xalign;
+ gfloat yalign;
+ guint xpad;
+ guint ypad;
+
+ g_object_get (
+ cell, "xalign", &xalign, "yalign", &yalign,
+ "xpad", &xpad, "ypad", &ypad, NULL);
+
+ calc_width = (gint) xpad * 2 + color_width;
+ calc_height = (gint) ypad * 2 + color_height;
+
+ if (cell_area && color_width > 0 && color_height > 0) {
+ if (x_offset) {
+ *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
+ (1.0 - xalign) : xalign) *
+ (cell_area->width - calc_width));
+ *x_offset = MAX (*x_offset, 0);
+ }
+
+ if (y_offset) {
+ *y_offset =(yalign *
+ (cell_area->height - calc_height));
+ *y_offset = MAX (*y_offset, 0);
+ }
+ } else {
+ if (x_offset) *x_offset = 0;
+ if (y_offset) *y_offset = 0;
+ }
+
+ if (width)
+ *width = calc_width;
+
+ if (height)
+ *height = calc_height;
+}
+
+static void
+cell_renderer_color_render (GtkCellRenderer *cell,
+ cairo_t *cr,
+ GtkWidget *widget,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ ECellRendererColorPrivate *priv;
+ GdkRectangle pix_rect;
+ GdkRectangle draw_rect;
+ guint xpad;
+ guint ypad;
+
+ priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (cell);
+
+ cell_renderer_color_get_size (
+ cell, widget, cell_area,
+ &pix_rect.x, &pix_rect.y,
+ &pix_rect.width, &pix_rect.height);
+
+ g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL);
+
+ pix_rect.x += cell_area->x + xpad;
+ pix_rect.y += cell_area->y + ypad;
+ pix_rect.width -= xpad * 2;
+ pix_rect.height -= ypad * 2;
+
+ if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
+ return;
+
+ gdk_cairo_set_source_rgba (cr, &priv->rgba);
+ cairo_rectangle (cr, pix_rect.x, pix_rect.y, draw_rect.width, draw_rect.height);
+
+ cairo_fill (cr);
+}
+
+static void
+cell_renderer_color_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ECellRendererColorPrivate *priv;
+ GdkRGBA *rgba;
+
+ priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (object);
+
+ switch (property_id) {
+ case PROP_RGBA:
+ rgba = g_value_dup_boxed (value);
+ if (rgba) {
+ priv->rgba = *rgba;
+ gdk_rgba_free (rgba);
+ } else {
+ priv->rgba.red = 0.0;
+ priv->rgba.green = 0.0;
+ priv->rgba.blue = 0.0;
+ priv->rgba.alpha = 0.0;
+ }
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+cell_renderer_color_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ECellRendererColorPrivate *priv;
+
+ priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (object);
+
+ switch (property_id) {
+ case PROP_RGBA:
+ g_value_set_boxed (value, &priv->rgba);
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_cell_renderer_color_class_init (ECellRendererColorClass *class)
+{
+ GObjectClass *object_class;
+ GtkCellRendererClass *cell_class;
+
+ g_type_class_add_private (class, sizeof (ECellRendererColorPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = cell_renderer_color_set_property;
+ object_class->get_property = cell_renderer_color_get_property;
+
+ cell_class = GTK_CELL_RENDERER_CLASS (class);
+ cell_class->get_size = cell_renderer_color_get_size;
+ cell_class->render = cell_renderer_color_render;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_RGBA,
+ g_param_spec_boxed (
+ "rgba",
+ "Color Info",
+ "The GdkRGBA color to render",
+ GDK_TYPE_RGBA,
+ G_PARAM_READWRITE));
+}
+
+static void
+e_cell_renderer_color_init (ECellRendererColor *cellcolor)
+{
+ cellcolor->priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (cellcolor);
+
+ g_object_set (cellcolor, "xpad", 4, NULL);
+}
+
+/**
+ * e_cell_renderer_color_new:
+ *
+ * Since: 2.22
+ **/
+GtkCellRenderer *
+e_cell_renderer_color_new (void)
+{
+ return g_object_new (E_TYPE_CELL_RENDERER_COLOR, NULL);
+}
diff --git a/libedataserverui/e-cell-renderer-color.h b/libedataserverui/e-cell-renderer-color.h
new file mode 100644
index 0000000..705bb76
--- /dev/null
+++ b/libedataserverui/e-cell-renderer-color.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-cell-renderer-color.h
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
+#error "Only <libedataserverui/libedataserverui.h> should be included directly."
+#endif
+
+#ifndef E_CELL_RENDERER_COLOR_H
+#define E_CELL_RENDERER_COLOR_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_CELL_RENDERER_COLOR \
+ (e_cell_renderer_color_get_type ())
+#define E_CELL_RENDERER_COLOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColor))
+#define E_CELL_RENDERER_COLOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColorClass))
+#define E_IS_CELL_RENDERER_COLOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CELL_RENDERER_COLOR))
+#define E_IS_CELL_RENDERER_COLOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE ((cls), E_TYPE_CELL_RENDERER_COLOR))
+#define E_CELL_RENDERER_COLOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ECellRendererColor ECellRendererColor;
+typedef struct _ECellRendererColorClass ECellRendererColorClass;
+typedef struct _ECellRendererColorPrivate ECellRendererColorPrivate;
+
+/**
+ * ECellRendererColor:
+ *
+ * Since: 2.22
+ **/
+struct _ECellRendererColor {
+ GtkCellRenderer parent;
+ ECellRendererColorPrivate *priv;
+};
+
+struct _ECellRendererColorClass {
+ GtkCellRendererClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+GType e_cell_renderer_color_get_type (void) G_GNUC_CONST;
+GtkCellRenderer *e_cell_renderer_color_new (void);
+
+G_END_DECLS
+
+#endif /* E_CELL_RENDERER_COLOR_H */
diff --git a/libedataserverui/e-webdav-discover-widget.c b/libedataserverui/e-webdav-discover-widget.c
new file mode 100644
index 0000000..69801b2
--- /dev/null
+++ b/libedataserverui/e-webdav-discover-widget.c
@@ -0,0 +1,1134 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtk.h>
+
+#include <libedataserver/libedataserver.h>
+
+#include "e-cell-renderer-color.h"
+#include "e-trust-prompt.h"
+#include "e-webdav-discover-widget.h"
+
+#define WEBDAV_DISCOVER_CONTENT_KEY "e-webdav-discover-content-widget-key"
+#define WEBDAV_DISCOVER_CONTENT_ENTRY_KEY "e-webdav-discover-content-widget-entry-key"
+#define WEBDAV_DISCOVER_CONTENT_DATA_KEY "e-webdav-discover-content-widget-data-key"
+
+enum {
+ COL_HREF_STRING = 0,
+ COL_SUPPORTS_UINT,
+ COL_DISPLAY_NAME_STRING,
+ COL_COLOR_STRING,
+ COL_DESCRIPTION_STRING,
+ COL_SUPPORTS_STRING,
+ COL_COLOR_GDKRGBA,
+ COL_SHOW_COLOR_BOOLEAN,
+ N_COLUMNS
+};
+
+typedef struct _EWebDAVDiscoverContentData {
+ ECredentialsPrompter *credentials_prompter;
+ ESource *source;
+ gchar *base_url;
+ guint supports_filter;
+
+ GtkTreeView *sources_tree_view; /* not referenced */
+ GtkComboBox *email_addresses_combo; /* not referenced */
+ GtkInfoBar *info_bar; /* not referenced */
+} EWebDAVDiscoverContentData;
+
+static void
+e_webdav_discover_content_data_free (gpointer ptr)
+{
+ EWebDAVDiscoverContentData *data = ptr;
+
+ if (data) {
+ g_clear_object (&data->credentials_prompter);
+ g_clear_object (&data->source);
+ g_free (data->base_url);
+ g_free (data);
+ }
+}
+
+/**
+ * e_webdav_discover_content_new:
+ * @credentials_prompter: an #ECredentialsPrompter to use to ask for credentials
+ * @source: (allow none): optional #ESource to use for authentication, or %NULL
+ * @base_url: (allow-none): optional base URL to use for discovery, or %NULL
+ * @supports_filter: a bit-or of #EWebDAVDiscoverSupports, a filter to limit what source
+ * types will be shown in the dialog content; use %E_WEBDAV_DISCOVER_SUPPORTS_NONE
+ * to show all
+ *
+ * Creates a new WebDAV discovery content, which is a #GtkGrid containing necessary
+ * widgets to provide a UI interface for a user to search and select for available
+ * WebDAV (CalDAV or CardDAV) sources provided by the given server. Do not pack
+ * anything into this content, its content can be changed dynamically.
+ *
+ * Returns: (transfer full): a new WebDAV discovery content widget.
+ *
+ * Since: 3.18
+ **/
+GtkWidget *
+e_webdav_discover_content_new (ECredentialsPrompter *credentials_prompter,
+ ESource *source,
+ const gchar *base_url,
+ guint supports_filter)
+{
+ EWebDAVDiscoverContentData *data;
+ GtkWidget *content, *scrolled_window, *tree_view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkListStore *list_store;
+ GtkGrid *grid;
+
+ g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER (credentials_prompter), NULL);
+ g_return_val_if_fail (base_url != NULL, NULL);
+
+ data = g_new0 (EWebDAVDiscoverContentData, 1);
+ data->credentials_prompter = g_object_ref (credentials_prompter);
+ data->source = source ? g_object_ref (source) : NULL;
+ data->base_url = g_strdup (base_url);
+ data->supports_filter = supports_filter;
+
+ content = gtk_grid_new ();
+ grid = GTK_GRID (content);
+ gtk_container_set_border_width (GTK_CONTAINER (grid), 4);
+ gtk_grid_set_row_spacing (grid, 4);
+ gtk_grid_set_column_spacing (grid, 4);
+
+ g_object_set_data_full (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY, data,
e_webdav_discover_content_data_free);
+
+ list_store = gtk_list_store_new (N_COLUMNS,
+ G_TYPE_STRING, /* COL_HREF_STRING */
+ G_TYPE_UINT, /* COL_SUPPORTS_UINT */
+ G_TYPE_STRING, /* COL_DISPLAY_NAME_STRING */
+ G_TYPE_STRING, /* COL_COLOR_STRING */
+ G_TYPE_STRING, /* COL_DESCRIPTION_STRING */
+ G_TYPE_STRING, /* COL_SUPPORTS_STRING */
+ GDK_TYPE_RGBA, /* COL_COLOR_GDKRGBA */
+ G_TYPE_BOOLEAN); /* COL_SHOW_COLOR_BOOLEAN */
+
+ tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
+ g_object_unref (list_store);
+
+ g_object_set (G_OBJECT (tree_view),
+ "hexpand", TRUE,
+ "vexpand", TRUE,
+ "halign", GTK_ALIGN_FILL,
+ "valign", GTK_ALIGN_FILL,
+ NULL);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
+ gtk_grid_attach (grid, scrolled_window, 0, 0, 1, 1);
+
+ data->sources_tree_view = GTK_TREE_VIEW (tree_view);
+
+ renderer = e_cell_renderer_color_new ();
+ g_object_set (G_OBJECT (renderer), "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
+
+ column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "rgba", COL_COLOR_GDKRGBA,
"visible", COL_SHOW_COLOR_BOOLEAN, NULL);
+ gtk_tree_view_append_column (data->sources_tree_view, column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer, "markup", COL_DESCRIPTION_STRING);
+ g_object_set (G_OBJECT (renderer),
+ "max-width-chars", 60,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR,
+ "wrap-width", 640,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Supports"), renderer, "text",
COL_SUPPORTS_STRING, NULL);
+ gtk_tree_view_append_column (data->sources_tree_view, column);
+
+ if (!supports_filter || (supports_filter & (E_WEBDAV_DISCOVER_SUPPORTS_EVENTS |
+ E_WEBDAV_DISCOVER_SUPPORTS_MEMOS | E_WEBDAV_DISCOVER_SUPPORTS_TASKS)) != 0) {
+ GtkWidget *widget, *box;
+
+ widget = gtk_combo_box_text_new ();
+ data->email_addresses_combo = GTK_COMBO_BOX (widget);
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+ widget = gtk_label_new_with_mnemonic (_("_User mail:"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (data->email_addresses_combo));
+
+ gtk_container_add (GTK_CONTAINER (box), widget);
+ gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (data->email_addresses_combo));
+
+ g_object_set (G_OBJECT (widget),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ g_object_set (G_OBJECT (data->email_addresses_combo),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ "halign", GTK_ALIGN_FILL,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ g_object_set (G_OBJECT (box),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ "halign", GTK_ALIGN_FILL,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ gtk_grid_attach (grid, box, 0, 1, 1, 1);
+ }
+
+ gtk_widget_show_all (content);
+
+ return content;
+}
+
+/**
+ * e_webdav_discover_content_get_tree_selection:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ *
+ * Returns inner #GtkTreeViewSelection. This is meant to be able to connect
+ * to its "changed" signal and update other parts of the parent widgets accordingly.
+ *
+ * Returns: (transfer none): inner #GtkTreeViewSelection
+ *
+ * Since: 3.18
+ **/
+GtkTreeSelection *
+e_webdav_discover_content_get_tree_selection (GtkWidget *content)
+{
+ EWebDAVDiscoverContentData *data;
+
+ g_return_val_if_fail (GTK_IS_GRID (content), NULL);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ return gtk_tree_view_get_selection (data->sources_tree_view);
+}
+
+/**
+ * e_webdav_discover_content_set_multiselect:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ * @multiselect: whether multiselect is allowed
+ *
+ * Sets whether the WebDAV discovery content allows multiselect.
+ *
+ * Since: 3.18
+ **/
+void
+e_webdav_discover_content_set_multiselect (GtkWidget *content,
+ gboolean multiselect)
+{
+ EWebDAVDiscoverContentData *data;
+ GtkTreeSelection *selection;
+
+ g_return_if_fail (GTK_IS_GRID (content));
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ selection = gtk_tree_view_get_selection (data->sources_tree_view);
+ gtk_tree_selection_set_mode (selection, multiselect ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
+}
+
+/**
+ * e_webdav_discover_content_get_multiselect:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ *
+ * Returns: whether multiselect is allowed for the @content.
+ *
+ * Since: 3.18
+ **/
+gboolean
+e_webdav_discover_content_get_multiselect (GtkWidget *content)
+{
+ EWebDAVDiscoverContentData *data;
+ GtkTreeSelection *selection;
+
+ g_return_val_if_fail (GTK_IS_GRID (content), FALSE);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ selection = gtk_tree_view_get_selection (data->sources_tree_view);
+ return gtk_tree_selection_get_mode (selection) == GTK_SELECTION_MULTIPLE;
+}
+
+/**
+ * e_webdav_discover_content_set_base_url:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ *
+ * Sets base URL for the @content. This is used to overwrite the one set on
+ * the #ESource from the creation time. The URL can be either a full URL, a path
+ * or even a %NULL.
+ *
+ * Since: 3.18
+ **/
+void
+e_webdav_discover_content_set_base_url (GtkWidget *content,
+ const gchar *base_url)
+{
+ EWebDAVDiscoverContentData *data;
+
+ g_return_if_fail (GTK_IS_GRID (content));
+ g_return_if_fail (base_url != NULL);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ if (g_strcmp0 (base_url, data->base_url) != 0) {
+ g_free (data->base_url);
+ data->base_url = g_strdup (base_url);
+ }
+}
+
+/**
+ * e_webdav_discover_content_get_base_url:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ *
+ * Returns currently set base URL for the @content. This is used to overwrite the one
+ * set on the #ESource from the creation time. The URL can be either a full URL, a path
+ * or even a %NULL.
+ *
+ * Returns: currently set base URL for the @content.
+ *
+ * Since: 3.18
+ **/
+const gchar *
+e_webdav_discover_content_get_base_url (GtkWidget *content)
+{
+ EWebDAVDiscoverContentData *data;
+
+ g_return_val_if_fail (GTK_IS_GRID (content), NULL);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ return data->base_url;
+}
+
+/**
+ * e_webdav_discover_content_get_base_url:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ * @index: an index of the selected source; counts from 0
+ * @out_href: (out): an output location for the URL of the selected source
+ * @out_supports: (out): an output location of a bit-or of #EWebDAVDiscoverSupports, the set
+ * of source types this server source location supports
+ * @out_display_name: (out): an output location of the sources display name
+ * @out_color: (out): an output location of the string representation of the color
+ * for the source, as set on the server
+ *
+ * Returns information about selected source at index @index. The function can be called
+ * multiple times, with the index starting at zero and as long as it doesn't return %FALSE.
+ * If the @content doesn't have allowed multiselection, then the only valid @index is 0.
+ *
+ * All the @out_href, @out_display_name and @out_color are newly allocated strings, which should
+ * be freed with g_free(), when no longer needed.
+ *
+ * Returns: %TRUE, when a selected source of index @index exists, %FALSE otherwise.
+ *
+ * Since: 3.18
+ **/
+gboolean
+e_webdav_discover_content_get_selected (GtkWidget *content,
+ gint index,
+ gchar **out_href,
+ guint *out_supports,
+ gchar **out_display_name,
+ gchar **out_color)
+{
+ EWebDAVDiscoverContentData *data;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model = NULL;
+ GList *selected_rows, *link;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (GTK_IS_GRID (content), FALSE);
+ g_return_val_if_fail (index >= 0, FALSE);
+ g_return_val_if_fail (out_href != NULL, FALSE);
+ g_return_val_if_fail (out_supports != NULL, FALSE);
+ g_return_val_if_fail (out_display_name != NULL, FALSE);
+ g_return_val_if_fail (out_color != NULL, FALSE);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ selection = gtk_tree_view_get_selection (data->sources_tree_view);
+ selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+ for (link = selected_rows; link && index > 0; link = g_list_next (link)) {
+ index--;
+ }
+
+ if (index == 0 && link) {
+ GtkTreePath *path = link->data;
+
+ if (path) {
+ GtkTreeIter iter;
+
+ success = gtk_tree_model_get_iter (model, &iter, path);
+ if (success) {
+ gtk_tree_model_get (model, &iter,
+ COL_HREF_STRING, out_href,
+ COL_SUPPORTS_UINT, out_supports,
+ COL_DISPLAY_NAME_STRING, out_display_name,
+ COL_COLOR_STRING, out_color,
+ -1);
+ }
+ }
+ }
+
+ g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
+
+ return success;
+}
+
+/**
+ * e_webdav_discover_content_get_user_address:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ *
+ * Get currently selected user address in the @content, if the server returned any.
+ * This value has meaning only with calendar sources.
+ *
+ * Returns: (transfer full): currently selected user address. The returned string
+ * is newly allocated and should be freed with g_free() when no longer needed.
+ * If there are none addresses provided by the server, or no calendar sources
+ * were found, then %NULL is returned instead.
+ *
+ * Since: 3.18
+ **/
+gchar *
+e_webdav_discover_content_get_user_address (GtkWidget *content)
+{
+ EWebDAVDiscoverContentData *data;
+ gchar *active_text;
+
+ g_return_val_if_fail (GTK_IS_GRID (content), NULL);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ if (!data->email_addresses_combo)
+ return NULL;
+
+ active_text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (data->email_addresses_combo));
+ if (active_text && !*active_text) {
+ g_free (active_text);
+ active_text = NULL;
+ }
+
+ return active_text;
+}
+
+static void
+e_webdav_discover_content_fill_discovered_sources (GtkTreeView *tree_view,
+ guint supports_filter,
+ GSList *discovered_sources)
+{
+ GtkListStore *list_store;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GSList *link;
+
+ /* It's okay to pass NULL here */
+ if (!tree_view)
+ return;
+
+ g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+ model = gtk_tree_view_get_model (tree_view);
+ list_store = GTK_LIST_STORE (model);
+ gtk_list_store_clear (list_store);
+
+ for (link = discovered_sources; link; link = g_slist_next (link)) {
+ const EWebDAVDiscoveredSource *source = link->data;
+ guint supports_bits;
+ GString *supports;
+ gchar *description_markup, *colorstr = NULL;
+ gboolean show_color = FALSE;
+ GdkRGBA rgba;
+
+ if (!source || (supports_filter && (source->supports & supports_filter) == 0) ||
!source->display_name)
+ continue;
+
+ if (source->color && *source->color) {
+ gint rr, gg, bb;
+
+ if (gdk_rgba_parse (&rgba, source->color)) {
+ show_color = TRUE;
+ } else if (sscanf (source->color, "#%02x%02x%02x", &rr, &gg, &bb) == 3) {
+ rgba.red = ((gdouble) rr) / 255.0;
+ rgba.green = ((gdouble) gg) / 255.0;
+ rgba.blue = ((gdouble) bb) / 255.0;
+ rgba.alpha = 1.0;
+
+ show_color = TRUE;
+ }
+
+ if (show_color) {
+ rr = 0xFF * rgba.red;
+ gg = 0xFF * rgba.green;
+ bb = 0xFF * rgba.blue;
+
+ colorstr = g_strdup_printf ("#%02x%02x%02x", rr & 0xFF, gg & 0xFF, bb & 0xFF);
+ }
+ }
+
+ if (source->description && *source->description) {
+ description_markup = g_markup_printf_escaped ("<b>%s</b>\n<small>%s</small>",
+ source->display_name, source->description);
+ } else {
+ description_markup = g_markup_printf_escaped ("<b>%s</b>",
+ source->display_name);
+ }
+
+ supports_bits = supports_filter ? (source->supports & supports_filter) : source->supports;
+ supports = g_string_new ("");
+
+ #define addbit(flg, cpt) { \
+ if (((flg) & supports_bits) != 0) { \
+ if (supports->len) \
+ g_string_append (supports, ", "); \
+ g_string_append (supports, cpt); \
+ } \
+ }
+
+ addbit (E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS, C_("WebDAVDiscover", "Contacts"));
+ addbit (E_WEBDAV_DISCOVER_SUPPORTS_EVENTS, C_("WebDAVDiscover", "Events"));
+ addbit (E_WEBDAV_DISCOVER_SUPPORTS_MEMOS, C_("WebDAVDiscover", "Memos"));
+ addbit (E_WEBDAV_DISCOVER_SUPPORTS_TASKS, C_("WebDAVDiscover", "Tasks"));
+
+ #undef addbit
+
+ gtk_list_store_append (list_store, &iter);
+ gtk_list_store_set (list_store, &iter,
+ COL_HREF_STRING, source->href,
+ COL_SUPPORTS_UINT, source->supports,
+ COL_DISPLAY_NAME_STRING, source->display_name,
+ COL_COLOR_STRING, colorstr,
+ COL_DESCRIPTION_STRING, description_markup,
+ COL_SUPPORTS_STRING, supports->str,
+ COL_COLOR_GDKRGBA, show_color ? &rgba : NULL,
+ COL_SHOW_COLOR_BOOLEAN, show_color,
+ -1);
+
+ g_free (description_markup);
+ g_free (colorstr);
+ g_string_free (supports, TRUE);
+ }
+}
+
+static void
+e_webdav_discover_content_fill_calendar_emails (GtkComboBox *combo_box,
+ GSList *calendar_user_addresses)
+{
+ GtkComboBoxText *text_combo;
+ gboolean any_added = FALSE;
+ GSList *link;
+
+ /* It's okay to pass NULL here */
+ if (!combo_box)
+ return;
+
+ g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo_box));
+
+ text_combo = GTK_COMBO_BOX_TEXT (combo_box);
+
+ gtk_combo_box_text_remove_all (text_combo);
+
+ for (link = calendar_user_addresses; link; link = g_slist_next (link)) {
+ const gchar *address = link->data;
+
+ if (address && *address) {
+ gtk_combo_box_text_append_text (text_combo, address);
+ any_added = TRUE;
+ }
+ }
+
+ if (any_added)
+ gtk_combo_box_set_active (combo_box, 0);
+}
+
+typedef struct _RefreshData {
+ GtkWidget *content;
+ GCancellable *cancellable;
+ GSimpleAsyncResult *simple;
+ gchar *base_url;
+ ENamedParameters *credentials;
+} RefreshData;
+
+static void
+refresh_data_free (gpointer ptr)
+{
+ RefreshData *rd = ptr;
+
+ if (rd) {
+ if (rd->content) {
+ EWebDAVDiscoverContentData *data;
+
+ data = g_object_get_data (G_OBJECT (rd->content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+
+ if (data) {
+ if (data->info_bar && gtk_info_bar_get_message_type (data->info_bar) ==
GTK_MESSAGE_INFO) {
+ gtk_widget_destroy (GTK_WIDGET (data->info_bar));
+ data->info_bar = NULL;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (data->sources_tree_view), TRUE);
+ if (data->email_addresses_combo)
+ gtk_widget_set_sensitive (GTK_WIDGET (data->email_addresses_combo),
TRUE);
+ }
+ }
+
+ g_clear_object (&rd->content);
+ g_clear_object (&rd->cancellable);
+ g_clear_object (&rd->simple);
+ g_free (rd->base_url);
+ e_named_parameters_free (rd->credentials);
+ g_free (rd);
+ }
+}
+
+static void
+e_webdav_discover_content_refresh_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void
+e_webdav_discover_content_trust_prompt_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+ ESource *source;
+ RefreshData *rd = user_data;
+ GError *local_error = NULL;
+
+ g_return_if_fail (E_IS_SOURCE (source_object));
+ g_return_if_fail (rd != NULL);
+
+ source = E_SOURCE (source_object);
+ if (!e_trust_prompt_run_for_source_finish (source, result, &response, &local_error)) {
+ g_simple_async_result_take_error (rd->simple, local_error);
+ local_error = NULL;
+ g_simple_async_result_complete (rd->simple);
+ refresh_data_free (rd);
+ } else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT || response ==
E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+ /* Use NULL credentials to reuse those from the last time. */
+ e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE,
rd->credentials, rd->cancellable,
+ e_webdav_discover_content_refresh_done_cb, rd);
+ } else {
+ g_cancellable_cancel (rd->cancellable);
+ g_cancellable_set_error_if_cancelled (rd->cancellable, &local_error);
+ g_simple_async_result_take_error (rd->simple, local_error);
+ local_error = NULL;
+ g_simple_async_result_complete (rd->simple);
+ refresh_data_free (rd);
+ }
+
+ g_clear_error (&local_error);
+}
+
+static void
+e_webdav_discover_content_credentials_prompt_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ RefreshData *rd = user_data;
+ ENamedParameters *credentials = NULL;
+ ESource *source = NULL;
+ GError *local_error = NULL;
+
+ g_return_if_fail (rd != NULL);
+ g_return_if_fail (E_IS_CREDENTIALS_PROMPTER (source_object));
+
+ if (!e_credentials_prompter_prompt_finish (E_CREDENTIALS_PROMPTER (source_object), result,
+ &source, &credentials, &local_error)) {
+ g_simple_async_result_take_error (rd->simple, local_error);
+ local_error = NULL;
+ g_simple_async_result_complete (rd->simple);
+ refresh_data_free (rd);
+ } else {
+ e_named_parameters_free (rd->credentials);
+ rd->credentials = credentials;
+ credentials = NULL;
+
+ e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE,
rd->credentials, rd->cancellable,
+ e_webdav_discover_content_refresh_done_cb, rd);
+ }
+
+ e_named_parameters_free (credentials);
+ g_clear_object (&source);
+ g_clear_error (&local_error);
+}
+
+static void
+e_webdav_discover_content_refresh_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ RefreshData *rd = user_data;
+ ESource *source;
+ gchar *certificate_pem = NULL;
+ GTlsCertificateFlags certificate_errors = 0;
+ GSList *discovered_sources = NULL;
+ GSList *calendar_user_addresses = NULL;
+ GError *local_error = NULL;
+
+ g_return_if_fail (E_IS_SOURCE (source_object));
+ g_return_if_fail (rd != NULL);
+
+ source = E_SOURCE (source_object);
+
+ if (!e_webdav_discover_sources_finish (source, result,
+ &certificate_pem, &certificate_errors, &discovered_sources,
+ &calendar_user_addresses, &local_error)) {
+ if (!g_cancellable_is_cancelled (rd->cancellable) && certificate_pem &&
+ g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ GtkWindow *parent;
+ GtkWidget *widget;
+
+ widget = gtk_widget_get_toplevel (rd->content);
+ parent = widget ? GTK_WINDOW (widget) : NULL;
+
+ e_trust_prompt_run_for_source (parent, source, certificate_pem, certificate_errors,
+ NULL, FALSE, rd->cancellable, e_webdav_discover_content_trust_prompt_done_cb,
rd);
+ rd = NULL;
+ } else if (g_cancellable_is_cancelled (rd->cancellable) ||
+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) {
+ g_simple_async_result_take_error (rd->simple, local_error);
+ local_error = NULL;
+ g_simple_async_result_complete (rd->simple);
+ } else {
+ EWebDAVDiscoverContentData *data;
+
+ data = g_object_get_data (G_OBJECT (rd->content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ e_credentials_prompter_prompt (data->credentials_prompter, source,
+ local_error ? local_error->message : NULL,
+ rd->credentials ? E_CREDENTIALS_PROMPTER_PROMPT_FLAG_NONE:
+ E_CREDENTIALS_PROMPTER_PROMPT_FLAG_ALLOW_STORED_CREDENTIALS,
+ e_webdav_discover_content_credentials_prompt_done_cb, rd);
+ rd = NULL;
+ }
+ } else {
+ EWebDAVDiscoverContentData *data;
+
+ data = g_object_get_data (G_OBJECT (rd->content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_warn_if_fail (data != NULL);
+
+ if (data) {
+ e_webdav_discover_content_fill_discovered_sources (data->sources_tree_view,
+ data->supports_filter, discovered_sources);
+ e_webdav_discover_content_fill_calendar_emails (data->email_addresses_combo,
+ calendar_user_addresses);
+ }
+
+ g_simple_async_result_set_op_res_gboolean (rd->simple, TRUE);
+ g_simple_async_result_complete (rd->simple);
+ }
+
+ g_free (certificate_pem);
+ e_webdav_discover_free_discovered_sources (discovered_sources);
+ g_slist_free_full (calendar_user_addresses, g_free);
+ refresh_data_free (rd);
+ g_clear_error (&local_error);
+}
+
+static void
+e_webdav_discover_info_bar_response_cb (GtkInfoBar *info_bar,
+ gint response_id,
+ RefreshData *rd)
+{
+ if (response_id == GTK_RESPONSE_CANCEL) {
+ g_return_if_fail (rd != NULL);
+ g_return_if_fail (rd->cancellable != NULL);
+
+ g_cancellable_cancel (rd->cancellable);
+ }
+}
+
+/**
+ * e_webdav_discover_content_refresh:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ * @display_name: (allow none): optional display name to use for scratch sources
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the request
+ * is satisfied
+ * @user_data: (closure): data to pass to the callback function
+ *
+ * Asynchronously starts refresh of the @content. This means to access the server
+ * and search it for available sources. The @content shows a feedback and a Cancel
+ * button during the operation.
+ *
+ * The @display_name is used only if the @content wasn't created with an #ESource and
+ * it's shown in the password prompts, if there are required any.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_webdav_discover_content_refresh_finish() to get the result of the operation.
+ *
+ * Since: 3.18
+ **/
+void
+e_webdav_discover_content_refresh (GtkWidget *content,
+ const gchar *display_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ EWebDAVDiscoverContentData *data;
+ RefreshData *rd;
+ ESource *source;
+ SoupURI *soup_uri;
+ GtkWidget *label;
+
+ g_return_if_fail (GTK_IS_GRID (content));
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (data->base_url != NULL);
+
+ soup_uri = soup_uri_new (data->base_url);
+ if (!soup_uri) {
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data,
e_webdav_discover_content_refresh);
+ g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid URL"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ return;
+ }
+
+ if (!soup_uri_get_user (soup_uri)) {
+ GSimpleAsyncResult *simple;
+
+ soup_uri_free (soup_uri);
+
+ simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data,
e_webdav_discover_content_refresh);
+ g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("User name not filled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ return;
+ }
+
+ rd = g_new0 (RefreshData, 1);
+ rd->content = g_object_ref (content);
+ rd->cancellable = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
+ rd->simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data,
e_webdav_discover_content_refresh);
+ rd->base_url = g_strdup (data->base_url);
+ rd->credentials = NULL;
+
+ if (data->source) {
+ source = g_object_ref (data->source);
+ } else {
+ ESourceWebdav *webdav_extension;
+ ESourceAuthentication *auth_extension;
+
+ source = e_source_new_with_uid (data->base_url, NULL, NULL);
+ g_return_if_fail (source != NULL);
+
+ webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ if (display_name && *display_name)
+ e_source_set_display_name (source, display_name);
+ e_source_webdav_set_soup_uri (webdav_extension, soup_uri);
+ e_source_authentication_set_host (auth_extension, soup_uri_get_host (soup_uri));
+ e_source_authentication_set_port (auth_extension, soup_uri_get_port (soup_uri));
+ e_source_authentication_set_user (auth_extension, soup_uri_get_user (soup_uri));
+ }
+
+ gtk_list_store_clear (GTK_LIST_STORE (gtk_tree_view_get_model (data->sources_tree_view)));
+ if (data->email_addresses_combo)
+ gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT (data->email_addresses_combo));
+
+ if (data->info_bar)
+ gtk_widget_destroy (GTK_WIDGET (data->info_bar));
+
+ data->info_bar = GTK_INFO_BAR (gtk_info_bar_new_with_buttons (_("Cancel"), GTK_RESPONSE_CANCEL,
NULL));
+ gtk_info_bar_set_message_type (data->info_bar, GTK_MESSAGE_INFO);
+ gtk_info_bar_set_show_close_button (data->info_bar, FALSE);
+ label = gtk_label_new (_("Searching server sources..."));
+ gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (data->info_bar)), label);
+ gtk_widget_show (label);
+ gtk_widget_show (GTK_WIDGET (data->info_bar));
+
+ g_signal_connect (data->info_bar, "response", G_CALLBACK (e_webdav_discover_info_bar_response_cb),
rd);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (data->sources_tree_view), FALSE);
+ if (data->email_addresses_combo)
+ gtk_widget_set_sensitive (GTK_WIDGET (data->email_addresses_combo), FALSE);
+
+ gtk_grid_attach (GTK_GRID (content), GTK_WIDGET (data->info_bar), 0, 2, 1, 1);
+
+ e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, rd->credentials,
rd->cancellable,
+ e_webdav_discover_content_refresh_done_cb, rd);
+
+ g_object_unref (source);
+ soup_uri_free (soup_uri);
+}
+
+/**
+ * e_webdav_discover_content_refresh_finish:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ * @result: a #GAsyncResult
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_webdav_discover_content_refresh(). If an
+ * error occurred, the function will set @error and return %FALSE. There is
+ * available e_webdav_discover_content_show_error() for convenience, which
+ * shows the error within @content and takes care of it when refreshing
+ * the content.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.18
+ **/
+gboolean
+e_webdav_discover_content_refresh_finish (GtkWidget *content,
+ GAsyncResult *result,
+ GError **error)
+{
+ EWebDAVDiscoverContentData *data;
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (GTK_IS_GRID (content), FALSE);
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (
+ result, G_OBJECT (content), e_webdav_discover_content_refresh), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+static void
+e_webdav_discover_info_bar_error_response_cb (GtkInfoBar *info_bar,
+ gint response_id,
+ GtkWidget *content)
+{
+ EWebDAVDiscoverContentData *data;
+
+ g_return_if_fail (GTK_IS_GRID (content));
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ if (data->info_bar == info_bar) {
+ gtk_widget_destroy (GTK_WIDGET (data->info_bar));
+ data->info_bar = NULL;
+ }
+}
+
+/**
+ * e_webdav_discover_content_show_error:
+ * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
+ * @error: (allow none): a #GError to show in the UI, or %NULL
+ *
+ * Shows the @error within @content, unless it's a #G_IO_ERROR_CANCELLED, or %NULL,
+ * which are safely ignored. The advantage of this function is that the error
+ * message is removed when the refresh operation is started.
+ *
+ * Since: 3.18
+ **/
+void
+e_webdav_discover_content_show_error (GtkWidget *content,
+ const GError *error)
+{
+ EWebDAVDiscoverContentData *data;
+ GtkWidget *label;
+
+ g_return_if_fail (GTK_IS_GRID (content));
+
+ data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ if (data->info_bar) {
+ gtk_widget_destroy (GTK_WIDGET (data->info_bar));
+ data->info_bar = NULL;
+ }
+
+ if (!error || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ data->info_bar = GTK_INFO_BAR (gtk_info_bar_new ());
+ gtk_info_bar_set_message_type (data->info_bar, GTK_MESSAGE_ERROR);
+ gtk_info_bar_set_show_close_button (data->info_bar, TRUE);
+
+ label = gtk_label_new (error->message);
+ gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (data->info_bar)), label);
+ gtk_widget_show (label);
+ gtk_widget_show (GTK_WIDGET (data->info_bar));
+
+ g_signal_connect (data->info_bar, "response", G_CALLBACK
(e_webdav_discover_info_bar_error_response_cb), content);
+
+ gtk_grid_attach (GTK_GRID (content), GTK_WIDGET (data->info_bar), 0, 2, 1, 1);
+}
+
+static void
+e_webdav_discover_content_dialog_refresh_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *local_error = NULL;
+
+ if (!e_webdav_discover_content_refresh_finish (GTK_WIDGET (source_object), result, &local_error)) {
+ e_webdav_discover_content_show_error (GTK_WIDGET (source_object), local_error);
+ }
+
+ g_clear_error (&local_error);
+}
+
+static void
+e_webdav_discover_content_selection_changed_cb (GtkTreeSelection *selection,
+ GtkDialog *dialog)
+{
+ g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_ACCEPT,
+ gtk_tree_selection_count_selected_rows (selection) > 0);
+}
+
+/**
+ * e_webdav_discover_dialog_new:
+ * @parent: a #GtkWindow parent for the dialog
+ * @title: title of the window
+ * @credentials_prompter: an #ECredentialsPrompter to use to ask for credentials
+ * @source: an #ESource to use for authentication
+ * @base_url: (allow-none): optional base URL to use for discovery, or %NULL
+ * @supports_filter: a bit-or of #EWebDAVDiscoverSupports, a filter to limit what source
+ * types will be shown in the dialog content; use %E_WEBDAV_DISCOVER_SUPPORTS_NONE
+ * to show all
+ *
+ * Creates a new #GtkDialog which has as its content a WebDAV discovery widget,
+ * created with e_webdav_discover_content_new(). This dialog can be shown to a user
+ * and when its final response is %GTK_RESPONSE_ACCEPT, then the inner content
+ * can be asked for currently selected source(s).
+ *
+ * Returns: (transfer full): a newly created #GtkDialog, which should be freed
+ * with gtk_widget_destroy(), when no longer needed.
+ *
+ * Since: 3.18
+ **/
+GtkDialog *
+e_webdav_discover_dialog_new (GtkWindow *parent,
+ const gchar *title,
+ ECredentialsPrompter *credentials_prompter,
+ ESource *source,
+ const gchar *base_url,
+ guint supports_filter)
+{
+ GtkWidget *dialog, *container, *widget;
+ GtkTreeSelection *selection;
+
+ dialog = gtk_dialog_new_with_buttons (title, parent, GTK_DIALOG_DESTROY_WITH_PARENT,
+ _("_Cancel"), GTK_RESPONSE_REJECT,
+ _("_OK"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ widget = e_webdav_discover_content_new (credentials_prompter, source, base_url, supports_filter);
+
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "vexpand", TRUE,
+ "halign", GTK_ALIGN_FILL,
+ "valign", GTK_ALIGN_FILL,
+ NULL);
+
+ container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ gtk_container_add (GTK_CONTAINER (container), widget);
+
+ g_object_set_data (G_OBJECT (dialog), WEBDAV_DISCOVER_CONTENT_KEY, widget);
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 400);
+
+ selection = e_webdav_discover_content_get_tree_selection (widget);
+ g_signal_connect (selection, "changed", G_CALLBACK (e_webdav_discover_content_selection_changed_cb),
dialog);
+ e_webdav_discover_content_selection_changed_cb (selection, GTK_DIALOG (dialog));
+
+ return GTK_DIALOG (dialog);
+}
+
+/**
+ * e_webdav_discover_dialog_get_content:
+ * @dialog: a #GtkDialog returned by e_webdav_discover_dialog_new()
+ *
+ * Returns inner WebDAV discovery content, which can be further manipulated.
+ *
+ * Returns: (transfer none): inner WebDAV discovery content
+ *
+ * Since: 3.18
+ **/
+GtkWidget *
+e_webdav_discover_dialog_get_content (GtkDialog *dialog)
+{
+ GtkWidget *content;
+
+ g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
+
+ content = g_object_get_data (G_OBJECT (dialog), WEBDAV_DISCOVER_CONTENT_KEY);
+ g_return_val_if_fail (content != NULL, NULL);
+
+ return content;
+}
+
+/**
+ * e_webdav_discover_dialog_refresh:
+ * @dialog: a #GtkDialog returned by e_webdav_discover_dialog_new()
+ *
+ * Invokes refresh of the inner content of the WebDAV discovery dialog.
+ *
+ * Since: 3.18
+ **/
+void
+e_webdav_discover_dialog_refresh (GtkDialog *dialog)
+{
+ GtkWidget *content;
+
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ content = g_object_get_data (G_OBJECT (dialog), WEBDAV_DISCOVER_CONTENT_KEY);
+ g_return_if_fail (content != NULL);
+
+ e_webdav_discover_content_refresh (content, gtk_window_get_title (GTK_WINDOW (dialog)),
+ NULL, e_webdav_discover_content_dialog_refresh_done_cb, NULL);
+}
diff --git a/libedataserverui/e-webdav-discover-widget.h b/libedataserverui/e-webdav-discover-widget.h
new file mode 100644
index 0000000..fdb7ee2
--- /dev/null
+++ b/libedataserverui/e-webdav-discover-widget.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
+#error "Only <libedataserverui/libedataserverui.h> should be included directly."
+#endif
+
+#ifndef E_WEBDAV_DISCOVER_WIDGET_H
+#define E_WEBDAV_DISCOVER_WIDGET_H
+
+#include <gio/gio.h>
+
+#include <gtk/gtk.h>
+
+#include <libedataserver/libedataserver.h>
+#include <libedataserverui/libedataserverui.h>
+
+G_BEGIN_DECLS
+
+GtkWidget * e_webdav_discover_content_new (ECredentialsPrompter *credentials_prompter,
+ ESource *source,
+ const gchar *base_url,
+ guint supports_filter);
+GtkTreeSelection *
+ e_webdav_discover_content_get_tree_selection
+ (GtkWidget *content);
+gboolean e_webdav_discover_content_get_multiselect
+ (GtkWidget *content);
+void e_webdav_discover_content_set_multiselect
+ (GtkWidget *content,
+ gboolean multiselect);
+const gchar * e_webdav_discover_content_get_base_url (GtkWidget *content);
+void e_webdav_discover_content_set_base_url (GtkWidget *content,
+ const gchar *base_url);
+gboolean e_webdav_discover_content_get_selected (GtkWidget *content,
+ gint index,
+ gchar **out_href,
+ guint *out_supports,
+ gchar **out_display_name,
+ gchar **out_color);
+gchar * e_webdav_discover_content_get_user_address
+ (GtkWidget *content);
+void e_webdav_discover_content_refresh (GtkWidget *content,
+ const gchar *display_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_webdav_discover_content_refresh_finish
+ (GtkWidget *content,
+ GAsyncResult *result,
+ GError **error);
+void e_webdav_discover_content_show_error (GtkWidget *content,
+ const GError *error);
+
+GtkDialog * e_webdav_discover_dialog_new (GtkWindow *parent,
+ const gchar *title,
+ ECredentialsPrompter *credentials_prompter,
+ ESource *source,
+ const gchar *base_url,
+ guint supports_filter);
+
+GtkWidget * e_webdav_discover_dialog_get_content (GtkDialog *dialog);
+void e_webdav_discover_dialog_refresh (GtkDialog *dialog);
+
+G_END_DECLS
+
+#endif /* E_WEBDAV_DISCOVER_WIDGET_H */
diff --git a/libedataserverui/libedataserverui.h b/libedataserverui/libedataserverui.h
index 19c60cb..3223492 100644
--- a/libedataserverui/libedataserverui.h
+++ b/libedataserverui/libedataserverui.h
@@ -20,10 +20,12 @@
#define __LIBEDATASERVERUI_H_INSIDE__
+#include <libedataserverui/e-cell-renderer-color.h>
#include <libedataserverui/e-credentials-prompter.h>
#include <libedataserverui/e-credentials-prompter-impl.h>
#include <libedataserverui/e-credentials-prompter-impl-password.h>
#include <libedataserverui/e-trust-prompt.h>
+#include <libedataserverui/e-webdav-discover-widget.h>
#undef __LIBEDATASERVERUI_H_INSIDE__
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 94cd9d5..04d2a17 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -195,6 +195,7 @@ libedataserver/e-webdav-discover.c
libedataserverui/e-credentials-prompter.c
libedataserverui/e-credentials-prompter-impl-password.c
libedataserverui/e-trust-prompt.c
+libedataserverui/e-webdav-discover-widget.c
modules/gnome-online-accounts/e-goa-password-based.c
modules/gnome-online-accounts/goaewsclient.c
modules/gnome-online-accounts/module-gnome-online-accounts.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]