KDEUI
kselector.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1997 Martin Jones (mjones@kde.org) 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "kselector.h" 00021 00022 #include <QImage> 00023 #include <QPainter> 00024 #include <QPaintEvent> 00025 #include <QPixmap> 00026 #include <QStyle> 00027 #include <QStyleOption> 00028 00029 #include "kcolorhelpers_p.h" 00030 00031 using KDEPrivate::fillOpaqueRect; 00032 00033 //----------------------------------------------------------------------------- 00034 /* 00035 * 1D value selector with contents drawn by derived class. 00036 * See KColorDialog for example. 00037 */ 00038 00039 #define ARROWSIZE 5 00040 00041 class KSelector::Private 00042 { 00043 public: 00044 Private() 00045 { 00046 arrowPE = QStyle::PE_IndicatorArrowLeft; 00047 m_indent = true; 00048 } 00049 00050 bool m_indent; 00051 QStyle::PrimitiveElement arrowPE; 00052 }; 00053 00054 class KGradientSelector::KGradientSelectorPrivate 00055 { 00056 public: 00057 KGradientSelectorPrivate(KGradientSelector *q): q(q) {} 00058 00059 KGradientSelector *q; 00060 QLinearGradient gradient; 00061 QString text1; 00062 QString text2; 00063 }; 00064 00065 KSelector::KSelector( QWidget *parent ) 00066 : QAbstractSlider( parent ) 00067 , d(new Private) 00068 { 00069 setOrientation(Qt::Horizontal); 00070 } 00071 00072 KSelector::KSelector( Qt::Orientation o, QWidget *parent ) 00073 : QAbstractSlider( parent ) 00074 , d(new Private) 00075 { 00076 setOrientation(o); 00077 if(o == Qt::Horizontal) 00078 setArrowDirection(Qt::UpArrow); 00079 } 00080 00081 KSelector::~KSelector() 00082 { 00083 delete d; 00084 } 00085 00086 void KSelector::setIndent( bool i ) 00087 { 00088 d->m_indent = i; 00089 } 00090 00091 bool KSelector::indent() const 00092 { 00093 return d->m_indent; 00094 } 00095 00096 QRect KSelector::contentsRect() const 00097 { 00098 int w = indent() ? style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) : 0; 00099 //TODO: is the height:width ratio of an indicator arrow always 2:1? hm. 00100 int iw = (w < ARROWSIZE) ? ARROWSIZE : w; 00101 00102 if ( orientation() == Qt::Vertical ) { 00103 if ( arrowDirection() == Qt::RightArrow ) { 00104 return QRect( w + ARROWSIZE, iw, 00105 width() - w*2 - ARROWSIZE, 00106 height() - iw*2 ); 00107 } else { 00108 return QRect( w, iw, 00109 width() - w*2 - ARROWSIZE, 00110 height() - iw*2 ); 00111 } 00112 } else { // Qt::Horizontal 00113 if ( arrowDirection() == Qt::UpArrow ) { 00114 return QRect( iw, w, 00115 width() - 2*iw, 00116 height() - w*2 - ARROWSIZE ); 00117 } else { 00118 return QRect( iw, w + ARROWSIZE, 00119 width() - 2*iw, 00120 height() - w*2 - ARROWSIZE ); 00121 } 00122 } 00123 } 00124 00125 void KSelector::paintEvent( QPaintEvent * ) 00126 { 00127 QPainter painter; 00128 int w = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ); 00129 int iw = (w < ARROWSIZE) ? ARROWSIZE : w; 00130 00131 painter.begin( this ); 00132 00133 drawContents( &painter ); 00134 00135 QBrush brush; 00136 00137 QPoint pos = calcArrowPos( value() ); 00138 drawArrow( &painter, pos ); 00139 00140 if ( indent() ) 00141 { 00142 QStyleOptionFrame opt; 00143 opt.initFrom( this ); 00144 opt.state = QStyle::State_Sunken; 00145 if ( orientation() == Qt::Vertical ) 00146 opt.rect.adjust( 0, iw - w, -5, w - iw ); 00147 else 00148 opt.rect.adjust(iw - w, 0, w - iw, -5); 00149 QBrush oldBrush = painter.brush(); 00150 painter.setBrush( Qt::NoBrush ); 00151 style()->drawPrimitive( QStyle::PE_Frame, &opt, &painter, this ); 00152 painter.setBrush( oldBrush ); 00153 } 00154 00155 00156 painter.end(); 00157 } 00158 00159 void KSelector::mousePressEvent( QMouseEvent *e ) 00160 { 00161 setSliderDown(true); 00162 moveArrow( e->pos() ); 00163 } 00164 00165 void KSelector::mouseMoveEvent( QMouseEvent *e ) 00166 { 00167 moveArrow( e->pos() ); 00168 } 00169 00170 void KSelector::mouseReleaseEvent( QMouseEvent *e ) 00171 { 00172 moveArrow( e->pos() ); 00173 setSliderDown(false); 00174 } 00175 00176 void KSelector::wheelEvent( QWheelEvent *e ) 00177 { 00178 int val = value() + e->delta()/120; 00179 setSliderDown(true); 00180 setValue( val ); 00181 setSliderDown(false); 00182 } 00183 00184 void KSelector::moveArrow( const QPoint &pos ) 00185 { 00186 int val; 00187 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 00188 int iw = (w < ARROWSIZE) ? ARROWSIZE : w; 00189 00190 if ( orientation() == Qt::Vertical ) 00191 val = ( maximum() - minimum() ) * (height() - pos.y() - iw) 00192 / (height() - iw * 2) + minimum(); 00193 else 00194 val = ( maximum() - minimum() ) * ( pos.x() - iw) 00195 / (width() - iw * 2) + minimum(); 00196 00197 setValue( val ); 00198 update(); 00199 } 00200 00201 QPoint KSelector::calcArrowPos( int val ) 00202 { 00203 QPoint p; 00204 int w = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ); 00205 int iw = ( w < ARROWSIZE ) ? ARROWSIZE : w; 00206 00207 if ( orientation() == Qt::Vertical ) 00208 { 00209 p.setY( height() - iw - 1 - (height() - 2 * iw - 1) * val / ( maximum() - minimum() ) ); 00210 00211 if ( d->arrowPE == QStyle::PE_IndicatorArrowRight ) { 00212 p.setX( 0 ); 00213 } else { 00214 p.setX( width() - 5 ); 00215 } 00216 } 00217 else 00218 { 00219 p.setX( iw + (width() - 2 * iw - 1) * val / ( maximum() - minimum() ) ); 00220 00221 if ( d->arrowPE == QStyle::PE_IndicatorArrowDown ) { 00222 p.setY( 0 ); 00223 } else { 00224 p.setY( height() - 5 ); 00225 } 00226 } 00227 00228 return p; 00229 } 00230 00231 void KSelector::setArrowDirection( Qt::ArrowType direction ) 00232 { 00233 switch ( direction ) { 00234 case Qt::UpArrow: 00235 if ( orientation() == Qt::Horizontal ) { 00236 d->arrowPE = QStyle::PE_IndicatorArrowUp; 00237 } else { 00238 d->arrowPE = QStyle::PE_IndicatorArrowLeft; 00239 } 00240 break; 00241 case Qt::DownArrow: 00242 if ( orientation() == Qt::Horizontal ) { 00243 d->arrowPE = QStyle::PE_IndicatorArrowDown; 00244 } else { 00245 d->arrowPE = QStyle::PE_IndicatorArrowRight; 00246 } 00247 break; 00248 case Qt::LeftArrow: 00249 if ( orientation() == Qt::Vertical ) { 00250 d->arrowPE = QStyle::PE_IndicatorArrowLeft; 00251 } else { 00252 d->arrowPE = QStyle::PE_IndicatorArrowDown; 00253 } 00254 break; 00255 case Qt::RightArrow: 00256 if ( orientation() == Qt::Vertical ) { 00257 d->arrowPE = QStyle::PE_IndicatorArrowRight; 00258 } else { 00259 d->arrowPE = QStyle::PE_IndicatorArrowUp; 00260 } 00261 break; 00262 00263 case Qt::NoArrow: 00264 break; 00265 } 00266 } 00267 00268 Qt::ArrowType KSelector::arrowDirection() const 00269 { 00270 switch ( d->arrowPE ) { 00271 case QStyle::PE_IndicatorArrowUp: 00272 return Qt::UpArrow; 00273 break; 00274 case QStyle::PE_IndicatorArrowDown: 00275 return Qt::DownArrow; 00276 break; 00277 case QStyle::PE_IndicatorArrowRight: 00278 return Qt::RightArrow; 00279 break; 00280 case QStyle::PE_IndicatorArrowLeft: 00281 default: 00282 return Qt::LeftArrow; 00283 break; 00284 } 00285 } 00286 00287 void KSelector::drawContents( QPainter * ) 00288 {} 00289 00290 void KSelector::drawArrow( QPainter *painter, const QPoint &pos ) 00291 { 00292 painter->setPen( QPen() ); 00293 painter->setBrush( QBrush( palette().color(QPalette::ButtonText) ) ); 00294 00295 QStyleOption o; 00296 00297 if ( orientation() == Qt::Vertical ) { 00298 o.rect = QRect( pos.x(), pos.y() - ARROWSIZE / 2, 00299 ARROWSIZE, ARROWSIZE ); 00300 } else { 00301 o.rect = QRect( pos.x() - ARROWSIZE / 2, pos.y(), 00302 ARROWSIZE, ARROWSIZE ); 00303 00304 } 00305 style()->drawPrimitive( d->arrowPE, &o, painter, this ); 00306 } 00307 00308 //---------------------------------------------------------------------------- 00309 00310 KGradientSelector::KGradientSelector( QWidget *parent ) 00311 : KSelector( parent ), d(new KGradientSelectorPrivate(this)) 00312 { 00313 } 00314 00315 00316 KGradientSelector::KGradientSelector( Qt::Orientation o, QWidget *parent ) 00317 : KSelector( o, parent ), d(new KGradientSelectorPrivate(this)) 00318 { 00319 } 00320 00321 00322 KGradientSelector::~KGradientSelector() 00323 { 00324 delete d; 00325 } 00326 00327 00328 void KGradientSelector::drawContents( QPainter *painter ) 00329 { 00330 d->gradient.setStart(contentsRect().topLeft()); 00331 if (orientation() == Qt::Vertical) { 00332 d->gradient.setFinalStop(contentsRect().bottomLeft()); 00333 } else { 00334 d->gradient.setFinalStop(contentsRect().topRight()); 00335 } 00336 QBrush gradientBrush(d->gradient); 00337 00338 fillOpaqueRect(painter, contentsRect(), gradientBrush); 00339 00340 if ( orientation() == Qt::Vertical ) 00341 { 00342 int yPos = contentsRect().top() + painter->fontMetrics().ascent() + 2; 00343 int xPos = contentsRect().left() + (contentsRect().width() - 00344 painter->fontMetrics().width( d->text2 )) / 2; 00345 QPen pen( qGray(firstColor().rgb()) > 180 ? Qt::black : Qt::white ); 00346 painter->setPen( pen ); 00347 painter->drawText( xPos, yPos, d->text2 ); 00348 00349 yPos = contentsRect().bottom() - painter->fontMetrics().descent() - 2; 00350 xPos = contentsRect().left() + (contentsRect().width() - 00351 painter->fontMetrics().width( d->text1 )) / 2; 00352 pen.setColor( qGray(secondColor().rgb()) > 180 ? Qt::black : Qt::white ); 00353 painter->setPen( pen ); 00354 painter->drawText( xPos, yPos, d->text1 ); 00355 } 00356 else 00357 { 00358 int yPos = contentsRect().bottom()-painter->fontMetrics().descent()-2; 00359 00360 QPen pen( qGray(firstColor().rgb()) > 180 ? Qt::black : Qt::white ); 00361 painter->setPen( pen ); 00362 painter->drawText( contentsRect().left() + 2, yPos, d->text1 ); 00363 00364 pen.setColor( qGray(secondColor().rgb()) > 180 ? Qt::black : Qt::white ); 00365 painter->setPen( pen ); 00366 painter->drawText( contentsRect().right() - 00367 painter->fontMetrics().width( d->text2 ) - 2, yPos, d->text2 ); 00368 } 00369 } 00370 00371 QSize KGradientSelector::minimumSize() const 00372 { 00373 return sizeHint(); 00374 } 00375 00376 void KGradientSelector::setStops( const QGradientStops &stops ) 00377 { 00378 d->gradient.setStops(stops); 00379 update(); 00380 } 00381 00382 QGradientStops KGradientSelector::stops() const 00383 { 00384 return d->gradient.stops(); 00385 } 00386 00387 void KGradientSelector::setColors( const QColor &col1, const QColor &col2 ) 00388 { 00389 d->gradient.setColorAt(0.0, col1); 00390 d->gradient.setColorAt(1.0, col2); 00391 update(); 00392 } 00393 00394 void KGradientSelector::setText( const QString &t1, const QString &t2 ) 00395 { 00396 d->text1 = t1; 00397 d->text2 = t2; 00398 update(); 00399 } 00400 00401 void KGradientSelector::setFirstColor( const QColor &col ) 00402 { 00403 d->gradient.setColorAt(0.0, col); 00404 update(); 00405 } 00406 00407 void KGradientSelector::setSecondColor( const QColor &col ) 00408 { 00409 d->gradient.setColorAt(1.0, col); 00410 update(); 00411 } 00412 00413 void KGradientSelector::setFirstText( const QString &t ) 00414 { 00415 d->text1 = t; 00416 update(); 00417 } 00418 00419 void KGradientSelector::setSecondText( const QString &t ) 00420 { 00421 d->text2 = t; 00422 update(); 00423 } 00424 00425 QColor KGradientSelector::firstColor() const 00426 { 00427 return d->gradient.stops().first().second; 00428 } 00429 00430 QColor KGradientSelector::secondColor() const 00431 { 00432 return d->gradient.stops().last().second; 00433 } 00434 00435 QString KGradientSelector::firstText() const 00436 { 00437 return d->text1; 00438 } 00439 00440 QString KGradientSelector::secondText() const 00441 { 00442 return d->text2; 00443 } 00444 00445 #include "kselector.moc"
KDE 4.6 API Reference