libyui-qt  2.43.5
/usr/src/RPM/BUILD/libyui-qt-2.43.5/src/QY2DiskUsageList.cc
00001 /*
00002   Copyright (C) 2000-2012 Novell, Inc
00003   This library is free software; you can redistribute it and/or modify
00004   it under the terms of the GNU Lesser General Public License as
00005   published by the Free Software Foundation; either version 2.1 of the
00006   License, or (at your option) version 3.0 of the License. This library
00007   is distributed in the hope that it will be useful, but WITHOUT ANY
00008   WARRANTY; without even the implied warranty of MERCHANTABILITY or
00009   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00010   License for more details. You should have received a copy of the GNU
00011   Lesser General Public License along with this library; if not, write
00012   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
00013   Floor, Boston, MA 02110-1301 USA
00014 */
00015 
00016 
00017 /*-/
00018 
00019   File:       QY2DiskUsageList.cc
00020 
00021   Author:     Stefan Hundhammer <sh@suse.de>
00022 
00023   Textdomain "qt"
00024 
00025   This is a pure Qt widget - it can be used independently of YaST2.
00026 
00027 
00028 /-*/
00029 
00030 #include "QY2DiskUsageList.h"
00031 #include "YQi18n.h"
00032 #include <QPainter>
00033 #include <QItemDelegate>
00034 #include <QDebug>
00035 
00036 #ifdef TEXTDOMAIN
00037 #    undef TEXTDOMAIN
00038 #endif
00039 
00040 #define TEXTDOMAIN "qt"
00041 
00042 
00043 
00044 /**
00045  * Stolen from KDirStat::KDirTreeView with the author's permission.
00046  **/
00047 QColor
00048 contrastingColor( const QColor & desiredColor,
00049                                         const QColor & contrastColor )
00050 {
00051     if ( desiredColor != contrastColor )
00052     {
00053         return desiredColor;
00054     }
00055 
00056     if ( contrastColor != contrastColor.light() )
00057     {
00058         // try a little lighter
00059         return contrastColor.light();
00060     }
00061     else
00062     {
00063         // try a little darker
00064         return contrastColor.dark();
00065     }
00066 }
00067 
00068 /**
00069  * Interpolate ( translate ) a value 'from' in the range between 'minFrom'
00070  * and 'maxFrom'  to a range between 'minTo' and 'maxTo'.
00071  **/
00072 static int
00073 interpolate( int from,
00074                                    int minFrom, int maxFrom,
00075                                    int minTo,   int maxTo       )
00076 {
00077     if ( minFrom > maxFrom )
00078     {
00079         // Swap min/max values
00080 
00081         int tmp = maxFrom;
00082         maxFrom = minFrom;
00083         minFrom = tmp;
00084     }
00085 
00086     long x = from - minFrom;
00087     x *= maxTo - minTo;
00088     x /= maxFrom - minFrom;
00089     x += minTo;
00090 
00091     if ( minTo < maxTo )
00092     {
00093         if ( x < minTo )        x = minTo;
00094         if ( x > maxTo )        x = maxTo;
00095     }
00096     else
00097     {
00098         if ( x < maxTo )        x = maxTo;
00099         if ( x > minTo )        x = minTo;
00100     }
00101 
00102     return (int) x;
00103 }
00104 
00105 /**
00106  * Interpolate ( in the HSV color space ) a color between 'minColor' and
00107  * 'maxColor' for a current value 'val' so that 'minVal' corresponds to
00108  * 'minColor' and 'maxVal' to 'maxColor'.
00109  *
00110  * Returns the interpolated color.
00111  **/
00112 static QColor
00113 interpolateColor( int           val,
00114                                         int             minVal,
00115                                         int             maxVal,
00116                                         const QColor &  minColor,
00117                                         const QColor &  maxColor )
00118 {
00119     int minH, maxH;
00120     int minS, maxS;
00121     int minV, maxV;
00122 
00123     minColor.getHsv( &minH, &minS, &minV );
00124     maxColor.getHsv( &maxH, &maxS, &maxV );
00125 
00126     return QColor::fromHsv( interpolate( val, minVal, maxVal, minH, maxH ),
00127                    interpolate( val, minVal, maxVal, minS, maxS ),
00128                    interpolate( val, minVal, maxVal, minV, maxV ) );
00129 }
00130 
00131 
00132 class QY2DiskUsagePercentageItem : public QItemDelegate
00133 {
00134     QY2DiskUsageList *_view;
00135 
00136 public:
00137     QY2DiskUsagePercentageItem( QY2DiskUsageList *parent ) : QItemDelegate( parent ), _view( parent ) {
00138     }
00139 
00140     virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
00141     {
00142         painter->save();
00143         QColor background = option.palette.color(QPalette::Window);
00144         painter->setBackground( background );
00145 
00146         QY2DiskUsageListItem *item = dynamic_cast<QY2DiskUsageListItem *>(_view->itemFromIndex(index));
00147         if ( item )
00148         {
00149           item->paintPercentageBar( painter,
00150                                     option,
00151                                     interpolateColor( item->usedPercent(),
00152                                                       60, 95,
00153                                                       QColor( 0, 0xa0, 0 ),     // Medium dark green
00154                                                       QColor( 0xFF, 0, 0 ) ) ); // Bright red
00155         }
00156         painter->restore();
00157     }
00158 };
00159 
00160 QY2DiskUsageList::QY2DiskUsageList( QWidget * parent, bool addStdColumns )
00161     : QY2ListView( parent )
00162 {
00163     _nameCol            = -42;
00164     _percentageBarCol   = -42;
00165     _usedSizeCol        = -42;
00166     _freeSizeCol        = -42;
00167     _totalSizeCol       = -42;
00168     _deviceNameCol      = -42;
00169 
00170     // set temporary textdomain to enable translations
00171     // in inherit classed (e.g. YQPkgDiskUsageList)
00172     // see bnc #445716
00173     QString savedtextdomain = textdomain(NULL);
00174     textdomain(TEXTDOMAIN);
00175 
00176     QStringList columnLabels;
00177     if ( addStdColumns )
00178     {
00179         int numCol = 0;
00180         columnLabels << _( "Name"               );      _nameCol                = numCol++;
00181         // Translators: Please keep this short!
00182         columnLabels <<  _("Disk Usage");       _percentageBarCol       = numCol++;
00183         setItemDelegateForColumn( _percentageBarCol, new QY2DiskUsagePercentageItem( this ) );
00184         //columnLabels << _("Used"); _usedSizeCol               = numCol++;
00185         columnLabels << _( "Free"); _freeSizeCol                = numCol++;
00186         columnLabels << _("Total"); _totalSizeCol               = numCol++;
00187 #if 0
00188         addColumn( _( "Device"          ) );    _deviceNameCol          = numCol++;
00189 #endif
00190         // needed?
00191         setColumnCount(numCol);
00192         setHeaderLabels(columnLabels);
00193 
00194         sortItems( percentageBarCol(), Qt::AscendingOrder );
00195         setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
00196     }
00197 
00198     textdomain(savedtextdomain.toAscii());
00199 
00200     saveColumnWidths();
00201     setSelectionMode(QAbstractItemView::NoSelection);
00202 }
00203 
00204 
00205 QY2DiskUsageList::~QY2DiskUsageList()
00206 {
00207 }
00208 
00209 
00210 void QY2DiskUsageList::drawRow( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
00211 {
00212     // Intentionally bypassing the direct parent class method, use the grandparent's:
00213     // Don't let QY2ListViewItem::_textColor / _backgroundColor interfere with our colors.
00214 
00215     QTreeWidget::drawRow( painter, option, index );
00216 }
00217 
00218 
00219 QY2DiskUsageListItem::QY2DiskUsageListItem( QY2DiskUsageList * parent )
00220     : QY2ListViewItem( parent )
00221     , _diskUsageList( parent )
00222 {
00223 }
00224 
00225 
00226 
00227 
00228 QY2DiskUsageListItem::~QY2DiskUsageListItem()
00229 {
00230     // NOP
00231 }
00232 
00233 
00234 
00235 
00236 void
00237 QY2DiskUsageListItem::init( bool allFields )
00238 {
00239     setSizeHint( percentageBarCol(), QSize( 20, 10 ) );
00240 
00241     setTextAlignment( usedSizeCol(), Qt::AlignRight );
00242     setTextAlignment( freeSizeCol(), Qt::AlignRight );
00243     setTextAlignment( totalSizeCol(), Qt::AlignRight );
00244 
00245     if ( usedSizeCol()          >= 0 ) setText( usedSizeCol(),          usedSize()      );
00246     if ( freeSizeCol()          >= 0 ) setText( freeSizeCol(),          freeSize()      );
00247 
00248     if ( allFields )
00249     {
00250         if ( totalSizeCol()     >= 0 ) setText( totalSizeCol(),         totalSize()     );
00251         if ( nameCol()          >= 0 ) setText( nameCol(),              name()  );
00252         if ( deviceNameCol()    >= 0 ) setText( deviceNameCol(),        deviceName()    );
00253     }
00254 
00255     if ( usedSizeCol() < 0 )
00256         setToolTip( freeSizeCol(), _( "Used %1" ).arg( usedSize().form( 0, 1, true ).c_str() ) );
00257 }
00258 
00259 
00260 void
00261 QY2DiskUsageListItem::setText( int column, const FSize & size )
00262 {
00263     QString sizeText = size.form( 0, 1, true ).c_str();
00264     setText( column, sizeText );
00265 }
00266 
00267 
00268 FSize
00269 QY2DiskUsageListItem::freeSize() const
00270 {
00271     return totalSize() - usedSize();
00272 }
00273 
00274 
00275 int
00276 QY2DiskUsageListItem::usedPercent() const
00277 {
00278     int percent = 0;
00279 
00280     if ( totalSize() != 0 )
00281         percent = ( 100 * usedSize() ) / totalSize();
00282 
00283     return percent;
00284 }
00285 
00286 
00287 void
00288 QY2DiskUsageListItem::updateStatus()
00289 {
00290     init( false );
00291 }
00292 
00293 
00294 void
00295 QY2DiskUsageListItem::updateData()
00296 {
00297     init( true );
00298 }
00299 
00300 
00301 
00302 
00303 
00304 /**
00305      * Comparison function used for sorting the list.
00306      * Reimplemented from QTreeWidgetItem
00307      **/
00308 bool
00309 QY2DiskUsageListItem::operator<( const QTreeWidgetItem & otherListViewItem ) const
00310 {
00311     const QY2DiskUsageListItem * other = dynamic_cast<const QY2DiskUsageListItem *> (&otherListViewItem);
00312     int col = treeWidget()->sortColumn();
00313 
00314     if ( other )
00315     {
00316         if ( col == percentageBarCol()   )
00317         {
00318             // Intentionally reverting sort order: Fullest first
00319             return ( this->usedPercent() < other->usedPercent() );
00320         }
00321         else if ( col == usedSizeCol() )
00322         {
00323             return ( this->usedSize() < other->usedSize() );
00324         }
00325         else if ( col == freeSizeCol() )
00326         {
00327             return ( this->freeSize() < other->freeSize() );
00328         }
00329         else if ( col == totalSizeCol() )
00330         {
00331             return ( this->totalSize() < other->totalSize() );
00332         }
00333     }
00334 
00335     return QY2ListViewItem::operator<( otherListViewItem );
00336 }
00337 
00338 /**
00339  * Stolen from KDirStat::KDirTreeView with the author's permission.
00340  **/
00341 void
00342 QY2DiskUsageListItem::paintPercentageBar( QPainter *            painter,
00343                                           QStyleOptionViewItem option,
00344                                           const QColor &        fillColor )
00345 {
00346     float percent = usedPercent();
00347     if ( percent > 100.0 )      percent = 100.0;
00348     if ( percent < 0.0   )      percent = 0.0;
00349     int x = option.rect.left() + 1;
00350     int y = option.rect.top() + 1;
00351     int w = option.rect.width() - 2;
00352     int h = option.rect.height() - 2;
00353     int fillWidth = 0;
00354 
00355     if ( w > 0 )
00356     {
00357         fillWidth = (int) ( w * percent / 100.0 );
00358 
00359         // Fill the desired percentage.
00360 
00361         painter->fillRect( x, y,  fillWidth, h,
00362                            fillColor );
00363 
00364         QString percentageText;
00365         percentageText.sprintf( "%d%%", usedPercent() );
00366 
00367         if ( usedPercent() > 50 ) {
00368             painter->setPen( treeWidget()->palette().color( QPalette::Base ) );
00369             painter->drawText( QRect( x, y,
00370                                       fillWidth - 3, h ),
00371                                Qt::AlignRight, percentageText );
00372         } else {
00373             painter->setPen( treeWidget()->palette().color( QPalette::Text ) );
00374             painter->drawText( QRect( x + fillWidth + 3, y,
00375                                       w - fillWidth - 3, h ),
00376                                Qt::AlignLeft, percentageText );
00377 
00378         }
00379     }
00380 }
00381 
00382 #include "QY2DiskUsageList.moc"
 All Classes Functions Variables