[gnome-calendar] utils: Move to utils/ subdir
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar] utils: Move to utils/ subdir
- Date: Fri, 26 Apr 2019 19:02:03 +0000 (UTC)
commit 3bff2b89816c83b467d183485b788c960a0b50da
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Apr 25 20:59:08 2019 -0300
utils: Move to utils/ subdir
We will split this file into more, specialized, files
so it makes sense to not pollute the top source dir.
src/meson.build | 3 +-
src/utils/gcal-utils.c | 1369 ++++++++++++++++++++++++++++++++++++++++++++++++
src/utils/gcal-utils.h | 140 +++++
3 files changed, 1511 insertions(+), 1 deletion(-)
---
diff --git a/src/meson.build b/src/meson.build
index adef2634..07014f69 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -20,6 +20,7 @@ gcal_deps = [
]
sources = files(
+ 'utils/gcal-utils.c',
'views/gcal-month-cell.c',
'views/gcal-month-popover.c',
'views/gcal-month-view.c',
@@ -52,7 +53,6 @@ sources = files(
'gcal-source-dialog.c',
'gcal-time-selector.c',
'gcal-time-zone-monitor.c',
- 'gcal-utils.c',
'gcal-window.c',
'gcal-timer.c'
)
@@ -106,6 +106,7 @@ sources += configure_file(
incs = [
top_inc,
+ include_directories('utils'),
include_directories('views'),
include_directories('weather'),
]
diff --git a/src/utils/gcal-utils.c b/src/utils/gcal-utils.c
new file mode 100644
index 00000000..c7646565
--- /dev/null
+++ b/src/utils/gcal-utils.c
@@ -0,0 +1,1369 @@
+/* gcal-utils.c
+ *
+ * Copyright (C) 2012 - Erick Pérez Castellanos
+ *
+ * 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/>.
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "Utils"
+
+/* langinfo.h in glibc 2.27 defines ALTMON_* only if _GNU_SOURCE is defined. */
+#define _GNU_SOURCE
+
+#include "gcal-enums.h"
+#include "gcal-utils.h"
+#include "gcal-event-widget.h"
+#include "gcal-view.h"
+
+#include <libecal/libecal.h>
+#include <libedataserver/libedataserver.h>
+
+#include <glib/gi18n.h>
+
+#include <langinfo.h>
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+/**
+ * SECTION:gcal-utils
+ * @short_description: Utility functions
+ * @title:Utility functions
+ */
+
+static const gint
+ab_day[7] =
+{
+ ABDAY_1,
+ ABDAY_2,
+ ABDAY_3,
+ ABDAY_4,
+ ABDAY_5,
+ ABDAY_6,
+ ABDAY_7,
+};
+
+static const gint
+month_item[12] =
+{
+ /* ALTMON_* constants have been introduced in glibc 2.27 (Feb 1, 2018), also
+ * have been supported in *BSD family (but not in OS X) since 1990s.
+ * If they exist they are the correct way to obtain the month names in
+ * nominative case, standalone, without the day number, as used in the
+ * calendar header. This is obligatory in some languages (Slavic, Baltic,
+ * Greek, etc.) but also recommended to use in all languages because for
+ * other languages there is no difference between ALTMON_* and MON_*.
+ * If ALTMON_* is not supported then we must use MON_*.
+ */
+#ifdef HAVE_ALTMON
+ ALTMON_1,
+ ALTMON_2,
+ ALTMON_3,
+ ALTMON_4,
+ ALTMON_5,
+ ALTMON_6,
+ ALTMON_7,
+ ALTMON_8,
+ ALTMON_9,
+ ALTMON_10,
+ ALTMON_11,
+ ALTMON_12
+#else
+ MON_1,
+ MON_2,
+ MON_3,
+ MON_4,
+ MON_5,
+ MON_6,
+ MON_7,
+ MON_8,
+ MON_9,
+ MON_10,
+ MON_11,
+ MON_12
+#endif
+};
+
+#define SCROLL_HARDNESS 10.0
+
+G_DEFINE_BOXED_TYPE (icaltimetype, icaltime, gcal_dup_icaltime, g_free)
+
+/**
+ * datetime_compare_date:
+ * @dt1: (nullable): a #GDateTime
+ * @dt2: (nullable): a #GDateTime
+ *
+ * Compares the dates of @dt1 and @dt2. The times are
+ * ignored.
+ *
+ * Returns: negative, 0 or positive
+ */
+gint
+datetime_compare_date (GDateTime *dt1,
+ GDateTime *dt2)
+{
+ if (!dt1 && !dt2)
+ return 0;
+ else if (!dt1)
+ return -1;
+ else if (!dt2)
+ return 1;
+
+ if (g_date_time_get_year (dt1) != g_date_time_get_year (dt2))
+ return (g_date_time_get_year (dt1) - g_date_time_get_year (dt2)) * 360;
+
+ if (g_date_time_get_month (dt1) != g_date_time_get_month (dt2))
+ return (g_date_time_get_month (dt1) - g_date_time_get_month (dt2)) * 30;
+
+ if (g_date_time_get_day_of_month (dt1) != g_date_time_get_day_of_month (dt2))
+ return g_date_time_get_day_of_month (dt1) - g_date_time_get_day_of_month (dt2);
+
+ return 0;
+}
+
+/**
+ * datetime_to_icaltime:
+ * @dt: a #GDateTime
+ *
+ * Converts the #GDateTime's @dt to an #icaltimetype.
+ *
+ * Returns: (transfer full): a #icaltimetype.
+ */
+icaltimetype*
+datetime_to_icaltime (GDateTime *dt)
+{
+ icaltimetype *idt;
+
+ if (!dt)
+ return NULL;
+
+ idt = g_new0 (icaltimetype, 1);
+
+ idt->year = g_date_time_get_year (dt);
+ idt->month = g_date_time_get_month (dt);
+ idt->day = g_date_time_get_day_of_month (dt);
+ idt->hour = g_date_time_get_hour (dt);
+ idt->minute = g_date_time_get_minute (dt);
+ idt->second = g_date_time_get_seconds (dt);
+ idt->is_date = (idt->hour == 0 &&
+ idt->minute == 0 &&
+ idt->second == 0);
+
+ return idt;
+}
+
+/**
+ * icaltime_to_datetime:
+ * @date: an #icaltimetype
+ *
+ * Converts the #icaltimetype's @date to a #GDateTime. The
+ * timezone is preserved.
+ *
+ * Returns: (transfer full): a #GDateTime.
+ */
+GDateTime*
+icaltime_to_datetime (const icaltimetype *date)
+{
+ GDateTime *dt;
+ GTimeZone *tz;
+
+ tz = date->zone ? g_time_zone_new (icaltime_get_tzid (*date)) : g_time_zone_new_utc ();
+ dt = g_date_time_new (tz,
+ date->year,
+ date->month,
+ date->day,
+ date->is_date ? 0 : date->hour,
+ date->is_date ? 0 : date->minute,
+ date->is_date ? 0 : date->second);
+
+ g_clear_pointer (&tz, g_time_zone_unref);
+
+ return dt;
+}
+
+/**
+ * datetime_is_date:
+ * @dt: a #GDateTime
+ *
+ * Checks if @dt represents a date. A pure date
+ * has the values of hour, minutes and seconds set
+ * to 0.
+ *
+ * Returns: %TRUE if @dt is a date, %FALSE if it's a
+ * timed datetime.
+ */
+gboolean
+datetime_is_date (GDateTime *dt)
+{
+ return g_date_time_get_hour (dt) == 0 &&
+ g_date_time_get_minute (dt) == 0 &&
+ g_date_time_get_seconds (dt) == 0;
+}
+
+/**
+ * gcal_dup_icaltime:
+ * @date: an #icaltimetype
+ *
+ * Creates an exact copy of @date.
+ *
+ * Returns: (transfer full): an #icaltimetype
+ */
+icaltimetype*
+gcal_dup_icaltime (const icaltimetype *date)
+{
+ return g_memdup (date, sizeof (icaltimetype));
+}
+
+/**
+ * gcal_get_weekday:
+ * @i: the weekday index
+ *
+ * Retrieves the weekday name.
+ *
+ * Returns: (transfer full): the weekday name
+ */
+gchar*
+gcal_get_weekday (gint i)
+{
+ return nl_langinfo (ab_day[i]);
+}
+
+/**
+ * gcal_get_month_name:
+ * @i: the month index
+ *
+ * Retrieves the month name.
+ *
+ * Returns: (transfer full): the month name
+ */
+gchar*
+gcal_get_month_name (gint i)
+{
+ return nl_langinfo (month_item[i]);
+}
+
+/**
+ * gcal_get_surface_from_color:
+ * @color: a #GdkRGBA
+ * @size: the size of the surface
+ *
+ * Creates a squared surface filled with @color. The
+ * surface is always @size x @size.
+ *
+ * Returns: (transfer full): a #cairo_surface_t
+ */
+cairo_surface_t*
+gcal_get_surface_from_color (GdkRGBA *color,
+ gint size)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgba (cr,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha);
+ cairo_rectangle (cr, 0, 0, size, size);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+
+ return surface;
+}
+
+/**
+ * get_circle_surface_from_color:
+ * @color: a #GdkRGBA
+ * @size: the size of the surface
+ *
+ * Creates a circular surface filled with @color. The
+ * surface is always @size x @size.
+ *
+ * Returns: (transfer full): a #cairo_surface_t
+ */
+cairo_surface_t*
+get_circle_surface_from_color (GdkRGBA *color,
+ gint size)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgba (cr,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha);
+ cairo_arc (cr, size / 2.0, size / 2.0, size / 2.0, 0., 2 * M_PI);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+
+ return surface;
+}
+
+/**
+ * get_color_name_from_source:
+ * @source: an #ESource
+ * @out_color: return value for the color
+ *
+ * Utility function to retrieve the color from @source.
+ */
+void
+get_color_name_from_source (ESource *source,
+ GdkRGBA *out_color)
+{
+ ESourceSelectable *extension = E_SOURCE_SELECTABLE (e_source_get_extension (source,
E_SOURCE_EXTENSION_CALENDAR));
+
+ /* FIXME: We should handle calendars colours better */
+ if (!gdk_rgba_parse (out_color, e_source_selectable_get_color (extension)))
+ gdk_rgba_parse (out_color, "#becedd"); /* calendar default colour */
+}
+
+/**
+ * get_desc_from_component:
+ * @component: an #ECalComponent
+ * @joint_char: the character to use when merging event comments
+ *
+ * Utility method to handle the extraction of the description from an
+ * #ECalComponent. This cycle through the list of #ECalComponentText
+ * and concatenate each string into one.
+ *
+ * Returns: (nullable)(transfer full) a new allocated string with the
+ * description
+ **/
+gchar*
+get_desc_from_component (ECalComponent *component,
+ const gchar *joint_char)
+{
+ GSList *text_list;
+ GSList *l;
+
+ gchar *desc = NULL;
+ e_cal_component_get_description_list (component, &text_list);
+
+ for (l = text_list; l != NULL; l = l->next)
+ {
+ if (l->data != NULL)
+ {
+ ECalComponentText *text;
+ gchar *carrier;
+ text = l->data;
+
+ if (desc != NULL)
+ {
+ carrier = g_strconcat (desc, joint_char, text->value, NULL);
+ g_free (desc);
+ desc = carrier;
+ }
+ else
+ {
+ desc = g_strdup (text->value);
+ }
+ }
+ }
+
+ e_cal_component_free_text_list (text_list);
+ return desc != NULL ? g_strstrip (desc) : NULL;
+}
+
+/**
+ * get_uuid_from_component:
+ * @source: an {@link ESource}
+ * @component: an {@link ECalComponent}
+ *
+ * Obtains the uuid from a component in the form
+ * "source_uid:event_uid:event_rid" or "source:uid:event_uid" if the
+ * component doesn't hold a recurrence event
+ *
+ * Returns: (Transfer full) a new allocated string with the description
+ **/
+gchar*
+get_uuid_from_component (ESource *source,
+ ECalComponent *component)
+{
+ gchar *uuid;
+ ECalComponentId *id;
+
+ id = e_cal_component_get_id (component);
+ if (id->rid != NULL)
+ {
+ uuid = g_strdup_printf ("%s:%s:%s",
+ e_source_get_uid (source),
+ id->uid,
+ id->rid);
+ }
+ else
+ {
+ uuid = g_strdup_printf ("%s:%s",
+ e_source_get_uid (source),
+ id->uid);
+ }
+ e_cal_component_free_id (id);
+
+ return uuid;
+}
+
+/**
+ * get_first_weekday:
+ *
+ * Copied from Clocks, which by itself is
+ * copied from GtkCalendar.
+ *
+ * Returns: the first weekday, from 0 to 6
+ */
+gint
+get_first_weekday (void)
+{
+ int week_start;
+
+#ifdef HAVE__NL_TIME_FIRST_WEEKDAY
+
+ union { unsigned int word; char *string; } langinfo;
+ gint week_1stday = 0;
+ gint first_weekday = 1;
+ guint week_origin;
+
+ langinfo.string = nl_langinfo (_NL_TIME_FIRST_WEEKDAY);
+ first_weekday = langinfo.string[0];
+ langinfo.string = nl_langinfo (_NL_TIME_WEEK_1STDAY);
+ week_origin = langinfo.word;
+ if (week_origin == 19971130) /* Sunday */
+ week_1stday = 0;
+ else if (week_origin == 19971201) /* Monday */
+ week_1stday = 1;
+ else
+ g_warning ("Unknown value of _NL_TIME_WEEK_1STDAY.\n");
+
+ week_start = (week_1stday + first_weekday - 1) % 7;
+
+#else
+
+ gchar *gtk_week_start;
+
+
+ /* Use a define to hide the string from xgettext */
+# define GTK_WEEK_START "calendar:week_start:0"
+ gtk_week_start = dgettext ("gtk30", GTK_WEEK_START);
+
+ if (strncmp (gtk_week_start, "calendar:week_start:", 20) == 0)
+ week_start = *(gtk_week_start + 20) - '0';
+ else
+ week_start = -1;
+
+ if (week_start < 0 || week_start > 6)
+ {
+ g_warning ("Whoever translated calendar:week_start:0 for GTK+ "
+ "did so wrongly.\n");
+ week_start = 0;
+ }
+
+#endif
+
+ return week_start;
+}
+
+/**
+ * build_component_from_details:
+ * @summary:
+ * @initial_date:
+ * @final_date:
+ *
+ * Create a component with the provided details
+ *
+ * Returns: (transfer full): an {@link ECalComponent} object
+ **/
+ECalComponent*
+build_component_from_details (const gchar *summary,
+ GDateTime *initial_date,
+ GDateTime *final_date)
+{
+ ECalComponent *event;
+ ECalComponentDateTime dt;
+ ECalComponentText summ;
+ icaltimezone *zone;
+ gboolean all_day;
+
+ event = e_cal_component_new ();
+ e_cal_component_set_new_vtype (event, E_CAL_COMPONENT_EVENT);
+
+ /*
+ * Check if the event is all day. Notice that it can be all day even
+ * without the final date.
+ */
+ all_day = datetime_is_date (initial_date) && (final_date ? datetime_is_date (final_date) : TRUE);
+
+ /*
+ * When the event is all day, we consider UTC timezone by default. Otherwise,
+ * we always use the system timezone to create new events
+ */
+ if (all_day)
+ {
+ zone = icaltimezone_get_utc_timezone ();
+ }
+ else
+ {
+ gchar *system_tz = e_cal_system_timezone_get_location ();
+
+ zone = icaltimezone_get_builtin_timezone (system_tz);
+
+ g_free (system_tz);
+ }
+
+ /* Start date */
+ dt.value = datetime_to_icaltime (initial_date);
+ icaltime_set_timezone (dt.value, zone);
+ dt.value->is_date = all_day;
+ dt.tzid = icaltimezone_get_tzid (zone);
+ e_cal_component_set_dtstart (event, &dt);
+
+ g_free (dt.value);
+
+ /* End date */
+ if (!final_date)
+ final_date = g_date_time_add_days (initial_date, 1);
+
+ dt.value = datetime_to_icaltime (final_date);
+ icaltime_set_timezone (dt.value, zone);
+ dt.value->is_date = all_day;
+ dt.tzid = icaltimezone_get_tzid (zone);
+ e_cal_component_set_dtend (event, &dt);
+
+ g_free (dt.value);
+
+ /* Summary */
+ summ.altrep = NULL;
+ summ.value = summary;
+ e_cal_component_set_summary (event, &summ);
+
+ e_cal_component_commit_sequence (event);
+
+ return event;
+}
+
+/**
+ * icaltime_compare_date:
+ * @date1: an #icaltimetype
+ * @date2: an #icaltimetype
+ *
+ * Compare date parts of #icaltimetype objects. Returns negative value,
+ * 0 or positive value accordingly if @date1 is before, same day of
+ * after date2.
+ *
+ * As a bonus it returns the amount of days passed between two days on the
+ * same year.
+ *
+ * Returns: negative, 0 or positive
+ **/
+gint
+icaltime_compare_date (const icaltimetype *date1,
+ const icaltimetype *date2)
+{
+ if (date2 == NULL)
+ return 0;
+
+ if (date1->year < date2->year)
+ return -1;
+ else if (date1->year > date2->year)
+ return 1;
+ else
+ return time_day_of_year (date1->day, date1->month - 1, date1->year) -
+ time_day_of_year (date2->day, date2->month - 1, date2->year);
+}
+
+/**
+ * icaltime_compare_with_current:
+ * @date1: an #icaltimetype
+ * @date2: an #icaltimetype
+ * @current_time_t: the current time
+ *
+ * Compares @date1 and @date2 against the current time. Dates
+ * closer to the current date are sorted before.
+ *
+ * Returns: negative if @date1 comes after @date2, 0 if they're
+ * equal, positive otherwise
+ */
+gint
+icaltime_compare_with_current (const icaltimetype *date1,
+ const icaltimetype *date2,
+ time_t *current_time_t)
+{
+ gint result = 0;
+
+ time_t start1, start2, diff1, diff2;
+ start1 = icaltime_as_timet_with_zone (*date1, date1->zone != NULL ? date1->zone :
e_cal_util_get_system_timezone ());
+ start2 = icaltime_as_timet_with_zone (*date2, date2->zone != NULL ? date2->zone :
e_cal_util_get_system_timezone ());
+ diff1 = start1 - *current_time_t;
+ diff2 = start2 - *current_time_t;
+
+ if (diff1 != diff2)
+ {
+ if (diff1 == 0)
+ result = -1;
+ else if (diff2 == 0)
+ result = 1;
+
+ if (diff1 > 0 && diff2 < 0)
+ result = -1;
+ else if (diff2 > 0 && diff1 < 0)
+ result = 1;
+ else if (diff1 < 0 && diff2 < 0)
+ result = ABS (diff1) - ABS (diff2);
+ else if (diff1 > 0 && diff2 > 0)
+ result = diff1 - diff2;
+ }
+
+ return result;
+}
+
+/**
+ * get_start_of_week:
+ * @date: an #icaltimetype
+ *
+ * Retrieves the start of the week that @date
+ * falls in. This function already takes the
+ * first weekday into account.
+ *
+ * Returns: (transfer full): a #GDateTime with
+ * the start of the week.
+ */
+GDateTime*
+get_start_of_week (icaltimetype *date)
+{
+ icaltimetype *new_date;
+ GDateTime *dt;
+
+ new_date = g_new0 (icaltimetype, 1);
+ *new_date = icaltime_from_day_of_year (icaltime_start_doy_week (*date, get_first_weekday () + 1),
+ date->year);
+ new_date->is_date = 0;
+ new_date->hour = 0;
+ new_date->minute = 0;
+ new_date->second = 0;
+
+ dt = g_date_time_new_local (new_date->year,
+ new_date->month,
+ new_date->day,
+ 0, 0, 0);
+
+ g_clear_pointer (&new_date, g_free);
+
+ return dt;
+}
+
+/**
+ * get_end_of_week:
+ * @date: an #icaltimetype
+ *
+ * Retrieves the end of the week that @date
+ * falls in. This function already takes the
+ * first weekday into account.
+ *
+ * Returns: (transfer full): a #GDateTime with
+ * the end of the week.
+ */
+GDateTime*
+get_end_of_week (icaltimetype *date)
+{
+ GDateTime *week_start, *week_end;
+
+ week_start = get_start_of_week (date);
+ week_end = g_date_time_add_days (week_start, 7);
+
+ g_clear_pointer (&week_start, g_date_time_unref);
+
+ return week_end;
+}
+
+/**
+ * is_clock_format_24h:
+ *
+ * Retrieves whether the current clock format is
+ * 12h or 24h based.
+ *
+ * Returns: %TRUE if the clock format is 24h, %FALSE
+ * otherwise.
+ */
+gboolean
+is_clock_format_24h (void)
+{
+ static GSettings *settings = NULL;
+ g_autofree gchar *clock_format = NULL;
+
+ if (!settings)
+ settings = g_settings_new ("org.gnome.desktop.interface");
+
+ clock_format = g_settings_get_string (settings, "clock-format");
+
+ return g_strcmp0 (clock_format, "24h") == 0;
+}
+
+/**
+ * e_strftime_fix_am_pm:
+ *
+ * Function to do a last minute fixup of the AM/PM stuff if the locale
+ * and gettext haven't done it right. Most English speaking countries
+ * except the USA use the 24 hour clock (UK, Australia etc). However
+ * since they are English nobody bothers to write a language
+ * translation (gettext) file. So the locale turns off the AM/PM, but
+ * gettext does not turn on the 24 hour clock. Leaving a mess.
+ *
+ * This routine checks if AM/PM are defined in the locale, if not it
+ * forces the use of the 24 hour clock.
+ *
+ * The function itself is a front end on strftime and takes exactly
+ * the same arguments.
+ *
+ * TODO: Actually remove the '%p' from the fixed up string so that
+ * there isn't a stray space.
+ */
+gsize
+e_strftime_fix_am_pm (gchar *str,
+ gsize max,
+ const gchar *fmt,
+ const struct tm *tm)
+{
+ gchar buf[10];
+ gchar *sp;
+ gchar *ffmt;
+ gsize ret;
+
+ if (strstr(fmt, "%p")==NULL && strstr(fmt, "%P")==NULL) {
+ /* No AM/PM involved - can use the fmt string directly */
+ ret = e_strftime (str, max, fmt, tm);
+ } else {
+ /* Get the AM/PM symbol from the locale */
+ e_strftime (buf, 10, "%p", tm);
+
+ if (buf[0]) {
+ /* AM/PM have been defined in the locale
+ * so we can use the fmt string directly. */
+ ret = e_strftime (str, max, fmt, tm);
+ } else {
+ /* No AM/PM defined by locale
+ * must change to 24 hour clock. */
+ ffmt = g_strdup (fmt);
+ for (sp=ffmt; (sp=strstr(sp, "%l")); sp++) {
+ /* Maybe this should be 'k', but I have never
+ * seen a 24 clock actually use that format. */
+ sp[1]='H';
+ }
+ for (sp=ffmt; (sp=strstr(sp, "%I")); sp++) {
+ sp[1]='H';
+ }
+ ret = e_strftime (str, max, ffmt, tm);
+ g_free (ffmt);
+ }
+ }
+
+ return (ret);
+}
+
+/**
+ * e_utf8_strftime_fix_am_pm:
+ *
+ * Stolen from Evolution codebase. Selects the
+ * correct time format.
+ *
+ * Returns: the size of the string
+ */
+gsize
+e_utf8_strftime_fix_am_pm (gchar *str,
+ gsize max,
+ const gchar *fmt,
+ const struct tm *tm)
+{
+ gsize sz, ret;
+ gchar *locale_fmt, *buf;
+
+ locale_fmt = g_locale_from_utf8 (fmt, -1, NULL, &sz, NULL);
+ if (!locale_fmt)
+ return 0;
+
+ ret = e_strftime_fix_am_pm (str, max, locale_fmt, tm);
+ if (!ret) {
+ g_free (locale_fmt);
+ return 0;
+ }
+
+ buf = g_locale_to_utf8 (str, ret, NULL, &sz, NULL);
+ if (!buf) {
+ g_free (locale_fmt);
+ return 0;
+ }
+
+ if (sz >= max) {
+ gchar *tmp = buf + max - 1;
+ tmp = g_utf8_find_prev_char (buf, tmp);
+ if (tmp)
+ sz = tmp - buf;
+ else
+ sz = 0;
+ }
+ memcpy (str, buf, sz);
+ str[sz] = '\0';
+ g_free (locale_fmt);
+ g_free (buf);
+ return sz;
+}
+
+
+/**
+ * fix_popover_menu_icons:
+ * @window: a #GtkPopover
+ *
+ * Hackish code that inspects the popover's children,
+ * retrieve the hidden GtkImage buried under lots of
+ * widgets, and make it visible again.
+ *
+ * Hopefully, we'll find a better way to do this in
+ * the long run.
+ *
+ */
+void
+fix_popover_menu_icons (GtkPopover *popover)
+{
+ GtkWidget *popover_stack;
+ GtkWidget *menu_section;
+ GtkWidget *menu_section_box;
+ GList *stack_children;
+ GList *menu_section_children;
+ GList *menu_section_box_children, *aux;
+
+ popover_stack = gtk_bin_get_child (GTK_BIN (popover));
+ stack_children = gtk_container_get_children (GTK_CONTAINER (popover_stack));
+
+ /**
+ * At the moment, the popover stack surely contains only
+ * one child of type GtkMenuSectionBox, which contains
+ * a single GtkBox.
+ */
+ menu_section = stack_children->data;
+ menu_section_children = gtk_container_get_children (GTK_CONTAINER (menu_section));
+
+ /**
+ * Get the unique box's children.
+ */
+ menu_section_box = menu_section_children->data;
+ menu_section_box_children = gtk_container_get_children (GTK_CONTAINER (menu_section_box));
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (menu_section_box), "calendars-list");
+
+ /**
+ * Iterate through the GtkModelButtons inside the menu section box.
+ */
+ for (aux = menu_section_box_children; aux != NULL; aux = aux->next)
+ {
+ GtkWidget *button_box;
+ GList *button_box_children, *aux2;
+
+ button_box = gtk_bin_get_child (GTK_BIN (aux->data));
+ button_box_children = gtk_container_get_children (GTK_CONTAINER (button_box));
+
+ /**
+ * Since there is no guarantee that the first child is
+ * the GtkImage we're looking for, we have to iterate
+ * through the children and check if the types match.
+ */
+ for (aux2 = button_box_children; aux2 != NULL; aux2 = aux2->next)
+ {
+ GtkWidget *button_box_child;
+ button_box_child = aux2->data;
+
+ if (g_type_is_a (G_OBJECT_TYPE (button_box_child), GTK_TYPE_IMAGE))
+ {
+ gtk_style_context_add_class (gtk_widget_get_style_context (button_box_child),
"calendar-color-image");
+ gtk_widget_show (button_box_child);
+ break;
+ }
+ }
+
+ g_list_free (button_box_children);
+ }
+
+ g_list_free (stack_children);
+ g_list_free (menu_section_children);
+ g_list_free (menu_section_box_children);
+}
+
+/**
+ * get_source_parent_name_color:
+ * @manager: a #GcalManager
+ * @source: an #ESource
+ * @name: (nullable): return location for the name
+ * @color: (nullable): return location for the color
+ *
+ * Retrieves the name and the color of the #ESource that is
+ * parent of @source.
+ */
+void
+get_source_parent_name_color (GcalManager *manager,
+ ESource *source,
+ gchar **name,
+ gchar **color)
+{
+ ESource *parent_source;
+
+ g_assert (source && E_IS_SOURCE (source));
+
+ parent_source = gcal_manager_get_source (manager, e_source_get_parent (source));
+
+ if (name != NULL)
+ *name = e_source_dup_display_name (parent_source);
+
+ if (color != NULL)
+ {
+ GdkRGBA c;
+
+ get_color_name_from_source (parent_source, &c);
+
+ *color = gdk_rgba_to_string (&c);
+ }
+}
+
+/**
+ * format_utc_offset:
+ * @offset: an UTC offset
+ *
+ * Formats the UTC offset to a string that GTimeZone can
+ * parse. E.g. "-0300" or "+0530".
+ *
+ * Returns: (transfer full): a string representing the
+ * offset
+ */
+gchar*
+format_utc_offset (gint64 offset)
+{
+ const char *sign = "+";
+ gint hours, minutes, seconds;
+
+ if (offset < 0) {
+ offset = -offset;
+ sign = "-";
+ }
+
+ /* offset can be seconds or microseconds */
+ if (offset >= 1000000)
+ offset = offset / 1000000;
+
+ hours = offset / 3600;
+ minutes = (offset % 3600) / 60;
+ seconds = offset % 60;
+
+ if (seconds > 0)
+ return g_strdup_printf ("%s%02i%02i%02i", sign, hours, minutes, seconds);
+ else
+ return g_strdup_printf ("%s%02i%02i", sign, hours, minutes);
+}
+
+/**
+ * get_alarm_trigger_minutes:
+ * @event: a #GcalEvent
+ * @alarm: a #ECalComponentAlarm
+ *
+ * Calculates the number of minutes before @event's
+ * start time that the alarm should be triggered.
+ *
+ * Returns: the number of minutes before the event
+ * start that @alarm will be triggered.
+ */
+gint
+get_alarm_trigger_minutes (GcalEvent *event,
+ ECalComponentAlarm *alarm)
+{
+ ECalComponentAlarmTrigger trigger;
+ GDateTime *alarm_dt;
+ gint diff;
+
+ e_cal_component_alarm_get_trigger (alarm, &trigger);
+
+ /*
+ * We only support alarms relative to the start date, and solely
+ * ignore whetever different it may be.
+ */
+ if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START)
+ return -1;
+
+ alarm_dt = g_date_time_add_full (gcal_event_get_date_start (event),
+ 0,
+ 0,
+ - (trigger.u.rel_duration.days + trigger.u.rel_duration.weeks * 7),
+ - trigger.u.rel_duration.hours,
+ - trigger.u.rel_duration.minutes,
+ - trigger.u.rel_duration.seconds);
+
+ diff = g_date_time_difference (gcal_event_get_date_start (event), alarm_dt) / G_TIME_SPAN_MINUTE;
+
+ g_clear_pointer (&alarm_dt, g_date_time_unref);
+
+ return diff;
+}
+
+/**
+ * should_change_date_for_scroll:
+ * @scroll_value: the current scroll value
+ * @scroll_event: the #GdkEventScroll that is being parsed
+ *
+ * Utility function to check if the date should change based
+ * on the scroll. The date is changed when the user scrolls
+ * too much on touchpad, or performs a rotation of the scroll
+ * button in a mouse.
+ *
+ * Returns: %TRUE if the date should change, %FALSE otherwise.
+ */
+gboolean
+should_change_date_for_scroll (gdouble *scroll_value,
+ GdkEventScroll *scroll_event)
+{
+ gdouble delta_y;
+
+ switch (scroll_event->direction)
+ {
+ case GDK_SCROLL_DOWN:
+ *scroll_value = SCROLL_HARDNESS;
+ break;
+
+ case GDK_SCROLL_UP:
+ *scroll_value = -SCROLL_HARDNESS;
+ break;
+
+ case GDK_SCROLL_SMOOTH:
+ gdk_event_get_scroll_deltas ((GdkEvent*) scroll_event, NULL, &delta_y);
+ *scroll_value += delta_y;
+ break;
+
+ /* Ignore horizontal scrolling for now */
+ case GDK_SCROLL_LEFT:
+ case GDK_SCROLL_RIGHT:
+ default:
+ break;
+ }
+
+ if (*scroll_value <= -SCROLL_HARDNESS || *scroll_value >= SCROLL_HARDNESS)
+ return TRUE;
+
+ return FALSE;
+}
+
+/**
+ * is_source_enabled:
+ * @source: an #ESource
+ *
+ * Retrieves whether the @source is enabled or not.
+ * Disabled sources don't show their events.
+ *
+ * Returns: %TRUE if @source is enabled, %FALSE otherwise.
+ */
+gboolean
+is_source_enabled (ESource *source)
+{
+ ESourceSelectable *selectable;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ selectable = e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR);
+
+ return e_source_selectable_get_selected (selectable);
+}
+
+/**
+ * ask_recurrence_modification_type:
+ * @parent: a #GtkWidget
+ * @modtype: an #ECalObjModType
+ * @source: an #ESource
+ *
+ * Assigns the appropriate modtype while modifying an event
+ * based on user's choice in the GtkMessageDialog that pops up.
+ * The modtype helps the user choose the part of recurrent events
+ * to modify. Such as Only This Event, Subsequent events
+ * or All events.
+ *
+ * Returns: %TRUE if user chooses appropriate option and
+ * @modtype is assigned, %FALSE otherwise.
+ */
+gboolean
+ask_recurrence_modification_type (GtkWidget *parent,
+ GcalRecurrenceModType *modtype,
+ ESource *source)
+{
+ GtkWidget *dialog;
+ GtkDialogFlags flags;
+ gint result;
+ gboolean is_set;
+ EClient *client;
+
+ flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
+ *modtype = GCAL_RECURRENCE_MOD_THIS_ONLY;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (parent)),
+ flags,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("The event you are trying to modify is recurring. The changes you have
selected should be applied to:"));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Cancel"),
+ GTK_RESPONSE_CANCEL,
+ _("_Only This Event"),
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ client = g_object_get_data (G_OBJECT (source), "client");
+
+ if (!e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_NO_THISANDFUTURE))
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Subsequent events"), GTK_RESPONSE_OK);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("_All events"), GTK_RESPONSE_YES);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ switch (result)
+ {
+ case GTK_RESPONSE_CANCEL:
+ is_set = FALSE;
+ break;
+ case GTK_RESPONSE_ACCEPT:
+ *modtype = GCAL_RECURRENCE_MOD_THIS_ONLY;
+ is_set = TRUE;
+ break;
+ case GTK_RESPONSE_OK:
+ *modtype = GCAL_RECURRENCE_MOD_THIS_AND_FUTURE;
+ is_set = TRUE;
+ break;
+ case GTK_RESPONSE_YES:
+ *modtype = GCAL_RECURRENCE_MOD_ALL;
+ is_set = TRUE;
+ break;
+ default:
+ is_set = FALSE;
+ break;
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ return is_set;
+}
+
+struct
+{
+ const gchar *territory;
+ GcalWeekDay no_work_days;
+} no_work_day_per_locale[] = {
+ { "AE", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* United Arab Emirates */,
+ { "AF", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Afghanistan */,
+ { "BD", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Bangladesh */,
+ { "BH", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Bahrain */,
+ { "BN", GCAL_WEEK_DAY_SUNDAY | GCAL_WEEK_DAY_FRIDAY } /* Brunei Darussalam */,
+ { "CR", GCAL_WEEK_DAY_SATURDAY } /* Costa Rica */,
+ { "DJ", GCAL_WEEK_DAY_FRIDAY } /* Djibouti */,
+ { "DZ", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Algeria */,
+ { "EG", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Egypt */,
+ { "GN", GCAL_WEEK_DAY_SATURDAY } /* Equatorial Guinea */,
+ { "HK", GCAL_WEEK_DAY_SATURDAY } /* Hong Kong */,
+ { "IL", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Israel */,
+ { "IQ", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Iraq */,
+ { "IR", GCAL_WEEK_DAY_THURSDAY | GCAL_WEEK_DAY_FRIDAY } /* Iran */,
+ { "KW", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Kuwait */,
+ { "KZ", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Kazakhstan */,
+ { "LY", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Libya */,
+ { "MX", GCAL_WEEK_DAY_SATURDAY } /* Mexico */,
+ { "MY", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Malaysia */,
+ { "NP", GCAL_WEEK_DAY_SATURDAY } /* Nepal */,
+ { "OM", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Oman */,
+ { "QA", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Qatar */,
+ { "SA", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Saudi Arabia */,
+ { "SU", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Sudan */,
+ { "SY", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Syria */,
+ { "UG", GCAL_WEEK_DAY_SUNDAY } /* Uganda */,
+ { "YE", GCAL_WEEK_DAY_FRIDAY | GCAL_WEEK_DAY_SATURDAY } /* Yemen */,
+};
+
+
+/**
+ * is_workday:
+ * @day: a guint representing the day of a week (0…Sunday, 6…Saturday)
+ *
+ * Checks whether @day is workday or not based on the Territory part of Locale.
+ *
+ * Returns: %TRUE if @day is a workday, %FALSE otherwise.
+ */
+gboolean
+is_workday (guint day)
+{
+ GcalWeekDay no_work_days;
+ gchar *locale;
+ gchar territory[3] = { 0, };
+ guint i;
+
+ if (day > 6)
+ return FALSE;
+
+ no_work_days = GCAL_WEEK_DAY_SATURDAY | GCAL_WEEK_DAY_SUNDAY;
+
+ locale = getenv ("LC_ALL");
+ if (!locale || g_utf8_strlen (locale, -1) < 5)
+ locale = getenv ("LC_TIME");
+
+ if (!locale)
+ {
+ g_warning ("Locale is NULL, assuming Saturday and Sunday as non workdays");
+ return !(no_work_days & 1 << day);
+ }
+
+ g_return_val_if_fail (g_utf8_strlen (locale, -1) >= 5, TRUE);
+
+ territory[0] = locale[3];
+ territory[1] = locale[4];
+
+ for (i = 0; i < G_N_ELEMENTS (no_work_day_per_locale); i++)
+ {
+ if (g_strcmp0 (territory, no_work_day_per_locale[i].territory) == 0)
+ {
+ no_work_days = no_work_day_per_locale[i].no_work_days;
+ break;
+ }
+ }
+
+ return !(no_work_days & 1 << day);
+}
+
+GList*
+filter_event_list_by_uid_and_modtype (GList *widgets,
+ GcalRecurrenceModType mod,
+ const gchar *uid)
+{
+ GcalEvent *event;
+ GList *result;
+ GList *l;
+
+ event = NULL;
+ result = NULL;
+
+ /* First pass: find the GcalEvent */
+ for (l = widgets; l != NULL; l = l->next)
+ {
+ GcalEventWidget *event_widget;
+ GcalEvent *ev;
+
+ event_widget = l->data;
+
+ /* Safeguard against stray widgets */
+ if (!GCAL_IS_EVENT_WIDGET (event_widget))
+ continue;
+
+ ev = gcal_event_widget_get_event (event_widget);
+
+ /*
+ * We can assume only one event will have the exact uuid. Even among
+ * recurrencies.
+ */
+ if (g_str_equal (uid, gcal_event_get_uid (ev)))
+ {
+ result = g_list_prepend (result, event_widget);
+ event = ev;
+ }
+ }
+
+ /* Second pass: find the other related events */
+ if (event && mod != GCAL_RECURRENCE_MOD_THIS_ONLY)
+ {
+ ECalComponentId *id;
+ ECalComponent *component;
+ ESource *source;
+ g_autofree gchar *id_prefix;
+
+ component = gcal_event_get_component (event);
+ source = gcal_event_get_source (event);
+ id = e_cal_component_get_id (component);
+ id_prefix = g_strdup_printf ("%s:%s", e_source_get_uid (source), id->uid);
+
+ for (l = widgets; l != NULL; l = l->next)
+ {
+ GcalEventWidget *event_widget;
+ GcalEvent *ev;
+
+ event_widget = l->data;
+
+ /* Safeguard against stray widgets */
+ if (!GCAL_IS_EVENT_WIDGET (event_widget))
+ continue;
+
+ ev = gcal_event_widget_get_event (event_widget);
+
+ if (g_str_equal (gcal_event_get_uid (ev), uid))
+ continue;
+
+ if (!g_str_has_prefix (gcal_event_get_uid (ev), id_prefix))
+ continue;
+
+ if (mod == GCAL_RECURRENCE_MOD_ALL)
+ {
+ result = g_list_prepend (result, event_widget);
+ }
+ else if (mod == GCAL_RECURRENCE_MOD_THIS_AND_FUTURE)
+ {
+ if (g_date_time_compare (gcal_event_get_date_start (event), gcal_event_get_date_start (ev)) <
0)
+ result = g_list_prepend (result, event_widget);
+ }
+
+ }
+
+ e_cal_component_free_id (id);
+ }
+
+ return result;
+}
+
+gboolean
+gcal_translate_child_window_position (GtkWidget *target,
+ GdkWindow *child_window,
+ gdouble src_x,
+ gdouble src_y,
+ gdouble *real_x,
+ gdouble *real_y)
+{
+ GdkWindow *window;
+ gdouble x, y;
+
+ x = src_x;
+ y = src_y;
+
+ /* Find the (x, y) values relative to the workbench */
+ window = child_window;
+ while (window && window != gtk_widget_get_window (target))
+ {
+ gdk_window_coords_to_parent (window, x, y, &x, &y);
+ window = gdk_window_get_parent (window);
+ }
+
+ if (!window)
+ return FALSE;
+
+ if (real_x)
+ *real_x = x;
+
+ if (real_y)
+ *real_y = y;
+
+ return TRUE;
+}
diff --git a/src/utils/gcal-utils.h b/src/utils/gcal-utils.h
new file mode 100644
index 00000000..bda43b95
--- /dev/null
+++ b/src/utils/gcal-utils.h
@@ -0,0 +1,140 @@
+/*
+ * gcal-window.h
+ * Copyright (C) 2015 Erick Pérez Castellanos <erickpc gnome org>
+ *
+ * gnome-calendar 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.
+ *
+ * gnome-calendar 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/>.
+ */
+
+#ifndef __GCAL_UTILS_H__
+#define __GCAL_UTILS_H__
+
+#include "gcal-manager.h"
+#include <gtk/gtk.h>
+#include <libecal/libecal.h>
+#include <libgweather/gweather.h>
+#include <libical/icaltime.h>
+
+#define ICAL_TIME_TYPE (icaltime_get_type ())
+
+#define ALIGNED(x) (round (x) + 0.5)
+#define MINUTES_PER_DAY 1440
+#define MAX_MINUTES (7 * MINUTES_PER_DAY)
+
+#define gcal_clear_datetime(dt) g_clear_pointer (dt, g_date_time_unref)
+#define gcal_clear_timeout(pp) { if (pp && *pp) { g_source_remove (*pp); *pp = 0; } }
+
+#if !EDS_CHECK_VERSION (3, 31, 90)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ESource, g_object_unref)
+#endif
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ECalComponent, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GWeatherLocation, gweather_location_unref)
+
+GType icaltime_get_type (void) G_GNUC_CONST;
+
+gint datetime_compare_date (GDateTime *dt1,
+ GDateTime *dt2);
+
+icaltimetype* datetime_to_icaltime (GDateTime *dt);
+
+gboolean datetime_is_date (GDateTime *dt);
+
+GDateTime* icaltime_to_datetime (const icaltimetype *date);
+
+icaltimetype* gcal_dup_icaltime (const icaltimetype *date);
+
+gchar* gcal_get_weekday (gint i);
+
+gchar* gcal_get_month_name (gint i);
+
+cairo_surface_t* gcal_get_surface_from_color (GdkRGBA *color,
+ gint size);
+
+cairo_surface_t* get_circle_surface_from_color (GdkRGBA *color,
+ gint size);
+
+void get_color_name_from_source (ESource *source,
+ GdkRGBA *out_color);
+
+gchar* get_desc_from_component (ECalComponent *component,
+ const gchar *joint_char);
+
+gchar* get_uuid_from_component (ESource *source,
+ ECalComponent *component);
+
+gint get_first_weekday (void);
+
+ECalComponent* build_component_from_details (const gchar *summary,
+ GDateTime *initial_date,
+ GDateTime *final_date);
+
+gint icaltime_compare_date (const icaltimetype *date1,
+ const icaltimetype *date2);
+
+gint icaltime_compare_with_current (const icaltimetype *date1,
+ const icaltimetype *date2,
+ time_t *current_time_t);
+
+GDateTime* get_start_of_week (icaltimetype *date);
+
+GDateTime* get_end_of_week (icaltimetype *date);
+
+gboolean is_clock_format_24h (void);
+
+/* code brought from evolution */
+gsize e_strftime_fix_am_pm (gchar *str,
+ gsize max,
+ const gchar *fmt,
+ const struct tm *tm);
+
+gsize e_utf8_strftime_fix_am_pm (gchar *str,
+ gsize max,
+ const gchar *fmt,
+ const struct tm *tm);
+
+void fix_popover_menu_icons (GtkPopover *popover);
+
+
+void get_source_parent_name_color (GcalManager *manager,
+ ESource *source,
+ gchar **name,
+ gchar **color);
+
+gchar* format_utc_offset (gint64 offset);
+
+gint get_alarm_trigger_minutes (GcalEvent *event,
+ ECalComponentAlarm *alarm);
+
+gboolean should_change_date_for_scroll (gdouble *scroll_value,
+ GdkEventScroll *scroll_event);
+
+gboolean is_source_enabled (ESource *source);
+
+gboolean ask_recurrence_modification_type (GtkWidget *parent,
+ GcalRecurrenceModType *modtype,
+ ESource *source);
+
+gboolean is_workday (guint day);
+
+GList* filter_event_list_by_uid_and_modtype (GList *widgets,
+ GcalRecurrenceModType mod,
+ const gchar *uid);
+
+gboolean gcal_translate_child_window_position (GtkWidget *target,
+ GdkWindow *child_window,
+ gdouble src_x,
+ gdouble src_y,
+ gdouble *real_x,
+ gdouble *real_y);
+#endif /* __GCAL_UTILS_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]