From: J. Ali Harlow Date: Fri, 30 Apr 2010 19:37:08 +0000 (+0100) Subject: Port applications manager to win32 X-Git-Tag: 0.3^0 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=f1344019e70655a5cfc562adc4d1e9bd15b9cced;p=plover.git Port applications manager to win32 --- diff --git a/.gitignore b/.gitignore index 5f74325..ecfd2e0 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,9 @@ stamp-h1 *.lo *.la plover/plover.pc +plover-gtk/plover-gtk.pc setup/resources.rc setup/setup update/resources.rc update/update +app-manager/resources.rc diff --git a/app-manager/Makefile.am b/app-manager/Makefile.am index d577425..b73f511 100644 --- a/app-manager/Makefile.am +++ b/app-manager/Makefile.am @@ -13,19 +13,41 @@ desktopdir=$(datadir)/applications desktop_DATA=app-manager.desktop scaleabledir=$(datadir)/icons/hicolor/scalable/apps scaleable_DATA=plover-applications.svg +smallicondir=$(datadir)/icons/hicolor/24x24/apps +smallicon_DATA=24x24/plover-applications.png +bigicondir=$(datadir)/icons/hicolor/48x48/apps +bigicon_DATA=48x48/plover-applications.png .rc.$(OBJEXT): $(WINDRES) $< $@ -resources.$(OBJEXT): plover-applications.ico +resources.$(OBJEXT): app-manager.ico plover-applications%.pnm: plover-applications.svg rsvg -w $* -h $* -f png $< temp.png pngtopnm temp.png | pnmquant 256 > $@ $(RM) temp.png -app-manager.ico: plover-applications16.pnm \ - plover-applications22.pnm plover-applications32.pnm - ppmtowinicon -output=$@ $^ +plover-applications%.pgm: plover-applications.svg + rsvg -w $* -h $* -f png $< temp.png + pngtopnm -alpha temp.png > $@ + $(RM) temp.png + +24x24/plover-applications.png: plover-applications.svg + mkdir -p 24x24 + rsvg -w 24 -h 24 -f png $< $@ + +48x48/plover-applications.png: plover-applications.svg + mkdir -p 48x48 + rsvg -w 48 -h 48 -f png $< $@ + +app-manager.ico: plover-applications16.pnm plover-applications16.pgm \ + plover-applications22.pnm plover-applications22.pgm \ + plover-applications32.pnm plover-applications32.pgm \ + plover-applications46.pnm plover-applications46.pgm + ppmtowinicon -andpgms -output=$@ $^ + +clean-local: + -rm -rf 24x24 48x48 EXTRA_DIST=app-manager.desktop app-manager.ui plover-applications.svg diff --git a/app-manager/app-manager.c b/app-manager/app-manager.c index e897c89..7d42ad6 100644 --- a/app-manager/app-manager.c +++ b/app-manager/app-manager.c @@ -30,6 +30,169 @@ GtkBuilder *ui; GtkTreeModel *installed,*applications,*location,*local_media; +char *prefix=NULL; +struct razor_relocations *relocations=NULL; + +void show_busy_cursor(gboolean busy) +{ + GList *list,*link,*remaining; + GdkDisplay *display; + GdkCursor *cursor; + GtkWidget *w; + list=gtk_window_list_toplevels(); + while(list) + { + w=GTK_WIDGET(list->data); + if (!w->window) + { + link=list; + list=g_slist_remove_link(list,link); + g_slist_free_1(link); + } + else + { + display=gtk_widget_get_display(w); + cursor=busy?gdk_cursor_new_for_display(display,GDK_WATCH):NULL; + remaining=NULL; + for(link=list;link;link=link->next) + { + w=GTK_WIDGET(link->data); + if (w->window) + { + if (gtk_widget_get_display(w)==display) + gdk_window_set_cursor(w->window,cursor); + else + remaining=g_slist_prepend(remaining,w); + } + } + gdk_display_flush(display); + if (cursor) + gdk_cursor_unref(cursor); + g_list_free(list); + list=remaining; + } + } +} + +/* + * In Gtk+ 2.16.6, the default handler generates g_warnings on error. + * It should display an error to the user. Do it ourselves. + */ + +static void show_uri(GtkLinkButton *button,const gchar *uri,gpointer data) +{ + GdkScreen *screen; + GtkWidget *dialog; + GError *error=NULL; + if (gtk_widget_has_screen(GTK_WIDGET(button))) + screen=gtk_widget_get_screen(GTK_WIDGET(button)); + else + screen=NULL; + gtk_show_uri(screen,uri,GDK_CURRENT_TIME,&error); + if (error) + { + dialog=gtk_message_dialog_new( + GTK_WINDOW(gtk_builder_get_object(ui,"MainWindow")), + GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, + "Unable to show '%s'",uri); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + error->message); + g_error_free(error); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } +} + +/* Checks whether a loader for SVG files has been registered + * with GdkPixbuf. + */ +static gboolean pixbuf_supports_svg(void) +{ + GSList *formats; + GSList *tmp_list; + static gint found_svg=-1; + gchar **mime_types,**mime_type; + if (found_svg!=-1) + return found_svg; + formats=gdk_pixbuf_get_formats(); + found_svg=FALSE; + for (tmp_list=formats;tmp_list && !found_svg;tmp_list=tmp_list->next) + { + mime_types=gdk_pixbuf_format_get_mime_types(tmp_list->data); + for (mime_type=mime_types;*mime_type && !found_svg;mime_type++) + if (!strcmp(*mime_type,"image/svg")) + found_svg=TRUE; + g_strfreev(mime_types); + } + g_slist_free(formats); + return found_svg; +} + +static void install_icon_at_size(const char *icon_name,GtkIconSet *icon_set, + GtkIconSize size,const char *filename) +{ + int w,h; + GdkPixbuf *pixbuf; + GtkIconSource *source; + if (gtk_icon_size_lookup(size,&w,&h)) + { + pixbuf=gdk_pixbuf_new_from_file_at_size(filename,w,h,NULL); + if (pixbuf) + { + source=gtk_icon_source_new(); + gtk_icon_source_set_size_wildcarded(source,FALSE); + gtk_icon_source_set_size(source,size); + gtk_icon_source_set_pixbuf(source,pixbuf); + gtk_icon_set_add_source(icon_set,source); + gtk_icon_source_free(source); + g_object_unref(pixbuf); + } + } +} + +static void install_icons(void) +{ + int w,h; + gchar *s; + GdkPixbuf *pixbuf; + GtkIconSource *source; + GtkIconSet *icon_set; + GtkIconFactory *factory; + factory=gtk_icon_factory_new(); + icon_set=gtk_icon_set_new(); + if (pixbuf_supports_svg()) + { + source=gtk_icon_source_new(); + s=g_build_filename(prefix?prefix:"/usr", + "share/icons/hicolor/scalable/apps/plover-applications.svg",NULL); + gtk_icon_source_set_filename(source,s); + g_free(s); + gtk_icon_set_add_source(icon_set,source); + gtk_icon_source_free(source); + } + else + { + s=g_build_filename(prefix?prefix:"/usr", + "share/icons/hicolor/24x24/apps/plover-applications.png",NULL); + install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_MENU,s); + install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_BUTTON,s); + install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_SMALL_TOOLBAR,s); + install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_LARGE_TOOLBAR,s); + g_free(s); + s=g_build_filename(prefix?prefix:"/usr", + "share/icons/hicolor/48x48/apps/plover-applications.png",NULL); + install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_DND,s); + install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_DIALOG,s); + g_free(s); + } + gtk_icon_factory_add(factory,LOGO_NAME,icon_set); + gtk_icon_set_unref(icon_set); + icon_set=gtk_icon_factory_lookup(factory,LOGO_NAME); + gtk_icon_factory_add_default(factory); + g_object_unref(factory); + icon_set=gtk_icon_factory_lookup_default(LOGO_NAME); + gtk_window_set_default_icon_name(LOGO_NAME); +} int main(int argc,char **argv) { @@ -46,13 +209,20 @@ int main(int argc,char **argv) g_printerr("%s",err->message); exit(0); } - gtk_window_set_default_icon_name(LOGO_NAME); +#ifdef WIN32 + prefix=g_win32_get_package_installation_directory_of_module(NULL); +#endif + install_icons(); ui=gtk_builder_new(); if (!g_file_get_contents("app-manager.ui",&contents,&len,&err) && g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT)) { - g_clear_error(&err); +#ifdef WIN32 + s=g_build_filename(prefix,"share","plover","app-manager.ui",NULL); +#else s=g_build_filename(PLOVER_DATADIR,"app-manager.ui",NULL); +#endif + g_clear_error(&err); (void)g_file_get_contents(s,&contents,&len,&err); g_free(s); } @@ -66,15 +236,31 @@ int main(int argc,char **argv) g_error("%s",err->message); exit(0); } + if (prefix) + { + relocations=razor_relocations_create(); + razor_relocations_add(relocations,"/usr",prefix); + } gtk_builder_connect_signals(ui,NULL); + gtk_link_button_set_uri_hook(show_uri,NULL,NULL); installed=GTK_TREE_MODEL(plover_package_store_new()); set=plover_package_set_new_from_installed("",NULL); if (set) + { plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set); + if (plover_package_set_get_no_details(set)) + { + w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles")); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),TRUE); + } + } applications=plover_applications_model_new(installed); set_package_model(applications); gtk_main(); g_object_unref(ui); + if (relocations) + razor_relocations_destroy(relocations); + g_free(prefix); exit(0); } @@ -102,7 +288,11 @@ G_MODULE_EXPORT void if (gtk_toggle_tool_button_get_active(button)) { if (!local_media) + { + show_busy_cursor(TRUE); local_media=plover_local_media_store_new(); + show_busy_cursor(FALSE); + } set_package_model(local_media); } } @@ -118,6 +308,9 @@ G_MODULE_EXPORT void on_open_location(GtkWidget *widget) { GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow")); GtkWidget *dialog; + GFile *file,*parent; + GFileInfo *fi; + GMount *mount; gchar *path,*name; PloverPackageSet *set; GSList *sets; @@ -130,8 +323,9 @@ G_MODULE_EXPORT void on_open_location(GtkWidget *widget) #endif if (gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT) { + show_busy_cursor(TRUE); path=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - set=plover_package_set_new_from_repository(path,&err); + set=plover_package_set_new_from_repository(path,relocations,&err); if (set) { if (!location) @@ -143,7 +337,34 @@ G_MODULE_EXPORT void on_open_location(GtkWidget *widget) plover_package_store_add_set(PLOVER_PACKAGE_STORE(location),set); g_object_unref(set); w=GTK_WIDGET(gtk_builder_get_object(ui,"LocationButton")); - name=g_filename_display_basename(path); + file=g_file_new_for_path(path); + parent=g_file_get_parent(file); + if (parent) + { + g_object_unref(parent); + mount=NULL; + } + else + mount=g_file_find_enclosing_mount(file,NULL,NULL); + if (mount) + { + name=g_mount_get_name(mount); + g_object_unref(mount); + } + else + { + fi=g_file_query_info(file, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL); + if (fi) + { + name=g_strdup(g_file_info_get_display_name(fi)); + g_object_unref(fi); + } + else + name=g_filename_display_basename(path); + g_object_unref(file); + } gtk_tool_button_set_label(GTK_TOOL_BUTTON(w),name); g_free(name); gtk_widget_show(w); @@ -161,15 +382,18 @@ G_MODULE_EXPORT void on_open_location(GtkWidget *widget) g_error_free(err); } g_free(path); + show_busy_cursor(FALSE); } gtk_widget_destroy(dialog); } G_MODULE_EXPORT void on_scan_local_media(GtkWidget *widget) { + show_busy_cursor(TRUE); if (!local_media) local_media=plover_local_media_store_new(); plover_local_media_store_scan(PLOVER_LOCAL_MEDIA_STORE(local_media)); + show_busy_cursor(FALSE); } G_MODULE_EXPORT void on_help_about(GtkWidget *widget) diff --git a/app-manager/app-manager.h b/app-manager/app-manager.h index dca76f9..63f077e 100644 --- a/app-manager/app-manager.h +++ b/app-manager/app-manager.h @@ -1,7 +1,9 @@ +#include #include #include extern GtkBuilder *ui; +extern struct razor_relocations *relocations; GtkTreeModel *plover_applications_model_new(GtkTreeModel *installed); void set_package_model(GtkTreeModel *model); PloverPackage *get_active_package(void); diff --git a/app-manager/app-manager.ui b/app-manager/app-manager.ui index c6b7f6b..be45944 100644 --- a/app-manager/app-manager.ui +++ b/app-manager/app-manager.ui @@ -87,7 +87,7 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Show a list of files owned by the selected package @@ -105,7 +105,7 @@ True True True - menuitem2 + ViewFiles @@ -149,7 +149,7 @@ True True vertical - 200 + 215 True @@ -238,7 +238,7 @@ Show installed applications _Applications True - plover-applications + plover-applications True diff --git a/app-manager/applications.c b/app-manager/applications.c index 6b72505..ceabefc 100644 --- a/app-manager/applications.c +++ b/app-manager/applications.c @@ -19,21 +19,46 @@ #include "config.h" #include #include +#ifdef WIN32 +#include +#endif #include #include #include #include "app-manager.h" +#ifdef WIN32 +static BOOL CALLBACK plover_applications_visible_callback(HMODULE module, + const char *type,char *name,long *param) +{ + gboolean *visible=(void *)param; + if (!IS_INTRESOURCE(name) && !strcmp(name,"MAINICON")) + *visible=TRUE; + return !*visible; +} +#endif + static gboolean plover_applications_visible_func(GtkTreeModel *model, GtkTreeIter *iter,gpointer data) { /* Visible if row is non-empty and package contains a .desktop file - * in /usr/share/applications + * in /usr/share/applications (UNIX) or package contains a .exe file + * which has a default application icon (MS-Windows). */ PloverPackage *package; GtkTreeModel *file_store; GtkTreeIter fi; - gchar *name,*dir; + gchar *name; +#ifdef WIN32 + HMODULE module; + DWORD flags= +#ifdef LOAD_LIBRARY_AS_IMAGE_RESOURCE + LOAD_LIBRARY_AS_IMAGE_RESOURCE| +#endif + LOAD_LIBRARY_AS_DATAFILE; +#else + gchar *dir; +#endif gboolean visible=FALSE; gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package,-1); if (package) @@ -45,11 +70,27 @@ static gboolean plover_applications_visible_func(GtkTreeModel *model, { gtk_tree_model_get(file_store,&fi, PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN,&name,-1); +#ifdef WIN32 + if (g_str_has_suffix(name,".exe")) + { + module=LoadLibraryExA(name,NULL,flags); + if (module) + { + (void)EnumResourceNamesA(module,RT_ICON, + plover_applications_visible_callback,&visible); + if (!visible) + (void)EnumResourceNamesA(module,RT_GROUP_ICON, + plover_applications_visible_callback,&visible); + FreeLibrary(module); + } + } +#else dir=g_path_get_dirname(name); if (!strcmp(dir,"/usr/share/applications") && g_str_has_suffix(name,".desktop")) visible=TRUE; g_free(dir); +#endif g_free(name); } while(!visible && gtk_tree_model_iter_next(file_store,&fi)); } @@ -62,7 +103,7 @@ GtkTreeModel *plover_applications_model_new(GtkTreeModel *installed) { GtkTreeModel *model; model=gtk_tree_model_filter_new(installed,NULL); - gtk_tree_model_filter_set_visible_func(model, + gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model), plover_applications_visible_func,NULL,NULL); return model; } diff --git a/app-manager/localmedia.c b/app-manager/localmedia.c index 9f6a2d8..831bdfe 100644 --- a/app-manager/localmedia.c +++ b/app-manager/localmedia.c @@ -19,10 +19,14 @@ #include "config.h" #include #include +#ifdef WIN32 +#include +#endif #include #include #include #include +#include "app-manager.h" #include "localmedia.h" G_DEFINE_TYPE(PloverLocalMediaStore,plover_local_media_store, @@ -56,12 +60,37 @@ static void local_media_scan_mount(PloverLocalMediaStore *store,GMount *mount) { GFile *root; gchar *path; +#ifdef WIN32 + gunichar2 *path2; + UINT type; +#endif PloverPackageSet *set; root=g_mount_get_root(mount); path=g_file_get_path(root); +#ifdef WIN32 if (path) { - set=plover_package_set_new_from_repository(path,NULL); + path2=g_utf8_to_utf16(path,-1,NULL,NULL,NULL); + if (path2) + { + type=GetDriveTypeW(path2); + g_free(path2); + } + else + type=DRIVE_UNKNOWN; + if (type!=DRIVE_REMOVABLE && type!=DRIVE_CDROM) + { + gchar *name=g_mount_get_name(mount); + g_debug("Skipping non-local mount \"%s\"",name); + g_free(name); + g_free(path); + path=NULL; + } + } +#endif + if (path) + { + set=plover_package_set_new_from_repository(path,relocations,NULL); if (set) { g_object_set_data(G_OBJECT(mount),"plover-local-media-set",set); @@ -94,25 +123,38 @@ static void local_media_scan_drive(PloverLocalMediaStore *store,GDrive *drive) { GVolume *volume; GMount *mount; - GList *volumes,*link; - if (g_drive_has_media(drive)) - { + GList *volumes,*mounts,*link; + if (!drive) + volumes=g_volume_monitor_get_volumes(store->monitor); + else if (g_drive_has_media(drive)) volumes=g_drive_get_volumes(drive); - for(link=volumes;link;link=link->next) + else + volumes=NULL; + for(link=volumes;link;link=link->next) + { + volume=G_VOLUME(link->data); + mount=g_volume_get_mount(volume); + if (mount) { - volume=G_VOLUME(link->data); - mount=g_volume_get_mount(volume); - if (mount) - { - local_media_scan_mount(store,mount); - g_object_unref(mount); - } - else if (!store->implicit_scan && g_volume_can_mount(volume)) - g_volume_mount(volume,G_MOUNT_MOUNT_NONE,NULL,NULL, - local_media_mounted,store); - g_object_unref(volume); + local_media_scan_mount(store,mount); + g_object_unref(mount); + } + else if (!store->implicit_scan && g_volume_can_mount(volume)) + g_volume_mount(volume,G_MOUNT_MOUNT_NONE,NULL,NULL, + local_media_mounted,store); + g_object_unref(volume); + } + g_list_free(volumes); + if (!drive) + { + mounts=g_volume_monitor_get_mounts(store->monitor); + for(link=mounts;link;link=link->next) + { + mount=G_MOUNT(link->data); + local_media_scan_mount(store,mount); + g_object_unref(mount); } - g_list_free(volumes); + g_list_free(mounts); } } @@ -127,9 +169,15 @@ static void local_media_polled(GObject *source,GAsyncResult *res,gpointer data) void plover_local_media_store_scan(PloverLocalMediaStore *store) { - GList *drives,*link; + GList *sets,*drives,*link; GDrive *drive; g_return_if_fail(PLOVER_IS_LOCAL_MEDIA_STORE(store)); + sets= + g_slist_copy(plover_package_store_get_sets(PLOVER_PACKAGE_STORE(store))); + for(link=sets;link;link=link->next) + plover_package_store_remove_set(PLOVER_PACKAGE_STORE(store), + PLOVER_PACKAGE_SET(link->data)); + g_slist_free(sets); drives=g_volume_monitor_get_connected_drives(store->monitor); for(link=drives;link;link=link->next) { @@ -149,6 +197,7 @@ void plover_local_media_store_scan(PloverLocalMediaStore *store) g_object_unref(drive); } g_list_free(drives); + local_media_scan_drive(store,NULL); } static void local_media_mount_added(GVolumeMonitor *volume_monitor, diff --git a/app-manager/packagelist.c b/app-manager/packagelist.c index 6425f95..988c7e3 100644 --- a/app-manager/packagelist.c +++ b/app-manager/packagelist.c @@ -75,9 +75,9 @@ void package_present(PloverPackage *package) if (t) t+=3; if (t) - s=strndup(t,strcspn(t,"/")); + s=g_strndup(t,strcspn(t,"/")); else - s=strdup(text); + s=g_strdup(text); gtk_button_set_label(GTK_BUTTON(w),s); g_free(s); } @@ -152,10 +152,11 @@ static void package_cell_data_func(GtkTreeViewColumn *column, { gchar *markup; gchar *summary,*name,*version; + g_return_if_fail(GTK_IS_TREE_MODEL(model)); gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_SUMMARY_COLUMN,&summary, PLOVER_PACKAGE_STORE_NAME_COLUMN,&name, PLOVER_PACKAGE_STORE_VERSION_COLUMN,&version,-1); - markup=g_strdup_printf("%s\n%s %s",summary,name,version,NULL); + markup=g_markup_printf_escaped("%s\n%s %s",summary,name,version); g_free(summary); g_free(name); g_free(version); diff --git a/configure.ac b/configure.ac index 854481e..4c1367e 100644 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,7 @@ LIBS="$save_LIBS" ################################################## # Checks for library functions. ################################################## +AC_CHECK_FUNCS_ONCE([fchdir]) ################################################## # Checks for processor independent files. diff --git a/plover-gtk/Makefile.am b/plover-gtk/Makefile.am index 4d41f41..ab6554e 100644 --- a/plover-gtk/Makefile.am +++ b/plover-gtk/Makefile.am @@ -1,5 +1,5 @@ AM_CFLAGS=-g $(PLOVER_GTK_CFLAGS) -LIBS=$(PLOVER_GTK_LIBS) +LIBS=../plover/libplover.la $(PLOVER_GTK_LIBS) INCLUDES=-I$(top_srcdir) LDFLAGS=-no-undefined -version-info $(PLOVER_GTK_LT_VERSION_INFO) diff --git a/plover-gtk/package.c b/plover-gtk/package.c index e3ea09e..96c8a73 100644 --- a/plover-gtk/package.c +++ b/plover-gtk/package.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "plover-gtk/package.h" @@ -83,7 +84,7 @@ PloverPackage *plover_package_new(struct razor_set *set, const char *plover_package_get_name(PloverPackage *package) { PloverPackagePrivate *priv; - const char *name; + const char *name=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_NAME,&name, @@ -94,7 +95,7 @@ const char *plover_package_get_name(PloverPackage *package) const char *plover_package_get_summary(PloverPackage *package) { PloverPackagePrivate *priv; - const char *summary; + const char *summary=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_SUMMARY,&summary, @@ -105,7 +106,7 @@ const char *plover_package_get_summary(PloverPackage *package) const char *plover_package_get_version(PloverPackage *package) { PloverPackagePrivate *priv; - const char *version; + const char *version=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_VERSION,&version, @@ -116,7 +117,7 @@ const char *plover_package_get_version(PloverPackage *package) const char *plover_package_get_license(PloverPackage *package) { PloverPackagePrivate *priv; - const char *license; + const char *license=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_LICENSE,&license, @@ -127,7 +128,7 @@ const char *plover_package_get_license(PloverPackage *package) const char *plover_package_get_arch(PloverPackage *package) { PloverPackagePrivate *priv; - const char *arch; + const char *arch=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_ARCH,&arch, @@ -138,7 +139,7 @@ const char *plover_package_get_arch(PloverPackage *package) const char *plover_package_get_description(PloverPackage *package) { PloverPackagePrivate *priv; - const char *description; + const char *description=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_DESCRIPTION, @@ -149,7 +150,7 @@ const char *plover_package_get_description(PloverPackage *package) const char *plover_package_get_URL(PloverPackage *package) { PloverPackagePrivate *priv; - const char *URL; + const char *URL=NULL; g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); priv=PLOVER_PACKAGE_GET_PRIVATE(package); razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_URL,&URL, diff --git a/plover-gtk/packagefilestore.c b/plover-gtk/packagefilestore.c index d119555..9250c0c 100644 --- a/plover-gtk/packagefilestore.c +++ b/plover-gtk/packagefilestore.c @@ -230,6 +230,7 @@ PloverPackageFileStore * plover_package_file_store_new(struct razor_file_iterator *files) { const char *name; + char *s; GSequenceIter *si; GtkTreeIter ti; GtkTreePath *path; @@ -243,7 +244,11 @@ PloverPackageFileStore * indices=gtk_tree_path_get_indices(path); while(razor_file_iterator_next(files,&name)) { - si=g_sequence_insert_sorted(priv->seq,g_strdup(name),g_strcmp0,NULL); + s=g_strdup(name); +#ifdef WIN32 + s=g_strdelimit(s,"/",'\\'); +#endif + si=g_sequence_insert_sorted(priv->seq,s,g_strcmp0,NULL); *indices=g_sequence_iter_get_position(si); ti.stamp=priv->stamp; ti.user_data=si; diff --git a/plover-gtk/packageset.c b/plover-gtk/packageset.c index 29b65aa..ceb009f 100644 --- a/plover-gtk/packageset.c +++ b/plover-gtk/packageset.c @@ -34,6 +34,7 @@ typedef struct _PloverPackageSetPrivate { struct razor_root *root; struct razor_set *set; GSList *packages; + int no_details; } PloverPackageSetPrivate; #define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\ @@ -84,6 +85,9 @@ static void plover_package_set_class_init(PloverPackageSetClass *klass) static void plover_package_set_init(PloverPackageSet *set) { + PloverPackageSetPrivate *priv; + priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set); + priv->no_details=-1; } PloverPackageSet *plover_package_set_new(void) @@ -118,27 +122,60 @@ PloverPackageSet *plover_package_set_new_from_installed(const char *root, } PloverPackageSet *plover_package_set_new_from_repository(const char *base, - GError **err) + struct razor_relocations *relocations,GError **err) { +#if HAVE_FCHDIR int fd; +#else + size_t wd_len; + char *wd; +#endif gchar *s; + struct razor_set *reloc; PloverPackageSet *set; PloverPackageSetPrivate *priv; set=plover_package_set_new(); priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set); +#if HAVE_FCHDIR fd=open(".",O_RDONLY); +#else + wd_len=32; + wd=malloc(wd_len); + while (!getcwd(wd,wd_len) && errno==ERANGE) + { + free(wd); + wd_len*=2; + wd=malloc(wd_len); + } +#endif s=g_build_filename(base,"repodata",NULL); if (chdir(s)<0) { g_set_error(err,G_FILE_ERROR,g_file_error_from_errno(errno), "%s: %s",s,g_strerror(errno)); g_object_unref(set); +#if HAVE_FCHDIR + close(fd); +#else + free(wd); +#endif return NULL; } g_free(s); priv->set=plover_razor_set_create_from_yum(".."); +#if HAVE_FCHDIR fchdir(fd); close(fd); +#else + chdir(wd); + free(wd); +#endif + if (priv->set && relocations) + { + reloc=plover_relocate_packages(priv->set,base,relocations); + razor_set_destroy(priv->set); + priv->set=reloc; + } if (!priv->set) { g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED, @@ -169,3 +206,44 @@ GSList *plover_package_set_get_packages(PloverPackageSet *set) } return priv->packages; } + +/* + * Some versions of razor have a bug which causes all detail strings + * to be discarded. If such a version of razor is used to install or + * update a package, then all the detail strings for the installed + * set will be lost. This function tests for this condition and can + * be used to present something more useful than blank details. + */ + +gboolean plover_package_set_get_no_details(PloverPackageSet *set) +{ + PloverPackageSetPrivate *priv; + PloverPackage *package; + GSList *packages,*link; + g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE); + priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set); + if (priv->no_details<0) + { + packages=plover_package_set_get_packages(set); + if (packages) + { + priv->no_details=0; + for(link=packages;link;link=link->next) + { + package=link->data; + priv->no_details+=2; + if (*plover_package_get_summary(package)) + priv->no_details--; + if (*plover_package_get_license(package)) + priv->no_details--; + if (*plover_package_get_description(package)) + priv->no_details--; + if (*plover_package_get_URL(package)) + priv->no_details--; + } + if (priv->no_details<0) /* More than 50% of strings present */ + priv->no_details=0; + } + } + return priv->no_details>0; +} diff --git a/plover-gtk/packageset.h b/plover-gtk/packageset.h index e3e8ecf..66c0529 100644 --- a/plover-gtk/packageset.h +++ b/plover-gtk/packageset.h @@ -1,6 +1,7 @@ #ifndef __PLOVER_PACKAGE_SET_H__ #define __PLOVER_PACKAGE_SET_H__ +#include #include G_BEGIN_DECLS @@ -36,8 +37,9 @@ PloverPackageSet *plover_package_set_new(void); PloverPackageSet *plover_package_set_new_from_installed(const char *root, GError **err); PloverPackageSet *plover_package_set_new_from_repository(const char *base, - GError **err); + struct razor_relocations *relocations,GError **err); GSList *plover_package_set_get_packages(PloverPackageSet *set); +gboolean plover_package_set_get_no_details(PloverPackageSet *set); G_END_DECLS diff --git a/plover-gtk/packagestore.c b/plover-gtk/packagestore.c index 408964c..1be7576 100644 --- a/plover-gtk/packagestore.c +++ b/plover-gtk/packagestore.c @@ -137,11 +137,12 @@ static GtkTreePath * static void plover_package_store_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter,gint column,GValue *value) { + char *s; PloverPackageStore *store=(PloverPackageStore *)tree_model; PloverPackage *package; g_return_if_fail(column>=0 && columnuser_data); + package=PLOVER_PACKAGE(g_sequence_get(iter->user_data)); g_value_init(value,column_types[column]); switch((PloverPackageStoreColumn)column) { @@ -160,7 +161,16 @@ static void plover_package_store_get_value(GtkTreeModel *tree_model, g_value_set_string(value,plover_package_get_version(package)); break; case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN: - g_value_set_string(value,plover_package_get_summary(package)); + s=plover_package_get_summary(package); + if (*s) + g_value_set_string(value,s); + else + { + s=g_strconcat("The ",plover_package_get_name(package), + " package",NULL); + g_value_set_string(value,s); + g_free(s); + } break; } } diff --git a/setup/Makefile.am b/setup/Makefile.am index 78c729a..f1c4d68 100644 --- a/setup/Makefile.am +++ b/setup/Makefile.am @@ -17,6 +17,6 @@ resources.$(OBJEXT): resources.rc setup.ico $(WINDRES) resources.rc $@ setup.ico: icon16.pnm icon22.pnm icon32.pnm - ppmtowinicon -output=$@ $^ + ppmtowinicon -output=$@ $^ EXTRA_DIST=icon16.png icon22.png icon32.png diff --git a/setup/resources.rc.in b/setup/resources.rc.in index 51a31cf..895d9f7 100644 --- a/setup/resources.rc.in +++ b/setup/resources.rc.in @@ -3,10 +3,10 @@ MAINICON ICON "setup.ico" VS_VERSION_INFO VERSIONINFO - FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_VERS -ION@,0 - PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_V -ERSION@,0 + FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@, + @PLOVER_MICRO_VERSION@,0 + PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@, + @PLOVER_MICRO_VERSION@,0 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { diff --git a/update/Makefile.am b/update/Makefile.am index c39f6de..0f721c2 100644 --- a/update/Makefile.am +++ b/update/Makefile.am @@ -17,6 +17,6 @@ resources.$(OBJEXT): resources.rc update.ico $(WINDRES) resources.rc $@ update.ico: icon16.pnm icon22.pnm icon32.pnm - ppmtowinicon -output=$@ $^ + ppmtowinicon -output=$@ $^ EXTRA_DIST=icon16.png icon22.png icon32.png diff --git a/update/resources.rc.in b/update/resources.rc.in index ea31644..b11aecb 100644 --- a/update/resources.rc.in +++ b/update/resources.rc.in @@ -3,10 +3,10 @@ MAINICON ICON "update.ico" VS_VERSION_INFO VERSIONINFO - FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_VERS -ION@,0 - PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_V -ERSION@,0 + FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@, + @PLOVER_MICRO_VERSION@,0 + PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@, + @PLOVER_MICRO_VERSION@,0 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP {