QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscolorbutton.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscolorbutton.cpp - Button which displays a color
3  --------------------------------------
4  Date : 12-Dec-2006
5  Copyright : (C) 2006 by Tom Elwertowski
6  Email : telwertowski at users dot sourceforge dot net
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgscolorbutton.h"
17 #include "qgscolordialog.h"
18 #include "qgsapplication.h"
19 #include "qgslogger.h"
20 
21 #include <QPainter>
22 #include <QSettings>
23 #include <QTemporaryFile>
24 
41 QgsColorButton::QgsColorButton( QWidget *parent, QString cdt, QColorDialog::ColorDialogOptions cdo )
42  : QPushButton( parent )
43  , mColorDialogTitle( cdt.isEmpty() ? tr( "Select Color" ) : cdt )
44  , mColor( Qt::black )
45  , mColorDialogOptions( cdo )
46  , mAcceptLiveUpdates( true )
47  , mTempPNG( NULL )
48 {
49  connect( this, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) );
50 }
51 
53 {
54  if ( mTempPNG.exists() )
55  mTempPNG.remove();
56 }
57 
59 {
60  static QPixmap transpBkgrd;
61 
62  if ( transpBkgrd.isNull() )
63  transpBkgrd = QgsApplication::getThemePixmap( "/transp-background_8x8.png" );
64 
65  return transpBkgrd;
66 }
67 
69 {
70  //QgsDebugMsg( "entered" );
71  QColor newColor;
72 #if QT_VERSION >= 0x040500
73  QSettings settings;
74  if ( mAcceptLiveUpdates && settings.value( "/qgis/live_color_dialogs", false ).toBool() )
75  {
77  color(), this, SLOT( setValidColor( const QColor& ) ),
78  this->parentWidget(), mColorDialogTitle, mColorDialogOptions );
79  }
80  else
81  {
82  newColor = QColorDialog::getColor( color(), this->parentWidget(), mColorDialogTitle, mColorDialogOptions );
83  }
84 #else
85  newColor = QColorDialog::getColor( color(), this->parentWidget() );
86 #endif
87  setValidColor( newColor );
88 
89  // reactivate button's window
90  activateWindow();
91 }
92 
93 void QgsColorButton::setValidColor( const QColor& newColor )
94 {
95  if ( newColor.isValid() )
96  {
97  setColor( newColor );
98  }
99 }
100 
102 {
103  if ( e->type() == QEvent::EnabledChange )
104  {
106  }
108 }
109 
110 #if 0 // causes too many cyclical updates, but may be needed on some platforms
111 void QgsColorButton::paintEvent( QPaintEvent* e )
112 {
113  QPushButton::paintEvent( e );
114 
115  if ( !mBackgroundSet )
116  {
118  }
119 }
120 #endif
121 
122 void QgsColorButton::showEvent( QShowEvent* e )
123 {
126 }
127 
128 void QgsColorButton::setColor( const QColor &color )
129 {
130  if ( !color.isValid() )
131  {
132  return;
133  }
134  QColor oldColor = mColor;
135  mColor = color;
136 
137  if ( oldColor != mColor )
138  {
140  if ( isEnabled() )
141  {
142  // TODO: May be beneficial to have the option to set color without emitting this signal.
143  // Now done by blockSignals( bool ) where button is used
144  emit colorChanged( mColor );
145  }
146  }
147 }
148 
150 {
151  if ( !text().isEmpty() )
152  {
153  // generate icon pixmap for regular pushbutton
154  setFlat( false );
155 
156  QPixmap pixmap;
157  pixmap = QPixmap( iconSize() );
158  pixmap.fill( QColor( 0, 0, 0, 0 ) );
159 
160  int iconW = iconSize().width();
161  int iconH = iconSize().height();
162  QRect rect( 0, 0, iconW, iconH );
163 
164  // QPainterPath::addRoundRect has flaws, draw chamfered corners instead
165  QPainterPath roundRect;
166  int chamfer = 3;
167  int inset = 1;
168  roundRect.moveTo( chamfer, inset );
169  roundRect.lineTo( iconW - chamfer, inset );
170  roundRect.lineTo( iconW - inset, chamfer );
171  roundRect.lineTo( iconW - inset, iconH - chamfer );
172  roundRect.lineTo( iconW - chamfer, iconH - inset );
173  roundRect.lineTo( chamfer, iconH - inset );
174  roundRect.lineTo( inset, iconH - chamfer );
175  roundRect.lineTo( inset, chamfer );
176  roundRect.closeSubpath();
177 
178  QPainter p;
179  p.begin( &pixmap );
180  p.setRenderHint( QPainter::Antialiasing );
181  p.setClipPath( roundRect );
182  p.setPen( Qt::NoPen );
183  if ( mColor.alpha() < 255 )
184  {
185  p.drawTiledPixmap( rect, transpBkgrd() );
186  }
187  p.setBrush( mColor );
188  p.drawRect( rect );
189  p.end();
190 
191  // set this pixmap as icon
192  setIcon( QIcon( pixmap ) );
193  }
194  else
195  {
196  // generate temp background image file with checkerboard canvas to be used via stylesheet
197 
198  // set flat, or inline spacing (widget margins) needs to be manually calculated and set
199  setFlat( true );
200 
201  bool useAlpha = ( mColorDialogOptions & QColorDialog::ShowAlphaChannel );
202 
203  // in case margins need to be adjusted
204  QString margin = QString( "%1px %2px %3px %4px" ).arg( 0 ).arg( 0 ).arg( 0 ).arg( 0 );
205 
206  //QgsDebugMsg( QString( "%1 margin: %2" ).arg( objectName() ).arg( margin ) );
207 
208  QString bkgrd = QString( " background-color: rgba(%1,%2,%3,%4);" )
209  .arg( mColor.red() )
210  .arg( mColor.green() )
211  .arg( mColor.blue() )
212  .arg( useAlpha ? mColor.alpha() : 255 );
213 
214  if ( useAlpha && mColor.alpha() < 255 )
215  {
216  QPixmap pixmap = transpBkgrd();
217  QRect rect( 0, 0, pixmap.width(), pixmap.height() );
218 
219  QPainter p;
220  p.begin( &pixmap );
221  p.setRenderHint( QPainter::Antialiasing );
222  p.setPen( Qt::NoPen );
223  p.setBrush( mColor );
224  p.drawRect( rect );
225  p.end();
226 
227  if ( mTempPNG.open() )
228  {
229  mTempPNG.setAutoRemove( false );
230  pixmap.save( mTempPNG.fileName(), "PNG" );
231  mTempPNG.close();
232  }
233 
234  bkgrd = QString( " background-image: url(%1);" ).arg( mTempPNG.fileName() );
235  }
236 
237  //QgsDebugMsg( QString( "%1" ).arg( bkgrd ) );
238 
239  // TODO: get OS-style focus color and switch border to that color when button in focus
240  setStyleSheet( QString( "QgsColorButton{"
241  " %1"
242  " background-position: top left;"
243  " background-origin: content;"
244  " background-clip: content;"
245  " padding: 2px;"
246  " margin: %2;"
247  " outline: none;"
248  " border-style: %4;"
249  " border-width: 1px;"
250  " border-color: rgb(%3,%3,%3);"
251  " border-radius: 3px;} "
252  "QgsColorButton:pressed{"
253  " %1"
254  " background-position: top left;"
255  " background-origin: content;"
256  " background-clip: content;"
257  " padding: 1px;"
258  " margin: %2;"
259  " outline: none;"
260  " border-style: inset;"
261  " border-width: 2px;"
262  " border-color: rgb(128,128,128);"
263  " border-radius: 4px;} " )
264  .arg( bkgrd )
265  .arg( margin )
266  .arg( isEnabled() ? "128" : "110" )
267  .arg( isEnabled() ? "outset" : "dotted" ) );
268  }
269 }
270 
271 QColor QgsColorButton::color() const
272 {
273  return mColor;
274 }
275 
276 void QgsColorButton::setColorDialogOptions( QColorDialog::ColorDialogOptions cdo )
277 {
278  mColorDialogOptions = cdo;
279 }
280 
281 QColorDialog::ColorDialogOptions QgsColorButton::colorDialogOptions()
282 {
283  return mColorDialogOptions;
284 }
285 
287 {
288  mColorDialogTitle = cdt;
289 }
290 
292 {
293  return mColorDialogTitle;
294 }