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