Documentation/Maemo 5 Developer Guide/Porting Software/Porting Existing GTK+ Application to Maemo 5

= Porting Existing GTK+ Application to Maemo 5.0 =

This section describes key aspects of the process of porting an application to the maemo platform. When starting to port an application to maemo platform, the first step is to set up the development environment. The actual porting after that is described in this section.

Introduction
Application that is used as an example for porting is Sliders, a GTK+ based game.

The Sliders interface consists of the main window with board, menu and a couple of dialogs. See source mentioned above for game history and description.

Autotools Usage
Sliders doesn't use GNU autotools originally, so we need to add `configure.ac', `Makefile.am' and `autogen.sh' for simplicity. See GNU Build System for corresponding information.

User Interface Changes
Sliders game is not designed for usage in mobile devices, so we need to hildonize it in order to build effective touch interface for this simple game.

Hildonizing Main View
Before using Hildon we need to initialize it. maemo-sliders/sliders.c

  /* Initialize the GTK+ and hildon libraries */   hildon_gtk_init  (&amp; argc ,  &amp; argv ); 

After that we can create main window with all necessary content. maemo-sliders/sliders.c

  static  GtkWidget  *  create_main_window  (  void  ) { GtkWidget <font color="#990000"> * main_window <font color="#990000"> ;  <font color="#9A1900">/* Create the main window */  main_window <font color="#990000"> =  <font color="#000000">hildon_stackable_window_new   <font color="#990000">;  <font color="#000000">gtk_window_set_title  <font color="#990000">(   <font color="#000000">GTK_WINDOW   <font color="#990000">( main_window <font color="#990000">),  <font color="#FF0000">"Welcome to Sliders"  <font color="#990000">);  <font color="#9A1900">/* Create and set application menu */  HildonAppMenu <font color="#990000"> * menu <font color="#990000"> =  <font color="#000000">create_menu   <font color="#990000">;  <font color="#000000">hildon_stackable_window_set_main_menu  <font color="#990000">(   <font color="#000000">HILDON_STACKABLE_WINDOW   <font color="#990000">( main_window <font color="#990000">), menu <font color="#990000">);  <font color="#9A1900">/* Create and pack table, that contains sliders */  appdata <font color="#990000">. table <font color="#990000"> =  <font color="#000000">create_table   <font color="#990000">;  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( main_window <font color="#990000">), appdata <font color="#990000">. table <font color="#990000">);  <font color="#9A1900">/* Exit from gtk_main on "delete_event" */   <font color="#000000">g_signal_connect  <font color="#990000">(( gpointer <font color="#990000">) main_window <font color="#990000">,  <font color="#FF0000">"delete_event"  <font color="#990000">,   <font color="#000000">G_CALLBACK   <font color="#990000">( gtk_main_quit <font color="#990000">), NULL <font color="#990000">);  <font color="#0000FF">return  main_window <font color="#990000"> ; <font color="#FF0000">} </tt>

We have replaced original Sliders menu and toolbar with hildon application menu.

maemo-sliders/sliders.c

  <font color="#0000FF">static  HildonAppMenu <font color="#990000"> *  <font color="#000000">create_menu  <font color="#990000">(  <font color="#009900">void  <font color="#990000">) <font color="#FF0000">{  <font color="#9A1900">/*   <font color="#9A1900">  * Create menu buttons one by one, connect to appropriate callbacks and  '' <font color="#9A1900">  * add to the menu.   <font color="#9A1900">   */ '' HildonSizeType button_size <font color="#990000"> = HILDON_SIZE_FINGER_HEIGHT <font color="#990000"> | HILDON_SIZE_AUTO_WIDTH <font color="#990000"> ; HildonAppMenu <font color="#990000"> * menu <font color="#990000"> =  <font color="#000000">HILDON_APP_MENU   <font color="#990000">(   <font color="#000000">hildon_app_menu_new   <font color="#990000">); GtkButton <font color="#990000"> * button <font color="#990000"> ; button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( button_size <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( button <font color="#990000">,  <font color="#FF0000">"New"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( button <font color="#990000">),  <font color="#FF0000">"clicked"  <font color="#990000">,         <font color="#000000">G_CALLBACK   <font color="#990000">( on_new_clicked <font color="#990000">), NULL <font color="#990000">);  <font color="#000000">hildon_app_menu_append  <font color="#990000">( menu <font color="#990000">,   <font color="#000000">GTK_BUTTON   <font color="#990000">( button <font color="#990000">)); button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( button_size <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( button <font color="#990000">,  <font color="#FF0000">"Scores"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( button <font color="#990000">),  <font color="#FF0000">"clicked"  <font color="#990000">,         <font color="#000000">G_CALLBACK   <font color="#990000">( on_scores_clicked <font color="#990000">), NULL <font color="#990000">);  <font color="#000000">hildon_app_menu_append  <font color="#990000">( menu <font color="#990000">,   <font color="#000000">GTK_BUTTON   <font color="#990000">( button <font color="#990000">)); button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( button_size <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( button <font color="#990000">,  <font color="#FF0000">"Open"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( button <font color="#990000">),  <font color="#FF0000">"clicked"  <font color="#990000">,         <font color="#000000">G_CALLBACK   <font color="#990000">( on_open_clicked <font color="#990000">), NULL <font color="#990000">);  <font color="#000000">hildon_app_menu_append  <font color="#990000">( menu <font color="#990000">,   <font color="#000000">GTK_BUTTON   <font color="#990000">( button <font color="#990000">)); button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( button_size <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( button <font color="#990000">,  <font color="#FF0000">"Save"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( button <font color="#990000">),  <font color="#FF0000">"clicked"  <font color="#990000">,         <font color="#000000">G_CALLBACK   <font color="#990000">( on_save_clicked <font color="#990000">), NULL <font color="#990000">);  <font color="#000000">hildon_app_menu_append  <font color="#990000">( menu <font color="#990000">,   <font color="#000000">GTK_BUTTON   <font color="#990000">( button <font color="#990000">)); button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( button_size <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( button <font color="#990000">,  <font color="#FF0000">"About"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( button <font color="#990000">),  <font color="#FF0000">"clicked"  <font color="#990000">,         <font color="#000000">G_CALLBACK   <font color="#990000">( on_about_clicked <font color="#990000">), NULL <font color="#990000">);  <font color="#000000">hildon_app_menu_append  <font color="#990000">( menu <font color="#990000">,   <font color="#000000">GTK_BUTTON   <font color="#990000">( button <font color="#990000">));  <font color="#0000FF">return  menu <font color="#990000"> ; <font color="#FF0000">} </tt>

Sliders table buttons [localhost#fig:maemo-sliders_table 16.14] are maximized and wrapped with `hildon_gtk_button_new '. maemo-sliders/sliders.c

  <font color="#0000FF">static  GtkWidget <font color="#990000"> *  <font color="#000000">create_table  <font color="#990000">(  <font color="#009900">void  <font color="#990000">) <font color="#FF0000">{ GtkWidget <font color="#990000"> * table <font color="#990000"> ; gint x <font color="#990000">, y <font color="#990000">, c <font color="#990000"> = <font color="#993399">0  <font color="#990000"> ; appdata <font color="#990000">. vacant_pos <font color="#990000"> = SLIDERS_NUMBER <font color="#990000"> ; appdata <font color="#990000">. move_no <font color="#990000"> = <font color="#993399">0  <font color="#990000"> ; HildonSizeType button_size <font color="#990000"> = HILDON_SIZE_FINGER_HEIGHT <font color="#990000"> | HILDON_SIZE_AUTO_WIDTH <font color="#990000"> ;  <font color="#9A1900">/* Create table for sliders */  table <font color="#990000"> =  <font color="#000000">gtk_table_new   <font color="#990000">(  <font color="#993399">4  <font color="#990000">,  <font color="#993399">4  <font color="#990000">, FALSE <font color="#990000">);  <font color="#9A1900">/*  '' <font color="#9A1900">  * Create buttons, that represents sliders. Set "current_pos" key for each button '' '' <font color="#9A1900">  * and connect each button to appropriate callback.   <font color="#9A1900">   */ ''  <font color="#0000FF">for  <font color="#990000">( x <font color="#990000"> =  <font color="#993399">0  <font color="#990000"> ; x <font color="#990000">&lt; SLIDERS_NUMBER <font color="#990000"> ; x <font color="#990000">++) <font color="#FF0000">{ gchar <font color="#990000"> * temp <font color="#990000"> =  <font color="#000000">g_strdup_printf   <font color="#990000">(  <font color="#FF0000">"%i"  <font color="#990000">, x <font color="#990000">+  <font color="#993399">1  <font color="#990000">); appdata <font color="#990000">. buttons <font color="#990000">[ x <font color="#990000">] <font color="#990000"> =   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( button_size <font color="#990000">);  <font color="#000000">gtk_button_set_label  <font color="#990000">(   <font color="#000000">GTK_BUTTON   <font color="#990000">( appdata <font color="#990000">. buttons <font color="#990000">[ x <font color="#990000">]), temp <font color="#990000">);  <font color="#000000">g_object_set_data  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( appdata <font color="#990000">. buttons <font color="#990000">[ x <font color="#990000">]), <font color="#FF0000">"current_pos"  <font color="#990000">,  <font color="#990000">( gpointer <font color="#990000">) x <font color="#990000">);  <font color="#000000">g_free  <font color="#990000">( temp <font color="#990000">);  <font color="#000000">gtk_signal_connect  <font color="#990000">(   <font color="#000000">GTK_OBJECT   <font color="#990000">( appdata <font color="#990000">. buttons <font color="#990000">[ x <font color="#990000">]), <font color="#FF0000">"clicked"  <font color="#990000">,   <font color="#000000">GTK_SIGNAL_FUNC   <font color="#990000">( on_button_clicked <font color="#990000">), NULL <font color="#990000">); <font color="#FF0000">}  <font color="#9A1900">/* Add sliders to table */   <font color="#0000FF">for  <font color="#990000">( x <font color="#990000"> =  <font color="#993399">0  <font color="#990000"> ; x <font color="#990000">&lt;  <font color="#993399">4  <font color="#990000"> ; x <font color="#990000">++)  <font color="#0000FF">for  <font color="#990000">( y <font color="#990000"> =  <font color="#993399">0  <font color="#990000"> ; y <font color="#990000">&lt;  <font color="#993399">4  <font color="#990000"> ; y <font color="#990000">++)  <font color="#0000FF">if  <font color="#990000">(!( x <font color="#990000"> ==  <font color="#993399">3  <font color="#990000">&amp;&amp; y <font color="#990000"> ==  <font color="#993399">3  <font color="#990000">))  <font color="#000000">gtk_table_attach_defaults  <font color="#990000">(   <font color="#000000">GTK_TABLE   <font color="#990000">( table <font color="#990000">), appdata <font color="#990000">. buttons <font color="#990000">[ c <font color="#990000">++], y <font color="#990000">, y <font color="#990000">+  <font color="#993399">1  <font color="#990000">, x <font color="#990000">, x <font color="#990000">+  <font color="#993399">1  <font color="#990000">);  <font color="#0000FF">return  table <font color="#990000"> ; <font color="#FF0000">} </tt>

Implementing Scores Window
We have replaced original Sliders win picture by scores window [localhost#fig:maemo-sliders_table 16.14], that appears in two cases. It's shown after ``Scores'' menu button clicked maemo-sliders/sliders.c

  <font color="#0000FF">static  <font color="#009900">void  <font color="#000000">on_scores_clicked  <font color="#990000">( GtkMenuItem <font color="#990000"> * menuitem <font color="#990000">, gpointer user_data <font color="#990000">) <font color="#FF0000">{  <font color="#000000">scores_window  <font color="#990000">(  <font color="#993399">0  <font color="#990000">); <font color="#FF0000">} </tt>

and when player has won. maemo-sliders/sliders.c

  <font color="#0000FF">static  <font color="#009900">void  <font color="#000000">on_button_clicked  <font color="#990000">( GtkWidget <font color="#990000"> * button <font color="#990000">, gpointer user_data <font color="#990000">) <font color="#FF0000">{ '' <font color="#9A1900">/* ... */ ''      <font color="#0000FF">if   <font color="#990000">(   <font color="#000000">has_player_won   <font color="#990000">  <font color="#990000">) <font color="#FF0000">{  <font color="#000000">scores_window  <font color="#990000">(  <font color="#993399">1  <font color="#990000">);  <font color="#000000">gtk_window_set_title  <font color="#990000">(   <font color="#000000">GTK_WINDOW   <font color="#990000">( appdata <font color="#990000">. main_window <font color="#990000">), <font color="#FF0000">"Welcome to Sliders"  <font color="#990000">); appdata <font color="#990000">. move_no <font color="#990000"> = <font color="#993399">0  <font color="#990000"> ; <font color="#FF0000">}  <font color="#0000FF">else  <font color="#FF0000">{ gchar <font color="#990000"> * temp <font color="#990000"> =  <font color="#000000">g_strdup_printf   <font color="#990000">(  <font color="#FF0000">"Move no.: %i"  <font color="#990000">, appdata <font color="#990000">. move_no <font color="#990000">);  <font color="#000000">gtk_window_set_title  <font color="#990000">(   <font color="#000000">GTK_WINDOW   <font color="#990000">( appdata <font color="#990000">. main_window <font color="#990000">), temp <font color="#990000">);  <font color="#000000">g_free  <font color="#990000">( temp <font color="#990000">); <font color="#FF0000">} '' <font color="#9A1900">/* ... */ '' <font color="#FF0000">} </tt>

Scores window contains pannable area with tree view maemo-sliders/sliders.c

  <font color="#9A1900">/* Create a tree view that represents scores table and an area for it */  area <font color="#990000"> =  <font color="#000000">hildon_pannable_area_new   <font color="#990000">; tree_view <font color="#990000"> =  <font color="#000000">create_treeview   <font color="#990000">( HILDON_UI_MODE_EDIT <font color="#990000">); '' <font color="#9A1900">/* ... */     <font color="#9A1900">/* Pack tree view */ ''  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( area <font color="#990000">), tree_view <font color="#990000">);  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( window <font color="#990000">), area <font color="#990000">); </tt>

and edit toolbar. maemo-sliders/sliders.c

  <font color="#9A1900">/* Create a new edit toolbar */  toolbar <font color="#990000"> =  <font color="#000000">hildon_edit_toolbar_new_with_text   <font color="#990000">(  <font color="#FF0000">"Choose scores to delete"  <font color="#990000">,                                                 <font color="#FF0000">"Delete"  <font color="#990000">); '' <font color="#9A1900">/* ... */     <font color="#9A1900">/* Add toolbar to the window */ ''  <font color="#000000">hildon_window_set_edit_toolbar  <font color="#990000">(   <font color="#000000">HILDON_WINDOW   <font color="#990000">( window <font color="#990000">),                                     <font color="#000000">HILDON_EDIT_TOOLBAR   <font color="#990000">( toolbar <font color="#990000">)); '' <font color="#9A1900">/* ... */     <font color="#9A1900">/* Set callback for "Delete" button */ ''  <font color="#000000">g_signal_connect  <font color="#990000">( toolbar <font color="#990000">,  <font color="#FF0000">"button-clicked"  <font color="#990000">,                       <font color="#000000">G_CALLBACK   <font color="#990000">( delete_selected_scores <font color="#990000">),                      tree_view <font color="#990000">);  <font color="#9A1900">/* Destroy scores window when upper corner arrow clicked */   <font color="#000000">g_signal_connect_swapped  <font color="#990000">( toolbar <font color="#990000">,  <font color="#FF0000">"arrow-clicked"  <font color="#990000">,                               <font color="#000000">G_CALLBACK   <font color="#990000">( gtk_widget_destroy <font color="#990000">),                              window <font color="#990000">); </tt>

Win banner is shown if `scores_window ' called in case player has won. maemo-sliders/sliders.c

  <font color="#9A1900">/* Additional actions for case, when player has won */   <font color="#0000FF">if  <font color="#990000">( win <font color="#990000">) <font color="#FF0000">{  <font color="#9A1900">/* Show appropriate banner */   <font color="#000000">hildon_banner_show_informationf  <font color="#990000">( window <font color="#990000">, NULL <font color="#990000">,  <font color="#FF0000">"Win! Score: %i"  <font color="#990000">, appdata <font color="#990000">. move_no <font color="#990000">); '' <font color="#9A1900">/* ... */ ''   <font color="#FF0000">} </tt>

Other scores related code is quite straightforward and doesn't use Hildon specific features, see `scores_window ' implementation for details.

State Saving
Maemo supports state saving feature, that we have used for current Sliders game saving. The application can later open this game with the same state as before. This section describes most important steps needed to make Sliders support state savings.

`state_save ' is called when user presses menu's ``Save'' button. Saving data should be updated before it's called. maemo-sliders/sliders.c

  <font color="#0000FF">static  <font color="#009900">void  <font color="#000000">on_save_clicked  <font color="#990000">( GtkMenuItem <font color="#990000"> * menuitem <font color="#990000">, gpointer user_data <font color="#990000">) <font color="#FF0000">{  <font color="#9A1900">/* Save moves number, vacant position and board layout to "state" */  state <font color="#990000">. move_no <font color="#990000"> = appdata <font color="#990000">. move_no <font color="#990000"> ; state <font color="#990000">. vacant_pos <font color="#990000"> = appdata <font color="#990000">. vacant_pos <font color="#990000"> ; <font color="#009900">int i <font color="#990000"> ;  <font color="#0000FF">for  <font color="#990000">( i <font color="#990000"> =  <font color="#993399">0  <font color="#990000"> ; i <font color="#990000">&lt; SLIDERS_NUMBER <font color="#990000"> ; i <font color="#990000">++) state <font color="#990000">. map <font color="#990000">[ i <font color="#990000">] <font color="#990000"> =  <font color="#990000">( gint <font color="#990000">)   <font color="#000000">gtk_object_get_data   <font color="#990000">(   <font color="#000000">GTK_OBJECT   <font color="#990000">( appdata <font color="#990000">. buttons <font color="#990000">[ i <font color="#990000">]), <font color="#FF0000">"current_pos"  <font color="#990000">);  <font color="#9A1900">/* Call state saving method and process return value */   <font color="#0000FF">if  <font color="#990000">(   <font color="#000000">state_save   <font color="#990000">)  <font color="#000000">hildon_banner_show_information  <font color="#990000">( appdata <font color="#990000">. main_window <font color="#990000">, NULL <font color="#990000">,  <font color="#FF0000">"Saved current game"  <font color="#990000">);  <font color="#0000FF">else   <font color="#000000">hildon_banner_show_information   <font color="#990000">( appdata <font color="#990000">. main_window <font color="#990000">, NULL <font color="#990000">,  <font color="#FF0000">"Can't save current game"  <font color="#990000">); <font color="#FF0000">} </tt>

Then `osso_state_write ' can be called for correct data. maemo-sliders/sliders.c

  <font color="#000000">state_save  <font color="#990000">(  <font color="#009900">void  <font color="#990000">) <font color="#FF0000">{ osso_state_t osso_state <font color="#990000"> ; osso_return_t ret <font color="#990000"> ; osso_state <font color="#990000">. state_size <font color="#990000"> =  <font color="#0000FF">sizeof   <font color="#990000">( StateData <font color="#990000">); osso_state <font color="#990000">. state_data <font color="#990000"> = <font color="#990000">&amp; state <font color="#990000"> ; ret <font color="#990000"> =  <font color="#000000">osso_state_write   <font color="#990000">( appdata <font color="#990000">. osso_context <font color="#990000">,  <font color="#990000">&amp; osso_state <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( ret <font color="#990000"> != OSSO_OK <font color="#990000">)  <font color="#0000FF">return  FALSE <font color="#990000"> ;  <font color="#0000FF">return  TRUE <font color="#990000"> ; <font color="#FF0000">} </tt>

`state_load ' is called when user clicks ``Open'' menu button. It uses `osso_state_read ' symmetric to `state_save '. maemo-sliders/sliders.c

  <font color="#000000">state_load  <font color="#990000">(  <font color="#009900">void  <font color="#990000">) <font color="#FF0000">{ osso_state_t osso_state <font color="#990000"> ; osso_return_t ret <font color="#990000"> ; osso_state <font color="#990000">. state_size <font color="#990000"> =  <font color="#0000FF">sizeof   <font color="#990000">( StateData <font color="#990000">); osso_state <font color="#990000">. state_data <font color="#990000"> = <font color="#990000">&amp; state <font color="#990000"> ; ret <font color="#990000"> =  <font color="#000000">osso_state_read   <font color="#990000">( appdata <font color="#990000">. osso_context <font color="#990000">,  <font color="#990000">&amp; osso_state <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( ret <font color="#990000"> != OSSO_OK <font color="#990000">)  <font color="#0000FF">return  FALSE <font color="#990000"> ;  <font color="#0000FF">return  TRUE <font color="#990000"> ; <font color="#FF0000">} </tt>

Don't forget to initialize the library context before state saving usage. maemo-sliders/sliders.c

  <font color="#9A1900">/* Initialize maemo application */  appdata <font color="#990000">. osso_context <font color="#990000"> =  <font color="#000000">osso_initialize   <font color="#990000">( OSSO_SERVICE <font color="#990000">, VERSION <font color="#990000">, TRUE <font color="#990000">, NULL <font color="#990000">); </tt>

The information saved by using state saving functions does not survive over power off of the device, so if you need to save some data more permanent you could use e.g. libxml as shown in next section for scores table.

Scores Saving
Scores data store is created, when `get_scores_store ' called first. The store is populated from file saved under user's home directory. Document tree is parsed with node pointer starting from root element. maemo-sliders/sliders.c

  <font color="#0000FF">static  GtkListStore <font color="#990000"> *  <font color="#000000">get_scores_store  <font color="#990000">(  <font color="#009900">void  <font color="#990000">) <font color="#FF0000">{  <font color="#0000FF">static  GtkListStore <font color="#990000"> * store <font color="#990000"> = NULL <font color="#990000"> ;  <font color="#9A1900">/* Return store if it has been created before */   <font color="#0000FF">if  <font color="#990000">( store <font color="#990000"> != NULL <font color="#990000">)  <font color="#0000FF">return  store <font color="#990000"> ;  <font color="#9A1900">/* Create store with 2 columns of specified types */  store <font color="#990000"> =  <font color="#000000">gtk_list_store_new   <font color="#990000">( N_COLUMNS <font color="#990000">, G_TYPE_STRING <font color="#990000">, G_TYPE_INT <font color="#990000">); xmlDocPtr doc <font color="#990000"> ;  <font color="#9A1900">/* the resulting document tree */  xmlNodePtr cur <font color="#990000"> ;  <font color="#9A1900">/* node pointer */  xmlChar <font color="#990000"> * attribute <font color="#990000"> ;  <font color="#9A1900">/* node attribute name */  <font color="#009900">char <font color="#990000"> * row_name <font color="#990000">,  <font color="#990000"> * temp <font color="#990000"> ; gint row_score <font color="#990000"> ;  <font color="#9A1900">/* Parse an XML file from the filesystem */  <font color="#009900">char <font color="#990000"> * slidersdir <font color="#990000"> =   <font color="#000000">g_strdup_printf   <font color="#990000">(  <font color="#FF0000">"%s%s%s"  <font color="#990000">,   <font color="#000000">getenv   <font color="#990000">(  <font color="#FF0000">"HOME"  <font color="#990000">), SLIDERS_DIR <font color="#990000">, SCORES_XML <font color="#990000">); doc <font color="#990000"> =  <font color="#000000">xmlReadFile   <font color="#990000">( slidersdir <font color="#990000">, NULL <font color="#990000">, XML_PARSE_NOERROR <font color="#990000">);  <font color="#000000">g_free  <font color="#990000">( slidersdir <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( doc <font color="#990000"> == NULL <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: Failed to parse document %s  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">, SCORES_XML <font color="#990000">);  <font color="#0000FF">return  store <font color="#990000"> ; <font color="#FF0000">}  <font color="#9A1900">/* Parse root element */  cur <font color="#990000"> =  <font color="#000000">xmlDocGetRootElement   <font color="#990000">( doc <font color="#990000">);   <font color="#9A1900">//scores   <font color="#0000FF">if  <font color="#990000">( cur <font color="#990000"> == NULL <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: Empty xml doc  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">);  <font color="#000000">xmlFreeDoc  <font color="#990000">( doc <font color="#990000">);  <font color="#0000FF">return  store <font color="#990000"> ; <font color="#FF0000">}  <font color="#9A1900">/* Parse first row tag */  cur <font color="#990000"> = cur <font color="#990000">-&gt; xmlChildrenNode <font color="#990000"> ;  <font color="#0000FF">if  <font color="#990000">( cur <font color="#990000"> == NULL <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: No row tag  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">);  <font color="#000000">xmlFreeDoc  <font color="#990000">( doc <font color="#990000">);  <font color="#0000FF">return  store <font color="#990000"> ; <font color="#FF0000">}  <font color="#9A1900">/* Parse row tags one by one */   <font color="#0000FF">while  <font color="#990000">( cur <font color="#990000"> != NULL <font color="#990000">) <font color="#FF0000">{ '' <font color="#9A1900">/* ... */       <font color="#9A1900">/* Add new row to the store */ ''  <font color="#000000">gtk_list_store_insert_with_values  <font color="#990000">( store <font color="#990000">, NULL <font color="#990000">,   <font color="#000000">gtk_tree_model_iter_n_children   <font color="#990000">(   <font color="#000000">GTK_TREE_MODEL   <font color="#990000">( store <font color="#990000">), NULL <font color="#990000">),  <font color="#993399">0  <font color="#990000">, row_name <font color="#990000">,  <font color="#993399">1  <font color="#990000">, row_score <font color="#990000">,  <font color="#990000">-  <font color="#993399">1  <font color="#990000">);  <font color="#9A1900">/* Parse next row element */   <font color="#000000">g_free  <font color="#990000">( row_name <font color="#990000">); cur <font color="#990000"> = cur <font color="#990000">-&gt; next <font color="#990000"> ; <font color="#FF0000">}  <font color="#9A1900">/* Free the resulting tree */   <font color="#000000">xmlFreeDoc  <font color="#990000">( doc <font color="#990000">);  <font color="#0000FF">return  store <font color="#990000"> ; <font color="#FF0000">} </tt>

'scores_xml_save ' is called before application quits. It uses xml text writer in order to save current data store to appropriate file. maemo-sliders/sliders.c

  <font color="#0000FF">static  <font color="#009900">void  <font color="#000000">scores_xml_save  <font color="#990000">(   <font color="#0000FF">const   <font color="#009900">char  <font color="#990000"> * uri <font color="#990000">) <font color="#FF0000">{ <font color="#009900">int rc <font color="#990000"> ; xmlTextWriterPtr writer <font color="#990000"> ;  <font color="#9A1900">/* Check if store have been created */  GtkListStore <font color="#990000"> * store <font color="#990000"> =  <font color="#000000">get_scores_store   <font color="#990000">;  <font color="#0000FF">if  <font color="#990000">(! store <font color="#990000">)   <font color="#0000FF">return   <font color="#990000"> ; '' <font color="#9A1900">/* Create a new XmlWriter for uri, with no compression. */ ''   writer <font color="#990000"> =   <font color="#000000">xmlNewTextWriterFilename   <font color="#990000">( uri <font color="#990000">,  <font color="#993399">0  <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( writer <font color="#990000"> == NULL <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: Error creating the xml writer for %s  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">, SCORES_XML <font color="#990000">);  <font color="#0000FF">return  <font color="#990000"> ; <font color="#FF0000">}  <font color="#9A1900">/* Start the document with the xml default for the version,   <font color="#9A1900">  * encoding UTF-8 and the default for the standalone  '' <font color="#9A1900">  * declaration. */ ''   rc <font color="#990000"> =   <font color="#000000">xmlTextWriterStartDocument   <font color="#990000">( writer <font color="#990000">, NULL <font color="#990000">,  <font color="#FF0000">"UTF-8"  <font color="#990000">, NULL <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( rc <font color="#990000">&lt;  <font color="#993399">0  <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: Error at xmlTextWriterStartDocument  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">);  <font color="#0000FF">return  <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* Start an element named ROOT_ELEMENT. Since thist is the first '' '' <font color="#9A1900">  * element, this will be the root element of the document. */ ''   rc <font color="#990000"> =   <font color="#000000">xmlTextWriterStartElement   <font color="#990000">( writer <font color="#990000">, BAD_CAST ROOT_ELEMENT <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( rc <font color="#990000">&lt;  <font color="#993399">0  <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: Error at xmlTextWriterStartElement  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">);  <font color="#0000FF">return  <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* Save each score row from store. */ ''    <font color="#000000">gtk_tree_model_foreach   <font color="#990000">(   <font color="#000000">GTK_TREE_MODEL   <font color="#990000">( store <font color="#990000">), scores_xml_save_score <font color="#990000">,  <font color="#990000">&amp; writer <font color="#990000">);  <font color="#9A1900">/* Here we could close the element named ROOT_ELEMENT using the   <font color="#9A1900">  * function xmlTextWriterEndElement, but since we do not want to   <font color="#9A1900">  * write any other elements, we simply call xmlTextWriterEndDocument,  '' <font color="#9A1900">  * which will do all the work. */ ''   rc <font color="#990000"> =   <font color="#000000">xmlTextWriterEndDocument   <font color="#990000">( writer <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( rc <font color="#990000">&lt;  <font color="#993399">0  <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"%s, %i: Error at xmlTextWriterEndDocument  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, __PRETTY_FUNCTION__ <font color="#990000">, __LINE__ <font color="#990000">); <font color="#FF0000">}  <font color="#000000">xmlFreeTextWriter  <font color="#990000">( writer <font color="#990000">); <font color="#FF0000">} </tt>

Integration to Menu
Application integration to menu needs .desktop file. This section describes the needed additions and changes.

Sliders doesn't have appropriate .desktop file, so we need to generate it from `maemo-sliders.desktop.in' with `configure' script. maemo-sliders.desktop.in

Application Packaging
`dh_make' tool have been used for Sliders debianization, [TODO: link to info on creating debian packages]