libyui-gtk-pkg  2.42.9
 All Classes
ygtkpkgstatusbar.cc
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 /* YGtkPkgStatusBar, a status-bar */
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 "YGUI.h"
14 #include "ygtkpkgstatusbar.h"
15 #include "YGPackageSelector.h"
16 #include "YGUtils.h"
17 #include "ygtkpkglistview.h"
18 #include "ygtkpkgundolist.h"
19 #include "yzyppwrapper.h"
20 #include <gtk/gtk.h>
21 
22 struct LastChange {
23  GtkWidget *hbox, *icon, *text, *undo_button;
24 
25  GtkWidget *getWidget() { return hbox; }
26 
27  LastChange()
28  {
29  icon = gtk_image_new();
30  gtk_widget_set_size_request (icon, 16, 16);
31 
32  text = gtk_label_new ("");
33  gtk_misc_set_alignment (GTK_MISC (text), 0, .5);
34  undo_button = gtk_button_new_from_stock (GTK_STOCK_UNDO);
35  YGUtils::shrinkWidget (undo_button);
36  g_signal_connect (G_OBJECT (undo_button), "clicked",
37  G_CALLBACK (undo_clicked_cb), this);
38  gchar *str = g_strdup_printf ("(<a href=\"more\">%s</a>)", _("view all changes"));
39  GtkWidget *more = gtk_label_new (str);
40  g_free (str);
41  gtk_label_set_use_markup (GTK_LABEL (more), TRUE);
42  gtk_label_set_track_visited_links (GTK_LABEL (more), FALSE);
43  g_signal_connect (G_OBJECT (more), "activate-link",
44  G_CALLBACK (more_link_cb), this);
45 
46  hbox = gtk_hbox_new (FALSE, 6);
47  gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
48  gtk_box_pack_start (GTK_BOX (hbox), text, FALSE, TRUE, 0);
49  gtk_box_pack_start (GTK_BOX (hbox), undo_button, FALSE, TRUE, 0);
50  gtk_box_pack_start (GTK_BOX (hbox), more, FALSE, TRUE, 0);
51  }
52 
53  void undoChanged (YGtkPkgUndoList *list)
54  {
55  int auto_count;
56  Ypp::Selectable *sel = list->front (&auto_count);
57  if (sel) {
58  const char *stock = getStatusStockIcon (*sel);
59  GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
60  stock, 16, GtkIconLookupFlags (0), NULL);
61  //GdkPixbuf *_pixbuf = YGUtils::setGray (pixbuf);
62  gtk_image_set_from_pixbuf (GTK_IMAGE (icon), pixbuf);
63  g_object_unref (G_OBJECT (pixbuf));
64 
65  const char *action = getStatusAction (sel);
66  gchar *str;
67  if (sel->toModifyAuto())
68  str = g_strdup_printf (_("<b>%s</b> %d preselected packages"), action, auto_count);
69  else {
70  if (auto_count == 0)
71  str = g_strdup_printf ("<b>%s</b> %s", action, sel->name().c_str());
72  else {
73  char *deps;
74  if (auto_count == 1)
75  deps = g_strdup (_("plus 1 dependency"));
76  else
77  deps = g_strdup_printf (_("plus %d dependencies"), auto_count);
78  str = g_strdup_printf ("<b>%s</b> %s, %s", action, sel->name().c_str(), deps);
79  g_free (deps);
80  }
81  }
82 
83  gtk_label_set_markup (GTK_LABEL (text), str);
84  gtk_label_set_attributes (GTK_LABEL (text), NULL);
85  gtk_widget_set_sensitive (undo_button, TRUE);
86  g_free (str);
87  }
88  else {
89  gtk_image_clear (GTK_IMAGE (icon));
90  gtk_label_set_text (GTK_LABEL (text), _("No changes to perform"));
91 
92  PangoAttrList *attrs = pango_attr_list_new();
93  pango_attr_list_insert (attrs, pango_attr_foreground_new (110<<8, 110<<8, 110<<8));
94  pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_ITALIC));
95  gtk_label_set_attributes (GTK_LABEL (text), attrs);
96  pango_attr_list_unref (attrs);
97 
98  gtk_widget_set_sensitive (undo_button, FALSE);
99  }
100  set_ellipsize (text);
101  }
102 
103  static gboolean more_link_cb (GtkLabel *label, gchar *uri, LastChange *pThis)
104  { YGPackageSelector::get()->popupChanges(); return TRUE; }
105 
106  static void undo_clicked_cb (GtkButton *button, LastChange *pThis)
107  {
108  Ypp::Selectable *sel = YGPackageSelector::get()->undoList()->front (NULL);
109  if (sel) sel->undo();
110  }
111 
112  void set_ellipsize (GtkWidget *label)
113  {
114  GtkWidget *hbox = gtk_widget_get_parent (this->hbox);
115  if (gtk_widget_get_realized (hbox)) {
116  gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
117 
118  GtkRequisition req;
119  gtk_widget_size_request (hbox, &req);
120  GtkWidget *window = gtk_widget_get_toplevel (hbox);
121  GtkAllocation allocation;
122  gtk_widget_get_allocation(window, &allocation);
123 
124  bool ellipsize = req.width > allocation.width - 10;
125 
126  PangoEllipsizeMode mode = ellipsize ? PANGO_ELLIPSIZE_MIDDLE : PANGO_ELLIPSIZE_NONE;
127  gtk_label_set_ellipsize (GTK_LABEL (label), mode);
128  gtk_box_set_child_packing (GTK_BOX (this->hbox), label, ellipsize, TRUE, 0, GTK_PACK_START);
129  }
130  }
131 };
132 
133 #if 0
134 struct StatChange {
135  GtkWidget *hbox, *to_install, *to_upgrade, *to_remove;
136 
137  GtkWidget *getWidget() { return hbox; }
138 
139  StatChange()
140  {
141  to_install = gtk_label_new ("");
142  gtk_label_set_selectable (GTK_LABEL (to_install), TRUE);
143  to_upgrade = gtk_label_new ("");
144  gtk_label_set_selectable (GTK_LABEL (to_upgrade), TRUE);
145  to_remove = gtk_label_new ("");
146  gtk_label_set_selectable (GTK_LABEL (to_remove), TRUE);
147 
148  hbox = gtk_hbox_new (FALSE, 6);
149  gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("To install:")), FALSE, TRUE, 0);
150  gtk_box_pack_start (GTK_BOX (hbox), to_install, FALSE, TRUE, 0);
151  gtk_box_pack_start (GTK_BOX (hbox), gtk_vseparator_new(), FALSE, TRUE, 0);
152  gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("To upgrade:")), FALSE, TRUE, 0);
153  gtk_box_pack_start (GTK_BOX (hbox), to_upgrade, FALSE, TRUE, 0);
154  gtk_box_pack_start (GTK_BOX (hbox), gtk_vseparator_new(), FALSE, TRUE, 0);
155  gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("To remove:")), FALSE, TRUE, 0);
156  gtk_box_pack_start (GTK_BOX (hbox), to_remove, FALSE, TRUE, 0);
157  }
158 
159  void undoChanged (YGtkPkgUndoList *undo)
160  {
161  int toInstall = 0, toUpgrade = 0, toRemove = 0;
162  Ypp::List list (undo->getList());
163  for (int i = 0; i < list.size(); i++) {
164  Ypp::Selectable &sel = list.get (i);
165  if (sel.toInstall()) {
166  if (sel.isInstalled())
167  toUpgrade++;
168  else
169  toInstall++;
170  }
171  else if (sel.toRemove())
172  toInstall++;
173  }
174 
175  label_set_int (to_install, toInstall);
176  label_set_int (to_upgrade, toUpgrade);
177  label_set_int (to_remove, toRemove);
178  }
179 
180  static void label_set_int (GtkWidget *label, int value)
181  {
182  gchar *str = g_strdup_printf ("%d", value);
183  gtk_label_set_text (GTK_LABEL (label), str);
184  g_free (str);
185  }
186 };
187 #endif
188 
189 #define MIN_FREE_MB_WARN 400
190 #define MIN_PERCENT_WARN 90
191 
192 struct DiskChange {
193  GtkWidget *hbox, *combo, *text;
194 
195  GtkWidget *getWidget() { return hbox; }
196 
197  DiskChange()
198  {
199  GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
200  std::vector <std::string> partitions = Ypp::getPartitionList();
201  int active = -1;
202  for (unsigned int i = 0; i < partitions.size(); i++) {
203  const std::string &part = partitions[i];
204  if (part == "/usr" || part == "/usr/")
205  active = i;
206  else if (active == -1 && part == "/")
207  active = i;
208 
209  GtkTreeIter iter;
210  gtk_list_store_append (store, &iter);
211  gtk_list_store_set (store, &iter, 0, part.c_str(), -1);
212  }
213 
214  combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
215  g_object_unref (G_OBJECT (store));
216  YGUtils::shrinkWidget (combo);
217  gtk_widget_set_name (combo, "small-widget");
218  gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (combo), FALSE);
219  GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
220  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
221  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer, "text", 0, NULL);
222  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
223  g_signal_connect (G_OBJECT (combo), "changed",
224  G_CALLBACK (combo_changed_cb), this);
225 
226  text = gtk_label_new ("");
227  YGUtils::setWidgetFont (text, PANGO_STYLE_ITALIC,
228  PANGO_WEIGHT_NORMAL, PANGO_SCALE_MEDIUM);
229  gtk_label_set_selectable (GTK_LABEL (text), TRUE);
230 
231  hbox = gtk_hbox_new (FALSE, 4);
232  gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Space available:")), FALSE, TRUE, 0);
233  gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0);
234  gtk_box_pack_start (GTK_BOX (hbox), text, FALSE, TRUE, 0);
235  }
236 
237  void undoChanged (YGtkPkgUndoList *undo)
238  {
239  GtkTreeIter iter;
240  gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
241  GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
242  gchar *mount_point;
243  gtk_tree_model_get (model, &iter, 0, &mount_point, -1);
244  const ZyppDu part = Ypp::getPartition (mount_point);
245  g_free (mount_point);
246 
247  int percent = part.total_size ? ((100 * part.pkg_size) / part.total_size) : 0;
248  long long free = (part.total_size - part.pkg_size) * 1024 * 1024;
249 
250  const char *format = "%s";
251  if (percent > MIN_PERCENT_WARN && free < MIN_FREE_MB_WARN)
252  format = "<b><span foreground=\"red\"><b>%s<b></span></b>";
253  char *str = g_strdup_printf (format, part.freeAfterCommit().asString().c_str());
254  gtk_label_set_markup (GTK_LABEL (text), str);
255  g_free (str);
256  }
257 
258  static void combo_changed_cb (GtkComboBox *combo, DiskChange *pThis)
259  { pThis->undoChanged (YGPackageSelector::get()->undoList()); }
260 };
261 
263  GtkWidget *box;
264  LastChange *last;
265  DiskChange *disk;
266 
267  GtkWidget *getWidget() { return box; }
268 
269  Impl (YGtkPkgUndoList *undo)
270  {
271  last = new LastChange();
272  disk = new DiskChange();
273 
274  GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
275  gtk_box_pack_start (GTK_BOX (hbox), last->getWidget(), TRUE, TRUE, 0);
276  gtk_box_pack_start (GTK_BOX (hbox), disk->getWidget(), FALSE, TRUE, 0);
277  box = hbox;
278  gtk_widget_show_all (box);
279 
280  undoChanged (undo);
281  undo->addListener (this);
282  }
283 
284  ~Impl()
285  {
286  delete last;
287  delete disk;
288  YGPackageSelector::get()->undoList()->removeListener (this);
289  }
290 
291  virtual void undoChanged (YGtkPkgUndoList *list)
292  {
293  last->undoChanged (list);
294  disk->undoChanged (list);
295  }
296 };
297 
298 YGtkPkgStatusBar::YGtkPkgStatusBar (YGtkPkgUndoList *undo)
299 : impl (new Impl (undo))
300 {}
301 
302 YGtkPkgStatusBar::~YGtkPkgStatusBar()
303 { delete impl; }
304 
305 GtkWidget *YGtkPkgStatusBar::getWidget()
306 { return impl->getWidget(); }
307