Documentation/Maemo 5 Developer Guide/Porting Software/Porting MaemoPad
(categorise) |
m (Reverted edits by 221.194.132.212 (Talk); changed back to last version by Amigadave) |
||
(5 intermediate revisions not shown) | |||
Line 1: | Line 1: | ||
- | + | This is a practical example of porting a [[Open development/Maemo roadmap/Diablo|Diablo]] (Maemo 4.1) application to [[Open development/Maemo roadmap/Fremantle|Fremantle]] (Maemo 5). The example application, MaemoPad, is a simple Notepad-like editor. | |
- | + | [[Image:maemopad.png|frame|center|alt=Screenshot of MaemoPad|MaemoPad main window]] | |
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
+ | == Porting MaemoPad from Diablo to Fremantle == | ||
Porting from Diablo to Fremantle involved mostly changes in GTK+- and Hildon-specific parts of the code, because newer versions of these libraries are now in use, and because of the new Fremantle GUI guidelines. This subsection will first explain how to install MaemoPad, and then proceeds to describing the main changes in the code. The reader is recommended to familiarize with chapters [[Documentation/Maemo 5 Developer Guide/Application Development|Application Development]] and [[Documentation/Maemo 5 Developer Guide/Human Interface Guidelines|Human Interface Guidelines]] before this one. For reference, see GTK+ and Hildon APIs from [http://maemo.org/development/sdks/maemo_5_api_documentation/ Maemo Fremantle APIs]. | Porting from Diablo to Fremantle involved mostly changes in GTK+- and Hildon-specific parts of the code, because newer versions of these libraries are now in use, and because of the new Fremantle GUI guidelines. This subsection will first explain how to install MaemoPad, and then proceeds to describing the main changes in the code. The reader is recommended to familiarize with chapters [[Documentation/Maemo 5 Developer Guide/Application Development|Application Development]] and [[Documentation/Maemo 5 Developer Guide/Human Interface Guidelines|Human Interface Guidelines]] before this one. For reference, see GTK+ and Hildon APIs from [http://maemo.org/development/sdks/maemo_5_api_documentation/ Maemo Fremantle APIs]. | ||
Line 19: | Line 10: | ||
=== Installing MaemoPad === | === Installing MaemoPad === | ||
- | MaemoPad can be installed and tested in the | + | MaemoPad can be installed and tested in the Scratchbox environment. |
* If not already activated, activate the X86 target, go to the testing directory, and download the source package of maemopad application. | * If not already activated, activate the X86 target, go to the testing directory, and download the source package of maemopad application. | ||
- | + | <pre> | |
- | + | [sbox-FREMANTLE_ARMEL] > sb-conf select FREMANTLE_X86 | |
- | + | [sbox-FREMANTLE_X86 ~] > mkdir maemopad | |
- | + | [sbox-FREMANTLE_X86 ~/maemopad] > cd maemopad | |
- | + | [sbox-FREMANTLE_X86 ~/maemopad] > apt-get source maemopad | |
+ | ...apt output... | ||
+ | </pre> | ||
* Check that you have the correct files. | * Check that you have the correct files. | ||
- | + | ||
- | + | <pre> | |
- | + | [sbox-FREMANTLE_X86: ~/maemopad] > ls -l | |
- | + | total 352 | |
- | + | drwxrwxr-x 6 maemo maemo 4096 Jul 28 14:09 maemopad-2.5 | |
- | + | -rw-rw-r-- 1 maemo maemo 465 Jul 6 16:02 maemopad_2.5.dsc | |
+ | -rw-rw-r-- 1 maemo maemo 346129 Jul 6 16:02 maemopad_2.5.tar.gz | ||
+ | </pre> | ||
* Go to the <code>maemopad-2.5</code> source directory, and build the maemopad package with <code>dpkg-buildpackage</code> command as shown here: | * Go to the <code>maemopad-2.5</code> source directory, and build the maemopad package with <code>dpkg-buildpackage</code> command as shown here: | ||
- | + | ||
- | + | <pre> | |
- | + | [sbox-FREMANTLE_X86: ~/maemopad] > cd maemopad-2.5 | |
- | + | [sbox-FREMANTLE_X86: ~/maemopad/maemopad-2.5] > dpkg-buildpackage -rfakeroot | |
- | + | dpkg-buildpackage: source package is maemopad | |
- | + | dpkg-buildpackage: source version is 2.5 | |
- | + | dpkg-buildpackage: source changed by Soumya Bijjal <soumya.3.bijjal@nokia.com> | |
- | + | dpkg-buildpackage: host architecture i386 | |
- | + | dpkg-buildpackage: source version without epoch 2.3 | |
+ | .... etc .... | ||
+ | </pre> | ||
* Install the newly compiled <code>maemopad_2.5_i386.deb</code> file inside the Scratchbox environment: | * Install the newly compiled <code>maemopad_2.5_i386.deb</code> file inside the Scratchbox environment: | ||
- | + | ||
- | + | <pre> | |
- | + | [sbox-FREMANTLE_X86: ~/maemopad] > dpkg -i maemopad_2.5_i386.deb | |
+ | ... output from dpkg ... | ||
+ | </pre> | ||
* Make sure you have the SDK UI running in Xephyr. | * Make sure you have the SDK UI running in Xephyr. | ||
Line 58: | Line 57: | ||
The MaemoPad source code resides in folder <code>maemopad-2.5/src:</code> | The MaemoPad source code resides in folder <code>maemopad-2.5/src:</code> | ||
- | + | <pre> | |
- | + | [sbox-FREMANTLE_X86: ~/maemopad] ls maemopad-2.5/src | |
- | + | total 280 | |
- | + | -rw-rw-r-- 1 maemo maemo 25491 Jul 28 15:45 Makefile | |
- | + | -rw-rw-r-- 1 maemo maemo 491 Jul 28 14:09 Makefile.am | |
- | + | -rw-rw-r-- 1 maemo maemo 23238 Jul 28 14:09 Makefile.in | |
- | + | -rwxrwxr-x 1 maemo maemo 83433 Jul 28 15:45 maemopad | |
- | + | -rw-rw-r-- 1 maemo maemo 82928 Jul 28 15:45 maemopad-maemopad-window.o | |
- | + | -rw-rw-r-- 1 maemo maemo 18564 Jul 28 15:45 maemopad-main.o | |
- | + | -rw-rw-r-- 1 maemo maemo 20400 Jul 28 14:09 maemopad-window.c | |
- | + | -rw-rw-r-- 1 maemo maemo 2391 Jul 28 14:09 maemopad-window.h | |
+ | -rw-rw-r-- 1 maemo maemo 2193 Jul 28 14:09 main.c | ||
+ | </pre> | ||
For comparison, the Diablo version of MaemoPad can also be examined: | For comparison, the Diablo version of MaemoPad can also be examined: | ||
- | + | <pre> | |
- | + | [sbox-FREMANTLE_X86: ~/maemopad] > svn export https://vcs.maemo.org/svn/\ | |
- | + | maemoexamples/tags/maemo_4.1/maemopad diablo_maemopad | |
- | + | [sbox-FREMANTLE_X86: ~/src] ls -lR diablo_maemopad/src | |
- | + | diablo_maemopad/src/: | |
- | + | total 16 | |
- | + | -rw-rw-r-- 1 maemo maemo 537 May 15 2008 Makefile.am | |
- | + | -rw-rw-r-- 1 maemo maemo 557 May 15 2008 appdata.h | |
- | + | -rw-rw-r-- 1 maemo maemo 2789 Dec 3 2008 main.c | |
- | + | drwxrwxr-x 2 maemo maemo 4096 Aug 20 11:53 ui | |
- | + | ||
- | + | diablo_maemopad/src/ui: | |
- | + | total 36 | |
- | + | -rw-rw-r-- 1 maemo maemo 12163 Dec 3 2008 callbacks.c | |
- | + | -rw-rw-r-- 1 maemo maemo 1682 Oct 29 2008 callbacks.h | |
- | + | -rw-rw-r-- 1 maemo maemo 14982 Dec 3 2008 interface.c | |
+ | -rw-rw-r-- 1 maemo maemo 2695 Dec 3 2008 interface.h | ||
+ | </pre> | ||
=== Code reorganization === | === Code reorganization === | ||
Line 103: | Line 106: | ||
maemopad-window.c | maemopad-window.c | ||
- | + | <source lang="c"> | |
- | + | #include <gdk/gdkkeysyms.h> | |
+ | </source> | ||
to include GDK definition for key "f", <code>GDK_f</code> to replace the earlier <code>HILDON_HARDKEY_FULLSCREEN</code>. Callback for Esc was completely removed. The full-screen action itself was principally unchanged. The key event function was modified correspondingly: | to include GDK definition for key "f", <code>GDK_f</code> to replace the earlier <code>HILDON_HARDKEY_FULLSCREEN</code>. Callback for Esc was completely removed. The full-screen action itself was principally unchanged. The key event function was modified correspondingly: | ||
- | Diablo callbacks.c | + | Diablo callbacks.c |
- | + | <source lang="c"> | |
- | + | gboolean key_press(GtkWidget * widget, GdkEventKey * event, | |
- | + | gpointer data) | |
- | + | { | |
- | + | ... | |
- | + | if (event->keyval == HILDON_HARDKEY_FULLSCREEN && !keypressed){ | |
- | + | keypressed = TRUE; | |
- | + | ... | |
- | + | if (event->keyval == HILDON_HARDKEY_ESC && !keypressed){ | |
- | + | keypressed = TRUE; | |
+ | ... | ||
+ | </source> | ||
+ | |||
Fremantle maemopad-window.c | Fremantle maemopad-window.c | ||
- | + | <source lang="c"> | |
- | + | static gboolean maemopad_window_on_key_press(GtkWidget *widget, GdkEventKey *event, | |
- | + | gpointer data) | |
- | + | { | |
- | + | ... | |
- | + | if (event->keyval == GDK_f && (event->state & GDK_CONTROL_MASK) && !self- >key_pressed) { | |
- | + | self->key_pressed = TRUE; | |
- | + | ... | |
+ | </source> | ||
=== Dropped libraries === | === Dropped libraries === | ||
Line 134: | Line 142: | ||
Hildon help library, libhildonhelp, was dropped from Fremantle so all dependencies to it had to be removed. | Hildon help library, libhildonhelp, was dropped from Fremantle so all dependencies to it had to be removed. | ||
- | libhildonhelp-dev needs to removed from build | + | libhildonhelp-dev needs to removed from build dependencies: |
Diablo: debian/control: | Diablo: debian/control: | ||
- | + | <pre> | |
- | + | Build-Depends: debhelper (>= 4.0.0), intltool, | |
- | + | libhildon1-dev, libgtk2.0-dev, libosso-gnomevfs2-dev, | |
- | + | libglib2.0-dev, libdbus-glib-1-dev, libosso-dev, libmodest-dbus-client-dev, | |
+ | conbtdialogs-dev,libhildonhelp-dev, libhildonfm2-dev, osso-af-settings | ||
+ | </pre> | ||
Fremantle: debian/control: | Fremantle: debian/control: | ||
- | + | <pre> | |
- | + | Build-Depends: debhelper (>= 4.0.0), intltool, | |
- | + | libhildon1-dev, libgtk2.0-dev, libosso-gnomevfs2-dev, | |
- | + | libglib2.0-dev, libdbus-glib-1-dev, libosso-dev, libmodest-dbus-client-dev, | |
+ | conbtdialogs-dev, libhildonfm2-dev, osso-af-settings | ||
+ | </pre> | ||
Callback and all other help stuff removed: | Callback and all other help stuff removed: | ||
Line 154: | Line 166: | ||
Diablo callbacks.c | Diablo callbacks.c | ||
- | + | <source lang="c"> | |
- | + | /* help */ | |
- | + | void callback_help( GtkAction * action, gpointer data ) | |
- | + | { | |
- | + | osso_return_t retval; | |
- | + | /* connect pointer to our AppUIData struct */ | |
- | + | AppUIData *mainview = NULL; | |
- | + | mainview = ( AppUIData * ) data; | |
- | + | g_assert(mainview != NULL && mainview->data != NULL ); | |
- | + | retval = hildon_help_show( | |
- | + | mainview->data->osso, /* osso_context */ | |
- | + | HELP_TOPIC_ID, /* topic id */ | |
- | + | HILDON_HELP_SHOW_DIALOG); | |
+ | } | ||
+ | </source> | ||
Diablo interface.c | Diablo interface.c | ||
- | + | <source lang="c"> | |
- | + | GtkWidget *help = NULL; | |
- | + | help = gtk_menu_item_new_with_label( _("Help") ); | |
- | + | gtk_menu_append( main_menu, help ); | |
- | + | g_signal_connect( G_OBJECT( help ), "activate", | |
+ | G_CALLBACK ( callback_help ), main ); | ||
+ | </source> | ||
Diablo callbacks.c | Diablo callbacks.c | ||
- | + | <source lang="c"> | |
- | + | #include <hildon/hildon-help.h> | |
+ | #define HELP_TOPIC_ID "Example_MaemoPad_Content" | ||
+ | </source> | ||
Diablo configure.ac: | Diablo configure.ac: | ||
- | + | <source lang="autoconf"> | |
+ | PKG_CHECK_MODULES(HILDON, hildon-1 hildon-fm-2 hildon-help conbtdialogs) | ||
+ | </source> | ||
Fremantle configure.ac: | Fremantle configure.ac: | ||
- | + | ||
- | + | <source lang="c"> | |
+ | PKG_CHECK_MODULES(HILDON, hildon-1 hildon-fm-2 conbtdialogs) | ||
+ | </source> | ||
Removed data/help directory which contained an example help file. | Removed data/help directory which contained an example help file. | ||
Line 194: | Line 216: | ||
Diablo data/Makefile.am: | Diablo data/Makefile.am: | ||
- | |||
- | |||
- | |||
- | |||
- | + | <source lang="make"> | |
+ | helpfile_engb_DATA = help/en_GB/MaemoPad.xml | ||
+ | -EXTRA_DIST = $(serviceentry_DATA) $(desktopentry_DATA) $(icon_26x26_DATA) $(icon_40x40_DATA) | ||
+ | $(icon_scalable_DATA) *$(helpfile_engb_DATA)* | ||
+ | </source> | ||
- | + | Diablo data/Makefile.am: | |
- | + | ||
- | + | ||
+ | <source lang="make"> | ||
+ | # Help file install directory | ||
+ | helpfile_engbdir=$datadir/hildon-help/en_GB | ||
+ | AC_SUBST(helpfile_engbdir) | ||
+ | </source> | ||
=== GUI design changes === | === GUI design changes === | ||
Line 212: | Line 237: | ||
Diablo interface.h | Diablo interface.h | ||
- | + | <source lang="c"> | |
- | + | /* Toolbar */ | |
- | + | GtkWidget* toolbar; | |
- | + | GtkWidget* iconw; | |
- | + | GtkToolItem* new_tb; | |
- | + | GtkToolItem* open_tb; | |
- | + | ... | |
+ | GtkToolItem* fullscreen_tb; | ||
+ | </source> | ||
- | Also the menu system was changed. In Diablo, a GtkMenu was used, but it was replaced with a HildonAppMenu in Fremantle, as shown in Figure: | + | Also the menu system was changed. In Diablo, a <code>GtkMenu</code> was used, but it was replaced with a <code>HildonAppMenu</code> in Fremantle, as shown in Figure: |
- | + | [[Image:maemopad_menu.png|frame|center|alt=Screenshot of MaemoPad menu|MaemoPad menu]] | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
Function <code>create_menu()</code> is responsible for creating the menus in both versions: | Function <code>create_menu()</code> is responsible for creating the menus in both versions: | ||
Line 237: | Line 255: | ||
Diablo interface.c | Diablo interface.c | ||
- | + | <source lang="c"> | |
- | + | static void create_menu( AppUIData *main ) | |
- | + | { | |
- | + | /* Create needed handles */ | |
- | + | GtkMenu *main_menu; | |
- | + | GtkWidget *file_menu, *edit_menu, *sendvia_menu; | |
- | + | GtkWidget *separator = NULL; | |
- | + | GtkWidget *close = NULL; | |
- | + | /* Create main menu and new menus for submenus in our drop down menu */ | |
- | + | main_menu = GTK_MENU( gtk_menu_new () ); | |
- | + | file_menu = gtk_menu_new (); | |
- | + | edit_menu = gtk_menu_new (); | |
- | + | sendvia_menu = gtk_menu_new (); | |
- | + | /* Create the menu items */ | |
- | + | main->file_item = gtk_menu_item_new_with_label ( _("File") ); | |
- | + | main->new_item = gtk_menu_item_new_with_label ( _("New") ); | |
- | + | main->open_item = gtk_menu_item_new_with_label ( _("Open") ); | |
- | + | ... | |
- | + | /* Add menu items to right menus */ | |
- | + | gtk_menu_append( main_menu, main->file_item ); | |
- | + | gtk_menu_append( file_menu, main->new_item ); | |
- | + | gtk_menu_append( file_menu, main->open_item ); | |
- | + | ... | |
- | + | gtk_menu_append( main_menu, close ); | |
- | + | /* Add submenus to the right items */ | |
- | + | gtk_menu_item_set_submenu( GTK_MENU_ITEM (main->file_item), file_menu ); | |
- | + | gtk_menu_item_set_submenu( GTK_MENU_ITEM (main->edit_item), edit_menu ); | |
- | + | gtk_menu_item_set_submenu( GTK_MENU_ITEM (main->sendvia_item), sendvia_menu ); | |
- | + | /* Attach the callback functions to the activate signal */ | |
- | + | g_signal_connect( G_OBJECT( main->new_item ), "activate", | |
- | + | G_CALLBACK ( callback_file_new), main ); | |
- | + | g_signal_connect( G_OBJECT( main->open_item ), "activate", | |
- | + | G_CALLBACK ( callback_file_open), main ); | |
- | + | ... | |
- | + | g_signal_connect( G_OBJECT( close ), "activate", gtk_main_quit, NULL ); | |
- | + | /* Add menu to HildonWindow */ | |
- | + | hildon_window_set_menu(main->data->window, main_menu); | |
- | + | /* We need to show menu items */ | |
- | + | gtk_widget_show_all( GTK_WIDGET( main_menu ) ); | |
+ | } | ||
+ | </source> | ||
Fremantle maemopad-window.c | Fremantle maemopad-window.c | ||
- | + | <source lang="c"> | |
- | + | static GtkWidget* add_menu_item (GtkWidget *main_menu, const gchar* title, | |
- | + | GCallback clicked_callback, gpointer user_data) | |
- | + | { | |
- | + | HildonAppMenu *app_menu = HILDON_APP_MENU (main_menu); | |
- | + | /* Create a button, add it, and return it: */ | |
- | + | GtkWidget *button = hildon_button_new_with_text (HILDON_SIZE_AUTO, | |
- | + | HILDON_BUTTON_ARRANGEMENT_VERTICAL, title, NULL); | |
- | + | gtk_widget_show (button); | |
- | + | g_signal_connect_after (button, "clicked", | |
- | + | G_CALLBACK (clicked_callback), user_data); | |
- | + | hildon_app_menu_append (app_menu, GTK_BUTTON (button)); | |
- | + | return button; | |
- | + | } | |
- | + | /* Create the menu items needed: */ | |
- | + | static void create_menu (MaemopadWindow *self) | |
- | + | { | |
- | + | /* Create needed handles */ | |
- | + | GtkWidget *main_menu = hildon_app_menu_new (); | |
- | + | /* Create the menu items */ | |
- | + | self->new_item = add_menu_item (main_menu, _("New"), | |
- | + | G_CALLBACK (&maemopad_window_on_menu_file_new), self); | |
- | + | self->open_item = add_menu_item (main_menu, _("Open"), | |
- | + | G_CALLBACK (&maemopad_window_on_menu_file_open), self); | |
- | + | ... | |
- | + | self->close_item = add_menu_item (main_menu, _("Close"), | |
- | + | G_CALLBACK (&maemopad_window_on_menu_close), self); | |
- | + | /* Add menu to HildonWindow */ | |
- | + | hildon_window_set_app_menu ( | |
- | + | HILDON_WINDOW (self), | |
- | + | HILDON_APP_MENU (main_menu)); | |
- | + | /* We need to show menu items */ | |
- | + | gtk_widget_show_all (GTK_WIDGET (main_menu)); | |
- | + | } | |
- | + | </source> | |
As a result to changes in the .c file, the following menu widget declarations used in Diablo became unnecessary: | As a result to changes in the .c file, the following menu widget declarations used in Diablo became unnecessary: | ||
Line 319: | Line 339: | ||
Diablo interface.h | Diablo interface.h | ||
- | + | <source lang="c"> | |
- | + | GtkWidget *file_item; | |
- | + | GtkWidget *edit_item; | |
+ | GtkWidget *sendvia_item; | ||
+ | </source> | ||
- | + | Menu callbacks were also changed. There were some changes in the callbacks themselves as a result of code reorganizations, but the main change from the menu viewpoint was that the 1st arguments of the callbacks were changed from <code>GtkAction</code> to <code>GtkButton</code>, like in the following example: | |
- | + | ||
- | Menu callbacks were also changed. There were some changes in the callbacks themselves as a result of code reorganizations, but the main change from the menu viewpoint was that the 1st arguments of the callbacks were changed from GtkAction to GtkButton, like in the following example: | + | |
Diablo callbacks.c | Diablo callbacks.c | ||
- | + | <source lang="c"> | |
+ | void callback_file_new(GtkAction * action, gpointer data) | ||
+ | </source> | ||
Fremantle maemopad-window.c | Fremantle maemopad-window.c | ||
- | + | <source lang="c"> | |
- | + | static void maemopad_window_on_menu_file_new (GtkButton *button, gpointer data) | |
+ | </source> | ||
=== Other updates in GTK+ and Hildon === | === Other updates in GTK+ and Hildon === | ||
- | |||
<ul> | <ul> | ||
<li> | <li> | ||
Rich text support was changed with the new GTK+, as described in [http://live.gnome.org/Maemo/Gtk210Migration Maemo-GTK+ 2.6 to 2.10 Migration].This required editing two lines: | Rich text support was changed with the new GTK+, as described in [http://live.gnome.org/Maemo/Gtk210Migration Maemo-GTK+ 2.6 to 2.10 Migration].This required editing two lines: | ||
- | |||
- | |||
- | < | + | Part of function <code>create_textarea()</code> in Diablo interface.c |
+ | |||
+ | <source lang="c"> | ||
/* Enable Rich Text Support */ | /* Enable Rich Text Support */ | ||
gtk_text_buffer_set_can_paste_rich_text ( main->buffer, TRUE ); | gtk_text_buffer_set_can_paste_rich_text ( main->buffer, TRUE ); | ||
gtk_text_buffer_set_rich_text_format ( main->buffer, "RTF" ); | gtk_text_buffer_set_rich_text_format ( main->buffer, "RTF" ); | ||
- | </ | + | </source> |
- | Part of function create_textarea() in Fremantle maemopad-window.c | + | Part of function <code>create_textarea()</code> in Fremantle maemopad-window.c |
- | < | + | <source lang="c"> |
/* Enable Rich Text Support */ | /* Enable Rich Text Support */ | ||
gtk_text_buffer_register_serialize_tagset (self->buffer, "RTF"); | gtk_text_buffer_register_serialize_tagset (self->buffer, "RTF"); | ||
gtk_text_buffer_register_deserialize_tagset (self->buffer, "RTF"); | gtk_text_buffer_register_deserialize_tagset (self->buffer, "RTF"); | ||
- | </ | + | </source> |
</li> | </li> | ||
- | |||
<li> | <li> | ||
- | HildonFontSelectionDialog was deprecated and replaced with a GtkFontButton. | + | <code>HildonFontSelectionDialog</code> was deprecated and replaced with a <code>GtkFontButton</code>. In Diablo, the font callback was a callback to a regular <code>GtkAction</code>: |
- | In Diablo, the font callback was a callback to a regular | + | |
- | < | + | |
callback.c | callback.c | ||
- | < | + | <source lang="c"> |
void callback_font( GtkAction * action, gpointer data ) | void callback_font( GtkAction * action, gpointer data ) | ||
{ | { | ||
Line 378: | Line 398: | ||
} | } | ||
} | } | ||
- | </ | + | </source> |
+ | |||
+ | Function <code>callback_font</code> got the font from an auxiliary function <code>interface_font_chooser()</code> and then modified the font in the text view. The auxiliary function <code>interface_font_chooser()</code> in turn opened a <code>HildonFontSelectionDialog</code> that returned the font parameters: | ||
- | |||
- | |||
callback.c | callback.c | ||
- | < | + | <source lang="c"> |
/* Font chooser */ | /* Font chooser */ | ||
PangoFontDescription* interface_font_chooser( AppUIData * main ) | PangoFontDescription* interface_font_chooser( AppUIData * main ) | ||
Line 417: | Line 437: | ||
return font; | return font; | ||
} | } | ||
- | </ | + | </source> |
+ | Instead of the deprecated <code>HildonFontSelectionDialog</code>, Fremantle uses a <code>GtkFontButton</code> directly in the font button callback: | ||
- | |||
- | |||
maemopad-window.c | maemopad-window.c | ||
- | < | + | <source lang="c"> |
/* font */ | /* font */ | ||
static void maemopad_window_on_font_set (GtkFontButton *button, gpointer data) | static void maemopad_window_on_font_set (GtkFontButton *button, gpointer data) | ||
Line 441: | Line 460: | ||
} | } | ||
} | } | ||
- | </ | + | </source> |
- | This GtkFontButton was initialized in function <code>create_menu()</code> (see above) in maemopad-window.c so that it would respond to the <code>"font-set"</code> signal and call the callback above: | + | This <code>GtkFontButton</code> was initialized in function <code>create_menu()</code> (see above) in <code>maemopad-window.c</code> so that it would respond to the <code>"font-set"</code> signal and call the callback above: |
- | + | <source lang="c"> | |
- | + | self->font_item = gtk_font_button_new (); | |
- | + | gtk_widget_show (self->font_item); | |
- | + | g_signal_connect_after (self->font_item, "font-set", | |
- | + | G_CALLBACK (maemopad_window_on_font_set), self); | |
+ | hildon_app_menu_append (HILDON_APP_MENU (main_menu), GTK_BUTTON (self->font_item)); | ||
+ | </source> | ||
</li> | </li> | ||
+ | <li> | ||
+ | Instead of <code>GtkTextView</code>, a [http://maemo.org/api_refs/5.0/5.0-final/hildon/HildonTextView.html HildonTextView] is now used: | ||
- | |||
- | |||
- | |||
Diablo callback.c | Diablo callback.c | ||
- | < | + | <source lang="c"> |
/* Create the text area */ | /* Create the text area */ | ||
void create_textarea( AppUIData *main ) | void create_textarea( AppUIData *main ) | ||
Line 469: | Line 489: | ||
... | ... | ||
} | } | ||
- | </ | + | </source> |
Fremantle maemopad-window.c | Fremantle maemopad-window.c | ||
- | < | + | <source lang="c"> |
static void create_textarea (MaemopadWindow *self) | static void create_textarea (MaemopadWindow *self) | ||
{ | { | ||
Line 482: | Line 502: | ||
self->buffer = hildon_text_view_get_buffer (GTK_TEXT_VIEW (self->textview)); | self->buffer = hildon_text_view_get_buffer (GTK_TEXT_VIEW (self->textview)); | ||
} | } | ||
- | </ | + | </source> |
</li> | </li> | ||
- | |||
<li> | <li> | ||
All Hildon applications should now initialize hildon before using it. In maemopad this is done by calling <code>hildon_gtk_init()</code> which also calls <code>gtk_init()</code> so the original call can be removed: | All Hildon applications should now initialize hildon before using it. In maemopad this is done by calling <code>hildon_gtk_init()</code> which also calls <code>gtk_init()</code> so the original call can be removed: | ||
- | + | ||
Diablo main.c | Diablo main.c | ||
- | < | + | <source lang="c"> |
/* Init the gtk - must be called before any hildon stuff */ | /* Init the gtk - must be called before any hildon stuff */ | ||
gtk_init( &argc, &argv ); | gtk_init( &argc, &argv ); | ||
- | </ | + | </source> |
Fremantle main.c | Fremantle main.c | ||
- | < | + | <source lang="c"> |
/* Inititialize GTK+ and hildon: */ | /* Inititialize GTK+ and hildon: */ | ||
hildon_gtk_init( &argc, &argv ); | hildon_gtk_init( &argc, &argv ); | ||
- | </ | + | </source> |
[[Category:Development]] | [[Category:Development]] | ||
[[Category:Documentation]] | [[Category:Documentation]] | ||
[[Category:Fremantle]] | [[Category:Fremantle]] |
Latest revision as of 08:43, 25 November 2010
This is a practical example of porting a Diablo (Maemo 4.1) application to Fremantle (Maemo 5). The example application, MaemoPad, is a simple Notepad-like editor.
Contents |
[edit] Porting MaemoPad from Diablo to Fremantle
Porting from Diablo to Fremantle involved mostly changes in GTK+- and Hildon-specific parts of the code, because newer versions of these libraries are now in use, and because of the new Fremantle GUI guidelines. This subsection will first explain how to install MaemoPad, and then proceeds to describing the main changes in the code. The reader is recommended to familiarize with chapters Application Development and Human Interface Guidelines before this one. For reference, see GTK+ and Hildon APIs from Maemo Fremantle APIs.
[edit] Installing MaemoPad
MaemoPad can be installed and tested in the Scratchbox environment.
- If not already activated, activate the X86 target, go to the testing directory, and download the source package of maemopad application.
[sbox-FREMANTLE_ARMEL] > sb-conf select FREMANTLE_X86 [sbox-FREMANTLE_X86 ~] > mkdir maemopad [sbox-FREMANTLE_X86 ~/maemopad] > cd maemopad [sbox-FREMANTLE_X86 ~/maemopad] > apt-get source maemopad ...apt output...
- Check that you have the correct files.
[sbox-FREMANTLE_X86: ~/maemopad] > ls -l total 352 drwxrwxr-x 6 maemo maemo 4096 Jul 28 14:09 maemopad-2.5 -rw-rw-r-- 1 maemo maemo 465 Jul 6 16:02 maemopad_2.5.dsc -rw-rw-r-- 1 maemo maemo 346129 Jul 6 16:02 maemopad_2.5.tar.gz
- Go to the
maemopad-2.5
source directory, and build the maemopad package withdpkg-buildpackage
command as shown here:
[sbox-FREMANTLE_X86: ~/maemopad] > cd maemopad-2.5 [sbox-FREMANTLE_X86: ~/maemopad/maemopad-2.5] > dpkg-buildpackage -rfakeroot dpkg-buildpackage: source package is maemopad dpkg-buildpackage: source version is 2.5 dpkg-buildpackage: source changed by Soumya Bijjal <soumya.3.bijjal@nokia.com> dpkg-buildpackage: host architecture i386 dpkg-buildpackage: source version without epoch 2.3 .... etc ....
- Install the newly compiled
maemopad_2.5_i386.deb
file inside the Scratchbox environment:
[sbox-FREMANTLE_X86: ~/maemopad] > dpkg -i maemopad_2.5_i386.deb ... output from dpkg ...
- Make sure you have the SDK UI running in Xephyr.
- You can now run MaemoPad by selecting it from the menu.
The MaemoPad source code resides in folder maemopad-2.5/src:
[sbox-FREMANTLE_X86: ~/maemopad] ls maemopad-2.5/src total 280 -rw-rw-r-- 1 maemo maemo 25491 Jul 28 15:45 Makefile -rw-rw-r-- 1 maemo maemo 491 Jul 28 14:09 Makefile.am -rw-rw-r-- 1 maemo maemo 23238 Jul 28 14:09 Makefile.in -rwxrwxr-x 1 maemo maemo 83433 Jul 28 15:45 maemopad -rw-rw-r-- 1 maemo maemo 82928 Jul 28 15:45 maemopad-maemopad-window.o -rw-rw-r-- 1 maemo maemo 18564 Jul 28 15:45 maemopad-main.o -rw-rw-r-- 1 maemo maemo 20400 Jul 28 14:09 maemopad-window.c -rw-rw-r-- 1 maemo maemo 2391 Jul 28 14:09 maemopad-window.h -rw-rw-r-- 1 maemo maemo 2193 Jul 28 14:09 main.c
For comparison, the Diablo version of MaemoPad can also be examined:
[sbox-FREMANTLE_X86: ~/maemopad] > svn export https://vcs.maemo.org/svn/\ maemoexamples/tags/maemo_4.1/maemopad diablo_maemopad [sbox-FREMANTLE_X86: ~/src] ls -lR diablo_maemopad/src diablo_maemopad/src/: total 16 -rw-rw-r-- 1 maemo maemo 537 May 15 2008 Makefile.am -rw-rw-r-- 1 maemo maemo 557 May 15 2008 appdata.h -rw-rw-r-- 1 maemo maemo 2789 Dec 3 2008 main.c drwxrwxr-x 2 maemo maemo 4096 Aug 20 11:53 ui diablo_maemopad/src/ui: total 36 -rw-rw-r-- 1 maemo maemo 12163 Dec 3 2008 callbacks.c -rw-rw-r-- 1 maemo maemo 1682 Oct 29 2008 callbacks.h -rw-rw-r-- 1 maemo maemo 14982 Dec 3 2008 interface.c -rw-rw-r-- 1 maemo maemo 2695 Dec 3 2008 interface.h
[edit] Code reorganization
If one takes a look at MaemoPad source code for Diablo and Fremantle, there are many bug fixes, and there have been major refractorizations. These are, however, not necessary for porting and are not discussed here in detail. The main change is reorganizing the files, which is already apparent from the ls
lists above:
-
src/ui
subfolder has been dropped -
src/ui/callbacks.c
andsrc/ui/interface
have been combined intosrc/maemopad-window.c
, similarly for header files -
appdata.h
is included inmain.c
- In
src/Makefile.am
,maemopad_SOURCES = <list of source files>
has been updated correspondingly.
[edit] Device-specific changes
The previous device, N810, had a separate full-screen and ESC keys that were dropped from the new device. In MaemoPad, pressing the full-screen key was replaced by Ctrl-F. This required the following addition:
maemopad-window.c
#include <gdk/gdkkeysyms.h>
to include GDK definition for key "f", GDK_f
to replace the earlier HILDON_HARDKEY_FULLSCREEN
. Callback for Esc was completely removed. The full-screen action itself was principally unchanged. The key event function was modified correspondingly:
Diablo callbacks.c
gboolean key_press(GtkWidget * widget, GdkEventKey * event, gpointer data) { ... if (event->keyval == HILDON_HARDKEY_FULLSCREEN && !keypressed){ keypressed = TRUE; ... if (event->keyval == HILDON_HARDKEY_ESC && !keypressed){ keypressed = TRUE; ...
Fremantle maemopad-window.c
static gboolean maemopad_window_on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) { ... if (event->keyval == GDK_f && (event->state & GDK_CONTROL_MASK) && !self- >key_pressed) { self->key_pressed = TRUE; ...
[edit] Dropped libraries
Hildon help library, libhildonhelp, was dropped from Fremantle so all dependencies to it had to be removed.
libhildonhelp-dev needs to removed from build dependencies:
Diablo: debian/control:
Build-Depends: debhelper (>= 4.0.0), intltool, libhildon1-dev, libgtk2.0-dev, libosso-gnomevfs2-dev, libglib2.0-dev, libdbus-glib-1-dev, libosso-dev, libmodest-dbus-client-dev, conbtdialogs-dev,libhildonhelp-dev, libhildonfm2-dev, osso-af-settings
Fremantle: debian/control:
Build-Depends: debhelper (>= 4.0.0), intltool, libhildon1-dev, libgtk2.0-dev, libosso-gnomevfs2-dev, libglib2.0-dev, libdbus-glib-1-dev, libosso-dev, libmodest-dbus-client-dev, conbtdialogs-dev, libhildonfm2-dev, osso-af-settings
Callback and all other help stuff removed:
Diablo callbacks.c
/* help */ void callback_help( GtkAction * action, gpointer data ) { osso_return_t retval; /* connect pointer to our AppUIData struct */ AppUIData *mainview = NULL; mainview = ( AppUIData * ) data; g_assert(mainview != NULL && mainview->data != NULL ); retval = hildon_help_show( mainview->data->osso, /* osso_context */ HELP_TOPIC_ID, /* topic id */ HILDON_HELP_SHOW_DIALOG); }
Diablo interface.c
GtkWidget *help = NULL; help = gtk_menu_item_new_with_label( _("Help") ); gtk_menu_append( main_menu, help ); g_signal_connect( G_OBJECT( help ), "activate", G_CALLBACK ( callback_help ), main );
Diablo callbacks.c
#include <hildon/hildon-help.h> #define HELP_TOPIC_ID "Example_MaemoPad_Content"
Diablo configure.ac:
GeSHi Error: GeSHi could not find the language autoconf (using path /usr/share/php-geshi/geshi/) (code 2)
You need to specify a language like this: <source lang="html4strict">...</source>
Supported languages for syntax highlighting:
abap, actionscript, actionscript3, ada, apache, applescript, apt_sources, asm, asp, autoit, avisynth, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_mac, caddcl, cadlisp, cfdg, cfm, cil, cmake, cobol, cpp, cpp-qt, csharp, css, d, dcs, delphi, diff, div, dos, dot, eiffel, email, erlang, fo, fortran, freebasic, genero, gettext, glsl, gml, gnuplot, groovy, haskell, hq9plus, html4strict, idl, ini, inno, intercal, io, java, java5, javascript, kixtart, klonec, klonecpp, latex, lisp, locobasic, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, make, matlab, mirc, modula3, mpasm, mxml, mysql, nsis, oberon2, objc, ocaml, ocaml-brief, oobas, oracle11, oracle8, pascal, per, perl, php, php-brief, pic16, pixelbender, plsql, povray, powershell, progress, prolog, properties, providex, python, qbasic, rails, rebol, reg, robots, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, tcl, teraterm, text, thinbasic, tsql, typoscript, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xml, xorg_conf, xpp, z80
Fremantle configure.ac:
PKG_CHECK_MODULES(HILDON, hildon-1 hildon-fm-2 conbtdialogs)
Removed data/help directory which contained an example help file.
Some files contained items related to it and they were also removed:
Diablo data/Makefile.am:
helpfile_engb_DATA = help/en_GB/MaemoPad.xml -EXTRA_DIST = $(serviceentry_DATA) $(desktopentry_DATA) $(icon_26x26_DATA) $(icon_40x40_DATA) $(icon_scalable_DATA) *$(helpfile_engb_DATA)*
Diablo data/Makefile.am:
# Help file install directory helpfile_engbdir=$datadir/hildon-help/en_GB AC_SUBST(helpfile_engbdir)
[edit] GUI design changes
Because of new UI guidelines, a toolbar that was at the bottom of the MaemoPadwindow in Diablo was dropped. This meant removing the function create_toolbar
and its declaration from interface.c
. Also the call for the function was dropped from the same file. Likewise, related declarations were dropped:
Diablo interface.h
/* Toolbar */ GtkWidget* toolbar; GtkWidget* iconw; GtkToolItem* new_tb; GtkToolItem* open_tb; ... GtkToolItem* fullscreen_tb;
Also the menu system was changed. In Diablo, a GtkMenu
was used, but it was replaced with a HildonAppMenu
in Fremantle, as shown in Figure:
Function create_menu()
is responsible for creating the menus in both versions:
Diablo interface.c
static void create_menu( AppUIData *main ) { /* Create needed handles */ GtkMenu *main_menu; GtkWidget *file_menu, *edit_menu, *sendvia_menu; GtkWidget *separator = NULL; GtkWidget *close = NULL; /* Create main menu and new menus for submenus in our drop down menu */ main_menu = GTK_MENU( gtk_menu_new () ); file_menu = gtk_menu_new (); edit_menu = gtk_menu_new (); sendvia_menu = gtk_menu_new (); /* Create the menu items */ main->file_item = gtk_menu_item_new_with_label ( _("File") ); main->new_item = gtk_menu_item_new_with_label ( _("New") ); main->open_item = gtk_menu_item_new_with_label ( _("Open") ); ... /* Add menu items to right menus */ gtk_menu_append( main_menu, main->file_item ); gtk_menu_append( file_menu, main->new_item ); gtk_menu_append( file_menu, main->open_item ); ... gtk_menu_append( main_menu, close ); /* Add submenus to the right items */ gtk_menu_item_set_submenu( GTK_MENU_ITEM (main->file_item), file_menu ); gtk_menu_item_set_submenu( GTK_MENU_ITEM (main->edit_item), edit_menu ); gtk_menu_item_set_submenu( GTK_MENU_ITEM (main->sendvia_item), sendvia_menu ); /* Attach the callback functions to the activate signal */ g_signal_connect( G_OBJECT( main->new_item ), "activate", G_CALLBACK ( callback_file_new), main ); g_signal_connect( G_OBJECT( main->open_item ), "activate", G_CALLBACK ( callback_file_open), main ); ... g_signal_connect( G_OBJECT( close ), "activate", gtk_main_quit, NULL ); /* Add menu to HildonWindow */ hildon_window_set_menu(main->data->window, main_menu); /* We need to show menu items */ gtk_widget_show_all( GTK_WIDGET( main_menu ) ); }
Fremantle maemopad-window.c
static GtkWidget* add_menu_item (GtkWidget *main_menu, const gchar* title, GCallback clicked_callback, gpointer user_data) { HildonAppMenu *app_menu = HILDON_APP_MENU (main_menu); /* Create a button, add it, and return it: */ GtkWidget *button = hildon_button_new_with_text (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL, title, NULL); gtk_widget_show (button); g_signal_connect_after (button, "clicked", G_CALLBACK (clicked_callback), user_data); hildon_app_menu_append (app_menu, GTK_BUTTON (button)); return button; } /* Create the menu items needed: */ static void create_menu (MaemopadWindow *self) { /* Create needed handles */ GtkWidget *main_menu = hildon_app_menu_new (); /* Create the menu items */ self->new_item = add_menu_item (main_menu, _("New"), G_CALLBACK (&maemopad_window_on_menu_file_new), self); self->open_item = add_menu_item (main_menu, _("Open"), G_CALLBACK (&maemopad_window_on_menu_file_open), self); ... self->close_item = add_menu_item (main_menu, _("Close"), G_CALLBACK (&maemopad_window_on_menu_close), self); /* Add menu to HildonWindow */ hildon_window_set_app_menu ( HILDON_WINDOW (self), HILDON_APP_MENU (main_menu)); /* We need to show menu items */ gtk_widget_show_all (GTK_WIDGET (main_menu)); }
As a result to changes in the .c file, the following menu widget declarations used in Diablo became unnecessary:
Diablo interface.h
GtkWidget *file_item; GtkWidget *edit_item; GtkWidget *sendvia_item;
Menu callbacks were also changed. There were some changes in the callbacks themselves as a result of code reorganizations, but the main change from the menu viewpoint was that the 1st arguments of the callbacks were changed from GtkAction
to GtkButton
, like in the following example:
Diablo callbacks.c
void callback_file_new(GtkAction * action, gpointer data)
Fremantle maemopad-window.c
static void maemopad_window_on_menu_file_new (GtkButton *button, gpointer data)
[edit] Other updates in GTK+ and Hildon
-
Rich text support was changed with the new GTK+, as described in Maemo-GTK+ 2.6 to 2.10 Migration.This required editing two lines:
Part of function
create_textarea()
in Diablo interface.c/* Enable Rich Text Support */ gtk_text_buffer_set_can_paste_rich_text ( main->buffer, TRUE ); gtk_text_buffer_set_rich_text_format ( main->buffer, "RTF" );
Part of function
create_textarea()
in Fremantle maemopad-window.c/* Enable Rich Text Support */ gtk_text_buffer_register_serialize_tagset (self->buffer, "RTF"); gtk_text_buffer_register_deserialize_tagset (self->buffer, "RTF");
-
HildonFontSelectionDialog
was deprecated and replaced with aGtkFontButton
. In Diablo, the font callback was a callback to a regularGtkAction
: callback.cvoid callback_font( GtkAction * action, gpointer data ) { ... new_font = interface_font_chooser( mainview ); /* if we got a new font from chooser -> change font */ if( new_font != NULL ) { mainview->font_desc = new_font; gtk_widget_modify_font ( mainview->textview, mainview->font_desc ); } }
Function
callback_font
got the font from an auxiliary functioninterface_font_chooser()
and then modified the font in the text view. The auxiliary functioninterface_font_chooser()
in turn opened aHildonFontSelectionDialog
that returned the font parameters:callback.c
/* Font chooser */ PangoFontDescription* interface_font_chooser( AppUIData * main ) { ... font = pango_font_description_new(); /* create dialog */ dialog = HILDON_FONT_SELECTION_DIALOG ( hildon_font_selection_dialog_new( NULL, NULL ) ); gtk_widget_show_all (GTK_WIDGET(dialog)); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { g_object_get(G_OBJECT(dialog), "family", &family, "size", &size, "bold", &bold, "italic", &italic, NULL); pango_font_description_set_family(font, family); pango_font_description_set_size(font, size * PANGO_SCALE); if (bold) { pango_font_description_set_weight(font, PANGO_WEIGHT_BOLD); } else { pango_font_description_set_weight(font, PANGO_WEIGHT_NORMAL); } if (italic) { pango_font_description_set_style(font, PANGO_STYLE_ITALIC); } else { pango_font_description_set_style(font, PANGO_STYLE_NORMAL); } } gtk_widget_destroy(GTK_WIDGET(dialog)); return font; }
Instead of the deprecated
HildonFontSelectionDialog
, Fremantle uses aGtkFontButton
directly in the font button callback:maemopad-window.c
/* font */ static void maemopad_window_on_font_set (GtkFontButton *button, gpointer data) { ... font_name = gtk_font_button_get_font_name (button); if (!font_name) return; new_font = pango_font_description_from_string (font_name); /* Change the font used in the GtkTextView */ if (new_font) { if (self->font_desc) pango_font_description_free (self->font_desc); self->font_desc = new_font; gtk_widget_modify_font (self->textview, self->font_desc); } }
This
GtkFontButton
was initialized in functioncreate_menu()
(see above) inmaemopad-window.c
so that it would respond to the"font-set"
signal and call the callback above:self->font_item = gtk_font_button_new (); gtk_widget_show (self->font_item); g_signal_connect_after (self->font_item, "font-set", G_CALLBACK (maemopad_window_on_font_set), self); hildon_app_menu_append (HILDON_APP_MENU (main_menu), GTK_BUTTON (self->font_item));
-
Instead of
GtkTextView
, a HildonTextView is now used: Diablo callback.c/* Create the text area */ void create_textarea( AppUIData *main ) { /* Text view */ main->textview = gtk_text_view_new (); ... /* Get handle */ main->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (main->textview)); ... }
Fremantle maemopad-window.c
static void create_textarea (MaemopadWindow *self) { /* Text view */ self->textview = hildon_text_view_new (); .... /* Get handle */ self->buffer = hildon_text_view_get_buffer (GTK_TEXT_VIEW (self->textview)); }
-
All Hildon applications should now initialize hildon before using it. In maemopad this is done by calling
hildon_gtk_init()
which also callsgtk_init()
so the original call can be removed: Diablo main.c/* Init the gtk - must be called before any hildon stuff */ gtk_init( &argc, &argv );
Fremantle main.c
/* Inititialize GTK+ and hildon: */ hildon_gtk_init( &argc, &argv );
- This page was last modified on 25 November 2010, at 08:43.
- This page has been accessed 27,147 times.