libyui-qt  2.46.13
QY2DiskUsageList.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: QY2DiskUsageList.cc
20 
21  Author: Stefan Hundhammer <sh@suse.de>
22 
23  Textdomain "qt"
24 
25  This is a pure Qt widget - it can be used independently of YaST2.
26 
27 
28 /-*/
29 
30 #include "QY2DiskUsageList.h"
31 #include "YQi18n.h"
32 #include <QPainter>
33 #include <QItemDelegate>
34 #include <QDebug>
35 
36 #ifdef TEXTDOMAIN
37 # undef TEXTDOMAIN
38 #endif
39 
40 #define TEXTDOMAIN "qt"
41 
42 
43 
44 /**
45  * Stolen from KDirStat::KDirTreeView with the author's permission.
46  **/
47 QColor
48 contrastingColor( const QColor & desiredColor,
49  const QColor & contrastColor )
50 {
51  if ( desiredColor != contrastColor )
52  {
53  return desiredColor;
54  }
55 
56  if ( contrastColor != contrastColor.light() )
57  {
58  // try a little lighter
59  return contrastColor.light();
60  }
61  else
62  {
63  // try a little darker
64  return contrastColor.dark();
65  }
66 }
67 
68 /**
69  * Interpolate ( translate ) a value 'from' in the range between 'minFrom'
70  * and 'maxFrom' to a range between 'minTo' and 'maxTo'.
71  **/
72 static int
73 interpolate( int from,
74  int minFrom, int maxFrom,
75  int minTo, int maxTo )
76 {
77  if ( minFrom > maxFrom )
78  {
79  // Swap min/max values
80 
81  int tmp = maxFrom;
82  maxFrom = minFrom;
83  minFrom = tmp;
84  }
85 
86  long x = from - minFrom;
87  x *= maxTo - minTo;
88  x /= maxFrom - minFrom;
89  x += minTo;
90 
91  if ( minTo < maxTo )
92  {
93  if ( x < minTo ) x = minTo;
94  if ( x > maxTo ) x = maxTo;
95  }
96  else
97  {
98  if ( x < maxTo ) x = maxTo;
99  if ( x > minTo ) x = minTo;
100  }
101 
102  return (int) x;
103 }
104 
105 /**
106  * Interpolate ( in the HSV color space ) a color between 'minColor' and
107  * 'maxColor' for a current value 'val' so that 'minVal' corresponds to
108  * 'minColor' and 'maxVal' to 'maxColor'.
109  *
110  * Returns the interpolated color.
111  **/
112 static QColor
113 interpolateColor( int val,
114  int minVal,
115  int maxVal,
116  const QColor & minColor,
117  const QColor & maxColor )
118 {
119  int minH, maxH;
120  int minS, maxS;
121  int minV, maxV;
122 
123  minColor.getHsv( &minH, &minS, &minV );
124  maxColor.getHsv( &maxH, &maxS, &maxV );
125 
126  return QColor::fromHsv( interpolate( val, minVal, maxVal, minH, maxH ),
127  interpolate( val, minVal, maxVal, minS, maxS ),
128  interpolate( val, minVal, maxVal, minV, maxV ) );
129 }
130 
131 
132 class QY2DiskUsagePercentageItem : public QItemDelegate
133 {
134  QY2DiskUsageList *_view;
135 
136 public:
137  QY2DiskUsagePercentageItem( QY2DiskUsageList *parent ) : QItemDelegate( parent ), _view( parent ) {
138  }
139 
140  virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
141  {
142  painter->save();
143  QColor background = option.palette.color(QPalette::Window);
144  painter->setBackground( background );
145 
146  QY2DiskUsageListItem *item = dynamic_cast<QY2DiskUsageListItem *>(_view->itemFromIndex(index));
147  if ( item )
148  {
149  item->paintPercentageBar( painter,
150  option,
151  interpolateColor( item->usedPercent(),
152  60, 95,
153  QColor( 0, 0xa0, 0 ), // Medium dark green
154  QColor( 0xFF, 0, 0 ) ) ); // Bright red
155  }
156  painter->restore();
157  }
158 };
159 
160 QY2DiskUsageList::QY2DiskUsageList( QWidget * parent, bool addStdColumns )
161  : QY2ListView( parent )
162 {
163  _nameCol = -42;
164  _percentageBarCol = -42;
165  _usedSizeCol = -42;
166  _freeSizeCol = -42;
167  _totalSizeCol = -42;
168  _deviceNameCol = -42;
169 
170  // set temporary textdomain to enable translations
171  // in inherit classed (e.g. YQPkgDiskUsageList)
172  // see bnc #445716
173  QString savedtextdomain = textdomain(NULL);
174  textdomain(TEXTDOMAIN);
175 
176  QStringList columnLabels;
177  if ( addStdColumns )
178  {
179  int numCol = 0;
180  columnLabels << _( "Name" ); _nameCol = numCol++;
181  // Translators: Please keep this short!
182  columnLabels << _("Disk Usage"); _percentageBarCol = numCol++;
183  setItemDelegateForColumn( _percentageBarCol, new QY2DiskUsagePercentageItem( this ) );
184  //columnLabels << _("Used"); _usedSizeCol = numCol++;
185  columnLabels << _( "Free"); _freeSizeCol = numCol++;
186  columnLabels << _("Total"); _totalSizeCol = numCol++;
187 #if 0
188  addColumn( _( "Device" ) ); _deviceNameCol = numCol++;
189 #endif
190  // needed?
191  setColumnCount(numCol);
192  setHeaderLabels(columnLabels);
193 
194  sortItems( percentageBarCol(), Qt::AscendingOrder );
195  setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
196  }
197 
198  textdomain(savedtextdomain.toLatin1());
199 
201  setSelectionMode(QAbstractItemView::NoSelection);
202 }
203 
204 
206 {
207 }
208 
209 
210 void QY2DiskUsageList::drawRow( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
211 {
212  // Intentionally bypassing the direct parent class method, use the grandparent's:
213  // Don't let QY2ListViewItem::_textColor / _backgroundColor interfere with our colors.
214 
215  QTreeWidget::drawRow( painter, option, index );
216 }
217 
218 
220  : QY2ListViewItem( parent )
221  , _diskUsageList( parent )
222 {
223 }
224 
225 
226 
227 
229 {
230  // NOP
231 }
232 
233 
234 
235 
236 void
237 QY2DiskUsageListItem::init( bool allFields )
238 {
239  setSizeHint( percentageBarCol(), QSize( 20, 10 ) );
240 
241  setTextAlignment( usedSizeCol(), Qt::AlignRight );
242  setTextAlignment( freeSizeCol(), Qt::AlignRight );
243  setTextAlignment( totalSizeCol(), Qt::AlignRight );
244 
245  if ( usedSizeCol() >= 0 ) setText( usedSizeCol(), usedSize() );
246  if ( freeSizeCol() >= 0 ) setText( freeSizeCol(), freeSize() );
247 
248  if ( allFields )
249  {
250  if ( totalSizeCol() >= 0 ) setText( totalSizeCol(), totalSize() );
251  if ( nameCol() >= 0 ) setText( nameCol(), name() );
252  if ( deviceNameCol() >= 0 ) setText( deviceNameCol(), deviceName() );
253  }
254 
255  if ( usedSizeCol() < 0 )
256  setToolTip( freeSizeCol(), _( "Used %1" ).arg( usedSize().form( 0, 1, true ).c_str() ) );
257 }
258 
259 
260 void
261 QY2DiskUsageListItem::setText( int column, const FSize & size )
262 {
263  QString sizeText = size.form( 0, 1, true ).c_str();
264  setText( column, sizeText );
265 }
266 
267 
268 FSize
270 {
271  return totalSize() - usedSize();
272 }
273 
274 
275 int
277 {
278  int percent = 0;
279 
280  if ( totalSize() != 0 )
281  percent = ( 100 * usedSize() ) / totalSize();
282 
283  return percent;
284 }
285 
286 
287 void
289 {
290  init( false );
291 }
292 
293 
294 void
296 {
297  init( true );
298 }
299 
300 
301 
302 
303 
304 /**
305  * Comparison function used for sorting the list.
306  * Reimplemented from QTreeWidgetItem
307  **/
308 bool
309 QY2DiskUsageListItem::operator<( const QTreeWidgetItem & otherListViewItem ) const
310 {
311  const QY2DiskUsageListItem * other = dynamic_cast<const QY2DiskUsageListItem *> (&otherListViewItem);
312  int col = treeWidget()->sortColumn();
313 
314  if ( other )
315  {
316  if ( col == percentageBarCol() )
317  {
318  // Intentionally reverting sort order: Fullest first
319  return ( this->usedPercent() < other->usedPercent() );
320  }
321  else if ( col == usedSizeCol() )
322  {
323  return ( this->usedSize() < other->usedSize() );
324  }
325  else if ( col == freeSizeCol() )
326  {
327  return ( this->freeSize() < other->freeSize() );
328  }
329  else if ( col == totalSizeCol() )
330  {
331  return ( this->totalSize() < other->totalSize() );
332  }
333  }
334 
335  return QY2ListViewItem::operator<( otherListViewItem );
336 }
337 
338 /**
339  * Stolen from KDirStat::KDirTreeView with the author's permission.
340  **/
341 void
343  QStyleOptionViewItem option,
344  const QColor & fillColor )
345 {
346  float percent = usedPercent();
347  if ( percent > 100.0 ) percent = 100.0;
348  if ( percent < 0.0 ) percent = 0.0;
349  int x = option.rect.left() + 1;
350  int y = option.rect.top() + 1;
351  int w = option.rect.width() - 2;
352  int h = option.rect.height() - 2;
353  int fillWidth = 0;
354 
355  if ( w > 0 )
356  {
357  fillWidth = (int) ( w * percent / 100.0 );
358 
359  // Fill the desired percentage.
360 
361  painter->fillRect( x, y, fillWidth, h,
362  fillColor );
363 
364  QString percentageText;
365  percentageText.sprintf( "%d%%", usedPercent() );
366 
367  if ( usedPercent() > 50 ) {
368  painter->setPen( treeWidget()->palette().color( QPalette::Base ) );
369  painter->drawText( QRect( x, y,
370  fillWidth - 3, h ),
371  Qt::AlignRight, percentageText );
372  } else {
373  painter->setPen( treeWidget()->palette().color( QPalette::Text ) );
374  painter->drawText( QRect( x + fillWidth + 3, y,
375  w - fillWidth - 3, h ),
376  Qt::AlignLeft, percentageText );
377 
378  }
379  }
380 }
381 
382 #include "QY2DiskUsageList.moc"
virtual FSize totalSize() const =0
The total size of this partition.
QY2DiskUsageList(QWidget *parent, bool addStdColumns=true)
Constructor.
virtual bool operator<(const QTreeWidgetItem &other) const
Comparison function used for sorting the list.
Definition: QY2ListView.cc:396
virtual int usedPercent() const
The currently used percentage ( 0..100 ) of this partition.
virtual QString deviceName() const
The device name of this partition.
virtual FSize usedSize() const =0
The currently used size of this partition.
virtual void updateStatus()
Update this item's status ( here: the numeric fields ).
QY2DiskUsageListItem(QY2DiskUsageList *parent)
Constructor.
virtual void updateData()
Update this item's data completely.
void saveColumnWidths()
Save the current column widths.
Definition: QY2ListView.cc:170
virtual FSize freeSize() const
The current free size of this partition.
virtual QString name() const =0
The name to display for this partition.
Abstract base class for one partition ( mount point ) to display in a QY2DiskUsageList.
virtual bool operator<(const QTreeWidgetItem &other) const
Comparison function used for sorting the list.
void init(bool allFields)
( Re- ) initialize fields - all displayed fields ( if 'allFields' is 'true' ) or only the varying fie...
Generic scrollable list of disk usage for any number of partitions.
Enhanced QTreeWidget.
Definition: QY2ListView.h:47
void setText(int column, const QString &text)
Re-declare ordinary setText() method so the compiler doesn't get confused which one to use...
virtual ~QY2DiskUsageListItem()
Destructor.
void paintPercentageBar(QPainter *painter, QStyleOptionViewItem option, const QColor &fillColor)
Paint a percentage bar into a QListViewItem cell.
Enhanced QTreeWidgetItem.
Definition: QY2ListView.h:233
virtual ~QY2DiskUsageList()
Destructor.