Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

gtask-view.c

Go to the documentation of this file.
00001 #include <string.h>
00002 
00003 #include <gdk/gdk.h>
00004 
00005 #include <gtk/gtk.h>
00006 
00007 #include <gtk/gtkscrolledwindow.h>
00008 #include <gtk/gtkcellrenderertext.h>
00009 
00010 #include <gnome.h>
00011 
00012 #include <eel/eel.h>
00013 
00014 #include <gtask-ui/gtask-view.h>
00015 
00016 #include <gtask-ui/gtask-cell-renderer-basic.h>
00017 #include <gtask-ui/gtask-cell-renderer-progress.h>
00018 
00019 #include <gtask-ui/gtask-marshalers.h>
00020 
00021 #include "gtask-internals.h"
00022 #include "gtask-ui-util.h"
00023 
00026 /* @{ */
00027 
00028 enum {
00029     COL_TASK,
00030 
00031     COL_TITLE,
00032     COL_CATEGORY,
00033 
00034     COL_STATUS_MESSAGE,
00035     COL_ERROR_MESSAGE,
00036 
00037     COL_PROGRESS,
00038     COL_TIME_LEFT,
00039     COL_ACTIVITY_STATE,
00040 
00041     COL_OLD_THUMB_URI,
00042     COL_THUMBNAIL,
00043     COL_IS_THUMBNAIL,
00044 
00045     N_TASK_COLUMNS
00046 };
00047 
00048 enum {
00049     PROP_0,
00050     PROP_VIEW_MODE
00051 };
00052 
00054 typedef struct _GTaskTaskIter {
00055     GTaskGenericTask *task;
00056     GtkTreeIter       iter;
00057 } GTaskTaskIter;
00058 
00059 struct GTaskGetTaskFoo {
00060     guint      num;
00061     GTaskView *view;
00062     GList     *tasks;
00063     gboolean   with_active;
00064     gboolean   with_inactive;
00065     gboolean   with_completed;
00066 };
00067 
00068 static void
00069 gtask_task_iter_free( GTaskTaskIter *iter ) {
00070     g_object_unref( iter->task );
00071     g_free( iter );
00072 }
00073 
00074 static gpointer parent_class;
00075 
00076 static void
00077 gtask_view_init( GTaskView *view, gpointer g_class );
00078 
00079 static void
00080 gtask_view_class_init( GTaskViewClass *klass );
00081 
00082 static void
00083 gtask_view_destroy( GtkObject *obj );
00084 
00085 static void
00086 gtask_view_finalize( GObject *obj );
00087 
00088 static void
00089 gtask_view_create_basic_mode( GTaskView *view );
00090 
00091 static void
00092 gtask_view_create_list_mode( GTaskView *view );
00093 
00094 static void
00095 gtask_view_create_task_model( GTaskView *view );
00096 
00097 static void
00098 gtask_view_update_task( GTaskView *view, GTaskTaskIter *iter );
00099 
00100 static gboolean
00101 gtask_view_button_press( GtkWidget *list,
00102                          GdkEventButton *event,
00103                          gpointer data );
00104 
00105 static void
00106 gtask_view_open_file( GObject *obj, gpointer *data );
00107 
00108 static void
00109 gtask_view_open_dir( GObject *obj, gpointer *data );
00110 
00111 /*
00112 static void
00113 gtask_view_open_file_properties( GObject *obj, gpointer *data );
00114 */
00115 
00116 static void
00117 gtask_view_set_property( GObject *object,
00118                          guint param_id,
00119                          const GValue *value,
00120                          GParamSpec *pspec );
00121 
00122 static void
00123 gtask_view_get_property( GObject *object,
00124                          guint param_id,
00125                          GValue *value,
00126                          GParamSpec *pspec );
00127 
00128 GType gtask_view_mode_get_type( ) {
00129     static GType type = 0;
00130 
00131     if( type == 0 ) {
00132         static const GEnumValue values[] = {
00133             { GTASK_VIEW_MODE_BASIC, "GTASK_VIEW_MODE_BASIC", "basic view" },
00134             { GTASK_VIEW_MODE_LIST, "GTASK_VIEW_MODE_LIST", "list view" },
00135             { 0, NULL, NULL }
00136         };
00137 
00138         type = g_enum_register_static( "GTaskViewMode", values );
00139     }
00140 
00141     return type;
00142 }
00143 
00144 GType gtask_view_get_type( ) {
00145     static GType type = 0;
00146 
00147     if( type == 0 ) {
00148         static const GTypeInfo info = {
00149             sizeof( GTaskViewClass ),
00150             NULL,   /* base init */
00151             NULL,   /* base_finalize */
00152             (GClassInitFunc) gtask_view_class_init,   /* class_init */
00153             NULL,   /* class_finalize */
00154             NULL,   /* class_data */
00155             sizeof( GTaskView ),
00156             0,      /* n_preallocs */
00157             (GInstanceInitFunc) gtask_view_init
00158             };
00159     
00160             type = g_type_register_static( GTK_TYPE_NOTEBOOK,
00161                                            "GTaskView",
00162                                            &info,
00163                                            0 );
00164         }
00165 
00166     return type;
00167 }
00168 
00169 static void
00170 gtask_view_init( GTaskView *view, gpointer g_class ) {
00171     GTaskViewPrivate *private;
00172 
00173     private = view->private = g_new0( GTaskViewPrivate, 1 );
00174 
00175     private->filter_string = g_string_new( NULL );
00176     private->filter_seed = g_ptr_array_new( );
00177     private->filter_columns = g_ptr_array_new( );
00178 
00179     /* the columns to filter by default, in the future this may perhaps
00180      * be configurable -- who's to say?
00181      */
00182     g_ptr_array_add( private->filter_columns,
00183                      GINT_TO_POINTER( COL_TITLE ) );
00184 
00185     g_ptr_array_add( private->filter_columns,
00186                      GINT_TO_POINTER( COL_STATUS_MESSAGE ) );
00187 
00188     g_ptr_array_add( private->filter_columns,
00189                      GINT_TO_POINTER( COL_ERROR_MESSAGE ) );
00190 
00191     g_ptr_array_add( private->filter_columns,
00192                      GINT_TO_POINTER( COL_CATEGORY ) );
00193 
00194     private->task_hash = g_hash_table_new_full( g_str_hash, g_str_equal,
00195                                                 g_free,
00196                                                 (GDestroyNotify) gtask_task_iter_free );
00197 
00198     gtk_notebook_set_show_tabs( (GtkNotebook *) view, FALSE );
00199     gtk_notebook_set_show_border( (GtkNotebook *) view, TRUE );
00200 
00201     gtask_view_create_task_model( view );
00202     gtask_view_create_basic_mode( view );
00203     gtask_view_create_list_mode( view );
00204 
00205     private->view_mode = GTASK_VIEW_MODE_BASIC;
00206 
00207     gtk_tree_view_set_model( private->task_view_basic,
00208                              (GtkTreeModel *) private->task_model_filter );
00209 
00210     gtk_notebook_set_current_page( (GtkNotebook *) view, 0 );
00211 
00212     gtk_tree_view_set_model( private->task_view_list, NULL );
00213 
00214     private->thumbnailer = gnome_thumbnail_factory_new( GNOME_THUMBNAIL_SIZE_NORMAL );
00215 }
00216 
00217 static void
00218 gtask_view_class_init( GTaskViewClass *klass ) {
00219     GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
00220     GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS( klass );
00221     GType           param_types[1];
00222 
00223     parent_class = g_type_class_peek_parent( klass );
00224 
00225     gobject_class->finalize = gtask_view_finalize;
00226     gobject_class->set_property = gtask_view_set_property;
00227     gobject_class->get_property = gtask_view_get_property;
00228 
00229     gtk_object_class->destroy = gtask_view_destroy;
00230 
00231     g_object_class_install_property( gobject_class,
00232                                      PROP_VIEW_MODE,
00233                                      g_param_spec_enum( "view-mode",
00234                                                         "View Mode",
00235                                                         "The currently selected view mode for the GTaskView",
00236                                                         GTASK_VIEW_MODE_TYPE,
00237                                                         GTASK_VIEW_MODE_BASIC,
00238                                                         G_PARAM_READWRITE ) );
00239 
00240     param_types[0] = G_TYPE_POINTER;
00241 
00242     klass->tasks_added_signal_id = g_signal_newv( "tasks-added",
00243                                                   G_TYPE_FROM_CLASS( klass ),
00244                                                   G_SIGNAL_RUN_LAST |
00245                                                     G_SIGNAL_NO_RECURSE |
00246                                                     G_SIGNAL_NO_HOOKS,
00247                                                   NULL,
00248                                                   NULL,
00249                                                   NULL,
00250                                                   gtask_marshal_VOID__POINTER,
00251                                                   G_TYPE_NONE,
00252                                                   1,
00253                                                   param_types );
00254 
00255     klass->tasks_updated_signal_id = g_signal_newv( "tasks-updated",
00256                                                   G_TYPE_FROM_CLASS( klass ),
00257                                                   G_SIGNAL_RUN_LAST |
00258                                                     G_SIGNAL_NO_RECURSE |
00259                                                     G_SIGNAL_NO_HOOKS,
00260                                                   NULL,
00261                                                   NULL,
00262                                                   NULL,
00263                                                   gtask_marshal_VOID__POINTER,
00264                                                   G_TYPE_NONE,
00265                                                   1,
00266                                                   param_types );
00267 
00268     klass->tasks_removed_signal_id = g_signal_newv( "tasks-removed",
00269                                                   G_TYPE_FROM_CLASS( klass ),
00270                                                   G_SIGNAL_RUN_LAST |
00271                                                     G_SIGNAL_NO_RECURSE |
00272                                                     G_SIGNAL_NO_HOOKS,
00273                                                   NULL,
00274                                                   NULL,
00275                                                   NULL,
00276                                                   gtask_marshal_VOID__POINTER,
00277                                                   G_TYPE_NONE,
00278                                                   1,
00279                                                   param_types );
00280 }
00281 
00282 static void
00283 gtask_view_destroy( GtkObject *obj ) {
00284     //GTaskView *view = GTASK_VIEW( obj );
00285 
00286     if( GTK_OBJECT_CLASS( parent_class )->destroy )
00287         GTK_OBJECT_CLASS( parent_class )->destroy( obj );
00288 }
00289 
00290 static void
00291 gtask_view_finalize( GObject *obj ) {
00292     GTaskView *view = GTASK_VIEW( obj );
00293 
00294     g_free( view->private );
00295 
00296     g_string_free( view->private->filter_string, TRUE );
00297 
00298     g_ptr_array_free( view->private->filter_seed, TRUE );
00299 
00300     if( G_OBJECT_CLASS( parent_class )->finalize )
00301         G_OBJECT_CLASS( parent_class )->finalize( obj );
00302 }
00303 
00304 static gboolean
00305 gtask_view_filter_func( GtkTreeModel *model, GtkTreeIter *iter, gpointer data )
00306 {
00307     GTaskView        *view = GTASK_VIEW( data );
00308     GTaskViewPrivate *private = view->private;
00309 
00310     gpointer         *columns = private->filter_columns->pdata;
00311     GPtrArray        *filter_seed = private->filter_seed;
00312     guint             n_columns = private->filter_columns->len;
00313     guint             i;
00314     guint             j;
00315     char             *low_str;
00316     char             *test_str;
00317 
00318     GString          *tot_str;
00319 
00320     g_debug( "IN: gtask_view_filter_func" );
00321 
00322     /* end right now if there is no filter string */
00323     if( filter_seed->len == 0 ) {
00324         g_debug( "LEAVING: gtask_view_filter_func - filter_seed empty" );
00325         return TRUE;
00326     }
00327 
00328     /* also end if no filter columns have been set */
00329     if( n_columns < 1 ) {
00330         g_debug( "LEAVING: gtask_view_filter_func - no filter columns set" );
00331         return TRUE;
00332     }
00333 
00334     tot_str = g_string_new( NULL );
00335 
00336     /* right now we are just placing everything in one larger string
00337      * and matching substrings on that. In cases where the model might
00338      * old a wheee bit of text this might not be that bright of an idea
00339      * @todo determine a possible better way of doing this 
00340      */
00341     for( i = 0; i < n_columns; i++ ) {
00342         const char *val;
00343         GValue      value = { 0, };
00344 
00345         gtk_tree_model_get_value( GTK_TREE_MODEL( private->task_model ), iter,
00346                                   GPOINTER_TO_INT( columns[i] ), &value );
00347 
00348         val = g_value_get_string( &value );
00349 
00350         if( !val ) {
00351             g_value_unset( &value );
00352 
00353             continue;
00354         }
00355 
00356         g_string_append( tot_str, val );
00357 
00358         g_value_unset( &value );
00359     }
00360 
00361     low_str = g_utf8_strdown( tot_str->str, -1 );
00362     test_str = g_utf8_normalize( low_str, -1, G_NORMALIZE_ALL );
00363 
00364     g_string_free( tot_str, TRUE );
00365     g_free( low_str );
00366 
00367     for( j = 0; j < filter_seed->len; j++ ) {
00368         char *seed_tmp = filter_seed->pdata[j];
00369 
00370         if( g_strrstr( test_str, seed_tmp ) == NULL ) {
00371             g_free( test_str );
00372 
00373             g_debug( "LEAVING: gtask_view_filter_func - row will not be shown" );
00374             return FALSE;
00375         }
00376     }
00377 
00378     g_free( test_str );
00379     g_debug( "LEAVING: gtask_view_filter_func - row will be shown" );
00380 
00381     return TRUE;
00382 }
00383 
00384 static void
00385 gtask_view_create_task_model( GTaskView *view ) {
00386     GTaskViewPrivate   *private= view->private;
00387     GtkTreeStore       *task_model;
00388     GtkTreeModelFilter *task_model_filter;
00389                 
00390     g_assert( private->task_model == NULL );
00391     g_assert( private->task_model_filter == NULL );
00392                         
00393     task_model = gtk_tree_store_new( N_TASK_COLUMNS,
00394                                      GTASK_GENERIC_TASK_TYPE,
00395 
00396                                      G_TYPE_STRING,
00397                                      G_TYPE_STRING,
00398 
00399                                      G_TYPE_STRING,
00400                                      G_TYPE_STRING,
00401 
00402                                      G_TYPE_FLOAT,
00403                                      G_TYPE_LONG,
00404                                      GTASK_ACTIVITY_STATE_TYPE,
00405                                      
00406                                      G_TYPE_STRING,
00407                                      GDK_TYPE_PIXBUF,
00408                                      G_TYPE_BOOLEAN );
00409 
00410     task_model_filter = GTK_TREE_MODEL_FILTER( gtk_tree_model_filter_new( GTK_TREE_MODEL( task_model ), NULL ) );
00411 
00412     gtk_tree_model_filter_set_visible_func( task_model_filter,
00413                                             gtask_view_filter_func,
00414                                             view,
00415                                             NULL );
00416 
00417     private->task_model = task_model;
00418     private->task_model_filter = task_model_filter;
00419 }
00420 
00421 static void
00422 gtask_view_create_basic_mode( GTaskView *view ) {
00423     GTaskViewPrivate   *private = view->private;
00424     GtkTreeViewColumn  *info_column;
00425     GtkCellRenderer    *rend;
00426     GtkTreeView        *task_view;
00427     GtkWidget          *task_scroll;
00428 
00429     g_assert( private->task_view_basic == NULL );
00430 
00431     task_scroll = gtk_scrolled_window_new( NULL, NULL );
00432     gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( task_scroll ),
00433                                     GTK_POLICY_NEVER,
00434                                     GTK_POLICY_AUTOMATIC );
00435 
00436     task_view = GTK_TREE_VIEW( gtk_tree_view_new( ) );
00437 
00438     gtk_container_add( GTK_CONTAINER( task_scroll ), GTK_WIDGET( task_view ) );
00439 
00440     gtk_notebook_append_page( (GtkNotebook *) view,
00441                               GTK_WIDGET( task_scroll ),
00442                               NULL );
00443 
00444     gtk_tree_view_set_headers_visible( task_view, FALSE );
00445     gtk_tree_view_set_rules_hint( task_view, TRUE );
00446     gtk_tree_view_set_reorderable( task_view, TRUE );
00447 
00448     info_column = gtk_tree_view_column_new();
00449 
00450     rend = GTK_CELL_RENDERER( gtask_cell_renderer_basic_new( ) );
00451 
00452     gtk_tree_view_column_pack_start( info_column, rend, TRUE );
00453     gtk_tree_view_column_set_attributes( info_column, rend,
00454                                          "progress", COL_PROGRESS,
00455                                          "title", COL_TITLE,
00456                                          "status-message", COL_STATUS_MESSAGE,
00457                                          "activity-state", COL_ACTIVITY_STATE,
00458                                          "preview", COL_THUMBNAIL,
00459                                          "preview-is-thumb", COL_IS_THUMBNAIL,
00460                                          "time-left", COL_TIME_LEFT,
00461                                          NULL );
00462 
00463     gtk_tree_view_append_column( GTK_TREE_VIEW( task_view ), info_column );
00464 
00465     g_signal_connect( G_OBJECT( task_view ),
00466                       "button-press-event",
00467                       G_CALLBACK( gtask_view_button_press ),
00468                       view );
00469 
00470     private->task_view_basic = task_view;
00471 }
00472 
00473 static void
00474 gtask_view_create_list_mode( GTaskView *view ) {
00475     GtkNotebook        *view_book = (GtkNotebook *) view;
00476     GTaskViewPrivate   *private =  view->private;
00477     GtkTreeViewColumn  *column;
00478     GtkCellRenderer    *rend;
00479     GtkTreeView        *task_view;
00480     GtkScrolledWindow  *task_list_scroll;
00481 
00482     g_assert( private->task_view_list == NULL );
00483 
00484     task_list_scroll = GTK_SCROLLED_WINDOW( gtk_scrolled_window_new( NULL, NULL ) );
00485 
00486     gtk_scrolled_window_set_policy( task_list_scroll,
00487                                     GTK_POLICY_AUTOMATIC,
00488                                     GTK_POLICY_AUTOMATIC );
00489 
00490     task_view = GTK_TREE_VIEW( gtk_tree_view_new( ) );
00491 
00492     gtk_container_add( GTK_CONTAINER( task_list_scroll ),
00493                        GTK_WIDGET( task_view ) );
00494 
00495     gtk_notebook_append_page( view_book,
00496                               GTK_WIDGET( task_list_scroll ),
00497                               NULL );
00498 
00499     gtk_tree_view_set_headers_visible( task_view, TRUE );
00500 
00501     gtk_tree_view_set_rules_hint( task_view, TRUE );
00502     gtk_tree_view_set_reorderable( task_view, TRUE );
00503 
00504     rend = gtk_cell_renderer_text_new();
00505 
00506     gtk_tree_view_insert_column_with_attributes( task_view,
00507                                                  0,
00508                                                  "Title",
00509                                                  rend,
00510                                                  "text", COL_TITLE,
00511                                                  NULL );
00512     column = gtk_tree_view_get_column( task_view, 0 );
00513     gtk_tree_view_column_set_resizable( column, TRUE );
00514 
00515     gtk_tree_view_insert_column_with_attributes( task_view,
00516                                                  1,
00517                                                  "Status Message",
00518                                                  rend,
00519                                                  "text", COL_STATUS_MESSAGE,
00520                                                  NULL );
00521     column = gtk_tree_view_get_column( task_view, 1 );
00522     gtk_tree_view_column_set_resizable( column, TRUE );
00523 
00524     gtk_tree_view_insert_column_with_attributes( task_view,
00525                                                  2,
00526                                                  "Category",
00527                                                  rend,
00528                                                  "text", COL_CATEGORY,
00529                                                  NULL );
00530 
00531     column = gtk_tree_view_get_column( task_view, 2 );
00532     gtk_tree_view_column_set_resizable( column, TRUE );
00533 
00534     rend = GTK_CELL_RENDERER( gtask_cell_renderer_progress_new( ) );
00535 
00536     gtk_tree_view_insert_column_with_attributes( task_view,
00537                                                  3,
00538                                                  "Percent Completed",
00539                                                  rend,
00540                                                  "value", COL_PROGRESS,
00541                                                  "activity-state", COL_ACTIVITY_STATE,
00542                                                  NULL );
00543 
00544     column = gtk_tree_view_get_column( task_view, 3 );
00545     gtk_tree_view_column_set_resizable( column, TRUE );
00546 
00547     g_signal_connect( G_OBJECT( task_view ),
00548                       "button-press-event",
00549                       G_CALLBACK( gtask_view_button_press ),
00550                       view );
00551 
00552     private->task_view_list = task_view;
00553 }
00554 
00555 static void
00556 test_close_not( gpointer data, GClosure *closure ) {
00557     g_debug( "===> in test_close_not for: %s", (gchar *) data );
00558     g_free( data );
00559 }
00560 
00561 static GtkWidget *
00562 gtask_view_create_file_menu_subitem( GTaskView *view,
00563                                      GTaskFile *file,
00564                                      guint      bound )
00565 {
00566     GTaskViewPrivate *private = view->private;
00567     GtkWidget        *file_item;
00568     const gchar      *tmp;
00569     gchar            *display_name;
00570 
00571     GSList           *preview_opts;
00572     GSList           *preview_opts_tmp;
00573 
00574     GdkPixbuf        *preview_pixbuf = NULL;
00575 
00576     const gchar      *file_uri = gtask_file_get_uri( file );
00577 
00578     /* determine the what to display in the label */
00579     tmp = gtask_file_get_description( file );
00580 
00581     if( tmp&& strlen( tmp ) )
00582         display_name = g_strdup( tmp );
00583     else
00584         display_name = g_path_get_basename( file_uri );
00585 
00586     file_item = gtk_image_menu_item_new_with_label( display_name );
00587     g_free( display_name );
00588 
00589     /* determine which thumbnail to load */
00590     preview_opts = gtask_ui_get_file_preview_options( file );
00591 
00592     preview_opts_tmp = preview_opts;
00593 
00594     while( preview_opts_tmp ) {
00595         GTaskPreview *preview = (GTaskPreview *) preview_opts_tmp->data;
00596 
00597         preview_pixbuf = gtask_preview_get_pixbuf( preview, 
00598                                                    private->thumbnailer );
00599 
00600         if( preview_pixbuf )
00601             break;
00602 
00603         preview_opts_tmp = g_slist_next( preview_opts_tmp );
00604     }
00605 
00606     gtask_preview_list_free( preview_opts );
00607 
00608     if( preview_pixbuf ) {
00609         GtkWidget *thumb_widget;
00610         GdkPixbuf *preview_scaled;
00611 
00612         preview_scaled = eel_gdk_pixbuf_scale_down_to_fit( preview_pixbuf,
00613                                                            bound,
00614                                                            bound );
00615 
00616         thumb_widget = gtk_image_new_from_pixbuf( preview_scaled );
00617 
00618         g_object_unref( (GObject *) preview_pixbuf );
00619         g_object_unref( (GObject *) preview_scaled );
00620 
00621         if( thumb_widget ) {
00622             gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM( file_item ),
00623                                            thumb_widget );
00624         }
00625     }
00626 
00627     if( gtask_file_get_completed( file ) ) {
00628         gtk_widget_set_sensitive( file_item, TRUE );
00629 
00630         g_signal_connect_data( G_OBJECT( file_item ),
00631                                "activate",
00632                                G_CALLBACK( gtask_view_open_file ),
00633                                g_strdup( file_uri ),
00634                                (GClosureNotify) test_close_not,
00635                                G_CONNECT_AFTER );
00636     } else {
00637         gtk_widget_set_sensitive( file_item, FALSE );
00638     }
00639 
00640     return file_item;
00641 }
00642 
00643 static GtkMenuItem *
00644 gtask_view_create_file_menu_item( GTaskView         *view,
00645                                   GTaskFileListInfo *file_info,
00646                                   guint              bound )
00647 {
00648     GtkMenuItem *item;
00649     GList       *files;
00650 
00651     g_assert( file_info != NULL );
00652 
00653     item = GTK_MENU_ITEM( gtk_image_menu_item_new_from_stock( GTK_STOCK_OPEN, NULL ) );
00654 
00655     files = file_info->files;
00656 
00657     if( file_info->num_files == 1 ) {
00658         GTaskFile   *file = (GTaskFile *) files->data;
00659         const gchar *file_uri = gtask_file_get_uri( file );
00660 
00661         if( gtask_file_get_completed( file ) ) {
00662             g_signal_connect_data( G_OBJECT( item ),
00663                                    "activate",
00664                                    G_CALLBACK( gtask_view_open_file ),
00665                                    g_strdup( file_uri ),
00666                                    (GClosureNotify) test_close_not,
00667                                    G_CONNECT_AFTER );
00668 
00669             gtk_widget_set_sensitive( (GtkWidget *) item, TRUE );
00670         } else {
00671             gtk_widget_set_sensitive( (GtkWidget *) item, FALSE );
00672         }
00673     } else if( file_info->num_files > 1 ) {
00674         GtkMenuShell *file_menu = GTK_MENU_SHELL( gtk_menu_new( ) );
00675             
00676         g_debug( "=====> %d %p", file_info->num_files, files );
00677 
00678         while( files ) {
00679             GTaskFile   *file = (GTaskFile *) files->data;
00680             GtkWidget   *file_sub;
00681             
00682             file_sub = gtask_view_create_file_menu_subitem( view, file, bound );
00683 
00684             gtk_menu_shell_append( file_menu, file_sub );
00685             files = g_list_next( files );
00686         }
00687 
00688         gtk_menu_item_set_submenu( item, (GtkWidget *) file_menu );
00689     } else {
00690         gtk_widget_set_sensitive( (GtkWidget *) item, FALSE );
00691     }
00692 
00693     return item;
00694 }
00695 
00696 static GtkMenuItem *
00697 gtask_view_create_dir_menu_item( GTaskView         *view,
00698                                  GTaskFileListInfo *file_info )
00699 {
00700     GtkMenuItem *item;
00701     GList       *dirs;
00702 
00703     g_assert( file_info != NULL );
00704 
00705     item = GTK_MENU_ITEM( gtk_menu_item_new_with_mnemonic( "Open Containing _Folder" ) );
00706 
00707     dirs = file_info->unique_directories;
00708 
00709     if( file_info->num_unique_directories == 1 ) {
00710         const gchar *dir_uri = (gchar *) dirs->data;
00711 
00712         g_signal_connect_data( G_OBJECT( item ),
00713                                "activate",
00714                                G_CALLBACK( gtask_view_open_dir ),
00715                                g_strdup( dir_uri ),
00716                                (GClosureNotify) test_close_not,
00717                                G_CONNECT_AFTER );
00718 
00719         gtk_widget_set_sensitive( (GtkWidget *) item, TRUE );
00720     } else if( file_info->num_unique_directories > 1 ) {
00721         GtkMenuShell *dir_menu = GTK_MENU_SHELL( gtk_menu_new( ) );
00722         GtkWidget    *dir_item;
00723             
00724         while( dirs ) {
00725             gchar *dir_uri = (gchar *) dirs->data;
00726 
00727             dir_item = gtk_menu_item_new_with_label( dir_uri );
00728 
00729             g_signal_connect_data( G_OBJECT( dir_item ),
00730                                    "activate",
00731                                    G_CALLBACK( gtask_view_open_dir ),
00732                                    g_strdup( dir_uri ),
00733                                    (GClosureNotify) test_close_not,
00734                                    G_CONNECT_AFTER );
00735 
00736             gtk_menu_shell_append( dir_menu, dir_item );
00737             dirs = g_list_next( dirs );
00738         }
00739 
00740         gtk_menu_item_set_submenu( item, (GtkWidget *) dir_menu );
00741     } else {
00742         gtk_widget_set_sensitive( (GtkWidget *) item, FALSE );
00743     }
00744 
00747     return item;
00748 }
00749 
00750 static gboolean
00751 gtask_view_button_press( GtkWidget *list,
00752                          GdkEventButton *event, 
00753                          gpointer data )
00754 {
00755     GTaskView        *view = GTASK_VIEW( data );
00756     GTaskViewPrivate *private = view->private;
00757 
00758     g_debug( "IN: gtask_view_button_press" );
00759 
00764     if( event->button == 3 && event->type == GDK_BUTTON_PRESS ) {
00765         GTaskGenericTask  *task;
00766         GTaskFileListInfo *file_info;
00767 
00768         GList             *files;
00769         GtkMenuShell      *task_menu;
00770         GtkTreePath       *path;
00771         GtkMenuItem       *item;
00772         GtkTreeIter        iter;
00773         GtkTreeModel      *task_model = GTK_TREE_MODEL( private->task_model );
00774         PangoLayout       *layout;
00775         guint              bound;
00776 
00777         /* figure out where the user clicked */
00778         if( !gtk_tree_view_get_path_at_pos( GTK_TREE_VIEW( list ),
00779                                             event->x,
00780                                             event->y,
00781                                             &path,
00782                                             NULL, NULL, NULL)) {
00783             return FALSE;
00784         }
00785 
00786         gtk_tree_model_get_iter( task_model, &iter, path );
00787 
00788         gtk_tree_model_get( task_model, &iter,
00789                             COL_TASK, &task,
00790                             -1 );
00791 
00792         files = gtask_generic_task_get_files( task );
00793 
00798         file_info = gtask_ui_get_file_list_info( files );
00799 
00800         task_menu = GTK_MENU_SHELL( gtk_menu_new( ) );
00801 
00802         g_signal_connect( task_menu,
00803                           "selection-done",
00804                           G_CALLBACK( gtk_object_destroy ),
00805                           NULL );
00806 
00807         layout = gtk_widget_create_pango_layout( list, NULL );
00808 
00809         pango_layout_get_pixel_size( layout, NULL, &bound );
00810 
00811         g_object_unref( (GObject *) layout );
00812 
00813         item = gtask_view_create_file_menu_item( view, file_info, bound );
00814         gtk_menu_shell_append( task_menu, (GtkWidget *) item );
00815 
00816         item = gtask_view_create_dir_menu_item( view, file_info );
00817         gtk_menu_shell_append( task_menu, (GtkWidget *) item );
00818 
00819         gtk_widget_show_all( (GtkWidget *) task_menu );
00820 
00821         gtk_menu_popup( (GtkMenu *) task_menu, NULL, NULL, NULL, NULL, 3, event->time);
00822 
00823 
00824         g_debug( "LEAVING: gtask_view_button_press" );
00825 
00826         return TRUE;
00827     }
00828 
00829     g_debug( "LEAVING: gtask_view_button_press" );
00830 
00831     return FALSE;
00832 }
00833 
00834 static void
00835 close_error_window( GtkDialog *dialog, gint arg1, gpointer data ) {
00836     gtk_widget_destroy( GTK_WIDGET( dialog ) );
00837 }
00838 
00839 static void
00840 gtask_view_open_file( GObject *obj, gpointer *data ) {
00841     char   *argv[3];
00842     char   *file = (char *) data;
00843     GError *error = NULL;
00844 
00845     argv[0] = "gnome-open";
00846     argv[1] = file;
00847     argv[2] = NULL;
00848 
00849     g_debug( "IN: gtask_view_open_file" );
00850 
00851     if( !g_spawn_async( NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error ) )
00852     {
00853         GtkWidget *mess_win;
00854 
00857         mess_win = gtk_message_dialog_new( NULL, 0,
00858                                 GTK_MESSAGE_ERROR,
00859                                 GTK_BUTTONS_OK,
00860                                 error->message );
00861 
00862         g_signal_connect( mess_win,
00863                          "response",
00864                          G_CALLBACK( close_error_window ),
00865                          NULL );
00866 
00867         gtk_widget_show( mess_win );
00868     }
00869 
00870     g_debug( "LEAVING: gtask_view_open_file" );
00871 }
00872 
00873 /*
00874 static void
00875 gtask_view_open_file_properties( GObject *obj, gpointer *data ) {
00876     g_debug( "IN: gtask_view_open_file_properties" );
00877     g_debug( "LEAVING: gtask_view_open_file_properties" );
00878 }
00879 */
00880 
00881 static void
00882 gtask_view_open_dir( GObject *obj, gpointer *data ) {
00883     gchar  *argv[3];
00884     gchar  *dir = (gchar *) data;
00885     GError *error = NULL;
00886 
00887     argv[0] = "nautilus";
00888     argv[1] = dir;
00889     argv[2] = NULL;
00890 
00891     g_debug( "IN: gtask_view_open_dir" );
00892 
00893     if( !g_spawn_async( NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error ) )
00894     {
00895         GtkWidget *mess_win;
00896 
00899         mess_win = gtk_message_dialog_new( NULL, 0,
00900                                 GTK_MESSAGE_ERROR,
00901                                 GTK_BUTTONS_OK,
00902                                 error->message );
00903 
00904         g_signal_connect( mess_win,
00905                          "response",
00906                          G_CALLBACK( close_error_window ),
00907                          NULL );
00908 
00909         gtk_widget_show( mess_win );
00910     }
00911 
00912     g_debug( "LEAVING: gtask_view_open_dir" );
00913 }
00914 
00915 static void
00916 gtask_view_set_property( GObject *object,
00917                          guint param_id,
00918                          const GValue *value,
00919                          GParamSpec *pspec )
00920 {
00921     GTaskView *view = GTASK_VIEW( object );
00922 
00923     switch( param_id ) {
00924         case PROP_VIEW_MODE:
00925             gtask_view_set_view_mode( view, g_value_get_enum( value ) );
00926             break;
00927         default:
00928             G_OBJECT_WARN_INVALID_PROPERTY_ID( object, param_id, pspec );
00929     }
00930 }
00931 
00932 static void
00933 gtask_view_get_property( GObject *object,
00934                          guint param_id,
00935                          GValue *value,
00936                          GParamSpec *pspec )
00937 {
00938     GTaskView *view = GTASK_VIEW( object );
00939 
00940     switch( param_id ) {
00941         case PROP_VIEW_MODE:
00942             g_value_set_enum( value, gtask_view_get_view_mode( view ) );
00943             break;
00944         default:
00945             G_OBJECT_WARN_INVALID_PROPERTY_ID( object, param_id, pspec );
00946     }
00947 }
00948 
00949 GTaskView *
00950 gtask_view_new( ) {
00951     return GTASK_VIEW( g_object_new( GTASK_VIEW_TYPE, NULL ) );
00952 }
00953 
00954 void
00955 gtask_view_set_view_mode( GTaskView *view, GTaskViewMode mode ) {
00956     GTaskViewPrivate *private;
00957 
00958     g_return_if_fail( GTASK_IS_VIEW( view ) );
00959 
00960     g_debug( "IN: gtask_view_set_view_mode" );
00961 
00962     private = view->private;
00963 
00964     if( mode == private->view_mode ) {
00965         g_debug( "LEAVING: gtask_view_set_view_mode - new mode same as old one" );
00966         return;
00967     }
00968 
00969     private->view_mode = mode;
00970 
00971     if( mode == GTASK_VIEW_MODE_BASIC ) {
00972         gtk_tree_view_set_model( private->task_view_basic,
00973                                  (GtkTreeModel *) private->task_model_filter );
00974 
00975         gtk_notebook_set_current_page( (GtkNotebook *) view, 0 );
00976 
00977         gtk_tree_view_set_model( private->task_view_list, NULL );
00978     } else {
00979         gtk_tree_view_set_model( private->task_view_list,
00980                                  (GtkTreeModel *) private->task_model_filter );
00981 
00982         gtk_notebook_set_current_page( (GtkNotebook *) view, 1 );
00983 
00984         gtk_tree_view_set_model( private->task_view_basic, NULL );
00985     }
00986 
00987     g_object_notify( (GObject *) view, "view-mode" );
00988 
00989     g_debug( "LEAVING: gtask_view_set_view_mode - mode changed" );
00990 }
00991 
00992 GTaskViewMode
00993 gtask_view_get_view_mode( GTaskView *view ) {
00994     g_return_val_if_fail( GTASK_IS_VIEW( view ), GTASK_VIEW_MODE_BASIC );
00995 
00996     return view->private->view_mode;
00997 }
00998 
00999 void
01000 gtask_view_add_task( GTaskView *view, GTaskGenericTask *task ) {
01001     GTaskViewPrivate *private = view->private;
01002     const char       *task_id;
01003     GTaskTaskIter    *task_iter;
01004     guint             signal_id;
01005     GList            *task_list = NULL;
01006 
01007     g_return_if_fail( GTASK_IS_VIEW( view ) );
01008     g_return_if_fail( GTASK_IS_GENERIC_TASK( task ) );
01009 
01010     g_warning( "IN: gtask_view_add_task" );
01011 
01012     task_id = gtask_generic_task_get_id( task );
01013 
01014     task_iter = (GTaskTaskIter *) g_hash_table_lookup( private->task_hash,
01015                                                        task_id );
01016 
01019     /* not in the model, insert it in */
01020     if( !task_iter ) {
01021         task_iter = g_new0( GTaskTaskIter, 1 );
01022 
01023         g_object_ref( task );
01024         task_iter->task = task;
01025         
01026         gtk_tree_store_append( private->task_model, &(task_iter->iter), NULL );
01027 
01028         /* set a default activity state */
01029         gtk_tree_store_set( private->task_model, &(task_iter->iter),
01030                             COL_ACTIVITY_STATE, GTASK_ACTIVITY_STATE_ACTIVE, 
01031                             -1 );
01032 
01033         g_hash_table_insert( private->task_hash,
01034                              g_strdup( task_id ),
01035                              task_iter );
01036 
01037         signal_id = GTASK_VIEW_GET_CLASS( view )->tasks_added_signal_id;
01038     } else {
01042         g_object_unref( task_iter->task );
01043         g_object_ref( task );
01044         task_iter->task = task;
01045 
01046         signal_id = GTASK_VIEW_GET_CLASS( view )->tasks_updated_signal_id;
01047     }
01048 
01049     gtask_view_update_task( view, task_iter );
01050 
01051     task_list = g_list_append( task_list, task );
01052 
01053     g_signal_emit( view, signal_id, 0, task_list );
01054 
01055     g_list_free( task_list );
01056 
01057     g_warning( "LEAVING: gtask_view_add_task" );
01058 }
01059 
01060 static void
01061 gtask_view_update_task_thumbnail( GTaskView *view, GTaskTaskIter *task_iter ) {
01062     GTaskViewPrivate   *private = view->private;
01063     GtkTreeIter        iter = task_iter->iter;
01064     GTaskGenericTask   *task = task_iter->task;
01065     GtkTreeModel       *model = GTK_TREE_MODEL( view->private->task_model );
01066 
01067     GTaskActivityState  state;
01068     const char         *old_thumb_uri;
01069     GValue              value = { 0, };
01070 
01071     GSList              *preview_list;
01072     GSList              *preview_list_tmp;
01073 
01074     g_debug( "IN: gtask_view_update_task_thumbnail" );
01075 
01076     state = gtask_generic_task_get_activity_state( task );
01077 
01078     gtk_tree_model_get_value( model, &iter, COL_OLD_THUMB_URI, &value );
01079     old_thumb_uri = g_value_get_string( &value );
01080 
01081     if( !old_thumb_uri )
01082         old_thumb_uri = "";
01083 
01084     preview_list = gtask_ui_get_task_preview_options( task );
01085 
01086     preview_list_tmp = preview_list;
01087 
01088     while( preview_list_tmp ) {
01089         GTaskPreview *preview = (GTaskPreview *) preview_list_tmp->data;
01090         GdkPixbuf    *preview_pixbuf;
01091 
01092         if( strcmp( preview->uri, old_thumb_uri ) == 0 )
01093             break;
01094 
01095                 
01096         preview_pixbuf = gtask_preview_get_pixbuf( preview,
01097                                                    private->thumbnailer );
01098 
01099         if( preview_pixbuf ) {
01100             gtk_tree_store_set( GTK_TREE_STORE( private->task_model ), &iter,
01101                                 COL_THUMBNAIL, preview_pixbuf,
01102                                 COL_OLD_THUMB_URI, preview->uri,
01103                                 COL_IS_THUMBNAIL, preview->is_thumbnail,
01104                                 -1 );
01105 
01106             g_object_unref( (GObject *) preview_pixbuf );
01107         }
01108 
01109         preview_list_tmp = g_slist_next( preview_list_tmp );
01110     }
01111 
01112     gtask_preview_list_free( preview_list );
01113 
01114     g_value_unset( &value );
01115 
01116     g_debug( "LEAVING: gtask_view_update_task_thumbnail" );
01117 }
01118 
01119 static void
01120 gtask_view_update_task( GTaskView *view, GTaskTaskIter *task_iter ) {
01121     GtkTreeIter         iter = task_iter->iter;
01122     GTaskGenericTask   *task = task_iter->task;
01123 
01124     GTaskViewPrivate   *private = view->private;
01125     GTaskActivityState  prev_activity_state;
01126     GTaskActivityState  curr_activity_state;
01127 
01128     const char         *status_msg;
01129     const char         *error_msg;
01130     const char         *title;
01131     const char         *category;
01132     const char         *thumb_uri;
01133     gfloat              percent;
01134     glong               time_left;
01135 
01136     GValue              val = { 0, };
01137 
01138     g_debug( "IN: gtask_view_update_task" );
01139 
01140     gtk_tree_model_get_value( GTK_TREE_MODEL( private->task_model ), &iter,
01141                               COL_ACTIVITY_STATE, &val );
01142 
01143     prev_activity_state = g_value_get_enum( &val );
01144 
01145     g_value_unset( &val );
01146 
01147     curr_activity_state = gtask_generic_task_get_activity_state( task );
01148 
01149     g_warning( "==========> %s : prev-%d : curr-%d", gtask_generic_task_get_title( task ), prev_activity_state, curr_activity_state );
01150 
01151     if( curr_activity_state == GTASK_ACTIVITY_STATE_COMPLETED &&
01152         prev_activity_state == GTASK_ACTIVITY_STATE_COMPLETED )
01153     {
01154         gtask_view_update_task_thumbnail( view, task_iter );
01159         g_debug( "LEAVING: gtask_view_update_task - prev status was COMPLETED" );
01160 
01161         return;
01162     }
01163 
01164     status_msg = gtask_generic_task_get_status_message( task );
01165     error_msg = gtask_generic_task_get_error_message( task );
01166 
01167     if( curr_activity_state == GTASK_ACTIVITY_STATE_INACTIVE &&
01168         prev_activity_state == GTASK_ACTIVITY_STATE_INACTIVE )
01169     {
01170         gtk_tree_store_set( private->task_model, &iter,
01171                             COL_TASK, task,
01172                             COL_STATUS_MESSAGE, status_msg,
01173                             COL_ERROR_MESSAGE, error_msg,
01174                             -1 );
01175         g_debug( "LEAVING: gtask_view_update_task - last 2 status were INACTIVE" );
01176 
01177         return;
01178     }
01179 
01180     gtask_view_update_task_thumbnail( view, task_iter );
01181 
01182     percent = gtask_generic_task_get_percent_done( task );;
01183     title = gtask_generic_task_get_title( task );
01184     category = gtask_generic_task_get_category( task );
01185     thumb_uri = gtask_generic_task_get_thumbnail_uri( task );
01186     time_left = gtask_generic_task_get_time_left( task );
01187 
01188     gtk_tree_store_set( private->task_model, &iter,
01189                         COL_TASK, task,
01190                         COL_PROGRESS, percent,
01191                         COL_TITLE, title,
01192                         COL_STATUS_MESSAGE, status_msg,
01193                         COL_CATEGORY, category,
01194                         COL_ACTIVITY_STATE, curr_activity_state,
01195                         COL_TIME_LEFT, time_left,
01196                         -1 );
01197 
01198     g_debug( "LEAVING: gtask_view_update_task - task updated" );
01199 }
01200 
01201 static gboolean
01202 remove_task( gpointer key, gpointer value, gpointer user_data ) {
01203     struct GTaskGetTaskFoo *boo = (struct GTaskGetTaskFoo *) user_data;
01204 
01205     GTaskView          *view = GTASK_VIEW( boo->view );
01206     GTaskTaskIter      *iter = (GTaskTaskIter *) value;
01207     GTaskGenericTask   *task = iter->task;
01208     GTaskActivityState  state = gtask_generic_task_get_activity_state( task );
01209     gboolean            remove = FALSE;
01210 
01211     switch( state ) {
01212         case GTASK_ACTIVITY_STATE_ACTIVE:
01213             if( boo->with_active )
01214                 remove = TRUE;
01215             break;
01216         case GTASK_ACTIVITY_STATE_INACTIVE:
01217             if( boo->with_inactive )
01218                 remove = TRUE;
01219             break;
01220         case GTASK_ACTIVITY_STATE_COMPLETED:
01221             if( boo->with_completed )
01222                 remove = TRUE;
01223             break;
01224         default:
01225             break;
01226     }
01227 
01228     if( remove ) {
01229         gtk_tree_store_remove( view->private->task_model, &(iter->iter) );
01230 
01231         g_object_ref( task );
01232 
01233         boo->tasks = g_list_append( boo->tasks, task );
01234 
01235         return TRUE;
01236     }
01237 
01238     return FALSE;
01239 }
01240 
01241 void
01242 gtask_view_clear_tasks( GTaskView *view, GTaskActivityState with_state ) {
01243     GTaskViewPrivate *private;
01244     struct GTaskGetTaskFoo boo = { 0, NULL, NULL };
01245 
01246     g_debug( "IN: gtask_view_clear_tasks" );
01247 
01248     boo.view = view;
01249     boo.with_active = ( with_state & GTASK_ACTIVITY_STATE_ACTIVE ) != 0;
01250     boo.with_inactive = ( with_state & GTASK_ACTIVITY_STATE_INACTIVE ) != 0;
01251     boo.with_completed = ( with_state & GTASK_ACTIVITY_STATE_COMPLETED ) != 0;
01252 
01253     g_return_if_fail( GTASK_IS_VIEW( view ) );
01254 
01255     private = view->private;
01256 
01257     /* clear the model, and the lookup hash
01258      * clearing the model is a side effect in remove_task() */
01259     g_hash_table_foreach_remove( private->task_hash, remove_task, &boo );
01260 
01261     g_signal_emit( view,
01262                    GTASK_VIEW_GET_CLASS( view )->tasks_removed_signal_id,
01263                    0,
01264                    boo.tasks );
01265 
01266     g_list_foreach( boo.tasks, (GFunc) g_object_unref, NULL );
01267 
01268     g_debug( "LEAVING: gtask_view_clear_tasks" );
01269 }
01270 
01271 void
01272 gtask_view_set_filter_string( GTaskView *view, const gchar *str ) {
01273     GTaskViewPrivate *private;
01274     PangoLogAttr     *attrs;
01275     char             *tmp_string;
01276     char             *norm_string;
01277     guint             word_start = 0;
01278     guint             str_len;
01279     guint             i;
01280 
01281     g_return_if_fail( GTASK_IS_VIEW( view ) );
01282     g_return_if_fail( str != NULL );
01283     g_return_if_fail( g_utf8_validate( str, -1, NULL ) );
01284 
01285     g_debug( "IN: gtask_view_set_filter_string" );
01286 
01287     private = view->private;
01288 
01289     tmp_string = g_utf8_strdown( str, -1 );
01290     norm_string = g_utf8_normalize( tmp_string, -1, G_NORMALIZE_ALL );
01291 
01292     for( i = 0; i < private->filter_seed->len; i++ ) {
01293         g_debug( "ffff" );
01294         g_free( private->filter_seed->pdata[i] );
01295     }
01296 
01297     g_ptr_array_set_size( private->filter_seed, 0 );
01298 
01299     str_len = g_utf8_strlen( norm_string, -1 );
01300     attrs = g_new0( PangoLogAttr, str_len + 1 );
01301 
01303     pango_get_log_attrs( norm_string, -1, -1, NULL, attrs, str_len + 1 );
01304 
01305     g_debug( "start splitting string" );
01306     for( i = 0; i < str_len + 1; i++ ) {
01307         char *start_word;
01308         char *end_word;
01309 
01310         if( attrs[i].is_word_end ) {
01311             char *word;
01312 
01313             start_word = g_utf8_offset_to_pointer( norm_string, word_start );
01314             end_word = g_utf8_offset_to_pointer( norm_string, i );
01315 
01316             word  = g_strndup( start_word, end_word - start_word );
01317 
01318             g_ptr_array_add( private->filter_seed, word );
01319         }
01320 
01321         if( attrs[i].is_word_start )
01322             word_start = i;
01323     }
01324     g_debug( "end splitting string" );
01325 
01326     g_string_assign( private->filter_string, str );
01327 
01328     g_free( attrs );
01329     g_free( tmp_string );
01330     g_free( norm_string );
01331 
01332 //    g_object_notify( (GObject *) view, "filter-string" );
01333 
01334     gtk_tree_model_filter_refilter( private->task_model_filter );
01335 
01336     g_debug( "LEAVING: gtask_view_set_filter_string" );
01337 }
01338 
01339 const gchar *
01340 gtask_view_get_filter_string( GTaskView *view ) {
01341     g_return_val_if_fail( GTASK_IS_VIEW( view ), "" );
01342 
01343     return view->private->filter_string->str;
01344 }
01345 
01346 static void
01347 sum_tasks( gpointer key, gpointer value, gpointer user_data ) {
01348     struct GTaskGetTaskFoo  *boo = (struct GTaskGetTaskFoo *) user_data;
01349 
01350     GTaskTaskIter *iter = (GTaskTaskIter *) value;
01351 
01352     GTaskGenericTask *task = GTASK_GENERIC_TASK( iter->task );
01353     GTaskActivityState state = gtask_generic_task_get_activity_state( task );
01354 
01355     switch( state ) {
01356         case GTASK_ACTIVITY_STATE_ACTIVE:
01357             if( boo->with_active )
01358                 boo->num++;
01359             break;
01360         case GTASK_ACTIVITY_STATE_INACTIVE:
01361             if( boo->with_inactive )
01362                 boo->num++;
01363             break;
01364         case GTASK_ACTIVITY_STATE_COMPLETED:
01365             if( boo->with_completed )
01366                 boo->num++;
01367             break;
01368         default:
01369             break;
01370     }
01371 }
01372 
01373 guint
01374 gtask_view_get_number_of_tasks( GTaskView *view,
01375                                 GTaskActivityState with_state )
01376 {
01377     struct GTaskGetTaskFoo boo = { 0, NULL, NULL, };
01378 
01379     g_debug( "IN: gtask_view_get_number_of_tasks" );
01380 
01381     boo.with_active = ( with_state & GTASK_ACTIVITY_STATE_ACTIVE ) != 0;
01382     boo.with_inactive = ( with_state & GTASK_ACTIVITY_STATE_INACTIVE ) != 0;
01383     boo.with_completed = ( with_state & GTASK_ACTIVITY_STATE_COMPLETED ) != 0;
01384 
01385     g_return_val_if_fail( GTASK_IS_VIEW( view ), 0 );
01386 
01387     g_hash_table_foreach( view->private->task_hash, sum_tasks, &boo );
01388 
01389     g_debug( "LEAVING: gtask_view_get_number_of_tasks" );
01390 
01391     return boo.num;
01392 }
01393 
01394 /* @} */

Generated on Mon Feb 2 21:33:25 2004 for libgtask-ui by doxygen 1.3.4