libyui-gtk-pkg  2.43.2
 All Classes
ygtkpkgvestigialdialog.cc
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 /* YGtkPkgVestigialDialog, dialog */
5 // check the header file for information about this widget
6 
7 /*
8  Textdomain "gtk"
9  */
10 
11 #include "YGi18n.h"
12 #include "config.h"
13 #include "YGDialog.h"
14 #include "ygtkpkgvestigialdialog.h"
15 #include "ygtkpkglistview.h"
16 #include "YGPackageSelector.h"
17 #include "yzyppwrapper.h"
18 #include <gtk/gtk.h>
19 
20 #include <zypp/parser/HistoryLogReader.h>
21 #define FILENAME "/var/log/zypp/history"
22 
24 {
25  std::set <std::string> m_dependencies;
26 
28  {
29  zypp::parser::HistoryLogReader parser (FILENAME, zypp::parser::HistoryLogReader::Options(), boost::ref (*this));
30  try {
31  parser.readAll();
32  }
33  catch (const zypp::Exception &ex) {
34  yuiWarning () << "Error: Could not load log file" << FILENAME << ": "
35  << ex.asUserHistory() << std::endl;
36  }
37  }
38 
39  bool operator() (const zypp::HistoryLogData::Ptr &item)
40  {
41  if (item->action().toEnum() == zypp::HistoryActionID::INSTALL_e) {
42  zypp::HistoryLogDataInstall *_item =
43  static_cast <zypp::HistoryLogDataInstall *> (item.get());
44 
45  const std::string &name (_item->name());
46  bool autoreq = _item->reqby().empty();
47  std::string repoName, repoUrl;
48  Ypp::getRepositoryFromAlias (_item->repoAlias(), repoName, repoUrl);
49  bool update = repoUrl.find ("update") != std::string::npos;
50 
51  if (!update) { // updates are ambiguous
52  if (autoreq)
53  m_dependencies.insert (name);
54  else
55  m_dependencies.erase (name);
56  }
57  }
58 
59  return true;
60  }
61 };
62 
64 {
65  GtkWidget *dialog;
66  YGtkPkgListView *view;
67  GtkWidget *progressbar;
68 
69  virtual void selectionChanged()
70  {
71  Ypp::List selected (view->getSelected());
72  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 1, selected.size());
73  }
74 
75  void goto_clicked()
76  {
77  Ypp::List selected (view->getSelected());
78  if (selected.size()) {
79  std::string name (selected.get(0).name());
80  YGPackageSelector::get()->searchFor (Ypp::PoolQuery::NAME, name);
81  }
82  gtk_widget_hide (dialog);
83  }
84 
85  void remove_all()
86  {
87  view->getList().remove();
88  }
89 
90  static void response_cb (GtkDialog *dialog, gint response, Impl *pThis)
91  {
92  switch (response) {
93  case 1: pThis->goto_clicked(); break;
94  case 2: pThis->remove_all(); break;
95  default: gtk_widget_hide (GTK_WIDGET (pThis->dialog)); break;
96  }
97  }
98 
99  void set_progress (gdouble fraction)
100  {
101  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progressbar), fraction);
102  while (g_main_context_iteration (NULL, FALSE)) ;
103  }
104 };
105 
106 static bool testIsNeededDependency (ZyppSelectable zsel)
107 { // pass only installed packages: zsel->status() == S_KeepInstalled
108  zsel->setStatus (zypp::ui::S_Del);
109  zypp::Resolver_Ptr zResolver = zypp::getZYpp()->resolver();
110  bool noProbs = zResolver->resolvePool();
111  zResolver->undo();
112  zsel->setStatus (zypp::ui::S_KeepInstalled);
113  return !noProbs;
114 }
115 
116 static void filterWhenContains (Ypp::Collection &col, std::list <ZyppSelectable> &pkgs)
117 {
118  std::list <ZyppSelectable>::iterator it = pkgs.begin();
119  while (it != pkgs.end()) {
120  Ypp::Selectable p (*it);
121  if (col.contains (p))
122  it = pkgs.erase (it);
123  else it++;
124  }
125 }
126 
127 static gboolean fill_list_idle_cb (void *data)
128 {
130 
131  // 1. get list of packages installed as dependencies
132  ZyppVestigialParser parser;
133  const std::set <std::string> &deps = parser.m_dependencies;
134  impl->set_progress (.1);
135  // 2. map string names to zypp objects and check whether they are still necessary
136  int size = deps.size(), i = 0;
137  std::list <ZyppSelectable> unneeded;
138  for (std::set <std::string>::const_iterator it = deps.begin();
139  it != deps.end(); it++) {
140  Ypp::PoolQuery query (Ypp::Selectable::PACKAGE);
141  query.addStringOr (*it);
142  query.addStringAttribute (Ypp::PoolQuery::NAME);
143  query.setStringMode (true, Ypp::PoolQuery::EXACT);
144  if (query.hasNext()) {
145  Ypp::Selectable sel (query.next());
146  ZyppSelectable zsel = sel.zyppSel();
147  if (zsel->status() == zypp::ui::S_KeepInstalled)
148  if (!testIsNeededDependency (zsel))
149  unneeded.push_back (zsel);
150  }
151 
152  if ((i % 2) == 0)
153  impl->set_progress (.1 + ((i / (gdouble) size) * .80));
154  i++;
155  }
156  // 3. filter those installed by a container
157  impl->set_progress (.90);
158  Ypp::LangQuery langQuery;
159  size = langQuery.guessSize(); i = 0;
160  while (langQuery.hasNext()) {
161  Ypp::Selectable sel (langQuery.next());
162  if (!sel.isInstalled()) continue;
163  Ypp::Collection col (sel);
164  filterWhenContains (col, unneeded);
165  }
166  impl->set_progress (.95);
167  Ypp::PoolQuery patternQuery (Ypp::Selectable::PATTERN);
168  patternQuery.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::IS_INSTALLED));
169  size = patternQuery.guessSize(); i = 0;
170  while (patternQuery.hasNext()) {
171  Ypp::Selectable sel (patternQuery.next());
172  Ypp::Collection col (sel);
173  filterWhenContains (col, unneeded);
174  }
175 
176  Ypp::List list (unneeded.size());
177  for (std::list <ZyppSelectable>::const_iterator it = unneeded.begin();
178  it != unneeded.end(); it++)
179  list.append (*it);
180  impl->view->setList (list);
181 
182  gtk_widget_hide (impl->progressbar);
183 // FIXME gdk_window_set_cursor (impl->dialog->window, NULL);
184  gtk_dialog_set_response_sensitive (GTK_DIALOG (impl->dialog), 2, unneeded.size());
185  gtk_window_present (GTK_WINDOW (impl->dialog));
186  return FALSE;
187 }
188 
189 YGtkPkgVestigialDialog::YGtkPkgVestigialDialog()
190 {
191  GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
192  GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_OTHER, GTK_BUTTONS_NONE,
193  _("Show Unneeded Dependencies"));
194  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
195  _("This is a listing of dependencies no longer used. It is neither "
196  "accurate, nor comprehensive. Use with care."));
197 
198  impl = new Impl();
199  GtkWidget *action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
200  impl->progressbar = gtk_progress_bar_new();
201  gtk_widget_set_size_request (impl->progressbar, 0, 0);
202  gtk_container_add (GTK_CONTAINER (action_area), impl->progressbar);
203 
204  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_JUMP_TO, 1);
205  gtk_dialog_add_button (GTK_DIALOG (dialog), _("Remove All"), 2);
206  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
207  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 1, FALSE);
208  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 2, FALSE);
209  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
210  gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
211  gtk_window_set_default_size (GTK_WINDOW (dialog), 650, 600);
212  g_signal_connect (G_OBJECT (dialog), "response",
213  G_CALLBACK (Impl::response_cb), impl);
214  g_signal_connect (G_OBJECT (dialog), "delete-event",
215  G_CALLBACK (gtk_true), NULL);
216 
217  impl->view = new YGtkPkgListView (true, Ypp::List::NAME_SORT, false, true);
218  impl->view->addCheckColumn (INSTALLED_CHECK_PROP);
219  impl->view->addTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1);
220  impl->view->addTextColumn (_("Version"), VERSION_PROP, true, 125);
221  impl->view->addTextColumn (_("Size"), SIZE_PROP, false, 85);
222  impl->view->addTextColumn (_("Repository"), REPOSITORY_PROP, false, 180);
223  impl->view->addTextColumn (_("Supportability"), SUPPORT_PROP, false, 120);
224  impl->view->setListener (impl);
225 
226  GtkBox *content = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG(dialog)));
227  gtk_box_pack_start (content, impl->view->getWidget(), TRUE, TRUE, 6);
228  gtk_widget_show_all (dialog);
229  impl->dialog = dialog;
230 
231  GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
232 // FIXME gdk_window_set_cursor (dialog->window, cursor);
233  gdk_cursor_unref (cursor);
234 
235  g_idle_add_full (G_PRIORITY_LOW, fill_list_idle_cb, impl, NULL);
236 }
237 
238 YGtkPkgVestigialDialog::~YGtkPkgVestigialDialog()
239 {
240  delete impl->view;
241  gtk_widget_destroy (impl->dialog);
242  delete impl;
243 }
244 
245 void YGtkPkgVestigialDialog::popup()
246 { gtk_window_present (GTK_WINDOW (impl->dialog)); }
247