calendar-management: Move code to GcalNewCalendarPage

parent 9cc07c57
......@@ -28,117 +28,6 @@
<property name="vhomogeneous">False</property>
<property name="transition_type">crossfade</property>
<signal name="notify::visible-child-name" handler="stack_visible_child_name_changed" object="GcalCalendarManagementDialog" swapped="no"/>
<child>
<object class="GtkGrid" id="web_source_grid">
<property name="visible">True</property>
<property name="border_width">18</property>
<property name="row_spacing">16</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="web_description_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Enter the address of the calendar that you want to add. If the calendar belongs to one of your online accounts, you can add it through the &lt;a href=&quot;GOA&quot;&gt;online account settings&lt;/a&gt;.</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
<property name="xalign">0</property>
<signal name="activate-link" handler="description_label_link_activated" object="GcalCalendarManagementDialog" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="calendar_address_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Calendar Address</property>
<property name="xalign">1</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="calendar_address_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<signal name="notify::text" handler="url_entry_text_changed" object="GcalCalendarManagementDialog" swapped="no"/>
<signal name="activate" handler="calendar_address_activated" object="GcalCalendarManagementDialog" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkRevealer" id="web_sources_revealer">
<property name="transition_type">crossfade</property>
<property name="transition_duration">200</property>
<child>
<object class="GtkBox" id="web_sources_listbox_box">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="web_sources_calendar_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Calendars</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="web_list_scrolledwindow">
<property name="height_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkViewport" id="viewport">
<property name="visible">True</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkListBox" id="web_sources_listbox">
<property name="visible">True</property>
<property name="activate_on_single_click">False</property>
<property name="selection_mode">none</property>
<style>
<class name="calendar-list"/>
</style>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">create</property>
<property name="title" translatable="yes">Add Calendar</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
......@@ -196,109 +85,4 @@
</object>
</child>
</template>
<object class="GtkDialog" id="credentials_dialog">
<property name="type_hint">dialog</property>
<property name="transient_for">GcalCalendarManagementDialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="credentials-dialog-vbox1">
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid" id="credentials_grid">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="border_width">12</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="credentials_user_dim_label">
<property name="visible">True</property>
<property name="label" translatable="yes">User</property>
<property name="xalign">1</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="credentials_password_dim_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Password</property>
<property name="xalign">1</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="credentials_user_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<signal name="activate" handler="credential_entry_activate" object="credentials_dialog" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="credentials_password_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="visibility">False</property>
<signal name="activate" handler="credential_entry_activate" object="credentials_dialog" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="credentials_headerbar">
<property name="visible">True</property>
<property name="title" translatable="yes">Enter your credentials</property>
<child>
<object class="GtkButton" id="credentials_cancel_button">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="credential_button_clicked" object="GcalCalendarManagementDialog" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton" id="credentials_connect_button">
<property name="label" translatable="yes">Connect</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="credential_button_clicked" object="GcalCalendarManagementDialog" swapped="no"/>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
......@@ -2,5 +2,213 @@
<interface>
<template class="GcalNewCalendarPage" parent="GtkBox">
<property name="visible">True</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="border_width">18</property>
<property name="row_spacing">16</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="web_description_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Enter the address of the calendar that you want to add. If the calendar belongs to one of your online accounts, you can add it through the &lt;a href=&quot;GOA&quot;&gt;online account settings&lt;/a&gt;.</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
<property name="xalign">0</property>
<signal name="activate-link" handler="description_label_link_activated" object="GcalNewCalendarPage" swapped="no" />
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="calendar_address_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Calendar Address</property>
<property name="xalign">1</property>
<style>
<class name="dim-label" />
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="calendar_address_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<signal name="notify::text" handler="on_url_entry_text_changed_cb" object="GcalNewCalendarPage" swapped="no" />
<signal name="activate" handler="on_calendar_address_activated_cb" object="GcalNewCalendarPage" swapped="no" />
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkRevealer" id="web_sources_revealer">
<property name="transition_type">crossfade</property>
<property name="transition_duration">200</property>
<child>
<object class="GtkBox" id="web_sources_listbox_box">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="web_sources_calendar_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Calendars</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold" />
</attributes>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="height_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkViewport" id="viewport">
<property name="visible">True</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkListBox" id="web_sources_listbox">
<property name="visible">True</property>
<property name="activate_on_single_click">False</property>
<property name="selection_mode">none</property>
<style>
<class name="calendar-list" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</template>
<!-- Credentials dialog -->
<object class="GtkDialog" id="credentials_dialog">
<property name="type_hint">dialog</property>
<property name="transient_for">GcalNewCalendarPage</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="credentials_headerbar">
<property name="visible">True</property>
<property name="title" translatable="yes">Enter your credentials</property>
<child>
<object class="GtkButton" id="credentials_cancel_button">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="clicked" handler="on_credential_button_clicked_cb" object="GcalNewCalendarPage" swapped="no" />
</object>
</child>
<child>
<object class="GtkButton" id="credentials_connect_button">
<property name="label" translatable="yes">Connect</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="clicked" handler="on_credential_button_clicked_cb" object="GcalNewCalendarPage" swapped="no" />
<style>
<class name="suggested-action" />
</style>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</object>
</child>
<child internal-child="vbox">
<object class="GtkBox" id="credentials-dialog-vbox1">
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid" id="credentials_grid">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="border_width">12</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="credentials_user_dim_label">
<property name="visible">True</property>
<property name="label" translatable="yes">User</property>
<property name="xalign">1</property>
<style>
<class name="dim-label" />
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="credentials_password_dim_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Password</property>
<property name="xalign">1</property>
<style>
<class name="dim-label" />
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="credentials_user_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<signal name="activate" handler="on_credential_entry_activate_cb" object="credentials_dialog" swapped="no" />
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="credentials_password_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="visibility">False</property>
<signal name="activate" handler="on_credential_entry_activate_cb" object="credentials_dialog" swapped="no" />
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
......@@ -24,15 +24,35 @@
#include "gcal-context.h"
#include "gcal-calendar-management-page.h"
#include "gcal-debug.h"
#include "gcal-new-calendar-page.h"
#define ENTRY_PROGRESS_TIMEOUT 100 // ms
struct _GcalNewCalendarPage
{
GtkBox parent;
GtkEntry *calendar_address_entry;
GtkWidget *credentials_cancel_button;
GtkWidget *credentials_connect_button;
GtkWidget *credentials_dialog;
GtkEntry *credentials_password_entry;
GtkEntry *credentials_user_entry;
GtkWidget *web_sources_listbox;
GtkWidget *web_sources_revealer;
guint calendar_address_id;
gboolean prompt_password;
GList *remote_sources;
guint validate_url_resource_id;
GcalContext *context;
};
static gboolean validate_url_cb (GcalNewCalendarPage *self);
static void gcal_calendar_management_page_iface_init (GcalCalendarManagementPageInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GcalNewCalendarPage, gcal_new_calendar_page, GTK_TYPE_BOX,
......@@ -46,6 +66,442 @@ enum
N_PROPS
};
/*
* Auxiliary methods
*/
static ESource*
duplicate_source (ESource *source)
{
ESourceExtension *ext;
ESource *new_source;
g_assert (source && E_IS_SOURCE (source));
new_source = e_source_new (NULL, NULL, NULL);
e_source_set_parent (new_source, "local");
ext = e_source_get_extension (new_source, E_SOURCE_EXTENSION_CALENDAR);
e_source_backend_set_backend_name (E_SOURCE_BACKEND (ext), "local");
/* Copy Authentication data */
if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION))
{
ESourceAuthentication *new_auth, *parent_auth;
parent_auth = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
new_auth = e_source_get_extension (new_source, E_SOURCE_EXTENSION_AUTHENTICATION);
e_source_authentication_set_host (new_auth, e_source_authentication_get_host (parent_auth));
e_source_authentication_set_method (new_auth, e_source_authentication_get_method (parent_auth));
e_source_authentication_set_port (new_auth, e_source_authentication_get_port (parent_auth));
e_source_authentication_set_user (new_auth, e_source_authentication_get_user (parent_auth));
e_source_authentication_set_proxy_uid (new_auth, e_source_authentication_get_proxy_uid (parent_auth));
}
/* Copy Webdav data */
if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND))
{
ESourceWebdav *new_webdav, *parent_webdav;
parent_webdav = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
new_webdav = e_source_get_extension (new_source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
e_source_webdav_set_display_name (new_webdav, e_source_webdav_get_display_name (parent_webdav));
e_source_webdav_set_resource_path (new_webdav, e_source_webdav_get_resource_path (parent_webdav));
e_source_webdav_set_resource_query (new_webdav, e_source_webdav_get_resource_query (parent_webdav));
e_source_webdav_set_email_address (new_webdav, e_source_webdav_get_email_address (parent_webdav));
e_source_webdav_set_ssl_trust (new_webdav, e_source_webdav_get_ssl_trust (parent_webdav));
e_source_set_parent (new_source, "webcal-stub");
e_source_backend_set_backend_name (E_SOURCE_BACKEND (ext), "webcal");
}
return new_source;
}
static gint
prompt_credentials (GcalNewCalendarPage *self,
gchar **username,
gchar **password)
{
gint response;
/* Cleanup last credentials */
gtk_entry_set_text (self->credentials_password_entry, "");
gtk_entry_set_text (self->credentials_user_entry, "");
gtk_widget_grab_focus (GTK_WIDGET (self->credentials_user_entry));
/* Show the dialog, then destroy it */
response = gtk_dialog_run (GTK_DIALOG (self->credentials_dialog));
if (response == GTK_RESPONSE_OK)
{
if (username)
*username = g_strdup (gtk_entry_get_text (self->credentials_user_entry));
if (password)
*password = g_strdup (gtk_entry_get_text (self->credentials_password_entry));
}
gtk_widget_hide (self->credentials_dialog);
return response;
}
/*
* Callbacks
*/
static gboolean
pulse_web_entry (GcalNewCalendarPage *self)
{
gtk_entry_progress_pulse (self->calendar_address_entry);
self->calendar_address_id = g_timeout_add (ENTRY_PROGRESS_TIMEOUT, (GSourceFunc) pulse_web_entry, self);
return G_SOURCE_CONTINUE;
}
static void
on_check_activated_cb (GtkWidget *check,
GParamSpec *spec,
GcalNewCalendarPage *self)
{
GtkWidget *row;
ESource *source;
row = gtk_widget_get_parent (check);
source = g_object_get_data (G_OBJECT (row), "source");
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)))
self->remote_sources = g_list_prepend (self->remote_sources, source);
else
self->remote_sources = g_list_remove (self->remote_sources, source);
//gtk_widget_set_sensitive (self->add_button, g_list_length (self->remote_sources) > 0);
}
static void
discover_sources_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GcalNewCalendarPage *self;
GSList *discovered_sources;
GSList *user_addresses;
GSList *aux;
GError *error;
self = GCAL_NEW_CALENDAR_PAGE (user_data);
error = NULL;
/* Stop the pulsing entry */
if (self->calendar_address_id != 0)
{
gtk_entry_set_progress_fraction (GTK_ENTRY (self->calendar_address_entry), 0);
g_source_remove (self->calendar_address_id);
self->calendar_address_id = 0;
}
if (!e_webdav_discover_sources_finish (E_SOURCE (source), result, NULL, NULL, &discovered_sources, &user_addresses,
&error))
{
/* Don't add an source with errors */
//gtk_widget_set_sensitive (self->add_button, FALSE);
/*
* If it's the first try and things went wrong, retry with the user
* credentials. Also, it checks for the error code, since we don't
* really want to retry things on unavailable servers.
*/
if (!self->prompt_password &&
(error->code == 14 ||
error->code == 401 ||
error->code == 403 ||
error->code == 405))
{
self->prompt_password = TRUE;
validate_url_cb (self);
}
else
{
g_debug ("Error: %s", error->message);
}
g_error_free (error);
return;
}
/* Add a success icon to the entry */
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (self->calendar_address_entry), GTK_ENTRY_ICON_SECONDARY,
"emblem-ok-symbolic");
/* Remove previous results */
g_list_free_full (gtk_container_get_children (GTK_CONTAINER (self->web_sources_listbox)),
(GDestroyNotify) gtk_widget_destroy);
/* Show the list of calendars */
gtk_revealer_set_reveal_child (GTK_REVEALER (self->web_sources_revealer), TRUE);
gtk_widget_show (self->web_sources_revealer);
/* TODO: show a list of calendars */
for (aux = discovered_sources; aux != NULL; aux = aux->next)
{
g_autoptr (SoupURI) soup_uri = NULL;
EWebDAVDiscoveredSource *discovered_source;
const gchar *resource_path = NULL;
discovered_source = aux->data;
soup_uri = soup_uri_new (discovered_source->href);
/* Get the new resource path from the uri */
resource_path = soup_uri_get_path (soup_uri);
if (soup_uri)
{
ESourceSelectable *selectable;
ESourceWebdav *webdav;
GtkWidget *row, *check;
ESource *new_source;
/* build up the new source */
new_source = duplicate_source (E_SOURCE (source));
e_source_set_display_name (E_SOURCE (new_source), discovered_source->display_name);
webdav = e_source_get_extension (new_source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
e_source_webdav_set_resource_path (webdav, resource_path);
e_source_webdav_set_display_name (webdav, discovered_source->display_name);
if (user_addresses)
e_source_webdav_set_email_address (webdav, user_addresses->data);
/* Setup the color */
selectable = e_source_get_extension (new_source, E_SOURCE_EXTENSION_CALENDAR);
e_source_selectable_set_color (selectable, discovered_source->color);
/* create the new row */
row = gtk_list_box_row_new ();
check = gtk_check_button_new ();
gtk_button_set_label (GTK_BUTTON (check), discovered_source->display_name);
g_signal_connect (check, "notify::active", G_CALLBACK (on_check_activated_cb), self);
gtk_container_add (GTK_CONTAINER (row), check);
gtk_container_add (GTK_CONTAINER (self->web_sources_listbox), row);
g_object_set_data (G_OBJECT (row), "parent-source", source);
g_object_set_data (G_OBJECT (row), "source", new_source);
gtk_widget_show_all (row);
}