1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/maemo-ui-old/src/mmyth_epg_grid_widget.c Wed Jan 23 20:09:09 2008 +0000
1.3 @@ -0,0 +1,776 @@
1.4 +#include <gtk/gtksignal.h>
1.5 +#include <gdk/gdkevents.h>
1.6 +#include <gdk/gdkkeysyms.h>
1.7 +
1.8 +#include "mmyth_uicommon.h"
1.9 +#include "mmyth_epg_grid_widget.h"
1.10 +
1.11 +#include <gmyth/gmyth_util.h>
1.12 +#include <gmyth/gmyth_epg.h>
1.13 +
1.14 +#define PIXELS_HOUR 105
1.15 +#define PROGRAM_SEPARATION 2
1.16 +
1.17 +enum {
1.18 + SELECTION_UPDATED_SIGNAL,
1.19 + LAST_SIGNAL
1.20 +};
1.21 +
1.22 +struct _MMythEpgGridWidgetPrivate {
1.23 + /*
1.24 + * private widget components
1.25 + */
1.26 + GtkWidget *epg_channels_vbox;
1.27 + GtkWidget *epg_programs_vbox;
1.28 +
1.29 + GHashTable *service_model_hash;
1.30 +
1.31 + /*
1.32 + * guidegrid attributes
1.33 + */
1.34 + gboolean show_favorites;
1.35 + gint current_start_channel_id;
1.36 +
1.37 + GTimeVal *current_start_time;
1.38 + GTimeVal *current_end_time;
1.39 +
1.40 + guint selected_channel_index;
1.41 +
1.42 + /*
1.43 + * GList of ProgramInfo for each Channel
1.44 + */
1.45 + GList *program_list[MAX_DISPLAY_CHANS];
1.46 + GList *channel_list;
1.47 +
1.48 + GMythEPG *mmyth_epg;
1.49 +
1.50 + GMythBackendInfo *backend_info;
1.51 +
1.52 + gint DISPLAY_CHANS;
1.53 +};
1.54 +
1.55 +static void mmyth_epg_grid_widget_class_init(MMythEpgGridWidgetClass *
1.56 + klass);
1.57 +static void mmyth_epg_grid_widget_init(MMythEpgGridWidget * object);
1.58 +static void
1.59 +mmyth_epg_grid_widget_private_init(MMythEpgGridWidgetPrivate * private);
1.60 +static void mmyth_epg_grid_widget_mount_services(MMythEpgGridWidget *
1.61 + object,
1.62 + GTimeVal * start_time,
1.63 + GTimeVal * end_time);
1.64 +static void mmyth_epg_grid_widget_mount_header(MMythEpgGridWidget *
1.65 + object);
1.66 +static void mmyth_epg_grid_widget_clicked(GtkWidget * widget,
1.67 + GdkEventExpose * event,
1.68 + gpointer data);
1.69 +static GtkWidget *create_event_box_lbl(gchar * str, int width,
1.70 + const GdkColor * bg_color,
1.71 + const GdkColor * fg_color);
1.72 +
1.73 +static void
1.74 +mmyth_epg_grid_widget_fill_programinfos(MMythEpgGridWidgetPrivate *
1.75 + private);
1.76 +static void
1.77 +mmyth_epg_grid_widget_fill_program_row_infos(MMythEpgGridWidgetPrivate *
1.78 + private, unsigned int chanNum,
1.79 + unsigned int row);
1.80 +
1.81 +static gint mmyth_epg_grid_widget_signals[LAST_SIGNAL] = { 0 };
1.82 +
1.83 +G_DEFINE_TYPE(MMythEpgGridWidget, mmyth_epg_grid_widget,
1.84 + GTK_TYPE_EVENT_BOX)
1.85 +
1.86 + static void
1.87 +
1.88 +
1.89 +
1.90 +
1.91 +
1.92 +
1.93 +
1.94 +
1.95 +
1.96 +
1.97 +
1.98 +
1.99 +
1.100 + mmyth_epg_grid_widget_class_init(MMythEpgGridWidgetClass * klass)
1.101 +{
1.102 + g_type_class_add_private(klass, sizeof(MMythEpgGridWidgetPrivate));
1.103 +
1.104 + mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL] =
1.105 + g_signal_new("selection_updated", G_TYPE_FROM_CLASS(klass),
1.106 + G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
1.107 + g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
1.108 + G_TYPE_POINTER);
1.109 +}
1.110 +
1.111 +static void
1.112 +mmyth_epg_grid_widget_private_init(MMythEpgGridWidgetPrivate * private)
1.113 +{
1.114 + time_t cur_time;
1.115 +
1.116 + g_return_if_fail(private != NULL);
1.117 +
1.118 + private->epg_channels_vbox = NULL;
1.119 + private->epg_programs_vbox = NULL;
1.120 + private->service_model_hash = NULL;
1.121 +
1.122 + private->show_favorites = FALSE;
1.123 + private->current_start_channel_id = -1;
1.124 +
1.125 + /*
1.126 + * Selected the first diplayable channel initially
1.127 + */
1.128 + private->selected_channel_index = 0;
1.129 +
1.130 + /*
1.131 + * TODO fix the current start/end time
1.132 + */
1.133 + private->current_start_time = g_new0(GTimeVal, 1);
1.134 + private->current_start_time->tv_sec = time(&cur_time);
1.135 +
1.136 + private->current_end_time = g_new0(GTimeVal, 1);
1.137 + private->current_end_time->tv_sec = time(&cur_time) + 10800;
1.138 +
1.139 + private->DISPLAY_CHANS = MAX_DISPLAY_CHANS;
1.140 +
1.141 + private->backend_info =
1.142 + gmyth_backend_info_new_full("localhost", "mythtv", "mythtv",
1.143 + "mythconverg", 6543);
1.144 +
1.145 + // TODO: Close the epg and unref it in dispose call
1.146 + private->mmyth_epg = gmyth_epg_new();
1.147 + if (!gmyth_epg_connect(private->mmyth_epg, private->backend_info)) {
1.148 + g_warning("[%s] Could not connect mysql handler to db",
1.149 + __FUNCTION__);
1.150 + g_object_unref(private->mmyth_epg);
1.151 + private->mmyth_epg = NULL;
1.152 + }
1.153 +}
1.154 +
1.155 +static void
1.156 +mmyth_epg_grid_widget_init(MMythEpgGridWidget * mmyth_epg_grid_widget)
1.157 +{
1.158 + MMythEpgGridWidgetPrivate *private =
1.159 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
1.160 +
1.161 + /*
1.162 + * init private fields
1.163 + */
1.164 + mmyth_epg_grid_widget_private_init(private);
1.165 +
1.166 + mmyth_epg_grid_widget->epg_view_model = NULL;
1.167 + mmyth_epg_grid_widget->selected_grid_item = NULL;
1.168 +
1.169 + GtkWidget *epg_event_box = GTK_WIDGET(mmyth_epg_grid_widget);
1.170 + gtk_widget_modify_bg(epg_event_box, GTK_STATE_NORMAL, &main_bg_color);
1.171 + gtk_widget_set_size_request(epg_event_box, 0, 125);
1.172 +
1.173 + GtkWidget *epg_main_hbox = gtk_hbox_new(FALSE, 10);
1.174 + gtk_container_set_border_width(GTK_CONTAINER(epg_main_hbox), 10);
1.175 +
1.176 + gtk_container_add(GTK_CONTAINER(epg_event_box), epg_main_hbox);
1.177 +
1.178 + /*
1.179 + * channels vbox
1.180 + */
1.181 + GtkWidget *epg_channels_vbox = gtk_vbox_new(FALSE, 3);
1.182 + private->epg_channels_vbox = epg_channels_vbox;
1.183 +
1.184 + /*
1.185 + * programs vbox
1.186 + */
1.187 + GtkWidget *epg_programs_vbox = gtk_vbox_new(FALSE, 3);
1.188 + private->epg_programs_vbox = epg_programs_vbox;
1.189 +
1.190 + /*
1.191 + * packing start
1.192 + */
1.193 + gtk_box_pack_start(GTK_BOX(epg_main_hbox),
1.194 + epg_channels_vbox, FALSE, FALSE, 0);
1.195 + gtk_box_pack_start(GTK_BOX(epg_main_hbox),
1.196 + epg_programs_vbox, FALSE, FALSE, 0);
1.197 +
1.198 + /*
1.199 + * table header (first line)
1.200 + */
1.201 + mmyth_epg_grid_widget_mount_header(mmyth_epg_grid_widget);
1.202 +
1.203 + /*
1.204 + * service programs
1.205 + */
1.206 + /*
1.207 + * mount service programs with current time
1.208 + */
1.209 + mmyth_epg_grid_widget_mount_services(mmyth_epg_grid_widget,
1.210 + private->current_start_time,
1.211 + private->current_end_time);
1.212 +}
1.213 +
1.214 +GtkWidget *
1.215 +mmyth_epg_grid_widget_new()
1.216 +{
1.217 + return GTK_WIDGET(gtk_type_new(mmyth_epg_grid_widget_get_type()));
1.218 +}
1.219 +
1.220 +static void
1.221 +mmyth_epg_grid_widget_mount_services(MMythEpgGridWidget *
1.222 + mmyth_epg_grid_widget,
1.223 + GTimeVal * start_time,
1.224 + GTimeVal * end_time)
1.225 +{
1.226 + GList *proglist;
1.227 + GList *channel_list = NULL;
1.228 + GMythChannelInfo *channel_info;
1.229 +
1.230 + int chanid;
1.231 + MMythEpgGridWidgetPrivate *private =
1.232 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
1.233 +
1.234 + // update view_model
1.235 + /*
1.236 + * FIXME shallow free or recursive?
1.237 + */
1.238 + if (mmyth_epg_grid_widget->epg_view_model != NULL) {
1.239 + g_list_free(mmyth_epg_grid_widget->epg_view_model);
1.240 + mmyth_epg_grid_widget->epg_view_model = NULL;
1.241 + }
1.242 +
1.243 + if (private->service_model_hash != NULL) {
1.244 + g_hash_table_destroy(private->service_model_hash);
1.245 + }
1.246 +
1.247 + private->service_model_hash = g_hash_table_new(NULL, NULL);
1.248 +
1.249 + /*
1.250 + * fill program infos from db
1.251 + */
1.252 + mmyth_epg_grid_widget_fill_programinfos(private);
1.253 +
1.254 + channel_list = private->channel_list;
1.255 +
1.256 + /*
1.257 + * for each channel get_programs()
1.258 + */
1.259 + for (chanid = 0; channel_list &&
1.260 + chanid < private->DISPLAY_CHANS; chanid++) {
1.261 + proglist = (GList *) private->program_list[chanid];
1.262 +
1.263 + channel_info = (GMythChannelInfo *) channel_list->data;
1.264 + channel_list = g_list_next(channel_list);
1.265 +
1.266 + /*
1.267 + * Service Title
1.268 + */
1.269 + GString *name = NULL;
1.270 + if (channel_info->channel_name)
1.271 + name = g_string_new(channel_info->channel_name->str);
1.272 +
1.273 + GdkColor title_bg_color;
1.274 + title_bg_color.red = 5000;
1.275 + title_bg_color.green = 9000;
1.276 + title_bg_color.blue = 40000;
1.277 +
1.278 + GdkColor title_fg_color;
1.279 + title_fg_color.red = 60000;
1.280 + title_fg_color.green = 60000;
1.281 + title_fg_color.blue = 60000;
1.282 +
1.283 + GtkWidget *event_box_channel =
1.284 + create_event_box_lbl(name->str, 90,
1.285 + &title_bg_color,
1.286 + &title_fg_color);
1.287 +
1.288 + gtk_box_pack_start(GTK_BOX(private->epg_channels_vbox),
1.289 + event_box_channel, FALSE, FALSE, 0);
1.290 +
1.291 + GtkWidget *epg_line_hbox = gtk_hbox_new(FALSE, 0);
1.292 +
1.293 + GdkColor bg_color;
1.294 + bg_color.red = 5000;
1.295 + bg_color.green = 30000;
1.296 + bg_color.blue = 60000;
1.297 +
1.298 + GdkColor fg_color;
1.299 + fg_color.red = 60000;
1.300 + fg_color.green = 60000;
1.301 + fg_color.blue = 60000;
1.302 +
1.303 + /*
1.304 + * Content parsing
1.305 + */
1.306 + GList *epg_grid_list = NULL;
1.307 +
1.308 + GMythProgramInfo *proginfo;
1.309 + int pixel_count = 0;
1.310 + for (; proglist; proglist = proglist->next) {
1.311 + proginfo = (GMythProgramInfo *) proglist->data;
1.312 +
1.313 + GString *content_name = proginfo->title;
1.314 +
1.315 + GTimeVal *initial_time = g_new0(GTimeVal, 1);
1.316 + GTimeVal *last_time = g_new0(GTimeVal, 1);
1.317 + GTimeVal *duration = g_new0(GTimeVal, 1);
1.318 +
1.319 + GTimeVal *schedule_start_time = proginfo->startts;
1.320 + GTimeVal *schedule_end_time = proginfo->endts;
1.321 +
1.322 + initial_time->tv_sec =
1.323 + (schedule_start_time->tv_sec <
1.324 + start_time->tv_sec) ? start_time->
1.325 + tv_sec : schedule_start_time->tv_sec;
1.326 + last_time->tv_sec =
1.327 + (schedule_end_time->tv_sec >
1.328 + end_time->tv_sec) ? end_time->tv_sec : schedule_end_time->
1.329 + tv_sec;
1.330 + duration->tv_sec = last_time->tv_sec - initial_time->tv_sec;
1.331 +
1.332 + // Verify program time
1.333 +#if 0
1.334 + g_debug("ServiceID: %d, ScheduleID: %d\n", service->id,
1.335 + schedule->id);
1.336 + fprintf(stderr, "program time\nfrom = %d, to = %d\n",
1.337 + schedule->validFrom, schedule->validTo);
1.338 +
1.339 + struct tm loctime;
1.340 +
1.341 + /*
1.342 + * Convert it to local time representation.
1.343 + */
1.344 + if (localtime_r((time_t *) & schedule->validFrom, &loctime) ==
1.345 + NULL) {
1.346 + g_warning("localtime_r error in mmyth_epg_grid_widget!\n");
1.347 + return NULL;
1.348 + }
1.349 + fprintf(stderr, asctime(&loctime));
1.350 +
1.351 + if (localtime_r((time_t *) & schedule->validTo, &loctime) ==
1.352 + NULL) {
1.353 + g_warning("localtime_r error in mmyth_epg_grid_widget!\n");
1.354 + return NULL;
1.355 + }
1.356 + fprintf(stderr, asctime(&loctime));
1.357 +#endif
1.358 +
1.359 + /*
1.360 + * fprintf(stderr, "duration = %d\n", duration);
1.361 + */
1.362 + double duration_hour =
1.363 + duration->tv_sec / (double) 3600.0;
1.364 + /*
1.365 + * fprintf(stderr, "duration_hour = %lf\n", duration_hour);
1.366 + */
1.367 +
1.368 + int size = PIXELS_HOUR * duration_hour;
1.369 +
1.370 + /*
1.371 + * complete hour
1.372 + */
1.373 + /*
1.374 + * FIXME: UGLY WRONG HACK TO ALIGN PROGRAM TIME!!!
1.375 + */
1.376 + if (last_time->tv_sec % 3600 != 0) {
1.377 + size -= PROGRAM_SEPARATION;
1.378 + }
1.379 + if (initial_time->tv_sec % 3600 != 0) {
1.380 + size -= PROGRAM_SEPARATION;
1.381 + }
1.382 +
1.383 + pixel_count += size + PROGRAM_SEPARATION;
1.384 + GtkWidget *event_box =
1.385 + create_event_box_lbl(content_name->str,
1.386 + size, &bg_color,
1.387 + &fg_color);
1.388 + gtk_widget_add_events(event_box,
1.389 + GDK_BUTTON_PRESS_MASK |
1.390 + GDK_BUTTON_RELEASE_MASK);
1.391 +
1.392 + /*
1.393 + * create EpgGridItem
1.394 + */
1.395 + EpgGridItem *epg_grid_item = g_new0(EpgGridItem, 1);
1.396 + epg_grid_item->proginfo = proginfo;
1.397 + epg_grid_item->event_box = event_box;
1.398 + epg_grid_item->object = mmyth_epg_grid_widget;
1.399 +
1.400 + epg_grid_list =
1.401 + g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);
1.402 +
1.403 + gtk_box_pack_start(GTK_BOX(epg_line_hbox),
1.404 + event_box, FALSE, FALSE,
1.405 + PROGRAM_SEPARATION);
1.406 +
1.407 + g_signal_connect(G_OBJECT(event_box), "button-press-event",
1.408 + G_CALLBACK(mmyth_epg_grid_widget_clicked),
1.409 + (gpointer *) epg_grid_list);
1.410 + }
1.411 +#if 0
1.412 + printf("chaind = %d!!!!" chanid);
1.413 + fflush(stdout);
1.414 +#endif
1.415 +
1.416 + if (!epg_grid_list) {
1.417 + /*
1.418 + * No programs for current channel
1.419 + */
1.420 + /*
1.421 + * FIXME: size HARDCODED
1.422 + */
1.423 + GtkWidget *event_box =
1.424 + create_event_box_lbl("No program list available",
1.425 + PIXELS_HOUR * 3, &bg_color,
1.426 + &fg_color);
1.427 + gtk_widget_add_events(event_box,
1.428 + GDK_BUTTON_PRESS_MASK |
1.429 + GDK_BUTTON_RELEASE_MASK);
1.430 +
1.431 + /*
1.432 + * create EpgGridItem
1.433 + */
1.434 + EpgGridItem *epg_grid_item = g_new0(EpgGridItem, 1);
1.435 + epg_grid_item->proginfo = NULL;
1.436 + epg_grid_item->event_box = event_box;
1.437 + epg_grid_item->object = mmyth_epg_grid_widget;
1.438 +
1.439 + epg_grid_list =
1.440 + g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);
1.441 +
1.442 + gtk_box_pack_start(GTK_BOX(epg_line_hbox),
1.443 + event_box, FALSE, FALSE,
1.444 + PROGRAM_SEPARATION);
1.445 +
1.446 + g_signal_connect(G_OBJECT(event_box), "button-press-event",
1.447 + G_CALLBACK(mmyth_epg_grid_widget_clicked),
1.448 + (gpointer *) epg_grid_list);
1.449 + }
1.450 +
1.451 + epg_grid_list = g_list_reverse(epg_grid_list);
1.452 + mmyth_epg_grid_widget->epg_view_model =
1.453 + g_list_append(mmyth_epg_grid_widget->epg_view_model,
1.454 + epg_grid_list);
1.455 +
1.456 + gtk_box_pack_start(GTK_BOX(private->epg_programs_vbox),
1.457 + epg_line_hbox, FALSE, FALSE, 0);
1.458 + }
1.459 +}
1.460 +
1.461 +static void
1.462 +mmyth_epg_grid_widget_mount_header(MMythEpgGridWidget *
1.463 + mmyth_epg_grid_widget)
1.464 +{
1.465 + MMythEpgGridWidgetPrivate *private =
1.466 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
1.467 +
1.468 + struct tm hour_tm;
1.469 + const gchar name_title[] = "Today";
1.470 + GtkWidget *lbl_title = gtk_label_new(name_title);
1.471 +
1.472 + gtk_misc_set_alignment(GTK_MISC(lbl_title), 0.0, 0.5);
1.473 +
1.474 + gtk_box_pack_start(GTK_BOX(private->epg_channels_vbox),
1.475 + lbl_title, FALSE, FALSE, 0);
1.476 +
1.477 + /*
1.478 + * hours title line
1.479 + */
1.480 + GtkWidget *epg_programs_hours_hbox = gtk_hbox_new(TRUE, 0);
1.481 +
1.482 + if (localtime_r
1.483 + ((time_t *) & private->current_start_time->tv_sec,
1.484 + &hour_tm) == NULL) {
1.485 + g_warning("localtime_r error in mmyth_epg_grid_widget!\n");
1.486 + return;
1.487 + }
1.488 +
1.489 + if (hour_tm.tm_min > 30) {
1.490 + hour_tm.tm_min = 30;
1.491 + } else if (hour_tm.tm_min > 0) {
1.492 + hour_tm.tm_min = 0;
1.493 + }
1.494 +
1.495 + gchar hour1_str[10];
1.496 + strftime(hour1_str, 8, "%H:%M", &hour_tm);
1.497 + GtkWidget *lbl_hour1 = gtk_label_new(hour1_str);
1.498 + gtk_misc_set_alignment(GTK_MISC(lbl_hour1), 0.0, 0.5);
1.499 +
1.500 + hour_tm.tm_hour++;
1.501 + gchar hour2_str[10];
1.502 + strftime(hour2_str, 8, "%H:%M", &hour_tm);
1.503 + GtkWidget *lbl_hour2 = gtk_label_new(hour2_str);
1.504 + gtk_misc_set_alignment(GTK_MISC(lbl_hour2), 0.0, 0.5);
1.505 +
1.506 + hour_tm.tm_hour++;
1.507 + gchar hour3_str[10];
1.508 + strftime(hour3_str, 8, "%H:%M", &hour_tm);
1.509 + GtkWidget *lbl_hour3 = gtk_label_new(hour3_str);
1.510 + gtk_misc_set_alignment(GTK_MISC(lbl_hour3), 0.0, 0.5);
1.511 +
1.512 + gtk_box_pack_start(GTK_BOX(epg_programs_hours_hbox),
1.513 + lbl_hour1, TRUE, TRUE, 0);
1.514 + gtk_box_pack_start(GTK_BOX(epg_programs_hours_hbox),
1.515 + lbl_hour2, TRUE, TRUE, 0);
1.516 + gtk_box_pack_start(GTK_BOX(epg_programs_hours_hbox),
1.517 + lbl_hour3, TRUE, TRUE, 0);
1.518 +
1.519 + gtk_box_pack_start(GTK_BOX(private->epg_programs_vbox),
1.520 + epg_programs_hours_hbox, FALSE, FALSE, 0);
1.521 +}
1.522 +
1.523 +/******************************************************************************
1.524 + * INTERNAL CALLBACKS FOR STATE CHANGE *
1.525 + *****************************************************************************/
1.526 +static void
1.527 +mmyth_epg_grid_widget_deselect_service(MMythEpgGridWidget *
1.528 + mmyth_epg_grid_widget)
1.529 +{
1.530 + EpgGridItem *epg_grid_item;
1.531 +
1.532 + /*
1.533 + * deselect
1.534 + */
1.535 + if (mmyth_epg_grid_widget->selected_grid_item != NULL) {
1.536 + epg_grid_item =
1.537 + (EpgGridItem *) mmyth_epg_grid_widget->selected_grid_item->
1.538 + data;
1.539 + gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box),
1.540 + GTK_STATE_NORMAL);
1.541 + }
1.542 +}
1.543 +
1.544 +static void
1.545 +mmyth_epg_grid_widget_clicked(GtkWidget * widget,
1.546 + GdkEventExpose * event, gpointer data)
1.547 +{
1.548 + g_return_if_fail(data != NULL);
1.549 +
1.550 + GList *epg_grid_item_list = (GList *) data;
1.551 + EpgGridItem *epg_grid_item =
1.552 + (EpgGridItem *) epg_grid_item_list->data;
1.553 +
1.554 + /*
1.555 + * update the selected service
1.556 + */
1.557 + mmyth_epg_grid_widget_update_service(epg_grid_item->object,
1.558 + (GList *) data);
1.559 +}
1.560 +
1.561 +void
1.562 +mmyth_epg_grid_widget_update_service(MMythEpgGridWidget * object,
1.563 + GList * selected_grid_list)
1.564 +{
1.565 + g_return_if_fail(object != NULL);
1.566 + g_return_if_fail(selected_grid_list != NULL);
1.567 +
1.568 + EpgGridItem *epg_grid_item =
1.569 + (EpgGridItem *) selected_grid_list->data;
1.570 +
1.571 + mmyth_epg_grid_widget_deselect_service(epg_grid_item->object);
1.572 +
1.573 + /*
1.574 + * updating current selected schedule_item and schedule_list
1.575 + */
1.576 + object->selected_grid_item = selected_grid_list;
1.577 +
1.578 + /*
1.579 + * set state of the event box
1.580 + */
1.581 + gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box),
1.582 + GTK_STATE_SELECTED);
1.583 + /*
1.584 + * emit update signal for listeners
1.585 + */
1.586 + g_signal_emit(object,
1.587 + mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL],
1.588 + 0, (gpointer) epg_grid_item);
1.589 +}
1.590 +
1.591 +static GtkWidget *
1.592 +create_event_box_lbl(gchar * str, int width, const GdkColor * bg_color,
1.593 + const GdkColor * fg_color)
1.594 +{
1.595 + GtkWidget *event_box = gtk_event_box_new();
1.596 + GtkWidget *lbl = gtk_label_new(str);
1.597 + gtk_label_set_ellipsize(GTK_LABEL(lbl), PANGO_ELLIPSIZE_END);
1.598 +
1.599 + gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, bg_color);
1.600 + gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, fg_color);
1.601 +
1.602 + /*
1.603 + * selected colors are const
1.604 + */
1.605 + GdkColor selected_bg_color;
1.606 + selected_bg_color.red = 100;
1.607 + selected_bg_color.green = 40000;
1.608 + selected_bg_color.blue = 100;
1.609 +
1.610 + GdkColor selected_fg_color;
1.611 + selected_fg_color.red = 100;
1.612 + selected_fg_color.green = 100;
1.613 + selected_fg_color.blue = 100;
1.614 +
1.615 + gtk_widget_modify_bg(event_box, GTK_STATE_SELECTED,
1.616 + &selected_bg_color);
1.617 + gtk_widget_modify_fg(lbl, GTK_STATE_SELECTED, &selected_fg_color);
1.618 +
1.619 + gtk_misc_set_alignment(GTK_MISC(lbl), 0.0, 0.5);
1.620 + gtk_container_add(GTK_CONTAINER(event_box), lbl);
1.621 + gtk_widget_set_size_request(event_box, width, -1);
1.622 +
1.623 + return event_box;
1.624 +}
1.625 +
1.626 +/******************************************************************************
1.627 + * METHODS *
1.628 + *****************************************************************************/
1.629 +
1.630 +/*
1.631 + * Callback for hardware keys
1.632 + */
1.633 +gboolean
1.634 +mmyth_epg_grid_widget_key_press(MMythEpgGridWidget * object,
1.635 + GtkWidget * widget, GdkEventKey * event)
1.636 +{
1.637 + MMythEpgGridWidgetPrivate *private =
1.638 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(object);
1.639 +
1.640 + EpgGridItem *epg_grid_item;
1.641 + GList *tmp;
1.642 +
1.643 + /*
1.644 + * List of selected_grid_item
1.645 + */
1.646 + GList *selected_view_model;
1.647 +
1.648 + gint channel_index;
1.649 +
1.650 + if (object->selected_grid_item == NULL) {
1.651 + g_warning("No program selected");
1.652 + return FALSE;
1.653 + }
1.654 +
1.655 + epg_grid_item = (EpgGridItem *) object->selected_grid_item->data;
1.656 +
1.657 + channel_index = private->selected_channel_index;
1.658 +
1.659 + switch (event->keyval) {
1.660 + case GDK_Up:
1.661 + selected_view_model =
1.662 + g_list_nth(object->epg_view_model, channel_index - 1);
1.663 + if (selected_view_model != NULL) {
1.664 + private->selected_channel_index = channel_index - 1;
1.665 + tmp = (GList *) selected_view_model->data;
1.666 + /*
1.667 + * TODO: select a better centralized item currently is
1.668 + * picking the 1st or last item
1.669 + */
1.670 + if (g_list_next(object->selected_grid_item) == NULL &&
1.671 + g_list_previous(object->selected_grid_item) != NULL) {
1.672 + /*
1.673 + * in this case the new selected will be the last
1.674 + */
1.675 + tmp = g_list_last(tmp);
1.676 + }
1.677 +
1.678 + /*
1.679 + * update the selected service
1.680 + */
1.681 + mmyth_epg_grid_widget_update_service(object, tmp);
1.682 + }
1.683 + return TRUE;
1.684 + case GDK_Down:
1.685 + selected_view_model =
1.686 + g_list_nth(object->epg_view_model, channel_index + 1);
1.687 + if (selected_view_model != NULL) {
1.688 + private->selected_channel_index = channel_index + 1;
1.689 + tmp = (GList *) selected_view_model->data;
1.690 + /*
1.691 + * TODO: select a better centralized item currently is
1.692 + * picking the 1st or last item
1.693 + */
1.694 + if (g_list_next(object->selected_grid_item) == NULL &&
1.695 + g_list_previous(object->selected_grid_item) != NULL) {
1.696 + /*
1.697 + * in this case the new selected will be the last
1.698 + */
1.699 + tmp = g_list_last(tmp);
1.700 + }
1.701 +
1.702 + /*
1.703 + * update the selected service
1.704 + */
1.705 + mmyth_epg_grid_widget_update_service(object, tmp);
1.706 + }
1.707 + return TRUE;
1.708 + case GDK_Left:
1.709 + tmp = g_list_previous(object->selected_grid_item);
1.710 + if (tmp != NULL) {
1.711 + /*
1.712 + * update the selected service
1.713 + */
1.714 + mmyth_epg_grid_widget_update_service(object, tmp);
1.715 + }
1.716 + return TRUE;
1.717 + case GDK_Right:
1.718 + tmp = g_list_next(object->selected_grid_item);
1.719 + if (tmp != NULL) {
1.720 + /*
1.721 + * update the selected service
1.722 + */
1.723 + mmyth_epg_grid_widget_update_service(object, tmp);
1.724 + }
1.725 + return TRUE;
1.726 + default:
1.727 + return TRUE;
1.728 + }
1.729 +
1.730 + return FALSE;
1.731 +}
1.732 +
1.733 +static void
1.734 +mmyth_epg_grid_widget_fill_programinfos(MMythEpgGridWidgetPrivate *
1.735 + private)
1.736 +{
1.737 + GList *channels_list = NULL;
1.738 + int y;
1.739 +
1.740 + if ((private->mmyth_epg != NULL) &&
1.741 + (gmyth_epg_get_channel_list(private->mmyth_epg, &channels_list) <
1.742 + 0)) {
1.743 + private->channel_list = NULL;
1.744 + return;
1.745 + }
1.746 +
1.747 + private->channel_list = channels_list;
1.748 +
1.749 + for (y = 0; y < private->DISPLAY_CHANS && channels_list; y++) {
1.750 + GMythChannelInfo *channel_info =
1.751 + (GMythChannelInfo *) channels_list->data;
1.752 +
1.753 + mmyth_epg_grid_widget_fill_program_row_infos(private,
1.754 + channel_info->
1.755 + channel_ID, y);
1.756 +
1.757 + channels_list = g_list_next(channels_list);
1.758 + }
1.759 +}
1.760 +
1.761 +static void
1.762 +mmyth_epg_grid_widget_fill_program_row_infos(MMythEpgGridWidgetPrivate *
1.763 + private, guint chanNum,
1.764 + guint row)
1.765 +{
1.766 + gint res = gmyth_epg_get_program_list(private->mmyth_epg,
1.767 + &(private->
1.768 + program_list[row]),
1.769 + chanNum,
1.770 + private->
1.771 + current_start_time,
1.772 + private->
1.773 + current_end_time);
1.774 +
1.775 + if (res < 0) {
1.776 + g_warning("[%s] Error while retrieving epg programs",
1.777 + __FUNCTION__);
1.778 + }
1.779 +}