14 #include "ygtkpkgpatternview.h"
15 #include "ygtktreeview.h"
16 #include "ygtkcellrenderertext.h"
19 #define GRAY_COLOR "#727272"
22 HAS_CHECK_COLUMN, CHECK_COLUMN, HAS_ICON_COLUMN, ICON_COLUMN,
23 TEXT_COLUMN, ORDER_COLUMN, POINTER_COLUMN, TOTAL_COLUMNS
27 GtkWidget *scroll, *view;
30 { Ypp::addSelListener (
this); }
33 Ypp::removeSelListener (
this);
34 if (!g_object_get_data (G_OBJECT (getModel()),
"patterns"))
35 gtk_tree_model_foreach (getModel(), free_foreach_cb,
this);
38 GtkTreeModel *getModel()
39 {
return gtk_tree_view_get_model (GTK_TREE_VIEW (view)); }
41 static gboolean free_foreach_cb (GtkTreeModel *model,
42 GtkTreePath *path, GtkTreeIter *iter, gpointer data)
45 gtk_tree_model_get (model, iter, POINTER_COLUMN, &_data, -1);
50 static gboolean update_foreach_cb (GtkTreeModel *model,
51 GtkTreePath *path, GtkTreeIter *iter, gpointer data)
54 gtk_tree_model_get (model, iter, POINTER_COLUMN, &_data, -1);
56 ZyppSelectablePtr zsel = (ZyppSelectablePtr) _data;
59 GtkTreeStore *store = GTK_TREE_STORE (model);
60 gtk_tree_store_set (store, iter, CHECK_COLUMN,
61 sel.isInstalled() || sel.toInstall(), -1);
66 virtual void selectableModified()
67 { gtk_tree_model_foreach (getModel(), update_foreach_cb,
this); }
70 static Ypp::Selectable get_iter_selectable (GtkTreeModel *model, GtkTreeIter *iter)
72 if (g_object_get_data (G_OBJECT (model),
"patterns")) {
73 ZyppSelectablePtr zsel;
74 gtk_tree_model_get (model, iter, POINTER_COLUMN, &zsel, -1);
79 gtk_tree_model_get (model, iter, POINTER_COLUMN, &code, -1);
80 zypp::Locale locale (code);
87 GtkTreeStore *store, GtkTreeIter *iter,
Ypp::Selectable &sel, ZyppPattern pattern)
90 GdkPixbuf *pixbuf = 0;
93 std::string filename (pattern->icon().asString());
94 if (filename == zypp::Pathname(
"yast-system").asString() || filename.empty())
95 filename =
"pattern-generic";
96 if (filename.compare (0, 2,
"./", 2) == 0)
97 filename.erase (0, 2);
98 filename = zypp::str::form (
"%s/icons/%dx%d/apps/%s.png",
99 THEMEDIR, 32, 32, filename.c_str());
100 pixbuf = YGUtils::loadPixbuf (filename);
108 order = pattern->order();
109 ptr = get_pointer (sel.zyppSel());
112 ptr = g_strdup (sel.zyppLocale().code().c_str());
114 gtk_tree_store_set (store, iter, HAS_CHECK_COLUMN, TRUE,
115 CHECK_COLUMN, sel.isInstalled() || sel.toInstall(), HAS_ICON_COLUMN, TRUE,
116 ICON_COLUMN, pixbuf, TEXT_COLUMN, (sel.name() +
'\n').c_str(),
117 ORDER_COLUMN, order.c_str(),
118 POINTER_COLUMN, ptr, -1);
121 g_object_unref (G_OBJECT (pixbuf));
124 static gboolean set_rows_cb (GtkTreeModel *model,
125 GtkTreePath *path, GtkTreeIter *iter, gpointer data)
128 gtk_tree_model_get (model, iter, POINTER_COLUMN, &_data, -1);
129 if (!_data)
return FALSE;
133 int installed, total;
135 gchar *text = g_strdup_printf (
"%s\n<span color=\"" GRAY_COLOR
136 "\"><small>Installed %d of %d</small></span>",
137 sel.name().c_str(), installed, total);
139 GtkTreeStore *store = GTK_TREE_STORE (model);
140 gtk_tree_store_set (store, iter, TEXT_COLUMN, text, -1);
145 static gboolean set_rows_idle (gpointer data)
147 gtk_tree_model_foreach (GTK_TREE_MODEL (data), set_rows_cb, NULL);
151 static bool find_name (GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter,
const std::string &name)
153 GtkTreeModel *model = GTK_TREE_MODEL (store);
155 if (gtk_tree_model_iter_children (model, iter, parent))
158 gtk_tree_model_get (model, iter, TEXT_COLUMN, &value, -1);
164 }
while (gtk_tree_model_iter_next (model, iter));
168 static bool find_place (GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter,
const std::string &order)
170 GtkTreeModel *model = GTK_TREE_MODEL (store);
172 if (gtk_tree_model_iter_children (model, iter, parent))
175 gtk_tree_model_get (model, iter, ORDER_COLUMN, &value, -1);
179 if (done)
return true;
180 }
while (gtk_tree_model_iter_next (model, iter));
184 static void insert_node (GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter,
const std::string &order)
186 if (find_place (store, parent, iter, order)) {
187 GtkTreeIter sibling = *iter;
188 gtk_tree_store_insert_before (store, iter, parent, &sibling);
191 gtk_tree_store_append (store, iter, parent);
194 static void insert_pattern (
195 GtkTreeStore *store, GtkTreeIter *parent,
Ypp::Selectable &sel, ZyppPattern pattern)
198 insert_node (store, parent, &iter, pattern->order());
199 set_row (store, &iter, sel, pattern);
202 static void insert_category (GtkTreeStore *store,
Ypp::Selectable &sel, ZyppPattern pattern)
205 std::string text (
"<big><b>" + pattern->category() +
"</b></big>");
207 if (!find_name (store, NULL, &iter, text)) {
208 insert_node (store, NULL, &iter, pattern->order());
209 gtk_tree_store_set (store, &iter, HAS_CHECK_COLUMN, FALSE,
210 CHECK_COLUMN, FALSE, HAS_ICON_COLUMN, FALSE, ICON_COLUMN, NULL,
211 TEXT_COLUMN, text.c_str(),
212 ORDER_COLUMN, pattern->order().c_str(), POINTER_COLUMN, NULL, -1);
214 insert_pattern (store, &iter, sel, pattern);
217 static void insert_language (GtkTreeStore *store,
Ypp::Selectable &sel)
219 std::string name (sel.name());
221 GtkTreeModel *model = GTK_TREE_MODEL (store);
223 if (gtk_tree_model_iter_children (model, &iter, NULL))
226 gtk_tree_model_get (model, &iter, TEXT_COLUMN, &value, -1);
227 if (g_utf8_collate (name.c_str(), value) < 0)
231 }
while (gtk_tree_model_iter_next (model, &iter));
234 GtkTreeIter sibling = iter;
235 gtk_tree_store_insert_before (store, &iter, NULL, &sibling);
238 gtk_tree_store_append (store, &iter, NULL);
240 set_row (store, &iter, sel, NULL);
243 static void install_cb (GtkWidget *widget, ZyppSelectablePtr zsel)
245 static void undo_cb (GtkWidget *widget, ZyppSelectablePtr zsel)
247 static void remove_cb (GtkWidget *widget, ZyppSelectablePtr zsel)
250 static GtkWidget *menu_item_append (GtkWidget *menu,
const char *_label,
const char *stock,
bool sensitive)
254 label = YGUtils::mapKBAccel (_label);
257 item = gtk_image_menu_item_new_with_mnemonic (label.c_str());
259 GtkWidget *icon = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
260 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon);
264 item = gtk_image_menu_item_new_from_stock (stock, NULL);
265 gtk_widget_set_sensitive (item, sensitive);
266 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
270 static void right_click_cb (YGtkTreeView *yview, gboolean outreach,
YGtkPkgPatternView *pThis)
273 GtkTreeView *view = GTK_TREE_VIEW (yview);
274 GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
277 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
278 ZyppSelectablePtr zsel;
279 gtk_tree_model_get (model, &iter, POINTER_COLUMN, &zsel, -1);
282 GtkWidget *menu = gtk_menu_new(), *item;
283 if (sel.toModify()) {
284 item = menu_item_append (menu, NULL, GTK_STOCK_UNDO,
true);
285 g_signal_connect (G_OBJECT (item),
"activate",
286 G_CALLBACK (undo_cb), zsel);
289 if (sel.isInstalled()) {
290 if (sel.canRemove()) {
291 item = menu_item_append (menu, _(
"&Remove"), GTK_STOCK_REMOVE,
true);
292 g_signal_connect (G_OBJECT (item),
"activate",
293 G_CALLBACK (remove_cb), zsel);
296 menu_item_append (menu, _(
"Remove: cannot remove patterns"), NULL,
false);
299 item = menu_item_append (menu, _(
"&Install"), GTK_STOCK_ADD,
true);
300 g_signal_connect (G_OBJECT (item),
"activate",
301 G_CALLBACK (install_cb), zsel);
305 ygtk_tree_view_popup_menu (yview, menu);
310 static void toggle_iter (GtkTreeModel *model, GtkTreeIter *iter)
313 sel.toModify() ? sel.undo() : sel.install();
316 static void row_activated_cb (GtkTreeView *view,
319 GtkTreeModel *model = pThis->impl->getModel();
321 if (gtk_tree_model_get_iter (model, &iter, path))
322 toggle_iter (model, &iter);
325 static void toggled_cb (GtkCellRendererToggle *renderer, gchar *path,
YGtkPkgPatternView *pThis)
327 GtkTreeModel *model = pThis->impl->getModel();
329 if (gtk_tree_model_get_iter_from_string (model, &iter, path))
330 toggle_iter (model, &iter);
333 static gboolean can_tree_select_cb (GtkTreeSelection *selection,
334 GtkTreeModel *model, GtkTreePath *path, gboolean path_selected, gpointer data)
337 gtk_tree_model_get_iter (model, &iter, path);
339 gtk_tree_model_get (model, &iter, POINTER_COLUMN, &_data, -1);
340 return _data != NULL;
343 static void selection_changed_cb (GtkTreeSelection *selection,
YGtkPkgPatternView *pThis)
346 static gboolean query_tooltip_cb (GtkWidget *widget, gint x, gint y,
349 GtkTreeView *view = GTK_TREE_VIEW (widget);
353 if (gtk_tree_view_get_tooltip_context (view,
354 &x, &y, keyboard_mode, &model, &path, &iter)) {
355 gtk_tree_view_set_tooltip_row (view, tooltip, path);
356 gtk_tree_path_free (path);
358 GtkTreeViewColumn *column;
360 gtk_tree_view_convert_widget_to_bin_window_coords (
361 view, x, y, &bx, &by);
362 gtk_tree_view_get_path_at_pos (
363 view, x, y, NULL, &column, NULL, NULL);
365 ZyppSelectablePtr zsel;
366 gtk_tree_model_get (model, &iter, POINTER_COLUMN, &zsel, -1);
370 if (column == ygtk_tree_view_get_column (YGTK_TREE_VIEW (view), 0)) {
371 if (sel.isInstalled())
372 gtk_tooltip_set_text (tooltip,
373 _(
"Installed: cannot remove a pattern.\n\n"
374 "You must manually remove the individual packages you no "
375 "longer want to keep."));
377 gtk_tooltip_set_text (tooltip, _(
"Not installed"));
380 std::string text (YGUtils::escapeMarkup (sel.description (
false)));
381 gtk_tooltip_set_text (tooltip, text.c_str());
389 YGtkPkgPatternView::YGtkPkgPatternView (Ypp::Selectable::Type type)
392 assert (type == Ypp::Selectable::LANGUAGE || type == Ypp::Selectable::PATTERN);
394 GtkTreeStore *store = gtk_tree_store_new (TOTAL_COLUMNS, G_TYPE_BOOLEAN,
395 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING,
396 G_TYPE_STRING, G_TYPE_POINTER);
398 if (type == Ypp::Selectable::LANGUAGE) {
401 list.sort (Ypp::List::NAME_SORT,
true);
402 for (
int i = 0; i < list.size(); i++)
403 insert_language (store, list.get(i));
407 #if 1 // zypp::PoolQuery is crashing on me when using Patterns
409 while (query.hasNext()) {
411 ZyppPattern pattern = castZyppPattern (sel.zyppSel()->theObj());
412 if (pattern->userVisible())
413 insert_category (store, sel, pattern);
427 for (zypp::ResPoolProxy::const_iterator it =
428 zypp::getZYpp()->poolProxy().byKindBegin <zypp::Pattern>();
429 it != zypp::getZYpp()->poolProxy().byKindEnd <zypp::Pattern>();
432 ZyppPattern pattern = castZyppPattern (sel.zyppSel()->theObj());
433 if (pattern->userVisible())
434 insert_category (store, sel, pattern);
437 g_object_set_data (G_OBJECT (store),
"patterns", GINT_TO_POINTER (1));
440 impl->view = ygtk_tree_view_new (NULL);
441 GtkTreeView *view = GTK_TREE_VIEW (impl->view);
442 gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
443 g_object_unref (G_OBJECT (store));
444 gtk_tree_view_set_headers_visible (view, FALSE);
445 gtk_tree_view_set_search_column (view, TEXT_COLUMN);
446 gtk_tree_view_expand_all (view);
447 gtk_tree_view_set_show_expanders (view, FALSE);
448 gtk_widget_set_has_tooltip (impl->view, TRUE);
449 g_signal_connect (G_OBJECT (view),
"query-tooltip",
450 G_CALLBACK (query_tooltip_cb),
this);
451 g_signal_connect (G_OBJECT (view),
"right-click",
452 G_CALLBACK (right_click_cb),
this);
453 g_signal_connect (G_OBJECT (view),
"row-activated",
454 G_CALLBACK (row_activated_cb),
this);
456 GtkCellRenderer *renderer;
457 GtkTreeViewColumn *column;
458 renderer = gtk_cell_renderer_toggle_new();
459 column = gtk_tree_view_column_new_with_attributes (
460 NULL, renderer,
"active", CHECK_COLUMN,
"visible", HAS_CHECK_COLUMN, NULL);
461 g_signal_connect (G_OBJECT (renderer),
"toggled",
462 G_CALLBACK (toggled_cb),
this);
463 ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
465 bool reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
467 column = gtk_tree_view_column_new();
468 gtk_tree_view_column_set_title (column, NULL);
469 gtk_tree_view_column_set_spacing (column, 4);
471 GtkCellRenderer *pix_renderer = gtk_cell_renderer_pixbuf_new();
473 gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
475 renderer = ygtk_cell_renderer_text_new();
476 gtk_tree_view_column_pack_start (column, renderer, TRUE);
477 gtk_tree_view_column_set_attributes (column, renderer,
478 "markup", TEXT_COLUMN, NULL);
479 g_object_set (G_OBJECT (renderer),
"ellipsize", PANGO_ELLIPSIZE_END, NULL);
482 gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
483 gtk_tree_view_column_set_attributes (column, pix_renderer,
484 "pixbuf", ICON_COLUMN,
"visible", HAS_ICON_COLUMN, NULL);
486 gtk_tree_view_column_set_resizable (column, TRUE);
487 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
488 gtk_tree_view_column_set_expand (column, TRUE);
489 ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
491 GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
492 gtk_tree_selection_set_select_function (selection, can_tree_select_cb, NULL, NULL);
493 g_signal_connect (G_OBJECT (selection),
"changed",
494 G_CALLBACK (selection_changed_cb),
this);
497 impl->scroll = gtk_scrolled_window_new (NULL, NULL);
498 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (impl->scroll),
499 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
500 gtk_scrolled_window_set_shadow_type (
501 GTK_SCROLLED_WINDOW (impl->scroll), GTK_SHADOW_IN);
502 gtk_container_add (GTK_CONTAINER (impl->scroll), impl->view);
503 gtk_widget_show_all (impl->scroll);
505 g_idle_add_full (G_PRIORITY_LOW, set_rows_idle, store, NULL);
508 YGtkPkgPatternView::~YGtkPkgPatternView()
511 GtkWidget *YGtkPkgPatternView::getWidget()
512 {
return impl->scroll; }
514 void YGtkPkgPatternView::clearSelection()
516 GtkTreeView *view = GTK_TREE_VIEW (impl->view);
517 GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
518 g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb,
this);
519 gtk_tree_selection_unselect_all (selection);
520 g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb,
this);
525 GtkTreeView *view = GTK_TREE_VIEW (impl->view);
526 GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
529 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
538 bool isPatternsPoolEmpty()
539 {
return zyppPool().empty <zypp::Pattern>(); }