Get events from Evolution
This commit copies existing and deployed (thus, working!) GPLv2 code from gnome-panel into src/calendar-client. Please keep in sync. Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
parent
374a88366b
commit
41b0e0832e
@ -66,6 +66,10 @@ GJS_MIN_VERSION=0.7.8
|
|||||||
MUTTER_MIN_VERSION=2.91.4
|
MUTTER_MIN_VERSION=2.91.4
|
||||||
GTK_MIN_VERSION=2.91.7
|
GTK_MIN_VERSION=2.91.7
|
||||||
GIO_MIN_VERSION=2.25.9
|
GIO_MIN_VERSION=2.25.9
|
||||||
|
LIBECAL_REQUIRED=1.6.0
|
||||||
|
LIBEDATASERVER_REQUIRED=1.2.0
|
||||||
|
LIBEDATASERVERUI_REQUIRED=1.2.0
|
||||||
|
|
||||||
|
|
||||||
# Collect more than 20 libraries for a prize!
|
# Collect more than 20 libraries for a prize!
|
||||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
|
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
|
||||||
@ -113,6 +117,10 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 2.90.0],
|
|||||||
AC_SUBST([HAVE_BLUETOOTH],[0])
|
AC_SUBST([HAVE_BLUETOOTH],[0])
|
||||||
AC_MSG_RESULT([no])])
|
AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBECAL, libecal-1.2 >= $LIBECAL_REQUIRED libedataserver-1.2 >= $LIBEDATASERVER_REQUIRED libedataserverui-1.2 >= $LIBEDATASERVERUI_REQUIRED)
|
||||||
|
AC_SUBST(LIBECAL_CFLAGS)
|
||||||
|
AC_SUBST(LIBECAL_LIBS)
|
||||||
|
|
||||||
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
|
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
|
||||||
# FIXME: metacity-plugins.pc should point directly to its .gir file
|
# FIXME: metacity-plugins.pc should point directly to its .gir file
|
||||||
MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins`
|
MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins`
|
||||||
|
@ -175,6 +175,9 @@ EmptyEventSource.prototype = {
|
|||||||
_init: function() {
|
_init: function() {
|
||||||
},
|
},
|
||||||
|
|
||||||
|
requestRange: function(begin, end) {
|
||||||
|
},
|
||||||
|
|
||||||
getEvents: function(begin, end) {
|
getEvents: function(begin, end) {
|
||||||
let result = [];
|
let result = [];
|
||||||
return result;
|
return result;
|
||||||
@ -199,12 +202,16 @@ EvolutionEventSource.prototype = {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
requestRange: function(begin, end) {
|
||||||
|
this._native.request_range(begin.getTime(), end.getTime());
|
||||||
|
},
|
||||||
|
|
||||||
getEvents: function(begin, end) {
|
getEvents: function(begin, end) {
|
||||||
let result = [];
|
let result = [];
|
||||||
let nativeEvents = this._native.get_events(begin.getTime(), end.getTime());
|
let nativeEvents = this._native.get_events(begin.getTime(), end.getTime());
|
||||||
for (let n = 0; n < nativeEvents.length; n++) {
|
for (let n = 0; n < nativeEvents.length; n++) {
|
||||||
let nativeEvent = nativeEvents[n];
|
let nativeEvent = nativeEvents[n];
|
||||||
result.push(new CalendarEvent(new Date(nativeEvent.date), nativeEvent.summary, nativeEvent.all_day));
|
result.push(new CalendarEvent(new Date(nativeEvent.msec_begin), nativeEvent.summary, nativeEvent.all_day));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
@ -296,6 +303,9 @@ FakeEventSource.prototype = {
|
|||||||
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
|
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
requestRange: function(begin, end) {
|
||||||
|
},
|
||||||
|
|
||||||
getEvents: function(begin, end) {
|
getEvents: function(begin, end) {
|
||||||
let result = [];
|
let result = [];
|
||||||
//log('begin:' + begin);
|
//log('begin:' + begin);
|
||||||
@ -332,7 +342,7 @@ Signals.addSignalMethods(FakeEventSource.prototype);
|
|||||||
|
|
||||||
// Calendar:
|
// Calendar:
|
||||||
// @eventSource: is an object implementing the EventSource API, e.g. the
|
// @eventSource: is an object implementing the EventSource API, e.g. the
|
||||||
// getEvents(), hasEvents() methods and the ::changed signal.
|
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
|
||||||
function Calendar(eventSource) {
|
function Calendar(eventSource) {
|
||||||
this._init(eventSource);
|
this._init(eventSource);
|
||||||
}
|
}
|
||||||
@ -516,13 +526,14 @@ Calendar.prototype = {
|
|||||||
children[i].destroy();
|
children[i].destroy();
|
||||||
|
|
||||||
// Start at the beginning of the week before the start of the month
|
// Start at the beginning of the week before the start of the month
|
||||||
let iter = new Date(this.selectedDate);
|
let beginDate = new Date(this.selectedDate);
|
||||||
iter.setDate(1);
|
beginDate.setDate(1);
|
||||||
iter.setSeconds(0);
|
beginDate.setSeconds(0);
|
||||||
iter.setHours(12);
|
beginDate.setHours(12);
|
||||||
let daysToWeekStart = (7 + iter.getDay() - this._weekStart) % 7;
|
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
|
||||||
iter.setTime(iter.getTime() - daysToWeekStart * MSECS_IN_DAY);
|
beginDate.setTime(beginDate.getTime() - daysToWeekStart * MSECS_IN_DAY);
|
||||||
|
|
||||||
|
let iter = new Date(beginDate);
|
||||||
let row = 2;
|
let row = 2;
|
||||||
while (true) {
|
while (true) {
|
||||||
let button = new St.Button({ label: iter.getDate().toString() });
|
let button = new St.Button({ label: iter.getDate().toString() });
|
||||||
@ -574,6 +585,9 @@ Calendar.prototype = {
|
|||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Signal to the event source that we are interested in events
|
||||||
|
// only from this date range
|
||||||
|
this._eventSource.requestRange(beginDate, iter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ include Makefile-gdmuser.am
|
|||||||
include Makefile-st.am
|
include Makefile-st.am
|
||||||
include Makefile-tray.am
|
include Makefile-tray.am
|
||||||
include Makefile-gvc.am
|
include Makefile-gvc.am
|
||||||
|
include Makefile-calendar-client.am
|
||||||
|
|
||||||
gnome_shell_cflags = \
|
gnome_shell_cflags = \
|
||||||
$(MUTTER_PLUGIN_CFLAGS) \
|
$(MUTTER_PLUGIN_CFLAGS) \
|
||||||
@ -214,7 +215,9 @@ libgnome_shell_la_LIBADD = \
|
|||||||
libst-1.0.la \
|
libst-1.0.la \
|
||||||
libgdmuser-1.0.la \
|
libgdmuser-1.0.la \
|
||||||
libtray.la \
|
libtray.la \
|
||||||
libgvc.la
|
libgvc.la \
|
||||||
|
libcalendar-client.la \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||||
|
|
||||||
|
1
src/calendar-client/README
Normal file
1
src/calendar-client/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
Please keep in sync with gnome-panel.
|
2169
src/calendar-client/calendar-client.c
Normal file
2169
src/calendar-client/calendar-client.c
Normal file
File diff suppressed because it is too large
Load Diff
149
src/calendar-client/calendar-client.h
Normal file
149
src/calendar-client/calendar-client.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Mark McLoughlin <mark@skynet.ie>
|
||||||
|
* William Jon McCann <mccann@jhu.edu>
|
||||||
|
* Martin Grimme <martin@pycage.de>
|
||||||
|
* Christian Kellner <gicmo@xatom.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CALENDAR_CLIENT_H__
|
||||||
|
#define __CALENDAR_CLIENT_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CALENDAR_EVENT_APPOINTMENT = 1 << 0,
|
||||||
|
CALENDAR_EVENT_TASK = 1 << 1,
|
||||||
|
CALENDAR_EVENT_ALL = (1 << 2) - 1
|
||||||
|
} CalendarEventType;
|
||||||
|
|
||||||
|
#define CALENDAR_TYPE_CLIENT (calendar_client_get_type ())
|
||||||
|
#define CALENDAR_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CALENDAR_TYPE_CLIENT, CalendarClient))
|
||||||
|
#define CALENDAR_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CALENDAR_TYPE_CLIENT, CalendarClientClass))
|
||||||
|
#define CALENDAR_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CALENDAR_TYPE_CLIENT))
|
||||||
|
#define CALENDAR_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CALENDAR_TYPE_CLIENT))
|
||||||
|
#define CALENDAR_CLIENT_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), CALENDAR_TYPE_CLIENT, CalendarClientClass))
|
||||||
|
|
||||||
|
typedef struct _CalendarClient CalendarClient;
|
||||||
|
typedef struct _CalendarClientClass CalendarClientClass;
|
||||||
|
typedef struct _CalendarClientPrivate CalendarClientPrivate;
|
||||||
|
|
||||||
|
struct _CalendarClient
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
CalendarClientPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _CalendarClientClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* appointments_changed) (CalendarClient *client);
|
||||||
|
void (* tasks_changed) (CalendarClient *client);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
time_t start_time;
|
||||||
|
time_t end_time;
|
||||||
|
} CalendarOccurrence;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *uid;
|
||||||
|
char *rid;
|
||||||
|
char *uri;
|
||||||
|
char *summary;
|
||||||
|
char *description;
|
||||||
|
char *color_string;
|
||||||
|
time_t start_time;
|
||||||
|
time_t end_time;
|
||||||
|
guint is_all_day : 1;
|
||||||
|
|
||||||
|
/* Only used internally */
|
||||||
|
GSList *occurrences;
|
||||||
|
} CalendarAppointment;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *uid;
|
||||||
|
char *summary;
|
||||||
|
char *description;
|
||||||
|
char *color_string;
|
||||||
|
char *url;
|
||||||
|
time_t start_time;
|
||||||
|
time_t due_time;
|
||||||
|
guint percent_complete;
|
||||||
|
time_t completed_time;
|
||||||
|
int priority;
|
||||||
|
} CalendarTask;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
CalendarAppointment appointment;
|
||||||
|
CalendarTask task;
|
||||||
|
} event;
|
||||||
|
CalendarEventType type;
|
||||||
|
} CalendarEvent;
|
||||||
|
|
||||||
|
#define CALENDAR_EVENT(e) ((CalendarEvent *)(e))
|
||||||
|
#define CALENDAR_APPOINTMENT(e) ((CalendarAppointment *)(e))
|
||||||
|
#define CALENDAR_TASK(e) ((CalendarTask *)(e))
|
||||||
|
|
||||||
|
typedef void (* CalendarDayIter) (CalendarClient *client,
|
||||||
|
guint day,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
|
||||||
|
GType calendar_client_get_type (void) G_GNUC_CONST;
|
||||||
|
CalendarClient *calendar_client_new (void);
|
||||||
|
|
||||||
|
void calendar_client_get_date (CalendarClient *client,
|
||||||
|
guint *year,
|
||||||
|
guint *month,
|
||||||
|
guint *day);
|
||||||
|
void calendar_client_select_month (CalendarClient *client,
|
||||||
|
guint month,
|
||||||
|
guint year);
|
||||||
|
void calendar_client_select_day (CalendarClient *client,
|
||||||
|
guint day);
|
||||||
|
|
||||||
|
GSList *calendar_client_get_events (CalendarClient *client,
|
||||||
|
CalendarEventType event_mask);
|
||||||
|
void calendar_client_foreach_appointment_day (CalendarClient *client,
|
||||||
|
CalendarDayIter iter_func,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
void calendar_client_set_task_completed (CalendarClient *client,
|
||||||
|
char *task_uid,
|
||||||
|
gboolean task_completed,
|
||||||
|
guint percent_complete);
|
||||||
|
|
||||||
|
void calendar_event_free (CalendarEvent *event);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CALENDAR_CLIENT_H__ */
|
52
src/calendar-client/calendar-debug.h
Normal file
52
src/calendar-client/calendar-debug.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Mark McLoughlin <mark@skynet.ie>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CALENDAR_DEBUG_H__
|
||||||
|
#define __CALENDAR_DEBUG_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifdef CALENDAR_ENABLE_DEBUG
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef G_HAVE_ISO_VARARGS
|
||||||
|
# define dprintf(...) fprintf (stderr, __VA_ARGS__);
|
||||||
|
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||||
|
# define dprintf(args...) fprintf (stderr, args);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* if !defined (CALENDAR_DEBUG) */
|
||||||
|
|
||||||
|
#ifdef G_HAVE_ISO_VARARGS
|
||||||
|
# define dprintf(...)
|
||||||
|
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||||
|
# define dprintf(args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CALENDAR_ENABLE_DEBUG */
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CALENDAR_DEBUG_H__ */
|
658
src/calendar-client/calendar-sources.c
Normal file
658
src/calendar-client/calendar-sources.c
Normal file
@ -0,0 +1,658 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Mark McLoughlin <mark@skynet.ie>
|
||||||
|
* William Jon McCann <mccann@jhu.edu>
|
||||||
|
* Martin Grimme <martin@pycage.de>
|
||||||
|
* Christian Kellner <gicmo@xatom.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "calendar-sources.h"
|
||||||
|
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <gconf/gconf-client.h>
|
||||||
|
#define HANDLE_LIBICAL_MEMORY
|
||||||
|
#include <libecal/e-cal.h>
|
||||||
|
#include <libedataserver/e-source-list.h>
|
||||||
|
#include <libedataserverui/e-passwords.h>
|
||||||
|
|
||||||
|
#undef CALENDAR_ENABLE_DEBUG
|
||||||
|
#include "calendar-debug.h"
|
||||||
|
|
||||||
|
#ifndef _
|
||||||
|
#define _(x) gettext(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef N_
|
||||||
|
#define N_(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CALENDAR_SOURCES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CALENDAR_TYPE_SOURCES, CalendarSourcesPrivate))
|
||||||
|
|
||||||
|
#define CALENDAR_SOURCES_EVO_DIR "/apps/evolution"
|
||||||
|
#define CALENDAR_SOURCES_APPOINTMENT_SOURCES_KEY CALENDAR_SOURCES_EVO_DIR "/calendar/sources"
|
||||||
|
#define CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR CALENDAR_SOURCES_EVO_DIR "/calendar/display"
|
||||||
|
#define CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_KEY CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR "/selected_calendars"
|
||||||
|
#define CALENDAR_SOURCES_TASK_SOURCES_KEY CALENDAR_SOURCES_EVO_DIR "/tasks/sources"
|
||||||
|
#define CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR CALENDAR_SOURCES_EVO_DIR "/calendar/tasks"
|
||||||
|
#define CALENDAR_SOURCES_SELECTED_TASK_SOURCES_KEY CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR "/selected_tasks"
|
||||||
|
|
||||||
|
typedef struct _CalendarSourceData CalendarSourceData;
|
||||||
|
|
||||||
|
struct _CalendarSourceData
|
||||||
|
{
|
||||||
|
ECalSourceType source_type;
|
||||||
|
CalendarSources *sources;
|
||||||
|
guint changed_signal;
|
||||||
|
|
||||||
|
GSList *clients;
|
||||||
|
GSList *selected_sources;
|
||||||
|
ESourceList *esource_list;
|
||||||
|
|
||||||
|
guint selected_sources_listener;
|
||||||
|
char *selected_sources_dir;
|
||||||
|
|
||||||
|
guint timeout_id;
|
||||||
|
|
||||||
|
guint loaded : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _CalendarSourcesPrivate
|
||||||
|
{
|
||||||
|
CalendarSourceData appointment_sources;
|
||||||
|
CalendarSourceData task_sources;
|
||||||
|
|
||||||
|
GConfClient *gconf_client;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void calendar_sources_class_init (CalendarSourcesClass *klass);
|
||||||
|
static void calendar_sources_init (CalendarSources *sources);
|
||||||
|
static void calendar_sources_finalize (GObject *object);
|
||||||
|
|
||||||
|
static void backend_died_cb (ECal *client, CalendarSourceData *source_data);
|
||||||
|
static void calendar_sources_esource_list_changed (ESourceList *source_list,
|
||||||
|
CalendarSourceData *source_data);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
APPOINTMENT_SOURCES_CHANGED,
|
||||||
|
TASK_SOURCES_CHANGED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static GObjectClass *parent_class = NULL;
|
||||||
|
static CalendarSources *calendar_sources_singleton = NULL;
|
||||||
|
|
||||||
|
GType
|
||||||
|
calendar_sources_get_type (void)
|
||||||
|
{
|
||||||
|
static GType sources_type = 0;
|
||||||
|
|
||||||
|
if (!sources_type)
|
||||||
|
{
|
||||||
|
static const GTypeInfo sources_info =
|
||||||
|
{
|
||||||
|
sizeof (CalendarSourcesClass),
|
||||||
|
NULL, /* base_init */
|
||||||
|
NULL, /* base_finalize */
|
||||||
|
(GClassInitFunc) calendar_sources_class_init,
|
||||||
|
NULL, /* class_finalize */
|
||||||
|
NULL, /* class_data */
|
||||||
|
sizeof (CalendarSources),
|
||||||
|
0, /* n_preallocs */
|
||||||
|
(GInstanceInitFunc) calendar_sources_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
sources_type = g_type_register_static (G_TYPE_OBJECT,
|
||||||
|
"CalendarSources",
|
||||||
|
&sources_info, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_class_init (CalendarSourcesClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = calendar_sources_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (CalendarSourcesPrivate));
|
||||||
|
|
||||||
|
signals [APPOINTMENT_SOURCES_CHANGED] =
|
||||||
|
g_signal_new ("appointment-sources-changed",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (CalendarSourcesClass,
|
||||||
|
appointment_sources_changed),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
|
||||||
|
signals [TASK_SOURCES_CHANGED] =
|
||||||
|
g_signal_new ("task-sources-changed",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (CalendarSourcesClass,
|
||||||
|
task_sources_changed),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_init (CalendarSources *sources)
|
||||||
|
{
|
||||||
|
sources->priv = CALENDAR_SOURCES_GET_PRIVATE (sources);
|
||||||
|
|
||||||
|
sources->priv->appointment_sources.source_type = E_CAL_SOURCE_TYPE_EVENT;
|
||||||
|
sources->priv->appointment_sources.sources = sources;
|
||||||
|
sources->priv->appointment_sources.changed_signal = signals [APPOINTMENT_SOURCES_CHANGED];
|
||||||
|
sources->priv->appointment_sources.timeout_id = 0;
|
||||||
|
|
||||||
|
sources->priv->task_sources.source_type = E_CAL_SOURCE_TYPE_TODO;
|
||||||
|
sources->priv->task_sources.sources = sources;
|
||||||
|
sources->priv->task_sources.changed_signal = signals [TASK_SOURCES_CHANGED];
|
||||||
|
sources->priv->task_sources.timeout_id = 0;
|
||||||
|
|
||||||
|
sources->priv->gconf_client = gconf_client_get_default ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_finalize_source_data (CalendarSources *sources,
|
||||||
|
CalendarSourceData *source_data)
|
||||||
|
{
|
||||||
|
if (source_data->loaded)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
if (source_data->selected_sources_dir)
|
||||||
|
{
|
||||||
|
gconf_client_remove_dir (sources->priv->gconf_client,
|
||||||
|
source_data->selected_sources_dir,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_free (source_data->selected_sources_dir);
|
||||||
|
source_data->selected_sources_dir = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source_data->selected_sources_listener)
|
||||||
|
{
|
||||||
|
gconf_client_notify_remove (sources->priv->gconf_client,
|
||||||
|
source_data->selected_sources_listener);
|
||||||
|
source_data->selected_sources_listener = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = source_data->clients; l; l = l->next)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
|
||||||
|
G_CALLBACK (backend_died_cb),
|
||||||
|
source_data);
|
||||||
|
g_object_unref (l->data);
|
||||||
|
}
|
||||||
|
g_slist_free (source_data->clients);
|
||||||
|
source_data->clients = NULL;
|
||||||
|
|
||||||
|
if (source_data->esource_list)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (source_data->esource_list,
|
||||||
|
G_CALLBACK (calendar_sources_esource_list_changed),
|
||||||
|
source_data);
|
||||||
|
g_object_unref (source_data->esource_list);
|
||||||
|
}
|
||||||
|
source_data->esource_list = NULL;
|
||||||
|
|
||||||
|
for (l = source_data->selected_sources; l; l = l->next)
|
||||||
|
g_free (l->data);
|
||||||
|
g_slist_free (source_data->selected_sources);
|
||||||
|
source_data->selected_sources = NULL;
|
||||||
|
|
||||||
|
if (source_data->timeout_id != 0)
|
||||||
|
{
|
||||||
|
g_source_remove (source_data->timeout_id);
|
||||||
|
source_data->timeout_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
source_data->loaded = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
CalendarSources *sources = CALENDAR_SOURCES (object);
|
||||||
|
|
||||||
|
calendar_sources_finalize_source_data (sources, &sources->priv->appointment_sources);
|
||||||
|
calendar_sources_finalize_source_data (sources, &sources->priv->task_sources);
|
||||||
|
|
||||||
|
if (sources->priv->gconf_client)
|
||||||
|
g_object_unref (sources->priv->gconf_client);
|
||||||
|
sources->priv->gconf_client = NULL;
|
||||||
|
|
||||||
|
if (G_OBJECT_CLASS (parent_class)->finalize)
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarSources *
|
||||||
|
calendar_sources_get (void)
|
||||||
|
{
|
||||||
|
gpointer singleton_location = &calendar_sources_singleton;
|
||||||
|
|
||||||
|
if (calendar_sources_singleton)
|
||||||
|
return g_object_ref (calendar_sources_singleton);
|
||||||
|
|
||||||
|
calendar_sources_singleton = g_object_new (CALENDAR_TYPE_SOURCES, NULL);
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (calendar_sources_singleton),
|
||||||
|
singleton_location);
|
||||||
|
|
||||||
|
return calendar_sources_singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_source_selected (ESource *esource,
|
||||||
|
GSList *selected_sources)
|
||||||
|
{
|
||||||
|
const char *uid;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
uid = e_source_peek_uid (esource);
|
||||||
|
|
||||||
|
for (l = selected_sources; l; l = l->next)
|
||||||
|
{
|
||||||
|
const char *source = l->data;
|
||||||
|
|
||||||
|
if (!strcmp (source, uid))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
auth_func_cb (ECal *ecal,
|
||||||
|
const char *prompt,
|
||||||
|
const char *key,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ESource *source;
|
||||||
|
const gchar *auth_domain;
|
||||||
|
const gchar *component_name;
|
||||||
|
|
||||||
|
source = e_cal_get_source (ecal);
|
||||||
|
auth_domain = e_source_get_property (source, "auth-domain");
|
||||||
|
component_name = auth_domain ? auth_domain : "Calendar";
|
||||||
|
|
||||||
|
return e_passwords_get_password (component_name, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The clients are just created here but not loaded */
|
||||||
|
static ECal *
|
||||||
|
get_ecal_from_source (ESource *esource,
|
||||||
|
ECalSourceType source_type,
|
||||||
|
GSList *existing_clients)
|
||||||
|
{
|
||||||
|
ECal *retval;
|
||||||
|
|
||||||
|
if (existing_clients)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = existing_clients; l; l = l->next)
|
||||||
|
{
|
||||||
|
ECal *client = E_CAL (l->data);
|
||||||
|
|
||||||
|
if (e_source_equal (esource, e_cal_get_source (client)))
|
||||||
|
{
|
||||||
|
dprintf (" load_esource: found existing source ... returning that\n");
|
||||||
|
|
||||||
|
return g_object_ref (client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = e_cal_new (esource, source_type);
|
||||||
|
if (!retval)
|
||||||
|
{
|
||||||
|
g_warning ("Could not load source '%s' from '%s'\n",
|
||||||
|
e_source_peek_name (esource),
|
||||||
|
e_source_peek_relative_uri (esource));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
e_cal_set_auth_func (retval, auth_func_cb, NULL);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - Order doesn't matter
|
||||||
|
* - Can just compare object pointers since we
|
||||||
|
* re-use client connections
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
compare_ecal_lists (GSList *a,
|
||||||
|
GSList *b)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
if (g_slist_length (a) != g_slist_length (b))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (l = a; l; l = l->next)
|
||||||
|
{
|
||||||
|
if (!g_slist_find (b, l->data))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
debug_dump_selected_sources (GSList *selected_sources)
|
||||||
|
{
|
||||||
|
#ifdef CALENDAR_ENABLE_DEBUG
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
dprintf ("Selected sources:\n");
|
||||||
|
for (l = selected_sources; l; l = l->next)
|
||||||
|
{
|
||||||
|
char *source = l->data;
|
||||||
|
|
||||||
|
dprintf (" %s\n", source);
|
||||||
|
}
|
||||||
|
dprintf ("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
debug_dump_ecal_list (GSList *ecal_list)
|
||||||
|
{
|
||||||
|
#ifdef CALENDAR_ENABLE_DEBUG
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
dprintf ("Loaded clients:\n");
|
||||||
|
for (l = ecal_list; l; l = l->next)
|
||||||
|
{
|
||||||
|
ECal *client = l->data;
|
||||||
|
ESource *source = e_cal_get_source (client);
|
||||||
|
|
||||||
|
dprintf (" %s %s %s\n",
|
||||||
|
e_source_peek_uid (source),
|
||||||
|
e_source_peek_name (source),
|
||||||
|
e_cal_get_uri (client));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_load_esource_list (CalendarSourceData *source_data);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
backend_restart (gpointer data)
|
||||||
|
{
|
||||||
|
CalendarSourceData *source_data = data;
|
||||||
|
|
||||||
|
calendar_sources_load_esource_list (source_data);
|
||||||
|
|
||||||
|
source_data->timeout_id = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
backend_died_cb (ECal *client, CalendarSourceData *source_data)
|
||||||
|
{
|
||||||
|
const char *uristr;
|
||||||
|
|
||||||
|
source_data->clients = g_slist_remove (source_data->clients, client);
|
||||||
|
if (g_slist_length (source_data->clients) < 1)
|
||||||
|
{
|
||||||
|
g_slist_free (source_data->clients);
|
||||||
|
source_data->clients = NULL;
|
||||||
|
}
|
||||||
|
uristr = e_cal_get_uri (client);
|
||||||
|
g_warning ("The calendar backend for %s has crashed.", uristr);
|
||||||
|
|
||||||
|
if (source_data->timeout_id != 0)
|
||||||
|
{
|
||||||
|
g_source_remove (source_data->timeout_id);
|
||||||
|
source_data->timeout_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
source_data->timeout_id = g_timeout_add_seconds (2, backend_restart,
|
||||||
|
source_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_load_esource_list (CalendarSourceData *source_data)
|
||||||
|
{
|
||||||
|
GSList *clients = NULL;
|
||||||
|
GSList *groups, *l;
|
||||||
|
gboolean emit_signal = FALSE;
|
||||||
|
|
||||||
|
g_return_if_fail (source_data->esource_list != NULL);
|
||||||
|
|
||||||
|
debug_dump_selected_sources (source_data->selected_sources);
|
||||||
|
|
||||||
|
dprintf ("Source groups:\n");
|
||||||
|
groups = e_source_list_peek_groups (source_data->esource_list);
|
||||||
|
for (l = groups; l; l = l->next)
|
||||||
|
{
|
||||||
|
GSList *esources, *s;
|
||||||
|
|
||||||
|
dprintf (" %s\n", e_source_group_peek_uid (l->data));
|
||||||
|
dprintf (" sources:\n");
|
||||||
|
|
||||||
|
esources = e_source_group_peek_sources (l->data);
|
||||||
|
for (s = esources; s; s = s->next)
|
||||||
|
{
|
||||||
|
ESource *esource = E_SOURCE (s->data);
|
||||||
|
ECal *client;
|
||||||
|
|
||||||
|
dprintf (" type = '%s' uid = '%s', name = '%s', relative uri = '%s': \n",
|
||||||
|
source_data->source_type == E_CAL_SOURCE_TYPE_EVENT ? "appointment" : "task",
|
||||||
|
e_source_peek_uid (esource),
|
||||||
|
e_source_peek_name (esource),
|
||||||
|
e_source_peek_relative_uri (esource));
|
||||||
|
|
||||||
|
if (is_source_selected (esource, source_data->selected_sources) &&
|
||||||
|
(client = get_ecal_from_source (esource, source_data->source_type, source_data->clients)))
|
||||||
|
{
|
||||||
|
clients = g_slist_prepend (clients, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dprintf ("\n");
|
||||||
|
|
||||||
|
if (source_data->loaded &&
|
||||||
|
!compare_ecal_lists (source_data->clients, clients))
|
||||||
|
emit_signal = TRUE;
|
||||||
|
|
||||||
|
for (l = source_data->clients; l; l = l->next)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
|
||||||
|
G_CALLBACK (backend_died_cb),
|
||||||
|
source_data);
|
||||||
|
|
||||||
|
g_object_unref (l->data);
|
||||||
|
}
|
||||||
|
g_slist_free (source_data->clients);
|
||||||
|
source_data->clients = g_slist_reverse (clients);
|
||||||
|
|
||||||
|
/* connect to backend_died after we disconnected the previous signal
|
||||||
|
* handlers. If we do it before, we'll lose some handlers (for clients that
|
||||||
|
* were already there before) */
|
||||||
|
for (l = source_data->clients; l; l = l->next)
|
||||||
|
{
|
||||||
|
g_signal_connect (G_OBJECT (l->data), "backend_died",
|
||||||
|
G_CALLBACK (backend_died_cb), source_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emit_signal)
|
||||||
|
{
|
||||||
|
dprintf ("Emitting %s-sources-changed signal\n",
|
||||||
|
source_data->source_type == E_CAL_SOURCE_TYPE_EVENT ? "appointment" : "task");
|
||||||
|
g_signal_emit (source_data->sources, source_data->changed_signal, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_dump_ecal_list (source_data->clients);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_esource_list_changed (ESourceList *source_list,
|
||||||
|
CalendarSourceData *source_data)
|
||||||
|
|
||||||
|
{
|
||||||
|
dprintf ("ESourceList changed, reloading\n");
|
||||||
|
|
||||||
|
calendar_sources_load_esource_list (source_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_selected_sources_notify (GConfClient *client,
|
||||||
|
guint cnx_id,
|
||||||
|
GConfEntry *entry,
|
||||||
|
CalendarSourceData *source_data)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
if (!entry->value ||
|
||||||
|
entry->value->type != GCONF_VALUE_LIST ||
|
||||||
|
gconf_value_get_list_type (entry->value) != GCONF_VALUE_STRING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dprintf ("Selected sources key (%s) changed, reloading\n", entry->key);
|
||||||
|
|
||||||
|
for (l = source_data->selected_sources; l; l = l->next)
|
||||||
|
g_free (l->data);
|
||||||
|
source_data->selected_sources = NULL;
|
||||||
|
|
||||||
|
for (l = gconf_value_get_list (entry->value); l; l = l->next)
|
||||||
|
{
|
||||||
|
const char *source = gconf_value_get_string (l->data);
|
||||||
|
|
||||||
|
source_data->selected_sources =
|
||||||
|
g_slist_prepend (source_data->selected_sources,
|
||||||
|
g_strdup (source));
|
||||||
|
}
|
||||||
|
source_data->selected_sources =
|
||||||
|
g_slist_reverse (source_data->selected_sources);
|
||||||
|
|
||||||
|
calendar_sources_load_esource_list (source_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_sources_load_sources (CalendarSources *sources,
|
||||||
|
CalendarSourceData *source_data,
|
||||||
|
const char *sources_key,
|
||||||
|
const char *selected_sources_key,
|
||||||
|
const char *selected_sources_dir)
|
||||||
|
{
|
||||||
|
GConfClient *gconf_client;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
dprintf ("---------------------------\n");
|
||||||
|
dprintf ("Loading sources:\n");
|
||||||
|
dprintf (" sources_key: %s\n", sources_key);
|
||||||
|
dprintf (" selected_sources_key: %s\n", selected_sources_key);
|
||||||
|
dprintf (" selected_sources_dir: %s\n", selected_sources_dir);
|
||||||
|
|
||||||
|
gconf_client = sources->priv->gconf_client;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
source_data->selected_sources = gconf_client_get_list (gconf_client,
|
||||||
|
selected_sources_key,
|
||||||
|
GCONF_VALUE_STRING,
|
||||||
|
&error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to get selected sources from '%s': %s\n",
|
||||||
|
selected_sources_key,
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gconf_client_add_dir (gconf_client,
|
||||||
|
selected_sources_dir,
|
||||||
|
GCONF_CLIENT_PRELOAD_NONE,
|
||||||
|
NULL);
|
||||||
|
source_data->selected_sources_dir = g_strdup (selected_sources_dir);
|
||||||
|
|
||||||
|
source_data->selected_sources_listener =
|
||||||
|
gconf_client_notify_add (gconf_client,
|
||||||
|
selected_sources_dir,
|
||||||
|
(GConfClientNotifyFunc) calendar_sources_selected_sources_notify,
|
||||||
|
source_data, NULL, NULL);
|
||||||
|
|
||||||
|
source_data->esource_list = e_source_list_new_for_gconf (gconf_client, sources_key);
|
||||||
|
g_signal_connect (source_data->esource_list, "changed",
|
||||||
|
G_CALLBACK (calendar_sources_esource_list_changed),
|
||||||
|
source_data);
|
||||||
|
|
||||||
|
calendar_sources_load_esource_list (source_data);
|
||||||
|
|
||||||
|
source_data->loaded = TRUE;
|
||||||
|
|
||||||
|
dprintf ("---------------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *
|
||||||
|
calendar_sources_get_appointment_sources (CalendarSources *sources)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
|
||||||
|
|
||||||
|
if (!sources->priv->appointment_sources.loaded)
|
||||||
|
{
|
||||||
|
calendar_sources_load_sources (sources,
|
||||||
|
&sources->priv->appointment_sources,
|
||||||
|
CALENDAR_SOURCES_APPOINTMENT_SOURCES_KEY,
|
||||||
|
CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_KEY,
|
||||||
|
CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources->priv->appointment_sources.clients;
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *
|
||||||
|
calendar_sources_get_task_sources (CalendarSources *sources)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
|
||||||
|
|
||||||
|
if (!sources->priv->task_sources.loaded)
|
||||||
|
{
|
||||||
|
calendar_sources_load_sources (sources,
|
||||||
|
&sources->priv->task_sources,
|
||||||
|
CALENDAR_SOURCES_TASK_SOURCES_KEY,
|
||||||
|
CALENDAR_SOURCES_SELECTED_TASK_SOURCES_KEY,
|
||||||
|
CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources->priv->task_sources.clients;
|
||||||
|
}
|
66
src/calendar-client/calendar-sources.h
Normal file
66
src/calendar-client/calendar-sources.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Mark McLoughlin <mark@skynet.ie>
|
||||||
|
* William Jon McCann <mccann@jhu.edu>
|
||||||
|
* Martin Grimme <martin@pycage.de>
|
||||||
|
* Christian Kellner <gicmo@xatom.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CALENDAR_SOURCES_H__
|
||||||
|
#define __CALENDAR_SOURCES_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CALENDAR_TYPE_SOURCES (calendar_sources_get_type ())
|
||||||
|
#define CALENDAR_SOURCES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CALENDAR_TYPE_SOURCES, CalendarSources))
|
||||||
|
#define CALENDAR_SOURCES_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CALENDAR_TYPE_SOURCES, CalendarSourcesClass))
|
||||||
|
#define CALENDAR_IS_SOURCES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CALENDAR_TYPE_SOURCES))
|
||||||
|
#define CALENDAR_IS_SOURCES_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CALENDAR_TYPE_SOURCES))
|
||||||
|
#define CALENDAR_SOURCES_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), CALENDAR_TYPE_SOURCES, CalendarSourcesClass))
|
||||||
|
|
||||||
|
typedef struct _CalendarSources CalendarSources;
|
||||||
|
typedef struct _CalendarSourcesClass CalendarSourcesClass;
|
||||||
|
typedef struct _CalendarSourcesPrivate CalendarSourcesPrivate;
|
||||||
|
|
||||||
|
struct _CalendarSources
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
CalendarSourcesPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _CalendarSourcesClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* appointment_sources_changed) (CalendarSources *sources);
|
||||||
|
void (* task_sources_changed) (CalendarSources *sources);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GType calendar_sources_get_type (void) G_GNUC_CONST;
|
||||||
|
CalendarSources *calendar_sources_get (void);
|
||||||
|
GSList *calendar_sources_get_appointment_sources (CalendarSources *sources);
|
||||||
|
GSList *calendar_sources_get_task_sources (CalendarSources *sources);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CALENDAR_SOURCES_H__ */
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "calendar-client/calendar-client.h"
|
||||||
#include "shell-evolution-event-source.h"
|
#include "shell-evolution-event-source.h"
|
||||||
|
|
||||||
|
|
||||||
@ -12,7 +13,10 @@ struct _ShellEvolutionEventSourceClass
|
|||||||
|
|
||||||
struct _ShellEvolutionEventSource {
|
struct _ShellEvolutionEventSource {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
CalendarClient *client;
|
||||||
|
/* The month that we are currently requesting events from */
|
||||||
|
gint req_year;
|
||||||
|
gint req_mon; /* starts at 1, not zero */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Signals */
|
/* Signals */
|
||||||
@ -26,14 +30,53 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||||||
|
|
||||||
G_DEFINE_TYPE (ShellEvolutionEventSource, shell_evolution_event_source, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (ShellEvolutionEventSource, shell_evolution_event_source, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_tasks_changed (CalendarClient *client,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (user_data);
|
||||||
|
/* g_print ("on tasks changed\n"); */
|
||||||
|
g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_appointments_changed (CalendarClient *client,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (user_data);
|
||||||
|
/* g_print ("on appointments changed\n"); */
|
||||||
|
g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_evolution_event_source_init (ShellEvolutionEventSource *source)
|
shell_evolution_event_source_init (ShellEvolutionEventSource *source)
|
||||||
{
|
{
|
||||||
|
source->client = calendar_client_new ();
|
||||||
|
g_signal_connect (source->client,
|
||||||
|
"tasks-changed",
|
||||||
|
G_CALLBACK (on_tasks_changed),
|
||||||
|
source);
|
||||||
|
g_signal_connect (source->client,
|
||||||
|
"appointments-changed",
|
||||||
|
G_CALLBACK (on_appointments_changed),
|
||||||
|
source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_evolution_event_source_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (object);
|
||||||
|
g_object_unref (source->client);
|
||||||
|
G_OBJECT_CLASS (shell_evolution_event_source_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_evolution_event_source_class_init (ShellEvolutionEventSourceClass *klass)
|
shell_evolution_event_source_class_init (ShellEvolutionEventSourceClass *klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = shell_evolution_event_source_finalize;
|
||||||
|
|
||||||
signals[CHANGED_SIGNAL] =
|
signals[CHANGED_SIGNAL] =
|
||||||
g_signal_new ("changed",
|
g_signal_new ("changed",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
@ -51,36 +94,118 @@ shell_evolution_event_source_new (void)
|
|||||||
return SHELL_EVOLUTION_EVENT_SOURCE (g_object_new (SHELL_TYPE_EVOLUTION_EVENT_SOURCE, NULL));
|
return SHELL_EVOLUTION_EVENT_SOURCE (g_object_new (SHELL_TYPE_EVOLUTION_EVENT_SOURCE, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shell_evolution_event_source_request_range (ShellEvolutionEventSource *source,
|
||||||
|
gint64 msec_begin,
|
||||||
|
gint64 msec_end)
|
||||||
|
{
|
||||||
|
GDateTime *middle;
|
||||||
|
|
||||||
|
/* The CalendarClient type is a convenience wrapper on top of
|
||||||
|
* Evolution Data Server. It is based on the assumption that only
|
||||||
|
* a single month is shown at a time.
|
||||||
|
*
|
||||||
|
* To avoid reimplemting all the work already done in CalendarClient
|
||||||
|
* we make the same assumption. This means that we only show events
|
||||||
|
* in the month that is in the middle of @msec_begin and
|
||||||
|
* @msec_end. Since the Shell displays a month at a time (plus the
|
||||||
|
* days before and after) it works out just fine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
middle = g_date_time_new_from_unix_utc ((msec_begin + msec_end) / 2 / 1000);
|
||||||
|
g_date_time_get_ymd (middle, &source->req_year, &source->req_mon, NULL);
|
||||||
|
g_date_time_unref (middle);
|
||||||
|
calendar_client_select_month (source->client, source->req_mon - 1, source->req_year);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
event_cmp (gconstpointer a,
|
||||||
|
gconstpointer b)
|
||||||
|
{
|
||||||
|
const ShellEvolutionEvent *ea;
|
||||||
|
const ShellEvolutionEvent *eb;
|
||||||
|
|
||||||
|
ea = a;
|
||||||
|
eb = b;
|
||||||
|
if (ea->msec_begin < eb->msec_begin)
|
||||||
|
return -1;
|
||||||
|
else if (ea->msec_begin > eb->msec_begin)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_evolution_event_source_get_events:
|
* shell_evolution_event_source_get_events:
|
||||||
* @source: A #ShellEvolutionEventSource.
|
* @source: A #ShellEvolutionEventSource.
|
||||||
* @date_begin: Start date (milli-seconds since Epoch).
|
* @msec_begin: Start date (milli-seconds since Epoch).
|
||||||
* @date_end: End date (milli-seconds since Epoch).
|
* @msec_end: End date (milli-seconds since Epoch).
|
||||||
*
|
*
|
||||||
* Gets all events that occur between @date_begin and @date_end.
|
* Gets all events that occur between @msec_begin and @msec_end.
|
||||||
*
|
*
|
||||||
* Returns: (element-type ShellEvolutionEvent) (transfer full): List of events.
|
* Returns: (element-type ShellEvolutionEvent) (transfer full): List of events.
|
||||||
*/
|
*/
|
||||||
GList *
|
GList *
|
||||||
shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
||||||
gint64 date_begin,
|
gint64 msec_begin,
|
||||||
gint64 date_end)
|
gint64 msec_end)
|
||||||
{
|
{
|
||||||
GList *result;
|
GList *result;
|
||||||
|
GDateTime *cur_date;
|
||||||
|
GDateTime *begin_date;
|
||||||
|
GDateTime *end_date;
|
||||||
|
|
||||||
g_print ("get_events\n");
|
g_return_val_if_fail (msec_begin <= msec_end, NULL);
|
||||||
g_print (" date_begin = %" G_GINT64_FORMAT "\n", date_begin);
|
|
||||||
g_print (" date_end = %" G_GINT64_FORMAT "\n", date_end);
|
|
||||||
|
|
||||||
result = NULL;
|
result = NULL;
|
||||||
|
|
||||||
gint64 event_time = 1295931631000 + 32 * 3600 * 1000;
|
begin_date = g_date_time_new_from_unix_utc (msec_begin / 1000);
|
||||||
if (event_time >= date_begin && event_time <= date_end)
|
end_date = g_date_time_new_from_unix_utc (msec_end / 1000);
|
||||||
|
cur_date = g_date_time_ref (begin_date);
|
||||||
|
do
|
||||||
{
|
{
|
||||||
ShellEvolutionEvent *event;
|
gint year, mon, day;
|
||||||
event = shell_evolution_event_new ("Stuff", FALSE, event_time);
|
GDateTime *next_date;
|
||||||
result = g_list_prepend (result, event);
|
|
||||||
|
g_date_time_get_ymd (cur_date, &year, &mon, &day);
|
||||||
|
/* g_print ("y=%04d m=%02d d=%02d: ", year, mon, day); */
|
||||||
|
|
||||||
|
/* Silently drop events not in range (see comment in
|
||||||
|
* shell_evolution_event_source_request_range() above)
|
||||||
|
*/
|
||||||
|
if (!(year == source->req_year && mon == source->req_mon))
|
||||||
|
{
|
||||||
|
/* g_print ("skipping day\n"); */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GSList *events;
|
||||||
|
GSList *l;
|
||||||
|
calendar_client_select_day (source->client, day);
|
||||||
|
events = calendar_client_get_events (source->client, CALENDAR_EVENT_APPOINTMENT);
|
||||||
|
/* g_print ("num_events: %d\n", g_slist_length (events)); */
|
||||||
|
for (l = events; l; l = l->next)
|
||||||
|
{
|
||||||
|
CalendarAppointment *appointment = l->data;
|
||||||
|
ShellEvolutionEvent *event;
|
||||||
|
event = shell_evolution_event_new (appointment->summary,
|
||||||
|
appointment->is_all_day,
|
||||||
|
appointment->start_time * G_GINT64_CONSTANT (1000));
|
||||||
|
result = g_list_prepend (result, event);
|
||||||
|
}
|
||||||
|
g_slist_foreach (events, (GFunc) calendar_event_free, NULL);
|
||||||
|
g_slist_free (events);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_date = g_date_time_add_days (cur_date, 1);
|
||||||
|
g_date_time_unref (cur_date);
|
||||||
|
cur_date = next_date;
|
||||||
}
|
}
|
||||||
|
while (g_date_time_difference (end_date, cur_date) > 0);
|
||||||
|
g_date_time_unref (begin_date);
|
||||||
|
g_date_time_unref (end_date);
|
||||||
|
|
||||||
|
result = g_list_sort (result, event_cmp);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -109,12 +234,12 @@ shell_evolution_event_copy (ShellEvolutionEvent *event)
|
|||||||
ShellEvolutionEvent *
|
ShellEvolutionEvent *
|
||||||
shell_evolution_event_new (const gchar *summary,
|
shell_evolution_event_new (const gchar *summary,
|
||||||
gboolean all_day,
|
gboolean all_day,
|
||||||
gint64 date)
|
gint64 msec_begin)
|
||||||
{
|
{
|
||||||
ShellEvolutionEvent *event;
|
ShellEvolutionEvent *event;
|
||||||
event = g_new0 (ShellEvolutionEvent, 1);
|
event = g_new0 (ShellEvolutionEvent, 1);
|
||||||
event->summary = g_strdup (summary);
|
event->summary = g_strdup (summary);
|
||||||
event->all_day = all_day;
|
event->all_day = all_day;
|
||||||
event->date = date;
|
event->msec_begin = msec_begin;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,13 @@ struct _ShellEvolutionEvent
|
|||||||
{
|
{
|
||||||
gchar *summary;
|
gchar *summary;
|
||||||
gboolean all_day;
|
gboolean all_day;
|
||||||
gint64 date;
|
gint64 msec_begin;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType shell_evolution_event_get_type (void) G_GNUC_CONST;
|
GType shell_evolution_event_get_type (void) G_GNUC_CONST;
|
||||||
ShellEvolutionEvent *shell_evolution_event_new (const gchar *summary,
|
ShellEvolutionEvent *shell_evolution_event_new (const gchar *summary,
|
||||||
gboolean all_day,
|
gboolean all_day,
|
||||||
gint64 date);
|
gint64 msec_begin);
|
||||||
ShellEvolutionEvent *shell_evolution_event_copy (ShellEvolutionEvent *event);
|
ShellEvolutionEvent *shell_evolution_event_copy (ShellEvolutionEvent *event);
|
||||||
void shell_evolution_event_free (ShellEvolutionEvent *event);
|
void shell_evolution_event_free (ShellEvolutionEvent *event);
|
||||||
|
|
||||||
@ -32,11 +32,14 @@ typedef struct _ShellEvolutionEventSourceClass ShellEvolutionEventSourceClass;
|
|||||||
#define SHELL_IS_EVOLUTION_EVENT_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_EVOLUTION_EVENT_SOURCE))
|
#define SHELL_IS_EVOLUTION_EVENT_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_EVOLUTION_EVENT_SOURCE))
|
||||||
#define SHELL_EVOLUTION_EVENT_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_EVOLUTION_EVENT_SOURCE, ShellEvolutionEventSourceClass))
|
#define SHELL_EVOLUTION_EVENT_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_EVOLUTION_EVENT_SOURCE, ShellEvolutionEventSourceClass))
|
||||||
|
|
||||||
GType shell_evolution_event_source_get_type (void) G_GNUC_CONST;
|
GType shell_evolution_event_source_get_type (void) G_GNUC_CONST;
|
||||||
ShellEvolutionEventSource *shell_evolution_event_source_new (void);
|
ShellEvolutionEventSource *shell_evolution_event_source_new (void);
|
||||||
GList *shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
void shell_evolution_event_source_request_range (ShellEvolutionEventSource *source,
|
||||||
gint64 date_begin,
|
gint64 msec_begin,
|
||||||
gint64 date_end);
|
gint64 msec_end);
|
||||||
|
GList *shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
||||||
|
gint64 msec_begin,
|
||||||
|
gint64 msec_end);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __SHELL_EVOLUTION_EVENT_SOURCE_H__ */
|
#endif /* __SHELL_EVOLUTION_EVENT_SOURCE_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user