QGIS API Documentation  2.2.0-Valmiera
 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  , mColorSet( false )
49 {
50  connect( this, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) );
51 }
52 
54 {
55  if ( mTempPNG.exists() )
56  mTempPNG.remove();
57 }
58 
60 {
61  static QPixmap transpBkgrd;
62 
63  if ( transpBkgrd.isNull() )
64  transpBkgrd = QgsApplication::getThemePixmap( "/transp-background_8x8.png" );
65 
66  return transpBkgrd;
67 }
68 
70 {
71  //QgsDebugMsg( "entered" );
72  QColor newColor;
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  setValidColor( newColor );
85 
86  // reactivate button's window
87  activateWindow();
88 }
89 
90 void QgsColorButton::setValidColor( const QColor& newColor )
91 {
92  if ( newColor.isValid() )
93  {
94  setColor( newColor );
95  }
96 }
97 
98 void QgsColorButton::changeEvent( QEvent* e )
99 {
100  if ( e->type() == QEvent::EnabledChange )
101  {
103  }
105 }
106 
107 #if 0 // causes too many cyclical updates, but may be needed on some platforms
108 void QgsColorButton::paintEvent( QPaintEvent* e )
109 {
110  QPushButton::paintEvent( e );
111 
112  if ( !mBackgroundSet )
113  {
115  }
116 }
117 #endif
118 
119 void QgsColorButton::showEvent( QShowEvent* e )
120 {
123 }
124 
125 void QgsColorButton::setColor( const QColor &color )
126 {
127  if ( !color.isValid() )
128  {
129  return;
130  }
131  QColor oldColor = mColor;
132  mColor = color;
133 
134  // handle when initially set color is same as default (Qt::black); consider it a color change
135  if ( oldColor != mColor || ( mColor == QColor( Qt::black ) && !mColorSet ) )
136  {
138  if ( isEnabled() )
139  {
140  // TODO: May be beneficial to have the option to set color without emitting this signal.
141  // Now done by blockSignals( bool ) where button is used
142  emit colorChanged( mColor );
143  }
144  }
145  mColorSet = true;
146 }
147 
149 {
150  if ( !text().isEmpty() )
151  {
152  // generate icon pixmap for regular pushbutton
153  setFlat( false );
154 
155  QPixmap pixmap;
156  pixmap = QPixmap( iconSize() );
157  pixmap.fill( QColor( 0, 0, 0, 0 ) );
158 
159  int iconW = iconSize().width();
160  int iconH = iconSize().height();
161  QRect rect( 0, 0, iconW, iconH );
162 
163  // QPainterPath::addRoundRect has flaws, draw chamfered corners instead
164  QPainterPath roundRect;
165  int chamfer = 3;
166  int inset = 1;
167  roundRect.moveTo( chamfer, inset );
168  roundRect.lineTo( iconW - chamfer, inset );
169  roundRect.lineTo( iconW - inset, chamfer );
170  roundRect.lineTo( iconW - inset, iconH - chamfer );
171  roundRect.lineTo( iconW - chamfer, iconH - inset );
172  roundRect.lineTo( chamfer, iconH - inset );
173  roundRect.lineTo( inset, iconH - chamfer );
174  roundRect.lineTo( inset, chamfer );
175  roundRect.closeSubpath();
176 
177  QPainter p;
178  p.begin( &pixmap );
179  p.setRenderHint( QPainter::Antialiasing );
180  p.setClipPath( roundRect );
181  p.setPen( Qt::NoPen );
182  if ( mColor.alpha() < 255 )
183  {
184  p.drawTiledPixmap( rect, transpBkgrd() );
185  }
186  p.setBrush( mColor );
187  p.drawRect( rect );
188  p.end();
189 
190  // set this pixmap as icon
191  setIcon( QIcon( pixmap ) );
192  }
193  else
194  {
195  // generate temp background image file with checkerboard canvas to be used via stylesheet
196 
197  // set flat, or inline spacing (widget margins) needs to be manually calculated and set
198  setFlat( true );
199 
200  bool useAlpha = ( mColorDialogOptions & QColorDialog::ShowAlphaChannel );
201 
202  // in case margins need to be adjusted
203  QString margin = QString( "%1px %2px %3px %4px" ).arg( 0 ).arg( 0 ).arg( 0 ).arg( 0 );
204 
205  //QgsDebugMsg( QString( "%1 margin: %2" ).arg( objectName() ).arg( margin ) );
206 
207  QString bkgrd = QString( " background-color: rgba(%1,%2,%3,%4);" )
208  .arg( mColor.red() )
209  .arg( mColor.green() )
210  .arg( mColor.blue() )
211  .arg( useAlpha ? mColor.alpha() : 255 );
212 
213  if ( useAlpha && mColor.alpha() < 255 )
214  {
215  QPixmap pixmap = transpBkgrd();
216  QRect rect( 0, 0, pixmap.width(), pixmap.height() );
217 
218  QPainter p;
219  p.begin( &pixmap );
220  p.setRenderHint( QPainter::Antialiasing );
221  p.setPen( Qt::NoPen );
222  p.setBrush( mColor );
223  p.drawRect( rect );
224  p.end();
225 
226  if ( mTempPNG.open() )
227  {
228  mTempPNG.setAutoRemove( false );
229  pixmap.save( mTempPNG.fileName(), "PNG" );
230  mTempPNG.close();
231  }
232 
233  bkgrd = QString( " background-image: url(%1);" ).arg( mTempPNG.fileName() );
234  }
235 
236  //QgsDebugMsg( QString( "%1" ).arg( bkgrd ) );
237 
238  // TODO: get OS-style focus color and switch border to that color when button in focus
239  setStyleSheet( QString( "QgsColorButton{"
240  " %1"
241  " background-position: top left;"
242  " background-origin: content;"
243  " background-clip: content;"
244  " padding: 2px;"
245  " margin: %2;"
246  " outline: none;"
247  " border-style: %4;"
248  " border-width: 1px;"
249  " border-color: rgb(%3,%3,%3);"
250  " border-radius: 3px;} "
251  "QgsColorButton:pressed{"
252  " %1"
253  " background-position: top left;"
254  " background-origin: content;"
255  " background-clip: content;"
256  " padding: 1px;"
257  " margin: %2;"
258  " outline: none;"
259  " border-style: inset;"
260  " border-width: 2px;"
261  " border-color: rgb(128,128,128);"
262  " border-radius: 4px;} " )
263  .arg( bkgrd )
264  .arg( margin )
265  .arg( isEnabled() ? "128" : "110" )
266  .arg( isEnabled() ? "outset" : "dotted" ) );
267  }
268 }
269 
270 QColor QgsColorButton::color() const
271 {
272  return mColor;
273 }
274 
275 void QgsColorButton::setColorDialogOptions( QColorDialog::ColorDialogOptions cdo )
276 {
277  mColorDialogOptions = cdo;
278 }
279 
280 QColorDialog::ColorDialogOptions QgsColorButton::colorDialogOptions()
281 {
282  return mColorDialogOptions;
283 }
284 
286 {
287  mColorDialogTitle = cdt;
288 }
289 
291 {
292  return mColorDialogTitle;
293 }