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