picking up branches/tmp/sh/qt4-port/, merging it with trunk
[duncan/yast2-qt4.git] / src / pkg / YQPkgDiskUsageList.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgDiskUsageList.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21
22 #define y2log_component "qt-pkg"
23 #include <ycp/y2log.h>
24
25 #include <q3header.h>
26 #include <qstyle.h>
27 //Added by qt3to4:
28 #include <qevent.h>
29
30 #include <zypp/ZYppFactory.h>
31
32 #include "utf8.h"
33 #include "YQPkgDiskUsageList.h"
34 #include "YQPkgDiskUsageWarningDialog.h"
35 #include "YQi18n.h"
36
37
38 using std::set;
39
40
41 // Warning ranges for "disk space is running out" or "disk space overflow".
42 // The WARN value triggers a warning popup once ( ! ). The warning will not be
43 // displayed again until the value sinks below the PROXIMITY value and then
44 // increases again to the WARN value.
45 //
46 // See class YQPkgWarningRangeNotifier in file YQPkgDiskUsageList.h for details.
47
48 #define MIN_FREE_MB_WARN        400
49 #define MIN_FREE_MB_PROXIMITY   700
50
51 #define MIN_PERCENT_WARN        90
52 #define MIN_PERCENT_PROXIMITY   80
53
54 #define OVERFLOW_MB_WARN        0
55 #define OVERFLOW_MB_PROXIMITY   300
56
57
58 typedef zypp::DiskUsageCounter::MountPointSet           ZyppDuSet;
59 typedef zypp::DiskUsageCounter::MountPointSet::iterator ZyppDuSetIterator;
60
61
62
63 YQPkgDiskUsageList::YQPkgDiskUsageList( QWidget * parent, int thresholdPercent )
64     : QY2DiskUsageList( parent, true )
65 {
66     _debug = false;
67
68     ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
69
70     if ( diskUsage.empty() )
71     {
72         zypp::getZYpp()->setPartitions( zypp::DiskUsageCounter::detectMountPoints() );
73         diskUsage = zypp::getZYpp()->diskUsage();
74     }
75
76
77     for ( ZyppDuSetIterator it = diskUsage.begin();
78           it != diskUsage.end();
79           ++it )
80     {
81         const ZyppPartitionDu & partitionDu = *it;
82
83         if ( ! partitionDu.readonly )
84         {
85             YQPkgDiskUsageListItem * item = new YQPkgDiskUsageListItem( this, partitionDu );
86             Q_CHECK_PTR( item );
87             item->updateData();
88             _items.insert( partitionDu.dir.c_str(), item );
89         }
90     }
91
92 }
93
94
95 void
96 YQPkgDiskUsageList::updateDiskUsage()
97 {
98     runningOutWarning.clear();
99     overflowWarning.clear();
100
101     ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
102
103     for ( ZyppDuSetIterator it = diskUsage.begin();
104           it != diskUsage.end();
105           ++it )
106     {
107         const ZyppPartitionDu & partitionDu = *it;
108         YQPkgDiskUsageListItem * item = _items[ partitionDu.dir.c_str() ];
109
110         if ( item )
111             item->updateDuData( partitionDu );
112         else
113             y2error( "No entry for mount point %s", partitionDu.dir.c_str() );
114     }
115
116     sort();
117     postPendingWarnings();
118 }
119
120
121 void
122 YQPkgDiskUsageList::postPendingWarnings()
123 {
124     if ( overflowWarning.needWarning() )
125     {
126         YQPkgDiskUsageWarningDialog::diskUsageWarning( _( "<b>Error:</b> Out of disk space!" ),
127                                                        100, _( "&OK" ) );
128
129         overflowWarning.warningPostedNotify();
130         runningOutWarning.warningPostedNotify(); // Suppress this ( now redundant ) other warning
131     }
132
133     if ( runningOutWarning.needWarning() )
134     {
135         YQPkgDiskUsageWarningDialog::diskUsageWarning( _( "<b>Warning:</b> Disk space is running out!" ) ,
136                                                        MIN_PERCENT_WARN, _( "&OK" ) );
137         runningOutWarning.warningPostedNotify();
138     }
139
140     if ( overflowWarning.leavingProximity() )
141         overflowWarning.clearHistory();
142
143     if ( runningOutWarning.leavingProximity() )
144         runningOutWarning.clearHistory();
145 }
146
147
148 QSize
149 YQPkgDiskUsageList::sizeHint() const
150 {
151     int width = header()->headerWidth()
152 #ifdef FIXME
153         + style().pixelMetric( QStyle::PM_ScrollBarExtent, verticalScrollBar() );
154 #else
155         + 30;
156 #endif
157
158     return QSize( width, 100 );
159 }
160
161
162 void
163 YQPkgDiskUsageList::keyPressEvent( QKeyEvent * event )
164 {
165
166     if ( event )
167     {
168         unsigned special_combo = ( Qt::ControlButton | Qt::ShiftButton | Qt::AltButton );
169
170         if ( ( event->state() & special_combo ) == special_combo )
171         {
172             if ( event->key() == Qt::Key_Q )
173             {
174                 _debug = ! _debug;
175                 y2milestone( "Debug mode %s", _debug ? "on" : "off" );
176             }
177
178         }
179
180         if ( _debug && currentItem() )
181         {
182             YQPkgDiskUsageListItem * item = dynamic_cast<YQPkgDiskUsageListItem *> ( currentItem() );
183
184             if ( item )
185             {
186                 {
187                     int percent = item->usedPercent();
188
189                     switch ( event->ascii() )
190                     {
191                         case '1':       percent = 10;   break;
192                         case '2':       percent = 20;   break;
193                         case '3':       percent = 30;   break;
194                         case '4':       percent = 40;   break;
195                         case '5':       percent = 50;   break;
196                         case '6':       percent = 60;   break;
197                         case '7':       percent = 70;   break;
198                         case '8':       percent = 80;   break;
199                         case '9':       percent = 90;   break;
200                         case '0':       percent = 100;  break;
201                         case '+':       percent += 3;   break;
202                         case '-':       percent -= 3;   break;
203
204                         case 'w':
205                             // Only for testing, thus intentionally using no translations
206                             YQPkgDiskUsageWarningDialog::diskUsageWarning( "<b>Warning:</b> Disk space is running out!",
207                                                                            90, "&OK" );
208                             break;
209
210                         case 'f':
211                             YQPkgDiskUsageWarningDialog::diskUsageWarning( "<b>Error:</b> Out of disk space!",
212                                                                            100, "&Continue anyway", "&Cancel" );
213                             break;
214                     }
215
216                     if ( percent < 0   )
217                         percent = 0;
218
219                     ZyppPartitionDu partitionDu( item->partitionDu() );
220
221                     if ( percent != item->usedPercent() )
222                     {
223                         partitionDu.pkg_size = partitionDu.total_size * percent / 100;
224
225                         runningOutWarning.clear();
226                         overflowWarning.clear();
227
228                         item->updateDuData( partitionDu );
229                         postPendingWarnings();
230                     }
231                 }
232             }
233         }
234     }
235
236     QY2DiskUsageList::keyPressEvent( event );
237 }
238
239
240
241
242
243
244 YQPkgDiskUsageListItem::YQPkgDiskUsageListItem( YQPkgDiskUsageList *    parent,
245                                                 const ZyppPartitionDu & partitionDu )
246         : QY2DiskUsageListItem( parent )
247         , _partitionDu( partitionDu )
248         , _pkgDiskUsageList( parent )
249 {
250     y2debug( "disk usage list entry for %s", partitionDu.dir.c_str() );
251 }
252
253
254 FSize
255 YQPkgDiskUsageListItem::usedSize() const
256 {
257     return FSize( _partitionDu.pkg_size, FSize::K );
258 }
259
260
261 FSize
262 YQPkgDiskUsageListItem::totalSize() const
263 {
264     return FSize( _partitionDu.total_size, FSize::K );
265 }
266
267
268 QString
269 YQPkgDiskUsageListItem::name() const
270 {
271     return fromUTF8( _partitionDu.dir.c_str() );
272 }
273
274
275 void
276 YQPkgDiskUsageListItem::updateDuData( const ZyppPartitionDu & fromData )
277 {
278     _partitionDu = fromData;
279     updateData();
280     checkRemainingDiskSpace();
281 }
282
283
284 void
285 YQPkgDiskUsageListItem::checkRemainingDiskSpace()
286 {
287     int percent = usedPercent();
288     int free    = freeSize() / FSize::MB;
289
290     if ( percent > MIN_PERCENT_WARN )
291     {
292         // Modern hard disks can be huge, so a warning based on percentage only
293         // can be misleading - check the absolute value, too.
294
295         if ( free < MIN_FREE_MB_PROXIMITY )
296             _pkgDiskUsageList->runningOutWarning.enterProximity();
297
298         if ( free < MIN_FREE_MB_WARN )
299             _pkgDiskUsageList->runningOutWarning.enterRange();
300     }
301
302     if ( free < MIN_FREE_MB_PROXIMITY )
303     {
304         if ( percent > MIN_PERCENT_PROXIMITY )
305             _pkgDiskUsageList->runningOutWarning.enterProximity();
306     }
307
308     if ( free < OVERFLOW_MB_WARN )
309         _pkgDiskUsageList->overflowWarning.enterRange();
310
311     if ( free < OVERFLOW_MB_PROXIMITY )
312         _pkgDiskUsageList->overflowWarning.enterProximity();
313 }
314
315
316
317
318
319
320 YQPkgWarningRangeNotifier::YQPkgWarningRangeNotifier()
321 {
322     clearHistory();
323 }
324
325
326 void
327 YQPkgWarningRangeNotifier::clear()
328 {
329     _inRange            = false;
330     _hasBeenClose       = _isClose;
331     _isClose            = false;
332 }
333
334
335 void
336 YQPkgWarningRangeNotifier::clearHistory()
337 {
338     clear();
339     _hasBeenClose  = false;
340     _warningPosted = false;
341 }
342
343
344 void
345 YQPkgWarningRangeNotifier::enterRange()
346 {
347     _inRange = true;
348     enterProximity();
349 }
350
351
352 void
353 YQPkgWarningRangeNotifier::enterProximity()
354 {
355     _isClose      = true;
356     _hasBeenClose = true;
357 }
358
359
360 void
361 YQPkgWarningRangeNotifier::warningPostedNotify()
362 {
363     _warningPosted = true;
364 }
365
366
367 bool
368 YQPkgWarningRangeNotifier::inRange() const
369 {
370     return _inRange;
371 }
372
373
374 bool
375 YQPkgWarningRangeNotifier::leavingProximity() const
376 {
377     return ! _isClose && ! _hasBeenClose;
378 }
379
380
381 bool
382 YQPkgWarningRangeNotifier::needWarning() const
383 {
384     return _inRange && ! _warningPosted;
385 }
386
387
388
389
390 #include "YQPkgDiskUsageList.moc"