Author: rpmcruz Date: Tue Jan 26 17:10:22 2010 New Revision: 60541 URL: http://svn.opensuse.org/viewcvs/yast?rev=60541&view=rev Log: * src/pkg/yzyppwrapper.h/cc: changed PkgList property method names to reflect those of Package, and made refreshProps() public. * src/pkg/ygtkpackageview.h/cc: reverted API so that columns are again added by the user-code. * src/pkg/ygtkpackagedetails.h/cc: some general polishing. Modified: trunk/gtk/ChangeLog trunk/gtk/src/YGPackageSelectorPluginStub.cc trunk/gtk/src/pkg/CMakeLists.txt trunk/gtk/src/pkg/YGPackageSelector.cc trunk/gtk/src/pkg/ygtkdetailview.cc trunk/gtk/src/pkg/ygtkpackageview.cc trunk/gtk/src/pkg/ygtkpackageview.h trunk/gtk/src/pkg/yzyppwrapper.cc trunk/gtk/src/pkg/yzyppwrapper.h trunk/gtk/src/ygtkrichtext.c trunk/gtk/src/ygtkwizard.c trunk/gtk/src/ygtkwizard.h Modified: trunk/gtk/ChangeLog URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/ChangeLog?rev=60541&r1=60... ============================================================================== --- trunk/gtk/ChangeLog (original) +++ trunk/gtk/ChangeLog Tue Jan 26 17:10:22 2010 @@ -1,3 +1,14 @@ +2010-01-26 Ricardo Cruz <rpmcruz@alunos.dcc.fc.up.pt> + + * src/pkg/yzyppwrapper.h/cc: changed PkgList property + method names to reflect those of Package, and made + refreshProps() public. + + * src/pkg/ygtkpackageview.h/cc: reverted API so that + columns are again added by the user-code. + + * src/pkg/ygtkpackagedetails.h/cc: some general polishing. + 2010-01-19 Ricardo Cruz <rpmcruz@alunos.dcc.fc.up.pt> * src/pkg/YGPackageSelector.cc: added --plug-sidebar flag. Modified: trunk/gtk/src/YGPackageSelectorPluginStub.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGPackageSelectorPluginSt... ============================================================================== --- trunk/gtk/src/YGPackageSelectorPluginStub.cc (original) +++ trunk/gtk/src/YGPackageSelectorPluginStub.cc Tue Jan 26 17:10:22 2010 @@ -11,21 +11,21 @@ #include <YEvent.h> #include <string.h> -bool search_entry_side = true, search_entry_top = false, dynamic_sidebar = true, +bool search_entry_side = false, search_entry_top = true, dynamic_sidebar = true, expander_sidebar = false, flex_sidebar = false, grid_sidebar = false, - layered_sidebar = false, layered_tabs_sidebar = false, plug_sidebar = false, + layered_sidebar = true, layered_tabs_sidebar = false, plug_sidebar = false, startup_menu = false, - big_icons_sidebar = false, icons_sidebar = false, + big_icons_sidebar = true, icons_sidebar = false, categories_side = true, repositories_side = true, categories_top = false, repositories_top = false, status_side = true, status_top = false, status_tabs = false, status_tabs_as_actions = false, undo_side = false, undo_tab = true, undo_old_style = false, undo_log_all = false, undo_log_changed = false, - undo_box = false, + undo_box = true, status_col = false, action_col = true, action_col_as_button = false, action_col_as_check = false, action_col_label = true, version_col = true, single_line_rows = false, colorful_rows = false, - italicize_changed_row = false, golden_changed_row = false, + italicize_changed_row = false, golden_changed_row = true, details_start_hide = false, toolbar_top = false, toolbar_yast = false, arrange_by = false; Modified: trunk/gtk/src/pkg/CMakeLists.txt URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/CMakeLists.txt?rev=60... ============================================================================== --- trunk/gtk/src/pkg/CMakeLists.txt (original) +++ trunk/gtk/src/pkg/CMakeLists.txt Tue Jan 26 17:10:22 2010 @@ -11,6 +11,7 @@ ygtkdiskview.cc ygtkcellrendererbutton.c + ygtkcellrenderersidebutton.c ygtknotebook.c ygtktreemodel.cc ygtktooltip.c Modified: trunk/gtk/src/pkg/YGPackageSelector.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/YGPackageSelector.cc?... ============================================================================== --- trunk/gtk/src/pkg/YGPackageSelector.cc (original) +++ trunk/gtk/src/pkg/YGPackageSelector.cc Tue Jan 26 17:10:22 2010 @@ -38,6 +38,19 @@ action_col, action_col_as_button, action_col_as_check, version_col, single_line_rows, details_start_hide, toolbar_top, toolbar_yast, arrange_by; +//** utilities + +static gboolean tree_view_row_separator_cb ( + GtkTreeModel *model, GtkTreeIter *iter, gpointer _text_col) +{ + int text_col = GPOINTER_TO_INT (_text_col); + gchar *str; + gtk_tree_model_get (model, iter, text_col, &str, -1); + bool ret = !str || !(*str); + g_free (str); + return ret; +} + //** UI components -- split up for re-usability, but mostly for readability static gboolean paint_white_expose_cb (GtkWidget *widget, GdkEventExpose *event) @@ -133,9 +146,8 @@ gtk_box_pack_start (GTK_BOX (label_box), icon, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (label_box), label, TRUE, TRUE, 0); YGtkPackageView *view = ygtk_package_view_new (FALSE); - view->setVisible ("available-version", false); -/* view->appendCheckColumn (checkCol); - view->appendTextColumn (NULL, NAME_PROP, -1, true);*/ + view->appendCheckColumn (INSTALLED_CHECK_PROP); + view->appendTextColumn (NULL, NAME_PROP, true, -1, true); view->setActivateAction (YGtkPackageView::UNDO_ACTION); view->setList (list, NULL); view->setListener (listener); @@ -1871,8 +1883,8 @@ } static bool confirmPkgs (const char *title, const char *message, - GtkMessageType icon, const Ypp::PkgList list, - const std::string &extraProp) + GtkMessageType icon, const Ypp::PkgList list, const char *extra_property_header, + int extra_property) { GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(), GtkDialogFlags (0), icon, GTK_BUTTONS_NONE, "%s", title); @@ -1885,7 +1897,8 @@ gtk_widget_show_all (dialog); YGtkPackageView *view = ygtk_package_view_new (TRUE); - view->setVisible (extraProp, true); + view->appendTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1); + view->appendTextColumn (extra_property_header, extra_property, true, -1); view->setList (list, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), GTK_WIDGET (view)); @@ -1906,7 +1919,8 @@ if (list.size() > 0) return confirmPkgs (_("Unsupported Packages"), _("Please realize that the following " "software is either unsupported or requires an additional customer contract " - "for support."), GTK_MESSAGE_WARNING, list, "support"); + "for support."), GTK_MESSAGE_WARNING, list, + _("Supportability"), SUPPORT_PROP); return true; } @@ -2132,52 +2146,82 @@ bool m_clearIcon; public: - SearchEntry (bool combo_props) : _QueryWidget() + SearchEntry (bool ver_combo) : _QueryWidget() { m_entry = gtk_entry_new(); g_signal_connect (G_OBJECT (m_entry), "realize", - G_CALLBACK (grab_focus_cb), NULL); - gtk_widget_set_size_request (m_entry, 50, -1); + G_CALLBACK (grab_focus_cb), this); + g_signal_connect (G_OBJECT (m_entry), "activate", + G_CALLBACK (activate_cb), this); + if (ver_combo) + gtk_widget_set_size_request (m_entry, 50, -1); + else + gtk_widget_set_size_request (m_entry, 150, -1); GtkWidget *entry_hbox = gtk_hbox_new (FALSE, 2), *find_label; - find_label = gtk_label_new_with_mnemonic (_("_Find:")); + find_label = gtk_label_new_with_mnemonic (_("_Search:")); gtk_box_pack_start (GTK_BOX (entry_hbox), find_label, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (entry_hbox), m_entry, TRUE, TRUE, 0); gtk_label_set_mnemonic_widget (GTK_LABEL (find_label), m_entry); + gtk_entry_set_icon_from_stock (GTK_ENTRY (m_entry), + GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND); + gtk_entry_set_icon_activatable (GTK_ENTRY (editable), GTK_ENTRY_ICON_PRIMARY, TRUE); + m_clearIcon = false; g_signal_connect (G_OBJECT (m_entry), "changed", G_CALLBACK (entry_changed_cb), this); g_signal_connect (G_OBJECT (m_entry), "icon-press", G_CALLBACK (icon_press_cb), this); - m_combo = 0; - if (combo_props) { - m_combo = gtk_combo_box_new_text(); - gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("Name & Summary")); - gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("Description")); - gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("File List")); - gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("Author")); - gtk_combo_box_set_active (GTK_COMBO_BOX (m_combo), 0); - g_signal_connect (G_OBJECT (m_combo), "changed", - G_CALLBACK (combo_changed_cb), this); - - GtkWidget *opt_hbox = gtk_hbox_new (FALSE, 2), *empty = gtk_event_box_new(); + m_combo = gtk_combo_box_new_text(); + GtkWidget *opt_hbox, *empty; + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("Name & Summary")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("Description")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("File List")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), ""); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), "RPM Provides"); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), "RPM Requires"); + + opt_hbox = gtk_hbox_new (FALSE, 2); + if (ver_combo) { + empty = gtk_event_box_new(); gtk_box_pack_start (GTK_BOX (opt_hbox), empty, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (opt_hbox), gtk_label_new (_("by")), FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (opt_hbox), m_combo, TRUE, TRUE, 0); + } + gtk_box_pack_start (GTK_BOX (opt_hbox), gtk_label_new (_("by")), FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (opt_hbox), m_combo, TRUE, TRUE, 0); + if (ver_combo) { GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (group, find_label); gtk_size_group_add_widget (group, empty); g_object_unref (G_OBJECT (group)); + } + +/* gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("by Name & Summary")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("by Description")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("by File List")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), ""); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("by RPM Provides")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_combo), _("by RPM Requires")); +*/ + if (ver_combo) m_widget = gtk_vbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (m_widget), entry_hbox, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (m_widget), opt_hbox, FALSE, TRUE, 0); - } else - m_widget = entry_hbox; + m_widget = gtk_hbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (m_widget), entry_hbox, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_widget), opt_hbox, FALSE, TRUE, 0); + + gtk_combo_box_set_active (GTK_COMBO_BOX (m_combo), 0); + g_signal_connect (G_OBJECT (m_combo), "changed", + G_CALLBACK (combo_changed_cb), this); + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (m_combo), + tree_view_row_separator_cb, GINT_TO_POINTER (0), NULL); gtk_widget_show_all (m_widget); + + gtk_widget_set_tooltip_markup (m_entry, + _("<b>Package search:</b> Use spaces to separate your keywords.\n" + "(usage example: a name search for "yast dhcp" would match yast dhcpd tool)")); } virtual GtkWidget *getWidget() { return m_widget; } @@ -2216,11 +2260,17 @@ break; case 2: writeQueryStr (subquery, "filelist", name, true, false); + //writeQueryStr (subquery, "provides", name, true, false); + break; + case 4: writeQueryStr (subquery, "provides", name, true, false); break; - case 3: - subquery->add (new Ypp::QueryProperty ("authors", name, false, true)); + case 5: + writeQueryStr (subquery, "requires", name, true, false); break; +/* case 3: + subquery->add (new Ypp::QueryProperty ("authors", name, false, true)); + break;*/ default: break; } query->add (subquery); @@ -2258,12 +2308,20 @@ static void icon_press_cb (GtkEntry *entry, GtkEntryIconPosition pos, GdkEvent *event, SearchEntry *pThis) { - gtk_entry_set_text (entry, ""); + if (pos == GTK_ENTRY_ICON_PRIMARY) + gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); + else + gtk_entry_set_text (entry, ""); gtk_widget_grab_focus (GTK_WIDGET (entry)); } static void grab_focus_cb (GtkWidget *widget) { gtk_widget_grab_focus (widget); } + + static void activate_cb (GtkEntry *entry, SearchEntry *pThis) + { + // TODO: activate package entry list + } }; class PropertyModel @@ -2273,11 +2331,11 @@ GtkTreeModel *m_filter; public: - enum Column { TEXT_COLUMN, VISIBLE_COLUMN, DATA_COLUMN, ICON_COLUMN, TOTAL_COLUMNS }; + enum Column { TEXT_COLUMN, VISIBLE_COLUMN, DATA_COLUMN, ICON_COLUMN, ENABLED_COLUMN, TOTAL_COLUMNS }; PropertyModel() { - m_store = gtk_list_store_new (TOTAL_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_STRING); + m_store = gtk_list_store_new (TOTAL_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN); if (dynamic_sidebar) { m_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (m_store), NULL); gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (m_filter), 1); @@ -2303,6 +2361,12 @@ gtk_list_store_set (store, iter, 0, _text, 1, count > 0, -1); g_free (_text); } + + void appendRow (GtkTreeIter *iter) + { + gtk_list_store_append (m_store, &iter); + gtk_list_store_set (m_store, &iter, 0, "", 1, TRUE, 2, 0, 3, NULL, 4, TRUE, -1); + } }; class StatusModel : public PropertyModel @@ -2311,23 +2375,23 @@ StatusModel() : PropertyModel() { GtkTreeIter iter; - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("All packages"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, GINT_TO_POINTER (0), 3, NULL, -1); - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("Available"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, GINT_TO_POINTER (1), 3, GTK_STOCK_NETWORK, -1); - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("Installed"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, GINT_TO_POINTER (2), 3, GTK_STOCK_HARDDISK, -1); - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("Upgrades"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, GINT_TO_POINTER (3), 3, GTK_STOCK_GO_UP, -1); - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("Summary"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, GINT_TO_POINTER (4), 3, NULL, -1); @@ -2405,7 +2469,7 @@ gtk_list_store_clear (m_store); GtkTreeIter iter; - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("All packages"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, NULL, ICON_COLUMN, NULL, -1); @@ -2415,7 +2479,7 @@ else category = Ypp::get()->getFirstCategory (type); for (; category; category = category->next()) { - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, category->name.c_str(), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, category, ICON_COLUMN, category->icon, -1); @@ -2468,31 +2532,23 @@ RepositoryModel() : PropertyModel() { GtkTreeIter iter; - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) gtk_list_store_set (m_store, &iter, 0, _("All packages"), -1); gtk_list_store_set (m_store, &iter, 1, TRUE, 2, NULL, ICON_COLUMN, NULL, -1); for (int i = 0; Ypp::get()->getRepository (i); i++) { const Ypp::Repository *repo = Ypp::get()->getRepository (i); - gtk_list_store_append (m_store, &iter); + appendRow (&iter); if (!dynamic_sidebar) { if (big_icons_sidebar) gtk_list_store_set (m_store, &iter, 0, (repo->name + '\n' + repo->url).c_str(), -1); else gtk_list_store_set (m_store, &iter, 0, repo->name.c_str(), -1); } - gtk_list_store_set (m_store, &iter, 1, TRUE, 2, repo, -1); + gtk_list_store_set (m_store, &iter, 1, TRUE, 2, repo, , + ENABLED_COLUMN, repo->enabled, -1); - const gchar *icon; - if (repo->url.empty()) - icon = GTK_STOCK_MISSING_IMAGE; - else if (repo->url.compare (0, 2, "cd", 2) == 0 || - repo->url.compare (0, 3, "dvd", 3) == 0) - icon = GTK_STOCK_CDROM; - else if (repo->url.compare (0, 3, "iso", 3) == 0) - icon = GTK_STOCK_FILE; - else - icon = GTK_STOCK_NETWORK; + const gchar *icon = getRepositoryStockIcon (repo->url); gtk_list_store_set (m_store, &iter, ICON_COLUMN, icon, -1); } } @@ -2568,12 +2624,12 @@ if (icons_sidebar || big_icons_sidebar) { GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new(); column = gtk_tree_view_column_new_with_attributes (NULL, - renderer, "icon-name", PropertyModel::ICON_COLUMN, NULL); + renderer, "icon-name", PropertyModel::ICON_COLUMN, "sensitive", PropertyModel::ENABLED_COLUMN, NULL); g_object_set (G_OBJECT (renderer), "stock-size", big_icons_sidebar ? GTK_ICON_SIZE_LARGE_TOOLBAR : GTK_ICON_SIZE_MENU, NULL); gtk_tree_view_append_column (tview, column); } column = gtk_tree_view_column_new_with_attributes ( - NULL, renderer, "markup", PropertyModel::TEXT_COLUMN, NULL); + NULL, renderer, "markup", PropertyModel::TEXT_COLUMN, "sensitive", PropertyModel::ENABLED_COLUMN, NULL); gtk_tree_view_append_column (tview, column); GtkWidget *scroll = gtk_scrolled_window_new (NULL, NULL); @@ -2719,7 +2775,8 @@ { pThis->notify(); } }; -#define BROWSER_PATH "/usr/bin/firefox" +#if 0 +#define BROWSER_BIN "/usr/bin/firefox" class DetailBox { @@ -2729,8 +2786,7 @@ public: GtkWidget *getWidget() { return m_widget; } - DetailBox() - : m_link_popup (NULL) + DetailBox() : m_link_popup (NULL) { m_text = ygtk_rich_text_new(); /* @@ -2738,6 +2794,7 @@ _("<i>Write a little introductory text here</i>")); */ YGtkPackageView *view = ygtk_package_view_new (TRUE); + view->appendTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1, true); m_pkg_view = GTK_WIDGET (view); //gtk_widget_set_size_request (m_pkg_view, -1, 200); @@ -2789,7 +2846,7 @@ gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (text), NULL); GtkWidget *item; - if (g_file_test (BROWSER_PATH, G_FILE_TEST_IS_EXECUTABLE)) { + if (g_file_test (BROWSER_BIN, G_FILE_TEST_IS_EXECUTABLE)) { std::string label; if (getuid() == 0) { const char *username = getenv ("USERNAME"); @@ -2836,12 +2893,12 @@ if (username) { command += "gnomesu -u "; command += username; - command += " -c "" BROWSER_PATH " --new-window "; + command += " -c "" BROWSER_BIN " --new-window "; command += link; command += """; } else { - command += BROWSER_PATH " --new-window "; + command += BROWSER_BIN " --new-window "; command += link; } command += " &"; @@ -2856,6 +2913,7 @@ gtk_clipboard_set_text (clipboard, link.c_str(), -1); } }; +#endif class Toolbar { @@ -2918,10 +2976,9 @@ gtk_widget_set_sensitive (m_remove_button, FALSE); } else { - bool installed = list.installed(); - gtk_widget_set_sensitive (m_install_button, !installed); - gtk_widget_set_sensitive (m_remove_button, installed); - gtk_widget_set_sensitive (m_upgrade_button, list.upgradable()); + gtk_widget_set_sensitive (m_install_button, list.isNotInstalled()); + gtk_widget_set_sensitive (m_remove_button, list.isInstalled()); + gtk_widget_set_sensitive (m_upgrade_button, list.hasUpgrade()); } } @@ -3309,16 +3366,17 @@ class UndoBox : public Ypp::PkgList::Listener { -GtkWidget *m_undo_box, *m_undo_package, *m_undo_details, *m_title; +GtkWidget *m_undo_box, *m_action_image, *m_package_label, *m_dependencies_label, *m_undo_button, *m_undo_details, *m_to_download_label, *m_to_occupy_label, *m_title, *m_disk_combo, *m_disk_label, *m_disk_delta_label, *m_package_box, *m_details_link; Ypp::PkgList m_pool; Ypp::Package *m_package; bool m_closed; +int m_autoNb; public: GtkWidget *getWidget() { return m_undo_box; } - UndoBox() : m_closed (false) + UndoBox() : m_closed (false), m_autoNb (0) { Ypp::QueryBase *query = new Ypp::QueryProperty ("to-modify", true); // if (pkg_selector->onlineUpdateMode()) @@ -3326,11 +3384,13 @@ // TODO: there could already be packages modified m_pool.addListener (this); + GtkWidget *hbox; m_undo_box = ygtk_tooltip_box_new(); - GtkWidget *vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); - gtk_container_add (GTK_CONTAINER (m_undo_box), vbox); - m_title = gtk_label_new (_("Software changes")); + + GtkWidget *main_box = gtk_vbox_new (FALSE, 2); + gtk_container_set_border_width (GTK_CONTAINER (main_box), 6); + gtk_container_add (GTK_CONTAINER (m_undo_box), main_box); + m_title = gtk_label_new (""); gtk_misc_set_alignment (GTK_MISC (m_title), .5, .5); YGUtils::setWidgetFont (m_title, PANGO_STYLE_NORMAL, PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM); GtkWidget *close_button = create_small_button (GTK_STOCK_CLOSE, _("Close")); @@ -3339,30 +3399,72 @@ GtkWidget *title_box = gtk_hbox_new (FALSE, 2); gtk_box_pack_start (GTK_BOX (title_box), m_title, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (title_box), close_button, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), title_box, FALSE, TRUE, 0); - GtkWidget *package_box = gtk_hbox_new (FALSE, 4); - m_undo_package = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (m_undo_package), 0, .5); - GtkWidget *undo_button = gtk_button_new_from_stock (GTK_STOCK_UNDO); + gtk_box_pack_start (GTK_BOX (main_box), title_box, TRUE, TRUE, 0); + + GtkWidget *undo_button, *undo_align; + m_package_box = gtk_vbox_new (FALSE, 2); + hbox = gtk_hbox_new (FALSE, 2); + m_action_image = gtk_image_new(); + GtkWidget *label_vbox = gtk_vbox_new (TRUE, 0); + m_package_label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (m_package_label), 0, .5); + m_dependencies_label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (m_dependencies_label), 0, .5); + undo_button = gtk_button_new_from_stock (GTK_STOCK_UNDO); + undo_align = gtk_alignment_new (1, 0, 0, 0); + gtk_container_add (GTK_CONTAINER (undo_align), undo_button); g_signal_connect (G_OBJECT (undo_button), "clicked", G_CALLBACK (undo_clicked_cb), this); - gtk_box_pack_start (GTK_BOX (package_box), m_undo_package, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (package_box), undo_button, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), package_box, FALSE, TRUE, 6); - m_undo_details = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (m_undo_details), 0, .5); - gtk_box_pack_start (GTK_BOX (vbox), m_undo_details, FALSE, TRUE, 0); - char *details_str = g_strdup_printf ("<a href="details">%s</a>", _("View details...")); - GtkWidget *details_label = gtk_label_new (details_str); - gtk_label_set_use_markup (GTK_LABEL (details_label), TRUE); + gtk_box_pack_start (GTK_BOX (label_vbox), m_package_label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (label_vbox), m_dependencies_label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), m_action_image, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), label_vbox, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), undo_align, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_package_box), hbox, TRUE, TRUE, 0); + + m_to_download_label = gtk_label_new (_("To download: X")); + gtk_misc_set_alignment (GTK_MISC (m_to_download_label), 0, .5); + gtk_box_pack_start (GTK_BOX (m_package_box), m_to_download_label, TRUE, TRUE, 0); + + m_to_occupy_label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (m_to_occupy_label), 0, .5); + gtk_box_pack_start (GTK_BOX (m_package_box), m_to_occupy_label, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (main_box), m_package_box, TRUE, TRUE, 0); + + hbox = gtk_hbox_new (FALSE, 4); + GtkWidget *icon = gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU); + m_disk_combo = gtk_combo_box_new_text(); + Ypp::Disk *disk = Ypp::get()->getDisk(); + for (int i = 0; disk->getPartition (i); i++) { + const Ypp::Disk::Partition *part = disk->getPartition (i); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_disk_combo), part->path.c_str()); + if (part->path == "/usr" || part->path == "/usr/" || part->path == "/") { + if (gtk_combo_box_get_active (GTK_COMBO_BOX (m_disk_combo)) == -1 || part->path != "/") + gtk_combo_box_set_active (GTK_COMBO_BOX (m_disk_combo), i); + } + } + m_disk_label = gtk_label_new (""); + m_disk_delta_label = gtk_label_new (""); + YGUtils::setWidgetFont (m_disk_delta_label, PANGO_STYLE_ITALIC, PANGO_WEIGHT_NORMAL, PANGO_SCALE_MEDIUM); + GtkWidget *disk_label = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (disk_label), m_disk_label); + gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), m_disk_combo, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), disk_label, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), m_disk_delta_label, FALSE, TRUE, 0); + g_signal_connect (G_OBJECT (m_disk_combo), "changed", + G_CALLBACK (disk_combo_changed_cb), this); + gtk_box_pack_start (GTK_BOX (main_box), hbox, TRUE, TRUE, 0); + + char *details_str = g_strdup_printf ("<a href="details">%s</a>", _("View all changes...")); + m_details_link = gtk_label_new (details_str); + gtk_label_set_use_markup (GTK_LABEL (m_details_link), TRUE); g_free (details_str); - gtk_label_set_track_visited_links (GTK_LABEL (details_label), FALSE); - gtk_misc_set_alignment (GTK_MISC (details_label), 1, .5); - gtk_box_pack_start (GTK_BOX (vbox), details_label, FALSE, TRUE, 0); - g_signal_connect (G_OBJECT (details_label), "activate-link", + gtk_label_set_track_visited_links (GTK_LABEL (m_details_link), FALSE); + gtk_misc_set_alignment (GTK_MISC (m_details_link), 1, .5); + g_signal_connect (G_OBJECT (m_details_link), "activate-link", G_CALLBACK (details_link_cb), this); - - // TODO: start by showing available disk space + gtk_box_pack_start (GTK_BOX (main_box), m_details_link, TRUE, TRUE, 0); } ~UndoBox() @@ -3371,27 +3473,55 @@ } void startHack() // call after init, after you did a show_all in the dialog - { gtk_widget_hide (m_undo_box); } + { + //gtk_widget_hide (m_undo_box); + gtk_widget_hide (m_package_box); + gtk_widget_hide (m_details_link); + setHasChanges (false); + } + + void setHasChanges (bool hasChanges) + { + const char *title = hasChanges ? _("Software changes") : _("Available space"); + gtk_label_set_text (GTK_LABEL (m_title), title); + hasChanges ? gtk_widget_show (m_package_box) : gtk_widget_hide (m_package_box); + } void setPackage (Ypp::Package *package) { if (m_closed) return; - m_package = package; + setHasChanges (true); + gtk_widget_show (m_details_link); - std::string action; - if (package->toInstall()) { - if (package->isInstalled()) - action = _("upgrade"); - else - action = _("add"); + gchar *str; + if (package->isAuto()) { + m_autoNb++; + gchar *str = g_strdup_printf ("\u26ab %s %d %s", _("plus"), m_autoNb, _("dependencies")); + gtk_label_set_text (GTK_LABEL (m_dependencies_label), str); + g_free (str); } - else //if (package->toRemove()) - action = _("remove"); + else { + m_package = package; + m_autoNb = 0; - gchar *package_str = g_strdup_printf ("%s %s", action.c_str(), package->name().c_str()); - gtk_label_set_text (GTK_LABEL (m_undo_package), package_str); - g_free (package_str); + str = g_strdup_printf ("\u26ab %s", package->name().c_str()); + gtk_label_set_text (GTK_LABEL (m_package_label), str); + g_free (str); + gtk_label_set_text (GTK_LABEL (m_dependencies_label), ""); + + const char *stock; + if (package->toInstall()) { + if (package->isInstalled()) + stock = GTK_STOCK_GO_UP; + else + stock = GTK_STOCK_SAVE; + } + else //if (package->toRemove()) + stock = GTK_STOCK_DELETE; + gtk_image_set_from_stock (GTK_IMAGE (m_action_image), stock, GTK_ICON_SIZE_BUTTON); + } +/* const Ypp::PkgList packages (Ypp::get()->getPackages (Ypp::Package::PACKAGE_TYPE)); int added = 0, removed = 0; for (int i = 0; i < packages.size(); i++) { @@ -3401,15 +3531,6 @@ removed++; } - std::string delta_str; - Ypp::Disk *disk = Ypp::get()->getDisk(); - for (int i = 0; disk->getPartition (i); i++) { - const Ypp::Disk::Partition *part = disk->getPartition (i); - // FIXME: check for '/' in a soft manner, /usr/ as a hard check - if (part->path == "/usr" || part->path == "/usr/" || part->path == "/") - delta_str = part->delta_str; - } - gchar *added_str = 0, *removed_str = 0; if (added) added_str = g_strdup_printf (_("Added %d packages\n"), added); @@ -3417,21 +3538,47 @@ removed_str = g_strdup_printf (_("Removed %d packages\n"), removed); gchar *details = g_strdup_printf (_("%s%sTotalling: %s"), added_str ? added_str : "", removed_str ? removed_str : "", delta_str.c_str()); - gtk_label_set_text (GTK_LABEL (m_undo_details), details); - g_free (details); if (added_str) g_free (added_str); if (removed_str) g_free (removed_str); +*/ + std::string delta_str; + Ypp::Disk *disk = Ypp::get()->getDisk(); + for (int i = 0; disk->getPartition (i); i++) { + const Ypp::Disk::Partition *part = disk->getPartition (i); + if (part->path == "/usr" || part->path == "/usr/" || part->path == "/") { + delta_str = part->delta_str; + if (part->path == "/") + break; + } + } + + str = g_strdup_printf (_("To occupy: %s"), delta_str.c_str()); + gtk_label_set_text (GTK_LABEL (m_to_occupy_label), str); + g_free (str); + + updateDisk(); gtk_widget_show (m_undo_box); } + void updateDisk() + { + int n = gtk_combo_box_get_active (GTK_COMBO_BOX (m_disk_combo)); + const Ypp::Disk::Partition *part = Ypp::get()->getDisk()->getPartition (n); + gchar *str = g_strdup_printf (_("%s free out of %s"), part->free_str.c_str(), part->total_str.c_str()); + gtk_label_set_text (GTK_LABEL (m_disk_label), str); + part->delta == 0 ? gtk_widget_hide (m_disk_label) : gtk_widget_show (m_disk_label); + g_free (str); + gtk_label_set_text (GTK_LABEL (m_disk_delta_label), part->delta_str.c_str()); + } + virtual void entryInserted (const Ypp::PkgList list, int index, Ypp::Package *package) { setPackage (package); } virtual void entryDeleted (const Ypp::PkgList list, int index, Ypp::Package *package) - { if (package == m_package) gtk_widget_hide (m_undo_box); } + { if (package == m_package) setHasChanges (false); } virtual void entryChanged (const Ypp::PkgList list, int index, Ypp::Package *package) {} @@ -3496,6 +3643,9 @@ delete changes; return TRUE; } + + static void disk_combo_changed_cb (GtkComboBox *combo, UndoBox *pThis) + { pThis->updateDisk(); } }; class UI : public YGtkPackageView::Listener, _QueryListener, Ypp::Disk::Listener @@ -3503,7 +3653,7 @@ GtkWidget *m_widget, *m_disk_label, *m_arrange_combo; YGtkPackageView *m_all_view, *m_installed_view, *m_available_view, *m_upgrades_view; std::list <_QueryWidget *> m_query; -DetailBox *m_details; +GtkWidget *m_details; DiskView *m_disk; StartupMenu *m_startup_menu; Ypp::Package::Type m_type; @@ -3532,7 +3682,7 @@ if (search_entry_top) { search_entry = new SearchEntry (false); m_query.push_back (search_entry); - gtk_widget_set_size_request (search_entry->getWidget(), 160, -1); + //gtk_widget_set_size_request (search_entry->getWidget(), 160, -1); } UndoView *undo_view = 0; @@ -3542,10 +3692,13 @@ GtkWidget *packages_view; if (status_tabs) { m_installed_view = ygtk_package_view_new (TRUE); + m_installed_view->appendTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1, true); m_installed_view->setListener (this); m_available_view = ygtk_package_view_new (TRUE); + m_available_view->appendTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1, true); m_available_view->setListener (this); m_upgrades_view = ygtk_package_view_new (TRUE); + m_upgrades_view->appendTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1, true); m_upgrades_view->setListener (this); packages_view = ygtk_notebook_new(); @@ -3581,12 +3734,18 @@ } else { m_all_view = ygtk_package_view_new (TRUE); + m_all_view->appendCheckColumn (INSTALLED_CHECK_PROP); + m_all_view->appendTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1); + m_all_view->appendTextColumn (_("Version"), VERSION_PROP, true, 120); + m_all_view->appendTextColumn (_("Size"), SIZE_PROP, true, 80); + m_all_view->appendTextColumn (_("Repository"), REPOSITORY_PROP, false, 180); + m_all_view->appendTextColumn (_("Supportability"), SUPPORT_PROP, false, 120); m_all_view->setListener (this); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (m_all_view), GTK_SHADOW_IN); packages_view = GTK_WIDGET (m_all_view); } - GtkWidget *packages_box = gtk_vbox_new (FALSE, 4); + GtkWidget *packages_box = gtk_vbox_new (FALSE, 2); if (arrange_by) { GtkWidget *arrange_box = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (arrange_box), gtk_label_new (_("Software arranged by")), FALSE, TRUE, 0); @@ -3604,7 +3763,7 @@ { GtkWidget *header_box = gtk_hbox_new (FALSE, 6); - GtkWidget *header = gtk_label_new_with_mnemonic (_("_Listing:")); + GtkWidget *header = gtk_label_new_with_mnemonic (_("Packages _listing:")); gtk_misc_set_alignment (GTK_MISC (header), 0, .5); gtk_label_set_mnemonic_widget (GTK_LABEL (header), GTK_WIDGET (m_all_view)); gtk_box_pack_start (GTK_BOX (header_box), header, TRUE, TRUE, 0); @@ -3659,9 +3818,10 @@ GtkWidget *view_pane = gtk_vpaned_new(); gtk_paned_pack1 (GTK_PANED (view_pane), packages_pane, TRUE, FALSE); - m_details = new DetailBox(); - gtk_paned_pack2 (GTK_PANED (view_pane), m_details->getWidget(), FALSE, TRUE); - gtk_paned_set_position (GTK_PANED (view_pane), 500); + + m_details = ygtk_detail_view_new (sel->onlineUpdateMode()); + gtk_paned_pack2 (GTK_PANED (view_pane), m_details, FALSE, TRUE); + gtk_paned_set_position (GTK_PANED (view_pane), 460); #if 0 GtkWidget *combo = gtk_combo_box_new_text(); @@ -3814,6 +3974,7 @@ GtkWidget *vpaned = gtk_vpaned_new(); gtk_paned_pack1 (GTK_PANED (vpaned), stack1->getWidget(), TRUE, FALSE); gtk_paned_pack2 (GTK_PANED (vpaned), stack2->getWidget(), TRUE, FALSE); + gtk_paned_set_position (GTK_PANED (vpaned), 480); gtk_box_pack_start (GTK_BOX (side_vbox), vpaned, TRUE, TRUE, 0); } @@ -3838,9 +3999,7 @@ gtk_widget_show_all (m_widget); if (details_start_hide) - gtk_widget_hide (m_details->getWidget()); - else - m_details->setPackage (NULL); + gtk_widget_hide (m_details); if (!categories_side && !search_entry_side && !status_side) gtk_widget_hide (side_vbox); if (changes_pane) @@ -3993,7 +4152,7 @@ virtual void packagesSelected (Ypp::PkgList packages) { - m_details->setPackage (packages.size() ? packages.get (0) : NULL); + YGTK_DETAIL_VIEW (m_details)->setPackages (packages); if (m_toolbar) m_toolbar->setPackages (packages); } @@ -4080,7 +4239,7 @@ ygtk_wizard_set_button_str_id (wizard, wizard->abort_button, "cancel"); ygtk_wizard_set_button_label (wizard, wizard->back_button, NULL, NULL); ygtk_wizard_set_button_label (wizard, wizard->next_button, - _("A_pply"), GTK_STOCK_APPLY); + _("_Apply"), GTK_STOCK_APPLY); ygtk_wizard_set_button_str_id (wizard, wizard->next_button, "accept"); g_signal_connect (G_OBJECT (wizard), "action-triggered", G_CALLBACK (wizard_action_cb), this); @@ -4091,39 +4250,65 @@ ygtk_wizard_set_extra_button (wizard, m_tools->getWidget()); #endif -#if 0 - GtkWidget *menu_bar = gtk_menu_bar_new(), *item, *submenu, *subitem; - item = gtk_menu_item_new_with_label (_("File")); - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); - subitem = gtk_menu_item_new_with_label (_("Import...")); - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem); - g_signal_connect (G_OBJECT (subitem), "activate", - G_CALLBACK (import_file_cb), this); - subitem = gtk_menu_item_new_with_label (_("Export...")); - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem); - g_signal_connect (G_OBJECT (subitem), "activate", - G_CALLBACK (export_file_cb), this); - subitem = gtk_separator_menu_item_new(); - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem); - subitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE, NULL); - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem); - subitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, NULL); - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem); - gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), item); - item = gtk_menu_item_new_with_label (_("View")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), item); - item = gtk_menu_item_new_with_label (_("Tools")); - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); - subitem = gtk_menu_item_new_with_label (_("Generate Dependency Testcase...")); - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem); - g_signal_connect (G_OBJECT (subitem), "activate", - G_CALLBACK (create_solver_testcase_cb), this); - gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), item); + GtkWidget *menu_bar = gtk_menu_bar_new(), *item, *submenu, *sub3menu, *subitem; + item = append_menu_item (menu_bar, _("File"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new())); + append_menu_item (submenu, _("Import..."), NULL, + G_CALLBACK (import_file_cb), this); + append_menu_item (submenu, _("Export..."), NULL, + G_CALLBACK (export_file_cb), this); + append_menu_item (submenu, NULL, NULL, NULL, NULL); + append_menu_item (submenu, NULL, GTK_STOCK_APPLY, NULL, this); + append_menu_item (submenu, NULL, GTK_STOCK_QUIT, NULL, this); + item = append_menu_item (menu_bar, _("Package"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new())); + append_menu_item (submenu, _("Install"), NULL, NULL, this); + append_menu_item (submenu, _("Do Not Install"), NULL, NULL, this); + append_menu_item (submenu, _("Keep"), NULL, NULL, this); + append_menu_item (submenu, _("Delete"), NULL, NULL, this); + append_menu_item (submenu, _("Taboo -- Never Install"), NULL, NULL, this); + //append_menu_item (submenu, _("Show solver information"), NULL, NULL, this); + append_menu_item (submenu, NULL, NULL, NULL, NULL); + subitem = append_menu_item (submenu, _("All in This List"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (subitem), (sub3menu = gtk_menu_new())); + append_menu_item (sub3menu, _("Install"), NULL, NULL, this); + append_menu_item (sub3menu, _("Do Not Install"), NULL, NULL, this); + append_menu_item (sub3menu, _("Keep"), NULL, NULL, this); + append_menu_item (sub3menu, _("Delete"), NULL, NULL, this); + append_menu_item (sub3menu, _("Update if newer version available"), NULL, NULL, this); + append_menu_item (sub3menu, _("Update unconditionally"), NULL, NULL, this); + append_menu_item (sub3menu, _("Taboo -- Never Install"), NULL, NULL, this); + append_menu_item (sub3menu, _("Protected -- Do Not Modify"), NULL, NULL, this); + subitem = append_menu_item (submenu, _("All Packages"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (subitem), (sub3menu = gtk_menu_new())); + append_menu_item (sub3menu, _("Update if newer version available"), NULL, NULL, this); + append_menu_item (sub3menu, _("Update unconditionally"), NULL, NULL, this); + item = append_menu_item (menu_bar, _("Configuration"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new())); + append_menu_item (submenu, _("Repositories..."), NULL, NULL, this); + append_menu_item (submenu, _("Online Update..."), NULL, NULL, this); + append_menu_item (submenu, _("Search Packages on Web..."), NULL, NULL, this); + item = append_menu_item (menu_bar, _("Dependencies"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new())); + append_menu_item (submenu, _("Check Now"), NULL, NULL, this); + append_menu_item (submenu, _("Autocheck"), NULL, NULL, this); + item = append_menu_item (menu_bar, _("Options"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new())); + append_menu_item (submenu, _("Show -devel packages"), NULL, NULL, this); + append_menu_item (submenu, _("Show -debuginfo/-debugsource Packages"), NULL, NULL, this); + append_menu_item (submenu, _("System Verification Mode"), NULL, NULL, this); + item = append_menu_item (menu_bar, _("Extras"), NULL, NULL, NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new())); + append_menu_item (submenu, _("Show Products"), NULL, NULL, this); + append_menu_item (submenu, _("Show Package Changes"), NULL, NULL, this); + append_menu_item (submenu, NULL, NULL, NULL, NULL); + append_menu_item (submenu, _("Install All Matching -debug-info Packages"), NULL, NULL, this); + append_menu_item (submenu, _("Install All Matching -debug-source Packages"), NULL, NULL, this); + append_menu_item (submenu, NULL, NULL, NULL, NULL); + append_menu_item (submenu, _("Generate Dependency Resolver Test Case"), NULL, NULL, this); + append_menu_item (submenu, _("Reset Ignored Dependency Conflicts"), NULL, NULL, this); gtk_widget_show_all (menu_bar); - ygtk_wizard_set_custom_menu (wizard, menu_bar); -#endif + ygtk_wizard_set_custom_menu (wizard, menu_bar, FALSE); m_progressbar = gtk_progress_bar_new(); GtkWidget *empty = gtk_event_box_new(); @@ -4215,7 +4400,7 @@ return confirmPkgs (_("Dependencies from Filtered Repositories"), _("The following packages have necessary dependencies that are not provided " "by the filtered repository. Install them?"), GTK_MESSAGE_WARNING, list, - "repository"); + _("Repository"), REPOSITORY_PROP); } virtual void loading (float progress) @@ -4240,6 +4425,28 @@ } } + // utilities + static GtkWidget *append_menu_item (GtkWidget *menu, const char *text, + const char *stock, GCallback callback, gpointer callback_data) + { + GtkWidget *item; + if (stock && text) { + GtkWidget *icon = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU); + item = gtk_image_menu_item_new_with_label (text); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon); + } + else if (text) + item = gtk_menu_item_new_with_label (text); + else if (stock) + item = gtk_image_menu_item_new_from_stock (stock, NULL); + else + item = gtk_separator_menu_item_new(); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + if (callback) + g_signal_connect (G_OBJECT (item), "activate", callback, callback_data); + return item; + } + YGWIDGET_IMPL_COMMON (YPackageSelector) }; Modified: trunk/gtk/src/pkg/ygtkdetailview.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/ygtkdetailview.cc?rev... ============================================================================== --- trunk/gtk/src/pkg/ygtkdetailview.cc (original) +++ trunk/gtk/src/pkg/ygtkdetailview.cc Tue Jan 26 17:10:22 2010 @@ -24,432 +24,411 @@ //** Utilities -#define BROWSER_PATH "/usr/bin/firefox" -#define GNOME_OPEN_PATH "/usr/bin/gnome-open" -inline bool CAN_OPEN_URL() -{ return g_file_test (BROWSER_PATH, G_FILE_TEST_IS_EXECUTABLE); } -inline bool CAN_OPEN_DIRNAME() -{ return g_file_test (GNOME_OPEN_PATH, G_FILE_TEST_IS_EXECUTABLE); } - -void run (const std::string &cmd, bool as_user) -{ - std::string prepend, append; - if (as_user && getuid() == 0) { - char *username = getenv ("USERNAME"); - if (username && *username && strcmp (username, "root") != 0) { - prepend.reserve (64); - prepend = "gnomesu -u "; - prepend += username; - prepend += " -c ""; - append = """; - } - } - system (((prepend + cmd + append) + " &").c_str()); -} - -void OPEN_URL (const char *uri) -{ - std::string command; - command.reserve (256); - command = BROWSER_PATH " --new-window "; - command += uri; - run (command, true); -} -void OPEN_DIRNAME (const char *uri) -{ - std::string command; - command.reserve (256); - command = GNOME_OPEN_PATH " "; - command += uri; - run (command, false); -} +#define BROWSER_BIN "/usr/bin/firefox" +#define GNOME_OPEN_BIN "/usr/bin/gnome-open" static const char *onlyInstalledMsg = _("<i>Information only available for installed packages.</i>"); //** Detail & control -class YGtkDetailView::Impl -{ -private: - struct Versions : public Ypp::PkgList::Listener { - GtkWidget *m_box, *m_versions_box, *m_button, *m_undo_button; - Ypp::PkgList m_packages; // we keep a copy to test against modified... - bool m_onlineUpdate; - - GtkWidget *getWidget() { return m_box; } - - Versions (bool onlineUpdate) : m_onlineUpdate (onlineUpdate) - { - GtkWidget *label = gtk_label_new (_("Versions:")); - YGUtils::setWidgetFont (label, PANGO_STYLE_NORMAL, PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - m_versions_box = gtk_vbox_new (FALSE, 2); - m_button = gtk_button_new_with_label (""); - g_signal_connect (G_OBJECT (m_button), "clicked", G_CALLBACK (button_clicked_cb), this); - GtkSettings *settings = gtk_settings_get_default(); - gboolean show_button_images; - g_object_get (settings, "gtk-button-images", &show_button_images, NULL); - if (show_button_images) { - m_undo_button = gtk_button_new_with_label (""); - gtk_button_set_image (GTK_BUTTON (m_undo_button), - gtk_image_new_from_stock (GTK_STOCK_UNDO, GTK_ICON_SIZE_BUTTON)); - gtk_widget_set_tooltip_text (m_undo_button, _("Undo")); - } - else - m_undo_button = gtk_button_new_with_label (_("Undo")); - g_signal_connect (G_OBJECT (m_undo_button), "clicked", G_CALLBACK (undo_clicked_cb), this); - GtkWidget *button_box = gtk_hbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (button_box), gtk_label_new(""), TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (button_box), m_button, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (button_box), m_undo_button, FALSE, TRUE, 0); - - m_box = gtk_vbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (m_box), label, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (m_box), m_versions_box, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (m_box), button_box, FALSE, TRUE, 0); - - // PkgList::addListeners() isn't currently working for ordinary PkgList - // other than getPackages(), thus this hack. - if (!m_onlineUpdate) - Ypp::get()->getPackages (Ypp::Package::PACKAGE_TYPE).addListener (this); - } - - ~Versions() - { - if (!m_onlineUpdate) - Ypp::get()->getPackages (Ypp::Package::PACKAGE_TYPE).removeListener (this); - } - - void setPackages (Ypp::PkgList packages) - { - m_packages = packages; - - GList *children = gtk_container_get_children (GTK_CONTAINER (m_versions_box)); - for (GList *i = children; i; i = i->next) - gtk_container_remove (GTK_CONTAINER (m_versions_box), (GtkWidget *) i->data); - g_list_free (children); - - if (packages.size() == 0) { - gtk_widget_hide (m_box); - return; - } - gtk_widget_show (m_box); - if (packages.size() == 1) { - Ypp::Package *package = packages.get (0); +struct Versions { + GtkWidget *m_box, *m_versions_box, *m_button, *m_undo_button; + Ypp::PkgList m_packages; + + GtkWidget *getWidget() { return m_box; } + + Versions() + { + m_versions_box = gtk_vbox_new (FALSE, 2); + m_button = gtk_button_new_with_label (""); + g_signal_connect (G_OBJECT (m_button), "clicked", G_CALLBACK (button_clicked_cb), this); + GtkSettings *settings = gtk_settings_get_default(); + gboolean show_button_images; + g_object_get (settings, "gtk-button-images", &show_button_images, NULL); + if (show_button_images) { + m_undo_button = gtk_button_new_with_label (""); + gtk_button_set_image (GTK_BUTTON (m_undo_button), + gtk_image_new_from_stock (GTK_STOCK_UNDO, GTK_ICON_SIZE_BUTTON)); + gtk_widget_set_tooltip_text (m_undo_button, _("Undo")); + } + else + m_undo_button = gtk_button_new_with_label (_("Undo")); + g_signal_connect (G_OBJECT (m_undo_button), "clicked", G_CALLBACK (undo_clicked_cb), this); + GtkWidget *button_box = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (button_box), gtk_label_new(""), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (button_box), m_button, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (button_box), m_undo_button, FALSE, TRUE, 0); + + m_box = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (m_box), m_versions_box, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_box), button_box, FALSE, TRUE, 0); + g_object_set_data (G_OBJECT (getWidget()), "class", this); + } - int children = 0; - GtkWidget *radio = 0; - const Ypp::Package::Version *version; - if ((version = package->getInstalledVersion())) { - std::string _version = YGUtils::truncate (version->number, 20, 0); - - bool italic = package->toRemove(); - char *text = g_strdup_printf ("%s%s <small>(%s)</small>\n%s%s", - italic ? "<i>" : "", - _version.c_str(), version->arch.c_str(), _("Installed"), - italic ? "</i>" : ""); - radio = gtk_radio_button_new_with_label (NULL, text); - gtk_label_set_use_markup (GTK_LABEL (GTK_BIN (radio)->child), TRUE); - if (version->number.size() > 20) { - char *text = g_strdup_printf ("%s <small>(%s)</small>\n%s", - version->number.c_str(), version->arch.c_str(), _("Installed")); - gtk_widget_set_tooltip_markup (radio, text); - g_free (text); - } - gtk_box_pack_start (GTK_BOX (m_versions_box), radio, FALSE, TRUE, 0); + void setPackages (Ypp::PkgList packages) + { + m_packages = packages; + + GList *children = gtk_container_get_children (GTK_CONTAINER (m_versions_box)); + for (GList *i = children; i; i = i->next) + gtk_container_remove (GTK_CONTAINER (m_versions_box), (GtkWidget *) i->data); + g_list_free (children); + + if (packages.size() == 0) { + gtk_widget_hide (m_box); + return; + } + gtk_widget_show (m_box); + if (packages.size() == 1) { + Ypp::Package *package = packages.get (0); + + int children = 0; + GtkWidget *radio = 0; + const Ypp::Package::Version *version; + if ((version = package->getInstalledVersion())) { + std::string _version = YGUtils::truncate (version->number, 20, 0); + + bool italic = package->toRemove(); + char *text = g_strdup_printf ("%s%s <small>(%s)</small>\n%s%s", + italic ? "<i>" : "", + _version.c_str(), version->arch.c_str(), _("Installed"), + italic ? "</i>" : ""); + radio = gtk_radio_button_new_with_label (NULL, text); + gtk_label_set_use_markup (GTK_LABEL (GTK_BIN (radio)->child), TRUE); + if (version->number.size() > 20) { + char *text = g_strdup_printf ("%s <small>(%s)</small>\n%s", + version->number.c_str(), version->arch.c_str(), _("Installed")); + gtk_widget_set_tooltip_markup (radio, text); g_free (text); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); - g_object_set_data (G_OBJECT (radio), "version", (void *) version); - g_signal_connect (G_OBJECT (radio), "toggled", - G_CALLBACK (version_toggled_cb), this); - children++; } - bool activeSet = package->toRemove(); - const Ypp::Package::Version *toInstall = 0; - if (!package->toInstall (&toInstall)) - toInstall = 0; - const Ypp::Repository *favoriteRepo = Ypp::get()->favoriteRepository(); - for (int i = 0; (version = package->getAvailableVersion (i)); i++) { - std::string _version = YGUtils::truncate (version->number, 20, 0); - std::string repo; - if (version->repo) - repo = YGUtils::truncate (version->repo->name, 22, 0); - - bool italic = toInstall == version; - char *text = g_strdup_printf ("%s%s <small>(%s)</small>\n%s%s", - italic ? "<i>" : "", - _version.c_str(), version->arch.c_str(), repo.c_str(), - italic ? "</i>" : ""); - radio = gtk_radio_button_new_with_label_from_widget ( - GTK_RADIO_BUTTON (radio), text); - gtk_label_set_use_markup (GTK_LABEL (GTK_BIN (radio)->child), TRUE); + gtk_box_pack_start (GTK_BOX (m_versions_box), radio, FALSE, TRUE, 0); + g_free (text); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + g_object_set_data (G_OBJECT (radio), "version", (void *) version); + g_signal_connect (G_OBJECT (radio), "toggled", + G_CALLBACK (version_toggled_cb), this); + children++; + } + bool activeSet = package->toRemove(); + const Ypp::Package::Version *toInstall = 0; + if (!package->toInstall (&toInstall)) + toInstall = 0; + const Ypp::Repository *favoriteRepo = Ypp::get()->favoriteRepository(); + for (int i = 0; (version = package->getAvailableVersion (i)); i++) { + std::string _version = YGUtils::truncate (version->number, 20, 0); + std::string repo; + if (version->repo) + repo = YGUtils::truncate (version->repo->name, 22, 0); + + bool italic = toInstall == version; + char *text = g_strdup_printf ("%s%s <small>(%s)</small>\n%s%s", + italic ? "<i>" : "", + _version.c_str(), version->arch.c_str(), repo.c_str(), + italic ? "</i>" : ""); + radio = gtk_radio_button_new_with_label_from_widget ( + GTK_RADIO_BUTTON (radio), text); + gtk_label_set_use_markup (GTK_LABEL (GTK_BIN (radio)->child), TRUE); + g_free (text); + if (version->number.size() > 20 || + (version->repo && version->repo->name.size() > 22)) { + char *text = g_strdup_printf ("%s <small>(%s)</small>\n%s", + version->number.c_str(), version->arch.c_str(), + version->repo ? version->repo->name.c_str() : ""); + gtk_widget_set_tooltip_markup (radio, text); g_free (text); - if (version->number.size() > 20 || - (version->repo && version->repo->name.size() > 22)) { - char *text = g_strdup_printf ("%s <small>(%s)</small>\n%s", - version->number.c_str(), version->arch.c_str(), - version->repo ? version->repo->name.c_str() : ""); - gtk_widget_set_tooltip_markup (radio, text); - g_free (text); + } + gtk_box_pack_start (GTK_BOX (m_versions_box), radio, FALSE, TRUE, 0); + if (!activeSet) { + if (toInstall == version) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + activeSet = true; } - gtk_box_pack_start (GTK_BOX (m_versions_box), radio, FALSE, TRUE, 0); - if (!activeSet) { - if (toInstall == version) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); - activeSet = true; - } - else if (i == 0 && (!package->isInstalled() || version->cmp > 0)) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); - else if (version->repo == favoriteRepo) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); - favoriteRepo = 0; // select only the 1st hit - } + else if (i == 0 && (!package->isInstalled() || version->cmp > 0)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + else if (version->repo == favoriteRepo) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + favoriteRepo = 0; // select only the 1st hit } - g_object_set_data (G_OBJECT (radio), "version", (void *) version); - g_signal_connect (G_OBJECT (radio), "toggled", - G_CALLBACK (version_toggled_cb), this); - if ((children % 2) == 1) - g_signal_connect (G_OBJECT (radio), "expose-event", G_CALLBACK (draw_gray_cb), this); - children++; } - gtk_widget_show_all (m_versions_box); - } - - // is locked - if (packages.locked() || packages.unlocked()) - gtk_widget_set_sensitive (m_button, !packages.locked()); - else - gtk_widget_set_sensitive (m_button, TRUE); - syncButton(); + g_object_set_data (G_OBJECT (radio), "version", (void *) version); + g_signal_connect (G_OBJECT (radio), "toggled", + G_CALLBACK (version_toggled_cb), this); + if ((children % 2) == 1) + g_signal_connect (G_OBJECT (radio), "expose-event", G_CALLBACK (draw_gray_cb), this); + children++; + } + gtk_widget_show_all (m_versions_box); } - private: - virtual void entryChanged (const Ypp::PkgList list, int index, Ypp::Package *package) - { - if (m_packages.contains (package)) - setPackages (m_packages); // refresh ! - } - // won't happen: - virtual void entryInserted (const Ypp::PkgList list, int index, Ypp::Package *package) {} - virtual void entryDeleted (const Ypp::PkgList list, int index, Ypp::Package *package) {} - - static gboolean draw_gray_cb (GtkWidget *widget, GdkEventExpose *event, Versions *pThis) - { - GtkAllocation *alloc = &widget->allocation; - int x = alloc->x, y = alloc->y, w = alloc->width, h = alloc->height; - - cairo_t *cr = gdk_cairo_create (widget->window); - cairo_rectangle (cr, x, y, w, h); - cairo_set_source_rgb (cr, 245/255.0, 245/255.0, 245/255.0); - cairo_fill (cr); - cairo_destroy (cr); - return FALSE; - } + // is locked + if (packages.isLocked() || packages.isUnlocked()) + gtk_widget_set_sensitive (m_button, !packages.isLocked()); + else + gtk_widget_set_sensitive (m_button, TRUE); + syncButton(); + } - const Ypp::Package::Version *getVersion() - { - GtkWidget *radio = 0; - GList *children = gtk_container_get_children (GTK_CONTAINER (m_versions_box)); - for (GList *i = children; i; i = i->next) - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (i->data))) { - radio = (GtkWidget *) i->data; - break; - } - g_list_free (children); - if (radio) - return (Ypp::Package::Version *) g_object_get_data (G_OBJECT (radio), "version"); - return NULL; - } - - void syncButton() - { - const char *label = 0, *stock = 0; - bool modified = false; - if (m_packages.size() == 1) { - Ypp::Package *package = m_packages.get (0); - const Ypp::Package::Version *version = getVersion(); - const Ypp::Package::Version *installed = package->getInstalledVersion(); - if (installed == version) { - label = _("Remove"); - stock = GTK_STOCK_DELETE; - if (package->toRemove()) - modified = true; - } - else { - if (installed) { - if (version->cmp > 0) { - label = _("Upgrade"); - stock = GTK_STOCK_GO_UP; - } - else if (version->cmp < 0) { - label = _("Downgrade"); - stock = GTK_STOCK_GO_DOWN; - } - else { - label = _("Re-install"); - stock = GTK_STOCK_REFRESH; - } - } - else { - label = _("Install"); - stock = GTK_STOCK_SAVE; - } +private: + static gboolean draw_gray_cb (GtkWidget *widget, GdkEventExpose *event, Versions *pThis) + { + GtkAllocation *alloc = &widget->allocation; + int x = alloc->x, y = alloc->y, w = alloc->width, h = alloc->height; - const Ypp::Package::Version *toInstall = 0; - if (!package->toInstall (&toInstall)) - toInstall = 0; - if (toInstall == version) - modified = true; - } + cairo_t *cr = gdk_cairo_create (widget->window); + cairo_rectangle (cr, x, y, w, h); + cairo_set_source_rgb (cr, 245/255.0, 245/255.0, 245/255.0); + cairo_fill (cr); + cairo_destroy (cr); + return FALSE; + } + + const Ypp::Package::Version *getVersion() + { + GtkWidget *radio = 0; + GList *children = gtk_container_get_children (GTK_CONTAINER (m_versions_box)); + for (GList *i = children; i; i = i->next) + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (i->data))) { + radio = (GtkWidget *) i->data; + break; } - else { - if (m_packages.modified()) + g_list_free (children); + if (radio) + return (Ypp::Package::Version *) g_object_get_data (G_OBJECT (radio), "version"); + return NULL; + } + + void syncButton() + { + const char *label = 0, *stock = 0; + bool modified = false; + if (m_packages.size() == 1) { + Ypp::Package *package = m_packages.get (0); + const Ypp::Package::Version *version = getVersion(); + const Ypp::Package::Version *installed = package->getInstalledVersion(); + if (installed == version) { + label = _("Remove"); + stock = GTK_STOCK_DELETE; + if (package->toRemove()) modified = true; - if (m_packages.upgradable()) { - label = _("Upgrade"); - stock = GTK_STOCK_GO_UP; - } - else if (m_packages.installed()) { - label = _("Remove"); - stock = GTK_STOCK_DELETE; + } + else { + if (installed) { + if (version->cmp > 0) { + label = _("Upgrade"); + stock = GTK_STOCK_GO_UP; + } + else if (version->cmp < 0) { + label = _("Downgrade"); + stock = GTK_STOCK_GO_DOWN; + } + else { + label = _("Re-install"); + stock = GTK_STOCK_REFRESH; + } } - else if (m_packages.notInstalled()) { + else { label = _("Install"); stock = GTK_STOCK_SAVE; } - else if (m_packages.modified()) { - label = _("Undo"); - stock = GTK_STOCK_UNDO; - modified = false; - } - } - if (label) { - gtk_button_set_label (GTK_BUTTON (m_button), label); - GtkWidget *image = gtk_image_new_from_stock ( - stock, GTK_ICON_SIZE_BUTTON); - gtk_button_set_image (GTK_BUTTON (m_button), image); - gtk_widget_show (m_button); + + const Ypp::Package::Version *toInstall = 0; + if (!package->toInstall (&toInstall)) + toInstall = 0; + if (toInstall == version) + modified = true; } + } + else { + if (m_packages.toModify()) + modified = true; + if (m_packages.hasUpgrade()) { + label = _("Upgrade"); + stock = GTK_STOCK_GO_UP; + } + else if (m_packages.isInstalled()) { + label = _("Remove"); + stock = GTK_STOCK_DELETE; + } + else if (m_packages.isNotInstalled()) { + label = _("Install"); + stock = GTK_STOCK_SAVE; + } + else if (m_packages.toModify()) { + label = _("Undo"); + stock = GTK_STOCK_UNDO; + modified = false; + } + } + if (label) { + gtk_button_set_label (GTK_BUTTON (m_button), label); + GtkWidget *image = gtk_image_new_from_stock ( + stock, GTK_ICON_SIZE_BUTTON); + gtk_button_set_image (GTK_BUTTON (m_button), image); + gtk_widget_show (m_button); + } + else + gtk_widget_hide (m_button); + gtk_widget_set_sensitive (m_button, !modified); + modified ? gtk_widget_show (m_undo_button) : gtk_widget_hide (m_undo_button); + } + + static void version_toggled_cb (GtkToggleButton *radio, Versions *pThis) + { if (gtk_toggle_button_get_active (radio)) pThis->syncButton(); } + + static void button_clicked_cb (GtkButton *button, Versions *pThis) + { + if (pThis->m_packages.size() == 1) { + Ypp::Package *package = pThis->m_packages.get (0); + const Ypp::Package::Version *version = pThis->getVersion(); + const Ypp::Package::Version *installed = package->getInstalledVersion(); + if (installed == version) + pThis->m_packages.remove(); else - gtk_widget_hide (m_button); - gtk_widget_set_sensitive (m_button, !modified); - modified ? gtk_widget_show (m_undo_button) : gtk_widget_hide (m_undo_button); - } - - static void version_toggled_cb (GtkToggleButton *radio, Versions *pThis) - { if (gtk_toggle_button_get_active (radio)) pThis->syncButton(); } - - static void button_clicked_cb (GtkButton *button, Versions *pThis) - { - if (pThis->m_packages.size() == 1) { - Ypp::Package *package = pThis->m_packages.get (0); - const Ypp::Package::Version *version = pThis->getVersion(); - const Ypp::Package::Version *installed = package->getInstalledVersion(); - if (installed == version) - pThis->m_packages.remove(); - else - package->install (version); - } - else { - if (pThis->m_packages.upgradable()) - pThis->m_packages.install(); - else if (pThis->m_packages.installed()) - pThis->m_packages.remove(); - else if (pThis->m_packages.notInstalled()) - pThis->m_packages.install(); - else if (pThis->m_packages.modified()) - pThis->m_packages.undo(); - } + package->install (version); } - - static void undo_clicked_cb (GtkButton *button, Versions *pThis) - { - pThis->m_packages.undo(); + else { + if (pThis->m_packages.hasUpgrade()) + pThis->m_packages.install(); + else if (pThis->m_packages.isInstalled()) + pThis->m_packages.remove(); + else if (pThis->m_packages.isNotInstalled()) + pThis->m_packages.install(); + else if (pThis->m_packages.toModify()) + pThis->m_packages.undo(); } - }; + } + + static void undo_clicked_cb (GtkButton *button, Versions *pThis) + { + pThis->m_packages.undo(); + } +}; -GtkWidget *m_scroll, *m_icon, *m_icon_frame, *m_description, *m_filelist, *m_changelog, - *m_authors, *m_support, *m_requires, *m_provides, *m_contents; +class YGtkDetailView::Impl : public Ypp::PkgList::Listener +{ +GtkWidget *m_scroll, *m_icon, *m_icon_frame, *m_name, *m_description, + *m_filelist, *m_changelog, *m_authors, *m_support, *m_dependencies, + *m_contents, *m_details, *m_versions_exp; +GtkWidget *m_link_popup; +std::string m_link_str; Versions *m_versions; bool m_verMode; +Ypp::PkgList m_packages; // we keep a copy to test against modified... +bool m_onlineUpdate; public: Impl (GtkWidget *scroll, bool onlineUpdate) - : m_verMode (false) + : m_verMode (false), m_onlineUpdate (onlineUpdate) { m_scroll = scroll; - m_versions = new Versions (onlineUpdate); + m_versions = new Versions(); GtkWidget *hbox = gtk_hbox_new (FALSE, 2); setupScrollAsWhite (scroll, hbox); - GtkWidget *versions_box = gtk_vbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (versions_box), - createIconWidget (&m_icon, &m_icon_frame), FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (versions_box), m_versions->getWidget(), FALSE, TRUE, 0); + GtkWidget *side_box = gtk_vbox_new (FALSE, 0); + m_versions_exp = appendExpander (side_box, _("Versions"), m_versions->getWidget(), versions_cb); + m_details = ygtk_rich_text_new(); + m_details = appendExpander (side_box, _("Details"), m_details, details_cb); + gtk_widget_set_size_request (m_details, 140, -1); + gtk_expander_set_expanded (GTK_EXPANDER (m_details), TRUE); GtkWidget *vbox = gtk_vbox_new (FALSE, 0); + m_name = ygtk_rich_text_new(); + GtkWidget *header_box = gtk_hbox_new (FALSE, 2); + gtk_box_pack_start (GTK_BOX (header_box), m_name, TRUE, TRUE, 0); + m_icon_frame = m_icon = gtk_image_new(); + gtk_box_pack_start (GTK_BOX (header_box), m_icon, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), header_box, FALSE, TRUE, 0); + m_description = ygtk_rich_text_new(); g_signal_connect (G_OBJECT (m_description), "link-clicked", - G_CALLBACK (link_pressed_cb), this); + G_CALLBACK (link_clicked_cb), this); gtk_box_pack_start (GTK_BOX (vbox), m_description, FALSE, TRUE, 0); - m_filelist = m_changelog = m_authors = m_support = m_requires = m_provides = m_contents = 0; + m_filelist = m_changelog = m_authors = m_support = m_dependencies = m_contents = 0; if (!onlineUpdate) { m_filelist = ygtk_rich_text_new(); - if (CAN_OPEN_DIRNAME()) - g_signal_connect (G_OBJECT (m_filelist), "link-clicked", - G_CALLBACK (dirname_pressed_cb), this); - m_changelog = ygtk_rich_text_new(); - m_authors = ygtk_rich_text_new(); + g_signal_connect (G_OBJECT (m_filelist), "link-clicked", + G_CALLBACK (dirname_pressed_cb), this); m_support = ygtk_rich_text_new(); - GtkWidget *dependencies_box = gtk_hbox_new (TRUE, 0); - m_requires = ygtk_rich_text_new(); - m_provides = ygtk_rich_text_new(); - gtk_box_pack_start (GTK_BOX (dependencies_box), m_requires, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (dependencies_box), m_provides, TRUE, TRUE, 0); - - appendExpander (vbox, _("File List"), m_filelist); - appendExpander (vbox, _("Changelog"), m_changelog); - appendExpander (vbox, _("Authors"), m_authors); - appendExpander (vbox, _("Dependencies"), dependencies_box); - appendExpander (vbox, "", m_support); + m_dependencies = gtk_hbox_new (TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_dependencies), ygtk_rich_text_new(), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_dependencies), ygtk_rich_text_new(), TRUE, TRUE, 0); + + m_filelist = appendExpander (vbox, _("File List"), m_filelist, filelist_cb); + m_changelog = appendExpander (vbox, _("Changelog"), ygtk_rich_text_new(), changelog_cb); + m_authors = appendExpander (vbox, _("Authors"), ygtk_rich_text_new(), authors_cb); + m_dependencies = appendExpander (vbox, _("Dependencies"), m_dependencies, dependencies_cb); + m_support = appendExpander (vbox, "", m_support, NULL); } else { YGtkPackageView *contents; m_contents = GTK_WIDGET (contents = ygtk_package_view_new (TRUE)); gtk_widget_set_size_request (m_contents, -1, 150); - appendExpander (vbox, _("Applies to"), m_contents); + m_contents = appendExpander (vbox, _("Applies to"), m_contents, contents_cb); } gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), versions_box, FALSE, TRUE, 0); - gtk_widget_show_all (hbox); + gtk_box_pack_start (GTK_BOX (hbox), side_box, FALSE, TRUE, 0); g_signal_connect (G_OBJECT (scroll), "hierarchy-changed", G_CALLBACK (hierarchy_changed_cb), this); g_signal_connect (G_OBJECT (scroll), "realize", G_CALLBACK (realize_cb), this); + + // PkgList::addListeners() isn't currently working for ordinary PkgList + // other than getPackages(), thus this hack. + if (!m_onlineUpdate) + Ypp::get()->getPackages (Ypp::Package::PACKAGE_TYPE).addListener (this); + gtk_widget_show_all (hbox); } ~Impl() - { delete m_versions; } + { + delete m_versions; + if (!m_onlineUpdate) + Ypp::get()->getPackages (Ypp::Package::PACKAGE_TYPE).removeListener (this); + } + + void refreshPackages (Ypp::PkgList packages) + { + std::string name; + name.reserve (1024); + if (packages.size() > 0) { + name = "<p bgcolor=""; + name += packages.toModify() ? "#f4f4b7" : "#ededed"; + name += "">"; + if (packages.size() == 1) { + Ypp::Package *package = packages.get (0); + name += "<b>" + package->name() + "</b> - " + package->summary(); + } + else { + name += "<b>"; + name += _("Several selected"); + name += "</b>"; + } + name += "</p>"; + } + ygtk_rich_text_set_text (YGTK_RICH_TEXT (m_name), name.c_str()); + ygtk_expander_update (m_versions_exp); + } void setPackages (Ypp::PkgList packages) { + m_packages = packages; + gtk_widget_hide (m_icon_frame); Ypp::Package *package = 0; if (packages.size() == 1) { package = packages.get (0); - std::string description = "<b>" + package->name() + "</b><br>"; - description += package->description (HTML_MARKUP); + std::string description (package->description (HTML_MARKUP)); ygtk_rich_text_set_text (YGTK_RICH_TEXT (m_description), description.c_str()); if (m_support) { std::string label ("<b>" + std::string (_("Supportability:")) + "</b> "); label += package->support(); - gtk_expander_set_label (GTK_EXPANDER (m_support->parent), label.c_str()); - ygtk_rich_text_set_text (YGTK_RICH_TEXT (m_support), + gtk_expander_set_label (GTK_EXPANDER (m_support), label.c_str()); + ygtk_rich_text_set_text (YGTK_RICH_TEXT (GTK_BIN (m_support)->child), package->supportText (HTML_MARKUP).c_str()); - gtk_widget_show (m_support->parent); + gtk_widget_show (m_support); } gtk_image_clear (GTK_IMAGE (m_icon)); GtkIconTheme *icons = gtk_icon_theme_get_default(); @@ -460,17 +439,10 @@ g_object_unref (G_OBJECT (pixbuf)); gtk_widget_show (m_icon_frame); } - setPassiveUpdate (m_filelist, filelist_cb, package); - setPassiveUpdate (m_changelog, changelog_cb, package); - setPassiveUpdate (m_authors, authors_cb, package); - setPassiveUpdate (m_requires, requires_cb, package); - setPassiveUpdate (m_provides, provides_cb, package); - setPassiveUpdate (m_contents, contents_cb, package); } else { std::string description; if (packages.size() > 0) { - description = _("Selected:"); description += "<ul>"; for (int i = 0; packages.get (i); i++) description += "<li>" + packages.get (i)->name() + "</li>"; @@ -478,23 +450,25 @@ } ygtk_rich_text_set_text (YGTK_RICH_TEXT (m_description), description.c_str()); if (m_support) - gtk_widget_hide (m_support->parent); - setPassiveUpdate (m_filelist, NULL, NULL); - setPassiveUpdate (m_changelog, NULL, NULL); - setPassiveUpdate (m_authors, NULL, NULL); - setPassiveUpdate (m_requires, NULL, NULL); - setPassiveUpdate (m_provides, NULL, NULL); - setPassiveUpdate (m_contents, NULL, NULL); + gtk_widget_hide (m_support); } - m_versions->setPackages (packages); + ygtk_expander_update (m_filelist); + ygtk_expander_update (m_changelog); + ygtk_expander_update (m_authors); + ygtk_expander_update (m_dependencies); + ygtk_expander_update (m_contents); + ygtk_expander_update (m_details); + + refreshPackages (packages); scrollTop(); } void setPackage (Ypp::Package *package) { Ypp::PkgList packages; - packages.append (package); + if (package) + packages.append (package); setPackages (packages); } @@ -506,6 +480,17 @@ } private: + virtual void entryChanged (const Ypp::PkgList list, int index, Ypp::Package *package) + { + if (m_packages.contains (package)) { + m_packages.refreshProps(); + refreshPackages (m_packages); + } + } + // won't happen: + virtual void entryInserted (const Ypp::PkgList list, int index, Ypp::Package *package) {} + virtual void entryDeleted (const Ypp::PkgList list, int index, Ypp::Package *package) {} + void scrollTop() { GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW (m_scroll); @@ -514,25 +499,6 @@ } // utilities: - static GtkWidget *createIconWidget (GtkWidget **icon_widget, GtkWidget **icon_frame) - { - *icon_widget = gtk_image_new(); - - GtkWidget *box, *align, *frame; - box = gtk_event_box_new(); - gtk_container_add (GTK_CONTAINER (box), *icon_widget); - gtk_container_set_border_width (GTK_CONTAINER (box), 2); - - frame = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (frame), box); - - align = gtk_alignment_new (0, 0, 0, 0); - gtk_container_add (GTK_CONTAINER (align), frame); - gtk_container_set_border_width (GTK_CONTAINER (align), 6); - *icon_frame = align; - return align; - } - static void setupScrollAsWhite (GtkWidget *scroll, GtkWidget *box) { struct inner { @@ -556,38 +522,103 @@ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), box); } - static GtkWidget *appendExpander (GtkWidget *box, const char *label, GtkWidget *child) + typedef bool (*UpdateCb) (GtkWidget *widget, Ypp::PkgList list); + GtkWidget *appendExpander (GtkWidget *box, const char *label, GtkWidget *child, UpdateCb update_cb) { std::string str = std::string ("<b>") + label + "</b>"; GtkWidget *expander = gtk_expander_new (str.c_str()); gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE); gtk_container_add (GTK_CONTAINER (expander), child); gtk_box_pack_start (GTK_BOX (box), expander, FALSE, TRUE, 0); + if (update_cb) { + g_object_set_data (G_OBJECT (expander), "update-cb", (gpointer) update_cb); + g_signal_connect_after (G_OBJECT (expander), "notify::expanded", + G_CALLBACK (ygtk_expander_expanded_cb), this); + } return expander; } // callbacks - static void link_pressed_cb (GtkWidget *text, const gchar *link, Impl *pThis) + static void link_clicked_cb (YGtkRichText *text, const gchar *link, Impl *pThis) { - if (!strncmp (link, "pkg://", 6)) { - const gchar *pkg_name = link + 6; - Ypp::Package *pkg = Ypp::get()->getPackages (Ypp::Package::PACKAGE_TYPE).find (pkg_name); - if (pkg) - pThis->setPackage (pkg); - else { - GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(), - GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, _("Package '%s' was not found."), pkg_name); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - } + if (!pThis->m_link_popup) { + GtkWidget *menu = pThis->m_link_popup = gtk_menu_new(); + gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (text), NULL); + + GtkWidget *item; + if (g_file_test (BROWSER_BIN, G_FILE_TEST_IS_EXECUTABLE)) { + std::string label; + if (getuid() == 0) { + const char *username = getenv ("USERNAME"); + if (!username || !(*username)) + username = "root"; + label = _("_Open (as "); + label += username; + label += ")"; + } + else + label = _("_Open"); + item = gtk_image_menu_item_new_with_mnemonic (label.c_str()); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), + gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU)); + gtk_widget_show (item); + g_signal_connect (G_OBJECT (item), "activate", + G_CALLBACK (open_link_cb), pThis); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + } + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL); + gtk_widget_show (item); + g_signal_connect (G_OBJECT (item), "activate", + G_CALLBACK (copy_link_cb), pThis); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + } + gtk_menu_popup (GTK_MENU (pThis->m_link_popup), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time()); + pThis->m_link_str = link; + } + + static void open_link_cb (GtkMenuItem *item, Impl *pThis) + { + const std::string &link = pThis->m_link_str; + std::string command; + command.reserve (256); + + const char *username = 0; + if (getuid() == 0) { + username = getenv ("USERNAME"); + if (username && !(*username)) + username = 0; + } + + if (username) { + command += "gnomesu -u "; + command += username; + command += " -c "" BROWSER_BIN " --new-window "; + command += link; + command += """; } - else - OPEN_URL (link); + else { + command += BROWSER_BIN " --new-window "; + command += link; + } + command += " &"; + system (command.c_str()); + } + + static void copy_link_cb (GtkMenuItem *item, Impl *pThis) + { + const std::string &link = pThis->m_link_str; + GtkClipboard *clipboard = + gtk_widget_get_clipboard (pThis->m_description, GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text (clipboard, link.c_str(), -1); } static void dirname_pressed_cb (GtkWidget *text, const gchar *link, Impl *pThis) - { OPEN_DIRNAME (link); } + { + gchar *cmd = g_strdup_printf (GNOME_OPEN_BIN " %s &", link); + system (cmd); + g_free (cmd); + } static void hierarchy_changed_cb (GtkWidget *widget, GtkWidget *old, Impl *pThis) { @@ -598,55 +629,102 @@ } } - static void filelist_cb (GtkWidget *widget, gpointer pkg) + static bool versions_cb (GtkWidget *widget, Ypp::PkgList list) + { + Versions *versions = (Versions *) g_object_get_data (G_OBJECT (widget), "class"); + versions->setPackages (list); + return true; + } + + static bool details_cb (GtkWidget *widget, Ypp::PkgList list) + { + if (list.size() != 1) return false; + Ypp::Package *pkg = list.get (0); + std::string text; + std::string b ("<b>"), _b ("</b> "), br ("<br/>"); + text.reserve (2048); + text += b + _("Size:") + _b + pkg->size(); + text += br + b + _("License:") + _b + pkg->license(); + std::string installed (pkg->installedDate()), candidate (pkg->candidateDate()); + if (!installed.empty()) + text += br + b + _("Installed at:") + _b + installed; + if (!candidate.empty()) + text += br + b + _("Latest build:") + _b + candidate; + ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), text.c_str()); + return true; + } + + static bool filelist_cb (GtkWidget *widget, Ypp::PkgList list) { - std::string str (((Ypp::Package *) pkg)->filelist (HTML_MARKUP)); + if (list.size() != 1) return false; + std::string str (list.get(0)->filelist (HTML_MARKUP)); if (str.empty()) ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), onlyInstalledMsg); else ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), str.c_str()); + return true; } - static void changelog_cb (GtkWidget *widget, gpointer pkg) + static bool changelog_cb (GtkWidget *widget, Ypp::PkgList list) { - std::string str (((Ypp::Package *) pkg)->changelog()); + if (list.size() != 1) return false; + std::string str (list.get(0)->changelog()); if (str.empty()) ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), onlyInstalledMsg); else ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), str.c_str()); + return true; } - static void authors_cb (GtkWidget *widget, gpointer pkg) + static bool authors_cb (GtkWidget *widget, Ypp::PkgList list) { - std::string str (((Ypp::Package *) pkg)->authors (HTML_MARKUP)); - ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), str.c_str()); - } - - static void requires_cb (GtkWidget *widget, gpointer pkg) - { - std::string str = _("Requires:"); - str += "<br><blockquote>"; - str += ((Ypp::Package *) pkg)->requires (HTML_MARKUP); - YGUtils::replace (str, "\n", 1, "<br>"); - str += "</blockquote>"; - ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), str.c_str()); + if (list.size() != 1) return false; + std::string str (list.get(0)->authors (HTML_MARKUP)); + if (str.empty()) + ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), + _("<i>Not specified.</i>")); + else + ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), str.c_str()); + return true; } - static void provides_cb (GtkWidget *widget, gpointer pkg) + static bool dependencies_cb (GtkWidget *widget, Ypp::PkgList list) { - std::string str = _("Provides:"); - str += "<br><blockquote>"; - str += ((Ypp::Package *) pkg)->provides (HTML_MARKUP); - YGUtils::replace (str, "\n", 1, "<br>"); - str += "</blockquote>"; - ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), str.c_str()); + if (list.size() != 1) return false; + Ypp::Package *pkg = list.get (0); + GList *children = gtk_container_get_children (GTK_CONTAINER (widget)); + int n = 0; + for (GList *i = children; i; i = i->next, n++) { + std::string str, label, text; + switch (n) { + case 0: + label = _("Requires:"); + text = pkg->requires (HTML_MARKUP); + break; + case 1: + label = _("Provides:"); + text = pkg->provides (HTML_MARKUP); + break; + } + YGUtils::replace (text, "\n", 1, "<br>"); + str.reserve (1024); + str = label; + str += "<br><blockquote>"; + str += text; + str += "</blockquote>"; + ygtk_rich_text_set_text (YGTK_RICH_TEXT (i->data), str.c_str()); + } + g_list_free (children); + return true; } - static void contents_cb (GtkWidget *widget, gpointer pkg) + static bool contents_cb (GtkWidget *widget, Ypp::PkgList list) { + if (list.size() != 1) return false; YGtkPackageView *contents = YGTK_PACKAGE_VIEW (widget); - Ypp::QueryBase *query = new Ypp::QueryCollection ((Ypp::Package *) pkg); + Ypp::QueryBase *query = new Ypp::QueryCollection (list.get (0)); contents->setList (Ypp::PkgQuery (Ypp::Package::PACKAGE_TYPE, query), 0); + return true; } // fix cursor keys support @@ -681,9 +759,14 @@ static inline void fix_keybindings (Impl *pThis, GtkWidget *widget) { + g_signal_connect (G_OBJECT (widget), "move-cursor", + G_CALLBACK (move_cursor_cb), pThis); + } + + static inline void fix_expander_keybindings (Impl *pThis, GtkWidget *widget) + { if (widget) - g_signal_connect (G_OBJECT (widget), "move-cursor", - G_CALLBACK (move_cursor_cb), pThis); + fix_keybindings (pThis, gtk_bin_get_child (GTK_BIN (widget))); } static void realize_cb (GtkWidget *widget, Impl *pThis) @@ -693,41 +776,27 @@ fix_keybindings (pThis, pThis->m_changelog); fix_keybindings (pThis, pThis->m_authors); fix_keybindings (pThis, pThis->m_support); - fix_keybindings (pThis, pThis->m_requires); - fix_keybindings (pThis, pThis->m_provides); + fix_keybindings (pThis, pThis->m_dependencies); } // make the widget request data when/if necessary; speeds up expander children - typedef void (*UpdateCb) (GtkWidget *widget, gpointer data); - - static void ygtk_widget_passive_update (GtkWidget *widget, UpdateCb update_cb, gpointer data) - { - g_object_set_data (G_OBJECT (widget), "update-cb", (gpointer) update_cb); - g_object_set_data (G_OBJECT (widget), "user-data", data); - if (GTK_WIDGET_MAPPED (widget) || !update_cb) - ygtk_widget_passive_update_cb (widget); - else - g_signal_connect (G_OBJECT (widget), "map", - G_CALLBACK (ygtk_widget_passive_update_cb), NULL); - } - - static void ygtk_widget_passive_update_cb (GtkWidget *widget) + void ygtk_expander_update (GtkWidget *expander) { - g_signal_handlers_disconnect_by_func (widget, (gpointer) ygtk_widget_passive_update_cb, NULL); - UpdateCb update_cb = (UpdateCb) g_object_get_data (G_OBJECT (widget), "update-cb"); - gpointer data = g_object_get_data (G_OBJECT (widget), "user-data"); - if (update_cb) // could be set to null to disable - update_cb (widget, data); - } - - static void setPassiveUpdate (GtkWidget *widget, UpdateCb update_cb, Ypp::Package *pkg) - { // convinience method - if (widget) { - ygtk_widget_passive_update (widget, update_cb, (gpointer) pkg); - GtkWidget *expander = gtk_widget_get_ancestor (widget, GTK_TYPE_EXPANDER); - pkg ? gtk_widget_show (expander) : gtk_widget_hide (expander); + if (!expander) return; + if (m_packages.size() == 1) + gtk_widget_show (expander); + else { + gtk_widget_hide (expander); + return; } + UpdateCb update_cb = (UpdateCb) g_object_get_data (G_OBJECT (expander), "update-cb"); + GtkWidget *child = gtk_bin_get_child (GTK_BIN (expander)); + if (gtk_expander_get_expanded (GTK_EXPANDER (expander))) + update_cb (child, m_packages); } + + static void ygtk_expander_expanded_cb (GObject *object, GParamSpec *param_spec, Impl *pThis) + { pThis->ygtk_expander_update (GTK_WIDGET (object)); } }; G_DEFINE_TYPE (YGtkDetailView, ygtk_detail_view, GTK_TYPE_SCROLLED_WINDOW) Modified: trunk/gtk/src/pkg/ygtkpackageview.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/ygtkpackageview.cc?re... ============================================================================== --- trunk/gtk/src/pkg/ygtkpackageview.cc (original) +++ trunk/gtk/src/pkg/ygtkpackageview.cc Tue Jan 26 17:10:22 2010 @@ -14,6 +14,7 @@ #include "ygtktreeview.h" #include "ygtktreemodel.h" #include "ygtkcellrendererbutton.h" +#include "ygtkcellrenderersidebutton.h" #include "YGi18n.h" #include "YGUtils.h" #include <gtk/gtk.h> @@ -105,29 +106,39 @@ } }; +//** General utilities + +const char *getRepositoryStockIcon (const std::string &url) +{ + const gchar *icon; + if (url.empty()) + icon = GTK_STOCK_MISSING_IMAGE; + else if (url.compare (0, 2, "cd", 2) == 0 || url.compare (0, 3, "dvd", 3) == 0) + icon = GTK_STOCK_CDROM; + else if (url.compare (0, 3, "iso", 3) == 0) + icon = GTK_STOCK_FILE; + else + icon = GTK_STOCK_NETWORK; + return icon; +} + //** Model -enum Property { - // pixbuf - ICON_PROP, - // text - NAME_PROP, SUMMARY_PROP, NAME_SUMMARY_PROP, REPOSITORY_PROP, SUPPORT_PROP, - SIZE_PROP, INSTALLED_VERSION_PROP, AVAILABLE_VERSION_PROP, - // checks - TO_INSTALL_PROP, TO_UPGRADE_PROP, TO_REMOVE_PROP, TO_MODIFY_PROP, - IS_INSTALLED_PROP, - // internal +enum ImplProperty { + // booleans + HAS_UPGRADE_PROP = TOTAL_PROPS, TO_UPGRADE_PROP, + // char STYLE_PROP, WEIGHT_PROP, SENSITIVE_PROP, CHECK_VISIBLE_PROP, FOREGROUND_PROP, VERSION_FOREGROUND_PROP, BACKGROUND_PROP, XPAD_PROP, - ACTION_LABEL_PROP, ACTION_STOCK_PROP, + ACTION_LABEL_PROP, ACTION_STOCK_PROP, REPOSITORY_STOCK_PROP, // misc - PTR_PROP, TOTAL_PROPS + PTR_PROP, TOTAL_IMPL_PROPS }; static GType _columnType (int col) { switch (col) { - case ICON_PROP: + case STATUS_ICON_PROP: return GDK_TYPE_PIXBUF; case NAME_PROP: case SUMMARY_PROP: @@ -137,17 +148,17 @@ case SIZE_PROP: case INSTALLED_VERSION_PROP: case AVAILABLE_VERSION_PROP: + case VERSION_PROP: case FOREGROUND_PROP: case VERSION_FOREGROUND_PROP: case BACKGROUND_PROP: case ACTION_LABEL_PROP: case ACTION_STOCK_PROP: + case REPOSITORY_STOCK_PROP: return G_TYPE_STRING; - case TO_INSTALL_PROP: + case INSTALLED_CHECK_PROP: + case HAS_UPGRADE_PROP: case TO_UPGRADE_PROP: - case TO_REMOVE_PROP: - case TO_MODIFY_PROP: - case IS_INSTALLED_PROP: case SENSITIVE_PROP: case CHECK_VISIBLE_PROP: return G_TYPE_BOOLEAN; @@ -164,7 +175,7 @@ static void _getValueDefault (int col, GValue *value) { switch (col) { - case ICON_PROP: + case STATUS_ICON_PROP: g_value_set_object (value, NULL); break; case NAME_PROP: @@ -175,6 +186,7 @@ case SIZE_PROP: case INSTALLED_VERSION_PROP: case AVAILABLE_VERSION_PROP: + case VERSION_PROP: case ACTION_LABEL_PROP: case ACTION_STOCK_PROP: g_value_set_string (value, g_strdup ("")); @@ -182,13 +194,12 @@ case FOREGROUND_PROP: case VERSION_FOREGROUND_PROP: case BACKGROUND_PROP: + case REPOSITORY_STOCK_PROP: g_value_set_string (value, NULL); break; - case TO_INSTALL_PROP: + case INSTALLED_CHECK_PROP: + case HAS_UPGRADE_PROP: case TO_UPGRADE_PROP: - case TO_REMOVE_PROP: - case TO_MODIFY_PROP: - case IS_INSTALLED_PROP: g_value_set_boolean (value, FALSE); break; case STYLE_PROP: @@ -326,7 +337,7 @@ { return block.sumSize(); } virtual int columnsNb() const - { return TOTAL_PROPS; } + { return TOTAL_IMPL_PROPS; } virtual bool showEmptyEntry() const { return true; } @@ -406,14 +417,6 @@ case FOREGROUND_PROP: g_value_set_string (value, g_strdup ("black")); break; - case TO_INSTALL_PROP: - case TO_UPGRADE_PROP: - case TO_REMOVE_PROP: - case TO_MODIFY_PROP: { - bool modified = segment->list.modified(); - g_value_set_boolean (value, modified); - break; - } case ACTION_LABEL_PROP: g_value_set_string (value, g_strdup (_("All"))); break; @@ -429,7 +432,7 @@ Ypp::Package *package = segment->list.get (index); switch (col) { - case ICON_PROP: { + case STATUS_ICON_PROP: { GdkPixbuf *pixbuf = 0; if (package->type() == Ypp::Package::PATTERN_TYPE) { std::string filename (package->icon()); @@ -472,10 +475,21 @@ if (package->toInstall (&version)) ; if (!version) version = package->getInstalledVersion(); - std::string repo; - if (version && version->repo) - repo = version->repo->name; - g_value_set_string (value, g_strdup (repo.c_str())); + std::string str; + if (version && version->repo) { + str = version->repo->name; + str += "\n<small>" + version->repo->url + "</small>"; + } + g_value_set_string (value, g_strdup (str.c_str())); + break; + } + case REPOSITORY_STOCK_PROP: { + const Ypp::Package::Version *version; + version = package->getAvailableVersion (0); + const char *stock = 0; + if (version) + stock = getRepositoryStockIcon (version->repo->url); + g_value_set_string (value, g_strdup (stock)); break; } case SUPPORT_PROP: @@ -496,22 +510,34 @@ g_value_set_string (value, g_strdup (version->number.c_str())); break; } - case TO_INSTALL_PROP: - g_value_set_boolean (value, package->toInstall()); - break; - case TO_UPGRADE_PROP: { - const Ypp::Package::Version *version = 0; - if (package->toInstall (&version)) - g_value_set_boolean (value, version->cmp > 0); + case VERSION_PROP: { + std::string str; + const Ypp::Package::Version *version; + version = package->getInstalledVersion(); + if (version) + str += version->number; + str += "\n"; + const Ypp::Repository *repo = Ypp::get()->favoriteRepository(); + if (repo) + version = package->fromRepository (repo); + else + version = package->getAvailableVersion (0); + if (version) { + // TODO: maybe hide when installed == candidate + str += "<small>"; + if (version->cmp < 0) + str += "<span color="blue">"; + else if (version->cmp > 0) + str += "<span color="red">"; + str += version->number; + if (version->cmp != 0) + str += "</span>"; + str += "</small>"; + } + g_value_set_string (value, g_strdup (str.c_str())); break; } - case TO_REMOVE_PROP: - g_value_set_boolean (value, package->toRemove()); - break; - case TO_MODIFY_PROP: - g_value_set_boolean (value, package->toModify()); - break; - case IS_INSTALLED_PROP: // if is-installed at the end + case INSTALLED_CHECK_PROP: // if is-installed at the end bool installed; if (package->toInstall()) installed = true; @@ -521,6 +547,12 @@ installed = package->isInstalled(); g_value_set_boolean (value, installed); break; + case HAS_UPGRADE_PROP: + g_value_set_boolean (value, package->hasUpgrade()); + break; + case TO_UPGRADE_PROP: + g_value_set_boolean (value, package->hasUpgrade() && package->toInstall()); + break; case SENSITIVE_PROP: { bool sensitive = !package->isLocked(); g_value_set_boolean (value, sensitive); @@ -543,10 +575,10 @@ if (colorful_rows) { if (!package->isInstalled()) color = "darkgray"; - if (col == VERSION_FOREGROUND_PROP) - if (package->hasUpgrade()) - color = "blue"; } +/* if (col == VERSION_FOREGROUND_PROP) + if (package->hasUpgrade()) + color = "blue";*/ g_value_set_string (value, color); break; } @@ -554,7 +586,7 @@ const char *color = 0; if (golden_changed_row) if (package->toModify()) - color = "yellow"; + color = "#f4f4b7"; g_value_set_string (value, color); break; } @@ -634,7 +666,7 @@ { virtual bool showEmptyEntry() const { return false; } virtual int rowsNb() { return 1; } - virtual int columnsNb() const { return TOTAL_PROPS; } + virtual int columnsNb() const { return TOTAL_IMPL_PROPS; } virtual GType columnType (int col) const { return _columnType (col); } virtual void getValue (int row, int col, GValue *value) @@ -660,39 +692,6 @@ //** View -struct Column { - const char *header; - std::string prop; - bool visibleDefault, allowHide, sortable; -}; -static const Column columns[] = { - { "Name", "name", true, false, true }, - { "Version", "available-version", true, true, false }, - { "Repository", "repository", false, true, false }, - { "Support", "support", false, true, false }, - { "Size", "size", false, true, true }, -}; -static int columns_size = sizeof (columns) / sizeof (Column); - -static Property translateProperty (const std::string &prop) -{ - if (prop == "name") - return single_line_rows ? NAME_PROP : NAME_SUMMARY_PROP; - if (prop == "available-version") - return AVAILABLE_VERSION_PROP; - if (prop == "repository") - return REPOSITORY_PROP; - if (prop == "support") - return SUPPORT_PROP; - if (prop == "size") - return SIZE_PROP; - if (prop == "to-install") - return TO_INSTALL_PROP; - if (prop == "is-installed") - return IS_INSTALLED_PROP; - return (Property) 0; -} - struct YGtkPackageView::Impl { Impl (GtkWidget *scroll, bool descriptiveTooltip) @@ -728,24 +727,6 @@ gtk_container_add (GTK_CONTAINER (scroll), m_view); gtk_widget_show_all (scroll); clear(); - - if (action_col) { - if (action_col_as_button) - appendButtonColumn (NULL, "to-install"); - else //if (action_col_as_check) - appendCheckColumn ("is-installed"); //("to-install"); - } - if (status_col) - appendIconColumn (NULL, "icon"); - - for (int i = 0; i < columns_size; i++) { - const Column *column = &columns[i]; - bool visible = column->visibleDefault; - if (column->prop == "available-version") - visible = version_col; - appendTextColumn (column->header, column->prop, - visible, column->sortable); - } } ~Impl() @@ -837,70 +818,85 @@ return packages; } - GtkTreeViewColumn *getColumn (const std::string &property) - { - GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (m_view)); - for (GList *i = columns; i; i = i->next) { - gchar *col_prop = (gchar *) g_object_get_data (G_OBJECT (i->data), "property"); - if (col_prop && property == col_prop) - return (GtkTreeViewColumn *) i->data; - } - return NULL; - } - - std::string getColumnProp (GtkTreeViewColumn *column) + void appendTextColumn (const char *header, int property, bool visible, int size, bool identAuto) { - gchar *prop = (gchar *) g_object_get_data (G_OBJECT (column), "property"); - return prop; - } - - void setVisible (const std::string &property, bool visible) - { gtk_tree_view_column_set_visible (getColumn (property), visible); } - - bool isVisible (const std::string &property) - { return gtk_tree_view_column_get_visible (getColumn (property)); } - - void appendIconColumn (const char *header, const std::string &prop) - { - int col = ICON_PROP; // 'prop' is ignored GtkTreeView *view = GTK_TREE_VIEW (m_view); if (header) gtk_tree_view_set_headers_visible (view, TRUE); - GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new(); - int height = MAX (34, YGUtils::getCharsHeight (m_view, 2)); - gtk_cell_renderer_set_fixed_size (renderer, -1, height); - GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ( - header, renderer, "pixbuf", col, - "cell-background", BACKGROUND_PROP, NULL); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width (column, 38); - gtk_tree_view_append_column (view, column); - } - static Action columnAction (int col) - { - switch (col) { - case TO_INSTALL_PROP: - case TO_UPGRADE_PROP: - default: - return INSTALL_ACTION; - case TO_REMOVE_PROP: - return REMOVE_ACTION; - case TO_MODIFY_PROP: - return UNDO_ACTION; - case IS_INSTALLED_PROP: - return TOGGLE_ACTION; + const char *text_type = "text"; + if (property == NAME_SUMMARY_PROP || property == VERSION_PROP || + property == REPOSITORY_PROP) + text_type = "markup"; + GtkCellRenderer *renderer; + if (property == VERSION_PROP) { + renderer = ygtk_cell_renderer_side_button_new(); + g_object_set (G_OBJECT (renderer), "stock-id", GTK_STOCK_GO_UP, NULL); } + else if (property == REPOSITORY_PROP) + renderer = ygtk_cell_renderer_text_pixbuf_new(); + else + renderer = gtk_cell_renderer_text_new(); + PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_END; + if (size >= 0 && property != NAME_SUMMARY_PROP) + ellipsize = PANGO_ELLIPSIZE_MIDDLE; + g_object_set (G_OBJECT (renderer), "ellipsize", ellipsize, NULL); +/* gboolean reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL; + if (reverse) { // work-around: Pango ignored alignment flag on RTL + gtk_widget_set_direction (m_view, GTK_TEXT_DIR_LTR); + g_object_set (renderer, "alignment", PANGO_ALIGN_RIGHT, NULL); + }*/ + GtkTreeViewColumn *column; + column = gtk_tree_view_column_new_with_attributes ( + header, renderer, text_type, property, + "sensitive", SENSITIVE_PROP, + "style", STYLE_PROP, + "weight", WEIGHT_PROP, + "cell-background", BACKGROUND_PROP, + NULL); + int foregroundCol = FOREGROUND_PROP; + if (property == VERSION_PROP) { + foregroundCol = VERSION_FOREGROUND_PROP; + gtk_tree_view_column_add_attribute (column, renderer, + "button-visible", HAS_UPGRADE_PROP); + gtk_tree_view_column_add_attribute (column, renderer, + "active", TO_UPGRADE_PROP); + g_signal_connect (G_OBJECT (renderer), "toggled", + G_CALLBACK (upgrade_toggled_cb), this); + } + else if (property == REPOSITORY_PROP) + gtk_tree_view_column_add_attribute (column, renderer, + "stock-id", REPOSITORY_STOCK_PROP); + gtk_tree_view_column_add_attribute (column, renderer, "foreground", foregroundCol); + if (identAuto) + gtk_tree_view_column_add_attribute (column, renderer, "xpad", XPAD_PROP); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_resizable (column, TRUE); +// gtk_tree_view_column_set_reorderable (column, TRUE); + if (size >= 0) + gtk_tree_view_column_set_fixed_width (column, size); + else + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_set_visible (column, visible); +// if (sortable) + gtk_tree_view_column_set_clickable (column, true); + g_signal_connect (G_OBJECT (column), "clicked", + G_CALLBACK (column_clicked_cb), this); + if (property == NAME_PROP || property == NAME_SUMMARY_PROP) { + gtk_tree_view_column_set_sort_indicator (column, TRUE); + gtk_tree_view_column_set_sort_order (column, GTK_SORT_ASCENDING); + } +// gtk_tree_view_insert_column (view, column, reverse ? 0 : -1); + gtk_tree_view_append_column (view, column); + g_object_set_data (G_OBJECT (column), "property", GINT_TO_POINTER (property+1)); } - void appendCheckColumn (const std::string &prop) + void appendCheckColumn (int property) { - int modelCol = translateProperty (prop); - GtkTreeView *view = GTK_TREE_VIEW (m_view); GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new(); GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (NULL, - renderer, "active", modelCol, "visible", CHECK_VISIBLE_PROP, + renderer, "active", property, "visible", CHECK_VISIBLE_PROP, "sensitive", SENSITIVE_PROP, "cell-background", BACKGROUND_PROP, NULL); g_signal_connect (G_OBJECT (renderer), "toggled", @@ -911,14 +907,15 @@ gtk_tree_view_column_set_fixed_width (column, 25); gtk_tree_view_append_column (view, column); - Action action = columnAction (modelCol); + Action action = TOGGLE_ACTION; g_object_set_data (G_OBJECT (renderer), "action", GINT_TO_POINTER (action)); if (m_activate_action == NONE_ACTION) m_activate_action = action; g_object_set_data (G_OBJECT (column), "status-tooltip", GINT_TO_POINTER (1)); + g_object_set_data (G_OBJECT (column), "property", GINT_TO_POINTER (property+1)); } - void appendButtonColumn (const char *header, const std::string &prop) + void appendButtonColumn (const char *header, int property) { int labelCol = ACTION_LABEL_PROP, stockCol = ACTION_STOCK_PROP; @@ -963,66 +960,26 @@ gtk_tree_view_column_set_fixed_width (column, width); gtk_tree_view_append_column (view, column); - Action action = columnAction (TO_INSTALL_PROP); + Action action = INSTALL_ACTION; g_object_set_data (G_OBJECT (renderer), "action", GINT_TO_POINTER (action)); if (m_activate_action == NONE_ACTION) m_activate_action = action; g_object_set_data (G_OBJECT (column), "status-tooltip", GINT_TO_POINTER (1)); } - void appendTextColumn (const char *header, const std::string &prop, bool visible, bool sortable, bool identAuto = false) + void appendIconColumn (const char *header, int property) { - int col = translateProperty (prop); - int size = 100; - if (col == NAME_PROP || col == NAME_SUMMARY_PROP) - size = -1; - GtkTreeView *view = GTK_TREE_VIEW (m_view); if (header) gtk_tree_view_set_headers_visible (view, TRUE); - GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); - PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_END; - if (size >= 0 && col != NAME_SUMMARY_PROP) - ellipsize = PANGO_ELLIPSIZE_MIDDLE; - g_object_set (G_OBJECT (renderer), "ellipsize", ellipsize, NULL); -/* gboolean reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL; - if (reverse) { // work-around: Pango ignored alignment flag on RTL - gtk_widget_set_direction (m_view, GTK_TEXT_DIR_LTR); - g_object_set (renderer, "alignment", PANGO_ALIGN_RIGHT, NULL); - }*/ - const char *colType = col == NAME_SUMMARY_PROP ? "markup" : "text"; - GtkTreeViewColumn *column; - column = gtk_tree_view_column_new_with_attributes ( - header, renderer, colType, col, - "sensitive", SENSITIVE_PROP, - "style", STYLE_PROP, - "weight", WEIGHT_PROP, - "cell-background", BACKGROUND_PROP, - NULL); - int foregroundCol = FOREGROUND_PROP; - if (col == AVAILABLE_VERSION_PROP) - foregroundCol = VERSION_FOREGROUND_PROP; - gtk_tree_view_column_add_attribute (column, renderer, "foreground", foregroundCol); - g_object_set_data_full (G_OBJECT (column), "property", g_strdup (prop.c_str()), g_free); - if (identAuto) - gtk_tree_view_column_add_attribute (column, renderer, "xpad", XPAD_PROP); + GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new(); + int height = MAX (34, YGUtils::getCharsHeight (m_view, 2)); + gtk_cell_renderer_set_fixed_size (renderer, -1, height); + GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ( + header, renderer, "pixbuf", property, + "cell-background", BACKGROUND_PROP, NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_resizable (column, TRUE); -// gtk_tree_view_column_set_reorderable (column, TRUE); - if (size >= 0) - gtk_tree_view_column_set_fixed_width (column, size); - else - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_column_set_visible (column, visible); - gtk_tree_view_column_set_clickable (column, sortable); - if (sortable) - g_signal_connect (G_OBJECT (column), "clicked", - G_CALLBACK (column_clicked_cb), this); - if (col == NAME_PROP || col == NAME_SUMMARY_PROP) { - gtk_tree_view_column_set_sort_indicator (column, TRUE); - gtk_tree_view_column_set_sort_order (column, GTK_SORT_ASCENDING); - } -// gtk_tree_view_insert_column (view, column, reverse ? 0 : -1); + gtk_tree_view_column_set_fixed_width (column, 38); gtk_tree_view_append_column (view, column); } @@ -1035,12 +992,6 @@ gtk_tree_view_append_column (view, column); } - void removeColumn (const char *header) - { gtk_tree_view_remove_column (GTK_TREE_VIEW (m_view), getColumn (header)); } - - bool hasColumn (const char *header) - { return getColumn (header); } - void setRulesHint (bool hint) { gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (m_view), TRUE); } @@ -1101,68 +1052,66 @@ { pThis->selectAll(); } static void show_column_cb (GtkCheckMenuItem *item, Impl *pThis) { - GList *siblings = gtk_container_get_children (GTK_CONTAINER ( - gtk_widget_get_parent (GTK_WIDGET (item)))), *i; - for (i = siblings; i; i = i->next) - if (i->data == item) - break; - int index = g_list_position (siblings, i) + 1; - g_list_free (siblings); - bool visible = gtk_check_menu_item_get_active (item); + int col = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "column")); GtkTreeViewColumn *column = gtk_tree_view_get_column ( - GTK_TREE_VIEW (pThis->m_view), index); + GTK_TREE_VIEW (pThis->m_view), col); + bool visible = gtk_check_menu_item_get_active (item); gtk_tree_view_column_set_visible (column, visible); } }; Ypp::PkgList packages = getSelected(); - bool empty = true, canLock = packages.canLock(), unlocked = packages.unlocked(); + bool empty = true, canLock = packages.canLock(), unlocked = packages.isUnlocked(); bool locked = !unlocked && canLock; - if (packages.notInstalled()) + if (packages.isNotInstalled()) inner::appendItem (menu, _("_Install"), 0, GTK_STOCK_SAVE, !locked, inner::install_cb, this), empty = false; - if (packages.upgradable()) + if (packages.hasUpgrade()) inner::appendItem (menu, _("_Upgrade"), 0, GTK_STOCK_GOTO_TOP, !locked, inner::install_cb, this), empty = false; - if (packages.installed() && packages.canRemove()) + if (packages.isInstalled() && packages.canRemove()) inner::appendItem (menu, _("_Remove"), 0, GTK_STOCK_DELETE, !locked, inner::remove_cb, this), empty = false; - if (packages.modified()) + if (packages.toModify()) inner::appendItem (menu, _("_Undo"), 0, GTK_STOCK_UNDO, true, inner::undo_cb, this), empty = false; if (canLock) { static const char *lock_tooltip = "<b>Package lock:</b> prevents the package status from being modified by " "the solver (that is, it won't honour dependencies or collections ties.)"; - if (packages.locked()) - inner::appendItem (menu, _("_Unlock"), _(lock_tooltip), "pkg-unlocked.png", +// TODO: use lock and lock-open for the icons here + if (packages.isLocked()) + inner::appendItem (menu, _("_Unlock"), _(lock_tooltip), GTK_STOCK_DIALOG_AUTHENTICATION,//"pkg-unlocked.png", true, inner::unlock_cb, this), empty = false; if (unlocked) - inner::appendItem (menu, _("_Lock"), _(lock_tooltip), "pkg-locked.png", + inner::appendItem (menu, _("_Lock"), _(lock_tooltip), GTK_STOCK_DIALOG_AUTHENTICATION,//"pkg-locked.png", true, inner::lock_cb, this), empty = false; } if (!empty) gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new()); inner::appendItem (menu, NULL, NULL, GTK_STOCK_SELECT_ALL, true, inner::select_all_cb, this); - - GtkWidget *item = gtk_menu_item_new_with_mnemonic (_("_Show Column")); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new()); + GtkWidget *item = gtk_menu_item_new_with_mnemonic (_("_Show column")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); GtkWidget *submenu = gtk_menu_new(); gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); - for (int i = 0; i < columns_size; i++) { - const Column *column = &columns[i]; - if (column->header) { - GtkWidget *item = gtk_check_menu_item_new_with_label (column->header); + GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (m_view)); + int n = 0; + for (GList *i = columns; i; i = i->next, n++) { + GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data; + const gchar *header = gtk_tree_view_column_get_title (column); + if (header) { + GtkWidget *item = gtk_check_menu_item_new_with_label (header); + g_object_set_data (G_OBJECT (item), "column", GINT_TO_POINTER (n)); gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), isVisible (column->prop)); - if (column->allowHide) - g_signal_connect (G_OBJECT (item), "toggled", - G_CALLBACK (inner::show_column_cb), this); - else - gtk_widget_set_sensitive (item, FALSE); + gboolean visible = gtk_tree_view_column_get_visible (column); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), visible); + g_signal_connect (G_OBJECT (item), "toggled", + G_CALLBACK (inner::show_column_cb), this); } } + g_list_free (columns); gtk_menu_attach_to_widget (GTK_MENU (menu), m_view, NULL); gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, event_time); @@ -1231,6 +1180,18 @@ return FALSE; } + static void upgrade_toggled_cb ( + GtkCellRenderer *renderer, gchar *path_str, Impl *pThis) + { + Ypp::Package *package = 0; + GtkTreeView *view = GTK_TREE_VIEW (pThis->m_view); + GtkTreeModel *model = gtk_tree_view_get_model (view); + GtkTreeIter iter; + gtk_tree_model_get_iter_from_string (model, &iter, path_str); + gtk_tree_model_get (model, &iter, PTR_PROP, &package, -1); + package->install (0); + } + static void renderer_toggled_cb (GtkCellRenderer *renderer, gchar *path_str, Impl *pThis) { @@ -1269,7 +1230,7 @@ case REMOVE_ACTION: packages.remove(); break; case UNDO_ACTION: packages.undo(); break; case TOGGLE_ACTION: - if (packages.installed()) + if (packages.isInstalled()) packages.remove(); else packages.install(); @@ -1343,7 +1304,7 @@ if (!filename.empty()) pixbuf = YGUtils::loadPixbuf (filename.c_str()); if (!pixbuf) - gtk_tree_model_get (model, &iter, ICON_PROP, &pixbuf, -1); + gtk_tree_model_get (model, &iter, STATUS_ICON_PROP, &pixbuf, -1); if (pixbuf) { gtk_tooltip_set_icon (tooltip, pixbuf); g_object_unref (G_OBJECT (pixbuf)); @@ -1356,7 +1317,49 @@ static void column_clicked_cb (GtkTreeViewColumn *column, Impl *pThis) { -fprintf (stderr, "column clicked\n"); + int property = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (column), "property"))-1; + const char *prop = 0; + bool as_int = false; + switch (property) { + case NAME_PROP: + case NAME_SUMMARY_PROP: + prop = "name"; + break; + case VERSION_PROP: + prop = "installed-version"; + break; + case REPOSITORY_PROP: + prop = "repository"; + as_int = true; + break; + case SUPPORT_PROP: + prop = "support"; + as_int = true; + break; + case SIZE_PROP: + prop = "size"; + as_int = true; + break; + case INSTALLED_CHECK_PROP: + prop = "installed"; + as_int = true; + break; + default: break; + } + + if (prop) { +fprintf (stderr, "sort list by %s as int? %d\n", prop, as_int); + Ypp::PkgList list (pThis->m_list); + pThis->clear(); + + list.sort_by_property (prop, as_int); + pThis->setList (list, NULL); + + gtk_tree_view_column_set_sort_indicator (column, TRUE); + gtk_tree_view_column_set_sort_order (column, GTK_SORT_ASCENDING); + } + +#if 0 GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (pThis->m_view)); for (GList *i = columns; i; i = i->next) { GtkTreeViewColumn *col = (GtkTreeViewColumn *) i->data; @@ -1382,6 +1385,7 @@ if (prop != "name") l = Ypp::PkgSort (pThis->m_list, prop.c_str(), sort == GTK_SORT_ASCENDING); pThis->setListImpl (l, NULL); +#endif } }; @@ -1420,11 +1424,20 @@ void YGtkPackageView::clear() { impl->clear(); } -void YGtkPackageView::setVisible (const std::string &property, bool visible) -{ impl->setVisible (property, visible); } +void YGtkPackageView::appendTextColumn (const char *header, int property, bool visible, int size, bool identAuto) +{ return impl->appendTextColumn (header, property, visible, size, identAuto); } + +void YGtkPackageView::appendCheckColumn (int property) +{ return impl->appendCheckColumn (property); } + +void YGtkPackageView::appendButtonColumn (const char *header, int property) +{ return impl->appendButtonColumn (header, property); } + +void YGtkPackageView::appendIconColumn (const char *header, int property) +{ return impl->appendIconColumn (header, property); } -bool YGtkPackageView::isVisible (const std::string &property) -{ return impl->isVisible (property); } +void YGtkPackageView::appendEmptyColumn (int size) +{ return impl->appendEmptyColumn (size); } void YGtkPackageView::setRulesHint (bool hint) { impl->setRulesHint (hint); } Modified: trunk/gtk/src/pkg/ygtkpackageview.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/ygtkpackageview.h?rev... ============================================================================== --- trunk/gtk/src/pkg/ygtkpackageview.h (original) +++ trunk/gtk/src/pkg/ygtkpackageview.h Tue Jan 26 17:10:22 2010 @@ -23,6 +23,12 @@ #define YGTK_PACKAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ YGTK_TYPE_PACKAGE_VIEW, YGtkPackageViewClass)) +enum Property { NAME_PROP, SUMMARY_PROP, NAME_SUMMARY_PROP, VERSION_PROP, + AVAILABLE_VERSION_PROP, INSTALLED_VERSION_PROP, + REPOSITORY_PROP, SUPPORT_PROP, SIZE_PROP, + INSTALLED_CHECK_PROP, STATUS_ICON_PROP, TOTAL_PROPS +}; + struct YGtkPackageView { // use ygtk_package_view_new() to instance the object GtkScrolledWindow parent; @@ -31,8 +37,11 @@ void packList (const char *header, Ypp::PkgList list, const char *applyAllLabel); void clear(); - void setVisible (const std::string &property, bool visible); - bool isVisible (const std::string &property); + void appendTextColumn (const char *header, int property, bool visible, int size, bool identAuto = false); + void appendCheckColumn (int property); + void appendButtonColumn (const char *header, int property); + void appendIconColumn (const char *header, int property); + void appendEmptyColumn (int size); void setRulesHint (bool hint); enum Action { NONE_ACTION, INSTALL_ACTION, REMOVE_ACTION, UNDO_ACTION, TOGGLE_ACTION }; @@ -56,5 +65,7 @@ YGtkPackageView* ygtk_package_view_new (gboolean descriptiveTooltip); GType ygtk_package_view_get_type (void) G_GNUC_CONST; +const char *getRepositoryStockIcon (const std::string &url); + #endif /*YGTK_PACKAGE_VIEW_H*/ Modified: trunk/gtk/src/pkg/yzyppwrapper.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/yzyppwrapper.cc?rev=6... ============================================================================== --- trunk/gtk/src/pkg/yzyppwrapper.cc (original) +++ trunk/gtk/src/pkg/yzyppwrapper.cc Tue Jan 26 17:10:22 2010 @@ -236,6 +236,9 @@ virtual std::string support() { return ""; } virtual std::string supportText (MarkupType markup) { return ""; } virtual std::string size() { return ""; } + virtual std::string license() { return ""; } + virtual std::string installedDate() { return ""; } + virtual std::string candidateDate() { return ""; } virtual std::string icon() = 0; virtual bool isRecommended() const { return false; } virtual bool isSuggested() const { return false; } @@ -303,6 +306,9 @@ std::string Ypp::Package::support() { return impl->support(); } std::string Ypp::Package::supportText (MarkupType markup) { return impl->supportText (markup); } std::string Ypp::Package::size() { return impl->size(); } +std::string Ypp::Package::license() { return impl->license(); } +std::string Ypp::Package::installedDate() { return impl->installedDate(); } +std::string Ypp::Package::candidateDate() { return impl->candidateDate(); } std::string Ypp::Package::icon() { return impl->icon(); } bool Ypp::Package::isRecommended() const { return impl->isRecommended(); } bool Ypp::Package::isSuggested() const { return impl->isSuggested(); } @@ -366,6 +372,10 @@ return description (markup); if (prop == "filelist") return filelist (markup); + if (prop == "requires") + return requires (NO_MARKUP); + if (prop == "provides") + return provides (NO_MARKUP); if (prop == "support") return support(); if (prop == "size") @@ -599,6 +609,12 @@ text += br; } + ZyppPackage package = tryCastToZyppPkg (object); + std::string url = package->url(); + if (!url.empty()) + text += std::string ("<b>") + _("Web site:") + "</b> <a href="" + url + "">" + url + "</a>"; + +#if 0 if (!isInstalled() && (isRecommended() || isSuggested())) { text += "<font color="#715300">"; if (isRecommended()) @@ -607,35 +623,6 @@ text += _("(As this package complements some installed packages, it is <b>suggested</b> it be installed.)"); text += "</font>" + br; } - - // specific - ZyppPackage package = tryCastToZyppPkg (object); -#if ZYPP_VERSION >= 5013001 - text += br + "<b>" + _("Size:") + "</b> " + object->installSize().asString(); -#else - text += br + "<b>" + _("Size:") + "</b> " + object->installsize().asString(); -#endif - std::string url = package->url(), license = package->license(); - if (!url.empty()) - text += br + "<b>" + _("Web site:") + "</b> <a href="" + url + "">" + url + "</a>"; - if (!license.empty()) - text += br + "<b>" + _("License:") + "</b> " + license; -#if 0 - text += br + "<b>" + _("Category:") + "</b> " + package->group(); -#endif -#if 0 // show "Installed at:" and "Last build:" info - bool hasCandidate = m_sel->hasCandidateObj(); - if (isInstalled()) { - text += br + "<b>" + _("Installed at:") + "</b> " + m_sel->installedObj()->installtime().form("%x"); - if (!hasUpgrade()) - hasCandidate = false; // only for upgrades - if (hasCandidate) - text += " "; - } - else if (hasCandidate) - text += br; - if (hasCandidate) - text += std::string ("<b>") + _("Last build:") + "</b> " + m_sel->candidateObj()->buildtime().form("%x"); #endif break; } @@ -881,6 +868,15 @@ virtual std::string size() { return m_sel->theObj()->installSize().asString(); } + virtual std::string license() + { return tryCastToZyppPkg (m_sel->theObj())->license(); } + + virtual std::string installedDate() + { return isInstalled() ? m_sel->installedObj()->installtime().form("%x") : ""; } + + virtual std::string candidateDate() + { return m_sel->hasCandidateObj() ? m_sel->candidateObj()->buildtime().form("%x") : ""; } + virtual std::string icon() { if (type == Ypp::Package::PATTERN_TYPE) { @@ -1828,6 +1824,18 @@ void Ypp::PkgList::sort (bool (* compare) (Package *, Package *)) { std::sort (impl->pool.begin(), impl->pool.end(), compare ? compare : pkgorder); } +static std::string _prop; // HACK +static bool int_prop_order (Ypp::Package *a, Ypp::Package *b) +{ return a->getPropertyInt (_prop) < b->getPropertyInt (_prop); } +static bool str_prop_order (Ypp::Package *a, Ypp::Package *b) +{ return a->getPropertyStr (_prop) < b->getPropertyStr (_prop); } + +void Ypp::PkgList::sort_by_property (const std::string &prop, bool as_int) +{ + _prop = prop; + sort (as_int ? int_prop_order : str_prop_order); +} + void Ypp::PkgList::remove (int i) { impl->remove (i); } @@ -1876,22 +1884,22 @@ bool Ypp::PkgList::operator == (const Ypp::PkgList &other) const { return this->impl == other.impl; } -bool Ypp::PkgList::installed() const +bool Ypp::PkgList::isInstalled() const { impl->buildProps(); return impl->_allInstalled; } -bool Ypp::PkgList::notInstalled() const +bool Ypp::PkgList::isNotInstalled() const { impl->buildProps(); return impl->_allNotInstalled; } -bool Ypp::PkgList::upgradable() const +bool Ypp::PkgList::hasUpgrade() const { impl->buildProps(); return impl->_allUpgradable; } -bool Ypp::PkgList::modified() const +bool Ypp::PkgList::toModify() const { impl->buildProps(); return impl->_allModified; } -bool Ypp::PkgList::locked() const +bool Ypp::PkgList::isLocked() const { impl->buildProps(); return impl->_allLocked; } -bool Ypp::PkgList::unlocked() const +bool Ypp::PkgList::isUnlocked() const { impl->buildProps(); return impl->_allUnlocked; } bool Ypp::PkgList::canLock() const @@ -1900,6 +1908,9 @@ bool Ypp::PkgList::canRemove() const { impl->buildProps(); return impl->_allCanRemove; } +void Ypp::PkgList::refreshProps() +{ impl->inited = false; } + void Ypp::PkgList::install() { Ypp::get()->startTransactions(); @@ -2132,21 +2143,6 @@ : PkgList ((impl = new PkgQuery::Impl (Ypp::get()->getPackages (type), query))) { copy (Ypp::get()->getPackages (type)); } -//** PkgSort - -static std::string _prop; // hack -static bool _ascend; - -static bool prop_order (Ypp::Package *a, Ypp::Package *b) -{ - int r = strcasecmp (a->getPropertyStr (_prop).c_str(), b->getPropertyStr (_prop).c_str()); - return _ascend ? r < 0 : r >= 0; -} - -Ypp::PkgSort::PkgSort (PkgList list, const std::string &prop, bool ascend) -: PkgList() -{ copy (list); _prop = prop; _ascend = ascend; sort (prop_order); } - //** Misc struct Ypp::Disk::Impl Modified: trunk/gtk/src/pkg/yzyppwrapper.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/yzyppwrapper.h?rev=60... ============================================================================== --- trunk/gtk/src/pkg/yzyppwrapper.h (original) +++ trunk/gtk/src/pkg/yzyppwrapper.h Tue Jan 26 17:10:22 2010 @@ -63,6 +63,9 @@ std::string supportText (MarkupType markup); std::string size(); std::string icon(); + std::string license(); + std::string installedDate(); + std::string candidateDate(); bool isRecommended() const; bool isSuggested() const; int buildAge() const; // if < 0 , unsupported or error @@ -129,6 +132,7 @@ void reserve (int size); void append (Package *package); void sort (bool (* order) (Package *, Package *) = 0); + void sort_by_property (const std::string &prop, bool as_int); void remove (int index); void copy (const PkgList list); // will only copy entry for which match() == true @@ -139,16 +143,18 @@ // NOTE: checks if both lists point to the same memory space, not equal contents bool operator == (const PkgList &other) const; - // common properties + // common properties (nomenclature used from Ypp::Package) // NOTE: there is a hit first time one of these methods is used - bool installed() const; - bool notInstalled() const; - bool upgradable() const; - bool modified() const; - bool locked() const; - bool unlocked() const; + // FIXME: we might move these methods into some "ListProps" structure + bool isInstalled() const; + bool isNotInstalled() const; + bool hasUpgrade() const; + bool toModify() const; + bool isLocked() const; + bool isUnlocked() const; bool canRemove() const; bool canLock() const; + void refreshProps(); // actions // NOTE: can take time (depending on size); show busy cursor @@ -239,10 +245,6 @@ Impl *impl; }; - struct PkgSort : public PkgList { - PkgSort (PkgList list, const std::string &prop, bool ascending); - }; - // list primitives const PkgList getPackages (Package::Type type); Modified: trunk/gtk/src/ygtkrichtext.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkrichtext.c?rev=60541&... ============================================================================== --- trunk/gtk/src/ygtkrichtext.c (original) +++ trunk/gtk/src/ygtkrichtext.c Tue Jan 26 17:10:22 2010 @@ -320,8 +320,7 @@ if (attribute_names[0] && !g_ascii_strcasecmp (attribute_names[0], "color")) { tag->tag = gtk_text_buffer_create_tag (state->buffer, NULL, - "foreground", attribute_values[0], - NULL); + "foreground", attribute_values[0], NULL); state->default_color = FALSE; } else @@ -331,8 +330,7 @@ if (attribute_names[0] && !g_ascii_strcasecmp (attribute_names[0], "href")) { tag->tag = gtk_text_buffer_create_tag (state->buffer, NULL, - "underline", PANGO_UNDERLINE_SINGLE, - NULL); + "underline", PANGO_UNDERLINE_SINGLE, NULL); if (state->default_color) g_object_set (tag->tag, "foreground-gdk", &link_color, NULL); g_object_set_data (G_OBJECT (tag->tag), "link", g_strdup (attribute_values[0])); @@ -361,7 +359,6 @@ HTMLList_init (list, !g_ascii_strcasecmp (element_name, "ol")); state->html_list = g_list_append (state->html_list, list); } - else if (!g_ascii_strcasecmp (element_name, "img")) { if (attribute_names[0] && !g_ascii_strcasecmp (attribute_names[0], "src")) { @@ -374,8 +371,7 @@ else g_warning ("Unknown img attribute: '%s'", attribute_names[0]); } - - // for tags like <br/>, GMarkup will pass them through the end + // tags like <br/>, GMarkup will pass them through the end // tag callback too, so we'll deal with them there else if (!g_ascii_strcasecmp (element_name, "br")) ; else if (!g_ascii_strcasecmp (element_name, "hr")) ; @@ -388,6 +384,15 @@ g_warning ("Unknown tag '%s'", element_name); } } + else if (attribute_names[0]) { // tags that may have extra attributes + if (!g_ascii_strcasecmp (element_name, "p")) { + if (!g_ascii_strcasecmp (attribute_names[0], "bgcolor")) + tag->tag = gtk_text_buffer_create_tag (state->buffer, NULL, + "paragraph-background", attribute_values[0], NULL); + else + g_warning ("Unknown p attribute: '%s'", attribute_names[0]); + } + } if (!tag->tag && isIdentTag (element_name)) { state->left_margin += IDENT_MARGIN; Modified: trunk/gtk/src/ygtkwizard.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkwizard.c?rev=60541&am... ============================================================================== --- trunk/gtk/src/ygtkwizard.c (original) +++ trunk/gtk/src/ygtkwizard.c Tue Jan 26 17:10:22 2010 @@ -920,7 +920,7 @@ { if (!wizard->menu) { wizard->menu = gtk_menu_bar_new(); - ygtk_wizard_set_custom_menu (wizard, wizard->menu); + ygtk_wizard_set_custom_menu (wizard, wizard->menu, TRUE); gtk_widget_show (wizard->menu); } @@ -1001,12 +1001,13 @@ } } -void ygtk_wizard_set_custom_menu (YGtkWizard *wizard, GtkWidget *menu_bar) +void ygtk_wizard_set_custom_menu (YGtkWizard *wizard, GtkWidget *menu_bar, gboolean hide_header) { gtk_container_add (GTK_CONTAINER (wizard->m_menu_box), menu_bar); gtk_widget_show (wizard->m_menu_box); // we probably want to hide the title, so the menu is more visible - gtk_widget_hide (wizard->m_title); + if (hide_header) + gtk_widget_hide (wizard->m_title); } void ygtk_wizard_add_step_header (YGtkWizard *wizard, const char *text) Modified: trunk/gtk/src/ygtkwizard.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkwizard.h?rev=60541&am... ============================================================================== --- trunk/gtk/src/ygtkwizard.h (original) +++ trunk/gtk/src/ygtkwizard.h Tue Jan 26 17:10:22 2010 @@ -162,7 +162,7 @@ const char *text, const char *id); gboolean ygtk_wizard_add_menu_separator (YGtkWizard *wizard, const char *parent_id); void ygtk_wizard_clear_menu (YGtkWizard *wizard); -void ygtk_wizard_set_custom_menu (YGtkWizard *wizard, GtkWidget *menu_bar); +void ygtk_wizard_set_custom_menu (YGtkWizard *wizard, GtkWidget *menu_bar, gboolean hide_header); void ygtk_wizard_add_step_header (YGtkWizard *wizard, const char *text); void ygtk_wizard_add_step (YGtkWizard *wizard, const char* text, const char *id); -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org