window: implement removing and undoing the removal of a calendar

We're still facing the bug where the just-added calendar segfaults when removed.
This commit is contained in:
Georges Basile Stavracas Neto
2015-05-25 12:35:26 -04:00
committed by Erick Pérez Castellanos
parent 9d222e47fc
commit 9df8b8077d
5 changed files with 93 additions and 16 deletions
+3
View File
@@ -33,6 +33,7 @@ typedef struct
GtkWidget *headerbar;
GtkWidget *name_entry;
GtkWidget *notebook;
GtkWidget *remove_button;
GtkWidget *select_file_button;
GtkWidget *stack;
@@ -382,6 +383,7 @@ gcal_source_dialog_constructed (GObject *object)
g_object_set_data (G_OBJECT (priv->add_button), "response", GINT_TO_POINTER (GTK_RESPONSE_APPLY));
g_object_set_data (G_OBJECT (priv->cancel_button), "response", GINT_TO_POINTER (GTK_RESPONSE_CANCEL));
g_object_set_data (G_OBJECT (priv->remove_button), "response", GINT_TO_POINTER (GCAL_RESPONSE_REMOVE_SOURCE));
/* setup titlebar */
gtk_window_set_titlebar (GTK_WINDOW (object), priv->headerbar);
@@ -450,6 +452,7 @@ gcal_source_dialog_class_init (GcalSourceDialogClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, headerbar);
gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, name_entry);
gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, notebook);
gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, remove_button);
gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, select_file_button);
gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, stack);
+2
View File
@@ -28,6 +28,8 @@
G_BEGIN_DECLS
#define GCAL_RESPONSE_REMOVE_SOURCE 2
#define GCAL_TYPE_SOURCE_DIALOG (gcal_source_dialog_get_type())
G_DECLARE_FINAL_TYPE (GcalSourceDialog, gcal_source_dialog, GCAL, SOURCE_DIALOG, GtkDialog)
+86 -12
View File
@@ -115,6 +115,8 @@ typedef struct
gint refresh_timeout;
gint refresh_timeout_id;
ESource *removed_source;
GHashTable *calendar_source_to_row;
/* temp to keep event_creation */
@@ -250,7 +252,7 @@ static void remove_event (GtkWidget *n
GParamSpec *spec,
gpointer user_data);
static void undo_remove_event (GtkButton *button,
static void undo_remove_action (GtkButton *button,
gpointer user_data);
static void gcal_window_constructed (GObject *object);
@@ -923,9 +925,11 @@ source_row_activated (GtkListBox *listbox,
GcalWindowPrivate *priv = gcal_window_get_instance_private (GCAL_WINDOW (user_data));
GtkWidget *new_row;
ESource *source;
gint response;
GList *l, *aux;
l = g_hash_table_get_keys (priv->calendar_source_to_row);
source = NULL;
for (aux = l; aux != NULL; aux = aux->next)
{
@@ -941,21 +945,44 @@ source_row_activated (GtkListBox *listbox,
}
}
/* double check the source */
if (source == NULL)
return;
gcal_source_dialog_set_mode (GCAL_SOURCE_DIALOG (priv->source_dialog), GCAL_SOURCE_DIALOG_MODE_EDIT);
gcal_source_dialog_set_source (GCAL_SOURCE_DIALOG (priv->source_dialog), source);
gtk_widget_hide (priv->calendar_popover);
gtk_dialog_run (GTK_DIALOG (priv->source_dialog));
response = gtk_dialog_run (GTK_DIALOG (priv->source_dialog));
gtk_widget_hide (priv->source_dialog);
/* update the source */
new_row = make_row_for_source (GCAL_WINDOW (user_data), source);
g_hash_table_remove (priv->calendar_source_to_row, source);
g_hash_table_insert (priv->calendar_source_to_row, source, new_row);
gtk_container_add (GTK_CONTAINER (priv->calendar_listbox), new_row);
if (response == GCAL_RESPONSE_REMOVE_SOURCE)
{
gchar *str;
str = g_strdup_printf (_("Calendar '%s' removed"), e_source_get_display_name (source));
priv->removed_source = source;
create_notification (GCAL_WINDOW (user_data), str, _("Undo"));
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->notification), TRUE);
gcal_manager_disable_source (priv->manager, source);
g_free (str);
}
else
{
new_row = make_row_for_source (GCAL_WINDOW (user_data), source);
g_hash_table_insert (priv->calendar_source_to_row, source, new_row);
gtk_container_add (GTK_CONTAINER (priv->calendar_listbox), new_row);
}
g_list_free (l);
}
@@ -1283,11 +1310,39 @@ remove_event (GtkWidget *notification,
g_clear_pointer (&(priv->event_to_delete), g_free);
}
/* If we have any removed source, finally delete it */
if (priv->removed_source != NULL)
{
GError *error = NULL;
/* We don't really want to remove non-removable sources */
if (!e_source_get_removable (priv->removed_source))
return;
e_source_remove_sync (priv->removed_source, NULL, &error);
/**
* If something goes wrong, throw
* an alert and add the source back.
*/
if (error != NULL)
{
g_warning ("Error removing source: %s", error->message);
add_source (priv->manager, priv->removed_source,
gcal_manager_source_enabled (priv->manager, priv->removed_source), user_data);
gcal_manager_enable_source (priv->manager, priv->removed_source);
g_error_free (error);
}
}
}
static void
undo_remove_event (GtkButton *button,
gpointer user_data)
undo_remove_action (GtkButton *button,
gpointer user_data)
{
GcalWindowPrivate *priv;
gchar *uuid;
@@ -1305,11 +1360,30 @@ undo_remove_event (GtkButton *button,
g_clear_pointer (&(priv->event_to_delete), g_free);
g_list_free (widgets);
g_free (uuid);
g_source_remove (priv->notification_timeout);
hide_notification (GCAL_WINDOW (user_data), NULL);
}
/* if there's any set source, unremove it */
if (priv->removed_source != NULL)
{
/**
* Enable the source before adding it again to
* avoid an enabled source with unchecked check
* button.
*/
gcal_manager_enable_source (priv->manager, priv->removed_source);
add_source (priv->manager, priv->removed_source,
gcal_manager_source_enabled (priv->manager, priv->removed_source), user_data);
/**
* Don't clear the pointer, since we don't
* want to erase the source at all.
*/
priv->removed_source = NULL;
}
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->notification), FALSE);
}
static gboolean
@@ -1433,7 +1507,7 @@ gcal_window_class_init(GcalWindowClass *klass)
/* Event removal related */
gtk_widget_class_bind_template_callback (widget_class, hide_notification);
gtk_widget_class_bind_template_callback (widget_class, remove_event);
gtk_widget_class_bind_template_callback (widget_class, undo_remove_event);
gtk_widget_class_bind_template_callback (widget_class, undo_remove_action);
/* Event creation related */
gtk_widget_class_bind_template_callback (widget_class, create_event);