libyui-ncurses-pkg  2.48.5
NCPkgPopupDiskspace.cc
1 /****************************************************************************
2 |
3 | Copyright (c) [2002-2011] Novell, Inc.
4 | All Rights Reserved.
5 |
6 | This program is free software; you can redistribute it and/or
7 | modify it under the terms of version 2 of the GNU General Public License as
8 | published by the Free Software Foundation.
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
16 | along with this program; if not, contact Novell, Inc.
17 |
18 | To contact Novell about this file by physical or electronic mail,
19 | you may find current contact information at www.novell.com
20 |
21 |***************************************************************************/
22 
23 
24 /*---------------------------------------------------------------------\
25 | |
26 | __ __ ____ _____ ____ |
27 | \ \ / /_ _/ ___|_ _|___ \ |
28 | \ V / _` \___ \ | | __) | |
29 | | | (_| |___) || | / __/ |
30 | |_|\__,_|____/ |_| |_____| |
31 | |
32 | core system |
33 | (C) SuSE GmbH |
34 \----------------------------------------------------------------------/
35 
36  File: NCPkgPopupDiskspace.cc
37 
38  Author: Gabriele Strattner <gs@suse.de>
39 
40 /-*/
41 #define YUILogComponent "ncurses-pkg"
42 #include <YUILog.h>
43 
44 #include "YMenuButton.h"
45 #include "YDialog.h"
46 #include "YTypes.h"
47 
48 #include "NCLayoutBox.h"
49 #include "NCSpacing.h"
50 #include "NCPkgStrings.h"
51 #include "NCLabel.h"
52 #include "NCPushButton.h"
53 #include "NCTable.h"
54 
55 #include "NCZypp.h"
56 
57 #include "NCPkgPopupDiskspace.h"
58 
59 #include "NCi18n.h"
60 
61 // set values as set in YQPkgDiskUsageList.cc
62 #define MIN_FREE_MB_WARN 400
63 #define MIN_FREE_MB_PROXIMITY 700
64 
65 #define MIN_PERCENT_WARN 90
66 #define MIN_PERCENT_PROXIMITY 80
67 
68 #define OVERFLOW_MB_WARN 0
69 #define OVERFLOW_MB_PROXIMITY 300
70 
71 using std::endl;
72 
73 /*
74  Textdomain "ncurses-pkg"
75 */
76 
77  ///////////////////////////////////////////////////////////////////
78 //
79 //
80 // METHOD NAME : NCPkgDiskspace::NCPkgDiskspace
81 // METHOD TYPE : Constructor
82 //
83 // DESCRIPTION :
84 //
85 NCPkgDiskspace::NCPkgDiskspace( bool testMode )
86  : testmode( testMode )
87  , popupWin( 0 )
88 {
89 
90  if ( testMode )
91  {
92  yuiMilestone() << "TESTMODE Diskspace" << endl;
93  zypp::getZYpp()->setPartitions(zypp::DiskUsageCounter::detectMountPoints ());
94  testDiskUsage = zypp::getZYpp()->diskUsage();
95  }
96 }
97 
98 ///////////////////////////////////////////////////////////////////
99 //
100 //
101 // METHOD NAME : NCPkgDiskspace::~NCPkgDiskspace
102 // METHOD TYPE : Destructor
103 //
104 // DESCRIPTION :
105 //
106 NCPkgDiskspace::~NCPkgDiskspace()
107 {
108 }
109 
110 ///////////////////////////////////////////////////////////////////
111 //
112 //
113 // METHOD NAME : NCPkgDiskspace::fillPartitionTable
114 // METHOD TYPE : void
115 //
116 // DESCRIPTION :
117 //
118 void NCPkgDiskspace::fillPartitionTable()
119 {
120  NCTable * partitions = popupWin->Partitions();
121  partitions->deleteAllItems(); // clear table
122 
123  YTableItem * newItem;
124  int i = 0;
125 
126  zypp::ZYpp::Ptr z = zypp::getZYpp();
127  ZyppDuSet du = z->diskUsage ();
128  ZyppDuSetIterator
129  b = du.begin (),
130  e = du.end (),
131  it;
132  if (b == e)
133  {
134  // retry after detecting from the target
135  z->setPartitions(zypp::DiskUsageCounter::detectMountPoints ());
136  du = z->diskUsage();
137  b = du.begin ();
138  e = du.end ();
139  }
140 
141  for (it = b; it != e; ++it)
142  {
143  if (it->readonly)
144  continue;
145 
146  zypp::ByteCount pkg_used (it->pkg_size * 1024);
147 
148  zypp::ByteCount pkg_available ((it->total_size - it->pkg_size) * 1024);
149 
150  zypp::ByteCount total (it->total_size * 1024);
151 
152  newItem = new YTableItem( it->dir,
153  pkg_used.asString (8),
154  pkg_available.asString (8),
155  total.asString (8),
156  usedPercent( it->pkg_size, it->total_size ) );
157 
158  partitions->addItem( newItem );
159 
160  i++;
161  }
162 }
163 
164 ///////////////////////////////////////////////////////////////////
165 //
166 //
167 // METHOD NAME : NCPkgDiskspace::checkDiskSpace
168 // METHOD TYPE : std::string
169 //
170 // DESCRIPTION : called to check disk space before installation
171 // (after OK button is pressed)
172 //
173 std::string NCPkgDiskspace::checkDiskSpace()
174 {
175  std::string text = "";
176 
177  zypp::ZYpp::Ptr z = zypp::getZYpp();
178  ZyppDuSet du = z->diskUsage ();
179  ZyppDuSetIterator
180  b = du.begin (),
181  e = du.end (),
182  it;
183  if (b == e)
184  {
185  // retry after detecting from the target
186  z->setPartitions(zypp::DiskUsageCounter::detectMountPoints ());
187  du = z->diskUsage();
188  b = du.begin ();
189  e = du.end ();
190  }
191 
192  for (it = b; it != e; ++it)
193  {
194  if (it->readonly)
195  continue;
196 
197  zypp::ByteCount pkg_available = (it->total_size - it->pkg_size) * 1024;
198  if ( pkg_available < 0 )
199  {
200  text += "\"";
201  text += it->dir;
202  text += "\"";
203  text += " ";
204  text += NCPkgStrings::MoreText();
205  text += " ";
206  std::string available = pkg_available.asString();
207  text += available.replace( 0, 1, " " ); // clear the minus sign??
208  text += " ";
209  text += NCPkgStrings::MoreSpaceText();
210  text += "<br>";
211  }
212  }
213  return text;
214 }
215 
216 ///////////////////////////////////////////////////////////////////
217 //
218 //
219 // METHOD NAME : NCPkgDiskspace::checkRemainingDiskSpace
220 // METHOD TYPE : void
221 //
222 // DESCRIPTION : check whether remaining disk space enters
223 // warning or error range
224 //
225 void NCPkgDiskspace::checkRemainingDiskSpace( const ZyppPartitionDu & partition )
226 {
227  FSize usedSize ( partition.pkg_size, FSize::K );
228  FSize totalSize ( partition.total_size, FSize::K );
229 
230  int percent = 0;
231 
232  if ( totalSize != 0 )
233  percent = ( 100 * usedSize ) / totalSize;
234 
235  int free = ( totalSize - usedSize ) / FSize::MB;
236 
237  yuiMilestone() << "Partition: " << partition.dir << " Used percent: "
238  << percent << " Free: " << free << endl;
239 
240  if ( percent > MIN_PERCENT_WARN )
241  {
242  // Modern hard disks can be huge, so a warning based on percentage only
243  // can be misleading - check the absolute value, too.
244  if ( free < MIN_FREE_MB_PROXIMITY )
245  {
246  runningOutWarning.enterProximity();
247  }
248  if ( free < MIN_FREE_MB_WARN )
249  {
250  runningOutWarning.enterRange();
251  }
252  }
253 
254  if ( free < MIN_FREE_MB_PROXIMITY )
255  {
256  if ( percent > MIN_PERCENT_PROXIMITY )
257  runningOutWarning.enterProximity();
258  }
259 
260  if ( free < OVERFLOW_MB_WARN )
261  overflowWarning.enterRange();
262 
263  if ( free < OVERFLOW_MB_PROXIMITY )
264  overflowWarning.enterProximity();
265 
266 }
267 
268 ///////////////////////////////////////////////////////////////////
269 //
270 //
271 // METHOD NAME : NCPkgDiskspace::setDiskSpace
272 // METHOD TYPE : void
273 //
274 // DESCRIPTION : For testing only; called from NCPkgTable if the PackageSelector
275 // running in testMode
276 // TESTDESCRIPTION: Call `PackageSelector with `opt(`testMode) (ycp example).
277 // With focus on the package list press '+' or '-' to
278 // increase/decrease used diskspace (see y2log).
279 // Use the 'Actions' menu to select/delete a package.
280 //
281 void NCPkgDiskspace::setDiskSpace( wint_t ch )
282 {
283  int percent = 0;
284 
285  // set diskspace values in ZyppDuSet testDiskSpace
286  for ( ZyppDuSetIterator it = testDiskUsage.begin();
287  it != testDiskUsage.end();
288  ++it )
289  {
290  const ZyppPartitionDu & partitionDu = *it;
291 
292  FSize usedSize ( partitionDu.pkg_size, FSize::K );
293  FSize totalSize ( partitionDu.total_size, FSize::K );
294 
295  if ( totalSize != 0 )
296  percent = ( 100 * usedSize ) / totalSize;
297 
298  if ( ch == '+' )
299  percent += 3;
300  else if ( ch == '-' )
301  percent -= 3;
302 
303  if ( percent < 0 )
304  percent = 0;
305 
306  partitionDu.pkg_size = partitionDu.total_size * percent / 100;
307 
308  FSize newSize ( partitionDu.pkg_size, FSize::K );
309 
310  yuiMilestone() << "Used size (MB): " << newSize / FSize::MB << endl;
311  yuiMilestone() << "Total size (MB): " << totalSize / FSize::MB << endl;
312  }
313 }
314 
315 ///////////////////////////////////////////////////////////////////
316 //
317 //
318 // METHOD NAME : NCPkgDiskspace::checkDiskSpaceRange
319 // METHOD TYPE : void
320 //
321 // DESCRIPTION : calls checkRemaingDiskspace for every partition
322 //
323 void NCPkgDiskspace::checkDiskSpaceRange( )
324 {
325  // see YQPkgDiskUsageList::updateDiskUsage()
326  runningOutWarning.clear();
327  overflowWarning.clear();
328  ZyppDuSet diskUsage;
329 
330  if ( testmode )
331  diskUsage = testDiskUsage;
332  else
333  diskUsage = zypp::getZYpp()->diskUsage();
334 
335  for ( ZyppDuSetIterator it = diskUsage.begin();
336  it != diskUsage.end();
337  ++it )
338  {
339  //Exclude readonly dirs from the check (#384368)
340  if( it->readonly )
341  continue;
342  checkRemainingDiskSpace( *it );
343  }
344 
345  // see YQPkgDiskUsageList::postPendingWarnings()
346  if ( overflowWarning.needWarning() )
347  {
348  showInfoPopup( _( "Error: Out of disk space!" ) );
349 
350  overflowWarning.warningPostedNotify();
351  runningOutWarning.warningPostedNotify(); // Suppress this ( now redundant ) other warning
352  }
353 
354  if ( runningOutWarning.needWarning() )
355  {
356  showInfoPopup( _( "Warning: Disk space is running out!" ) );
357 
358  runningOutWarning.warningPostedNotify();
359  }
360 
361  if ( overflowWarning.leavingProximity() )
362  overflowWarning.clearHistory();
363 
364  if ( runningOutWarning.leavingProximity() )
365  runningOutWarning.clearHistory();
366 
367  if ( testmode )
368  {
369  yuiMilestone() << "Running out Warning:" << endl;
370  runningOutWarning.logSettings();
371 
372  yuiMilestone() << "Overflow Warning:" << endl;
373  overflowWarning.logSettings();
374  }
375 }
376 
377 std::string NCPkgDiskspace::usedPercent( FSize used, FSize total )
378 {
379  int percent = 0;
380  char percentStr[10];
381 
382  if ( total != 0 )
383  percent = ( 100 * used ) / total;
384 
385  sprintf( percentStr, "%d%%", percent );
386 
387  return percentStr;
388 }
389 
390 ///////////////////////////////////////////////////////////////////
391 //
392 //
393 // METHOD NAME : NCPkgDiskspace::showInfoPopup
394 // METHOD TYPE : void
395 //
396 // DESCRIPTION :
397 //
398 void NCPkgDiskspace::showInfoPopup( std::string headline )
399 {
400 
401  popupWin = new NCPkgPopupDiskspace (wpos( (NCurses::lines() - 15)/2, NCurses::cols()/6 ), headline );
402  // update values in partition table
403  fillPartitionTable();
404  popupWin->doit();
405  YDialog::deleteTopmostDialog();
406 }
407 
408 zypp::ByteCount NCPkgDiskspace::calculateDiff()
409 {
410  zypp::ZYpp::Ptr z = zypp::getZYpp();
411  ZyppDuSet du = z->diskUsage ();
412  ZyppDuSetIterator
413  b = du.begin (),
414  e = du.end (),
415  it;
416  if (b == e)
417  {
418  // retry after detecting from the target
419  z->setPartitions(zypp::DiskUsageCounter::detectMountPoints ());
420  du = z->diskUsage();
421  b = du.begin ();
422  e = du.end ();
423  }
424 
425  zypp::ByteCount diff = 0;
426  for (it = b; it != e; ++it)
427  {
428  diff += (it->pkg_size - it->used_size) * 1024;
429  }
430 
431  return diff;
432 }
433 
434 //////////////////////////////////////////////////////////////////
435 //
436 //
437 // METHOD NAME : NCPkgPopupDiskspace::NCPkgPopupDiskspace
438 // METHOD TYPE : Constructor
439 //
440 NCPkgPopupDiskspace::NCPkgPopupDiskspace( const wpos at, std::string headline )
441  : NCPopup( at, false )
442  , partitions( 0 )
443  , okButton( 0 )
444  , head( 0 )
445 {
446  createLayout( headline );
447 }
448 
449 ///////////////////////////////////////////////////////////////////
450 //
451 //
452 // METHOD NAME : NCPkgPopupDiskspace::~NCPkgPopupDiskspace
453 // METHOD TYPE : Destructor
454 //
455 NCPkgPopupDiskspace::~NCPkgPopupDiskspace()
456 {
457 }
458 
459 //////////////////////////////////////////////////////////////////
460 //
461 //
462 // METHOD NAME : NCPkgPopupDiskspace::createLyout
463 // METHOD TYPE : void
464 //
465 // DESCRIPTION : create layout (partition table)
466 //
467 void NCPkgPopupDiskspace::createLayout( std::string headline )
468 {
469  // the vertical split is the (only) child of the dialog
470  NCLayoutBox * split = new NCLayoutBox( this, YD_VERT );
471 
472  head = new NCLabel( split, "", true, false ); // isHeading = true
473  head->setLabel( headline );
474 
475  YTableHeader * tableHeader = new YTableHeader();
476  tableHeader->addColumn( NCPkgStrings::Partition(), YAlignBegin );
477  tableHeader->addColumn( NCPkgStrings::UsedSpace(), YAlignBegin );
478  tableHeader->addColumn( NCPkgStrings::FreeSpace(), YAlignBegin );
479  tableHeader->addColumn( NCPkgStrings::TotalSpace(), YAlignBegin );
480  tableHeader->addColumn( "% ", YAlignBegin );
481 
482  // add the partition table
483  partitions = new NCTable( split, tableHeader );
484 
485  // add the ok button
486  okButton = new NCPushButton( split, NCPkgStrings::OKLabel() );
487  okButton->setFunctionKey( 10 );
488  okButton->setKeyboardFocus();
489 }
490 
491 
492 ///////////////////////////////////////////////////////////////////
493 //
494 //
495 // METHOD NAME : NCPkgPopupDiskspace::preferredWidth
496 // METHOD TYPE : int
497 //
498 int NCPkgPopupDiskspace::preferredWidth()
499 {
500  return NCurses::cols()*2/3;
501 }
502 
503 ///////////////////////////////////////////////////////////////////
504 //
505 //
506 // METHOD NAME : NCPkgPopupDiskspace::preferredHeight
507 // METHOD TYPE : int
508 //
509 int NCPkgPopupDiskspace::preferredHeight()
510 {
511  if ( NCurses::lines() > 15 )
512  return 15;
513  else
514  return NCurses::lines()-4;
515 }
516 
517 void NCPkgPopupDiskspace::doit()
518 {
519  postevent = NCursesEvent();
520  do {
521  // show the popup
522  popupDialog( );
523  } while ( postAgain() );
524 
525  popdownDialog();
526 
527 }
528 ///////////////////////////////////////////////////////////////////
529 //
530 //
531 // METHOD NAME : NCPopup::wHandleInput
532 // METHOD TYPE : NCursesEvent
533 //
534 // DESCRIPTION :
535 //
536 NCursesEvent NCPkgPopupDiskspace::wHandleInput( wint_t ch )
537 {
538  if ( ch == 27 ) // ESC
539  return NCursesEvent::cancel;
540 
541  if ( ch == KEY_RETURN )
542  return NCursesEvent::button;
543 
544  return NCDialog::wHandleInput( ch );
545 }
546 
547 ///////////////////////////////////////////////////////////////////
548 //
549 //
550 // METHOD NAME : NCPkgPopupDiskspace::postAgain
551 // METHOD TYPE : bool
552 //
553 // DESCRIPTION :
554 //
555 bool NCPkgPopupDiskspace::postAgain()
556 {
557  if ( ! postevent.widget )
558  return false;
559 
560  if ( postevent == NCursesEvent::button || postevent == NCursesEvent::cancel )
561  {
562  // return false means: close the popup dialog
563  return false;
564  }
565  return true;
566 }
567 
568 
569 
570 
572 {
573  clearHistory();
574 }
575 
576 
577 void
579 {
580  _inRange = false;
581  _hasBeenClose = _isClose;
582  _isClose = false;
583 }
584 
585 
586 void
588 {
589  clear();
590  _hasBeenClose = false;
591  _warningPosted = false;
592 }
593 
594 
595 void
597 {
598  _inRange = true;
599  enterProximity();
600 }
601 
602 
603 void
605 {
606  _isClose = true;
607  _hasBeenClose = true;
608 }
609 
610 
611 void
613 {
614  _warningPosted = true;
615 }
616 
617 
618 bool
620 {
621  return _inRange;
622 }
623 
624 
625 bool
627 {
628  return ! _isClose && ! _hasBeenClose;
629 }
630 
631 
632 bool
634 {
635  return _inRange && ! _warningPosted;
636 }
637 
638 void
639 NCPkgWarningRangeNotifier::logSettings() const
640 {
641  yuiMilestone() << "in range: " << (_inRange?"true":"false") << endl;
642  yuiMilestone() << "is close: " << (_isClose?"true":"false") << endl;
643  yuiMilestone() << "has been close: " << (_hasBeenClose?"true":"false") << endl;
644  yuiMilestone() << "warning posted: " << (_warningPosted?"true":"false") << endl;
645 }
646 
bool needWarning() const
Check if a warning should be posted, i.e.
void warningPostedNotify()
Notification that a warning has been posted.
void clearHistory()
Clear everything, including all history values such as if a warning has been posted.
bool leavingProximity() const
Check if the value is leaving the proximity range.
void clear()
Clear the current values, i.e.
NCPkgWarningRangeNotifier()
Constructor.
bool inRange() const
Check if the value is in range, i.e.
void enterProximity()
Notification that the proximity range is entered, i.e.
void enterRange()
Notification that the inner range is entered.
static const std::string OKLabel()
The label of the OK button.