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