QGIS API Documentation  master-3f58142
src/gui/qgscolorbutton.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002     qgscolorbutton.cpp - Button which displays a color
00003      --------------------------------------
00004     Date                 : 12-Dec-2006
00005     Copyright            : (C) 2006 by Tom Elwertowski
00006     Email                : telwertowski at users dot sourceforge dot net
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 #include "qgscolorbutton.h"
00017 #include "qgscolordialog.h"
00018 #include "qgsapplication.h"
00019 #include "qgslogger.h"
00020 
00021 #include <QPainter>
00022 #include <QSettings>
00023 #include <QTemporaryFile>
00024 
00041 QgsColorButton::QgsColorButton( QWidget *parent, QString cdt, QColorDialog::ColorDialogOptions cdo )
00042     : QPushButton( parent )
00043     , mColorDialogTitle( cdt.isEmpty() ? tr( "Select Color" ) : cdt )
00044     , mColor( Qt::black )
00045     , mColorDialogOptions( cdo )
00046     , mAcceptLiveUpdates( true )
00047     , mTempPNG( NULL )
00048 {
00049   connect( this, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) );
00050 }
00051 
00052 QgsColorButton::~QgsColorButton()
00053 {
00054   if ( mTempPNG.exists() )
00055     mTempPNG.remove();
00056 }
00057 
00058 const QPixmap& QgsColorButton::transpBkgrd()
00059 {
00060   static QPixmap transpBkgrd;
00061 
00062   if ( transpBkgrd.isNull() )
00063     transpBkgrd = QgsApplication::getThemePixmap( "/transp-background_8x8.png" );
00064 
00065   return transpBkgrd;
00066 }
00067 
00068 void QgsColorButton::onButtonClicked()
00069 {
00070   //QgsDebugMsg( "entered" );
00071   QColor newColor;
00072 #if QT_VERSION >= 0x040500
00073   QSettings settings;
00074   if ( mAcceptLiveUpdates && settings.value( "/qgis/live_color_dialogs", false ).toBool() )
00075   {
00076     newColor = QgsColorDialog::getLiveColor(
00077                  color(), this, SLOT( setValidColor( const QColor& ) ),
00078                  this->parentWidget(), mColorDialogTitle, mColorDialogOptions );
00079   }
00080   else
00081   {
00082     newColor = QColorDialog::getColor( color(), this->parentWidget(), mColorDialogTitle, mColorDialogOptions );
00083   }
00084 #else
00085   newColor = QColorDialog::getColor( color(), this->parentWidget() );
00086 #endif
00087   setValidColor( newColor );
00088 
00089   // reactivate button's window
00090   activateWindow();
00091 }
00092 
00093 void QgsColorButton::setValidColor( const QColor& newColor )
00094 {
00095   if ( newColor.isValid() )
00096   {
00097     setColor( newColor );
00098   }
00099 }
00100 
00101 void QgsColorButton::changeEvent( QEvent* e )
00102 {
00103   if ( e->type() == QEvent::EnabledChange )
00104   {
00105     setButtonBackground();
00106   }
00107   QPushButton::changeEvent( e );
00108 }
00109 
00110 #if 0 // causes too many cyclical updates, but may be needed on some platforms
00111 void QgsColorButton::paintEvent( QPaintEvent* e )
00112 {
00113   QPushButton::paintEvent( e );
00114 
00115   if ( !mBackgroundSet )
00116   {
00117     setButtonBackground();
00118   }
00119 }
00120 #endif
00121 
00122 void QgsColorButton::showEvent( QShowEvent* e )
00123 {
00124   setButtonBackground();
00125   QPushButton::showEvent( e );
00126 }
00127 
00128 void QgsColorButton::setColor( const QColor &color )
00129 {
00130   if ( !color.isValid() )
00131   {
00132     return;
00133   }
00134   QColor oldColor = mColor;
00135   mColor = color;
00136 
00137   if ( oldColor != mColor )
00138   {
00139     setButtonBackground();
00140     if ( isEnabled() )
00141     {
00142       // TODO: May be beneficial to have the option to set color without emitting this signal.
00143       //       Now done by blockSignals( bool ) where button is used
00144       emit colorChanged( mColor );
00145     }
00146   }
00147 }
00148 
00149 void QgsColorButton::setButtonBackground()
00150 {
00151   if ( !text().isEmpty() )
00152   {
00153     // generate icon pixmap for regular pushbutton
00154     setFlat( false );
00155 
00156     QPixmap pixmap;
00157     pixmap = QPixmap( iconSize() );
00158     pixmap.fill( QColor( 0, 0, 0, 0 ) );
00159 
00160     int iconW = iconSize().width();
00161     int iconH = iconSize().height();
00162     QRect rect( 0, 0, iconW, iconH );
00163 
00164     // QPainterPath::addRoundRect has flaws, draw chamfered corners instead
00165     QPainterPath roundRect;
00166     int chamfer = 3;
00167     int inset = 1;
00168     roundRect.moveTo( chamfer, inset );
00169     roundRect.lineTo( iconW - chamfer, inset );
00170     roundRect.lineTo( iconW - inset, chamfer );
00171     roundRect.lineTo( iconW - inset, iconH - chamfer );
00172     roundRect.lineTo( iconW - chamfer, iconH - inset );
00173     roundRect.lineTo( chamfer, iconH - inset );
00174     roundRect.lineTo( inset, iconH - chamfer );
00175     roundRect.lineTo( inset, chamfer );
00176     roundRect.closeSubpath();
00177 
00178     QPainter p;
00179     p.begin( &pixmap );
00180     p.setRenderHint( QPainter::Antialiasing );
00181     p.setClipPath( roundRect );
00182     p.setPen( Qt::NoPen );
00183     if ( mColor.alpha() < 255 )
00184     {
00185       p.drawTiledPixmap( rect, transpBkgrd() );
00186     }
00187     p.setBrush( mColor );
00188     p.drawRect( rect );
00189     p.end();
00190 
00191     // set this pixmap as icon
00192     setIcon( QIcon( pixmap ) );
00193   }
00194   else
00195   {
00196     // generate temp background image file with checkerboard canvas to be used via stylesheet
00197 
00198     // set flat, or inline spacing (widget margins) needs to be manually calculated and set
00199     setFlat( true );
00200 
00201     bool useAlpha = ( mColorDialogOptions & QColorDialog::ShowAlphaChannel );
00202 
00203     // in case margins need to be adjusted
00204     QString margin = QString( "%1px %2px %3px %4px" ).arg( 0 ).arg( 0 ).arg( 0 ).arg( 0 );
00205 
00206     //QgsDebugMsg( QString( "%1 margin: %2" ).arg( objectName() ).arg( margin ) );
00207 
00208     QString bkgrd = QString( " background-color: rgba(%1,%2,%3,%4);" )
00209                     .arg( mColor.red() )
00210                     .arg( mColor.green() )
00211                     .arg( mColor.blue() )
00212                     .arg( useAlpha ? mColor.alpha() : 255 );
00213 
00214     if ( useAlpha && mColor.alpha() < 255 )
00215     {
00216       QPixmap pixmap = transpBkgrd();
00217       QRect rect( 0, 0, pixmap.width(), pixmap.height() );
00218 
00219       QPainter p;
00220       p.begin( &pixmap );
00221       p.setRenderHint( QPainter::Antialiasing );
00222       p.setPen( Qt::NoPen );
00223       p.setBrush( mColor );
00224       p.drawRect( rect );
00225       p.end();
00226 
00227       if ( mTempPNG.open() )
00228       {
00229         mTempPNG.setAutoRemove( false );
00230         pixmap.save( mTempPNG.fileName(), "PNG" );
00231         mTempPNG.close();
00232       }
00233 
00234       bkgrd = QString( " background-image: url(%1);" ).arg( mTempPNG.fileName() );
00235     }
00236 
00237     //QgsDebugMsg( QString( "%1" ).arg( bkgrd ) );
00238 
00239     // TODO: get OS-style focus color and switch border to that color when button in focus
00240     setStyleSheet( QString( "QgsColorButton{"
00241                             " %1"
00242                             " background-position: top left;"
00243                             " background-origin: content;"
00244                             " background-clip: content;"
00245                             " padding: 2px;"
00246                             " margin: %2;"
00247                             " outline: none;"
00248                             " border-style: %4;"
00249                             " border-width: 1px;"
00250                             " border-color: rgb(%3,%3,%3);"
00251                             " border-radius: 3px;} "
00252                             "QgsColorButton:pressed{"
00253                             " %1"
00254                             " background-position: top left;"
00255                             " background-origin: content;"
00256                             " background-clip: content;"
00257                             " padding: 1px;"
00258                             " margin: %2;"
00259                             " outline: none;"
00260                             " border-style: inset;"
00261                             " border-width: 2px;"
00262                             " border-color: rgb(128,128,128);"
00263                             " border-radius: 4px;} " )
00264                    .arg( bkgrd )
00265                    .arg( margin )
00266                    .arg( isEnabled() ? "128" : "110" )
00267                    .arg( isEnabled() ? "outset" : "dotted" ) );
00268   }
00269 }
00270 
00271 QColor QgsColorButton::color() const
00272 {
00273   return mColor;
00274 }
00275 
00276 void QgsColorButton::setColorDialogOptions( QColorDialog::ColorDialogOptions cdo )
00277 {
00278   mColorDialogOptions = cdo;
00279 }
00280 
00281 QColorDialog::ColorDialogOptions QgsColorButton::colorDialogOptions()
00282 {
00283   return mColorDialogOptions;
00284 }
00285 
00286 void QgsColorButton::setColorDialogTitle( QString cdt )
00287 {
00288   mColorDialogTitle = cdt;
00289 }
00290 
00291 QString QgsColorButton::colorDialogTitle()
00292 {
00293   return mColorDialogTitle;
00294 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines