libyui-gtk  2.44.7
YGProgressBar.cc
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 
5 /*
6  Textdomain "gtk"
7  */
8 
9 #define YUILogComponent "gtk"
10 #include <yui/Libyui_config.h>
11 #include "YGUI.h"
12 #include "YGWidget.h"
13 #include "YGi18n.h"
14 
15 std::string size_stdform (YFileSize_t size)
16 {
17  long double mantissa = size;
18  int unit = 0;
19  for (; mantissa/1024 > 1; unit++)
20  mantissa /= 1024;
21 
22  const char *unit_str = "";
23  switch (unit) {
24  // translator: byte shorthand
25  case 0: unit_str = _("B"); break;
26  case 1: unit_str = _("KB"); break;
27  case 2: unit_str = _("MB"); break;
28  case 3: unit_str = _("GB"); break;
29  case 4: unit_str = _("TB"); break;
30  default: mantissa = 0; break;
31  }
32 
33  gchar *text = g_strdup_printf ("%.1f %s", (float) mantissa, unit_str);
34  std::string str (text);
35  g_free (text);
36  return str;
37 }
38 
39 #include "YProgressBar.h"
40 
41 class YGProgressBar : public YProgressBar, public YGLabeledWidget
42 {
43 public:
44  YGProgressBar (YWidget *parent, const std::string &label, int maxValue)
45  : YProgressBar (NULL, label, maxValue)
46  // NOTE: its label widget is positionated at the vertical, because its label
47  // may change often and so will its size, which will look odd (we may want
48  // to make the label widget to only grow).
49  , YGLabeledWidget (this, parent, label, YD_VERT, GTK_TYPE_PROGRESS_BAR, NULL)
50  {}
51 
52  // YProgressBar
53  virtual void setValue (int value)
54  {
55  YProgressBar::setValue (value);
56  GtkProgressBar *bar = GTK_PROGRESS_BAR (getWidget());
57  float fraction = CLAMP ((float) value / maxValue(), 0, 1);
58  gtk_progress_bar_set_fraction (bar, fraction);
59 
60  char *text = g_strdup_printf ("%d %%", (int) (fraction*100));
61  gtk_progress_bar_set_text (bar, text);
62  g_free (text);
63  gtk_progress_bar_set_show_text(bar, true);
64 
65  gtk_main_iteration_do(false);
66  }
67 
68  virtual unsigned int getMinSize (YUIDimension dim)
69  { return dim == YD_HORIZ ? 200 : 0; }
70 
71  YGLABEL_WIDGET_IMPL (YProgressBar)
72 };
73 
74 YProgressBar *YGWidgetFactory::createProgressBar (YWidget *parent, const std::string &label,
75  int maxValue)
76 {
77  return new YGProgressBar (parent, label, maxValue);
78 }
79 
80 #include "YDownloadProgress.h"
81 
82 class YGDownloadProgress : public YDownloadProgress, public YGLabeledWidget
83 {
84 guint timeout_id;
85 
86 public:
87  YGDownloadProgress (YWidget *parent, const std::string &label,
88  const std::string &filename, YFileSize_t expectedFileSize)
89  : YDownloadProgress (NULL, label, filename, expectedFileSize)
90  , YGLabeledWidget (this, parent, label, YD_HORIZ, GTK_TYPE_PROGRESS_BAR, NULL)
91  {
92  timeout_id = g_timeout_add (250, timeout_cb, this);
93  }
94 
95  virtual ~YGDownloadProgress()
96  {
97  g_source_remove (timeout_id);
98  }
99 
100  virtual void setExpectedSize (YFileSize_t size)
101  {
102  YDownloadProgress::setExpectedSize (size);
103  timeout_cb (this); // force an update
104  }
105 
106  static gboolean timeout_cb (void *pData)
107  {
108  YGDownloadProgress *pThis = (YGDownloadProgress*) pData;
109  GtkProgressBar *bar = GTK_PROGRESS_BAR (pThis->getWidget());
110 
111  gtk_progress_bar_set_fraction (bar, pThis->currentPercent() / 100.0);
112  if (pThis->expectedSize() > 0) {
113  std::string current (size_stdform (pThis->currentFileSize()));
114  std::string total (size_stdform (pThis->expectedSize()));
115  std::string text = current + " " + _("of") + " " + total;
116  gtk_progress_bar_set_text (GTK_PROGRESS_BAR (bar), text.c_str());
117  }
118  return TRUE;
119  }
120 
121  YGLABEL_WIDGET_IMPL (YDownloadProgress)
122 };
123 
124 YDownloadProgress *YGOptionalWidgetFactory::createDownloadProgress (YWidget *parent,
125  const std::string &label, const std::string &filename, YFileSize_t expectedFileSize)
126 { return new YGDownloadProgress (parent, label, filename, expectedFileSize); }
127 
128 #include "ygtkratiobox.h"
129 #include "YMultiProgressMeter.h"
130 
131 class YGMultiProgressMeter : public YMultiProgressMeter, public YGWidget
132 {
133 public:
134  YGMultiProgressMeter (YWidget *parent, YUIDimension dim, const std::vector <float> &maxValues)
135  : YMultiProgressMeter (NULL, dim, maxValues)
136  , YGWidget (this, parent,
137  horizontal() ? YGTK_TYPE_RATIO_HBOX : YGTK_TYPE_RATIO_VBOX, NULL)
138  {
139  ygtk_ratio_box_set_spacing (YGTK_RATIO_BOX (getWidget()), 2);
140  for (int s = 0; s < segments(); s++) {
141  GtkWidget *bar = gtk_progress_bar_new();
142  gtk_orientable_set_orientation(GTK_ORIENTABLE(bar), horizontal() ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
143  gtk_progress_bar_set_inverted(GTK_PROGRESS_BAR (bar), horizontal() ? FALSE : TRUE);
144  // Progress bars would ask for too much size with weight...
145  const int min_size = 5;
146  if (horizontal())
147  gtk_widget_set_size_request (bar, min_size, -1);
148  else
149  gtk_widget_set_size_request (bar, -1, min_size);
150  ygtk_ratio_box_pack (YGTK_RATIO_BOX (getWidget()), bar, getSegmentWeight (s));
151  }
152 
153  ygtk_adj_size_set_max (YGTK_ADJ_SIZE (m_adj_size), horizontal() ? 200 : 0,
154  horizontal() ? 0 : 200);
155  gtk_widget_show_all (getWidget());
156  }
157 
158  virtual void doUpdate()
159  {
160  GList* children = gtk_container_get_children (GTK_CONTAINER (getWidget()));
161  int s = 0;
162  for (GList *i = children; i && s < segments(); i = i->next, s++) {
163  GtkProgressBar *bar = GTK_PROGRESS_BAR (i->data);
164  gtk_progress_bar_set_fraction (bar, getSegmentValue (s));
165  }
166  g_list_free (children);
167  }
168 
169  int getSegmentWeight (int n)
170  {
171  if (vertical())
172  n = (segments() - n) - 1;
173  return maxValue (n);
174  }
175  float getSegmentValue (int n)
176  {
177  if (vertical())
178  n = (segments() - n) - 1;
179  if (currentValue (n) < 0)
180  return 0;
181  return 1.0 - (((float) currentValue (n)) / maxValue (n));
182  }
183 
184  YGWIDGET_IMPL_COMMON (YMultiProgressMeter)
185 };
186 
187 YMultiProgressMeter *YGOptionalWidgetFactory::createMultiProgressMeter (YWidget *parent,
188  YUIDimension dim, const std::vector <float> &maxValues)
189 { return new YGMultiProgressMeter (parent, dim, maxValues); }
190 
191 #include "YBusyIndicator.h"
192 
193 /* YBusyIndicator semantics are pretty contrived. It seems we should animate the widget
194  until timeout is reached. The application will ping setAlive(true) calls -- and we
195  reset the timeout -- as an indication that the program hasn't hang in some operation. */
196 
197 #define PULSE_INTERVAL 100
198 #define PULSE_STEP 0.050
199 
200 class YGBusyIndicator : public YBusyIndicator, public YGLabeledWidget
201 {
202 guint pulse_timeout_id;
203 int alive_timeout;
204 
205 public:
206  YGBusyIndicator (YWidget *parent, const std::string &label, int timeout)
207  : YBusyIndicator (NULL, label, timeout)
208  , YGLabeledWidget (this, parent, label, YD_VERT,
209  GTK_TYPE_PROGRESS_BAR, "pulse-step", PULSE_STEP, NULL)
210  {
211  pulse_timeout_id = 0;
212  pulse();
213  }
214 
215  virtual ~YGBusyIndicator()
216  { stop(); }
217 
218  void pulse()
219  {
220  alive_timeout = timeout();
221  if (!pulse_timeout_id)
222  pulse_timeout_id = g_timeout_add (PULSE_INTERVAL, pulse_timeout_cb, this);
223  }
224 
225  void stop()
226  {
227  alive_timeout = 0;
228  if (pulse_timeout_id) {
229  g_source_remove (pulse_timeout_id);
230  pulse_timeout_id = 0;
231  }
232  }
233 
234  // YBusyIndicator
235  virtual void setAlive (bool alive)
236  {
237  YBusyIndicator::setAlive (alive);
238  alive ? pulse() : stop();
239  }
240 
241  // callbacks
242  static gboolean pulse_timeout_cb (void *pData)
243  {
244  YGBusyIndicator *pThis = (YGBusyIndicator*) pData;
245  gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pThis->getWidget()));
246  pThis->alive_timeout -= PULSE_INTERVAL;
247  if (pThis->alive_timeout <= 0) {
248  pThis->pulse_timeout_id = 0;
249  return FALSE;
250  }
251  return TRUE;
252  }
253 
254  YGLABEL_WIDGET_IMPL (YBusyIndicator)
255 };
256 
257 YBusyIndicator *YGWidgetFactory::createBusyIndicator (YWidget *parent, const std::string &label, int timeout)
258 { return new YGBusyIndicator (parent, label, timeout); }
259