Changeset 2348
- Timestamp:
- 06/06/07 05:19:13 (2 years ago)
- Files:
-
- frontend/trunk/manager/ChangeLog (modified) (1 diff)
- frontend/trunk/manager/frontend-gtk/Makefile.am (modified) (1 diff)
- frontend/trunk/manager/frontend-gtk/gui_cb.c (copied) (copied from frontend/branches/fix-root-uninstall/manager/frontend-gtk/gui_cb.c)
- frontend/trunk/manager/frontend-gtk/main.c (modified) (16 diffs)
- frontend/trunk/manager/frontend-gtk/manager-gtk.glade (modified) (1 diff)
- frontend/trunk/manager/frontend-gtk/manager-gtk.h (copied) (copied from frontend/branches/fix-root-uninstall/manager/frontend-gtk/manager-gtk.h)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
frontend/trunk/manager/ChangeLog
r2332 r2348 1 2007-05-25 Isak Savo <isak.savo@gmail.com> 2 3 * frontend-gtk/gui_cb.c (show_uninstall_error_message): Ooops.. missing 'break;' in case statement 4 5 2007-05-24 Isak Savo <isak.savo@gmail.com> 6 7 * frontend-gtk/manager-gtk.h: New file! Moved app global declarations here instead of having them at the top of main.c. 8 9 * frontend-gtk/main.c: Removed a bunch of the global variables and made them either function private or attached them to GObjects using g_object_set_data() 10 11 * frontend-gtk/gui_cb.c: New file! Moved all gui callbacks and their helper functions to this file. 12 (remove_clicked_cb): Changed so that we now call 'package remove <shortname>' for root owned packages instead of spawning a new manager as root. 13 This is much more intuitive behavior. Should fix #21 and may also fix #1. 14 (show_uninstall_error_message): Much better error reporting in case something goes wrong when a package is uninstalled. 15 1 16 2007-05-23 Isak Savo <isak.savo@gmail.com> 2 17 frontend/trunk/manager/frontend-gtk/Makefile.am
r2307 r2348 5 5 6 6 bin_PROGRAMS = autopackage-manager-gtk 7 autopackage_manager_gtk_SOURCES = main.c prefix.c 7 autopackage_manager_gtk_SOURCES = main.c prefix.c gui_cb.c 8 8 autopackage_manager_gtk_LDFLAGS = `pkg-config --libs gtk+-2.0 libglade-2.0 gmodule-2.0 gthread-2.0` 9 9 autopackage_manager_gtk_LDADD = $(top_builddir)/managercore/libcore.a -lpthread frontend/trunk/manager/frontend-gtk/main.c
r2328 r2348 24 24 */ 25 25 26 #ifdef HAVE_CONFIG_H27 # include <config.h>28 #endif29 26 #include <string.h> 30 27 #include <stdio.h> 31 28 #include <unistd.h> 32 29 #include <stdlib.h> 33 #include <assert.h>34 30 #include <unistd.h> 35 31 #include <time.h> 36 32 #include <sys/types.h> 37 #include <sys/wait.h>38 #include <libintl.h>39 33 40 34 #include <gtk/gtk.h> 41 35 #include <gmodule.h> 42 #include <glade/glade.h>43 36 #include <gdk-pixbuf/gdk-pixbuf.h> 44 37 … … 46 39 47 40 #include "prefix.h" 48 49 #include "../managercore/frontend-interface.h" 50 51 static void add_to_list (ApplicationInfo *info); 41 #include "manager-gtk.h" 42 43 52 44 53 45 int logging = 0; 54 46 GladeXML *xml; 55 GtkListStore *store;56 47 gchar *selfpath = NULL; 57 48 gchar *prefix = NULL; 58 49 ApplicationInfo *selected; 59 50 60 static gboolean pulse_progress_id = FALSE; 61 62 #define TRACE(s...) if (logging) { printf("autopackage-manager-gtk: "); printf(s); } 51 guint pulse_progress_id = 0; 63 52 64 53 /* This determines what apps to show in the list (see frontend-interface.h for details) */ 65 AutoPackageAppType filter = APP_TYPE_DESKTOP; 66 67 GList *pkg_list = NULL; 68 /* 69 * Standard gettext macros. 70 */ 71 #ifdef ENABLE_NLS 72 # include <libintl.h> 73 # undef _ 74 # define _(String) dgettext (GETTEXT_PACKAGE, String) 75 # ifdef gettext_noop 76 # define N_(String) gettext_noop (String) 77 # else 78 # define N_(String) (String) 79 # endif 80 #else 81 # define textdomain(String) (String) 82 # define gettext(String) (String) 83 # define dgettext(Domain,Message) (Message) 84 # define dcgettext(Domain,Message,Type) (Message) 85 # define bindtextdomain(Domain,Directory) (Domain) 86 # define _(String) (String) 87 # define N_(String) (String) 88 #endif 89 90 #define W(x) glade_xml_get_widget (xml, x) 91 92 /* Done in C for portability <sigh> */ 93 94 enum 95 { 96 COL_PIXBUF, 97 COL_NAME, 98 COL_INFO, 99 COL_DETAILS, 100 NUM_COLS 101 }; 54 //AutoPackageAppType filter = APP_TYPE_DESKTOP; 102 55 103 56 /* To simplify pointer comparisons */ … … 110 63 * If 'str' is null, the empty string ("") is returned! 111 64 * 112 * Returns: the (ev. partially)converted string. This must always be free()'d65 * Returns: the converted string. This must always be free()'d 113 66 * since this function never returns NULL. 114 67 */ … … 134 87 { 135 88 g_free (retval); 136 137 g_error_free (err); 138 err = NULL; 89 clear_error(&err); 139 90 if (bytes_read > 0) 140 91 valid_utf8bytes = bytes_read; … … 170 121 } 171 122 172 // Called every time the selected app changes 173 static void update_selection(ApplicationInfo *info) 174 { 175 if (info == NULL) 176 { 177 TRACE("user has nothing selected\n "); 178 gtk_widget_hide (W("rootwarning")); 179 gtk_widget_set_sensitive(W("remove"), FALSE); 180 } 181 else 182 { 183 TRACE("user selected %s, %s\n", info->name, info->root ? "root install" : "user install"); 184 if (info->root && geteuid() != 0) 185 gtk_widget_show(W("rootwarning")); 186 else 187 gtk_widget_hide(W("rootwarning")); 188 189 gtk_widget_set_sensitive(W("remove"), TRUE); 190 } 191 selected = info; 192 } 193 194 static void clear_error(GError **error) 123 124 void clear_error(GError **error) 195 125 { 196 126 if (*error) … … 331 261 } 332 262 333 static gchar * 334 nice_date(char *timestamp) 263 static gchar *nice_date(char *timestamp) 335 264 { 336 265 gchar **components, **date, **stime; … … 379 308 } 380 309 381 staticvoid add_to_list (ApplicationInfo *info)310 void add_to_list (ApplicationInfo *info) 382 311 { 383 312 GdkPixbuf *pixbuf = lookup_icon(info->icon); 384 313 gchar *details, *size, *date; 385 314 gchar *namestr; 386 315 GtkListStore *store = GTK_LIST_STORE ( gtk_tree_view_get_model(GTK_TREE_VIEW(W("packagelist"))) ); 387 316 388 317 /* FIXME: These should use MiB and KiB instead */ … … 435 364 { 436 365 ApplicationInfo *info = (ApplicationInfo *) ptr; 366 AutoPackageAppType filter = gtk_option_menu_get_history (GTK_OPTION_MENU (W("appfilter"))); 437 367 438 368 TRACE("application_found: %p\n", ptr); … … 448 378 return FALSE; 449 379 } 450 451 pkg_list = g_list_append (pkg_list, info);380 GList *pkg_list = g_object_get_data (G_OBJECT(W("packagelist")), "pkglist"); 381 g_object_set_data (G_OBJECT(W("packagelist")), "pkglist", g_list_append (pkg_list, info)); 452 382 453 383 if (info->type == APP_TYPE_DESKTOP) { … … 469 399 } 470 400 471 /* runs in a separate thread, so marshal it back to the main thread */ 401 /* Runs in a separate thread, so marshal it back to the main thread 402 * (g_idle_add is thread safe) */ 472 403 static void application_found_callback(ApplicationInfo *info) 473 404 { … … 476 407 } 477 408 478 void filter_changed_cb (GtkOptionMenu *optionmenu, gpointer data) 479 { 480 GList *node = pkg_list; 481 filter = gtk_option_menu_get_history (GTK_OPTION_MENU (W("appfilter"))); 482 TRACE ("Filter changed: %s\n", filter == APP_TYPE_DESKTOP ? "APP_TYPE_DESKTOP" : "APP_TYPE_SYSTEM"); 483 484 gtk_list_store_clear (GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (W("packagelist"))))); 485 486 while (node) { 487 ApplicationInfo *i = node->data; 488 switch (filter) { 489 case APP_TYPE_DESKTOP: 490 if (i->type == APP_TYPE_DESKTOP) 491 add_to_list(i); 492 break; 493 494 case APP_TYPE_SYSTEM: 495 add_to_list(i); 496 break; 497 } 498 499 node = node->next; 500 } 501 } 502 503 static void packagelist_selection_changed(GtkTreeSelection *selection, gpointer data) 504 { 505 GtkTreeIter iter; 506 GtkTreeModel *model; 507 508 if (gtk_tree_selection_get_selected(selection, &model, &iter)) 509 { 510 ApplicationInfo *info; 511 512 gtk_tree_model_get(model, &iter, COL_INFO, &info, -1); 513 update_selection(info); 514 } 515 else 516 update_selection(NULL); 517 } 518 519 static gboolean pulse_progress(gpointer widget) 520 { 521 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(widget)); 409 410 gboolean pulse_progress (GtkWidget *progressbar) 411 { 412 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progressbar)); 522 413 return TRUE; 523 414 } 524 415 525 static void enable_disable_gui(gboolean enabled)526 {527 gtk_widget_set_sensitive(W("packagelist"), enabled);528 gtk_widget_set_sensitive(W("remove"), enabled);529 gtk_widget_set_sensitive(W("close"), enabled);530 gtk_widget_set_sensitive(W("appfilter"), enabled);531 }532 533 static gboolean uninstall_completed_callback(gpointer _errorcode)534 {535 int errorcode = GPOINTER_TO_INT(_errorcode);536 TRACE("uninstall completed, errorcode=%d\n", errorcode);537 538 GtkWidget *view = W("packagelist");539 if (errorcode == 0)540 {541 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));542 GtkTreeIter iter;543 GtkTreeModel *model;544 545 gtk_tree_selection_get_selected(sel, &model, &iter);546 GdkPixbuf *pixbuf;547 gtk_tree_model_get(model, &iter, COL_PIXBUF, &pixbuf, -1);548 if (pixbuf) gdk_pixbuf_unref(pixbuf);549 gtk_list_store_remove(store, &iter);550 551 /* remove from internal list */552 pkg_list = g_list_remove(pkg_list, selected);553 554 /* select the first item */555 GtkTreePath *path = gtk_tree_path_new_from_string("0");556 gtk_tree_view_set_cursor(GTK_TREE_VIEW(view), path, NULL, FALSE);557 gtk_tree_path_free(path);558 }559 560 gtk_label_set_text(GTK_LABEL(W("status")),561 (const gchar *) _("Select the application you want to uninstall and click \"Remove\"."));562 563 enable_disable_gui(TRUE);564 gtk_widget_grab_focus(view);565 gtk_timeout_remove(pulse_progress_id);566 gtk_widget_hide(W("removing"));567 gtk_widget_show(W("appfilter"));568 return FALSE;569 }570 571 572 static void uninstall_completed_callback_marshaller(int errorcode)573 {574 g_idle_add(uninstall_completed_callback, GINT_TO_POINTER(errorcode));575 }576 577 void remove_clicked(GtkWidget *button, gpointer data)578 {579 assert( selected );580 TRACE("remove clicked for %s\n", selected->name);581 582 GtkLabel *status = GTK_LABEL(W("status"));583 584 char *text = g_strdup_printf((const gchar *) _("Removing %s..."), selected->name);585 gtk_label_set_text(status, text);586 587 enable_disable_gui(FALSE);588 589 gtk_widget_show(W("removing"));590 gtk_widget_hide(W("appfilter"));591 // clearlooks can send us into an infinite loop with this line so hide it instead592 pulse_progress_id = gtk_timeout_add(20, pulse_progress, W("removing"));593 594 595 if (selected->root && geteuid() != 0)596 {597 TRACE("Need elevated privileges to remove selected package!\n");598 gpointer gnomesu_spawn_async2;599 GModule *mod = g_module_open("libgnomesu.so.0", G_MODULE_BIND_LAZY );600 601 if (mod && g_module_symbol(mod, "gnomesu_spawn_async2", &gnomesu_spawn_async2))602 {603 TRACE("Using libgnomesu to spawn '%s'\n", selfpath);604 /* libgnomesu is available */605 typedef gboolean (*GnomesuSpawnAsync2) (const gchar *user, const gchar **argv, GPid *pid,606 GdkPixbuf *icon, const gchar *title, gboolean show_command);607 const gchar *argv[3];608 609 argv[0] = selfpath;610 argv[1] = "--rootmode";611 argv[2] = NULL;612 gtk_widget_hide(W("window1"));613 ((GnomesuSpawnAsync2) gnomesu_spawn_async2)(NULL, argv, NULL,614 NULL, _("Manage 3rd party software"), FALSE);615 exit(0);616 617 } else618 {619 gchar *autosu = NULL;620 gchar *home = g_strdup_printf("%s/.local/libexec/autopackage/autosu", g_get_home_dir());621 622 if (g_file_test("/usr/libexec/autopackage/autosu-gtk", G_FILE_TEST_IS_REGULAR))623 autosu = g_strdup("/usr/libexec/autopackage/autosu-gtk");624 else if (g_file_test(home, G_FILE_TEST_IS_REGULAR))625 autosu = g_strdup(home);626 g_free (home);627 TRACE("Using autosu (%s) to spawn '%s'\n", autosu, selfpath);628 if (!autosu)629 {630 uninstall_completed_callback(GINT_TO_POINTER(-1));631 GtkWidget *dlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,632 GTK_MESSAGE_ERROR,633 GTK_BUTTONS_OK,634 "Cannot uninstall the selected package because the program used to switch to root (autosu) could not be found\n"635 "You need to start the 'autopackage-manager-gtk' as root directly to remove this application'");636 gtk_dialog_run(GTK_DIALOG(dlg));637 gtk_widget_destroy(dlg);638 return;639 640 }641 GError *err = NULL;642 gint child_exitstatus;643 gchar *argv[7];644 argv[0] = autosu;645 argv[1] = "--root-only";646 argv[2] = "-m";647 argv[3] = "manage";648 argv[4] = (gchar *) selfpath;649 argv[5] = "--rootmode";650 argv[6] = NULL;651 if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_CHILD_INHERITS_STDIN,652 NULL, NULL, NULL /* stdout */, NULL /* stderr */, &child_exitstatus, &err))653 {654 uninstall_completed_callback(GINT_TO_POINTER(-2));655 GtkWidget *dlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,656 GTK_MESSAGE_ERROR,657 GTK_BUTTONS_OK,658 "Cannot uninstall the selected package because the program used to switch "659 "to root (autosu) could not be launched.\n\n"660 "The error reported was: %s", err->message);661 gtk_dialog_run(GTK_DIALOG(dlg));662 g_error_free(err);663 gtk_widget_destroy(dlg);664 return;665 666 }667 child_exitstatus = WEXITSTATUS(child_exitstatus);668 TRACE ("Exitstatus of autosu: %d\n", child_exitstatus);669 if (child_exitstatus == 0)670 exit(0);671 uninstall_completed_callback(GINT_TO_POINTER(-3));672 }673 674 } else675 uninstallPackage(selected, uninstall_completed_callback_marshaller);676 }677 416 678 417 static gboolean post_gui_init(gpointer ptr) … … 680 419 TRACE("post gui init\n"); 681 420 682 store = gtk_list_store_new(NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);421 GtkListStore *store = gtk_list_store_new (NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING); 683 422 684 423 GtkCellRenderer *textrenderer = gtk_cell_renderer_text_new(); … … 687 426 688 427 GtkTreeView *view = GTK_TREE_VIEW(W("packagelist")); 689 assert( view);428 g_assert (view); 690 429 691 430 … … 704 443 705 444 gtk_tree_view_insert_column_with_attributes(view, -1, _("Icon"), 706 iconrenderer, "pixbuf", COL_PIXBUF, NULL);445 iconrenderer, "pixbuf", COL_PIXBUF, NULL); 707 446 708 447 if (expando) … … 728 467 GtkTreeSelection *select = gtk_tree_view_get_selection(view); 729 468 gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); 730 g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(p ackagelist_selection_changed), NULL);469 g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(pkglst_selection_changed_cb), NULL); 731 470 732 471 g_signal_connect(G_OBJECT(W("window1")), "delete_event", G_CALLBACK(gtk_main_quit), NULL); … … 816 555 gtk_widget_show(W("searching")); 817 556 g_idle_add(post_gui_init, NULL); 818 pulse_progress_id = gtk_timeout_add(20, pulse_progress, W("searching"));557 pulse_progress_id = gtk_timeout_add(20, (GSourceFunc) pulse_progress, W("searching")); 819 558 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(W("searching")), 0.01); 820 559 frontend/trunk/manager/frontend-gtk/manager-gtk.glade
r2315 r2348 191 191 <property name="relief">GTK_RELIEF_NORMAL</property> 192 192 193 <signal name="clicked" handler="remove_clicked " last_modification_time="Tue, 28 Dec 2004 21:22:10 GMT"/>193 <signal name="clicked" handler="remove_clicked_cb" last_modification_time="Tue, 28 Dec 2004 21:22:10 GMT"/> 194 194 195 195 <child>
