libyui-ncurses-pkg  2.43.4.1
 All Classes Functions
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