Reimplement event drag n' drop
Reintroduce the code using GTK4 tooling for in-process DnD. This is looking much better!
This commit is contained in:
@@ -48,6 +48,7 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
GCAL_RECURRENCE_MOD_NONE = 0,
|
||||||
GCAL_RECURRENCE_MOD_THIS_ONLY = E_CAL_OBJ_MOD_THIS,
|
GCAL_RECURRENCE_MOD_THIS_ONLY = E_CAL_OBJ_MOD_THIS,
|
||||||
GCAL_RECURRENCE_MOD_THIS_AND_FUTURE = E_CAL_OBJ_MOD_THIS_AND_FUTURE,
|
GCAL_RECURRENCE_MOD_THIS_AND_FUTURE = E_CAL_OBJ_MOD_THIS_AND_FUTURE,
|
||||||
GCAL_RECURRENCE_MOD_ALL = E_CAL_OBJ_MOD_ALL,
|
GCAL_RECURRENCE_MOD_ALL = E_CAL_OBJ_MOD_ALL,
|
||||||
|
|||||||
+95
-112
@@ -88,92 +88,23 @@ update_style_flags (GcalMonthCell *self)
|
|||||||
gtk_widget_remove_css_class (GTK_WIDGET (self), "today");
|
gtk_widget_remove_css_class (GTK_WIDGET (self), "today");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callbacks
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
day_changed_cb (GcalClock *clock,
|
move_event (GcalMonthCell *self,
|
||||||
GcalMonthCell *self)
|
GcalEvent *event,
|
||||||
|
GcalRecurrenceModType mod_type)
|
||||||
{
|
{
|
||||||
update_style_flags (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
overflow_button_clicked_cb (GtkWidget *button,
|
|
||||||
GcalMonthCell *self)
|
|
||||||
{
|
|
||||||
g_signal_emit (self, signals[SHOW_OVERFLOW], 0, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GtkWidget overrides
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gcal_month_cell_drag_motion (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
GcalMonthCell *self;
|
|
||||||
|
|
||||||
self = GCAL_MONTH_CELL (widget);
|
|
||||||
|
|
||||||
if (self->different_month)
|
|
||||||
gtk_drag_unhighlight (widget);
|
|
||||||
else
|
|
||||||
gtk_drag_highlight (widget);
|
|
||||||
|
|
||||||
gdk_drag_status (context, self->different_month ? 0 : GDK_ACTION_MOVE, time);
|
|
||||||
|
|
||||||
return !self->different_month;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gcal_month_cell_drag_drop (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
g_autoptr (GcalEvent) changed_event = NULL;
|
g_autoptr (GcalEvent) changed_event = NULL;
|
||||||
GcalRecurrenceModType mod;
|
g_autoptr (GDateTime) start_dt = NULL;
|
||||||
GcalMonthCell *self;
|
GTimeSpan timespan = 0;
|
||||||
GcalCalendar *calendar;
|
GDateTime *end_dt;
|
||||||
GtkWidget *event_widget;
|
|
||||||
GDateTime *start_dt, *end_dt;
|
|
||||||
GcalEvent *event;
|
|
||||||
gint diff;
|
gint diff;
|
||||||
gint start_month, current_month;
|
gint start_month, current_month;
|
||||||
gint start_year, current_year;
|
gint start_year, current_year;
|
||||||
GTimeSpan timespan = 0;
|
|
||||||
|
|
||||||
self = GCAL_MONTH_CELL (widget);
|
|
||||||
event_widget = gtk_drag_get_source_widget (context);
|
|
||||||
mod = GCAL_RECURRENCE_MOD_THIS_ONLY;
|
|
||||||
|
|
||||||
GCAL_ENTRY;
|
GCAL_ENTRY;
|
||||||
|
|
||||||
if (!GCAL_IS_EVENT_WIDGET (event_widget))
|
|
||||||
GCAL_RETURN (FALSE);
|
|
||||||
|
|
||||||
if (self->different_month)
|
|
||||||
GCAL_RETURN (FALSE);
|
|
||||||
|
|
||||||
event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (event_widget));
|
|
||||||
changed_event = gcal_event_new_from_event (event);
|
changed_event = gcal_event_new_from_event (event);
|
||||||
calendar = gcal_event_get_calendar (changed_event);
|
|
||||||
|
|
||||||
if (gcal_event_has_recurrence (changed_event) &&
|
|
||||||
!ask_recurrence_modification_type (widget, &mod, calendar))
|
|
||||||
{
|
|
||||||
GCAL_GOTO (out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move the event's date */
|
/* Move the event's date */
|
||||||
start_dt = gcal_event_get_date_start (changed_event);
|
start_dt = gcal_event_get_date_start (changed_event);
|
||||||
@@ -194,47 +125,107 @@ gcal_month_cell_drag_drop (GtkWidget *widget,
|
|||||||
|
|
||||||
diff = g_date_time_get_day_of_month (self->date) - g_date_time_get_day_of_month (start_dt);
|
diff = g_date_time_get_day_of_month (self->date) - g_date_time_get_day_of_month (start_dt);
|
||||||
|
|
||||||
if (diff != 0 ||
|
if (diff != 0 || current_month != start_month || current_year != start_year)
|
||||||
current_month != start_month ||
|
|
||||||
current_year != start_year)
|
|
||||||
{
|
{
|
||||||
g_autoptr (GDateTime) new_start = NULL;
|
g_autoptr (GDateTime) new_start = g_date_time_add_days (start_dt, diff);
|
||||||
|
|
||||||
new_start = g_date_time_add_days (start_dt, diff);
|
|
||||||
|
|
||||||
gcal_event_set_date_start (changed_event, new_start);
|
gcal_event_set_date_start (changed_event, new_start);
|
||||||
|
|
||||||
/* The event may have a NULL end date, so we have to check it here */
|
/* The event may have a NULL end date, so we have to check it here */
|
||||||
if (end_dt)
|
if (end_dt)
|
||||||
{
|
{
|
||||||
GDateTime *new_end = g_date_time_add (new_start, timespan);
|
g_autoptr (GDateTime) new_end = g_date_time_add (new_start, timespan);
|
||||||
|
|
||||||
gcal_event_set_date_end (changed_event, new_end);
|
gcal_event_set_date_end (changed_event, new_end);
|
||||||
g_clear_pointer (&new_end, g_date_time_unref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gcal_manager_update_event (gcal_context_get_manager (self->context), changed_event, mod);
|
gcal_manager_update_event (gcal_context_get_manager (self->context), changed_event, mod_type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_clear_pointer (&start_dt, g_date_time_unref);
|
|
||||||
|
|
||||||
out:
|
/*
|
||||||
/* Cancel the DnD */
|
* Callbacks
|
||||||
gtk_drag_unhighlight (widget);
|
*/
|
||||||
gtk_drag_finish (context, TRUE, FALSE, time);
|
|
||||||
|
static void
|
||||||
|
day_changed_cb (GcalClock *clock,
|
||||||
|
GcalMonthCell *self)
|
||||||
|
{
|
||||||
|
update_style_flags (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
overflow_button_clicked_cb (GtkWidget *button,
|
||||||
|
GcalMonthCell *self)
|
||||||
|
{
|
||||||
|
g_signal_emit (self, signals[SHOW_OVERFLOW], 0, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_drop_target_accept_cb (GtkDropTarget *drop_target,
|
||||||
|
GdkDrop *drop,
|
||||||
|
GcalMonthCell *self)
|
||||||
|
{
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
if ((gdk_drop_get_actions (drop) & gtk_drop_target_get_actions (drop_target)) == 0)
|
||||||
|
GCAL_RETURN (FALSE);
|
||||||
|
|
||||||
|
if (!gdk_content_formats_contain_gtype (gdk_drop_get_formats (drop), GCAL_TYPE_EVENT_WIDGET))
|
||||||
|
GCAL_RETURN (FALSE);
|
||||||
|
|
||||||
|
GCAL_RETURN (!self->different_month);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_ask_recurrence_response_cb (GcalEvent *event,
|
||||||
|
GcalRecurrenceModType mod_type,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GcalMonthCell *self = GCAL_MONTH_CELL (user_data);
|
||||||
|
|
||||||
|
if (mod_type != GCAL_RECURRENCE_MOD_NONE)
|
||||||
|
move_event (self, event, mod_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_drop_target_drop_cb (GtkDropTarget *drop_target,
|
||||||
|
const GValue *value,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
GcalMonthCell *self)
|
||||||
|
{
|
||||||
|
GcalEventWidget *event_widget;
|
||||||
|
GcalEvent *event;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
if (self->different_month)
|
||||||
|
GCAL_RETURN (FALSE);
|
||||||
|
|
||||||
|
if (!G_VALUE_HOLDS (value, GCAL_TYPE_EVENT_WIDGET))
|
||||||
|
GCAL_RETURN (FALSE);
|
||||||
|
|
||||||
|
event_widget = g_value_get_object (value);
|
||||||
|
|
||||||
|
event = gcal_event_widget_get_event (event_widget);
|
||||||
|
|
||||||
|
if (gcal_event_has_recurrence (event))
|
||||||
|
{
|
||||||
|
gcal_utils_ask_recurrence_modification_type (GTK_WIDGET (self),
|
||||||
|
event,
|
||||||
|
on_ask_recurrence_response_cb,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move_event (self, event, GCAL_RECURRENCE_MOD_THIS_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
GCAL_RETURN (TRUE);
|
GCAL_RETURN (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gcal_month_cell_drag_leave (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
gtk_drag_unhighlight (widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GObject overrides
|
* GObject overrides
|
||||||
@@ -302,12 +293,6 @@ gcal_month_cell_class_init (GcalMonthCellClass *klass)
|
|||||||
object_class->set_property = gcal_month_cell_set_property;
|
object_class->set_property = gcal_month_cell_set_property;
|
||||||
object_class->get_property = gcal_month_cell_get_property;
|
object_class->get_property = gcal_month_cell_get_property;
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
|
||||||
widget_class->drag_motion = gcal_month_cell_drag_motion;
|
|
||||||
widget_class->drag_drop = gcal_month_cell_drag_drop;
|
|
||||||
widget_class->drag_leave = gcal_month_cell_drag_leave;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
signals[SHOW_OVERFLOW] = g_signal_new ("show-overflow",
|
signals[SHOW_OVERFLOW] = g_signal_new ("show-overflow",
|
||||||
GCAL_TYPE_MONTH_CELL,
|
GCAL_TYPE_MONTH_CELL,
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
@@ -342,16 +327,14 @@ gcal_month_cell_class_init (GcalMonthCellClass *klass)
|
|||||||
static void
|
static void
|
||||||
gcal_month_cell_init (GcalMonthCell *self)
|
gcal_month_cell_init (GcalMonthCell *self)
|
||||||
{
|
{
|
||||||
|
GtkDropTarget *drop_target;
|
||||||
|
|
||||||
gtk_widget_init_template (GTK_WIDGET (self));
|
gtk_widget_init_template (GTK_WIDGET (self));
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
drop_target = gtk_drop_target_new (GCAL_TYPE_EVENT_WIDGET, GDK_ACTION_COPY);
|
||||||
/* Setup the month cell as a drag n' drop destination */
|
g_signal_connect (drop_target, "accept", G_CALLBACK (on_drop_target_accept_cb), self);
|
||||||
gtk_drag_dest_set (GTK_WIDGET (self),
|
g_signal_connect (drop_target, "drop", G_CALLBACK (on_drop_target_drop_cb), self);
|
||||||
0,
|
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drop_target));
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
GDK_ACTION_MOVE);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget*
|
GtkWidget*
|
||||||
|
|||||||
+163
-162
@@ -35,6 +35,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GcalWeekGrid *self;
|
||||||
|
GcalEvent *event;
|
||||||
|
gint drop_cell;
|
||||||
|
} DropData;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
@@ -322,6 +329,156 @@ on_click_gesture_released_cb (GtkGestureClick *click_gesture,
|
|||||||
gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_NONE);
|
gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
get_dnd_cell (GcalWeekGrid *self,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y)
|
||||||
|
{
|
||||||
|
GtkAllocation alloc;
|
||||||
|
gdouble column_width, cell_height;
|
||||||
|
gint column, row;
|
||||||
|
|
||||||
|
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||||
|
|
||||||
|
column_width = alloc.width / 7.0;
|
||||||
|
cell_height = alloc.height / 48.0;
|
||||||
|
column = floor (x / column_width);
|
||||||
|
row = y / cell_height;
|
||||||
|
|
||||||
|
return column * 48 + row;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
move_event_to_cell (GcalWeekGrid *self,
|
||||||
|
GcalEvent *event,
|
||||||
|
guint cell,
|
||||||
|
GcalRecurrenceModType mod_type)
|
||||||
|
{
|
||||||
|
|
||||||
|
g_autoptr (GDateTime) week_start = NULL;
|
||||||
|
g_autoptr (GDateTime) dnd_date = NULL;
|
||||||
|
g_autoptr (GDateTime) new_end = NULL;
|
||||||
|
g_autoptr (GcalEvent) changed_event = NULL;
|
||||||
|
GTimeSpan timespan = 0;
|
||||||
|
|
||||||
|
/* RTL languages swap the drop cell column */
|
||||||
|
if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
|
||||||
|
{
|
||||||
|
gint column, row;
|
||||||
|
|
||||||
|
column = cell / (MINUTES_PER_DAY / 30);
|
||||||
|
row = cell - column * 48;
|
||||||
|
|
||||||
|
cell = (6 - column) * 48 + row;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed_event = gcal_event_new_from_event (event);
|
||||||
|
week_start = gcal_date_time_get_start_of_week (self->active_date);
|
||||||
|
dnd_date = g_date_time_add_minutes (week_start, cell * 30);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the diff between the dropped cell and the event's start date,
|
||||||
|
* so we can update the end date accordingly.
|
||||||
|
*/
|
||||||
|
timespan = g_date_time_difference (gcal_event_get_date_end (changed_event), gcal_event_get_date_start (changed_event));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the event's start and end dates. Since the event may have a
|
||||||
|
* NULL end date, so we have to check it here
|
||||||
|
*/
|
||||||
|
gcal_event_set_all_day (changed_event, FALSE);
|
||||||
|
gcal_event_set_date_start (changed_event, dnd_date);
|
||||||
|
|
||||||
|
/* Setup the new end date */
|
||||||
|
new_end = g_date_time_add (dnd_date, timespan);
|
||||||
|
gcal_event_set_date_end (changed_event, new_end);
|
||||||
|
|
||||||
|
/* Commit the changes */
|
||||||
|
gcal_manager_update_event (gcal_context_get_manager (self->context), changed_event, mod_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_ask_recurrence_response_cb (GcalEvent *event,
|
||||||
|
GcalRecurrenceModType mod_type,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
DropData *data = user_data;
|
||||||
|
|
||||||
|
if (mod_type != GCAL_RECURRENCE_MOD_NONE)
|
||||||
|
move_event_to_cell (data->self, data->event, data->drop_cell, mod_type);
|
||||||
|
|
||||||
|
g_clear_object (&data->event);
|
||||||
|
g_clear_pointer (&data, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_drop_target_drop_cb (GtkDropTarget *drop_target,
|
||||||
|
const GValue *value,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
GcalWeekGrid *self)
|
||||||
|
{
|
||||||
|
GcalEventWidget *event_widget;
|
||||||
|
GcalEvent *event;
|
||||||
|
gint cell;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
if (!G_VALUE_HOLDS (value, GCAL_TYPE_EVENT_WIDGET))
|
||||||
|
GCAL_RETURN (FALSE);
|
||||||
|
|
||||||
|
cell = get_dnd_cell (self, x, y);
|
||||||
|
event_widget = g_value_get_object (value);
|
||||||
|
event = gcal_event_widget_get_event (event_widget);
|
||||||
|
|
||||||
|
if (gcal_event_has_recurrence (event))
|
||||||
|
{
|
||||||
|
DropData *data;
|
||||||
|
|
||||||
|
data = g_new0 (DropData, 1);
|
||||||
|
data->self = self;
|
||||||
|
data->event = g_object_ref (event);
|
||||||
|
data->drop_cell = cell;
|
||||||
|
|
||||||
|
gcal_utils_ask_recurrence_modification_type (GTK_WIDGET (self),
|
||||||
|
event,
|
||||||
|
on_ask_recurrence_response_cb,
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move_event_to_cell (self, event, cell, GCAL_RECURRENCE_MOD_THIS_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCAL_RETURN (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_drop_target_leave_cb (GtkDropTarget *drop_target,
|
||||||
|
GcalWeekGrid *self)
|
||||||
|
{
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self->dnd_cell = -1;
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkDragAction
|
||||||
|
on_drop_target_motion_cb (GtkDropTarget *drop_target,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
GcalWeekGrid *self)
|
||||||
|
{
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self->dnd_cell = get_dnd_cell (self, x, y);
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
GCAL_RETURN (self->dnd_cell != -1 ? GDK_ACTION_COPY : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gcal_week_grid_dispose (GObject *object)
|
gcal_week_grid_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -689,160 +846,6 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
|
||||||
static gint
|
|
||||||
get_dnd_cell (GtkWidget *widget,
|
|
||||||
gint x,
|
|
||||||
gint y)
|
|
||||||
{
|
|
||||||
GtkAllocation alloc;
|
|
||||||
gdouble column_width, cell_height;
|
|
||||||
gint column, row;
|
|
||||||
|
|
||||||
gtk_widget_get_allocation (widget, &alloc);
|
|
||||||
|
|
||||||
column_width = alloc.width / 7.0;
|
|
||||||
cell_height = alloc.height / 48.0;
|
|
||||||
column = floor (x / column_width);
|
|
||||||
row = y / cell_height;
|
|
||||||
|
|
||||||
return column * 48 + row;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gcal_week_grid_drag_motion (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
GcalWeekGrid *self;
|
|
||||||
|
|
||||||
self = GCAL_WEEK_GRID (widget);
|
|
||||||
self->dnd_cell = get_dnd_cell (widget, x, y);
|
|
||||||
|
|
||||||
/* Setup the drag highlight */
|
|
||||||
if (self->dnd_cell != -1)
|
|
||||||
gtk_drag_highlight (widget);
|
|
||||||
else
|
|
||||||
gtk_drag_unhighlight (widget);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the status of the drag - if it fails, sets the action to 0 and
|
|
||||||
* aborts the drag with FALSE.
|
|
||||||
*/
|
|
||||||
gdk_drag_status (context,
|
|
||||||
self->dnd_cell == -1 ? 0 : GDK_ACTION_MOVE,
|
|
||||||
time);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
return self->dnd_cell != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gcal_week_grid_drag_drop (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
g_autoptr (GDateTime) week_start = NULL;
|
|
||||||
g_autoptr (GDateTime) dnd_date = NULL;
|
|
||||||
g_autoptr (GDateTime) new_end = NULL;
|
|
||||||
g_autoptr (GcalEvent) changed_event = NULL;
|
|
||||||
GcalRecurrenceModType mod;
|
|
||||||
GcalWeekGrid *self;
|
|
||||||
GcalCalendar *calendar;
|
|
||||||
GtkWidget *event_widget;
|
|
||||||
GcalEvent *event;
|
|
||||||
GTimeSpan timespan = 0;
|
|
||||||
gboolean ltr;
|
|
||||||
gint drop_cell;
|
|
||||||
|
|
||||||
self = GCAL_WEEK_GRID (widget);
|
|
||||||
ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
|
|
||||||
drop_cell = get_dnd_cell (widget, x, y);
|
|
||||||
event_widget = gtk_drag_get_source_widget (context);
|
|
||||||
|
|
||||||
mod = GCAL_RECURRENCE_MOD_THIS_ONLY;
|
|
||||||
|
|
||||||
if (!GCAL_IS_EVENT_WIDGET (event_widget))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* RTL languages swap the drop cell column */
|
|
||||||
if (!ltr)
|
|
||||||
{
|
|
||||||
gint column, row;
|
|
||||||
|
|
||||||
column = drop_cell / (MINUTES_PER_DAY / 30);
|
|
||||||
row = drop_cell - column * 48;
|
|
||||||
|
|
||||||
drop_cell = (6 - column) * 48 + row;
|
|
||||||
}
|
|
||||||
|
|
||||||
event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (event_widget));
|
|
||||||
changed_event = gcal_event_new_from_event (event);
|
|
||||||
calendar = gcal_event_get_calendar (changed_event);
|
|
||||||
|
|
||||||
if (gcal_event_has_recurrence (changed_event) &&
|
|
||||||
!ask_recurrence_modification_type (widget, &mod, calendar))
|
|
||||||
{
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
week_start = gcal_date_time_get_start_of_week (self->active_date);
|
|
||||||
dnd_date = g_date_time_add_minutes (week_start, drop_cell * 30);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the diff between the dropped cell and the event's start date,
|
|
||||||
* so we can update the end date accordingly.
|
|
||||||
*/
|
|
||||||
timespan = g_date_time_difference (gcal_event_get_date_end (changed_event), gcal_event_get_date_start (changed_event));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the event's start and end dates. Since the event may have a
|
|
||||||
* NULL end date, so we have to check it here
|
|
||||||
*/
|
|
||||||
gcal_event_set_all_day (changed_event, FALSE);
|
|
||||||
gcal_event_set_date_start (changed_event, dnd_date);
|
|
||||||
|
|
||||||
|
|
||||||
/* Setup the new end date */
|
|
||||||
new_end = g_date_time_add (dnd_date, timespan);
|
|
||||||
gcal_event_set_date_end (changed_event, new_end);
|
|
||||||
|
|
||||||
/* Commit the changes */
|
|
||||||
|
|
||||||
gcal_manager_update_event (gcal_context_get_manager (self->context), changed_event, mod);
|
|
||||||
|
|
||||||
out:
|
|
||||||
/* Cancel the DnD */
|
|
||||||
self->dnd_cell = -1;
|
|
||||||
gtk_drag_unhighlight (widget);
|
|
||||||
|
|
||||||
gtk_drag_finish (context, TRUE, FALSE, time);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gcal_week_grid_drag_leave (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
GcalWeekGrid *self = GCAL_WEEK_GRID (widget);
|
|
||||||
|
|
||||||
/* Cancel the drag */
|
|
||||||
self->dnd_cell = -1;
|
|
||||||
gtk_drag_unhighlight (widget);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gcal_week_grid_class_init (GcalWeekGridClass *klass)
|
gcal_week_grid_class_init (GcalWeekGridClass *klass)
|
||||||
{
|
{
|
||||||
@@ -872,6 +875,7 @@ gcal_week_grid_class_init (GcalWeekGridClass *klass)
|
|||||||
static void
|
static void
|
||||||
gcal_week_grid_init (GcalWeekGrid *self)
|
gcal_week_grid_init (GcalWeekGrid *self)
|
||||||
{
|
{
|
||||||
|
GtkDropTarget *drop_target;
|
||||||
GtkGesture *click_gesture;
|
GtkGesture *click_gesture;
|
||||||
|
|
||||||
self->selection_start = -1;
|
self->selection_start = -1;
|
||||||
@@ -896,14 +900,11 @@ gcal_week_grid_init (GcalWeekGrid *self)
|
|||||||
gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_NONE);
|
gtk_event_controller_set_propagation_phase (self->motion_controller, GTK_PHASE_NONE);
|
||||||
gtk_widget_add_controller (GTK_WIDGET (self), self->motion_controller);
|
gtk_widget_add_controller (GTK_WIDGET (self), self->motion_controller);
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
drop_target = gtk_drop_target_new (GCAL_TYPE_EVENT_WIDGET, GDK_ACTION_COPY);
|
||||||
/* Setup the week view as a drag n' drop destination */
|
g_signal_connect (drop_target, "drop", G_CALLBACK (on_drop_target_drop_cb), self);
|
||||||
gtk_drag_dest_set (GTK_WIDGET (self),
|
g_signal_connect (drop_target, "leave", G_CALLBACK (on_drop_target_leave_cb), self);
|
||||||
0,
|
g_signal_connect (drop_target, "motion", G_CALLBACK (on_drop_target_motion_cb), self);
|
||||||
NULL,
|
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drop_target));
|
||||||
0,
|
|
||||||
GDK_ACTION_MOVE);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public API */
|
/* Public API */
|
||||||
|
|||||||
+178
-156
@@ -60,6 +60,13 @@ typedef struct
|
|||||||
GtkWidget *weekday_name_label;
|
GtkWidget *weekday_name_label;
|
||||||
} WeekdayHeader;
|
} WeekdayHeader;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GcalWeekHeader *self;
|
||||||
|
GcalEvent *event;
|
||||||
|
gint drop_cell;
|
||||||
|
} DropData;
|
||||||
|
|
||||||
struct _GcalWeekHeader
|
struct _GcalWeekHeader
|
||||||
{
|
{
|
||||||
GtkBox parent;
|
GtkBox parent;
|
||||||
@@ -1144,6 +1151,171 @@ on_expand_action_activated (GcalWeekHeader *self,
|
|||||||
header_expand (self);
|
header_expand (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
get_dnd_cell (GcalWeekHeader *self,
|
||||||
|
gint x,
|
||||||
|
gint y)
|
||||||
|
{
|
||||||
|
gdouble column_width;
|
||||||
|
|
||||||
|
column_width = gtk_widget_get_allocated_width (GTK_WIDGET (self)) / 7.0;
|
||||||
|
|
||||||
|
return x / column_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
move_event_to_cell (GcalWeekHeader *self,
|
||||||
|
GcalEvent *event,
|
||||||
|
guint cell,
|
||||||
|
GcalRecurrenceModType mod_type)
|
||||||
|
{
|
||||||
|
g_autoptr (GDateTime) week_start = NULL;
|
||||||
|
g_autoptr (GDateTime) dnd_date = NULL;
|
||||||
|
g_autoptr (GDateTime) new_end = NULL;
|
||||||
|
g_autoptr (GDateTime) tmp_dt = NULL;
|
||||||
|
g_autoptr (GcalEvent) changed_event = NULL;
|
||||||
|
GDateTime *start_date;
|
||||||
|
GDateTime *end_date;
|
||||||
|
GTimeSpan difference;
|
||||||
|
gboolean turn_all_day;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
/* RTL languages swap the drop cell column */
|
||||||
|
if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
|
||||||
|
cell = 6 - cell;
|
||||||
|
|
||||||
|
changed_event = gcal_event_new_from_event (event);
|
||||||
|
start_date = gcal_event_get_date_start (changed_event);
|
||||||
|
end_date = gcal_event_get_date_end (changed_event);
|
||||||
|
week_start = gcal_date_time_get_start_of_week (self->active_date);
|
||||||
|
|
||||||
|
turn_all_day = !gcal_event_is_multiday (changed_event) || gcal_event_get_all_day (changed_event);
|
||||||
|
|
||||||
|
if (!turn_all_day)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The only case where we don't touch the timezone is for
|
||||||
|
* timed, multiday events.
|
||||||
|
*/
|
||||||
|
tmp_dt = g_date_time_new (g_date_time_get_timezone (start_date),
|
||||||
|
g_date_time_get_year (week_start),
|
||||||
|
g_date_time_get_month (week_start),
|
||||||
|
g_date_time_get_day_of_month (week_start),
|
||||||
|
g_date_time_get_hour (start_date),
|
||||||
|
g_date_time_get_minute (start_date),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp_dt = g_date_time_new_utc (g_date_time_get_year (week_start),
|
||||||
|
g_date_time_get_month (week_start),
|
||||||
|
g_date_time_get_day_of_month (week_start),
|
||||||
|
0, 0, 0);
|
||||||
|
}
|
||||||
|
dnd_date = g_date_time_add_days (tmp_dt, cell);
|
||||||
|
|
||||||
|
/* End date */
|
||||||
|
difference = turn_all_day ? 24 : g_date_time_difference (end_date, start_date) / G_TIME_SPAN_HOUR;
|
||||||
|
|
||||||
|
new_end = g_date_time_add_hours (dnd_date, difference);
|
||||||
|
gcal_event_set_date_end (changed_event, new_end);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the start date ~after~ the end date, so we can compare
|
||||||
|
* the event's start and end dates above
|
||||||
|
*/
|
||||||
|
gcal_event_set_date_start (changed_event, dnd_date);
|
||||||
|
|
||||||
|
if (turn_all_day)
|
||||||
|
gcal_event_set_all_day (changed_event, TRUE);
|
||||||
|
|
||||||
|
/* Commit the changes */
|
||||||
|
gcal_manager_update_event (gcal_context_get_manager (self->context), changed_event, mod_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_ask_recurrence_response_cb (GcalEvent *event,
|
||||||
|
GcalRecurrenceModType mod_type,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
DropData *data = user_data;
|
||||||
|
|
||||||
|
if (mod_type != GCAL_RECURRENCE_MOD_NONE)
|
||||||
|
move_event_to_cell (data->self, data->event, data->drop_cell, mod_type);
|
||||||
|
|
||||||
|
g_clear_object (&data->event);
|
||||||
|
g_clear_pointer (&data, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_drop_target_drop_cb (GtkDropTarget *drop_target,
|
||||||
|
const GValue *value,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
GcalWeekHeader *self)
|
||||||
|
{
|
||||||
|
GcalEventWidget *event_widget;
|
||||||
|
GcalEvent *event;
|
||||||
|
gint cell;
|
||||||
|
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
if (!G_VALUE_HOLDS (value, GCAL_TYPE_EVENT_WIDGET))
|
||||||
|
GCAL_RETURN (FALSE);
|
||||||
|
|
||||||
|
cell = get_dnd_cell (self, x, y);
|
||||||
|
event_widget = g_value_get_object (value);
|
||||||
|
event = gcal_event_widget_get_event (event_widget);
|
||||||
|
|
||||||
|
if (gcal_event_has_recurrence (event))
|
||||||
|
{
|
||||||
|
DropData *data;
|
||||||
|
|
||||||
|
data = g_new0 (DropData, 1);
|
||||||
|
data->self = self;
|
||||||
|
data->event = g_object_ref (event);
|
||||||
|
data->drop_cell = cell;
|
||||||
|
|
||||||
|
gcal_utils_ask_recurrence_modification_type (GTK_WIDGET (self),
|
||||||
|
event,
|
||||||
|
on_ask_recurrence_response_cb,
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move_event_to_cell (self, event, cell, GCAL_RECURRENCE_MOD_THIS_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCAL_RETURN (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_drop_target_leave_cb (GtkDropTarget *drop_target,
|
||||||
|
GcalWeekHeader *self)
|
||||||
|
{
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self->dnd_cell = -1;
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
GCAL_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkDragAction
|
||||||
|
on_drop_target_motion_cb (GtkDropTarget *drop_target,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
GcalWeekHeader *self)
|
||||||
|
{
|
||||||
|
GCAL_ENTRY;
|
||||||
|
|
||||||
|
self->dnd_cell = get_dnd_cell (self, x, y);
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
GCAL_RETURN (self->dnd_cell != -1 ? GDK_ACTION_COPY : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Drawing area content and size */
|
/* Drawing area content and size */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1264,154 +1436,6 @@ gcal_week_header_snapshot (GtkWidget *widget,
|
|||||||
g_clear_pointer (&week_end, g_date_time_unref);
|
g_clear_pointer (&week_end, g_date_time_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
|
||||||
static gint
|
|
||||||
get_dnd_cell (GtkWidget *widget,
|
|
||||||
gint x,
|
|
||||||
gint y)
|
|
||||||
{
|
|
||||||
gdouble column_width;
|
|
||||||
|
|
||||||
column_width = gtk_widget_get_allocated_width (widget) / 7.0;
|
|
||||||
|
|
||||||
return x / column_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gcal_week_header_drag_motion (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
GcalWeekHeader *self;
|
|
||||||
|
|
||||||
self = GCAL_WEEK_HEADER (widget);
|
|
||||||
self->dnd_cell = get_dnd_cell (widget, x, y);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the status of the drag - if it fails, sets the action to 0 and
|
|
||||||
* aborts the drag with FALSE.
|
|
||||||
*/
|
|
||||||
gdk_drag_status (context,
|
|
||||||
self->dnd_cell == -1 ? 0 : GDK_ACTION_MOVE,
|
|
||||||
time);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
return self->dnd_cell != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gcal_week_header_drag_drop (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
g_autoptr (GDateTime) week_start = NULL;
|
|
||||||
g_autoptr (GDateTime) dnd_date = NULL;
|
|
||||||
g_autoptr (GDateTime) new_end = NULL;
|
|
||||||
g_autoptr (GDateTime) tmp_dt = NULL;
|
|
||||||
g_autoptr (GcalEvent) changed_event = NULL;
|
|
||||||
GcalWeekHeader *self;
|
|
||||||
GDateTime *start_date;
|
|
||||||
GDateTime *end_date;
|
|
||||||
GTimeSpan difference;
|
|
||||||
GtkWidget *event_widget;
|
|
||||||
GcalEvent *event;
|
|
||||||
gboolean turn_all_day;
|
|
||||||
gboolean ltr;
|
|
||||||
gint drop_cell;
|
|
||||||
|
|
||||||
GCAL_ENTRY;
|
|
||||||
|
|
||||||
self = GCAL_WEEK_HEADER (widget);
|
|
||||||
ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
|
|
||||||
drop_cell = get_dnd_cell (widget, x, y);
|
|
||||||
event_widget = gtk_drag_get_source_widget (context);
|
|
||||||
|
|
||||||
if (!GCAL_IS_EVENT_WIDGET (event_widget))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* RTL languages swap the drop cell column */
|
|
||||||
if (!ltr)
|
|
||||||
drop_cell = 6 - drop_cell;
|
|
||||||
|
|
||||||
event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (event_widget));
|
|
||||||
changed_event = gcal_event_new_from_event (event);
|
|
||||||
start_date = gcal_event_get_date_start (changed_event);
|
|
||||||
end_date = gcal_event_get_date_end (changed_event);
|
|
||||||
week_start = gcal_date_time_get_start_of_week (self->active_date);
|
|
||||||
|
|
||||||
turn_all_day = !gcal_event_is_multiday (changed_event) || gcal_event_get_all_day (changed_event);
|
|
||||||
|
|
||||||
if (!turn_all_day)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The only case where we don't touch the timezone is for
|
|
||||||
* timed, multiday events.
|
|
||||||
*/
|
|
||||||
tmp_dt = g_date_time_new (g_date_time_get_timezone (start_date),
|
|
||||||
g_date_time_get_year (week_start),
|
|
||||||
g_date_time_get_month (week_start),
|
|
||||||
g_date_time_get_day_of_month (week_start),
|
|
||||||
g_date_time_get_hour (start_date),
|
|
||||||
g_date_time_get_minute (start_date),
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp_dt = g_date_time_new_utc (g_date_time_get_year (week_start),
|
|
||||||
g_date_time_get_month (week_start),
|
|
||||||
g_date_time_get_day_of_month (week_start),
|
|
||||||
0, 0, 0);
|
|
||||||
}
|
|
||||||
dnd_date = g_date_time_add_days (tmp_dt, drop_cell);
|
|
||||||
|
|
||||||
/* End date */
|
|
||||||
difference = turn_all_day ? 24 : g_date_time_difference (end_date, start_date) / G_TIME_SPAN_HOUR;
|
|
||||||
|
|
||||||
new_end = g_date_time_add_hours (dnd_date, difference);
|
|
||||||
gcal_event_set_date_end (changed_event, new_end);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the start date ~after~ the end date, so we can compare
|
|
||||||
* the event's start and end dates above
|
|
||||||
*/
|
|
||||||
gcal_event_set_date_start (changed_event, dnd_date);
|
|
||||||
|
|
||||||
if (turn_all_day)
|
|
||||||
gcal_event_set_all_day (changed_event, TRUE);
|
|
||||||
|
|
||||||
/* Commit the changes */
|
|
||||||
gcal_manager_update_event (gcal_context_get_manager (self->context),
|
|
||||||
changed_event,
|
|
||||||
GCAL_RECURRENCE_MOD_THIS_ONLY);
|
|
||||||
|
|
||||||
/* Cancel the DnD */
|
|
||||||
self->dnd_cell = -1;
|
|
||||||
|
|
||||||
gtk_drag_finish (context, TRUE, FALSE, time);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
GCAL_RETURN (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gcal_week_header_drag_leave (GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
guint time)
|
|
||||||
{
|
|
||||||
GcalWeekHeader *self = GCAL_WEEK_HEADER (widget);
|
|
||||||
|
|
||||||
/* Cancel the drag */
|
|
||||||
self->dnd_cell = -1;
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GObject overrides
|
* GObject overrides
|
||||||
@@ -1477,6 +1501,7 @@ gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
|
|||||||
static void
|
static void
|
||||||
gcal_week_header_init (GcalWeekHeader *self)
|
gcal_week_header_init (GcalWeekHeader *self)
|
||||||
{
|
{
|
||||||
|
GtkDropTarget *drop_target;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
self->expanded = FALSE;
|
self->expanded = FALSE;
|
||||||
@@ -1515,14 +1540,11 @@ gcal_week_header_init (GcalWeekHeader *self)
|
|||||||
gtk_grid_attach (self->grid, gtk_box_new (GTK_ORIENTATION_VERTICAL, 0), i, 0, 1, 1);
|
gtk_grid_attach (self->grid, gtk_box_new (GTK_ORIENTATION_VERTICAL, 0), i, 0, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO: DND
|
drop_target = gtk_drop_target_new (GCAL_TYPE_EVENT_WIDGET, GDK_ACTION_COPY);
|
||||||
/* Setup the week header as a drag n' drop destination */
|
g_signal_connect (drop_target, "drop", G_CALLBACK (on_drop_target_drop_cb), self);
|
||||||
gtk_drag_dest_set (GTK_WIDGET (self),
|
g_signal_connect (drop_target, "leave", G_CALLBACK (on_drop_target_leave_cb), self);
|
||||||
0,
|
g_signal_connect (drop_target, "motion", G_CALLBACK (on_drop_target_motion_cb), self);
|
||||||
NULL,
|
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drop_target));
|
||||||
0,
|
|
||||||
GDK_ACTION_MOVE);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -328,6 +328,9 @@ weekgrid:selected,
|
|||||||
background-color: alpha(@accent_bg_color, 0.25);
|
background-color: alpha(@accent_bg_color, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
weekgrid.dnd, .week-header.dnd {
|
||||||
|
background-color: alpha(@accent_bg_color, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Month cell
|
* Month cell
|
||||||
|
|||||||
@@ -1332,3 +1332,86 @@ out:
|
|||||||
if (out_meeting_url)
|
if (out_meeting_url)
|
||||||
*out_meeting_url = g_steal_pointer (&meeting_url);
|
*out_meeting_url = g_steal_pointer (&meeting_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GcalEvent *event;
|
||||||
|
GcalAskRecurrenceCallback callback;
|
||||||
|
gpointer user_data;
|
||||||
|
} AskRecurrenceData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_message_dialog_response_cb (GtkDialog *dialog,
|
||||||
|
gint response,
|
||||||
|
AskRecurrenceData *data)
|
||||||
|
{
|
||||||
|
GcalRecurrenceModType mod_type;
|
||||||
|
|
||||||
|
switch (response)
|
||||||
|
{
|
||||||
|
case GTK_RESPONSE_CANCEL:
|
||||||
|
mod_type = GCAL_RECURRENCE_MOD_NONE;
|
||||||
|
break;
|
||||||
|
case GTK_RESPONSE_ACCEPT:
|
||||||
|
mod_type = GCAL_RECURRENCE_MOD_THIS_ONLY;
|
||||||
|
break;
|
||||||
|
case GTK_RESPONSE_OK:
|
||||||
|
mod_type = GCAL_RECURRENCE_MOD_THIS_AND_FUTURE;
|
||||||
|
break;
|
||||||
|
case GTK_RESPONSE_YES:
|
||||||
|
mod_type = GCAL_RECURRENCE_MOD_ALL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mod_type = GCAL_RECURRENCE_MOD_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_destroy (GTK_WINDOW (dialog));
|
||||||
|
|
||||||
|
data->callback (data->event, mod_type, data->user_data);
|
||||||
|
g_clear_object (&data->event);
|
||||||
|
g_clear_pointer (&data, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gcal_utils_ask_recurrence_modification_type (GtkWidget *parent,
|
||||||
|
GcalEvent *event,
|
||||||
|
GcalAskRecurrenceCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
AskRecurrenceData *data;
|
||||||
|
GtkDialogFlags flags;
|
||||||
|
ECalClient *client;
|
||||||
|
GtkWidget *dialog;
|
||||||
|
|
||||||
|
data = g_new0 (AskRecurrenceData, 1);
|
||||||
|
data->event = g_object_ref (event);
|
||||||
|
data->callback = callback;
|
||||||
|
data->user_data = user_data;
|
||||||
|
|
||||||
|
flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
|
||||||
|
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_native (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 = gcal_calendar_get_client (gcal_event_get_calendar (event));
|
||||||
|
|
||||||
|
if (!e_client_check_capability (E_CLIENT (client), E_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_native (parent)));
|
||||||
|
g_signal_connect (dialog, "response", G_CALLBACK (on_message_dialog_response_cb), data);
|
||||||
|
|
||||||
|
gtk_window_present (GTK_WINDOW (dialog));
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ECalComponent, g_object_unref)
|
|||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GWeatherLocation, gweather_location_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GWeatherLocation, gweather_location_unref)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (*GcalAskRecurrenceCallback) (GcalEvent *event,
|
||||||
|
GcalRecurrenceModType modtype,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ICalTime, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ICalTime, g_object_unref)
|
||||||
|
|
||||||
gchar* gcal_get_weekday (gint i);
|
gchar* gcal_get_weekday (gint i);
|
||||||
@@ -130,4 +134,9 @@ void gcal_utils_extract_google_section (const gchar
|
|||||||
gchar **out_description,
|
gchar **out_description,
|
||||||
gchar **out_meeting_url);
|
gchar **out_meeting_url);
|
||||||
|
|
||||||
|
void gcal_utils_ask_recurrence_modification_type (GtkWidget *parent,
|
||||||
|
GcalEvent *event,
|
||||||
|
GcalAskRecurrenceCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
#endif /* __GCAL_UTILS_H__ */
|
#endif /* __GCAL_UTILS_H__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user