month-view: Show weather reports.
This commit triggers two existing issues:
1. window size calculation
(this breaks month-cells)
2. wrong reference counts in views
(I use :destroy to avoid dangling pointers)
This commit is contained in:
committed by
Georges Basile Stavracas Neto
parent
9ac45e840d
commit
e9e403ce7a
+2
-1
@@ -1670,13 +1670,14 @@ gcal_window_init (GcalWindow *self)
|
||||
* FIXME: this is a hack around the issue that happens when trying to bind
|
||||
* there properties using the GtkBuilder .ui file.
|
||||
*/
|
||||
g_object_bind_property (self, "weather-service", self->week_view, "weather-service", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->edit_dialog, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->source_dialog, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->week_view, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->month_view, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->year_view, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->quick_add_popover, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "weather-service", self->week_view, "weather-service", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "weather-service", self->month_view, "weather-service", G_BINDING_DEFAULT);
|
||||
|
||||
/* setup accels */
|
||||
app = g_application_get_default ();
|
||||
|
||||
@@ -33,6 +33,8 @@ struct _GcalMonthCell
|
||||
|
||||
GtkLabel *day_label;
|
||||
GtkWidget *header_box;
|
||||
GtkImage *weather_icon;
|
||||
|
||||
GtkWidget *overflow_button;
|
||||
GtkWidget *overflow_label;
|
||||
GtkWidget *overlay;
|
||||
@@ -427,6 +429,7 @@ gcal_month_cell_class_init (GcalMonthCellClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, GcalMonthCell, overflow_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, GcalMonthCell, overflow_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, GcalMonthCell, overlay);
|
||||
gtk_widget_class_bind_template_child (widget_class, GcalMonthCell, weather_icon);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, enter_notify_event_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, leave_notify_event_cb);
|
||||
@@ -485,6 +488,38 @@ gcal_month_cell_set_date (GcalMonthCell *self,
|
||||
update_style_flags (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gcal_month_cell_set_weather:
|
||||
* @self: The #GcalMonthCell instance.
|
||||
* @info: (nullable): The weather information to display.
|
||||
*
|
||||
* Sets the weather information to display for this day.
|
||||
*
|
||||
* Note that this function does not check dates nor
|
||||
* manages weather information changes on its own.
|
||||
*/
|
||||
void
|
||||
gcal_month_cell_set_weather (GcalMonthCell *self,
|
||||
GcalWeatherInfo *info)
|
||||
{
|
||||
g_return_if_fail (GCAL_IS_MONTH_CELL (self));
|
||||
g_return_if_fail (info == NULL || GCAL_IS_WEATHER_INFO (info));
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
gtk_image_clear (self->weather_icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
const gchar* icon_name; /* unowned */
|
||||
|
||||
icon_name = gcal_weather_info_get_icon_name (info);
|
||||
gtk_image_set_from_icon_name (self->weather_icon, icon_name, GTK_ICON_SIZE_SMALL_TOOLBAR);
|
||||
}
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (self->weather_icon));
|
||||
}
|
||||
|
||||
gboolean
|
||||
gcal_month_cell_get_different_month (GcalMonthCell *self)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define GCAL_MONTH_CELL_H
|
||||
|
||||
#include "gcal-manager.h"
|
||||
#include "gcal-weather-info.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
@@ -36,6 +37,9 @@ GDateTime* gcal_month_cell_get_date (GcalMonthCell
|
||||
void gcal_month_cell_set_date (GcalMonthCell *self,
|
||||
GDateTime *date);
|
||||
|
||||
void gcal_month_cell_set_weather (GcalMonthCell *self,
|
||||
GcalWeatherInfo *info);
|
||||
|
||||
gboolean gcal_month_cell_get_different_month (GcalMonthCell *self);
|
||||
|
||||
void gcal_month_cell_set_different_month (GcalMonthCell *self,
|
||||
|
||||
+188
-1
@@ -70,7 +70,7 @@ struct _GcalMonthView
|
||||
|
||||
/* Grid widgets */
|
||||
GtkWidget *grid;
|
||||
GtkWidget *month_cell[6][7];
|
||||
GtkWidget *month_cell[6][7]; /* unowned */
|
||||
|
||||
/*
|
||||
* Hash to keep children widgets (all of them, parent widgets and its parts if there's any),
|
||||
@@ -132,6 +132,8 @@ struct _GcalMonthView
|
||||
icaltimetype *date;
|
||||
GcalManager *manager;
|
||||
|
||||
GcalWeatherService *weather_service;
|
||||
|
||||
gboolean pending_event_allocation;
|
||||
};
|
||||
|
||||
@@ -141,6 +143,9 @@ static void gtk_buildable_interface_init (GtkBuildableIf
|
||||
|
||||
static void e_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface);
|
||||
|
||||
static void update_weather (GcalMonthView *self,
|
||||
gboolean clear_old);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GcalMonthView, gcal_month_view, GTK_TYPE_CONTAINER,
|
||||
G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER,
|
||||
@@ -153,6 +158,7 @@ enum
|
||||
PROP_0,
|
||||
PROP_DATE,
|
||||
PROP_MANAGER,
|
||||
PROP_WEATHER_SERVICE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
@@ -162,6 +168,7 @@ enum
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static gpointer month_view_parent_class = NULL;
|
||||
static guint signals[NUM_SIGNALS] = { 0, };
|
||||
|
||||
|
||||
@@ -194,6 +201,13 @@ event_widget_visibility_changed_cb (GcalMonthView *self)
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
weather_changed_cb (GcalWeatherService *weather_service,
|
||||
GcalMonthView *self)
|
||||
{
|
||||
update_weather (self, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_child_widget (GcalMonthView *self,
|
||||
GtkWidget *widget)
|
||||
@@ -896,6 +910,76 @@ setup_month_grid (GcalMonthView *self,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_weather (GcalMonthView *self,
|
||||
gboolean clear_old)
|
||||
{
|
||||
g_return_if_fail (GCAL_IS_MONTH_VIEW (self));
|
||||
|
||||
/* Drop old weather information */
|
||||
if (clear_old)
|
||||
{
|
||||
guint row;
|
||||
guint col;
|
||||
|
||||
for (row = 0; row < 6; row++)
|
||||
{
|
||||
for (col = 0; col < 7; col++)
|
||||
{
|
||||
GcalMonthCell *cell;
|
||||
|
||||
cell = GCAL_MONTH_CELL (self->month_cell[row][col]);
|
||||
gcal_month_cell_set_weather (cell, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set new one */
|
||||
if (self->weather_service != NULL)
|
||||
{
|
||||
GcalMonthCell *fstcell;
|
||||
GDateTime *firstdt;
|
||||
GSList *weather_infos;
|
||||
GSList *witer;
|
||||
GDate first;
|
||||
|
||||
fstcell = GCAL_MONTH_CELL (self->month_cell[0][0]);
|
||||
firstdt = gcal_month_cell_get_date (fstcell);
|
||||
|
||||
g_date_set_dmy (&first,
|
||||
g_date_time_get_day_of_month (firstdt),
|
||||
g_date_time_get_month (firstdt),
|
||||
g_date_time_get_year (firstdt));
|
||||
|
||||
weather_infos = gcal_weather_service_get_weather_infos (self->weather_service);
|
||||
for (witer = weather_infos; witer; witer = witer->next)
|
||||
{
|
||||
GcalWeatherInfo *info;
|
||||
GDate weather_date;
|
||||
gint day_difference;
|
||||
|
||||
info = GCAL_WEATHER_INFO (witer->data);
|
||||
gcal_weather_info_get_date (info, &weather_date);
|
||||
day_difference = g_date_days_between (&first, &weather_date);
|
||||
|
||||
if (day_difference >= 0 && day_difference < 6 * 7)
|
||||
{
|
||||
GcalMonthCell *wcell;
|
||||
guint row;
|
||||
guint column;
|
||||
|
||||
row = day_difference / 7;
|
||||
column = day_difference % 7;
|
||||
wcell = GCAL_MONTH_CELL (self->month_cell[row][column]);
|
||||
|
||||
gcal_month_cell_set_weather (wcell, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_month_cells (GcalMonthView *self)
|
||||
{
|
||||
@@ -928,6 +1012,7 @@ update_month_cells (GcalMonthView *self)
|
||||
cell_date = g_date_time_add_days (dt, row * 7 + col - self->days_delay);
|
||||
|
||||
gcal_month_cell_set_date (cell, cell_date);
|
||||
gcal_month_cell_set_weather (cell, NULL);
|
||||
|
||||
/* Different month */
|
||||
different_month = day < self->days_delay ||
|
||||
@@ -976,6 +1061,8 @@ update_month_cells (GcalMonthView *self)
|
||||
}
|
||||
}
|
||||
|
||||
update_weather (self, FALSE);
|
||||
|
||||
self->update_grid_id = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
@@ -1685,6 +1772,9 @@ gcal_month_view_set_property (GObject *object,
|
||||
g_object_notify (object, "manager");
|
||||
break;
|
||||
|
||||
case PROP_WEATHER_SERVICE:
|
||||
gcal_month_view_set_weather_service (self, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -1709,17 +1799,48 @@ gcal_month_view_get_property (GObject *object,
|
||||
g_value_set_object (value, self->manager);
|
||||
break;
|
||||
|
||||
case PROP_WEATHER_SERVICE:
|
||||
g_value_set_boxed (value, gcal_month_view_get_weather_service (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when self is destroyed.
|
||||
*
|
||||
* WARNING: This is a workaround. This is one of the views where
|
||||
* reference counts are off. We overwrite destroy to avoid dangling
|
||||
* pointers. This issue needs to be addressed and this function removed.
|
||||
*/
|
||||
static void
|
||||
gcal_month_view_destroyed (GtkWidget *widget)
|
||||
{
|
||||
GcalMonthView *self = GCAL_MONTH_VIEW (widget);
|
||||
|
||||
if (self->weather_service)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->weather_service, weather_changed_cb, self);
|
||||
g_clear_object (&self->weather_service);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (month_view_parent_class)->destroy ((GtkWidget*) G_TYPE_CHECK_INSTANCE_CAST (self, GTK_TYPE_GRID, GtkGrid));
|
||||
}
|
||||
|
||||
static void
|
||||
gcal_month_view_finalize (GObject *object)
|
||||
{
|
||||
GcalMonthView *self = GCAL_MONTH_VIEW (object);
|
||||
|
||||
if (self->weather_service)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->weather_service, weather_changed_cb, self);
|
||||
g_clear_object (&self->weather_service);
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->date, g_free);
|
||||
g_clear_pointer (&self->children, g_hash_table_destroy);
|
||||
g_clear_pointer (&self->single_cell_children, g_hash_table_destroy);
|
||||
@@ -2086,6 +2207,18 @@ gcal_month_view_class_init (GcalMonthViewClass *klass)
|
||||
g_object_class_override_property (object_class, PROP_DATE, "active-date");
|
||||
g_object_class_override_property (object_class, PROP_MANAGER, "manager");
|
||||
|
||||
/**
|
||||
* GcalWeekView:weather-service:
|
||||
*
|
||||
* Sets the weather service to use.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class,
|
||||
PROP_WEATHER_SERVICE,
|
||||
g_param_spec_object ("weather-service", "weather-service", "weather-service",
|
||||
GCAL_TYPE_WEATHER_SERVICE,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
|
||||
|
||||
signals[EVENT_ACTIVATED] = g_signal_new ("event-activated",
|
||||
GCAL_TYPE_MONTH_VIEW,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
@@ -2111,6 +2244,10 @@ gcal_month_view_class_init (GcalMonthViewClass *klass)
|
||||
gtk_widget_class_set_css_name (widget_class, "calendar-view");
|
||||
|
||||
g_type_ensure (GCAL_TYPE_MONTH_POPOVER);
|
||||
|
||||
/* FIXME: Hack to deal with broken reference counts */
|
||||
month_view_parent_class = g_type_class_peek_parent (klass);
|
||||
((GtkWidgetClass *) klass)->destroy = (void (*) (GtkWidget *)) gcal_month_view_destroyed;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2120,6 +2257,7 @@ gcal_month_view_init (GcalMonthView *self)
|
||||
|
||||
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
|
||||
|
||||
self->weather_service = NULL;
|
||||
self->children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_list_free);
|
||||
self->single_cell_children = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_list_free);
|
||||
self->overflow_cells = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_list_free);
|
||||
@@ -2189,3 +2327,52 @@ gcal_month_view_set_use_24h_format (GcalMonthView *self,
|
||||
{
|
||||
self->use_24h_format = use_24h;
|
||||
}
|
||||
|
||||
/**
|
||||
* gcal_month_view_set_weather_service:
|
||||
* @self: The #GcalWeatherView instance.
|
||||
* @service: (nullable): The weather service to query.
|
||||
*
|
||||
* Sets the service to query for weather reports.
|
||||
*/
|
||||
void
|
||||
gcal_month_view_set_weather_service (GcalMonthView *self,
|
||||
GcalWeatherService *service)
|
||||
{
|
||||
g_return_if_fail (GCAL_IS_MONTH_VIEW (self));
|
||||
g_return_if_fail (!service || GCAL_IS_WEATHER_SERVICE (service));
|
||||
|
||||
if (self->weather_service == service)
|
||||
return;
|
||||
|
||||
if (self->weather_service)
|
||||
g_signal_handlers_disconnect_by_func (self->weather_service, weather_changed_cb, self);
|
||||
|
||||
g_set_object (&self->weather_service, service);
|
||||
|
||||
if (service)
|
||||
{
|
||||
g_signal_connect (service,
|
||||
"weather-changed",
|
||||
G_CALLBACK (weather_changed_cb),
|
||||
self);
|
||||
}
|
||||
|
||||
update_weather (self, TRUE);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "weather-service");
|
||||
}
|
||||
|
||||
/**
|
||||
* gcal_month_view_get_weather_service:
|
||||
* @self: The #GcalWeatherView instance.
|
||||
*
|
||||
* Returns: (transfer none): The internal weather service object.
|
||||
*/
|
||||
GcalWeatherService*
|
||||
gcal_month_view_get_weather_service (GcalMonthView *self)
|
||||
{
|
||||
g_return_val_if_fail (GCAL_IS_MONTH_VIEW (self), NULL);
|
||||
|
||||
return self->weather_service;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define __GCAL_MONTH_VIEW_H__
|
||||
|
||||
#include "gcal-manager.h"
|
||||
#include "gcal-weather-service.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -34,6 +35,11 @@ void gcal_month_view_set_first_weekday (GcalMonthView
|
||||
void gcal_month_view_set_use_24h_format (GcalMonthView *self,
|
||||
gboolean use_24h);
|
||||
|
||||
void gcal_month_view_set_weather_service (GcalMonthView *self,
|
||||
GcalWeatherService *service);
|
||||
|
||||
GcalWeatherService* gcal_month_view_get_weather_service (GcalMonthView *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GCAL_MONTH_VIEW_H__ */
|
||||
|
||||
Reference in New Issue
Block a user