[yast-commit] r60205 - in /trunk/gtk: ChangeLog src/YGPackageSelectorPluginStub.cc src/pkg/YGPackageSelector.cc src/pkg/ygtkdetailview.cc src/pkg/yzyppwrapper.cc src/pkg/yzyppwrapper.h
Author: rpmcruz Date: Wed Dec 30 12:01:38 2009 New Revision: 60205 URL: http://svn.opensuse.org/viewcvs/yast?rev=60205&view=rev Log: * src/pkg/YGPackageSelector.cc: added --status-top flag. * src/pkg/yzyppwrapper.h/cc: PkgQuery overhaul. Most criteria are now set as string properties, and QueryAnd / QueryOr allow for a finer tuned query. Modified: trunk/gtk/ChangeLog trunk/gtk/src/YGPackageSelectorPluginStub.cc trunk/gtk/src/pkg/YGPackageSelector.cc trunk/gtk/src/pkg/ygtkdetailview.cc trunk/gtk/src/pkg/yzyppwrapper.cc trunk/gtk/src/pkg/yzyppwrapper.h Modified: trunk/gtk/ChangeLog URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/ChangeLog?rev=60205&r1=60204&r2=60205&view=diff ============================================================================== --- trunk/gtk/ChangeLog (original) +++ trunk/gtk/ChangeLog Wed Dec 30 12:01:38 2009 @@ -1,3 +1,12 @@ +2009-12-29 Ricardo Cruz <rpmcruz@alunos.dcc.fc.up.pt> + + * src/pkg/YGPackageSelector.cc: added --status-top + flag. + + * src/pkg/yzyppwrapper.h/cc: PkgQuery overhaul. Most + criteria are now set as string properties, and QueryAnd + / QueryOr allow for a finer tuned query. + 2009-12-27 Ricardo Cruz <rpmcruz@alunos.dcc.fc.up.pt> * src/pkg/YGPackageSelector.cc: added --categories-top Modified: trunk/gtk/src/YGPackageSelectorPluginStub.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGPackageSelectorPluginStub.cc?rev=60205&r1=60204&r2=60205&view=diff ============================================================================== --- trunk/gtk/src/YGPackageSelectorPluginStub.cc (original) +++ trunk/gtk/src/YGPackageSelectorPluginStub.cc Wed Dec 30 12:01:38 2009 @@ -13,11 +13,11 @@ bool search_entry_side = true, search_entry_top = false, dynamic_sidebar = false, categories_side = true, categories_top = false, status_side = false, - status_tabs = true, status_tabs_as_actions = false, undo_side = false, - undo_tab = true, undo_old_style = false, status_col = false, action_col = true, - action_col_as_button = true, action_col_as_check = false, version_col = true, - single_line_rows = false, details_start_hide = true, toolbar_top = false, - toolbar_yast = false, arrange_by = false; + status_top = false, status_tabs = true, status_tabs_as_actions = false, + undo_side = false, undo_tab = true, undo_old_style = false, status_col = false, + action_col = true, action_col_as_button = true, action_col_as_check = false, + version_col = true, single_line_rows = false, details_start_hide = true, + toolbar_top = false, toolbar_yast = false, arrange_by = false; struct Arg { const char *arg; @@ -30,6 +30,7 @@ { "categories-side", &categories_side }, { "categories-top", &categories_top }, { "status-side", &status_side }, + { "status-top", &status_top }, { "status-tabs", &status_tabs }, { "status-tabs-as-actions", &status_tabs_as_actions }, { "undo-side", &undo_side }, @@ -61,7 +62,7 @@ int arg_len = strlen (arguments[i].arg); if (!strncmp (arg, arguments[i].arg, arg_len) && arg[arg_len] == '=') { *arguments[i].var = arg[arg_len+1] == 'y'; -fprintf (stderr, "found '%s' as '%s' = '%d'\n", arg, arguments[i].arg, *arguments[i].var); +//fprintf (stderr, "found '%s' as '%s' = '%d'\n", arg, arguments[i].arg, *arguments[i].var); return true; } } Modified: trunk/gtk/src/pkg/YGPackageSelector.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/YGPackageSelector.cc?rev=60205&r1=60204&r2=60205&view=diff ============================================================================== --- trunk/gtk/src/pkg/YGPackageSelector.cc (original) +++ trunk/gtk/src/pkg/YGPackageSelector.cc Wed Dec 30 12:01:38 2009 @@ -28,8 +28,8 @@ // experiments: extern bool search_entry_side, search_entry_top, dynamic_sidebar, categories_side, - categories_top, status_side, status_tabs, status_tabs_as_actions, undo_side, - undo_tab, undo_old_style, status_col, action_col, action_col_as_button, + categories_top, status_side, status_top, status_tabs, status_tabs_as_actions, + undo_side, undo_tab, undo_old_style, status_col, action_col, action_col_as_button, action_col_as_check, version_col, single_line_rows, details_start_hide, toolbar_top, toolbar_yast, arrange_by; @@ -44,8 +44,7 @@ UndoView() { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->setToModify (true); + Ypp::QueryBase *query = new Ypp::QueryProperty ("to-modify", true); m_changes = Ypp::PkgQuery (Ypp::Package::PACKAGE_TYPE, query); #if 0 GtkWidget *view = createView (listener); @@ -82,27 +81,27 @@ GtkWidget *main_box = horizontal ? gtk_hbox_new (TRUE, 6) : gtk_vbox_new (TRUE, 6); for (int i = 0; i < 3; i++) { const char *str = 0, *stock = 0; - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); const char *prop; switch (i) { case 0: str = _("To install:"); stock = GTK_STOCK_ADD; - query->setToInstall (true); - query->setIsInstalled (false); + query->add (new Ypp::QueryProperty ("to-install", true)); + query->add (new Ypp::QueryProperty ("is-installed", false)); prop = "to-install"; break; case 1: str = _("To upgrade:"); stock = GTK_STOCK_GO_UP; - query->setToInstall (true); - query->setIsInstalled (true); + query->add (new Ypp::QueryProperty ("to-install", true)); + query->add (new Ypp::QueryProperty ("is-installed", true)); prop = "to-upgrade"; break; case 2: str = _("To remove:"); stock = GTK_STOCK_REMOVE; - query->setToRemove (true); + query->add (new Ypp::QueryProperty ("to-remove", true)); prop = "to-remove"; break; default: break; @@ -274,8 +273,7 @@ gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (m_box), GTK_POS_TOP); gtk_handle_box_set_snap_edge (GTK_HANDLE_BOX (m_box), GTK_POS_RIGHT); - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->setToModify (true); + Ypp::QueryBase *query = new Ypp::QueryProperty ("to-modify", true); /* if (pkg_selector->onlineUpdateMode()) query->addType (Ypp::Package::PATCH_TYPE);*/ m_pool = Ypp::PkgQuery (Ypp::Package::PACKAGE_TYPE, query); @@ -1758,10 +1756,10 @@ static bool askConfirmUnsupported() { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->setIsInstalled (false); - query->setToModify (true); - query->setIsSupported (false); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); + query->add (new Ypp::QueryProperty ("is-installed", false)); + query->add (new Ypp::QueryProperty ("to-modify", true)); + query->add (new Ypp::QueryProperty ("is-supported", false)); Ypp::PkgQuery list (Ypp::Package::PACKAGE_TYPE, query); if (list.size() > 0) @@ -1954,7 +1952,7 @@ virtual void updateList (Ypp::PkgList list) = 0; virtual bool begsUpdate() = 0; - virtual bool writeQuery (Ypp::PkgQuery::Query *query) = 0; + virtual bool writeQuery (Ypp::QueryAnd *query) = 0; void setListener (_QueryListener *listener) { m_listener = listener; } @@ -2047,16 +2045,44 @@ virtual void updateList (Ypp::PkgList list) {} virtual bool begsUpdate() { return false; } - virtual bool writeQuery (Ypp::PkgQuery::Query *query) + static void writeQueryStr (Ypp::QueryOr *query, const std::string &prop, const gchar *value, bool case_sensitive, bool whole_word) + { + Ypp::QueryAnd *subquery = new Ypp::QueryAnd(); + const gchar delimiter[2] = { ' ', '\0' }; + gchar **names = g_strsplit (value, delimiter, -1); + for (gchar **i = names; *i; i++) + subquery->add (new Ypp::QueryProperty (prop, *i, case_sensitive, whole_word)); + g_strfreev (names); + query->add (subquery); + } + + virtual bool writeQuery (Ypp::QueryAnd *query) { const gchar *name = gtk_entry_get_text (GTK_ENTRY (m_entry)); if (*name) { int opt = 0; if (m_combo) opt = gtk_combo_box_get_active (GTK_COMBO_BOX (m_combo)); - bool whole_word = opt >= 2; - query->addNames (name, ' ', opt == 0, opt == 0, opt == 1, opt == 2, - opt == 3, whole_word); + + Ypp::QueryOr *subquery = new Ypp::QueryOr(); + switch (opt) { + case 0: + writeQueryStr (subquery, "name", name, false, false); + writeQueryStr (subquery, "summary", name, false, false); + break; + case 1: + writeQueryStr (subquery, "description", name, false, false); + break; + case 2: + writeQueryStr (subquery, "filelist", name, true, false); + writeQueryStr (subquery, "provides", name, true, false); + break; + case 3: + subquery->add (new Ypp::QueryProperty ("authors", name, false, true)); + break; + default: break; + } + query->add (subquery); return true; } return false; @@ -2211,15 +2237,15 @@ } while (gtk_tree_model_iter_next (model, &iter)); } - bool writeQuery (Ypp::PkgQuery::Query *query, GtkTreeIter *iter) + bool writeQuery (Ypp::QueryAnd *query, GtkTreeIter *iter) { Ypp::Node *category; gtk_tree_model_get (getModel(), iter, 2, &category, -1); if (category) { if (m_type2) - query->addCategory2 (category); + query->add (new Ypp::QueryCategory (category, true)); else - query->addCategory (category); + query->add (new Ypp::QueryCategory (category, false)); return true; } return false; @@ -2282,7 +2308,7 @@ virtual bool begsUpdate() { return dynamic_sidebar; } - virtual bool writeQuery (Ypp::PkgQuery::Query *query) + virtual bool writeQuery (Ypp::QueryAnd *query) { GtkTreeIter iter; GtkTreeSelection *selection; @@ -2341,25 +2367,241 @@ virtual bool begsUpdate() { return dynamic_sidebar; } - virtual bool writeQuery (Ypp::PkgQuery::Query *query) + virtual bool writeQuery (Ypp::QueryAnd *query) { GtkTreeIter iter; - gtk_combo_box_get_active_iter (GTK_COMBO_BOX (m_combo), &iter); - return m_model->writeQuery (query, &iter); + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (m_combo), &iter)) + return m_model->writeQuery (query, &iter); + return false; } static void changed_cb (GtkComboBox *combo, CategoryCombo *pThis) { pThis->notify(); } }; +class StatusModel +{ +GtkListStore *m_store; +GtkTreeModel *m_filter; +bool m_dynamic; + +public: + StatusModel (bool dynamic) + : m_dynamic (dynamic) + { + m_store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT); + + GtkTreeIter iter; + gtk_list_store_append (m_store, &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, 0, -1); + gtk_list_store_append (m_store, &iter); + if (!dynamic_sidebar) + gtk_list_store_set (m_store, &iter, 0, _("Available"), -1); + gtk_list_store_set (m_store, &iter, 1, TRUE, 2, 1, -1); + gtk_list_store_append (m_store, &iter); + if (!dynamic_sidebar) + gtk_list_store_set (m_store, &iter, 0, _("Installed"), -1); + gtk_list_store_set (m_store, &iter, 1, TRUE, 2, 2, -1); + gtk_list_store_append (m_store, &iter); + if (!dynamic_sidebar) + gtk_list_store_set (m_store, &iter, 0, _("Upgrades"), -1); + gtk_list_store_set (m_store, &iter, 1, TRUE, 2, 3, -1); + gtk_list_store_append (m_store, &iter); + if (!dynamic_sidebar) + gtk_list_store_set (m_store, &iter, 0, _("Summary"), -1); + gtk_list_store_set (m_store, &iter, 1, TRUE, 2, 4, -1); + + if (m_dynamic) { + 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); + g_object_unref (G_OBJECT (m_store)); + } + } + + ~StatusModel() + { g_object_unref (G_OBJECT (getModel())); } + + GtkTreeModel *getModel() + { return m_dynamic ? m_filter : GTK_TREE_MODEL (m_store); } + + void setType (Ypp::Package::Type type) {} + + void updateList (Ypp::PkgList list) + { + if (!m_dynamic) return; + int installedNb = 0, upgradableNb = 0, notInstalledNb = 0, modifiedNb = 0; + for (int i = 0; i < list.size(); i++) { + Ypp::Package *pkg = list.get (i); + if (pkg->isInstalled()) { + installedNb++; + if (pkg->hasUpgrade()) + upgradableNb++; + } + else + notInstalledNb++; + if (pkg->toModify()) + modifiedNb++; + } + + GtkListStore *store = m_store; + GtkTreeModel *model = GTK_TREE_MODEL (m_store); + GtkTreeIter iter; + gtk_tree_model_iter_nth_child (model, &iter, NULL, 0); + list_store_set_text_count (store, &iter, _("Any Status"), list.size()); + gtk_tree_model_iter_nth_child (model, &iter, NULL, 1); + list_store_set_text_count (store, &iter, _("Not Installed"), notInstalledNb); + gtk_tree_model_iter_nth_child (model, &iter, NULL, 2); + list_store_set_text_count (store, &iter, _("Installed"), installedNb); + gtk_tree_model_iter_nth_child (model, &iter, NULL, 3); + list_store_set_text_count (store, &iter, _("Upgradable"), upgradableNb); + gtk_tree_model_iter_nth_child (model, &iter, NULL, 4); + list_store_set_text_count (store, &iter, _("Modified"), modifiedNb); + } + + bool writeQuery (Ypp::QueryAnd *query, GtkTreeIter *iter) + { + int status; + gtk_tree_model_get (getModel(), iter, 2, &status, -1); + switch (status) { + case 0: default: break; + case 1: query->add (new Ypp::QueryProperty ("is-installed", false)); break; + case 2: query->add (new Ypp::QueryProperty ("is-installed", true)); break; + case 3: query->add (new Ypp::QueryProperty ("has-upgrade", true)); break; + case 4: query->add (new Ypp::QueryProperty ("to-modify", true)); break; + } + if (status > 0 && status <= 4) + return true; + return false; + } +}; + class StatusView : public _QueryWidget { GtkWidget *m_widget, *m_view; -GtkTreeModel *m_model; +StatusModel *m_model; public: StatusView() : _QueryWidget() { + m_model = new StatusModel (dynamic_sidebar); + m_view = tree_view_new(); + gtk_tree_view_set_model (GTK_TREE_VIEW (m_view), m_model->getModel()); + GtkWidget *scroll = scrolled_window_new (m_view); + + GtkWidget *label = gtk_label_new_with_mnemonic ("_Status:"); + gtk_misc_set_alignment (GTK_MISC (label), 0, .5); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), m_view); + + m_widget = gtk_vbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (m_widget), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_widget), scroll, TRUE, TRUE, 0); + + GtkTreeSelection *selection; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_view)); + g_signal_connect (G_OBJECT (selection), "changed", + G_CALLBACK (selection_changed_cb), this); + } + + virtual GtkWidget *getWidget() + { return m_widget; } + + virtual void updateType (Ypp::Package::Type type) + { + m_model->setType (type); + + GtkTreeSelection *selection; + GtkTreeIter iter; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_view)); + g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb, this); + gtk_tree_model_get_iter_first (m_model->getModel(), &iter); + gtk_tree_selection_select_iter (selection, &iter); + g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb, this); + } + + virtual void updateList (Ypp::PkgList list) + { m_model->updateList (list); } + + virtual bool begsUpdate() { return dynamic_sidebar; } + + virtual bool writeQuery (Ypp::QueryAnd *query) + { + GtkTreeIter iter; + GtkTreeSelection *selection; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_view)); + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + return m_model->writeQuery (query, &iter); + return false; + } +}; + +class StatusCombo : public _QueryWidget +{ +GtkWidget *m_widget, *m_combo; +StatusModel *m_model; + +public: + StatusCombo() : _QueryWidget() + { + m_model = new StatusModel (dynamic_sidebar); + m_combo = gtk_combo_box_new_with_model (m_model->getModel()); + + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (m_combo), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (m_combo), renderer, + "markup", 0, NULL); + + GtkWidget *label = gtk_label_new_with_mnemonic ("_Status:"); + gtk_misc_set_alignment (GTK_MISC (label), 0, .5); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), m_combo); + + m_widget = gtk_hbox_new (FALSE, 2); + gtk_box_pack_start (GTK_BOX (m_widget), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_widget), m_combo, TRUE, TRUE, 0); + g_signal_connect (G_OBJECT (m_combo), "changed", + G_CALLBACK (changed_cb), this); + } + + virtual GtkWidget *getWidget() + { return m_widget; } + + virtual void updateType (Ypp::Package::Type type) + { + m_model->setType (type); + + g_signal_handlers_block_by_func (m_combo, (gpointer) changed_cb, this); + gtk_combo_box_set_active (GTK_COMBO_BOX (m_combo), 0); + g_signal_handlers_unblock_by_func (m_combo, (gpointer) changed_cb, this); + } + + virtual void updateList (Ypp::PkgList list) + { m_model->updateList (list); } + + virtual bool begsUpdate() { return dynamic_sidebar; } + + virtual bool writeQuery (Ypp::QueryAnd *query) + { + GtkTreeIter iter; + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (m_combo), &iter)) + return m_model->writeQuery (query, &iter); + return false; + } + + static void changed_cb (GtkComboBox *combo, StatusCombo *pThis) + { pThis->notify(); } +}; + +#if 0 +class StatusView : public _QueryWidget +{ +GtkWidget *m_widget, *m_view; +StatusModel *m_model; + +public: + StatusView() : _QueryWidget() + { + m_model = new StatusModel m_view = tree_view_new(); GtkWidget *label = gtk_label_new_with_mnemonic ("_Statuses:"); @@ -2447,28 +2689,17 @@ virtual bool begsUpdate() { return dynamic_sidebar; } - virtual bool writeQuery (Ypp::PkgQuery::Query *query) + virtual bool writeQuery (Ypp::QueryAnd *query) { - GtkTreeModel *model; GtkTreeIter iter; GtkTreeSelection *selection; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_view)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - int status; - gtk_tree_model_get (model, &iter, 2, &status, -1); - switch (status) { - case 0: default: break; - case 1: query->setIsInstalled (false); break; - case 2: query->setIsInstalled (true); break; - case 3: query->setHasUpgrade (true); break; - case 4: query->setToModify (true); break; - } - if (status > 0 && status <= 4) - return true; - } + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + return m_model->writeQuery (query, &iter); return false; } }; +#endif #define BROWSER_PATH "/usr/bin/firefox" @@ -2520,8 +2751,7 @@ ygtk_rich_text_set_plain_text (YGTK_RICH_TEXT (m_text), ""); if (package && package->type() != Ypp::Package::PACKAGE_TYPE) { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->addCollection (package); + Ypp::QueryBase *query = new Ypp::QueryCollection (package); Ypp::PkgQuery list (Ypp::Package::PACKAGE_TYPE, query); ((YGtkPackageView *) m_pkg_view)->setList (list, NULL); gtk_widget_show (m_pkg_view); @@ -2740,6 +2970,11 @@ category_combo = new CategoryCombo(); m_query.push_back (category_combo); } + StatusCombo *status_combo = 0; + if (status_top) { + status_combo = new StatusCombo(); + m_query.push_back (status_combo); + } UndoView *undo_view = 0; if (undo_side || undo_tab) @@ -2818,6 +3053,8 @@ } if (category_combo) gtk_box_pack_start (GTK_BOX (header_box), category_combo->getWidget(), FALSE, TRUE, 0); + if (status_combo) + gtk_box_pack_start (GTK_BOX (header_box), status_combo->getWidget(), FALSE, TRUE, 0); if (search_entry) gtk_box_pack_start (GTK_BOX (header_box), search_entry->getWidget(), FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (packages_box), header_box, FALSE, TRUE, 0); @@ -2825,12 +3062,14 @@ } GtkWidget *packages_button_box = gtk_vbox_new (FALSE, 4); - if (status_tabs && (arrange_box || category_combo)) { + if (status_tabs && (arrange_box || category_combo || status_combo)) { GtkWidget *hbox = gtk_hbox_new (FALSE, 6); if (arrange_box) gtk_box_pack_start (GTK_BOX (hbox), arrange_box, FALSE, TRUE, 0); if (category_combo) gtk_box_pack_start (GTK_BOX (hbox), category_combo->getWidget(), FALSE, TRUE, 0); + if (status_combo) + gtk_box_pack_start (GTK_BOX (hbox), status_combo->getWidget(), FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (packages_button_box), hbox, FALSE, TRUE, 0); } gtk_box_pack_start (GTK_BOX (packages_button_box), packages_box, TRUE, TRUE, 0); @@ -2950,7 +3189,7 @@ private: void updateWidget (_QueryWidget *widget) { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); for (std::list <_QueryWidget *>::const_iterator it = m_query.begin(); it != m_query.end(); it++) { if (*it == widget) @@ -2978,7 +3217,7 @@ Ypp::Node *category; for (int cycle = 0; true; cycle++) { // for arrange_by - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); for (std::list <_QueryWidget *>::const_iterator it = m_query.begin(); it != m_query.end(); it++) (*it)->modified = (*it)->writeQuery (query); @@ -2993,13 +3232,13 @@ if (!category) break; header = category->name.c_str(); - query->addCategory2 (category); + query->add (new Ypp::QueryCategory (category, true)); } else if (arrange == 1) { // repositories const Ypp::Repository *repo = Ypp::get()->getRepository (cycle); if (repo) { header = repo->name.c_str(); - query->addRepository (repo); + query->add (new Ypp::QueryRepository (repo)); } else break; @@ -3007,19 +3246,19 @@ else if (arrange == 2) { // statuses if (cycle == 0) { header = _("Available"); - query->setIsInstalled (false); + query->add (new Ypp::QueryProperty ("is-installed", false)); } else if (cycle == 1) { header = _("Upgrades"); - query->setHasUpgrade (true); + query->add (new Ypp::QueryProperty ("has-upgrade", true)); } else if (cycle == 2) { header = _("Installed"); - query->setIsInstalled (true); + query->add (new Ypp::QueryProperty ("is-installed", true)); } else if (cycle == 3) { header = _("Modified"); - query->setToModify (true); + query->add (new Ypp::QueryProperty ("to-modify", true)); } else break; @@ -3032,20 +3271,20 @@ m_all_view->packList (header, list, NULL); if (m_installed_view) { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->setIsInstalled (true); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); + query->add (new Ypp::QueryProperty ("is-installed", true)); Ypp::PkgQuery _list (list, query); m_installed_view->packList (header, _list, NULL); } if (m_available_view) { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->setIsInstalled (false); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); + query->add (new Ypp::QueryProperty ("is-installed", false)); Ypp::PkgQuery _list (list, query); m_available_view->packList (header, _list, NULL); } if (m_upgrades_view) { - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->setHasUpgrade (true); + Ypp::QueryAnd *query = new Ypp::QueryAnd(); + query->add (new Ypp::QueryProperty ("has-upgrade", true)); Ypp::PkgQuery _list (list, query); m_upgrades_view->packList (header, _list, _("Upgrade all")); } Modified: trunk/gtk/src/pkg/ygtkdetailview.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/ygtkdetailview.cc?rev=60205&r1=60204&r2=60205&view=diff ============================================================================== --- trunk/gtk/src/pkg/ygtkdetailview.cc (original) +++ trunk/gtk/src/pkg/ygtkdetailview.cc Wed Dec 30 12:01:38 2009 @@ -645,8 +645,7 @@ static void contents_cb (GtkWidget *widget, gpointer pkg) { YGtkPackageView *contents = YGTK_PACKAGE_VIEW (widget); - Ypp::PkgQuery::Query *query = new Ypp::PkgQuery::Query(); - query->addCollection ((Ypp::Package *) pkg); + Ypp::QueryBase *query = new Ypp::QueryCollection ((Ypp::Package *) pkg); contents->setList (Ypp::PkgQuery (Ypp::Package::PACKAGE_TYPE, query), 0); } Modified: trunk/gtk/src/pkg/yzyppwrapper.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/yzyppwrapper.cc?rev=60205&r1=60204&r2=60205&view=diff ============================================================================== --- trunk/gtk/src/pkg/yzyppwrapper.cc (original) +++ trunk/gtk/src/pkg/yzyppwrapper.cc Wed Dec 30 12:01:38 2009 @@ -334,6 +334,34 @@ std::string Ypp::Package::provides (MarkupType markup) const { return impl->provides (markup); } std::string Ypp::Package::requires (MarkupType markup) const { return impl->requires (markup); } +bool Ypp::Package::getPropertyBool (const std::string &prop) +{ + if (prop == "is-installed") + return isInstalled(); + if (prop == "has-upgrade") + return hasUpgrade(); + if (prop == "to-modify") + return toModify(); + if (prop == "is-recommended") + return isRecommended(); + if (prop == "is-suggested") + return isSuggested(); + if (prop == "is-supported") + return isSupported(); + if (prop == "to-install") + return toInstall(); + yuiError() << "No boolean property: " << prop << std::endl; + return false; +} + +int Ypp::Package::getPropertyInt (const std::string &prop) +{ + if (prop == "severity") + return severity(); + yuiError() << "No integer property: " << prop << std::endl; + return 0; +} + std::string Ypp::Package::getPropertyStr (const std::string &prop, MarkupType markup) { if (prop == "name") @@ -348,6 +376,8 @@ return support(); if (prop == "size") return size(); + if (prop == "authors") + return authors (markup); if (prop == "available-version") { const Ypp::Package::Version *version = getAvailableVersion (0); if (version) @@ -367,28 +397,6 @@ return ""; } -int Ypp::Package::getPropertyInt (const std::string &prop) -{ - if (prop == "severity") - return severity(); - yuiError() << "No integer property: " << prop << std::endl; - return 0; -} - -bool Ypp::Package::getPropertyBool (const std::string &prop) -{ - if (prop == "is-recommended") - return isRecommended(); - if (prop == "is-suggested") - return isSuggested(); - if (prop == "is-supported") - return isSupported(); - if (prop == "to-install") - return toInstall(); - yuiError() << "No boolean property: " << prop << std::endl; - return false; -} - const Ypp::Package::Version *Ypp::Package::getInstalledVersion() { return impl->getInstalledVersion(); } const Ypp::Package::Version *Ypp::Package::getAvailableVersion (int nb) @@ -1936,311 +1944,174 @@ void Ypp::PkgList::removeListener (Ypp::PkgList::Listener *listener) const { const_cast <Impl *> (impl)->removeListener (listener); } -//** PkgQuery +//** QueryBase + +struct Ypp::QueryAnd::Impl +{ std::list <QueryBase *> m_queries; }; + +Ypp::QueryAnd::QueryAnd() +{ impl = new Impl(); } -struct Ypp::PkgQuery::Query::Impl +Ypp::QueryAnd::~QueryAnd() { - template <typename T> - struct Key - { - Key() : defined (false) {} - void set (T v) - { - defined = true; - value = v; - } - bool is (const T &v) const - { - if (!defined) return true; - return value == v; - } - bool defined; - T value; - }; + for (std::list <QueryBase *>::const_iterator it = impl->m_queries.begin(); + it != impl->m_queries.end(); it++) + delete (*it); +} - template <typename T> - struct Keys - { - Keys() : defined (false) {} - void add (T v) - { - defined = true; - values.push_back (v); - } - bool is (const T &v) const - { - if (!defined) return true; - typename std::list <T>::const_iterator it; - for (it = values.begin(); it != values.end(); it++) - if (*it == v) - return true; +void Ypp::QueryAnd::add (Ypp::QueryBase *query) +{ impl->m_queries.push_back (query); } + +bool Ypp::QueryAnd::match (Ypp::Package *package) +{ + for (std::list <QueryBase *>::const_iterator it = impl->m_queries.begin(); + it != impl->m_queries.end(); it++) + if (!(*it)->match (package)) return false; - } - bool defined; - std::list <T> values; - }; + return true; +} - Keys <std::string> names; - unsigned int use_name : 1, use_summary : 1, use_description : 1, use_filelist : 1, - use_authors : 1, whole_word : 1, whole_string : 1; - Keys <Node *> categories, categories2; - Keys <const Package *> collections; - Keys <const Repository *> repositories; - Key <bool> isInstalled, hasUpgrade, toModify, toInstall, toRemove; - Key <bool> isRecommended, isSuggested; - Key <int> buildAge; - Key <bool> isSupported; - Key <int> severity; - bool clear; - Ypp::Package *highlight; +struct Ypp::QueryOr::Impl +{ std::list <QueryBase *> m_queries; }; -#if 0 - template <typename T> - struct PropKey { - T property; - T value; - }; - std::list <PropKey <bool> > boolKeys; - std::list <PropKey <int > > intKeys; - std::list <PropKey <std::string > > strKeys; -#endif +Ypp::QueryOr::QueryOr() +{ impl = new Impl(); } - Impl() : clear (false), highlight (NULL) - {} +Ypp::QueryOr::~QueryOr() +{ + for (std::list <QueryBase *>::const_iterator it = impl->m_queries.begin(); + it != impl->m_queries.end(); it++) + delete (*it); +} - bool match (Package *package) const - { - struct inner { - static bool strstr (const char *str1, const char *str2, - bool case_sensitive, bool whole_word, bool whole_string) - { - const char *i; - if (whole_string) { - if (case_sensitive) - return strcmp (str1, str2) == 0; - return strcasecmp (str1, str2) == 0; - } - if (case_sensitive) - i = ::strstr (str1, str2); - else - i = ::strcasestr (str1, str2); - if (whole_word && i) { // check boundries - if (i != str1 && isalpha (i[-1])) - return false; - int len = strlen (str2); - if (i [len] && isalpha (i [len])) - return false; - return true; - } - return i; - } - }; +void Ypp::QueryOr::add (Ypp::QueryBase *query) +{ impl->m_queries.push_back (query); } - if (clear) - return false; - bool match = true; -#if 0 - for (std::list <PropKey <bool> >::const_iterator it = boolKeys.begin(); - it != boolKeys.end(); it++) { - const PropKey <bool> &key = *it; - if (package->getPropertyBool (key.property) != key.value) - return false; - } - for (std::list <PropKey <int> >::const_iterator it = intKeys.begin(); - it != intKeys.end(); it++) { - const PropKey <int> &key = *it; - if (package->getPropertyInt (key.property) != key.value) - return false; - } - bool str_match = false; - for (std::list <PropKey <std::string> >::const_iterator it = strKeys.begin(); - it != strKeys.end(); it++) { - const PropKey <std::string> &key = *it; - std::string pkg_value = package->getPropertyStr (key.property); - if (pkg_value != key.value) - return false; - } -#endif - if (match && (isInstalled.defined || hasUpgrade.defined)) { - // only one of the specified status must match - bool status_match = false; - if (isInstalled.defined) - status_match = isInstalled.is (package->isInstalled()); - if (!status_match && hasUpgrade.defined) - status_match = hasUpgrade.is (package->hasUpgrade()); - match = status_match; - } - if (match && toModify.defined) - match = toModify.is (package->toModify()); - if (match && toInstall.defined) - match = toInstall.is (package->toInstall()); - if (match && toRemove.defined) - match = toRemove.is (package->toRemove()); - if (match && isRecommended.defined) - match = isRecommended.is (package->isRecommended()); - if (match && isSuggested.defined) - match = isSuggested.is (package->isSuggested()); - if (match && buildAge.defined) { - int age = package->buildAge(); - if (age < 0 || age > buildAge.value) - match = false; - } - if (match && isSupported.defined) - match = isSupported.is (package->isSupported()); - if (match && severity.defined) - match = severity.is (package->severity()); - if (match && names.defined) { - const std::list <std::string> &values = names.values; - std::list <std::string>::const_iterator it; - for (it = values.begin(); it != values.end(); it++) { - const char *key = it->c_str(); - bool str_match = false; - if (use_name) - str_match = inner::strstr (package->name().c_str(), key, - false, whole_word, whole_string); - if (!str_match && use_summary) - str_match = inner::strstr (package->summary().c_str(), key, - false, whole_word, whole_string); - if (!str_match && use_description) - str_match = inner::strstr (package->description (NO_MARKUP).c_str(), key, - false, whole_word, whole_string); - if (!str_match && use_filelist) - str_match = inner::strstr (package->filelist (NO_MARKUP).c_str(), key, - false, whole_word, whole_string); - if (!str_match && use_authors) - str_match = inner::strstr (package->authors (NO_MARKUP).c_str(), key, - false, whole_word, whole_string); - if (!str_match) { - match = false; - break; - } - } - if (match && !highlight && use_name) { - if (values.size() == 1 && !strcasecmp (values.front().c_str(), package->name().c_str())) - const_cast <Impl *> (this)->highlight = package; - } - } - if (match && categories.defined) { - Ypp::Node *pkg_category = package->category(); - const std::list <Ypp::Node *> &values = categories.values; - std::list <Ypp::Node *>::const_iterator it; - for (it = values.begin(); it != values.end(); it++) { - GNode *node = (GNode *) (*it)->impl; - if (g_node_find (node, G_PRE_ORDER, G_TRAVERSE_ALL, pkg_category)) - break; - } - match = it != values.end(); - } - if (match && categories2.defined) { - Ypp::Node *pkg_category = package->category2(); - const std::list <Ypp::Node *> &values = categories2.values; - std::list <Ypp::Node *>::const_iterator it; - for (it = values.begin(); it != values.end(); it++) { - GNode *node = (GNode *) (*it)->impl; - if (g_node_find (node, G_PRE_ORDER, G_TRAVERSE_ALL, pkg_category)) - break; - } - match = it != values.end(); - } - if (match && repositories.defined) { - const std::list <const Repository *> &values = repositories.values; - std::list <const Repository *>::const_iterator it; - for (it = values.begin(); it != values.end(); it++) { - bool match = false; - for (int i = 0; package->getAvailableVersion (i); i++) { - const Ypp::Package::Version *version = package->getAvailableVersion (i); - if (version->repo == *it) { - // filter if available isn't upgrade - if (package->isInstalled() && hasUpgrade.defined && hasUpgrade.value) { - if (version->cmp > 0) - match = true; - } - else - match = true; - break; - } - } - if (match) - break; - } - match = it != values.end(); - } - if (match && collections.defined) { - const std::list <const Ypp::Package *> &values = collections.values; - std::list <const Ypp::Package *>::const_iterator it; - for (it = values.begin(); it != values.end(); it++) - if (package->fromCollection (*it)) - break; - match = it != values.end(); - } - return match; +bool Ypp::QueryOr::match (Ypp::Package *package) +{ + for (std::list <QueryBase *>::const_iterator it = impl->m_queries.begin(); + it != impl->m_queries.end(); it++) + if ((*it)->match (package)) + return true; + return false; +} + +struct Ypp::QueryProperty::Impl +{ virtual bool match (Ypp::Package *) = 0; }; + +struct QueryBool : public Ypp::QueryProperty::Impl +{ + std::string property; + bool value; + + QueryBool (const std::string &property, bool value) + : property (property), value (value) {} + + virtual bool match (Ypp::Package *package) + { return package->getPropertyBool (property) == value; } +}; + +struct QueryInt : public Ypp::QueryProperty::Impl +{ + std::string property; + int value; + + QueryInt (const std::string &property, int value) + : property (property), value (value) {} + + virtual bool match (Ypp::Package *package) + { return package->getPropertyInt (property) == value; } +}; + +struct QueryStr : public Ypp::QueryProperty::Impl +{ + std::string property; + std::string value; + bool case_sensitive, whole_word; + + QueryStr (const std::string &property, const std::string &value, + bool case_sensitive, bool whole_word) + : property (property), value (value), case_sensitive (case_sensitive), + whole_word (whole_word) {} + + virtual bool match (Ypp::Package *package) + { + std::string pkg_value = package->getPropertyStr (property); + if (whole_word) { + if (case_sensitive) + return strcmp (pkg_value.c_str(), value.c_str()) == 0; + return strcasecmp (pkg_value.c_str(), value.c_str()) == 0; + } + if (case_sensitive) + return strstr (pkg_value.c_str(), value.c_str()) != NULL; + return strcasestr (pkg_value.c_str(), value.c_str()) != NULL; } }; -Ypp::PkgQuery::Query::Query() -{ impl = new Impl(); } -Ypp::PkgQuery::Query::~Query() +Ypp::QueryProperty::QueryProperty (const std::string &property, bool value) +{ impl = new QueryBool (property, value); } + +Ypp::QueryProperty::QueryProperty (const std::string &property, int value) +{ impl = new QueryInt (property, value); } + +Ypp::QueryProperty::QueryProperty (const std::string &property, const std::string &value, bool case_sensitive, bool whole_word) +{ impl = new QueryStr (property, value, case_sensitive, whole_word); } + +Ypp::QueryProperty::~QueryProperty() +{ delete impl; } + +bool Ypp::QueryProperty::match (Ypp::Package *package) +{ return impl->match (package); } + +struct Ypp::QueryCategory::Impl { + const Node *category; + bool category2; + Impl (const Node *category, bool category2) + : category (category), category2 (category2) {} +}; + +Ypp::QueryCategory::QueryCategory (const Ypp::Node *category, bool category2) +{ impl = new Impl (category, category2); } + +Ypp::QueryCategory::~QueryCategory() { delete impl; } -void Ypp::PkgQuery::Query::addNames (std::string value, char separator, bool use_name, - bool use_summary, bool use_description, bool use_filelist, bool use_authors, - bool whole_word, bool whole_string) -{ - if (separator) { - const gchar delimiter[2] = { separator, '\0' }; - gchar **names = g_strsplit (value.c_str(), delimiter, -1); - for (gchar **i = names; *i; i++) - impl->names.add (*i); - g_strfreev (names); - } - else - impl->names.add (value); - impl->use_name = use_name; - impl->use_summary = use_summary; - impl->use_description = use_description; - impl->use_filelist = use_filelist; - impl->use_authors = use_authors; - impl->whole_word = whole_word; - impl->whole_string = whole_string; -} -void Ypp::PkgQuery::Query::addCategory (Ypp::Node *value) -{ impl->categories.add (value); } -void Ypp::PkgQuery::Query::addCategory2 (Ypp::Node *value) -{ impl->categories2.add (value); } -void Ypp::PkgQuery::Query::addCollection (const Ypp::Package *value) -{ impl->collections.add (value); } -void Ypp::PkgQuery::Query::addRepository (const Repository *value) -{ impl->repositories.add (value); } -void Ypp::PkgQuery::Query::setIsInstalled (bool value) -{ impl->isInstalled.set (value); } -void Ypp::PkgQuery::Query::setHasUpgrade (bool value) -{ impl->hasUpgrade.set (value); } -void Ypp::PkgQuery::Query::setToModify (bool value) -{ impl->toModify.set (value); } -void Ypp::PkgQuery::Query::setToInstall (bool value) -{ impl->toInstall.set (value); } -void Ypp::PkgQuery::Query::setToRemove (bool value) -{ impl->toRemove.set (value); } -void Ypp::PkgQuery::Query::setIsRecommended (bool value) -{ impl->isRecommended.set (value); } -void Ypp::PkgQuery::Query::setIsSuggested (bool value) -{ impl->isSuggested.set (value); } -void Ypp::PkgQuery::Query::setBuildAge (int value) -{ impl->buildAge.set (value); } -void Ypp::PkgQuery::Query::setIsSupported (bool value) -{ impl->isSupported.set (value); } -void Ypp::PkgQuery::Query::setSeverity (int value) -{ impl->severity.set (value); } -void Ypp::PkgQuery::Query::setClear() -{ impl->clear = true; } +bool Ypp::QueryCategory::match (Ypp::Package *package) +{ + GNode *node = (GNode *) impl->category->impl; + Node *pkg_category = impl->category2 ? package->category2() : package->category(); + if (g_node_find (node, G_PRE_ORDER, G_TRAVERSE_ALL, pkg_category)) + return true; + return false; +} + +Ypp::QueryRepository::QueryRepository (const Ypp::Repository *_repo) +{ repo = _repo; } + +bool Ypp::QueryRepository::match (Ypp::Package *package) +{ + for (int i = 0; package->getAvailableVersion (i); i++) { + const Package::Version *version = package->getAvailableVersion (i); + if (version->repo == repo) + return true; + } + return false; +} + +Ypp::QueryCollection::QueryCollection (const Ypp::Package *_collection) +{ collection = _collection; } + +bool Ypp::QueryCollection::match (Ypp::Package *package) +{ return package->fromCollection (collection); } + +//** PkgQuery struct Ypp::PkgQuery::Impl : public Ypp::PkgList::Impl { -Query *query; +QueryBase *query; - Impl (const PkgList parent, Query *query) - : PkgList::Impl (&parent), query (query) - {} + Impl (const PkgList parent, QueryBase *query) + : PkgList::Impl (&parent), query (query) {} ~Impl() { delete query; } @@ -2248,22 +2119,22 @@ virtual bool liveList() const { return true; } - virtual bool match (Package *pkg) const - { return query ? query->impl->match (pkg) : true; } + virtual bool match (Package *package) const + { return query->match (package); } virtual bool highlight (Package *pkg) const { - if (query && query->impl->highlight == pkg) - return true; +/* if (old_query->impl->highlight == pkg) + return true;*/ return parent->highlight (pkg); // this might be a sub-query } }; -Ypp::PkgQuery::PkgQuery (const Ypp::PkgList list, Ypp::PkgQuery::Query *query) +Ypp::PkgQuery::PkgQuery (const Ypp::PkgList list, Ypp::QueryBase *query) : PkgList ((impl = new PkgQuery::Impl (list, query))) { copy (list); } -Ypp::PkgQuery::PkgQuery (Ypp::Package::Type type, Ypp::PkgQuery::Query *query) +Ypp::PkgQuery::PkgQuery (Ypp::Package::Type type, Ypp::QueryBase *query) : PkgList ((impl = new PkgQuery::Impl (Ypp::get()->getPackages (type), query))) { copy (Ypp::get()->getPackages (type)); } Modified: trunk/gtk/src/pkg/yzyppwrapper.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/pkg/yzyppwrapper.h?rev=60205&r1=60204&r2=60205&view=diff ============================================================================== --- trunk/gtk/src/pkg/yzyppwrapper.h (original) +++ trunk/gtk/src/pkg/yzyppwrapper.h Wed Dec 30 12:01:38 2009 @@ -73,9 +73,9 @@ std::string provides (MarkupType markup) const; std::string requires (MarkupType markup) const; - std::string getPropertyStr (const std::string &prop, MarkupType markup = NO_MARKUP); - int getPropertyInt (const std::string &prop); bool getPropertyBool (const std::string &prop); + int getPropertyInt (const std::string &prop); + std::string getPropertyStr (const std::string &prop, MarkupType markup = NO_MARKUP); struct Version { std::string number, arch; @@ -178,36 +178,62 @@ }; // listing of packages as filtered - struct PkgQuery : public PkgList { - struct Query { - Query(); - void addNames (std::string name, char separator = 0, bool use_name = true, - bool use_summary = true, bool use_description = false, - bool use_filelist = false, bool use_authors = false, - bool whole_word = false, bool whole_string = false); - void addCategory (Ypp::Node *category); - void addCategory2 (Ypp::Node *category); - void addCollection (const Ypp::Package *package); - void addRepository (const Ypp::Repository *repository); - void setIsInstalled (bool installed); - void setHasUpgrade (bool upgradable); - void setToModify (bool modify); - void setToInstall (bool install); - void setToRemove (bool remove); - void setIsRecommended (bool recommended); - void setIsSuggested (bool suggested); - void setBuildAge (int days); - void setIsSupported (bool supported); - void setSeverity (int severity); - void setClear(); - - ~Query(); - struct Impl; - Impl *impl; - }; + struct QueryBase { + virtual ~QueryBase() {} + virtual bool match (Package *) = 0; + }; + struct QueryAnd : public QueryBase { + QueryAnd(); + void add (QueryBase *query); + + virtual ~QueryAnd(); + virtual bool match (Package *); + struct Impl; + Impl *impl; + }; + struct QueryOr : public QueryBase { + QueryOr(); + void add (QueryBase *query); + + virtual ~QueryOr(); + virtual bool match (Package *); + struct Impl; + Impl *impl; + }; + struct QueryProperty : public QueryBase { + QueryProperty (const std::string &property, bool value); + QueryProperty (const std::string &property, int value); + QueryProperty (const std::string &property, const std::string &value, bool case_sensitive, bool whole_word); - PkgQuery (const PkgList list, Query *query); - PkgQuery (Package::Type type, Query *query); // shortcut + virtual ~QueryProperty(); + virtual bool match (Package *); + struct Impl; + Impl *impl; + }; + struct QueryCategory : public QueryBase { + QueryCategory (const Node *category, bool category2); + + virtual ~QueryCategory(); + virtual bool match (Package *); + struct Impl; + Impl *impl; + }; + struct QueryRepository : public QueryBase { + QueryRepository (const Repository *repository); + + virtual bool match (Package *); + const Repository *repo; + }; + struct QueryCollection : public QueryBase { + QueryCollection (const Ypp::Package *collection); + + virtual bool match (Package *); + const Ypp::Package *collection; + }; + + struct PkgQuery : public PkgList { + PkgQuery (const PkgList list, QueryBase *query); + PkgQuery (Package::Type type, QueryBase *query); // shortcut struct Impl; Impl *impl; -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org
participants (1)
-
rpmcruz@svn.opensuse.org