gmyth/src/gui/mmyth_epg_grid_widget.c
author leo_sobral
Wed Sep 20 23:45:35 2006 +0100 (2006-09-20)
branchtrunk
changeset 1 ffdf467315ec
permissions -rw-r--r--
[svn r2] imported to sf repository
leo_sobral@1
     1
#include <gtk/gtksignal.h>
leo_sobral@1
     2
#include <gdk/gdkevents.h>
leo_sobral@1
     3
#include <gdk/gdkkeysyms.h>
leo_sobral@1
     4
leo_sobral@1
     5
#include "mmyth_uicommon.h"
leo_sobral@1
     6
#include "mmyth_epg_grid_widget.h"
leo_sobral@1
     7
leo_sobral@1
     8
#include "gmyth_util.h" 
leo_sobral@1
     9
#include "gmyth_epg.h"
leo_sobral@1
    10
leo_sobral@1
    11
#define PIXELS_HOUR 105
leo_sobral@1
    12
#define PROGRAM_SEPARATION 2
leo_sobral@1
    13
leo_sobral@1
    14
enum {
leo_sobral@1
    15
  SELECTION_UPDATED_SIGNAL,
leo_sobral@1
    16
  LAST_SIGNAL
leo_sobral@1
    17
};
leo_sobral@1
    18
leo_sobral@1
    19
struct _MMythEpgGridWidgetPrivate {
leo_sobral@1
    20
    /* private widget components */
leo_sobral@1
    21
    GtkWidget *epg_channels_vbox;
leo_sobral@1
    22
    GtkWidget *epg_programs_vbox;
leo_sobral@1
    23
 
leo_sobral@1
    24
    GHashTable *service_model_hash;
leo_sobral@1
    25
    
leo_sobral@1
    26
    /* guidegrid attributes */
leo_sobral@1
    27
    gboolean show_favorites;
leo_sobral@1
    28
    gint current_start_channel_id;
leo_sobral@1
    29
    
leo_sobral@1
    30
    time_t current_start_time;
leo_sobral@1
    31
    time_t current_end_time;
leo_sobral@1
    32
leo_sobral@1
    33
    guint selected_channel_index;
leo_sobral@1
    34
    
leo_sobral@1
    35
    /* GList of ProgramInfo for each Channel */
leo_sobral@1
    36
    GList * program_list[MAX_DISPLAY_CHANS];
leo_sobral@1
    37
    GList * channel_list;
leo_sobral@1
    38
    
leo_sobral@1
    39
    GMythEPG *mmyth_epg;
leo_sobral@1
    40
    
leo_sobral@1
    41
    gint DISPLAY_CHANS;
leo_sobral@1
    42
};
leo_sobral@1
    43
leo_sobral@1
    44
static void mmyth_epg_grid_widget_class_init          (MMythEpgGridWidgetClass *klass);
leo_sobral@1
    45
static void mmyth_epg_grid_widget_init                (MMythEpgGridWidget *object);
leo_sobral@1
    46
static void mmyth_epg_grid_widget_private_init        (MMythEpgGridWidgetPrivate *private);
leo_sobral@1
    47
static void mmyth_epg_grid_widget_mount_services      (MMythEpgGridWidget *object, 
leo_sobral@1
    48
                                                       int start_time, int end_time);
leo_sobral@1
    49
static void mmyth_epg_grid_widget_mount_header        (MMythEpgGridWidget *object);
leo_sobral@1
    50
static void mmyth_epg_grid_widget_clicked             (GtkWidget* widget, 
leo_sobral@1
    51
                                                       GdkEventExpose *event, 
leo_sobral@1
    52
                                                       gpointer data);
leo_sobral@1
    53
static GtkWidget *create_event_box_lbl                (gchar *str, int width, 
leo_sobral@1
    54
                                                       const GdkColor *bg_color, 
leo_sobral@1
    55
                                                       const GdkColor *fg_color);
leo_sobral@1
    56
leo_sobral@1
    57
static void mmyth_epg_grid_widget_fill_programinfos(MMythEpgGridWidgetPrivate *private);
leo_sobral@1
    58
static void mmyth_epg_grid_widget_fill_program_row_infos(
leo_sobral@1
    59
                    MMythEpgGridWidgetPrivate *private, 
leo_sobral@1
    60
                    unsigned int chanNum, unsigned int row);
leo_sobral@1
    61
leo_sobral@1
    62
static gint mmyth_epg_grid_widget_signals[LAST_SIGNAL] = { 0 };
leo_sobral@1
    63
leo_sobral@1
    64
G_DEFINE_TYPE(MMythEpgGridWidget, mmyth_epg_grid_widget, GTK_TYPE_EVENT_BOX)
leo_sobral@1
    65
    
leo_sobral@1
    66
static void
leo_sobral@1
    67
mmyth_epg_grid_widget_class_init (MMythEpgGridWidgetClass *klass)
leo_sobral@1
    68
{
leo_sobral@1
    69
  g_type_class_add_private (klass, sizeof (MMythEpgGridWidgetPrivate));
leo_sobral@1
    70
  
leo_sobral@1
    71
  mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL] = g_signal_new (
leo_sobral@1
    72
                     "selection_updated",
leo_sobral@1
    73
					 G_TYPE_FROM_CLASS(klass), 
leo_sobral@1
    74
					 G_SIGNAL_RUN_FIRST,
leo_sobral@1
    75
					 0,
leo_sobral@1
    76
                     NULL,
leo_sobral@1
    77
                     NULL,
leo_sobral@1
    78
					 g_cclosure_marshal_VOID__POINTER, 
leo_sobral@1
    79
                     G_TYPE_NONE, 
leo_sobral@1
    80
                     1,
leo_sobral@1
    81
                     G_TYPE_POINTER);
leo_sobral@1
    82
}
leo_sobral@1
    83
leo_sobral@1
    84
static void 
leo_sobral@1
    85
mmyth_epg_grid_widget_private_init (MMythEpgGridWidgetPrivate *private)
leo_sobral@1
    86
{
leo_sobral@1
    87
    time_t cur_time;
leo_sobral@1
    88
    
leo_sobral@1
    89
    g_return_if_fail(private != NULL);     
leo_sobral@1
    90
leo_sobral@1
    91
    private->epg_channels_vbox   = NULL;
leo_sobral@1
    92
    private->epg_programs_vbox   = NULL;
leo_sobral@1
    93
    private->service_model_hash  = NULL;
leo_sobral@1
    94
leo_sobral@1
    95
    private->show_favorites = FALSE;
leo_sobral@1
    96
    private->current_start_channel_id = -1;
leo_sobral@1
    97
leo_sobral@1
    98
    /* Selected the first diplayable channel initially */
leo_sobral@1
    99
    private->selected_channel_index = 0;
leo_sobral@1
   100
        
leo_sobral@1
   101
    /* TODO fix the current start/end time */
leo_sobral@1
   102
    private->current_start_time = time(&cur_time);
leo_sobral@1
   103
    private->current_end_time = time(&cur_time) + 10800;   
leo_sobral@1
   104
    
leo_sobral@1
   105
    private->DISPLAY_CHANS = MAX_DISPLAY_CHANS;
leo_sobral@1
   106
    
leo_sobral@1
   107
    // TODO: Close the epg and unref it in dispose call
leo_sobral@1
   108
    private->mmyth_epg = gmyth_epg_new ();
leo_sobral@1
   109
    if (!gmyth_epg_connect (private->mmyth_epg)) {
leo_sobral@1
   110
    	g_warning ("[%s] Could not connect mysql handler to db", __FUNCTION__);
leo_sobral@1
   111
    	g_object_unref (private->mmyth_epg);
leo_sobral@1
   112
    	private->mmyth_epg = NULL;
leo_sobral@1
   113
    }
leo_sobral@1
   114
}
leo_sobral@1
   115
leo_sobral@1
   116
static void
leo_sobral@1
   117
mmyth_epg_grid_widget_init (MMythEpgGridWidget *mmyth_epg_grid_widget)
leo_sobral@1
   118
{
leo_sobral@1
   119
    MMythEpgGridWidgetPrivate *private = 
leo_sobral@1
   120
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
leo_sobral@1
   121
    
leo_sobral@1
   122
    /* init private fields */
leo_sobral@1
   123
    mmyth_epg_grid_widget_private_init(private);
leo_sobral@1
   124
leo_sobral@1
   125
    mmyth_epg_grid_widget->epg_view_model      = NULL;
leo_sobral@1
   126
    mmyth_epg_grid_widget->selected_grid_item  = NULL;
leo_sobral@1
   127
leo_sobral@1
   128
    GtkWidget *epg_event_box = GTK_WIDGET(mmyth_epg_grid_widget);
leo_sobral@1
   129
    gtk_widget_modify_bg(epg_event_box, GTK_STATE_NORMAL, &main_bg_color);
leo_sobral@1
   130
    gtk_widget_set_size_request (epg_event_box, 0, 125);
leo_sobral@1
   131
    
leo_sobral@1
   132
    GtkWidget *epg_main_hbox = gtk_hbox_new (FALSE, 10);
leo_sobral@1
   133
    gtk_container_set_border_width(GTK_CONTAINER (epg_main_hbox), 10);
leo_sobral@1
   134
    
leo_sobral@1
   135
    gtk_container_add (GTK_CONTAINER (epg_event_box),
leo_sobral@1
   136
                       epg_main_hbox);
leo_sobral@1
   137
		        
leo_sobral@1
   138
    /* channels vbox */
leo_sobral@1
   139
    GtkWidget *epg_channels_vbox = gtk_vbox_new (FALSE, 3); 
leo_sobral@1
   140
    private->epg_channels_vbox = epg_channels_vbox; 
leo_sobral@1
   141
leo_sobral@1
   142
    /* programs vbox */
leo_sobral@1
   143
    GtkWidget *epg_programs_vbox = gtk_vbox_new (FALSE, 3);
leo_sobral@1
   144
    private->epg_programs_vbox = epg_programs_vbox;
leo_sobral@1
   145
    
leo_sobral@1
   146
    /* packing start */
leo_sobral@1
   147
    gtk_box_pack_start (GTK_BOX (epg_main_hbox),
leo_sobral@1
   148
	                epg_channels_vbox, FALSE, FALSE, 0);
leo_sobral@1
   149
    gtk_box_pack_start (GTK_BOX (epg_main_hbox),
leo_sobral@1
   150
                        epg_programs_vbox, FALSE, FALSE, 0);
leo_sobral@1
   151
leo_sobral@1
   152
    /* table header (first line) */  
leo_sobral@1
   153
    mmyth_epg_grid_widget_mount_header(mmyth_epg_grid_widget);                 
leo_sobral@1
   154
    
leo_sobral@1
   155
    /* service programs */ 
leo_sobral@1
   156
    /* mount service programs with current time */
leo_sobral@1
   157
    mmyth_epg_grid_widget_mount_services(mmyth_epg_grid_widget, 
leo_sobral@1
   158
                                         private->current_start_time,
leo_sobral@1
   159
                                         private->current_end_time);                                           
leo_sobral@1
   160
}
leo_sobral@1
   161
leo_sobral@1
   162
GtkWidget*
leo_sobral@1
   163
mmyth_epg_grid_widget_new ()
leo_sobral@1
   164
{
leo_sobral@1
   165
  return GTK_WIDGET ( gtk_type_new (mmyth_epg_grid_widget_get_type ()));
leo_sobral@1
   166
}
leo_sobral@1
   167
leo_sobral@1
   168
static void
leo_sobral@1
   169
mmyth_epg_grid_widget_mount_services(MMythEpgGridWidget *mmyth_epg_grid_widget, 
leo_sobral@1
   170
                                     int start_time, int end_time)
leo_sobral@1
   171
{
leo_sobral@1
   172
    GList *proglist;
leo_sobral@1
   173
    GList *channel_list = NULL;
leo_sobral@1
   174
    GMythChannelInfo *channel_info;
leo_sobral@1
   175
leo_sobral@1
   176
    int chanid;
leo_sobral@1
   177
    MMythEpgGridWidgetPrivate *private = 
leo_sobral@1
   178
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
leo_sobral@1
   179
	
leo_sobral@1
   180
	// update view_model
leo_sobral@1
   181
	/* FIXME shallow free or recursive? */
leo_sobral@1
   182
	if(mmyth_epg_grid_widget->epg_view_model != NULL) {
leo_sobral@1
   183
		g_list_free(mmyth_epg_grid_widget->epg_view_model);
leo_sobral@1
   184
		mmyth_epg_grid_widget->epg_view_model = NULL;
leo_sobral@1
   185
	}
leo_sobral@1
   186
	
leo_sobral@1
   187
	if(private->service_model_hash != NULL) {
leo_sobral@1
   188
		g_hash_table_destroy(private->service_model_hash);
leo_sobral@1
   189
	}
leo_sobral@1
   190
leo_sobral@1
   191
	private->service_model_hash = g_hash_table_new(NULL, NULL);
leo_sobral@1
   192
leo_sobral@1
   193
    /* fill program infos from db */
leo_sobral@1
   194
    mmyth_epg_grid_widget_fill_programinfos(private);
leo_sobral@1
   195
    
leo_sobral@1
   196
    channel_list = private->channel_list;
leo_sobral@1
   197
 
leo_sobral@1
   198
    /* for each channel get_programs() */
leo_sobral@1
   199
    for (chanid=0; channel_list &&
leo_sobral@1
   200
                   chanid < private->DISPLAY_CHANS; chanid++) {
leo_sobral@1
   201
        proglist = (GList *) private->program_list[chanid];        
leo_sobral@1
   202
    
leo_sobral@1
   203
        channel_info = (GMythChannelInfo *) channel_list->data;
leo_sobral@1
   204
        channel_list = g_list_next(channel_list);        
leo_sobral@1
   205
leo_sobral@1
   206
        /* Service Title*/
leo_sobral@1
   207
        GString *name = NULL;
leo_sobral@1
   208
        if (channel_info->channel_name)
leo_sobral@1
   209
        	name = g_string_new (channel_info->channel_name->str);
leo_sobral@1
   210
		
leo_sobral@1
   211
		GdkColor title_bg_color;
leo_sobral@1
   212
		title_bg_color.red = 5000;
leo_sobral@1
   213
		title_bg_color.green = 9000;
leo_sobral@1
   214
		title_bg_color.blue = 40000;        
leo_sobral@1
   215
		
leo_sobral@1
   216
		GdkColor title_fg_color;
leo_sobral@1
   217
		title_fg_color.red = 60000;
leo_sobral@1
   218
		title_fg_color.green = 60000;
leo_sobral@1
   219
		title_fg_color.blue = 60000;        
leo_sobral@1
   220
		
leo_sobral@1
   221
		GtkWidget *event_box_channel = create_event_box_lbl(
leo_sobral@1
   222
                                                        name->str, 90, 
leo_sobral@1
   223
									                    &title_bg_color, 
leo_sobral@1
   224
									                    &title_fg_color);
leo_sobral@1
   225
leo_sobral@1
   226
        gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox),
leo_sobral@1
   227
		                    event_box_channel, FALSE, FALSE, 0);
leo_sobral@1
   228
leo_sobral@1
   229
  		GtkWidget *epg_line_hbox = gtk_hbox_new (FALSE, 0);      
leo_sobral@1
   230
leo_sobral@1
   231
	    GdkColor bg_color;
leo_sobral@1
   232
	    bg_color.red = 5000;
leo_sobral@1
   233
	    bg_color.green = 30000;
leo_sobral@1
   234
	    bg_color.blue = 60000;        
leo_sobral@1
   235
	
leo_sobral@1
   236
	    GdkColor fg_color;
leo_sobral@1
   237
	    fg_color.red = 60000;
leo_sobral@1
   238
	    fg_color.green = 60000;
leo_sobral@1
   239
	    fg_color.blue = 60000;        
leo_sobral@1
   240
		
leo_sobral@1
   241
		/* Content parsing */
leo_sobral@1
   242
        GList *epg_grid_list = NULL;
leo_sobral@1
   243
leo_sobral@1
   244
        GMythProgramInfo *proginfo;
leo_sobral@1
   245
        int pixel_count = 0;
leo_sobral@1
   246
        for (; proglist; proglist = proglist->next) {
leo_sobral@1
   247
            proginfo = (GMythProgramInfo *) proglist->data;
leo_sobral@1
   248
            
leo_sobral@1
   249
            GString *content_name = proginfo->title;
leo_sobral@1
   250
                    
leo_sobral@1
   251
       	    int initial_time, last_time, duration;
leo_sobral@1
   252
leo_sobral@1
   253
            int schedule_start_time = proginfo->startts;
leo_sobral@1
   254
            int schedule_end_time   = proginfo->endts;
leo_sobral@1
   255
leo_sobral@1
   256
	        initial_time = 
leo_sobral@1
   257
                (schedule_start_time < start_time) ? start_time : schedule_start_time;
leo_sobral@1
   258
            last_time = (schedule_end_time > end_time) ? end_time : schedule_end_time;
leo_sobral@1
   259
	        duration = last_time - initial_time;
leo_sobral@1
   260
		    
leo_sobral@1
   261
            // Verify program time 
leo_sobral@1
   262
            #if 0
leo_sobral@1
   263
			    g_debug ("ServiceID: %d, ScheduleID: %d\n", service->id, schedule->id);
leo_sobral@1
   264
                fprintf (stderr, "program time\nfrom = %d, to = %d\n", 
leo_sobral@1
   265
                         schedule->validFrom, schedule->validTo); 
leo_sobral@1
   266
                
leo_sobral@1
   267
                struct tm loctime;
leo_sobral@1
   268
    
leo_sobral@1
   269
                /* Convert it to local time representation. */
leo_sobral@1
   270
                if (localtime_r((time_t *)&schedule->validFrom, &loctime) == NULL) {
leo_sobral@1
   271
                    g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
leo_sobral@1
   272
                    return NULL;
leo_sobral@1
   273
                }            
leo_sobral@1
   274
                fprintf (stderr, asctime (&loctime)); 
leo_sobral@1
   275
                
leo_sobral@1
   276
                if (localtime_r((time_t *)&schedule->validTo, &loctime) == NULL) {
leo_sobral@1
   277
                    g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
leo_sobral@1
   278
                    return NULL;
leo_sobral@1
   279
                } 
leo_sobral@1
   280
                fprintf (stderr, asctime (&loctime)); 
leo_sobral@1
   281
            #endif
leo_sobral@1
   282
    		
leo_sobral@1
   283
    	    /* fprintf(stderr, "duration = %d\n", duration); */
leo_sobral@1
   284
    	    double duration_hour = duration / (double) 3600.0;
leo_sobral@1
   285
    	    /* fprintf(stderr, "duration_hour = %lf\n", duration_hour); */
leo_sobral@1
   286
    		
leo_sobral@1
   287
            int size = PIXELS_HOUR * duration_hour;
leo_sobral@1
   288
                
leo_sobral@1
   289
            /* complete hour */
leo_sobral@1
   290
            /* FIXME: UGLY WRONG HACK TO ALIGN PROGRAM TIME!!!*/
leo_sobral@1
   291
            if(last_time%3600 != 0) {
leo_sobral@1
   292
                size -= PROGRAM_SEPARATION;                
leo_sobral@1
   293
            }
leo_sobral@1
   294
            if(initial_time%3600 != 0) {
leo_sobral@1
   295
                size -= PROGRAM_SEPARATION;                
leo_sobral@1
   296
            }
leo_sobral@1
   297
leo_sobral@1
   298
            pixel_count += size + PROGRAM_SEPARATION;
leo_sobral@1
   299
	        GtkWidget *event_box = create_event_box_lbl(content_name->str, 
leo_sobral@1
   300
							  size, &bg_color, 
leo_sobral@1
   301
							  &fg_color);
leo_sobral@1
   302
							  gtk_widget_add_events(event_box, 
leo_sobral@1
   303
							  GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
leo_sobral@1
   304
            
leo_sobral@1
   305
            /* create EpgGridItem */
leo_sobral@1
   306
            EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1);
leo_sobral@1
   307
            epg_grid_item->proginfo  = proginfo;
leo_sobral@1
   308
            epg_grid_item->event_box = event_box;
leo_sobral@1
   309
            epg_grid_item->object    = mmyth_epg_grid_widget;
leo_sobral@1
   310
            
leo_sobral@1
   311
            epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);                                   		                        
leo_sobral@1
   312
leo_sobral@1
   313
     	    gtk_box_pack_start (GTK_BOX (epg_line_hbox),
leo_sobral@1
   314
	                            event_box, FALSE, FALSE, PROGRAM_SEPARATION);
leo_sobral@1
   315
	                                 
leo_sobral@1
   316
   	        g_signal_connect (G_OBJECT (event_box), "button-press-event",
leo_sobral@1
   317
		                      G_CALLBACK (mmyth_epg_grid_widget_clicked), 
leo_sobral@1
   318
                              (gpointer*) epg_grid_list);
leo_sobral@1
   319
        }
leo_sobral@1
   320
#if 0
leo_sobral@1
   321
        printf("chaind = %d!!!!" chanid);fflush(stdout);
leo_sobral@1
   322
#endif        
leo_sobral@1
   323
leo_sobral@1
   324
        if(!epg_grid_list) {
leo_sobral@1
   325
            /* No programs for current channel */
leo_sobral@1
   326
            /* FIXME: size HARDCODED */
leo_sobral@1
   327
            GtkWidget *event_box = create_event_box_lbl("No program list available",
leo_sobral@1
   328
                              PIXELS_HOUR * 3, &bg_color,
leo_sobral@1
   329
                              &fg_color);
leo_sobral@1
   330
                              gtk_widget_add_events(event_box,
leo_sobral@1
   331
                              GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
leo_sobral@1
   332
leo_sobral@1
   333
            /* create EpgGridItem */
leo_sobral@1
   334
            EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1);
leo_sobral@1
   335
            epg_grid_item->proginfo  = NULL;
leo_sobral@1
   336
            epg_grid_item->event_box = event_box;
leo_sobral@1
   337
            epg_grid_item->object    = mmyth_epg_grid_widget;
leo_sobral@1
   338
leo_sobral@1
   339
            epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);
leo_sobral@1
   340
            
leo_sobral@1
   341
            gtk_box_pack_start (GTK_BOX (epg_line_hbox),
leo_sobral@1
   342
	                            event_box, FALSE, FALSE, PROGRAM_SEPARATION);            	
leo_sobral@1
   343
	                                 
leo_sobral@1
   344
   	        g_signal_connect (G_OBJECT (event_box), "button-press-event",
leo_sobral@1
   345
		                      G_CALLBACK (mmyth_epg_grid_widget_clicked),
leo_sobral@1
   346
                              (gpointer*) epg_grid_list);
leo_sobral@1
   347
        }
leo_sobral@1
   348
leo_sobral@1
   349
        epg_grid_list = g_list_reverse(epg_grid_list);
leo_sobral@1
   350
        mmyth_epg_grid_widget->epg_view_model = 
leo_sobral@1
   351
              g_list_append(mmyth_epg_grid_widget->epg_view_model, epg_grid_list);
leo_sobral@1
   352
        
leo_sobral@1
   353
	    gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox),
leo_sobral@1
   354
	                        epg_line_hbox, FALSE, FALSE,  0);                    		    		
leo_sobral@1
   355
    }
leo_sobral@1
   356
}
leo_sobral@1
   357
leo_sobral@1
   358
static void
leo_sobral@1
   359
mmyth_epg_grid_widget_mount_header(MMythEpgGridWidget *mmyth_epg_grid_widget)
leo_sobral@1
   360
{	          	    
leo_sobral@1
   361
    MMythEpgGridWidgetPrivate *private = 
leo_sobral@1
   362
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
leo_sobral@1
   363
    
leo_sobral@1
   364
    struct tm hour_tm;
leo_sobral@1
   365
    const gchar name_title[] = "Today";    
leo_sobral@1
   366
    GtkWidget * lbl_title = gtk_label_new(name_title);
leo_sobral@1
   367
leo_sobral@1
   368
    gtk_misc_set_alignment (GTK_MISC(lbl_title), 0.0, 0.5);
leo_sobral@1
   369
    
leo_sobral@1
   370
    gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox),
leo_sobral@1
   371
                        lbl_title, FALSE, FALSE, 0);
leo_sobral@1
   372
leo_sobral@1
   373
	/* hours title line */
leo_sobral@1
   374
    GtkWidget *epg_programs_hours_hbox = gtk_hbox_new (TRUE, 0); 
leo_sobral@1
   375
leo_sobral@1
   376
    if (localtime_r((time_t *)&private->current_start_time, &hour_tm) == NULL) {
leo_sobral@1
   377
        g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
leo_sobral@1
   378
        return NULL;
leo_sobral@1
   379
    }    
leo_sobral@1
   380
leo_sobral@1
   381
    if (hour_tm.tm_min>30) {
leo_sobral@1
   382
        hour_tm.tm_min = 30;
leo_sobral@1
   383
    } else if (hour_tm.tm_min>0) {
leo_sobral@1
   384
        hour_tm.tm_min = 0;
leo_sobral@1
   385
    }
leo_sobral@1
   386
        
leo_sobral@1
   387
    gchar hour1_str[10];
leo_sobral@1
   388
    strftime(hour1_str, 8, "%H:%M", &hour_tm);
leo_sobral@1
   389
    GtkWidget * lbl_hour1 = gtk_label_new(hour1_str);
leo_sobral@1
   390
    gtk_misc_set_alignment (GTK_MISC(lbl_hour1), 0.0, 0.5);    
leo_sobral@1
   391
	
leo_sobral@1
   392
    hour_tm.tm_hour++;
leo_sobral@1
   393
    gchar hour2_str[10];    
leo_sobral@1
   394
    strftime(hour2_str, 8, "%H:%M", &hour_tm);
leo_sobral@1
   395
    GtkWidget * lbl_hour2 = gtk_label_new(hour2_str);
leo_sobral@1
   396
    gtk_misc_set_alignment (GTK_MISC(lbl_hour2), 0.0, 0.5);        
leo_sobral@1
   397
leo_sobral@1
   398
    hour_tm.tm_hour++;
leo_sobral@1
   399
	gchar hour3_str[10];    
leo_sobral@1
   400
    strftime(hour3_str, 8, "%H:%M", &hour_tm);
leo_sobral@1
   401
    GtkWidget * lbl_hour3 = gtk_label_new(hour3_str);
leo_sobral@1
   402
    gtk_misc_set_alignment (GTK_MISC(lbl_hour3), 0.0, 0.5);        
leo_sobral@1
   403
    
leo_sobral@1
   404
    gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
leo_sobral@1
   405
                        lbl_hour1, TRUE, TRUE, 0);                    
leo_sobral@1
   406
    gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
leo_sobral@1
   407
                        lbl_hour2, TRUE, TRUE, 0);                    
leo_sobral@1
   408
    gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
leo_sobral@1
   409
                        lbl_hour3, TRUE, TRUE, 0); 
leo_sobral@1
   410
 
leo_sobral@1
   411
    gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox),
leo_sobral@1
   412
                        epg_programs_hours_hbox, FALSE, FALSE, 0);                        
leo_sobral@1
   413
}
leo_sobral@1
   414
leo_sobral@1
   415
/******************************************************************************
leo_sobral@1
   416
 *              INTERNAL CALLBACKS FOR STATE CHANGE                           *
leo_sobral@1
   417
 *****************************************************************************/
leo_sobral@1
   418
static void 
leo_sobral@1
   419
mmyth_epg_grid_widget_deselect_service(MMythEpgGridWidget *mmyth_epg_grid_widget)
leo_sobral@1
   420
{
leo_sobral@1
   421
	EpgGridItem *epg_grid_item;
leo_sobral@1
   422
	
leo_sobral@1
   423
  	/* deselect*/
leo_sobral@1
   424
    if(mmyth_epg_grid_widget->selected_grid_item != NULL) {
leo_sobral@1
   425
    	epg_grid_item = 
leo_sobral@1
   426
            (EpgGridItem*) mmyth_epg_grid_widget->selected_grid_item->data;
leo_sobral@1
   427
    	gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_NORMAL);
leo_sobral@1
   428
    }            
leo_sobral@1
   429
}
leo_sobral@1
   430
leo_sobral@1
   431
static void 
leo_sobral@1
   432
mmyth_epg_grid_widget_clicked (GtkWidget* widget, 
leo_sobral@1
   433
                               GdkEventExpose *event, gpointer data)
leo_sobral@1
   434
{           
leo_sobral@1
   435
    g_return_if_fail(data != NULL);
leo_sobral@1
   436
leo_sobral@1
   437
    GList *epg_grid_item_list = (GList *) data;
leo_sobral@1
   438
    EpgGridItem *epg_grid_item = (EpgGridItem *) epg_grid_item_list->data;
leo_sobral@1
   439
leo_sobral@1
   440
    /* update the selected service */
leo_sobral@1
   441
    mmyth_epg_grid_widget_update_service( epg_grid_item->object, (GList*) data );       
leo_sobral@1
   442
}
leo_sobral@1
   443
leo_sobral@1
   444
void
leo_sobral@1
   445
mmyth_epg_grid_widget_update_service(MMythEpgGridWidget * object,
leo_sobral@1
   446
                                     GList *selected_grid_list)
leo_sobral@1
   447
{
leo_sobral@1
   448
    g_return_if_fail(object != NULL);
leo_sobral@1
   449
    g_return_if_fail(selected_grid_list != NULL);
leo_sobral@1
   450
		
leo_sobral@1
   451
	EpgGridItem *epg_grid_item = (EpgGridItem *) selected_grid_list->data;
leo_sobral@1
   452
leo_sobral@1
   453
    mmyth_epg_grid_widget_deselect_service(epg_grid_item->object);
leo_sobral@1
   454
leo_sobral@1
   455
    /* updating current selected schedule_item and schedule_list*/
leo_sobral@1
   456
    object->selected_grid_item = selected_grid_list;
leo_sobral@1
   457
    
leo_sobral@1
   458
    /* set state of the event box */
leo_sobral@1
   459
    gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_SELECTED);
leo_sobral@1
   460
    /* emit update signal for listeners */
leo_sobral@1
   461
    g_signal_emit(object, 
leo_sobral@1
   462
                  mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL],
leo_sobral@1
   463
                  0,
leo_sobral@1
   464
                  (gpointer) epg_grid_item);
leo_sobral@1
   465
}
leo_sobral@1
   466
leo_sobral@1
   467
static GtkWidget * 
leo_sobral@1
   468
create_event_box_lbl(gchar *str, int width, const GdkColor *bg_color, 
leo_sobral@1
   469
                     const GdkColor *fg_color) 
leo_sobral@1
   470
{
leo_sobral@1
   471
    GtkWidget *event_box = gtk_event_box_new();
leo_sobral@1
   472
	GtkWidget *lbl = gtk_label_new(str);
leo_sobral@1
   473
    gtk_label_set_ellipsize(GTK_LABEL(lbl), PANGO_ELLIPSIZE_END);
leo_sobral@1
   474
leo_sobral@1
   475
    gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, bg_color);    
leo_sobral@1
   476
    gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, fg_color);    
leo_sobral@1
   477
    
leo_sobral@1
   478
    /* selected colors are const*/
leo_sobral@1
   479
    GdkColor selected_bg_color;
leo_sobral@1
   480
    selected_bg_color.red = 100;
leo_sobral@1
   481
    selected_bg_color.green = 40000;
leo_sobral@1
   482
    selected_bg_color.blue = 100;        
leo_sobral@1
   483
leo_sobral@1
   484
    GdkColor selected_fg_color;
leo_sobral@1
   485
    selected_fg_color.red = 100;
leo_sobral@1
   486
    selected_fg_color.green = 100;
leo_sobral@1
   487
    selected_fg_color.blue = 100;        
leo_sobral@1
   488
            
leo_sobral@1
   489
    gtk_widget_modify_bg(event_box, GTK_STATE_SELECTED, &selected_bg_color);    
leo_sobral@1
   490
    gtk_widget_modify_fg(lbl, GTK_STATE_SELECTED, &selected_fg_color);    
leo_sobral@1
   491
    
leo_sobral@1
   492
    gtk_misc_set_alignment (GTK_MISC(lbl), 0.0, 0.5);    
leo_sobral@1
   493
	gtk_container_add (GTK_CONTAINER (event_box),
leo_sobral@1
   494
                       lbl);
leo_sobral@1
   495
	gtk_widget_set_size_request(event_box, width, -1);
leo_sobral@1
   496
	                       
leo_sobral@1
   497
    return event_box;
leo_sobral@1
   498
}
leo_sobral@1
   499
leo_sobral@1
   500
/******************************************************************************
leo_sobral@1
   501
 *                            METHODS                                         *
leo_sobral@1
   502
 *****************************************************************************/
leo_sobral@1
   503
leo_sobral@1
   504
/* Callback for hardware keys */
leo_sobral@1
   505
gboolean
leo_sobral@1
   506
mmyth_epg_grid_widget_key_press (MMythEpgGridWidget * object, 
leo_sobral@1
   507
                                 GtkWidget * widget, GdkEventKey * event)
leo_sobral@1
   508
{
leo_sobral@1
   509
    MMythEpgGridWidgetPrivate *private = 
leo_sobral@1
   510
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(object);
leo_sobral@1
   511
  
leo_sobral@1
   512
    EpgGridItem *epg_grid_item;
leo_sobral@1
   513
    GList *tmp;
leo_sobral@1
   514
    
leo_sobral@1
   515
    /* List of selected_grid_item */
leo_sobral@1
   516
    GList *selected_view_model;
leo_sobral@1
   517
    
leo_sobral@1
   518
    gint channel_index;
leo_sobral@1
   519
    
leo_sobral@1
   520
	if(object->selected_grid_item == NULL) {
leo_sobral@1
   521
        g_warning ("No program selected");
leo_sobral@1
   522
	    return FALSE;
leo_sobral@1
   523
	} 
leo_sobral@1
   524
    
leo_sobral@1
   525
    epg_grid_item = (EpgGridItem*) object->selected_grid_item->data;    
leo_sobral@1
   526
    
leo_sobral@1
   527
    channel_index = private->selected_channel_index;
leo_sobral@1
   528
    
leo_sobral@1
   529
    switch (event->keyval) {
leo_sobral@1
   530
        case GDK_Up:        
leo_sobral@1
   531
            selected_view_model = g_list_nth( object->epg_view_model, channel_index - 1 );
leo_sobral@1
   532
            if(selected_view_model != NULL) {
leo_sobral@1
   533
                private->selected_channel_index = channel_index - 1;
leo_sobral@1
   534
   	            tmp = (GList *) selected_view_model->data;               
leo_sobral@1
   535
                /* TODO: select a better centralized item 
leo_sobral@1
   536
                   currently is picking the 1st or last item */
leo_sobral@1
   537
                if(g_list_next(object->selected_grid_item) == NULL &&
leo_sobral@1
   538
                   g_list_previous(object->selected_grid_item) != NULL) {
leo_sobral@1
   539
                    /* in this case the new selected will be the last */ 
leo_sobral@1
   540
                    tmp = g_list_last(tmp);
leo_sobral@1
   541
                }
leo_sobral@1
   542
leo_sobral@1
   543
	            /* update the selected service */
leo_sobral@1
   544
                mmyth_epg_grid_widget_update_service( object, tmp );
leo_sobral@1
   545
            }    
leo_sobral@1
   546
        return TRUE;         
leo_sobral@1
   547
        case GDK_Down:
leo_sobral@1
   548
            selected_view_model = g_list_nth( object->epg_view_model, channel_index + 1 );            
leo_sobral@1
   549
            if(selected_view_model != NULL) {   	            
leo_sobral@1
   550
                private->selected_channel_index = channel_index + 1;
leo_sobral@1
   551
   	            tmp = (GList *) selected_view_model->data;
leo_sobral@1
   552
                /* TODO: select a better centralized item 
leo_sobral@1
   553
                   currently is picking the 1st or last item */
leo_sobral@1
   554
                if(g_list_next(object->selected_grid_item) == NULL &&
leo_sobral@1
   555
                   g_list_previous(object->selected_grid_item) != NULL) {
leo_sobral@1
   556
                    /* in this case the new selected will be the last */ 
leo_sobral@1
   557
                    tmp = g_list_last(tmp);
leo_sobral@1
   558
                }
leo_sobral@1
   559
leo_sobral@1
   560
	            /* update the selected service */
leo_sobral@1
   561
                mmyth_epg_grid_widget_update_service( object, tmp );
leo_sobral@1
   562
            }
leo_sobral@1
   563
        return TRUE;        
leo_sobral@1
   564
        case GDK_Left:    
leo_sobral@1
   565
            tmp = g_list_previous( object->selected_grid_item );
leo_sobral@1
   566
            if(tmp != NULL) {
leo_sobral@1
   567
	            /* update the selected service */
leo_sobral@1
   568
                mmyth_epg_grid_widget_update_service( object, tmp );
leo_sobral@1
   569
            }
leo_sobral@1
   570
        return TRUE;        
leo_sobral@1
   571
        case GDK_Right:
leo_sobral@1
   572
            tmp = g_list_next( object->selected_grid_item );
leo_sobral@1
   573
            if(tmp != NULL) {
leo_sobral@1
   574
	            /* update the selected service */
leo_sobral@1
   575
                mmyth_epg_grid_widget_update_service( object, tmp );
leo_sobral@1
   576
            }
leo_sobral@1
   577
        return TRUE;        
leo_sobral@1
   578
	    default:
leo_sobral@1
   579
	    return TRUE;
leo_sobral@1
   580
    }
leo_sobral@1
   581
    
leo_sobral@1
   582
    return FALSE;
leo_sobral@1
   583
}
leo_sobral@1
   584
leo_sobral@1
   585
static void 
leo_sobral@1
   586
mmyth_epg_grid_widget_fill_programinfos (MMythEpgGridWidgetPrivate *private)
leo_sobral@1
   587
{
leo_sobral@1
   588
    GList *channels_list = NULL;
leo_sobral@1
   589
    int y;
leo_sobral@1
   590
leo_sobral@1
   591
    if ((private->mmyth_epg != NULL) &&
leo_sobral@1
   592
	   	(gmyth_epg_get_channel_list (private->mmyth_epg, &channels_list) < 0 )) {
leo_sobral@1
   593
			private->channel_list = NULL;
leo_sobral@1
   594
			return;
leo_sobral@1
   595
    }
leo_sobral@1
   596
    
leo_sobral@1
   597
    private->channel_list = channels_list;
leo_sobral@1
   598
    
leo_sobral@1
   599
    for (y = 0; y < private->DISPLAY_CHANS && channels_list; y++) {
leo_sobral@1
   600
        GMythChannelInfo *channel_info = (GMythChannelInfo *) channels_list->data;
leo_sobral@1
   601
leo_sobral@1
   602
        mmyth_epg_grid_widget_fill_program_row_infos(
leo_sobral@1
   603
                            private, channel_info->channel_ID, y);
leo_sobral@1
   604
leo_sobral@1
   605
        channels_list = g_list_next (channels_list);
leo_sobral@1
   606
    }
leo_sobral@1
   607
}
leo_sobral@1
   608
leo_sobral@1
   609
static void 
leo_sobral@1
   610
mmyth_epg_grid_widget_fill_program_row_infos(MMythEpgGridWidgetPrivate *private,
leo_sobral@1
   611
                                             guint chanNum, guint row)
leo_sobral@1
   612
{    
leo_sobral@1
   613
    gint res =  gmyth_epg_get_program_list (private->mmyth_epg,
leo_sobral@1
   614
    					&(private->program_list[row]),
leo_sobral@1
   615
                        chanNum, private->current_start_time, 
leo_sobral@1
   616
                        private->current_end_time);
leo_sobral@1
   617
                        
leo_sobral@1
   618
    if (res < 0) {
leo_sobral@1
   619
    	g_warning ("[%s] Error while retrieving epg programs", __FUNCTION__);
leo_sobral@1
   620
    }
leo_sobral@1
   621
}
leo_sobral@1
   622