Add file importing dialog
Add a file importing dialog, and pass through files received from command line. Fixes https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/5
This commit is contained in:
@@ -34,6 +34,10 @@ src/gui/gcal-weather-settings.ui
|
|||||||
src/gui/gcal-window.c
|
src/gui/gcal-window.c
|
||||||
src/gui/gcal-window.ui
|
src/gui/gcal-window.ui
|
||||||
src/gui/gtk/help-overlay.ui
|
src/gui/gtk/help-overlay.ui
|
||||||
|
src/gui/importer/gcal-import-dialog.c
|
||||||
|
src/gui/importer/gcal-import-dialog.ui
|
||||||
|
src/gui/importer/gcal-importer.c
|
||||||
|
src/gui/importer/gcal-import-file-row.c
|
||||||
src/gui/views/gcal-month-popover.ui
|
src/gui/views/gcal-month-popover.ui
|
||||||
src/gui/views/gcal-week-grid.c
|
src/gui/views/gcal-week-grid.c
|
||||||
src/gui/views/gcal-week-header.c
|
src/gui/views/gcal-week-header.c
|
||||||
|
|||||||
@@ -457,11 +457,14 @@ gcal_application_command_line (GApplication *app,
|
|||||||
GApplicationCommandLine *command_line)
|
GApplicationCommandLine *command_line)
|
||||||
{
|
{
|
||||||
g_autoptr (GVariant) option = NULL;
|
g_autoptr (GVariant) option = NULL;
|
||||||
|
g_auto (GStrv) arguments = NULL;
|
||||||
GcalApplication *self;
|
GcalApplication *self;
|
||||||
GVariantDict *options;
|
GVariantDict *options;
|
||||||
const gchar* date = NULL;
|
const gchar* date = NULL;
|
||||||
const gchar* uuid = NULL;
|
const gchar* uuid = NULL;
|
||||||
gsize length;
|
gsize length;
|
||||||
|
gint n_arguments;
|
||||||
|
gint i;
|
||||||
|
|
||||||
GCAL_ENTRY;
|
GCAL_ENTRY;
|
||||||
|
|
||||||
@@ -510,6 +513,37 @@ gcal_application_command_line (GApplication *app,
|
|||||||
|
|
||||||
g_application_activate (app);
|
g_application_activate (app);
|
||||||
|
|
||||||
|
arguments = g_application_command_line_get_arguments (command_line, &n_arguments);
|
||||||
|
if (n_arguments > 1)
|
||||||
|
{
|
||||||
|
g_autoptr (GHashTable) unique_files = NULL;
|
||||||
|
g_autoptr (GPtrArray) files = NULL;
|
||||||
|
gint n_files = 0;
|
||||||
|
|
||||||
|
files = g_ptr_array_new_full (n_arguments - 1, g_object_unref);
|
||||||
|
unique_files = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
|
||||||
|
|
||||||
|
for (i = 1; i < n_arguments; i++)
|
||||||
|
{
|
||||||
|
g_autoptr (GFile) file = NULL;
|
||||||
|
const gchar *arg;
|
||||||
|
|
||||||
|
arg = arguments[i];
|
||||||
|
file = g_application_command_line_create_file_for_arg (command_line, arg);
|
||||||
|
|
||||||
|
if (g_str_has_prefix (arg, "-") || g_hash_table_contains (unique_files, file))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_hash_table_add (unique_files, file);
|
||||||
|
g_ptr_array_add (files, g_steal_pointer (&file));
|
||||||
|
|
||||||
|
n_files++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_files > 0)
|
||||||
|
g_application_open (app, (GFile **) files->pdata, n_files, "");
|
||||||
|
}
|
||||||
|
|
||||||
GCAL_RETURN (0);
|
GCAL_RETURN (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,6 +608,23 @@ gcal_application_dbus_unregister (GApplication *application,
|
|||||||
GCAL_EXIT;
|
GCAL_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_application_open (GApplication *application,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files,
|
||||||
|
const gchar *hint)
|
||||||
|
{
|
||||||
|
GcalApplication *self;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self = GCAL_APPLICATION (application);
|
||||||
|
|
||||||
|
gcal_window_import_files (GCAL_WINDOW (self->window), files, n_files);
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gcal_application_class_init (GcalApplicationClass *klass)
|
gcal_application_class_init (GcalApplicationClass *klass)
|
||||||
{
|
{
|
||||||
@@ -588,6 +639,7 @@ gcal_application_class_init (GcalApplicationClass *klass)
|
|||||||
application_class->activate = gcal_application_activate;
|
application_class->activate = gcal_application_activate;
|
||||||
application_class->startup = gcal_application_startup;
|
application_class->startup = gcal_application_startup;
|
||||||
application_class->command_line = gcal_application_command_line;
|
application_class->command_line = gcal_application_command_line;
|
||||||
|
application_class->open = gcal_application_open;
|
||||||
application_class->handle_local_options = gcal_application_handle_local_options;
|
application_class->handle_local_options = gcal_application_handle_local_options;
|
||||||
application_class->dbus_register = gcal_application_dbus_register;
|
application_class->dbus_register = gcal_application_dbus_register;
|
||||||
application_class->dbus_unregister = gcal_application_dbus_unregister;
|
application_class->dbus_unregister = gcal_application_dbus_unregister;
|
||||||
@@ -631,7 +683,7 @@ gcal_application_new (void)
|
|||||||
return g_object_new (gcal_application_get_type (),
|
return g_object_new (gcal_application_get_type (),
|
||||||
"resource-base-path", "/org/gnome/calendar",
|
"resource-base-path", "/org/gnome/calendar",
|
||||||
"application-id", APPLICATION_ID,
|
"application-id", APPLICATION_ID,
|
||||||
"flags", G_APPLICATION_HANDLES_COMMAND_LINE,
|
"flags", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#include "gcal-window.h"
|
#include "gcal-window.h"
|
||||||
#include "gcal-year-view.h"
|
#include "gcal-year-view.h"
|
||||||
|
|
||||||
|
#include "importer/gcal-import-dialog.h"
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
#include <libecal/libecal.h>
|
#include <libecal/libecal.h>
|
||||||
|
|
||||||
@@ -116,6 +118,7 @@ struct _GcalWindow
|
|||||||
GtkWidget *views_switcher;
|
GtkWidget *views_switcher;
|
||||||
|
|
||||||
GcalEventEditorDialog *event_editor;
|
GcalEventEditorDialog *event_editor;
|
||||||
|
GtkWidget *import_dialog;
|
||||||
|
|
||||||
DzlSuggestionButton *search_button;
|
DzlSuggestionButton *search_button;
|
||||||
|
|
||||||
@@ -1205,3 +1208,17 @@ gcal_window_open_event_by_uuid (GcalWindow *self,
|
|||||||
edit_dialog_data);
|
edit_dialog_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gcal_window_import_files (GcalWindow *self,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GCAL_IS_WINDOW (self));
|
||||||
|
|
||||||
|
g_clear_pointer (&self->import_dialog, gtk_widget_destroy);
|
||||||
|
|
||||||
|
self->import_dialog = gcal_import_dialog_new_for_files (self->context, files, n_files);
|
||||||
|
gtk_window_set_transient_for (GTK_WINDOW (self->import_dialog), GTK_WINDOW (self));
|
||||||
|
gtk_window_present (GTK_WINDOW (self->import_dialog));
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ void gcal_window_set_search_query (GcalWindow
|
|||||||
void gcal_window_open_event_by_uuid (GcalWindow *self,
|
void gcal_window_open_event_by_uuid (GcalWindow *self,
|
||||||
const gchar *uuid);
|
const gchar *uuid);
|
||||||
|
|
||||||
|
void gcal_window_import_files (GcalWindow *self,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GCAL_WINDOW_H__ */
|
#endif /* __GCAL_WINDOW_H__ */
|
||||||
|
|||||||
@@ -0,0 +1,569 @@
|
|||||||
|
/* gcal-import-dialog.c
|
||||||
|
*
|
||||||
|
* Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define G_LOG_DOMAIN "GcalImportDialog"
|
||||||
|
|
||||||
|
#include "gcal-import-dialog.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "gcal-debug.h"
|
||||||
|
#include "gcal-import-file-row.h"
|
||||||
|
#include "gcal-utils.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _GcalImportDialog
|
||||||
|
{
|
||||||
|
HdyWindow parent;
|
||||||
|
|
||||||
|
GtkImage *calendar_color_image;
|
||||||
|
GtkLabel *calendar_name_label;
|
||||||
|
GtkListBox *calendars_listbox;
|
||||||
|
GtkPopover *calendars_popover;
|
||||||
|
GtkWidget *cancel_button;
|
||||||
|
GtkListBox *files_listbox;
|
||||||
|
HdyHeaderBar *headerbar;
|
||||||
|
GtkWidget *import_button;
|
||||||
|
GtkSizeGroup *title_sizegroup;
|
||||||
|
|
||||||
|
GtkWidget *selected_row;
|
||||||
|
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GcalContext *context;
|
||||||
|
gint n_events;
|
||||||
|
gint n_files;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void on_import_row_file_loaded_cb (GcalImportFileRow *row,
|
||||||
|
GPtrArray *events,
|
||||||
|
GcalImportDialog *self);
|
||||||
|
|
||||||
|
static void on_manager_calendar_added_cb (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar,
|
||||||
|
GcalImportDialog *self);
|
||||||
|
|
||||||
|
static void on_manager_calendar_changed_cb (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar,
|
||||||
|
GcalImportDialog *self);
|
||||||
|
|
||||||
|
static void on_manager_calendar_removed_cb (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar,
|
||||||
|
GcalImportDialog *self);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GcalImportDialog, gcal_import_dialog, HDY_TYPE_WINDOW)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_CONTEXT,
|
||||||
|
N_PROPS
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *properties [N_PROPS];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Auxiliary methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
create_calendar_row (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar)
|
||||||
|
{
|
||||||
|
g_autofree gchar *parent_name = NULL;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
const GdkRGBA *color;
|
||||||
|
GtkWidget *icon;
|
||||||
|
GtkWidget *row;
|
||||||
|
|
||||||
|
color = gcal_calendar_get_color (calendar);
|
||||||
|
surface = get_circle_surface_from_color (color, 16);
|
||||||
|
get_source_parent_name_color (manager,
|
||||||
|
gcal_calendar_get_source (calendar),
|
||||||
|
&parent_name,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* The icon with the source color */
|
||||||
|
icon = gtk_image_new_from_surface (surface);
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (icon), "calendar-color-image");
|
||||||
|
gtk_widget_show (icon);
|
||||||
|
|
||||||
|
/* The row itself */
|
||||||
|
row = g_object_new (HDY_TYPE_ACTION_ROW,
|
||||||
|
"title", gcal_calendar_get_name (calendar),
|
||||||
|
"subtitle", parent_name,
|
||||||
|
"sensitive", !gcal_calendar_is_read_only (calendar),
|
||||||
|
"activatable", TRUE,
|
||||||
|
"width-request", 300,
|
||||||
|
NULL);
|
||||||
|
hdy_action_row_add_prefix (HDY_ACTION_ROW (row), icon);
|
||||||
|
gtk_widget_show (row);
|
||||||
|
|
||||||
|
g_object_set_data_full (G_OBJECT (row), "calendar", g_object_ref (calendar), g_object_unref);
|
||||||
|
g_object_set_data (G_OBJECT (row), "color-icon", icon);
|
||||||
|
|
||||||
|
g_clear_pointer (&surface, cairo_surface_destroy);
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
get_row_for_calendar (GcalImportDialog *self,
|
||||||
|
GcalCalendar *calendar)
|
||||||
|
{
|
||||||
|
g_autoptr (GList) children = NULL;
|
||||||
|
GtkWidget *row;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
row = NULL;
|
||||||
|
children = gtk_container_get_children (GTK_CONTAINER (self->calendars_listbox));
|
||||||
|
|
||||||
|
for (l = children; l != NULL; l = g_list_next (l))
|
||||||
|
{
|
||||||
|
GcalCalendar *row_calendar = g_object_get_data (l->data, "calendar");
|
||||||
|
|
||||||
|
if (row_calendar == calendar)
|
||||||
|
{
|
||||||
|
row = l->data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
select_row (GcalImportDialog *self,
|
||||||
|
GtkListBoxRow *row)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
const GdkRGBA *color;
|
||||||
|
GcalCalendar *calendar;
|
||||||
|
|
||||||
|
self->selected_row = GTK_WIDGET (row);
|
||||||
|
|
||||||
|
/* Setup the event page's source name and color */
|
||||||
|
calendar = g_object_get_data (G_OBJECT (row), "calendar");
|
||||||
|
|
||||||
|
gtk_label_set_label (self->calendar_name_label, gcal_calendar_get_name (calendar));
|
||||||
|
|
||||||
|
color = gcal_calendar_get_color (calendar);
|
||||||
|
surface = get_circle_surface_from_color (color, 16);
|
||||||
|
gtk_image_set_from_surface (self->calendar_color_image, surface);
|
||||||
|
|
||||||
|
g_clear_pointer (&surface, cairo_surface_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_default_calendar_row (GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
GcalCalendar *default_calendar;
|
||||||
|
GcalManager *manager;
|
||||||
|
GtkWidget *row;
|
||||||
|
|
||||||
|
manager = gcal_context_get_manager (self->context);
|
||||||
|
default_calendar = gcal_manager_get_default_calendar (manager);
|
||||||
|
|
||||||
|
row = get_row_for_calendar (self, default_calendar);
|
||||||
|
if (row != NULL)
|
||||||
|
select_row (self, GTK_LIST_BOX_ROW (row));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_calendars (GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
g_autoptr (GList) calendars = NULL;
|
||||||
|
GcalManager *manager;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
manager = gcal_context_get_manager (self->context);
|
||||||
|
calendars = gcal_manager_get_calendars (manager);
|
||||||
|
|
||||||
|
for (l = calendars; l; l = l->next)
|
||||||
|
on_manager_calendar_added_cb (manager, l->data, self);
|
||||||
|
|
||||||
|
update_default_calendar_row (self);
|
||||||
|
|
||||||
|
g_signal_connect_object (manager, "calendar-added", G_CALLBACK (on_manager_calendar_added_cb), self, 0);
|
||||||
|
g_signal_connect_object (manager, "calendar-changed", G_CALLBACK (on_manager_calendar_changed_cb), self, 0);
|
||||||
|
g_signal_connect_object (manager, "calendar-removed", G_CALLBACK (on_manager_calendar_removed_cb), self, 0);
|
||||||
|
g_signal_connect_object (manager, "notify::default-calendar", G_CALLBACK (update_default_calendar_row), self, G_CONNECT_SWAPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_files (GcalImportDialog *self,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self->n_files = n_files;
|
||||||
|
|
||||||
|
for (i = 0; i < n_files; i++)
|
||||||
|
{
|
||||||
|
GtkWidget *row;
|
||||||
|
|
||||||
|
row = gcal_import_file_row_new (files[i], self->title_sizegroup);
|
||||||
|
g_signal_connect (row, "file-loaded", G_CALLBACK (on_import_row_file_loaded_cb), self);
|
||||||
|
|
||||||
|
if (n_files > 1)
|
||||||
|
gcal_import_file_row_show_filename (GCAL_IMPORT_FILE_ROW (row));
|
||||||
|
|
||||||
|
gtk_list_box_insert (self->files_listbox, row, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callbacks
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_events_created_cb (GObject *source_object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
GcalImportDialog *self;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self = GCAL_IMPORT_DIALOG (user_data);
|
||||||
|
|
||||||
|
e_cal_client_create_objects_finish (E_CAL_CLIENT (source_object), result, NULL, &error);
|
||||||
|
if (error)
|
||||||
|
g_warning ("Error creating events: %s", error->message);
|
||||||
|
|
||||||
|
gtk_widget_destroy (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_calendars_listbox_row_activated_cb (GtkListBox *listbox,
|
||||||
|
GtkListBoxRow *row,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
select_row (self, row);
|
||||||
|
gtk_popover_popdown (self->calendars_popover);
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_cancel_button_clicked_cb (GtkButton *button,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
gtk_widget_destroy (GTK_WIDGET (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_import_button_clicked_cb (GtkButton *button,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
g_autoptr (GList) children = NULL;
|
||||||
|
GcalCalendar *calendar;
|
||||||
|
ECalClient *client;
|
||||||
|
GSList *slist;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
calendar = g_object_get_data (G_OBJECT (self->selected_row), "calendar");
|
||||||
|
g_assert (self->selected_row != NULL);
|
||||||
|
|
||||||
|
slist = NULL;
|
||||||
|
children = gtk_container_get_children (GTK_CONTAINER (self->files_listbox));
|
||||||
|
for (l = children; l; l = l->next)
|
||||||
|
{
|
||||||
|
GcalImportFileRow *row = l->data;
|
||||||
|
GPtrArray *ical_components;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
ical_components = gcal_import_file_row_get_ical_components (row);
|
||||||
|
if (!ical_components)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < ical_components->len; i++)
|
||||||
|
slist = g_slist_prepend (slist, g_ptr_array_index (ical_components, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!slist)
|
||||||
|
GCAL_RETURN ();
|
||||||
|
|
||||||
|
self->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
|
||||||
|
|
||||||
|
client = gcal_calendar_get_client (calendar);
|
||||||
|
e_cal_client_create_objects (client,
|
||||||
|
slist,
|
||||||
|
E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
self->cancellable,
|
||||||
|
on_events_created_cb,
|
||||||
|
self);
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_import_row_file_loaded_cb (GcalImportFileRow *row,
|
||||||
|
GPtrArray *events,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
g_autofree gchar *title = NULL;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self->n_events += events ? events->len : 0;
|
||||||
|
|
||||||
|
title = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
|
||||||
|
"Import %d event",
|
||||||
|
"Import %d events",
|
||||||
|
self->n_events),
|
||||||
|
self->n_events);
|
||||||
|
hdy_header_bar_set_title (self->headerbar, title);
|
||||||
|
|
||||||
|
gtk_widget_show (GTK_WIDGET (row));
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_calendar_added_cb (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
if (gcal_calendar_is_read_only (calendar))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (self->calendars_listbox),
|
||||||
|
create_calendar_row (manager, calendar));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_calendar_changed_cb (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
const GdkRGBA *color;
|
||||||
|
GtkWidget *row, *color_icon;
|
||||||
|
gboolean read_only;
|
||||||
|
|
||||||
|
read_only = gcal_calendar_is_read_only (calendar);
|
||||||
|
row = get_row_for_calendar (self, calendar);
|
||||||
|
|
||||||
|
/* If the calendar changed from/to read-only, we add or remove it here */
|
||||||
|
if (read_only)
|
||||||
|
{
|
||||||
|
if (row)
|
||||||
|
gtk_container_remove (GTK_CONTAINER (self->calendars_listbox), row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!row)
|
||||||
|
{
|
||||||
|
on_manager_calendar_added_cb (manager, calendar, self);
|
||||||
|
row = get_row_for_calendar (self, calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (row), gcal_calendar_get_name (calendar));
|
||||||
|
gtk_widget_set_sensitive (row, !read_only);
|
||||||
|
|
||||||
|
/* Setup the source color, in case it changed */
|
||||||
|
color = gcal_calendar_get_color (calendar);
|
||||||
|
surface = get_circle_surface_from_color (color, 16);
|
||||||
|
color_icon = g_object_get_data (G_OBJECT (row), "color-icon");
|
||||||
|
gtk_image_set_from_surface (GTK_IMAGE (color_icon), surface);
|
||||||
|
|
||||||
|
gtk_list_box_invalidate_sort (GTK_LIST_BOX (self->calendars_listbox));
|
||||||
|
|
||||||
|
g_clear_pointer (&surface, cairo_surface_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_calendar_removed_cb (GcalManager *manager,
|
||||||
|
GcalCalendar *calendar,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
GtkWidget *row;
|
||||||
|
|
||||||
|
row = get_row_for_calendar (self, calendar);
|
||||||
|
|
||||||
|
if (!row)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_container_remove (GTK_CONTAINER (self->calendars_listbox), row);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_select_calendar_row_activated_cb (GtkListBox *listbox,
|
||||||
|
GtkListBoxRow *row,
|
||||||
|
GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
gtk_popover_popup (self->calendars_popover);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
sort_func (GtkListBoxRow *row1,
|
||||||
|
GtkListBoxRow *row2,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GcalCalendar *calendar1, *calendar2;
|
||||||
|
g_autofree gchar *name1 = NULL;
|
||||||
|
g_autofree gchar *name2 = NULL;
|
||||||
|
|
||||||
|
calendar1 = g_object_get_data (G_OBJECT (row1), "calendar");
|
||||||
|
calendar2 = g_object_get_data (G_OBJECT (row2), "calendar");
|
||||||
|
|
||||||
|
name1 = g_utf8_casefold (gcal_calendar_get_name (calendar1), -1);
|
||||||
|
name2 = g_utf8_casefold (gcal_calendar_get_name (calendar2), -1);
|
||||||
|
|
||||||
|
return g_strcmp0 (name1, name2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GObject overrides
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_dialog_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GcalImportDialog *self = (GcalImportDialog *)object;
|
||||||
|
|
||||||
|
g_cancellable_cancel (self->cancellable);
|
||||||
|
g_clear_object (&self->cancellable);
|
||||||
|
g_clear_object (&self->context);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gcal_import_dialog_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_dialog_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GcalImportDialog *self = GCAL_IMPORT_DIALOG (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_CONTEXT:
|
||||||
|
g_value_set_object (value, self->context);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_dialog_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GcalImportDialog *self = GCAL_IMPORT_DIALOG (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_CONTEXT:
|
||||||
|
g_assert (self->context == NULL);
|
||||||
|
self->context = g_value_dup_object (value);
|
||||||
|
setup_calendars (self);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_dialog_class_init (GcalImportDialogClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gcal_import_dialog_finalize;
|
||||||
|
object_class->get_property = gcal_import_dialog_get_property;
|
||||||
|
object_class->set_property = gcal_import_dialog_set_property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GcalEventPopover::context:
|
||||||
|
*
|
||||||
|
* The context of the import dialog.
|
||||||
|
*/
|
||||||
|
properties[PROP_CONTEXT] = g_param_spec_object ("context",
|
||||||
|
"Context",
|
||||||
|
"Context",
|
||||||
|
GCAL_TYPE_CONTEXT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/gui/importer/gcal-import-dialog.ui");
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, calendar_color_image);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, calendar_name_label);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, calendars_listbox);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, calendars_popover);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, cancel_button);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, files_listbox);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, headerbar);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, import_button);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportDialog, title_sizegroup);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, on_calendars_listbox_row_activated_cb);
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, on_cancel_button_clicked_cb);
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, on_import_button_clicked_cb);
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, on_select_calendar_row_activated_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_dialog_init (GcalImportDialog *self)
|
||||||
|
{
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
gtk_list_box_set_sort_func (GTK_LIST_BOX (self->calendars_listbox), sort_func, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
gcal_import_dialog_new_for_files (GcalContext *context,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files)
|
||||||
|
{
|
||||||
|
GcalImportDialog *self;
|
||||||
|
|
||||||
|
self = g_object_new (GCAL_TYPE_IMPORT_DIALOG,
|
||||||
|
"context", context,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
setup_files (self, files, n_files);
|
||||||
|
|
||||||
|
return GTK_WIDGET (self);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* gcal-import-dialog.h
|
||||||
|
*
|
||||||
|
* Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gcal-context.h"
|
||||||
|
|
||||||
|
#include <handy.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GCAL_TYPE_IMPORT_DIALOG (gcal_import_dialog_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (GcalImportDialog, gcal_import_dialog, GCAL, IMPORT_DIALOG, HdyWindow)
|
||||||
|
|
||||||
|
GtkWidget* gcal_import_dialog_new_for_files (GcalContext *context,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="GcalImportDialog" parent="HdyWindow">
|
||||||
|
<property name="width_request">500</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="border_width">0</property>
|
||||||
|
<property name="default_width">550</property>
|
||||||
|
<property name="default_height">500</property>
|
||||||
|
<property name="resizable">False</property>
|
||||||
|
<property name="type_hint">dialog</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="destroy_with_parent">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="HdyDeck">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="HdyHeaderBar" id="headerbar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="title" translatable="yes">Import Files…</property>
|
||||||
|
<property name="show_close_button">False</property>
|
||||||
|
|
||||||
|
<!-- Cancel button -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="cancel_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">_Cancel</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<signal name="clicked" handler="on_cancel_button_clicked_cb" object="GcalImportDialog" swapped="no" />
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<!-- Import button -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="import_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">_Import</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<signal name="clicked" handler="on_import_button_clicked_cb" object="GcalImportDialog" swapped="no" />
|
||||||
|
<style>
|
||||||
|
<class name="suggested-action" />
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack-type">end</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="hscrollbar-policy">never</property>
|
||||||
|
<property name="propagate-natural-height">True</property>
|
||||||
|
<property name="min-content-height">400</property>
|
||||||
|
<property name="max-content-height">700</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<property name="margin-top">24</property>
|
||||||
|
<property name="margin-bottom">24</property>
|
||||||
|
<property name="margin-start">36</property>
|
||||||
|
<property name="margin-end">36</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
|
||||||
|
<!-- Calendar row -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
<signal name="row-activated" handler="on_select_calendar_row_activated_cb" object="GcalImportDialog" swapped="no" />
|
||||||
|
<style>
|
||||||
|
<class name="content" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="HdyActionRow" id="calendar_row">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">C_alendar</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="calendar_row_widgets_box">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="margin-start">12</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
|
||||||
|
<!-- Color -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="calendar_color_image">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<!-- Calendar name -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="calendar_name_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="pixel-size">16</property>
|
||||||
|
<property name="icon-name">pan-down-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<!-- Files overview -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox" id="files_listbox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
|
||||||
|
<child type="placeholder">
|
||||||
|
<object class="GtkSpinner">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
<class name="background" />
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Calendars popover -->
|
||||||
|
<object class="GtkPopover" id="calendars_popover">
|
||||||
|
<property name="position">bottom</property>
|
||||||
|
<property name="relative-to">calendar_row_widgets_box</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="hscrollbar-policy">never</property>
|
||||||
|
<property name="max-content-height">350</property>
|
||||||
|
<property name="propagate-natural-width">True</property>
|
||||||
|
<property name="propagate-natural-height">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox" id="calendars_listbox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
<signal name="row-activated" handler="on_calendars_listbox_row_activated_cb" object="GcalImportDialog" swapped="no" />
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
|
||||||
|
<object class="GtkSizeGroup" id="title_sizegroup">
|
||||||
|
<property name="mode">horizontal</property>
|
||||||
|
</object>
|
||||||
|
|
||||||
|
</interface>
|
||||||
@@ -0,0 +1,388 @@
|
|||||||
|
/* gcal-import-file-row.c
|
||||||
|
*
|
||||||
|
* Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define G_LOG_DOMAIN "GcalImportFileRow"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "gcal-import-file-row.h"
|
||||||
|
#include "gcal-importer.h"
|
||||||
|
#include "gcal-utils.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _GcalImportFileRow
|
||||||
|
{
|
||||||
|
GtkListBoxRow parent;
|
||||||
|
|
||||||
|
GtkListBox *events_listbox;
|
||||||
|
GtkLabel *filename_label;
|
||||||
|
GtkSizeGroup *title_sizegroup;
|
||||||
|
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GFile *file;
|
||||||
|
GPtrArray *ical_components;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void read_calendar_finished_cb (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GcalImportFileRow, gcal_import_file_row, GTK_TYPE_LIST_BOX_ROW)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_FILE,
|
||||||
|
N_PROPS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FILE_LOADED,
|
||||||
|
N_SIGNALS,
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[N_SIGNALS] = { 0, };
|
||||||
|
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Auxiliary methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_grid_row (GcalImportFileRow *self,
|
||||||
|
GtkGrid *grid,
|
||||||
|
gint row,
|
||||||
|
const gchar *title,
|
||||||
|
const gchar *value)
|
||||||
|
{
|
||||||
|
GtkWidget *title_label;
|
||||||
|
GtkWidget *value_label;
|
||||||
|
|
||||||
|
if (!value || g_utf8_strlen (value, -1) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
title_label = g_object_new (GTK_TYPE_LABEL,
|
||||||
|
"visible", TRUE,
|
||||||
|
"label", title,
|
||||||
|
"xalign", 1.0,
|
||||||
|
"yalign", 0.0,
|
||||||
|
"ellipsize", PANGO_ELLIPSIZE_END,
|
||||||
|
"max-width-chars", 40,
|
||||||
|
NULL);
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (title_label), "dim-label");
|
||||||
|
gtk_grid_attach (grid, title_label, 0, row, 1, 1);
|
||||||
|
|
||||||
|
gtk_size_group_add_widget (self->title_sizegroup, title_label);
|
||||||
|
|
||||||
|
value_label = g_object_new (GTK_TYPE_LABEL,
|
||||||
|
"visible", TRUE,
|
||||||
|
"label", value,
|
||||||
|
"xalign", 0.0,
|
||||||
|
"selectable", TRUE,
|
||||||
|
"ellipsize", PANGO_ELLIPSIZE_END,
|
||||||
|
"max-width-chars", 40,
|
||||||
|
NULL);
|
||||||
|
gtk_grid_attach (grid, value_label, 1, row, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_grid_with_event_data (GcalImportFileRow *self,
|
||||||
|
GtkGrid *grid,
|
||||||
|
ICalComponent *ical_component)
|
||||||
|
{
|
||||||
|
g_autofree gchar *start_string = NULL;
|
||||||
|
g_autofree gchar *description = NULL;
|
||||||
|
g_autofree gchar *end_string = NULL;
|
||||||
|
g_autoptr (GDateTime) start = NULL;
|
||||||
|
g_autoptr (GDateTime) end = NULL;
|
||||||
|
ICalTime *ical_start;
|
||||||
|
ICalTime *ical_end;
|
||||||
|
gint row = 0;
|
||||||
|
|
||||||
|
ical_start = i_cal_component_get_dtstart (ical_component);
|
||||||
|
start = gcal_date_time_from_icaltime (ical_start);
|
||||||
|
if (i_cal_time_is_date (ical_start))
|
||||||
|
start_string = g_date_time_format (start, "%x");
|
||||||
|
else
|
||||||
|
start_string = g_date_time_format (start, "%x %X");
|
||||||
|
|
||||||
|
ical_end = i_cal_component_get_dtend (ical_component);
|
||||||
|
if (ical_end)
|
||||||
|
{
|
||||||
|
end = gcal_date_time_from_icaltime (ical_end);
|
||||||
|
if (i_cal_time_is_date (ical_end))
|
||||||
|
end_string = g_date_time_format (end, "%x");
|
||||||
|
else
|
||||||
|
end_string = g_date_time_format (end, "%x %X");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end = g_date_time_add_days (start, 1);
|
||||||
|
if (i_cal_time_is_date (ical_start))
|
||||||
|
end_string = g_date_time_format (end, "%x");
|
||||||
|
else
|
||||||
|
end_string = g_date_time_format (end, "%x %X");
|
||||||
|
}
|
||||||
|
|
||||||
|
gcal_utils_extract_google_section (i_cal_component_get_description (ical_component),
|
||||||
|
&description,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
add_grid_row (self, grid, row++, _("Title"), i_cal_component_get_summary (ical_component));
|
||||||
|
add_grid_row (self, grid, row++, _("Location"), i_cal_component_get_location (ical_component));
|
||||||
|
add_grid_row (self, grid, row++, _("Starts"), start_string);
|
||||||
|
add_grid_row (self, grid, row++, _("Ends"), end_string);
|
||||||
|
add_grid_row (self, grid, row++, _("Description"), description);
|
||||||
|
|
||||||
|
g_clear_object (&ical_start);
|
||||||
|
g_clear_object (&ical_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_events_to_listbox (GcalImportFileRow *self,
|
||||||
|
GPtrArray *events)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < events->len; i++)
|
||||||
|
{
|
||||||
|
ICalComponent *ical_component;
|
||||||
|
GtkWidget *grid;
|
||||||
|
GtkWidget *row;
|
||||||
|
|
||||||
|
ical_component = g_ptr_array_index (events, i);
|
||||||
|
|
||||||
|
row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
|
||||||
|
"visible", TRUE,
|
||||||
|
"activatable", FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
grid = g_object_new (GTK_TYPE_GRID,
|
||||||
|
"visible", TRUE,
|
||||||
|
"row-spacing", 6,
|
||||||
|
"column-spacing", 12,
|
||||||
|
"margin-top", 18,
|
||||||
|
"margin-bottom", 18,
|
||||||
|
"margin-start", 24,
|
||||||
|
"margin-end", 24,
|
||||||
|
NULL);
|
||||||
|
fill_grid_with_event_data (self, GTK_GRID (grid), ical_component);
|
||||||
|
gtk_container_add (GTK_CONTAINER (row), grid);
|
||||||
|
|
||||||
|
gtk_list_box_insert (self->events_listbox, row, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GPtrArray*
|
||||||
|
filter_event_components (ICalComponent *component)
|
||||||
|
{
|
||||||
|
g_autoptr (GPtrArray) event_components = NULL;
|
||||||
|
ICalComponent *aux;
|
||||||
|
|
||||||
|
if (!component)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
event_components = g_ptr_array_new_full (20, g_object_unref);
|
||||||
|
aux = i_cal_component_get_first_real_component (component);
|
||||||
|
while (aux)
|
||||||
|
{
|
||||||
|
g_ptr_array_add (event_components, g_object_ref (aux));
|
||||||
|
aux = i_cal_component_get_next_component (component, I_CAL_VEVENT_COMPONENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_steal_pointer (&event_components);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_file (GcalImportFileRow *self)
|
||||||
|
{
|
||||||
|
g_autofree gchar *basename = NULL;
|
||||||
|
|
||||||
|
basename = g_file_get_basename (self->file);
|
||||||
|
gtk_label_set_label (self->filename_label, basename);
|
||||||
|
|
||||||
|
gcal_importer_import_file (self->file,
|
||||||
|
self->cancellable,
|
||||||
|
read_calendar_finished_cb,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callbacks
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_calendar_finished_cb (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GPtrArray) event_components = NULL;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
g_autofree gchar *subtitle = NULL;
|
||||||
|
ICalComponent *component;
|
||||||
|
GcalImportFileRow *self;
|
||||||
|
|
||||||
|
self = GCAL_IMPORT_FILE_ROW (user_data);
|
||||||
|
component = gcal_importer_import_file_finish (res, &error);
|
||||||
|
event_components = filter_event_components (component);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (self), !error && event_components && event_components->len > 0);
|
||||||
|
|
||||||
|
if (error || !event_components || event_components->len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
add_events_to_listbox (self, event_components);
|
||||||
|
|
||||||
|
self->ical_components = g_ptr_array_ref (event_components);
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[FILE_LOADED], 0, event_components);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GObject overrides
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_file_row_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GcalImportFileRow *self = (GcalImportFileRow *)object;
|
||||||
|
|
||||||
|
g_cancellable_cancel (self->cancellable);
|
||||||
|
g_clear_object (&self->cancellable);
|
||||||
|
g_clear_object (&self->file);
|
||||||
|
g_clear_pointer (&self->ical_components, g_ptr_array_unref);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gcal_import_file_row_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_file_row_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GcalImportFileRow *self = GCAL_IMPORT_FILE_ROW (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_FILE:
|
||||||
|
g_value_set_object (value, self->file);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_file_row_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GcalImportFileRow *self = GCAL_IMPORT_FILE_ROW (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_FILE:
|
||||||
|
g_assert (self->file == NULL);
|
||||||
|
self->file = g_value_dup_object (value);
|
||||||
|
setup_file (self);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_file_row_class_init (GcalImportFileRowClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gcal_import_file_row_finalize;
|
||||||
|
object_class->get_property = gcal_import_file_row_get_property;
|
||||||
|
object_class->set_property = gcal_import_file_row_set_property;
|
||||||
|
|
||||||
|
signals[FILE_LOADED] = g_signal_new ("file-loaded",
|
||||||
|
GCAL_TYPE_IMPORT_FILE_ROW,
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0, NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__BOXED,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1,
|
||||||
|
G_TYPE_PTR_ARRAY);
|
||||||
|
|
||||||
|
properties[PROP_FILE] = g_param_spec_object ("file",
|
||||||
|
"An ICS file",
|
||||||
|
"An ICS file",
|
||||||
|
G_TYPE_FILE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/gui/importer/gcal-import-file-row.ui");
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportFileRow, events_listbox);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GcalImportFileRow, filename_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gcal_import_file_row_init (GcalImportFileRow *self)
|
||||||
|
{
|
||||||
|
self->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
gcal_import_file_row_new (GFile *file,
|
||||||
|
GtkSizeGroup *title_sizegroup)
|
||||||
|
{
|
||||||
|
GcalImportFileRow *self;
|
||||||
|
|
||||||
|
self = g_object_new (GCAL_TYPE_IMPORT_FILE_ROW,
|
||||||
|
"file", file,
|
||||||
|
NULL);
|
||||||
|
self->title_sizegroup = title_sizegroup;
|
||||||
|
|
||||||
|
return (GtkWidget*) self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gcal_import_file_row_show_filename (GcalImportFileRow *self)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GCAL_IS_IMPORT_FILE_ROW (self));
|
||||||
|
|
||||||
|
gtk_widget_show (GTK_WIDGET (self->filename_label));
|
||||||
|
}
|
||||||
|
|
||||||
|
GPtrArray*
|
||||||
|
gcal_import_file_row_get_ical_components (GcalImportFileRow *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GCAL_IS_IMPORT_FILE_ROW (self), NULL);
|
||||||
|
|
||||||
|
return self->ical_components;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* gcal-import-file-row.h
|
||||||
|
*
|
||||||
|
* Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GCAL_TYPE_IMPORT_FILE_ROW (gcal_import_file_row_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (GcalImportFileRow, gcal_import_file_row, GCAL, IMPORT_FILE_ROW, GtkListBoxRow)
|
||||||
|
|
||||||
|
GtkWidget* gcal_import_file_row_new (GFile *file,
|
||||||
|
GtkSizeGroup *title_sizegroup);
|
||||||
|
|
||||||
|
void gcal_import_file_row_show_filename (GcalImportFileRow *self);
|
||||||
|
|
||||||
|
GPtrArray* gcal_import_file_row_get_ical_components (GcalImportFileRow *self);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="GcalImportFileRow" parent="GtkListBoxRow">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="activatable">False</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
|
||||||
|
<!-- File name label -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="filename_label">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="margin-top">12</property>
|
||||||
|
<property name="xalign">0.0</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold" />
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<!-- Event preview listbox -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox" id="events_listbox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
<style>
|
||||||
|
<class name="content" />
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
/* gcal-importer.c
|
||||||
|
*
|
||||||
|
* Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gcal-importer.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
G_DEFINE_QUARK (ICalErrorEnum, i_cal_error);
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
i_cal_error_enum_to_string (ICalErrorEnum ical_error)
|
||||||
|
{
|
||||||
|
switch (ical_error)
|
||||||
|
{
|
||||||
|
case I_CAL_NO_ERROR:
|
||||||
|
return _("No error");
|
||||||
|
|
||||||
|
case I_CAL_BADARG_ERROR:
|
||||||
|
return _("Bad argument to function");
|
||||||
|
|
||||||
|
case I_CAL_NEWFAILED_ERROR:
|
||||||
|
case I_CAL_ALLOCATION_ERROR:
|
||||||
|
return _("Failed to allocate a new object in memory");
|
||||||
|
|
||||||
|
case I_CAL_MALFORMEDDATA_ERROR:
|
||||||
|
return _("File is malformed, invalid, or corrupted");
|
||||||
|
|
||||||
|
case I_CAL_PARSE_ERROR:
|
||||||
|
return _("Failed to parse the calendar contents");
|
||||||
|
|
||||||
|
case I_CAL_FILE_ERROR:
|
||||||
|
return _("Failed to read file");
|
||||||
|
|
||||||
|
case I_CAL_INTERNAL_ERROR:
|
||||||
|
case I_CAL_USAGE_ERROR:
|
||||||
|
case I_CAL_UNIMPLEMENTED_ERROR:
|
||||||
|
case I_CAL_UNKNOWN_ERROR:
|
||||||
|
default:
|
||||||
|
return _("Internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_file_in_thread (GTask *task,
|
||||||
|
gpointer source_object,
|
||||||
|
gpointer task_data,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
g_autoptr (GFileInfo) file_info = NULL;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
g_autofree gchar *contents = NULL;
|
||||||
|
g_autofree gchar *path = NULL;
|
||||||
|
ICalComponent *component;
|
||||||
|
ICalErrorEnum ical_error;
|
||||||
|
gsize length;
|
||||||
|
GFile *file;
|
||||||
|
|
||||||
|
file = task_data;
|
||||||
|
file_info = g_file_query_info (file,
|
||||||
|
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
|
||||||
|
G_FILE_QUERY_INFO_NONE,
|
||||||
|
cancellable,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (g_file_info_get_content_type (file_info), "text/calendar") != 0)
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
G_FILE_ERROR_FAILED,
|
||||||
|
"%s",
|
||||||
|
_("File is not an iCalendar (.ics) file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = g_file_get_path (file);
|
||||||
|
g_file_get_contents (path, &contents, &length, &error);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
component = i_cal_parser_parse_string (contents);
|
||||||
|
ical_error = i_cal_errno_return ();
|
||||||
|
|
||||||
|
if (ical_error != I_CAL_NO_ERROR)
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task,
|
||||||
|
I_CAL_ERROR,
|
||||||
|
ical_error,
|
||||||
|
"%s",
|
||||||
|
i_cal_error_enum_to_string (ical_error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!component)
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task,
|
||||||
|
I_CAL_ERROR,
|
||||||
|
I_CAL_MALFORMEDDATA_ERROR,
|
||||||
|
"%s",
|
||||||
|
i_cal_error_enum_to_string (I_CAL_MALFORMEDDATA_ERROR));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_task_return_pointer (task, g_object_ref (component), g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gcal_importer_import_file:
|
||||||
|
* @file: a #GFile
|
||||||
|
* @cancellable: (nullable): a #GCancellable
|
||||||
|
* @callback: a #GAsyncReadyCallback to execute upon completion
|
||||||
|
* @user_data: closure data for @callback
|
||||||
|
*
|
||||||
|
* Import an ICS file.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gcal_importer_import_file (GFile *file,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
task = g_task_new (NULL, cancellable, callback, user_data);
|
||||||
|
g_task_set_task_data (task, g_object_ref (file), g_object_unref);
|
||||||
|
g_task_set_source_tag (task, gcal_importer_import_file);
|
||||||
|
g_task_run_in_thread (task, read_file_in_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gcal_importer_do_something_finish:
|
||||||
|
* @result: a #GAsyncResult provided to callback
|
||||||
|
* @error: a location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Returns: (nullable): an #ICalComponent
|
||||||
|
*/
|
||||||
|
ICalComponent*
|
||||||
|
gcal_importer_import_file_finish (GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
|
||||||
|
|
||||||
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/* gcal-importer.h
|
||||||
|
*
|
||||||
|
* Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include <libecal/libecal.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define I_CAL_ERROR i_cal_error_quark ()
|
||||||
|
GQuark i_cal_error_quark (void);
|
||||||
|
|
||||||
|
void gcal_importer_import_file (GFile *file,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
ICalComponent* gcal_importer_import_file_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/org/gnome/calendar/ui/gui/importer">
|
||||||
|
<file compressed="true">gcal-import-dialog.ui</file>
|
||||||
|
<file compressed="true">gcal-import-file-row.ui</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
calendar_incs += include_directories('.')
|
||||||
|
|
||||||
|
built_sources += gnome.compile_resources(
|
||||||
|
'importer-resources',
|
||||||
|
'importer.gresource.xml',
|
||||||
|
c_name: 'importer',
|
||||||
|
)
|
||||||
|
|
||||||
|
sources += files(
|
||||||
|
'gcal-import-dialog.c',
|
||||||
|
'gcal-import-file-row.c',
|
||||||
|
'gcal-importer.c',
|
||||||
|
)
|
||||||
@@ -2,6 +2,7 @@ subdir('calendar-management')
|
|||||||
subdir('event-editor')
|
subdir('event-editor')
|
||||||
subdir('gtk')
|
subdir('gtk')
|
||||||
subdir('icons')
|
subdir('icons')
|
||||||
|
subdir('importer')
|
||||||
subdir('views')
|
subdir('views')
|
||||||
|
|
||||||
calendar_incs += include_directories('.')
|
calendar_incs += include_directories('.')
|
||||||
|
|||||||
Reference in New Issue
Block a user