Support parallel installations. The idea is that for CAD screener, we want
to be able to install this on the same machine as a standard AVOT setup
(most notably for John's laptop). To allow for the possibility of a second
application that might have the same requirements, we add the concept of
vendor-specific distributions. Thus we can have one distribution for CAD
screener and one for The Next Big Thing. It doesn't seem trivial to have
both CAD screener and AVOT under the same vendor tag so we'll have to have
AVOT under "City Occupational" and CAD screener under "City Occupational Ltd"
or some such kludge.
Most of this is done although we are very short of test cases (in particular
we don't test that it's actually possible to install CAD screener in parallel
with AVOT or to update either of them once installed, which is fundamental).
We also have a lot of baggage left over, including an intercept of razor_set.
The problem that this was introduced to debug has been fixed but it looks
like there are a number of memory leaks which it might be useful to help
track down so it has been left in place for now.
There is still a lot of confusion in plover between path-based and URI-based
API. We should review the API, decide what we want and have a general clear up.
There is also confusion as to the purpose of RAZOR_ROOT (and meaning; path or
URI). This is not used at all in librazor (although it is used in razor.exe).
Ideally we shouldn't use it in plover or plover-gtk either although again, we
might want to support it or an equivalent in (some of) the various executables.
Work that would still to nice to do for CAD screener:
- uninstall (ideally as an installed program that hooks into Add/Remove programs
but even re-running the installer would be acceptable).
- xz support (smaller packages).
- repomd.xml and xml:base (would be needed for an Internet installer).
- graphical installer.
2 * Copyright (C) 2010 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <whelk/whelk.h>
30 #include <plover/plover.h>
31 #include <plover/packageset.h>
32 #include <plover-gtk/stockicons.h>
33 #include "app-manager.h"
34 #include "localmedia.h"
36 LUALIB_API int luaopen_posix(lua_State *L);
38 #define LOGO_NAME "plover-applications"
41 GtkTreeModel *installed,*applications,*location,*local_media;
43 struct razor_relocations *relocations=NULL;
45 void show_busy_cursor(gboolean busy)
47 GList *list,*link,*remaining;
51 list=gtk_window_list_toplevels();
54 w=GTK_WIDGET(list->data);
58 list=g_list_remove_link(list,link);
63 display=gtk_widget_get_display(w);
64 cursor=busy?gdk_cursor_new_for_display(display,GDK_WATCH):NULL;
66 for(link=list;link;link=link->next)
68 w=GTK_WIDGET(link->data);
71 if (gtk_widget_get_display(w)==display)
72 gdk_window_set_cursor(w->window,cursor);
74 remaining=g_list_prepend(remaining,w);
77 gdk_display_flush(display);
79 gdk_cursor_unref(cursor);
87 * In Gtk+ 2.16.6, the default handler generates g_warnings on error.
88 * It should display an error to the user. Do it ourselves.
91 static void show_uri(GtkLinkButton *button,const gchar *uri,gpointer data)
96 if (gtk_widget_has_screen(GTK_WIDGET(button)))
97 screen=gtk_widget_get_screen(GTK_WIDGET(button));
100 gtk_show_uri(screen,uri,GDK_CURRENT_TIME,&error);
103 dialog=gtk_message_dialog_new(
104 GTK_WINDOW(gtk_builder_get_object(ui,"MainWindow")),
105 GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
106 "Unable to show '%s'",uri);
107 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
110 gtk_dialog_run(GTK_DIALOG(dialog));
111 gtk_widget_destroy(dialog);
116 /* Checks whether a loader for SVG files has been registered
119 static gboolean pixbuf_supports_svg(void)
123 static gint found_svg=-1;
124 gchar **mime_types,**mime_type;
127 formats=gdk_pixbuf_get_formats();
129 for (tmp_list=formats;tmp_list && !found_svg;tmp_list=tmp_list->next)
131 mime_types=gdk_pixbuf_format_get_mime_types(tmp_list->data);
132 for (mime_type=mime_types;*mime_type && !found_svg;mime_type++)
133 if (!strcmp(*mime_type,"image/svg"))
135 g_strfreev(mime_types);
137 g_slist_free(formats);
141 static void install_icon_at_size(const char *icon_name,GtkIconSet *icon_set,
142 GtkIconSize size,const char *filename)
146 GtkIconSource *source;
147 if (gtk_icon_size_lookup(size,&w,&h))
149 pixbuf=gdk_pixbuf_new_from_file_at_size(filename,w,h,NULL);
152 source=gtk_icon_source_new();
153 gtk_icon_source_set_size_wildcarded(source,FALSE);
154 gtk_icon_source_set_size(source,size);
155 gtk_icon_source_set_pixbuf(source,pixbuf);
156 gtk_icon_set_add_source(icon_set,source);
157 gtk_icon_source_free(source);
158 g_object_unref(pixbuf);
163 static void install_icons(void)
166 GtkIconSource *source;
167 GtkIconSet *icon_set;
168 GtkIconFactory *factory;
169 factory=gtk_icon_factory_new();
170 icon_set=gtk_icon_set_new();
171 if (pixbuf_supports_svg())
173 source=gtk_icon_source_new();
174 s=g_build_filename(prefix?prefix:"/usr",
175 "share/icons/hicolor/scalable/apps/plover-applications.svg",NULL);
176 gtk_icon_source_set_filename(source,s);
178 gtk_icon_set_add_source(icon_set,source);
179 gtk_icon_source_free(source);
183 s=g_build_filename(prefix?prefix:"/usr",
184 "share/icons/hicolor/24x24/apps/plover-applications.png",NULL);
185 install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_MENU,s);
186 install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_BUTTON,s);
187 install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_SMALL_TOOLBAR,s);
188 install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_LARGE_TOOLBAR,s);
190 s=g_build_filename(prefix?prefix:"/usr",
191 "share/icons/hicolor/48x48/apps/plover-applications.png",NULL);
192 install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_DND,s);
193 install_icon_at_size(LOGO_NAME,icon_set,GTK_ICON_SIZE_DIALOG,s);
196 gtk_icon_factory_add(factory,LOGO_NAME,icon_set);
197 gtk_icon_set_unref(icon_set);
198 icon_set=gtk_icon_factory_lookup(factory,LOGO_NAME);
199 gtk_icon_factory_add_default(factory);
200 g_object_unref(factory);
201 icon_set=gtk_icon_factory_lookup_default(LOGO_NAME);
202 gtk_window_set_default_icon_name(LOGO_NAME);
206 static void install_icons(void)
208 GtkIconSet *icon_set;
209 plover_icons_add_to_stock("apps",LOGO_NAME);
210 icon_set=gtk_icon_factory_lookup_default(LOGO_NAME);
211 gtk_window_set_default_icon_name(LOGO_NAME);
214 int main(int argc,char **argv)
218 gchar *s,*database_uri,*contents;
219 gchar *database=NULL,*setup_base=NULL,*update_base=NULL;
222 PloverPackageSet *set=NULL;
223 GSList *objects,*lnk;
225 GOptionEntry options[]={
226 {"database",0,0,G_OPTION_ARG_STRING,&database,
227 "Operate on a distribution-local database","vendor/distribution"},
228 {"setup",0,0,G_OPTION_ARG_STRING,&setup_base,
229 "Setup from installation media","uri"},
230 {"update",0,0,G_OPTION_ARG_STRING,&update_base,
231 "Update from upgrade media","uri"},
236 * app-manager is normally a GUI application, but rpm scripts may well
237 * call console applications and it looks ugly if console windows keep
238 * popping up. Avoid this by allocating our own console and hiding it.
240 * - If app-manager is a console application (typically for debugging),
241 * then skip this step.
242 * - Call ShowWindow twice to negate special handling on first call.
244 if (!GetConsoleWindow())
247 ShowWindow(GetConsoleWindow(),SW_HIDE);
248 ShowWindow(GetConsoleWindow(),SW_HIDE);
251 plover_exception_handler_init();
252 razor_set_lua_loader("posix",(void (*)())luaopen_posix);
253 razor_set_lua_loader("whelk",(void (*)())luaopen_whelk);
254 if (!gtk_init_with_args(&argc,&argv,NULL,options,NULL,&err))
256 g_printerr("%s\n",err->message);
259 if (setup_base && update_base)
261 g_printerr("--setup and --update are mutually exclusive\n");
265 prefix=g_win32_get_package_installation_directory_of_module(NULL);
268 ui=gtk_builder_new();
269 if (!g_file_get_contents("app-manager.ui",&contents,&len,&err) &&
270 g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT))
273 s=g_build_filename(prefix,"share","plover","app-manager.ui",NULL);
275 s=g_build_filename(PLOVER_DATADIR,"app-manager.ui",NULL);
278 (void)g_file_get_contents(s,&contents,&len,&err);
283 (void)gtk_builder_add_from_string(ui,contents,len,&err);
288 g_error("%s",err->message);
291 gtk_builder_connect_signals(ui,NULL);
292 gtk_link_button_set_uri_hook(show_uri,NULL,NULL);
294 started=setup(setup_base);
295 else if (update_base)
296 started=update(update_base);
303 s=strchr(database,'/');
306 comps=plover_comps_new();
307 plover_comps_set_vendor(comps,database);
310 plover_comps_set_distribution(comps,s);
313 prefix=plover_comps_get_default_prefix(comps);
314 plover_comps_free(comps);
315 s=g_strconcat(prefix,"/var/lib/razor",NULL);
316 database_uri=razor_path_to_uri(s);
318 razor_set_database_uri(database_uri);
319 g_free(database_uri);
323 relocations=razor_relocations_create();
324 razor_relocations_add(relocations,"/usr",prefix);
326 installed=GTK_TREE_MODEL(plover_package_store_new());
327 set=plover_package_set_new();
328 (void)plover_package_set_open(set,"",TRUE,NULL);
329 plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set);
330 if (plover_package_set_get_no_details(set))
332 w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles"));
333 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),TRUE);
335 applications=plover_applications_model_new(installed);
336 set_package_model(applications);
337 w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
343 g_clear_object(&set);
344 objects=gtk_builder_get_objects(ui);
345 for(lnk=objects;lnk;lnk=lnk->next)
346 if (GTK_IS_WIDGET(lnk->data) &&
347 gtk_widget_is_toplevel(GTK_WIDGET(lnk->data)))
348 gtk_widget_destroy(GTK_WIDGET(lnk->data));
349 g_slist_free(objects);
351 g_clear_object(&installed);
352 g_clear_object(&applications);
353 g_clear_object(&location);
354 g_clear_object(&local_media);
356 razor_relocations_destroy(relocations);
365 on_applications_toggled(GtkToggleToolButton *button,gpointer data)
367 if (gtk_toggle_tool_button_get_active(button))
370 applications=plover_applications_model_new(installed);
371 set_package_model(applications);
376 on_all_packages_toggled(GtkToggleToolButton *button,gpointer data)
378 if (gtk_toggle_tool_button_get_active(button))
379 set_package_model(installed);
383 on_local_media_toggled(GtkToggleToolButton *button,gpointer data)
385 if (gtk_toggle_tool_button_get_active(button))
389 show_busy_cursor(TRUE);
390 local_media=plover_local_media_store_new();
391 show_busy_cursor(FALSE);
393 set_package_model(local_media);
398 on_location_toggled(GtkToggleToolButton *button,gpointer data)
400 if (gtk_toggle_tool_button_get_active(button))
401 set_package_model(location);
404 G_MODULE_EXPORT void on_open_location(GtkWidget *widget)
406 GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
412 PloverPackageSet *set;
415 dialog=gtk_file_chooser_dialog_new("Open Location",GTK_WINDOW(w),
416 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,GTK_STOCK_CANCEL,
417 GTK_RESPONSE_CANCEL,GTK_STOCK_OPEN,GTK_RESPONSE_ACCEPT,NULL);
418 #if GTK_CHECK_VERSION(2,18,0)
419 gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dialog),FALSE);
421 if (gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT)
423 show_busy_cursor(TRUE);
424 path=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
425 set=plover_package_set_new_from_yum(path,relocations,&err);
429 location=GTK_TREE_MODEL(plover_package_store_new());
431 plover_package_store_get_sets(PLOVER_PACKAGE_STORE(location))))
432 plover_package_store_remove_set(PLOVER_PACKAGE_STORE(location),
433 PLOVER_PACKAGE_SET(sets->data));
434 plover_package_store_add_set(PLOVER_PACKAGE_STORE(location),set);
436 w=GTK_WIDGET(gtk_builder_get_object(ui,"LocationButton"));
437 file=g_file_new_for_path(path);
438 parent=g_file_get_parent(file);
441 g_object_unref(parent);
445 mount=g_file_find_enclosing_mount(file,NULL,NULL);
448 name=g_mount_get_name(mount);
449 g_object_unref(mount);
453 fi=g_file_query_info(file,
454 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
455 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
458 name=g_strdup(g_file_info_get_display_name(fi));
462 name=g_filename_display_basename(path);
463 g_object_unref(file);
465 gtk_tool_button_set_label(GTK_TOOL_BUTTON(w),name);
468 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w),TRUE);
472 gtk_widget_destroy(dialog);
473 dialog=gtk_message_dialog_new(GTK_WINDOW(w),
474 GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,
475 GTK_BUTTONS_CLOSE,"Error loading repository '%s'",path);
476 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
478 gtk_dialog_run(GTK_DIALOG(dialog));
482 show_busy_cursor(FALSE);
484 gtk_widget_destroy(dialog);
487 G_MODULE_EXPORT void on_scan_local_media(GtkWidget *widget)
489 show_busy_cursor(TRUE);
491 local_media=plover_local_media_store_new();
492 plover_local_media_store_scan(PLOVER_LOCAL_MEDIA_STORE(local_media));
493 show_busy_cursor(FALSE);
496 G_MODULE_EXPORT void on_help_about(GtkWidget *widget)
498 GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
499 gtk_show_about_dialog(GTK_WINDOW(w),"name",PACKAGE_NAME,
500 "version",PACKAGE_VERSION,"comments","Application Manager",
501 "copyright","Copyright © 2010, 2014 J. Ali Harlow",
502 "logo-icon-name",LOGO_NAME,
506 G_MODULE_EXPORT void on_find_clicked(GtkButton *button)
509 GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"SearchEntry"));
510 text=g_strdup(gtk_entry_get_text(GTK_ENTRY(w)));
511 gtk_entry_set_text(GTK_ENTRY(w),"");
512 gtk_entry_set_text(GTK_ENTRY(w),text);