Port applications manager to win32 0.3
authorJ. Ali Harlow <ali@juiblex.co.uk>
Fri Apr 30 20:37:08 2010 +0100 (2010-04-30)
changeset 108b50be3e2998
parent 9 8d3b1ddf789c
child 11 0987519d94ba
child 12 1d18b9c34d26
Port applications manager to win32
.gitignore
app-manager/Makefile.am
app-manager/app-manager.c
app-manager/app-manager.h
app-manager/app-manager.ui
app-manager/applications.c
app-manager/localmedia.c
app-manager/packagelist.c
configure.ac
plover-gtk/Makefile.am
plover-gtk/package.c
plover-gtk/packagefilestore.c
plover-gtk/packageset.c
plover-gtk/packageset.h
plover-gtk/packagestore.c
setup/Makefile.am
setup/resources.rc.in
update/Makefile.am
update/resources.rc.in
     1.1 --- a/.gitignore	Sat Feb 20 12:11:02 2010 +0000
     1.2 +++ b/.gitignore	Fri Apr 30 20:37:08 2010 +0100
     1.3 @@ -14,7 +14,9 @@
     1.4  *.lo
     1.5  *.la
     1.6  plover/plover.pc
     1.7 +plover-gtk/plover-gtk.pc
     1.8  setup/resources.rc
     1.9  setup/setup
    1.10  update/resources.rc
    1.11  update/update
    1.12 +app-manager/resources.rc
     2.1 --- a/app-manager/Makefile.am	Sat Feb 20 12:11:02 2010 +0000
     2.2 +++ b/app-manager/Makefile.am	Fri Apr 30 20:37:08 2010 +0100
     2.3 @@ -13,19 +13,41 @@
     2.4  desktop_DATA=app-manager.desktop
     2.5  scaleabledir=$(datadir)/icons/hicolor/scalable/apps
     2.6  scaleable_DATA=plover-applications.svg
     2.7 +smallicondir=$(datadir)/icons/hicolor/24x24/apps
     2.8 +smallicon_DATA=24x24/plover-applications.png
     2.9 +bigicondir=$(datadir)/icons/hicolor/48x48/apps
    2.10 +bigicon_DATA=48x48/plover-applications.png
    2.11  
    2.12  .rc.$(OBJEXT):
    2.13  	$(WINDRES) $< $@
    2.14  
    2.15 -resources.$(OBJEXT):	plover-applications.ico
    2.16 +resources.$(OBJEXT):	app-manager.ico
    2.17  
    2.18  plover-applications%.pnm:	plover-applications.svg
    2.19  	rsvg -w $* -h $* -f png $< temp.png
    2.20  	pngtopnm temp.png | pnmquant 256 > $@
    2.21  	$(RM) temp.png
    2.22  
    2.23 -app-manager.ico:	plover-applications16.pnm \
    2.24 -		plover-applications22.pnm plover-applications32.pnm
    2.25 -	ppmtowinicon -output=$@ $^
    2.26 +plover-applications%.pgm:	plover-applications.svg
    2.27 +	rsvg -w $* -h $* -f png $< temp.png
    2.28 +	pngtopnm -alpha temp.png > $@
    2.29 +	$(RM) temp.png
    2.30 +
    2.31 +24x24/plover-applications.png:	plover-applications.svg
    2.32 +	mkdir -p 24x24
    2.33 +	rsvg -w 24 -h 24 -f png $< $@
    2.34 +
    2.35 +48x48/plover-applications.png:	plover-applications.svg
    2.36 +	mkdir -p 48x48
    2.37 +	rsvg -w 48 -h 48 -f png $< $@
    2.38 +
    2.39 +app-manager.ico:	plover-applications16.pnm plover-applications16.pgm \
    2.40 +		plover-applications22.pnm plover-applications22.pgm \
    2.41 +		plover-applications32.pnm plover-applications32.pgm \
    2.42 +		plover-applications46.pnm plover-applications46.pgm
    2.43 +	ppmtowinicon -andpgms -output=$@ $^
    2.44 +
    2.45 +clean-local:
    2.46 +	-rm -rf 24x24 48x48
    2.47  
    2.48  EXTRA_DIST=app-manager.desktop app-manager.ui plover-applications.svg
     3.1 --- a/app-manager/app-manager.c	Sat Feb 20 12:11:02 2010 +0000
     3.2 +++ b/app-manager/app-manager.c	Fri Apr 30 20:37:08 2010 +0100
     3.3 @@ -30,6 +30,169 @@
     3.4  
     3.5  GtkBuilder *ui;
     3.6  GtkTreeModel *installed,*applications,*location,*local_media;
     3.7 +char *prefix=NULL;
     3.8 +struct razor_relocations *relocations=NULL;
     3.9 +
    3.10 +void show_busy_cursor(gboolean busy)
    3.11 +{
    3.12 +    GList *list,*link,*remaining;
    3.13 +    GdkDisplay *display;
    3.14 +    GdkCursor *cursor;
    3.15 +    GtkWidget *w;
    3.16 +    list=gtk_window_list_toplevels();
    3.17 +    while(list)
    3.18 +    {
    3.19 +	w=GTK_WIDGET(list->data);
    3.20 +	if (!w->window)
    3.21 +	{
    3.22 +	    link=list;
    3.23 +	    list=g_slist_remove_link(list,link);
    3.24 +	    g_slist_free_1(link);
    3.25 +	}
    3.26 +	else
    3.27 +	{
    3.28 +	    display=gtk_widget_get_display(w);
    3.29 +	    cursor=busy?gdk_cursor_new_for_display(display,GDK_WATCH):NULL;
    3.30 +	    remaining=NULL;
    3.31 +	    for(link=list;link;link=link->next)
    3.32 +	    {
    3.33 +		w=GTK_WIDGET(link->data);
    3.34 +		if (w->window)
    3.35 +		{
    3.36 +		    if (gtk_widget_get_display(w)==display)
    3.37 +			gdk_window_set_cursor(w->window,cursor);
    3.38 +		    else
    3.39 +			remaining=g_slist_prepend(remaining,w);
    3.40 +		}
    3.41 +	    }
    3.42 +	    gdk_display_flush(display);
    3.43 +	    if (cursor)
    3.44 +		gdk_cursor_unref(cursor);
    3.45 +	    g_list_free(list);
    3.46 +	    list=remaining;
    3.47 +	}
    3.48 +    }
    3.49 +}
    3.50 +
    3.51 +/*
    3.52 + * In Gtk+ 2.16.6, the default handler generates g_warnings on error.
    3.53 + * It should display an error to the user. Do it ourselves.
    3.54 + */
    3.55 +
    3.56 +static void show_uri(GtkLinkButton *button,const gchar *uri,gpointer data)
    3.57 +{
    3.58 +    GdkScreen *screen;
    3.59 +    GtkWidget *dialog;
    3.60 +    GError *error=NULL;
    3.61 +    if (gtk_widget_has_screen(GTK_WIDGET(button)))
    3.62 +	screen=gtk_widget_get_screen(GTK_WIDGET(button));
    3.63 +    else
    3.64 +	screen=NULL;
    3.65 +    gtk_show_uri(screen,uri,GDK_CURRENT_TIME,&error);
    3.66 +    if (error)
    3.67 +    {
    3.68 +	dialog=gtk_message_dialog_new(
    3.69 +	  GTK_WINDOW(gtk_builder_get_object(ui,"MainWindow")),
    3.70 +	  GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
    3.71 +	  "Unable to show '%s'",uri);
    3.72 +	gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
    3.73 +	  error->message);
    3.74 +	g_error_free(error);
    3.75 +	gtk_dialog_run(GTK_DIALOG(dialog));
    3.76 +	gtk_widget_destroy(dialog);
    3.77 +    }
    3.78 +}
    3.79 +
    3.80 +/* Checks whether a loader for SVG files has been registered
    3.81 + * with GdkPixbuf.
    3.82 + */
    3.83 +static gboolean pixbuf_supports_svg(void)
    3.84 +{
    3.85 +    GSList *formats;
    3.86 +    GSList *tmp_list;
    3.87 +    static gint found_svg=-1;
    3.88 +    gchar **mime_types,**mime_type;
    3.89 +    if (found_svg!=-1)
    3.90 +	return found_svg;
    3.91 +    formats=gdk_pixbuf_get_formats();
    3.92 +    found_svg=FALSE;
    3.93 +    for (tmp_list=formats;tmp_list && !found_svg;tmp_list=tmp_list->next)
    3.94 +    {
    3.95 +	mime_types=gdk_pixbuf_format_get_mime_types(tmp_list->data);
    3.96 +	for (mime_type=mime_types;*mime_type && !found_svg;mime_type++)
    3.97 +	    if (!strcmp(*mime_type,"image/svg"))
    3.98 +		found_svg=TRUE;
    3.99 +	g_strfreev(mime_types);
   3.100 +    }
   3.101 +    g_slist_free(formats);
   3.102 +    return found_svg;
   3.103 +}
   3.104 +
   3.105 +static void install_icon_at_size(const char *icon_name,GtkIconSet *icon_set,
   3.106 +  GtkIconSize size,const char *filename)
   3.107 +{
   3.108 +    int w,h;
   3.109 +    GdkPixbuf *pixbuf;
   3.110 +    GtkIconSource *source;
   3.111 +    if (gtk_icon_size_lookup(size,&w,&h))
   3.112 +    {
   3.113 +	pixbuf=gdk_pixbuf_new_from_file_at_size(filename,w,h,NULL);
   3.114 +	if (pixbuf)
   3.115 +	{
   3.116 +	    source=gtk_icon_source_new();
   3.117 +	    gtk_icon_source_set_size_wildcarded(source,FALSE);
   3.118 +	    gtk_icon_source_set_size(source,size);
   3.119 +	    gtk_icon_source_set_pixbuf(source,pixbuf);
   3.120 +	    gtk_icon_set_add_source(icon_set,source);
   3.121 +	    gtk_icon_source_free(source);
   3.122 +	    g_object_unref(pixbuf);
   3.123 +	}
   3.124 +    }
   3.125 +}
   3.126 +
   3.127 +static void install_icons(void)
   3.128 +{
   3.129 +    int w,h;
   3.130 +    gchar *s;
   3.131 +    GdkPixbuf *pixbuf;
   3.132 +    GtkIconSource *source;
   3.133 +    GtkIconSet *icon_set;
   3.134 +    GtkIconFactory *factory;
   3.135 +    factory=gtk_icon_factory_new();
   3.136 +    icon_set=gtk_icon_set_new();
   3.137 +    if (pixbuf_supports_svg())
   3.138 +    {
   3.139 +	source=gtk_icon_source_new();
   3.140 +	s=g_build_filename(prefix?prefix:"/usr",
   3.141 +	  "share/icons/hicolor/scalable/apps/plover-applications.svg",NULL);
   3.142 +	gtk_icon_source_set_filename(source,s);
   3.143 +	g_free(s);
   3.144 +	gtk_icon_set_add_source(icon_set,source);
   3.145 +	gtk_icon_source_free(source);
   3.146 +    }
   3.147 +    else
   3.148 +    {
   3.149 +	s=g_build_filename(prefix?prefix:"/usr",
   3.150 +	  "share/icons/hicolor/24x24/apps/plover-applications.png",NULL);
   3.151 +	install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_MENU,s);
   3.152 +	install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_BUTTON,s);
   3.153 +	install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_SMALL_TOOLBAR,s);
   3.154 +	install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_LARGE_TOOLBAR,s);
   3.155 +	g_free(s);
   3.156 +	s=g_build_filename(prefix?prefix:"/usr",
   3.157 +	  "share/icons/hicolor/48x48/apps/plover-applications.png",NULL);
   3.158 +	install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_DND,s);
   3.159 +	install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_DIALOG,s);
   3.160 +	g_free(s);
   3.161 +    }
   3.162 +    gtk_icon_factory_add(factory,LOGO_NAME,icon_set);
   3.163 +    gtk_icon_set_unref(icon_set);
   3.164 +    icon_set=gtk_icon_factory_lookup(factory,LOGO_NAME);
   3.165 +    gtk_icon_factory_add_default(factory);
   3.166 +    g_object_unref(factory);
   3.167 +    icon_set=gtk_icon_factory_lookup_default(LOGO_NAME);
   3.168 +    gtk_window_set_default_icon_name(LOGO_NAME);
   3.169 +}
   3.170  
   3.171  int main(int argc,char **argv)
   3.172  {
   3.173 @@ -46,13 +209,20 @@
   3.174  	g_printerr("%s",err->message);
   3.175  	exit(0);
   3.176      }
   3.177 -    gtk_window_set_default_icon_name(LOGO_NAME);
   3.178 +#ifdef WIN32
   3.179 +    prefix=g_win32_get_package_installation_directory_of_module(NULL);
   3.180 +#endif
   3.181 +    install_icons();
   3.182      ui=gtk_builder_new();
   3.183      if (!g_file_get_contents("app-manager.ui",&contents,&len,&err) &&
   3.184        g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT))
   3.185      {
   3.186 +#ifdef WIN32
   3.187 +	s=g_build_filename(prefix,"share","plover","app-manager.ui",NULL);
   3.188 +#else
   3.189 +	s=g_build_filename(PLOVER_DATADIR,"app-manager.ui",NULL);
   3.190 +#endif
   3.191  	g_clear_error(&err);
   3.192 -	s=g_build_filename(PLOVER_DATADIR,"app-manager.ui",NULL);
   3.193  	(void)g_file_get_contents(s,&contents,&len,&err);
   3.194  	g_free(s);
   3.195      }
   3.196 @@ -66,15 +236,31 @@
   3.197  	g_error("%s",err->message);
   3.198  	exit(0);
   3.199      }
   3.200 +    if (prefix)
   3.201 +    {
   3.202 +	relocations=razor_relocations_create();
   3.203 +	razor_relocations_add(relocations,"/usr",prefix);
   3.204 +    }
   3.205      gtk_builder_connect_signals(ui,NULL);
   3.206 +    gtk_link_button_set_uri_hook(show_uri,NULL,NULL);
   3.207      installed=GTK_TREE_MODEL(plover_package_store_new());
   3.208      set=plover_package_set_new_from_installed("",NULL);
   3.209      if (set)
   3.210 +    {
   3.211  	plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set);
   3.212 +	if (plover_package_set_get_no_details(set))
   3.213 +	{
   3.214 +	    w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles"));
   3.215 +	    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),TRUE);
   3.216 +	}
   3.217 +    }
   3.218      applications=plover_applications_model_new(installed);
   3.219      set_package_model(applications);
   3.220      gtk_main();
   3.221      g_object_unref(ui);
   3.222 +    if (relocations)
   3.223 +	razor_relocations_destroy(relocations);
   3.224 +    g_free(prefix);
   3.225      exit(0);
   3.226  }
   3.227  
   3.228 @@ -102,7 +288,11 @@
   3.229      if (gtk_toggle_tool_button_get_active(button))
   3.230      {
   3.231  	if (!local_media)
   3.232 +	{
   3.233 +	    show_busy_cursor(TRUE);
   3.234  	    local_media=plover_local_media_store_new();
   3.235 +	    show_busy_cursor(FALSE);
   3.236 +	}
   3.237  	set_package_model(local_media);
   3.238      }
   3.239  }
   3.240 @@ -118,6 +308,9 @@
   3.241  {
   3.242      GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
   3.243      GtkWidget *dialog;
   3.244 +    GFile *file,*parent;
   3.245 +    GFileInfo *fi;
   3.246 +    GMount *mount;
   3.247      gchar *path,*name;
   3.248      PloverPackageSet *set;
   3.249      GSList *sets;
   3.250 @@ -130,8 +323,9 @@
   3.251  #endif
   3.252      if (gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT)
   3.253      {
   3.254 +	show_busy_cursor(TRUE);
   3.255  	path=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
   3.256 -	set=plover_package_set_new_from_repository(path,&err);
   3.257 +	set=plover_package_set_new_from_repository(path,relocations,&err);
   3.258  	if (set)
   3.259  	{
   3.260  	    if (!location)
   3.261 @@ -143,7 +337,34 @@
   3.262  	    plover_package_store_add_set(PLOVER_PACKAGE_STORE(location),set);
   3.263  	    g_object_unref(set);
   3.264  	    w=GTK_WIDGET(gtk_builder_get_object(ui,"LocationButton"));
   3.265 -	    name=g_filename_display_basename(path);
   3.266 +	    file=g_file_new_for_path(path);
   3.267 +	    parent=g_file_get_parent(file);
   3.268 +	    if (parent)
   3.269 +	    {
   3.270 +		g_object_unref(parent);
   3.271 +		mount=NULL;
   3.272 +	    }
   3.273 +	    else
   3.274 +		mount=g_file_find_enclosing_mount(file,NULL,NULL);
   3.275 +	    if (mount)
   3.276 +	    {
   3.277 +		name=g_mount_get_name(mount);
   3.278 +		g_object_unref(mount);
   3.279 +	    }
   3.280 +	    else
   3.281 +	    {
   3.282 +		fi=g_file_query_info(file,
   3.283 +		  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
   3.284 +		  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
   3.285 +		if (fi)
   3.286 +		{
   3.287 +		    name=g_strdup(g_file_info_get_display_name(fi));
   3.288 +		    g_object_unref(fi);
   3.289 +		}
   3.290 +		else
   3.291 +		    name=g_filename_display_basename(path);
   3.292 +		g_object_unref(file);
   3.293 +	    }
   3.294  	    gtk_tool_button_set_label(GTK_TOOL_BUTTON(w),name);
   3.295  	    g_free(name);
   3.296  	    gtk_widget_show(w);
   3.297 @@ -161,15 +382,18 @@
   3.298  	    g_error_free(err);
   3.299  	}
   3.300  	g_free(path);
   3.301 +	show_busy_cursor(FALSE);
   3.302      }
   3.303      gtk_widget_destroy(dialog);
   3.304  }
   3.305  
   3.306  G_MODULE_EXPORT void on_scan_local_media(GtkWidget *widget)
   3.307  {
   3.308 +    show_busy_cursor(TRUE);
   3.309      if (!local_media)
   3.310  	local_media=plover_local_media_store_new();
   3.311      plover_local_media_store_scan(PLOVER_LOCAL_MEDIA_STORE(local_media));
   3.312 +    show_busy_cursor(FALSE);
   3.313  }
   3.314  
   3.315  G_MODULE_EXPORT void on_help_about(GtkWidget *widget)
     4.1 --- a/app-manager/app-manager.h	Sat Feb 20 12:11:02 2010 +0000
     4.2 +++ b/app-manager/app-manager.h	Fri Apr 30 20:37:08 2010 +0100
     4.3 @@ -1,7 +1,9 @@
     4.4 +#include <razor.h>
     4.5  #include <gtk/gtk.h>
     4.6  #include <plover-gtk/package.h>
     4.7  
     4.8  extern GtkBuilder *ui;
     4.9 +extern struct razor_relocations *relocations;
    4.10  GtkTreeModel *plover_applications_model_new(GtkTreeModel *installed);
    4.11  void set_package_model(GtkTreeModel *model);
    4.12  PloverPackage *get_active_package(void);
     5.1 --- a/app-manager/app-manager.ui	Sat Feb 20 12:11:02 2010 +0000
     5.2 +++ b/app-manager/app-manager.ui	Fri Apr 30 20:37:08 2010 +0100
     5.3 @@ -87,7 +87,7 @@
     5.4                      <property name="visible">True</property>
     5.5                      <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     5.6                      <child>
     5.7 -                      <object class="GtkRadioMenuItem" id="menuitem2">
     5.8 +                      <object class="GtkRadioMenuItem" id="ViewFiles">
     5.9                          <property name="visible">True</property>
    5.10                          <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    5.11                          <property name="tooltip_text" translatable="yes">Show a list of files owned by the selected package</property>
    5.12 @@ -105,7 +105,7 @@
    5.13                          <property name="use_underline">True</property>
    5.14                          <property name="active">True</property>
    5.15                          <property name="draw_as_radio">True</property>
    5.16 -                        <property name="group">menuitem2</property>
    5.17 +                        <property name="group">ViewFiles</property>
    5.18                          <signal name="toggled" handler="on_view_details_toggled"/>
    5.19                        </object>
    5.20                      </child>
    5.21 @@ -149,7 +149,7 @@
    5.22              <property name="visible">True</property>
    5.23              <property name="can_focus">True</property>
    5.24              <property name="orientation">vertical</property>
    5.25 -            <property name="position">200</property>
    5.26 +            <property name="position">215</property>
    5.27              <property name="position_set">True</property>
    5.28              <child>
    5.29                <object class="GtkAlignment" id="alignment1">
    5.30 @@ -238,7 +238,7 @@
    5.31                                      <property name="tooltip_text" translatable="yes">Show installed applications</property>
    5.32                                      <property name="label" translatable="yes">_Applications</property>
    5.33                                      <property name="use_underline">True</property>
    5.34 -                                    <property name="icon_name">plover-applications</property>
    5.35 +                                    <property name="stock_id">plover-applications</property>
    5.36                                      <property name="active">True</property>
    5.37                                      <signal name="toggled" handler="on_applications_toggled"/>
    5.38                                    </object>
     6.1 --- a/app-manager/applications.c	Sat Feb 20 12:11:02 2010 +0000
     6.2 +++ b/app-manager/applications.c	Fri Apr 30 20:37:08 2010 +0100
     6.3 @@ -19,21 +19,46 @@
     6.4  #include "config.h"
     6.5  #include <stdlib.h>
     6.6  #include <string.h>
     6.7 +#ifdef WIN32
     6.8 +#include <windows.h>
     6.9 +#endif
    6.10  #include <glib.h>
    6.11  #include <gtk/gtk.h>
    6.12  #include <plover-gtk/packagestore.h>
    6.13  #include "app-manager.h"
    6.14  
    6.15 +#ifdef WIN32
    6.16 +static BOOL CALLBACK plover_applications_visible_callback(HMODULE module,
    6.17 +  const char *type,char *name,long *param)
    6.18 +{
    6.19 +    gboolean *visible=(void *)param;
    6.20 +    if (!IS_INTRESOURCE(name) && !strcmp(name,"MAINICON"))
    6.21 +	*visible=TRUE;
    6.22 +    return !*visible;
    6.23 +}
    6.24 +#endif
    6.25 +
    6.26  static gboolean plover_applications_visible_func(GtkTreeModel *model,
    6.27    GtkTreeIter *iter,gpointer data)
    6.28  {
    6.29      /* Visible if row is non-empty and package contains a .desktop file
    6.30 -     * in /usr/share/applications
    6.31 +     * in /usr/share/applications (UNIX) or package contains a .exe file
    6.32 +     * which has a default application icon (MS-Windows).
    6.33       */
    6.34      PloverPackage *package;
    6.35      GtkTreeModel *file_store;
    6.36      GtkTreeIter fi;
    6.37 -    gchar *name,*dir;
    6.38 +    gchar *name;
    6.39 +#ifdef WIN32
    6.40 +    HMODULE module;
    6.41 +    DWORD flags=
    6.42 +#ifdef LOAD_LIBRARY_AS_IMAGE_RESOURCE
    6.43 +      LOAD_LIBRARY_AS_IMAGE_RESOURCE|
    6.44 +#endif
    6.45 +      LOAD_LIBRARY_AS_DATAFILE;
    6.46 +#else
    6.47 +    gchar *dir;
    6.48 +#endif
    6.49      gboolean visible=FALSE;
    6.50      gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package,-1);
    6.51      if (package)
    6.52 @@ -45,11 +70,27 @@
    6.53  	    {
    6.54  		gtk_tree_model_get(file_store,&fi,
    6.55  		  PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN,&name,-1);
    6.56 +#ifdef WIN32
    6.57 +		if (g_str_has_suffix(name,".exe"))
    6.58 +		{
    6.59 +		    module=LoadLibraryExA(name,NULL,flags);
    6.60 +		    if (module)
    6.61 +		    {
    6.62 +			(void)EnumResourceNamesA(module,RT_ICON,
    6.63 +			  plover_applications_visible_callback,&visible);
    6.64 +			if (!visible)
    6.65 +			    (void)EnumResourceNamesA(module,RT_GROUP_ICON,
    6.66 +			      plover_applications_visible_callback,&visible);
    6.67 +			FreeLibrary(module);
    6.68 +		    }
    6.69 +		}
    6.70 +#else
    6.71  		dir=g_path_get_dirname(name);
    6.72  		if (!strcmp(dir,"/usr/share/applications") &&
    6.73  		  g_str_has_suffix(name,".desktop"))
    6.74  		    visible=TRUE;
    6.75  		g_free(dir);
    6.76 +#endif
    6.77  		g_free(name);
    6.78  	    } while(!visible && gtk_tree_model_iter_next(file_store,&fi));
    6.79  	}
    6.80 @@ -62,7 +103,7 @@
    6.81  {
    6.82      GtkTreeModel *model;
    6.83      model=gtk_tree_model_filter_new(installed,NULL);
    6.84 -    gtk_tree_model_filter_set_visible_func(model,
    6.85 +    gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model),
    6.86        plover_applications_visible_func,NULL,NULL);
    6.87      return model;
    6.88  }
     7.1 --- a/app-manager/localmedia.c	Sat Feb 20 12:11:02 2010 +0000
     7.2 +++ b/app-manager/localmedia.c	Fri Apr 30 20:37:08 2010 +0100
     7.3 @@ -19,10 +19,14 @@
     7.4  #include "config.h"
     7.5  #include <stdlib.h>
     7.6  #include <string.h>
     7.7 +#ifdef WIN32
     7.8 +#include <windows.h>
     7.9 +#endif
    7.10  #include <glib.h>
    7.11  #include <gio/gio.h>
    7.12  #include <gtk/gtk.h>
    7.13  #include <plover-gtk/packagestore.h>
    7.14 +#include "app-manager.h"
    7.15  #include "localmedia.h"
    7.16  
    7.17  G_DEFINE_TYPE(PloverLocalMediaStore,plover_local_media_store,
    7.18 @@ -56,12 +60,37 @@
    7.19  {
    7.20      GFile *root;
    7.21      gchar *path;
    7.22 +#ifdef WIN32
    7.23 +    gunichar2 *path2;
    7.24 +    UINT type;
    7.25 +#endif
    7.26      PloverPackageSet *set;
    7.27      root=g_mount_get_root(mount);
    7.28      path=g_file_get_path(root);
    7.29 +#ifdef WIN32
    7.30      if (path)
    7.31      {
    7.32 -	set=plover_package_set_new_from_repository(path,NULL);
    7.33 +	path2=g_utf8_to_utf16(path,-1,NULL,NULL,NULL);
    7.34 +	if (path2)
    7.35 +	{
    7.36 +	    type=GetDriveTypeW(path2);
    7.37 +	    g_free(path2);
    7.38 +	}
    7.39 +	else
    7.40 +	    type=DRIVE_UNKNOWN;
    7.41 +	if (type!=DRIVE_REMOVABLE && type!=DRIVE_CDROM)
    7.42 +	{
    7.43 +	    gchar *name=g_mount_get_name(mount);
    7.44 +	    g_debug("Skipping non-local mount \"%s\"",name);
    7.45 +	    g_free(name);
    7.46 +	    g_free(path);
    7.47 +	    path=NULL;
    7.48 +	}
    7.49 +    }
    7.50 +#endif
    7.51 +    if (path)
    7.52 +    {
    7.53 +	set=plover_package_set_new_from_repository(path,relocations,NULL);
    7.54  	if (set)
    7.55  	{
    7.56  	    g_object_set_data(G_OBJECT(mount),"plover-local-media-set",set);
    7.57 @@ -94,25 +123,38 @@
    7.58  {
    7.59      GVolume *volume;
    7.60      GMount *mount;
    7.61 -    GList *volumes,*link;
    7.62 -    if (g_drive_has_media(drive))
    7.63 +    GList *volumes,*mounts,*link;
    7.64 +    if (!drive)
    7.65 +	volumes=g_volume_monitor_get_volumes(store->monitor);
    7.66 +    else if (g_drive_has_media(drive))
    7.67 +	volumes=g_drive_get_volumes(drive);
    7.68 +    else
    7.69 +	volumes=NULL;
    7.70 +    for(link=volumes;link;link=link->next)
    7.71      {
    7.72 -	volumes=g_drive_get_volumes(drive);
    7.73 -	for(link=volumes;link;link=link->next)
    7.74 +	volume=G_VOLUME(link->data);
    7.75 +	mount=g_volume_get_mount(volume);
    7.76 +	if (mount)
    7.77  	{
    7.78 -	    volume=G_VOLUME(link->data);
    7.79 -	    mount=g_volume_get_mount(volume);
    7.80 -	    if (mount)
    7.81 -	    {
    7.82 -		local_media_scan_mount(store,mount);
    7.83 -		g_object_unref(mount);
    7.84 -	    }
    7.85 -	    else if (!store->implicit_scan && g_volume_can_mount(volume))
    7.86 -		g_volume_mount(volume,G_MOUNT_MOUNT_NONE,NULL,NULL,
    7.87 -		  local_media_mounted,store);
    7.88 -	    g_object_unref(volume);
    7.89 +	    local_media_scan_mount(store,mount);
    7.90 +	    g_object_unref(mount);
    7.91  	}
    7.92 -	g_list_free(volumes);
    7.93 +	else if (!store->implicit_scan && g_volume_can_mount(volume))
    7.94 +	    g_volume_mount(volume,G_MOUNT_MOUNT_NONE,NULL,NULL,
    7.95 +	      local_media_mounted,store);
    7.96 +	g_object_unref(volume);
    7.97 +    }
    7.98 +    g_list_free(volumes);
    7.99 +    if (!drive)
   7.100 +    {
   7.101 +	mounts=g_volume_monitor_get_mounts(store->monitor);
   7.102 +	for(link=mounts;link;link=link->next)
   7.103 +	{
   7.104 +	    mount=G_MOUNT(link->data);
   7.105 +	    local_media_scan_mount(store,mount);
   7.106 +	    g_object_unref(mount);
   7.107 +	}
   7.108 +	g_list_free(mounts);
   7.109      }
   7.110  }
   7.111  
   7.112 @@ -127,9 +169,15 @@
   7.113  
   7.114  void plover_local_media_store_scan(PloverLocalMediaStore *store)
   7.115  {
   7.116 -    GList *drives,*link;
   7.117 +    GList *sets,*drives,*link;
   7.118      GDrive *drive;
   7.119      g_return_if_fail(PLOVER_IS_LOCAL_MEDIA_STORE(store));
   7.120 +    sets=
   7.121 +      g_slist_copy(plover_package_store_get_sets(PLOVER_PACKAGE_STORE(store)));
   7.122 +    for(link=sets;link;link=link->next)
   7.123 +	plover_package_store_remove_set(PLOVER_PACKAGE_STORE(store),
   7.124 +	  PLOVER_PACKAGE_SET(link->data));
   7.125 +    g_slist_free(sets);
   7.126      drives=g_volume_monitor_get_connected_drives(store->monitor);
   7.127      for(link=drives;link;link=link->next)
   7.128      {
   7.129 @@ -149,6 +197,7 @@
   7.130  	g_object_unref(drive);
   7.131      }
   7.132      g_list_free(drives);
   7.133 +    local_media_scan_drive(store,NULL);
   7.134  }
   7.135  
   7.136  static void local_media_mount_added(GVolumeMonitor *volume_monitor,
     8.1 --- a/app-manager/packagelist.c	Sat Feb 20 12:11:02 2010 +0000
     8.2 +++ b/app-manager/packagelist.c	Fri Apr 30 20:37:08 2010 +0100
     8.3 @@ -75,9 +75,9 @@
     8.4  		if (t)
     8.5  		    t+=3;
     8.6  		if (t)
     8.7 -		    s=strndup(t,strcspn(t,"/"));
     8.8 +		    s=g_strndup(t,strcspn(t,"/"));
     8.9  		else
    8.10 -		    s=strdup(text);
    8.11 +		    s=g_strdup(text);
    8.12  		gtk_button_set_label(GTK_BUTTON(w),s);
    8.13  		g_free(s);
    8.14  	    }
    8.15 @@ -152,10 +152,11 @@
    8.16  {
    8.17      gchar *markup;
    8.18      gchar *summary,*name,*version;
    8.19 +    g_return_if_fail(GTK_IS_TREE_MODEL(model));
    8.20      gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_SUMMARY_COLUMN,&summary,
    8.21        PLOVER_PACKAGE_STORE_NAME_COLUMN,&name,
    8.22        PLOVER_PACKAGE_STORE_VERSION_COLUMN,&version,-1);
    8.23 -    markup=g_strdup_printf("<b>%s</b>\n%s %s",summary,name,version,NULL);
    8.24 +    markup=g_markup_printf_escaped("<b>%s</b>\n%s %s",summary,name,version);
    8.25      g_free(summary);
    8.26      g_free(name);
    8.27      g_free(version);
     9.1 --- a/configure.ac	Sat Feb 20 12:11:02 2010 +0000
     9.2 +++ b/configure.ac	Fri Apr 30 20:37:08 2010 +0100
     9.3 @@ -116,6 +116,7 @@
     9.4  ##################################################
     9.5  # Checks for library functions.
     9.6  ##################################################
     9.7 +AC_CHECK_FUNCS_ONCE([fchdir])
     9.8  
     9.9  ##################################################
    9.10  # Checks for processor independent files.
    10.1 --- a/plover-gtk/Makefile.am	Sat Feb 20 12:11:02 2010 +0000
    10.2 +++ b/plover-gtk/Makefile.am	Fri Apr 30 20:37:08 2010 +0100
    10.3 @@ -1,5 +1,5 @@
    10.4  AM_CFLAGS=-g $(PLOVER_GTK_CFLAGS)
    10.5 -LIBS=$(PLOVER_GTK_LIBS)
    10.6 +LIBS=../plover/libplover.la $(PLOVER_GTK_LIBS)
    10.7  INCLUDES=-I$(top_srcdir)
    10.8  LDFLAGS=-no-undefined -version-info $(PLOVER_GTK_LT_VERSION_INFO)
    10.9  
    11.1 --- a/plover-gtk/package.c	Sat Feb 20 12:11:02 2010 +0000
    11.2 +++ b/plover-gtk/package.c	Fri Apr 30 20:37:08 2010 +0100
    11.3 @@ -20,6 +20,7 @@
    11.4  #include <stdlib.h>
    11.5  #include <string.h>
    11.6  #include <glib-object.h>
    11.7 +#include <gtk/gtk.h>
    11.8  #include <razor.h>
    11.9  #include "plover-gtk/package.h"
   11.10  
   11.11 @@ -83,7 +84,7 @@
   11.12  const char *plover_package_get_name(PloverPackage *package)
   11.13  {
   11.14      PloverPackagePrivate *priv;
   11.15 -    const char *name;
   11.16 +    const char *name=NULL;
   11.17      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.18      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.19      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_NAME,&name,
   11.20 @@ -94,7 +95,7 @@
   11.21  const char *plover_package_get_summary(PloverPackage *package)
   11.22  {
   11.23      PloverPackagePrivate *priv;
   11.24 -    const char *summary;
   11.25 +    const char *summary=NULL;
   11.26      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.27      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.28      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_SUMMARY,&summary,
   11.29 @@ -105,7 +106,7 @@
   11.30  const char *plover_package_get_version(PloverPackage *package)
   11.31  {
   11.32      PloverPackagePrivate *priv;
   11.33 -    const char *version;
   11.34 +    const char *version=NULL;
   11.35      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.36      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.37      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_VERSION,&version,
   11.38 @@ -116,7 +117,7 @@
   11.39  const char *plover_package_get_license(PloverPackage *package)
   11.40  {
   11.41      PloverPackagePrivate *priv;
   11.42 -    const char *license;
   11.43 +    const char *license=NULL;
   11.44      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.45      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.46      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_LICENSE,&license,
   11.47 @@ -127,7 +128,7 @@
   11.48  const char *plover_package_get_arch(PloverPackage *package)
   11.49  {
   11.50      PloverPackagePrivate *priv;
   11.51 -    const char *arch;
   11.52 +    const char *arch=NULL;
   11.53      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.54      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.55      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_ARCH,&arch,
   11.56 @@ -138,7 +139,7 @@
   11.57  const char *plover_package_get_description(PloverPackage *package)
   11.58  {
   11.59      PloverPackagePrivate *priv;
   11.60 -    const char *description;
   11.61 +    const char *description=NULL;
   11.62      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.63      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.64      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_DESCRIPTION,
   11.65 @@ -149,7 +150,7 @@
   11.66  const char *plover_package_get_URL(PloverPackage *package)
   11.67  {
   11.68      PloverPackagePrivate *priv;
   11.69 -    const char *URL;
   11.70 +    const char *URL=NULL;
   11.71      g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   11.72      priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   11.73      razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_URL,&URL,
    12.1 --- a/plover-gtk/packagefilestore.c	Sat Feb 20 12:11:02 2010 +0000
    12.2 +++ b/plover-gtk/packagefilestore.c	Fri Apr 30 20:37:08 2010 +0100
    12.3 @@ -230,6 +230,7 @@
    12.4    plover_package_file_store_new(struct razor_file_iterator *files)
    12.5  {
    12.6      const char *name;
    12.7 +    char *s;
    12.8      GSequenceIter *si;
    12.9      GtkTreeIter ti;
   12.10      GtkTreePath *path;
   12.11 @@ -243,7 +244,11 @@
   12.12      indices=gtk_tree_path_get_indices(path);
   12.13      while(razor_file_iterator_next(files,&name))
   12.14      {
   12.15 -	si=g_sequence_insert_sorted(priv->seq,g_strdup(name),g_strcmp0,NULL);
   12.16 +	s=g_strdup(name);
   12.17 +#ifdef WIN32
   12.18 +	s=g_strdelimit(s,"/",'\\');
   12.19 +#endif
   12.20 +	si=g_sequence_insert_sorted(priv->seq,s,g_strcmp0,NULL);
   12.21  	*indices=g_sequence_iter_get_position(si);
   12.22  	ti.stamp=priv->stamp;
   12.23  	ti.user_data=si;
    13.1 --- a/plover-gtk/packageset.c	Sat Feb 20 12:11:02 2010 +0000
    13.2 +++ b/plover-gtk/packageset.c	Fri Apr 30 20:37:08 2010 +0100
    13.3 @@ -34,6 +34,7 @@
    13.4      struct razor_root *root;
    13.5      struct razor_set *set;
    13.6      GSList *packages;
    13.7 +    int no_details;
    13.8  } PloverPackageSetPrivate;
    13.9  
   13.10  #define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
   13.11 @@ -84,6 +85,9 @@
   13.12  
   13.13  static void plover_package_set_init(PloverPackageSet *set)
   13.14  {
   13.15 +    PloverPackageSetPrivate *priv;
   13.16 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   13.17 +    priv->no_details=-1;
   13.18  }
   13.19  
   13.20  PloverPackageSet *plover_package_set_new(void)
   13.21 @@ -118,27 +122,60 @@
   13.22  }
   13.23  
   13.24  PloverPackageSet *plover_package_set_new_from_repository(const char *base,
   13.25 -  GError **err)
   13.26 +  struct razor_relocations *relocations,GError **err)
   13.27  {
   13.28 +#if HAVE_FCHDIR
   13.29      int fd;
   13.30 +#else
   13.31 +    size_t wd_len;
   13.32 +    char *wd;
   13.33 +#endif
   13.34      gchar *s;
   13.35 +    struct razor_set *reloc;
   13.36      PloverPackageSet *set;
   13.37      PloverPackageSetPrivate *priv;
   13.38      set=plover_package_set_new();
   13.39      priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   13.40 +#if HAVE_FCHDIR
   13.41      fd=open(".",O_RDONLY);
   13.42 +#else
   13.43 +    wd_len=32;
   13.44 +    wd=malloc(wd_len);
   13.45 +    while (!getcwd(wd,wd_len) && errno==ERANGE)
   13.46 +    {
   13.47 +	free(wd);
   13.48 +	wd_len*=2;
   13.49 +	wd=malloc(wd_len);
   13.50 +    }
   13.51 +#endif
   13.52      s=g_build_filename(base,"repodata",NULL);
   13.53      if (chdir(s)<0)
   13.54      {
   13.55  	g_set_error(err,G_FILE_ERROR,g_file_error_from_errno(errno),
   13.56  	  "%s: %s",s,g_strerror(errno));
   13.57  	g_object_unref(set);
   13.58 +#if HAVE_FCHDIR
   13.59 +	close(fd);
   13.60 +#else
   13.61 +	free(wd);
   13.62 +#endif
   13.63  	return NULL;
   13.64      }
   13.65      g_free(s);
   13.66      priv->set=plover_razor_set_create_from_yum("..");
   13.67 +#if HAVE_FCHDIR
   13.68      fchdir(fd);
   13.69      close(fd);
   13.70 +#else
   13.71 +    chdir(wd);
   13.72 +    free(wd);
   13.73 +#endif
   13.74 +    if (priv->set && relocations)
   13.75 +    {
   13.76 +	reloc=plover_relocate_packages(priv->set,base,relocations);
   13.77 +	razor_set_destroy(priv->set);
   13.78 +	priv->set=reloc;
   13.79 +    }
   13.80      if (!priv->set)
   13.81      {
   13.82  	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   13.83 @@ -169,3 +206,44 @@
   13.84      }
   13.85      return priv->packages;
   13.86  }
   13.87 +
   13.88 +/*
   13.89 + * Some versions of razor have a bug which causes all detail strings
   13.90 + * to be discarded. If such a version of razor is used to install or
   13.91 + * update a package, then all the detail strings for the installed
   13.92 + * set will be lost. This function tests for this condition and can
   13.93 + * be used to present something more useful than blank details.
   13.94 + */
   13.95 +
   13.96 +gboolean plover_package_set_get_no_details(PloverPackageSet *set)
   13.97 +{
   13.98 +    PloverPackageSetPrivate *priv;
   13.99 +    PloverPackage *package;
  13.100 +    GSList *packages,*link;
  13.101 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  13.102 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  13.103 +    if (priv->no_details<0)
  13.104 +    {
  13.105 +	packages=plover_package_set_get_packages(set);
  13.106 +	if (packages)
  13.107 +	{
  13.108 +	    priv->no_details=0;
  13.109 +	    for(link=packages;link;link=link->next)
  13.110 +	    {
  13.111 +		package=link->data;
  13.112 +		priv->no_details+=2;
  13.113 +		if (*plover_package_get_summary(package))
  13.114 +		    priv->no_details--;
  13.115 +		if (*plover_package_get_license(package))
  13.116 +		    priv->no_details--;
  13.117 +		if (*plover_package_get_description(package))
  13.118 +		    priv->no_details--;
  13.119 +		if (*plover_package_get_URL(package))
  13.120 +		    priv->no_details--;
  13.121 +	    }
  13.122 +	    if (priv->no_details<0)	/* More than 50% of strings present */
  13.123 +		priv->no_details=0;
  13.124 +	}
  13.125 +    }
  13.126 +    return priv->no_details>0;
  13.127 +}
    14.1 --- a/plover-gtk/packageset.h	Sat Feb 20 12:11:02 2010 +0000
    14.2 +++ b/plover-gtk/packageset.h	Fri Apr 30 20:37:08 2010 +0100
    14.3 @@ -1,6 +1,7 @@
    14.4  #ifndef __PLOVER_PACKAGE_SET_H__
    14.5  #define __PLOVER_PACKAGE_SET_H__
    14.6  
    14.7 +#include <razor.h>
    14.8  #include <glib-object.h>
    14.9  
   14.10  G_BEGIN_DECLS
   14.11 @@ -36,8 +37,9 @@
   14.12  PloverPackageSet *plover_package_set_new_from_installed(const char *root,
   14.13    GError **err);
   14.14  PloverPackageSet *plover_package_set_new_from_repository(const char *base,
   14.15 -  GError **err);
   14.16 +  struct razor_relocations *relocations,GError **err);
   14.17  GSList *plover_package_set_get_packages(PloverPackageSet *set);
   14.18 +gboolean plover_package_set_get_no_details(PloverPackageSet *set);
   14.19  
   14.20  G_END_DECLS
   14.21  
    15.1 --- a/plover-gtk/packagestore.c	Sat Feb 20 12:11:02 2010 +0000
    15.2 +++ b/plover-gtk/packagestore.c	Fri Apr 30 20:37:08 2010 +0100
    15.3 @@ -137,11 +137,12 @@
    15.4  static void plover_package_store_get_value(GtkTreeModel *tree_model,
    15.5    GtkTreeIter *iter,gint column,GValue *value)
    15.6  {
    15.7 +    char *s;
    15.8      PloverPackageStore *store=(PloverPackageStore *)tree_model;
    15.9      PloverPackage *package;
   15.10      g_return_if_fail(column>=0 && column<PLOVER_PACKAGE_STORE_NO_COLUMNS);
   15.11      g_return_if_fail(VALID_ITER(iter,store));
   15.12 -    package=g_sequence_get(iter->user_data);
   15.13 +    package=PLOVER_PACKAGE(g_sequence_get(iter->user_data));
   15.14      g_value_init(value,column_types[column]);
   15.15      switch((PloverPackageStoreColumn)column)
   15.16      {
   15.17 @@ -160,7 +161,16 @@
   15.18  	    g_value_set_string(value,plover_package_get_version(package));
   15.19  	    break;
   15.20  	case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN:
   15.21 -	    g_value_set_string(value,plover_package_get_summary(package));
   15.22 +	    s=plover_package_get_summary(package);
   15.23 +	    if (*s)
   15.24 +		g_value_set_string(value,s);
   15.25 +	    else
   15.26 +	    {
   15.27 +		s=g_strconcat("The ",plover_package_get_name(package),
   15.28 +		  " package",NULL);
   15.29 +		g_value_set_string(value,s);
   15.30 +		g_free(s);
   15.31 +	    }
   15.32  	    break;
   15.33      }
   15.34  }
    16.1 --- a/setup/Makefile.am	Sat Feb 20 12:11:02 2010 +0000
    16.2 +++ b/setup/Makefile.am	Fri Apr 30 20:37:08 2010 +0100
    16.3 @@ -17,6 +17,6 @@
    16.4  	$(WINDRES) resources.rc $@
    16.5  
    16.6  setup.ico:     icon16.pnm icon22.pnm icon32.pnm
    16.7 -        ppmtowinicon -output=$@ $^
    16.8 +	ppmtowinicon -output=$@ $^
    16.9  
   16.10  EXTRA_DIST=icon16.png icon22.png icon32.png
    17.1 --- a/setup/resources.rc.in	Sat Feb 20 12:11:02 2010 +0000
    17.2 +++ b/setup/resources.rc.in	Fri Apr 30 20:37:08 2010 +0100
    17.3 @@ -3,10 +3,10 @@
    17.4  MAINICON ICON "setup.ico"
    17.5  
    17.6  VS_VERSION_INFO VERSIONINFO
    17.7 -    FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_VERS
    17.8 -ION@,0
    17.9 -    PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_V
   17.10 -ERSION@,0
   17.11 +    FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,
   17.12 +      @PLOVER_MICRO_VERSION@,0
   17.13 +    PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,
   17.14 +      @PLOVER_MICRO_VERSION@,0
   17.15      FILEOS VOS__WINDOWS32
   17.16      FILETYPE VFT_APP
   17.17      {
    18.1 --- a/update/Makefile.am	Sat Feb 20 12:11:02 2010 +0000
    18.2 +++ b/update/Makefile.am	Fri Apr 30 20:37:08 2010 +0100
    18.3 @@ -17,6 +17,6 @@
    18.4  	$(WINDRES) resources.rc $@
    18.5  
    18.6  update.ico:     icon16.pnm icon22.pnm icon32.pnm
    18.7 -        ppmtowinicon -output=$@ $^
    18.8 +	ppmtowinicon -output=$@ $^
    18.9  
   18.10  EXTRA_DIST=icon16.png icon22.png icon32.png
    19.1 --- a/update/resources.rc.in	Sat Feb 20 12:11:02 2010 +0000
    19.2 +++ b/update/resources.rc.in	Fri Apr 30 20:37:08 2010 +0100
    19.3 @@ -3,10 +3,10 @@
    19.4  MAINICON ICON "update.ico"
    19.5  
    19.6  VS_VERSION_INFO VERSIONINFO
    19.7 -    FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_VERS
    19.8 -ION@,0
    19.9 -    PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_V
   19.10 -ERSION@,0
   19.11 +    FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,
   19.12 +      @PLOVER_MICRO_VERSION@,0
   19.13 +    PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,
   19.14 +      @PLOVER_MICRO_VERSION@,0
   19.15      FILEOS VOS__WINDOWS32
   19.16      FILETYPE VFT_APP
   19.17      {