libyui-qt-pkg  2.45.15.2
YQPkgDiskUsageList.cc
1 /**************************************************************************
2 Copyright (C) 2000 - 2010 Novell, Inc.
3 All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 
19 **************************************************************************/
20 
21 
22 /*---------------------------------------------------------------------\
23 | |
24 | __ __ ____ _____ ____ |
25 | \ \ / /_ _/ ___|_ _|___ \ |
26 | \ V / _` \___ \ | | __) | |
27 | | | (_| |___) || | / __/ |
28 | |_|\__,_|____/ |_| |_____| |
29 | |
30 | core system |
31 | (C) SuSE GmbH |
32 \----------------------------------------------------------------------/
33 
34  File: YQPkgDiskUsageList.cc
35 
36  Author: Stefan Hundhammer <sh@suse.de>
37 
38  Textdomain "qt-pkg"
39 
40 /-*/
41 
42 #define YUILogComponent "qt-pkg"
43 #include "YUILog.h"
44 
45 #include <QStyle>
46 #include <QHeaderView>
47 #include <QEvent>
48 
49 #include <zypp/ZYppFactory.h>
50 
51 #include "utf8.h"
52 #include "YQPkgDiskUsageList.h"
53 #include "YQPkgDiskUsageWarningDialog.h"
54 #include "YQi18n.h"
55 
56 
57 using std::set;
58 using std::endl;
59 
60 
61 // Warning ranges for "disk space is running out" or "disk space overflow".
62 // The WARN value triggers a warning popup once ( ! ). The warning will not be
63 // displayed again until the value sinks below the PROXIMITY value and then
64 // increases again to the WARN value.
65 //
66 // See class YQPkgWarningRangeNotifier in file YQPkgDiskUsageList.h for details.
67 
68 #define MIN_FREE_MB_WARN 400
69 #define MIN_FREE_MB_PROXIMITY 700
70 
71 #define MIN_PERCENT_WARN 90
72 #define MIN_PERCENT_PROXIMITY 80
73 
74 #define OVERFLOW_MB_WARN 0
75 #define OVERFLOW_MB_PROXIMITY 300
76 
77 
78 typedef zypp::DiskUsageCounter::MountPointSet ZyppDuSet;
79 typedef zypp::DiskUsageCounter::MountPointSet::iterator ZyppDuSetIterator;
80 
81 
82 
83 YQPkgDiskUsageList::YQPkgDiskUsageList( QWidget * parent, int thresholdPercent )
84  : QY2DiskUsageList( parent, true )
85 {
86  _debug = false;
87 
88  ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
89 
90  if ( diskUsage.empty() )
91  {
92  zypp::getZYpp()->setPartitions( zypp::DiskUsageCounter::detectMountPoints() );
93  diskUsage = zypp::getZYpp()->diskUsage();
94  }
95 
96 
97  for ( ZyppDuSetIterator it = diskUsage.begin();
98  it != diskUsage.end();
99  ++it )
100  {
101  const ZyppPartitionDu & partitionDu = *it;
102 
103  if ( ! partitionDu.readonly )
104  {
105  YQPkgDiskUsageListItem * item = new YQPkgDiskUsageListItem( this, partitionDu );
106  Q_CHECK_PTR( item );
107  item->updateData();
108  _items.insert( QString::fromUtf8(partitionDu.dir.c_str()), item );
109  }
110  }
111 
112  resizeColumnToContents( nameCol() );
113  resizeColumnToContents( totalSizeCol() );
114  //resizeColumnToContents( usedSizeCol() );
115  resizeColumnToContents( freeSizeCol() );
116 
117  sortByColumn( percentageBarCol(), Qt::DescendingOrder );
118 
119  header()->setSectionResizeMode( nameCol(), QHeaderView::Stretch );
120  header()->setSectionResizeMode( QHeaderView::Interactive );
121 }
122 
123 
124 void
126 {
129 
130  ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
131 
132  for ( ZyppDuSetIterator it = diskUsage.begin();
133  it != diskUsage.end();
134  ++it )
135  {
136  const ZyppPartitionDu & partitionDu = *it;
137  YQPkgDiskUsageListItem * item = _items[ QString::fromUtf8(partitionDu.dir.c_str()) ];
138 
139  if ( item )
140  item->updateDuData( partitionDu );
141  else
142  yuiError() << "No entry for mount point " << partitionDu.dir << endl;
143  }
144 
145  resizeColumnToContents( totalSizeCol() );
147 }
148 
149 
150 void
152 {
154  {
155  YQPkgDiskUsageWarningDialog::diskUsageWarning( _( "<b>Error:</b> Out of disk space!" ),
156  100, _( "&OK" ) );
157 
159  runningOutWarning.warningPostedNotify(); // Suppress this ( now redundant ) other warning
160  }
161 
163  {
164  YQPkgDiskUsageWarningDialog::diskUsageWarning( _( "<b>Warning:</b> Disk space is running out!" ) ,
165  MIN_PERCENT_WARN, _( "&OK" ) );
167  }
168 
171 
174 }
175 
176 
177 QSize
179 {
180  QFontMetrics fms( font() );
181  return QSize( fms.width( "/var/usr/home 100% 100.32GB 100.3GB" ) + 50, 100 );
182 
183 #ifdef FIXME
184  int width = header()->headerWidth()
185  + style().pixelMetric( QStyle::PM_ScrollBarExtent, verticalScrollBar() );
186 #else
187  int width = header()->sizeHint().width()
188  + 30;
189 #endif
190 
191  return QSize( width, 100 );
192 }
193 
194 
195 void
197 {
198 
199  if ( event )
200  {
201  Qt::KeyboardModifiers special_combo = ( Qt::ControlModifier| Qt::ShiftModifier | Qt::AltModifier );
202 
203  if ( ( event->modifiers() & special_combo ) == special_combo )
204  {
205  if ( event->key() == Qt::Key_Q )
206  {
207  _debug = ! _debug;
208  yuiMilestone() << "Debug mode: " << _debug << endl;
209  }
210 
211  }
212 
213  if ( _debug && currentItem() )
214  {
215  YQPkgDiskUsageListItem * item = dynamic_cast<YQPkgDiskUsageListItem *> ( currentItem() );
216 
217  if ( item )
218  {
219  {
220  int percent = item->usedPercent();
221 
222  switch ( event->key() )
223  {
224  case Qt::Key_1: percent = 10; break;
225  case Qt::Key_2: percent = 20; break;
226  case Qt::Key_3: percent = 30; break;
227  case Qt::Key_4: percent = 40; break;
228  case Qt::Key_5: percent = 50; break;
229  case Qt::Key_6: percent = 60; break;
230  case Qt::Key_7: percent = 70; break;
231  case Qt::Key_8: percent = 80; break;
232  case Qt::Key_9: percent = 90; break;
233  case Qt::Key_0: percent = 100; break;
234  case Qt::Key_Plus: percent += 3; break;
235  case Qt::Key_Minus: percent -= 3; break;
236 
237  case 'w':
238  // Only for testing, thus intentionally using no translations
239  YQPkgDiskUsageWarningDialog::diskUsageWarning( "<b>Warning:</b> Disk space is running out!",
240  90, "&OK" );
241  break;
242 
243  case 'f':
244  YQPkgDiskUsageWarningDialog::diskUsageWarning( "<b>Error:</b> Out of disk space!",
245  100, "&Continue anyway", "&Cancel" );
246  break;
247  }
248 
249  if ( percent < 0 )
250  percent = 0;
251 
252  ZyppPartitionDu partitionDu( item->partitionDu() );
253 
254  if ( percent != item->usedPercent() )
255  {
256  partitionDu.pkg_size = double(partitionDu.total_size) * percent / 100;
257 
260 
261  item->updateDuData( partitionDu );
263  }
264  }
265  }
266  }
267  }
268 
269  QY2DiskUsageList::keyPressEvent( event );
270 }
271 
272 
273 
274 
275 
276 
278  const ZyppPartitionDu & partitionDu )
279  : QY2DiskUsageListItem( parent )
280  , _partitionDu( partitionDu )
281  , _pkgDiskUsageList( parent )
282 {
283  yuiDebug() << "disk usage list entry for " << partitionDu.dir << endl;
284 }
285 
286 // FIXME: workaround to override the QY2DiskUsageListItem issue with large disks
287 void
289 {
290  init( false );
291 }
292 
293 // FIXME: workaround to override the QY2DiskUsageListItem issue with large disks
294 void
296 {
297  init( true );
298 }
299 
300 namespace {
301  // FIXME: workaround for a broken formatting in the FSize class for sizes >8EiB
302  QString formatSize(double size, int width = 0)
303  {
304  // FSize::bestUnit does not work for huge numbers so only use it for small ones
305  FSize::Unit unit = (size >= FSize::TB) ? FSize::T : FSize(size).bestUnit();
306  // FIXME: the precision is different than in the ncurses UI (it uses 1), unify it!
307  int prec = unit == FSize::B ? 0 : 2;
308 
309  return QString("%1 %2").arg(size / FSize::factor(unit), 0, 'f', prec).arg(FSize::unit(unit));
310  }
311 }
312 
313 // FIXME: workaround to override the QY2DiskUsageListItem issue with large disks,
314 // copied from QY2DiskUsageList.cc from libyui-qt to have minimal changes,
315 // modified to use "double" data type to avoid overflow
316 void
317 YQPkgDiskUsageListItem::init( bool allFields )
318 {
319  setSizeHint( percentageBarCol(), QSize( 20, 10 ) );
320 
321  setTextAlignment( usedSizeCol(), Qt::AlignRight );
322  setTextAlignment( freeSizeCol(), Qt::AlignRight );
323  setTextAlignment( totalSizeCol(), Qt::AlignRight );
324 
325  if ( usedSizeCol() >= 0 ) setText( usedSizeCol(), double(_partitionDu.pkg_size) * FSize::KB );
326  if ( freeSizeCol() >= 0 ) setText( freeSizeCol(), double(_partitionDu.total_size - _partitionDu.pkg_size) * FSize::KB );
327 
328  if ( allFields )
329  {
330  if ( totalSizeCol() >= 0 ) setText( totalSizeCol(), double(_partitionDu.total_size) * FSize::KB );
331  if ( nameCol() >= 0 ) setText( nameCol(), name() );
332  if ( deviceNameCol() >= 0 ) setText( deviceNameCol(), deviceName() );
333  }
334 
335  if ( usedSizeCol() < 0 )
336  setToolTip( freeSizeCol(), _( "Used %1" ).arg( formatSize(double(_partitionDu.pkg_size) * FSize::KB)));
337 }
338 
339 void
340 YQPkgDiskUsageListItem::setText( int column, double size )
341 {
342  QString sizeText = formatSize(size);
343  setText( column, sizeText );
344 }
345 
346 // FIXME: not used, does not support large disks
347 FSize
349 {
350  return FSize( _partitionDu.pkg_size, FSize::K );
351 }
352 
353 // FIXME: not used, does not support large disks
354 FSize
356 {
357  return FSize( _partitionDu.total_size, FSize::K );
358 }
359 
360 
361 QString
363 {
364  return fromUTF8( _partitionDu.dir.c_str() );
365 }
366 
367 
368 void
369 YQPkgDiskUsageListItem::updateDuData( const ZyppPartitionDu & fromData )
370 {
371  _partitionDu = fromData;
372  updateData();
374 }
375 
376 
377 void
379 {
380  int percent = usedPercent();
381 
382  // free size (MiB) - the libzypp sizes are in KiB so just divide by 1024 to get MiB
383  long long free = (_partitionDu.total_size - _partitionDu.pkg_size) / 1024;
384 
385  if ( percent > MIN_PERCENT_WARN )
386  {
387  // Modern hard disks can be huge, so a warning based on percentage only
388  // can be misleading - check the absolute value, too.
389 
390  if ( free < MIN_FREE_MB_PROXIMITY )
391  _pkgDiskUsageList->runningOutWarning.enterProximity();
392 
393  if ( free < MIN_FREE_MB_WARN )
394  _pkgDiskUsageList->runningOutWarning.enterRange();
395  }
396 
397  if ( free < MIN_FREE_MB_PROXIMITY )
398  {
399  if ( percent > MIN_PERCENT_PROXIMITY )
400  _pkgDiskUsageList->runningOutWarning.enterProximity();
401  }
402 
403  if ( free < OVERFLOW_MB_WARN )
404  _pkgDiskUsageList->overflowWarning.enterRange();
405 
406  if ( free < OVERFLOW_MB_PROXIMITY )
407  _pkgDiskUsageList->overflowWarning.enterProximity();
408 }
409 
410 
411 
412 
413 
414 
416 {
417  clearHistory();
418 }
419 
420 
421 void
423 {
424  _inRange = false;
425  _hasBeenClose = _isClose;
426  _isClose = false;
427 }
428 
429 
430 void
432 {
433  clear();
434  _hasBeenClose = false;
435  _warningPosted = false;
436 }
437 
438 
439 void
441 {
442  _inRange = true;
443  enterProximity();
444 }
445 
446 
447 void
449 {
450  _isClose = true;
451  _hasBeenClose = true;
452 }
453 
454 
455 void
457 {
458  _warningPosted = true;
459 }
460 
461 
462 bool
464 {
465  return _inRange;
466 }
467 
468 
469 bool
471 {
472  return ! _isClose && ! _hasBeenClose;
473 }
474 
475 
476 bool
478 {
479  return _inRange && ! _warningPosted;
480 }
481 
482 
483 
484 
485 #include "YQPkgDiskUsageList.moc"
YQPkgWarningRangeNotifier overflowWarning
Warning range notifier about disk space overflow warning.
YQPkgDiskUsageListItem(YQPkgDiskUsageList *parent, const ZyppPartitionDu &partitionDu)
Constructor.
YQPkgDiskUsageList(QWidget *parent, int thresholdPercent=0)
Constructor.
void postPendingWarnings()
Post all pending disk space warnings based on the warning range notifiers.
void checkRemainingDiskSpace()
Check the remaining disk space of this partition based on percentage and absolute free MB...
bool leavingProximity() const
Check if the value is leaving the proximity range.
virtual void keyPressEvent(QKeyEvent *ev)
Event handler for keyboard input - for debugging and testing.
virtual QSize sizeHint() const
Suggest reasonable default size.
void updateDiskUsage()
Update all statistical data in the list.
bool needWarning() const
Check if a warning should be posted, i.e.
virtual QString name() const
The name to display for this partition ( the mount point ).
virtual FSize totalSize() const
The total size of this partition.
bool inRange() const
Check if the value is in range, i.e.
void enterProximity()
Notification that the proximity range is entered, i.e.
YQPkgWarningRangeNotifier()
Constructor.
virtual QString deviceName() const
The device name of this partition.
void clear()
Clear the current values, i.e.
virtual void updateStatus()
Update this item&#39;s status ( here: the numeric fields ).
YQPkgWarningRangeNotifier runningOutWarning
Warning range notifier about running out of disk space warning.
static bool diskUsageWarning(const QString &message, int thresholdPercent, const QString &acceptButtonLabel, const QString &rejectButtonLabel=QString::null)
Static convenience method: Post a disk usage warning with text &#39;message&#39;, a list of partitions that a...
void enterRange()
Notification that the inner range is entered.
void clearHistory()
Clear everything, including all history values such as if a warning has been posted.
virtual void updateData()
Update this item&#39;s data completely.
virtual FSize usedSize() const
The currently used size of this partition.
ZyppPartitionDu partitionDu() const
Returns the corresponding disk usage data.
void warningPostedNotify()
Notification that a warning has been posted.
void setText(int column, const QString &text)
Re-declare ordinary setText() method so the compiler doesn&#39;t get confused which one to use...
List of disk usage of all attached partitions.
void updateDuData(const ZyppPartitionDu &fromData)
Update the disk usage data.