QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgscolordialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscolordialog.cpp - color selection dialog
3 
4  ---------------------
5  begin : March 19, 2013
6  copyright : (C) 2013 by Larry Shaffer
7  email : larrys at dakcarto dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgscolordialog.h"
18 #include "qgscolorscheme.h"
19 #include "qgscolorschemeregistry.h"
20 #include "qgssymbollayerv2utils.h"
21 #include "qgscursors.h"
22 #include "qgsapplication.h"
23 #include <QSettings>
24 #include <QPushButton>
25 #include <QMenu>
26 #include <QToolButton>
27 #include <QFileDialog>
28 #include <QMessageBox>
29 #include <QDesktopWidget>
30 #include <QMouseEvent>
31 #include <QInputDialog>
32 
34 {
35 }
36 
38 {
39 }
40 
41 QColor QgsColorDialog::getLiveColor( const QColor& initialColor, QObject* updateObject, const char* updateSlot,
42  QWidget* parent,
43  const QString& title,
44  QColorDialog::ColorDialogOptions options )
45 {
46  QColor returnColor( initialColor );
47  QColorDialog* liveDialog = new QColorDialog( initialColor, parent );
48  liveDialog->setWindowTitle( title.isEmpty() ? tr( "Select Color" ) : title );
49  liveDialog->setOptions( options );
50 
51  connect( liveDialog, SIGNAL( currentColorChanged( const QColor& ) ),
52  updateObject, updateSlot );
53 
54  if ( liveDialog->exec() )
55  {
56  returnColor = liveDialog->currentColor();
57  }
58  delete liveDialog;
59  liveDialog = 0;
60 
61  return returnColor;
62 }
63 
64 
65 //
66 // QgsColorDialogV2
67 //
68 
69 QgsColorDialogV2::QgsColorDialogV2( QWidget *parent, Qt::WindowFlags fl, const QColor& color )
70  : QDialog( parent, fl )
71  , mPreviousColor( color )
72  , mAllowAlpha( true )
73  , mLastCustomColorIndex( 0 )
74  , mPickingColor( false )
75 {
76  setupUi( this );
77 
78  QSettings settings;
79  restoreGeometry( settings.value( "/Windows/ColorDialog/geometry" ).toByteArray() );
80 
81  mSchemeList->header()->hide();
82  mSchemeList->setColumnWidth( 0, 44 );
83 
84  //get schemes with ShowInColorDialog set
85  refreshSchemeComboBox();
86  QList<QgsColorScheme *> schemeList = QgsColorSchemeRegistry::instance()->schemes( QgsColorScheme::ShowInColorDialog );
87 
88  //choose a reasonable starting scheme
89  int activeScheme = settings.value( "/Windows/ColorDialog/activeScheme", 0 ).toInt();
90  activeScheme = activeScheme >= mSchemeComboBox->count() ? 0 : activeScheme;
91 
92  mSchemeList->setScheme( schemeList.at( activeScheme ) );
93  mSchemeComboBox->setCurrentIndex( activeScheme );
94  mActionImportColors->setEnabled( schemeList.at( activeScheme )->isEditable() );
95  mActionPasteColors->setEnabled( schemeList.at( activeScheme )->isEditable() );
96  mAddColorToSchemeButton->setEnabled( schemeList.at( activeScheme )->isEditable() );
97  mRemoveColorsFromSchemeButton->setEnabled( schemeList.at( activeScheme )->isEditable() );
98  QgsUserColorScheme* userScheme = dynamic_cast<QgsUserColorScheme*>( schemeList.at( activeScheme ) );
99  mActionRemovePalette->setEnabled( userScheme ? true : false );
100 
101  //listen out for selection changes in list, so we can enable/disable the copy colors option
102  connect( mSchemeList->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SLOT( listSelectionChanged( QItemSelection, QItemSelection ) ) );
103  //copy action defaults to disabled
104  mActionCopyColors->setEnabled( false );
105 
106  connect( mActionCopyColors, SIGNAL( triggered() ), mSchemeList, SLOT( copyColors() ) );
107  connect( mActionPasteColors, SIGNAL( triggered() ), mSchemeList, SLOT( pasteColors() ) );
108  connect( mActionExportColors, SIGNAL( triggered() ), this, SLOT( exportColors() ) );
109  connect( mActionImportColors, SIGNAL( triggered() ), this, SLOT( importColors() ) );
110  connect( mActionImportPalette, SIGNAL( triggered() ), this, SLOT( importPalette() ) );
111  connect( mActionRemovePalette, SIGNAL( triggered() ), this, SLOT( removePalette() ) );
112  connect( mActionNewPalette, SIGNAL( triggered() ), this, SLOT( newPalette() ) );
113  connect( mRemoveColorsFromSchemeButton, SIGNAL( clicked() ), mSchemeList, SLOT( removeSelection() ) );
114 
115  QMenu* schemeMenu = new QMenu( mSchemeToolButton );
116  schemeMenu->addAction( mActionCopyColors );
117  schemeMenu->addAction( mActionPasteColors );
118  schemeMenu->addSeparator();
119  schemeMenu->addAction( mActionImportColors );
120  schemeMenu->addAction( mActionExportColors );
121  schemeMenu->addSeparator();
122  schemeMenu->addAction( mActionNewPalette );
123  schemeMenu->addAction( mActionImportPalette );
124  schemeMenu->addAction( mActionRemovePalette );
125  mSchemeToolButton->setMenu( schemeMenu );
126 
127  connect( mSchemeComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( schemeIndexChanged( int ) ) );
128  connect( mSchemeList, SIGNAL( colorSelected( QColor ) ), this, SLOT( setColor( QColor ) ) );
129 
130  if ( mPreviousColor.isValid() )
131  {
132  QPushButton* resetButton = new QPushButton( tr( "Reset" ) );
133  mButtonBox->addButton( resetButton, QDialogButtonBox::ResetRole );
134  }
135  else
136  {
137  mOldColorLabel->hide();
138  }
139 
140  mVerticalRamp->setOrientation( QgsColorRampWidget::Vertical );
141  mVerticalRamp->setInteriorMargin( 2 );
142  mVerticalRamp->setShowFrame( true );
143 
144  mRedSlider->setComponent( QgsColorWidget::Red );
145  mGreenSlider->setComponent( QgsColorWidget::Green );
146  mBlueSlider->setComponent( QgsColorWidget::Blue );
147  mHueSlider->setComponent( QgsColorWidget::Hue );
148  mSaturationSlider->setComponent( QgsColorWidget::Saturation );
149  mValueSlider->setComponent( QgsColorWidget::Value );
150  mAlphaSlider->setComponent( QgsColorWidget::Alpha );
151 
152  mSwatchButton1->setShowMenu( false );
153  mSwatchButton1->setBehaviour( QgsColorButtonV2::SignalOnly );
154  mSwatchButton2->setShowMenu( false );
155  mSwatchButton2->setBehaviour( QgsColorButtonV2::SignalOnly );
156  mSwatchButton3->setShowMenu( false );
157  mSwatchButton3->setBehaviour( QgsColorButtonV2::SignalOnly );
158  mSwatchButton4->setShowMenu( false );
159  mSwatchButton4->setBehaviour( QgsColorButtonV2::SignalOnly );
160  mSwatchButton5->setShowMenu( false );
161  mSwatchButton5->setBehaviour( QgsColorButtonV2::SignalOnly );
162  mSwatchButton6->setShowMenu( false );
163  mSwatchButton6->setBehaviour( QgsColorButtonV2::SignalOnly );
164  mSwatchButton7->setShowMenu( false );
165  mSwatchButton7->setBehaviour( QgsColorButtonV2::SignalOnly );
166  mSwatchButton8->setShowMenu( false );
167  mSwatchButton8->setBehaviour( QgsColorButtonV2::SignalOnly );
168  mSwatchButton9->setShowMenu( false );
169  mSwatchButton9->setBehaviour( QgsColorButtonV2::SignalOnly );
170  mSwatchButton10->setShowMenu( false );
171  mSwatchButton10->setBehaviour( QgsColorButtonV2::SignalOnly );
172  mSwatchButton11->setShowMenu( false );
173  mSwatchButton11->setBehaviour( QgsColorButtonV2::SignalOnly );
174  mSwatchButton12->setShowMenu( false );
175  mSwatchButton12->setBehaviour( QgsColorButtonV2::SignalOnly );
176  mSwatchButton13->setShowMenu( false );
177  mSwatchButton13->setBehaviour( QgsColorButtonV2::SignalOnly );
178  mSwatchButton14->setShowMenu( false );
179  mSwatchButton14->setBehaviour( QgsColorButtonV2::SignalOnly );
180  mSwatchButton15->setShowMenu( false );
181  mSwatchButton15->setBehaviour( QgsColorButtonV2::SignalOnly );
182  mSwatchButton16->setShowMenu( false );
183  mSwatchButton16->setBehaviour( QgsColorButtonV2::SignalOnly );
184  //restore custom colors
185  mSwatchButton1->setColor( settings.value( "/Windows/ColorDialog/customColor1", QVariant( QColor() ) ).value<QColor>() );
186  mSwatchButton2->setColor( settings.value( "/Windows/ColorDialog/customColor2", QVariant( QColor() ) ).value<QColor>() );
187  mSwatchButton3->setColor( settings.value( "/Windows/ColorDialog/customColor3", QVariant( QColor() ) ).value<QColor>() );
188  mSwatchButton4->setColor( settings.value( "/Windows/ColorDialog/customColor4", QVariant( QColor() ) ).value<QColor>() );
189  mSwatchButton5->setColor( settings.value( "/Windows/ColorDialog/customColor5", QVariant( QColor() ) ).value<QColor>() );
190  mSwatchButton6->setColor( settings.value( "/Windows/ColorDialog/customColor6", QVariant( QColor() ) ).value<QColor>() );
191  mSwatchButton7->setColor( settings.value( "/Windows/ColorDialog/customColor7", QVariant( QColor() ) ).value<QColor>() );
192  mSwatchButton8->setColor( settings.value( "/Windows/ColorDialog/customColor8", QVariant( QColor() ) ).value<QColor>() );
193  mSwatchButton9->setColor( settings.value( "/Windows/ColorDialog/customColor9", QVariant( QColor() ) ).value<QColor>() );
194  mSwatchButton10->setColor( settings.value( "/Windows/ColorDialog/customColor10", QVariant( QColor() ) ).value<QColor>() );
195  mSwatchButton11->setColor( settings.value( "/Windows/ColorDialog/customColor11", QVariant( QColor() ) ).value<QColor>() );
196  mSwatchButton12->setColor( settings.value( "/Windows/ColorDialog/customColor12", QVariant( QColor() ) ).value<QColor>() );
197  mSwatchButton13->setColor( settings.value( "/Windows/ColorDialog/customColor13", QVariant( QColor() ) ).value<QColor>() );
198  mSwatchButton14->setColor( settings.value( "/Windows/ColorDialog/customColor14", QVariant( QColor() ) ).value<QColor>() );
199  mSwatchButton15->setColor( settings.value( "/Windows/ColorDialog/customColor15", QVariant( QColor() ) ).value<QColor>() );
200  mSwatchButton16->setColor( settings.value( "/Windows/ColorDialog/customColor16", QVariant( QColor() ) ).value<QColor>() );
201 
202  //restore sample radius
203  mSpinBoxRadius->setValue( settings.value( "/Windows/ColorDialog/sampleRadius", 1 ).toInt() );
204  mSamplePreview->setColor( QColor() );
205 
206  if ( color.isValid() )
207  {
208  setColor( color );
209  mColorPreview->setColor2( color );
210  }
211 
212  //restore active component radio button
213  int activeRadio = settings.value( "/Windows/ColorDialog/activeComponent", 2 ).toInt();
214  switch ( activeRadio )
215  {
216  case 0:
217  mHueRadio->setChecked( true );
218  break;
219  case 1:
220  mSaturationRadio->setChecked( true );
221  break;
222  case 2:
223  mValueRadio->setChecked( true );
224  break;
225  case 3:
226  mRedRadio->setChecked( true );
227  break;
228  case 4:
229  mGreenRadio->setChecked( true );
230  break;
231  case 5:
232  mBlueRadio->setChecked( true );
233  break;
234  }
235  int currentTab = settings.value( "/Windows/ColorDialog/activeTab", 0 ).toInt();
236  mTabWidget->setCurrentIndex( currentTab );
237 
238 #ifdef Q_WS_MAC
239  //disable color picker tab for OSX, as it is impossible to grab the mouse under OSX
240  //see note for QWidget::grabMouse() re OSX Cocoa
241  //http://qt-project.org/doc/qt-4.8/qwidget.html#grabMouse
242  mTabWidget->removeTab( 3 );
243 #endif
244 
245  //setup connections
246  connect( mColorBox, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
247  connect( mColorWheel, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
248  connect( mColorText, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
249  connect( mVerticalRamp, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
250  connect( mRedSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
251  connect( mGreenSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
252  connect( mBlueSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
253  connect( mHueSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
254  connect( mValueSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
255  connect( mSaturationSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
256  connect( mAlphaSlider, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
257  connect( mColorPreview, SIGNAL( colorChanged( QColor ) ), this, SLOT( setColor( QColor ) ) );
258  connect( mSwatchButton1, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
259  connect( mSwatchButton2, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
260  connect( mSwatchButton3, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
261  connect( mSwatchButton4, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
262  connect( mSwatchButton5, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
263  connect( mSwatchButton6, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
264  connect( mSwatchButton7, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
265  connect( mSwatchButton8, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
266  connect( mSwatchButton9, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
267  connect( mSwatchButton10, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
268  connect( mSwatchButton11, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
269  connect( mSwatchButton12, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
270  connect( mSwatchButton13, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
271  connect( mSwatchButton14, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
272  connect( mSwatchButton15, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
273  connect( mSwatchButton16, SIGNAL( colorClicked( QColor ) ), this, SLOT( setColor( QColor ) ) );
274 }
275 
277 {
278 
279 }
280 
282 {
283  //all widgets should have the same color, so it shouldn't matter
284  //which we fetch it from
285  return mColorPreview->color();
286 }
287 
288 void QgsColorDialogV2::setTitle( const QString title )
289 {
290  setWindowTitle( title.isEmpty() ? tr( "Select Color" ) : title );
291 }
292 
293 void QgsColorDialogV2::setAllowAlpha( const bool allowAlpha )
294 {
295  mAllowAlpha = allowAlpha;
296  mAlphaLabel->setVisible( allowAlpha );
297  mAlphaSlider->setVisible( allowAlpha );
298  if ( !allowAlpha )
299  {
300  mAlphaLayout->setContentsMargins( 0, 0, 0, 0 );
301  mAlphaLayout->setSpacing( 0 );
302  }
303 }
304 
305 QColor QgsColorDialogV2::getLiveColor( const QColor &initialColor, QObject *updateObject, const char *updateSlot, QWidget *parent, const QString &title, const bool allowAlpha )
306 {
307  QColor returnColor( initialColor );
308  QgsColorDialogV2* liveDialog = new QgsColorDialogV2( parent, 0, initialColor );
309  liveDialog->setWindowTitle( title.isEmpty() ? tr( "Select Color" ) : title );
310  if ( !allowAlpha )
311  {
312  liveDialog->setAllowAlpha( false );
313  }
314 
315  connect( liveDialog, SIGNAL( currentColorChanged( const QColor& ) ),
316  updateObject, updateSlot );
317 
318  if ( liveDialog->exec() )
319  {
320  returnColor = liveDialog->color();
321  }
322  delete liveDialog;
323  liveDialog = 0;
324 
325  return returnColor;
326 }
327 
328 QColor QgsColorDialogV2::getColor( const QColor &initialColor, QWidget *parent, const QString &title, const bool allowAlpha )
329 {
330  QString dialogTitle = title.isEmpty() ? tr( "Select Color" ) : title;
331 
332  QSettings settings;
333  //using native color dialogs?
334  bool useNative = settings.value( "/qgis/native_color_dialogs", false ).toBool();
335  if ( useNative )
336  {
337  return QColorDialog::getColor( initialColor, parent, dialogTitle, allowAlpha ? QColorDialog::ShowAlphaChannel : ( QColorDialog::ColorDialogOption )0 );
338  }
339  else
340  {
341  QgsColorDialogV2* dialog = new QgsColorDialogV2( parent, 0, initialColor );
342  dialog->setWindowTitle( dialogTitle );
343  dialog->setAllowAlpha( allowAlpha );
344 
345  QColor result;
346  if ( dialog->exec() )
347  {
348  result = dialog->color();
349  }
350 
351  if ( !parent )
352  {
353  delete dialog;
354  }
355  return result;
356  }
357 }
358 
359 void QgsColorDialogV2::on_mButtonBox_accepted()
360 {
361  saveSettings();
362  accept();
363 }
364 
365 void QgsColorDialogV2::on_mButtonBox_rejected()
366 {
367  saveSettings();
368  reject();
369 }
370 
371 void QgsColorDialogV2::on_mButtonBox_clicked( QAbstractButton * button )
372 {
373  if ( mButtonBox->buttonRole( button ) == QDialogButtonBox::ResetRole && mPreviousColor.isValid() )
374  {
375  setColor( mPreviousColor );
376  }
377 }
378 
379 void QgsColorDialogV2::importColors()
380 {
381  QSettings s;
382  QString lastDir = s.value( "/UI/lastGplPaletteDir", "" ).toString();
383  QString filePath = QFileDialog::getOpenFileName( this, tr( "Select palette file" ), lastDir, "GPL (*.gpl);;All files (*.*)" );
384  activateWindow();
385  if ( filePath.isEmpty() )
386  {
387  return;
388  }
389 
390  //check if file exists
391  QFileInfo fileInfo( filePath );
392  if ( !fileInfo.exists() || !fileInfo.isReadable() )
393  {
394  QMessageBox::critical( 0, tr( "Invalid file" ), tr( "Error, file does not exist or is not readable" ) );
395  return;
396  }
397 
398  s.setValue( "/UI/lastGplPaletteDir", fileInfo.absolutePath() );
399  QFile file( filePath );
400  bool importOk = mSchemeList->importColorsFromGpl( file );
401  if ( !importOk )
402  {
403  QMessageBox::critical( 0, tr( "Invalid file" ), tr( "Error, no colors found in palette file" ) );
404  return;
405  }
406 }
407 
408 void QgsColorDialogV2::refreshSchemeComboBox()
409 {
410  mSchemeComboBox->blockSignals( true );
411  mSchemeComboBox->clear();
412  QList<QgsColorScheme *> schemeList = QgsColorSchemeRegistry::instance()->schemes( QgsColorScheme::ShowInColorDialog );
413  QList<QgsColorScheme *>::const_iterator schemeIt = schemeList.constBegin();
414  for ( ; schemeIt != schemeList.constEnd(); ++schemeIt )
415  {
416  mSchemeComboBox->addItem(( *schemeIt )->schemeName() );
417  }
418  mSchemeComboBox->blockSignals( false );
419 }
420 
421 void QgsColorDialogV2::importPalette()
422 {
423  QSettings s;
424  QString lastDir = s.value( "/UI/lastGplPaletteDir", "" ).toString();
425  QString filePath = QFileDialog::getOpenFileName( this, tr( "Select palette file" ), lastDir, "GPL (*.gpl);;All files (*.*)" );
426  activateWindow();
427  if ( filePath.isEmpty() )
428  {
429  return;
430  }
431 
432  //check if file exists
433  QFileInfo fileInfo( filePath );
434  if ( !fileInfo.exists() || !fileInfo.isReadable() )
435  {
436  QMessageBox::critical( 0, tr( "Invalid file" ), tr( "Error, file does not exist or is not readable" ) );
437  return;
438  }
439 
440  s.setValue( "/UI/lastGplPaletteDir", fileInfo.absolutePath() );
441  QFile file( filePath );
442 
443  QgsNamedColorList importedColors;
444  bool ok = false;
445  QString paletteName;
446  importedColors = QgsSymbolLayerV2Utils::importColorsFromGpl( file, ok, paletteName );
447  if ( !ok )
448  {
449  QMessageBox::critical( 0, tr( "Invalid file" ), tr( "Palette file is not readable" ) );
450  return;
451  }
452 
453  if ( importedColors.length() == 0 )
454  {
455  //no imported colors
456  QMessageBox::critical( 0, tr( "Invalid file" ), tr( "No colors found in palette file" ) );
457  return;
458  }
459 
460  //TODO - handle conflicting file names, name for new palette
461  QgsUserColorScheme* importedScheme = new QgsUserColorScheme( fileInfo.fileName() );
462  importedScheme->setName( paletteName );
463  importedScheme->setColors( importedColors );
464 
466 
467  //refresh combobox
468  refreshSchemeComboBox();
469  mSchemeComboBox->setCurrentIndex( mSchemeComboBox->count() - 1 );
470 }
471 
472 void QgsColorDialogV2::removePalette()
473 {
474  //get current scheme
475  QList<QgsColorScheme *> schemeList = QgsColorSchemeRegistry::instance()->schemes( QgsColorScheme::ShowInColorDialog );
476  int prevIndex = mSchemeComboBox->currentIndex();
477  if ( prevIndex >= schemeList.length() )
478  {
479  return;
480  }
481 
482  //make user scheme is a user removable scheme
483  QgsUserColorScheme* userScheme = dynamic_cast<QgsUserColorScheme*>( schemeList.at( prevIndex ) );
484  if ( !userScheme )
485  {
486  return;
487  }
488 
489  if ( QMessageBox::question( this, tr( "Remove Color Palette" ),
490  QString( tr( "Are you sure you want to remove %1?" ) ).arg( userScheme->schemeName() ),
491  QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
492  {
493  //user cancelled
494  return;
495  }
496 
497  //remove palette and associated gpl file
498  if ( !userScheme->erase() )
499  {
500  //something went wrong
501  return;
502  }
503 
504  //remove scheme from registry
506  refreshSchemeComboBox();
507  prevIndex = qMax( qMin( prevIndex, mSchemeComboBox->count() - 1 ), 0 );
508  mSchemeComboBox->setCurrentIndex( prevIndex );
509 }
510 
511 void QgsColorDialogV2::newPalette()
512 {
513  bool ok = false;
514  QString name = QInputDialog::getText( this, tr( "Create New Palette" ), tr( "Enter a name for the new palette:" ),
515  QLineEdit::Normal, tr( "New palette" ), &ok );
516 
517  if ( !ok || name.isEmpty() )
518  {
519  //user cancelled
520  return;
521  }
522 
523  //generate file name for new palette
524  QDir palettePath( gplFilePath() );
525  QRegExp badChars( "[,^@={}\\[\\]~!?:&*\"|#%<>$\"'();`' /\\\\]" );
526  QString filename = name.simplified().toLower().replace( badChars, QString( "_" ) );
527  if ( filename.isEmpty() )
528  {
529  filename = tr( "new_palette" );
530  }
531  QFileInfo destFileInfo( palettePath.filePath( filename + ".gpl" ) );
532  int fileNumber = 1;
533  while ( destFileInfo.exists() )
534  {
535  //try to generate a unique file name
536  destFileInfo = QFileInfo( palettePath.filePath( filename + QString( "%1.gpl" ).arg( fileNumber ) ) );
537  fileNumber++;
538  }
539 
540  QgsUserColorScheme* newScheme = new QgsUserColorScheme( destFileInfo.fileName() );
541  newScheme->setName( name );
542 
544 
545  //refresh combobox and set new scheme as active
546  refreshSchemeComboBox();
547  mSchemeComboBox->setCurrentIndex( mSchemeComboBox->count() - 1 );
548 }
549 
550 QString QgsColorDialogV2::gplFilePath()
551 {
552  QString palettesDir = QgsApplication::qgisSettingsDirPath() + "/palettes";
553 
554  QDir localDir;
555  if ( !localDir.mkpath( palettesDir ) )
556  {
557  return QString();
558  }
559 
560  return palettesDir;
561 }
562 
563 void QgsColorDialogV2::exportColors()
564 {
565  QSettings s;
566  QString lastDir = s.value( "/UI/lastGplPaletteDir", "" ).toString();
567  QString fileName = QFileDialog::getSaveFileName( this, tr( "Palette file" ), lastDir, "GPL (*.gpl)" );
568  activateWindow();
569  if ( fileName.isEmpty() )
570  {
571  return;
572  }
573 
574  // ensure filename contains extension
575  if ( !fileName.toLower().endsWith( ".gpl" ) )
576  {
577  fileName += ".gpl";
578  }
579 
580  QFileInfo fileInfo( fileName );
581  s.setValue( "/UI/lastGplPaletteDir", fileInfo.absolutePath() );
582 
583  QFile file( fileName );
584  bool exportOk = mSchemeList->exportColorsToGpl( file );
585  if ( !exportOk )
586  {
587  QMessageBox::critical( 0, tr( "Error exporting" ), tr( "Error writing palette file" ) );
588  return;
589  }
590 }
591 
592 void QgsColorDialogV2::schemeIndexChanged( int index )
593 {
594  //save changes to scheme
595  if ( mSchemeList->isDirty() )
596  {
597  mSchemeList->saveColorsToScheme();
598  }
599 
600  //get schemes with ShowInColorDialog set
601  QList<QgsColorScheme *> schemeList = QgsColorSchemeRegistry::instance()->schemes( QgsColorScheme::ShowInColorDialog );
602  if ( index >= schemeList.length() )
603  {
604  return;
605  }
606 
607  QgsColorScheme* scheme = schemeList.at( index );
608  mSchemeList->setScheme( scheme );
609  mActionImportColors->setEnabled( scheme->isEditable() );
610  mActionPasteColors->setEnabled( scheme->isEditable() );
611  mAddColorToSchemeButton->setEnabled( scheme->isEditable() );
612  mRemoveColorsFromSchemeButton->setEnabled( scheme->isEditable() );
613  QgsUserColorScheme* userScheme = dynamic_cast<QgsUserColorScheme*>( scheme );
614  mActionRemovePalette->setEnabled( userScheme ? true : false );
615 
616  //copy action defaults to disabled
617  mActionCopyColors->setEnabled( false );
618 }
619 
620 void QgsColorDialogV2::listSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
621 {
622  Q_UNUSED( deselected );
623  mActionCopyColors->setEnabled( selected.length() > 0 );
624 }
625 
626 void QgsColorDialogV2::on_mAddCustomColorButton_clicked()
627 {
628  switch ( mLastCustomColorIndex )
629  {
630  case 0:
631  mSwatchButton1->setColor( mColorPreview->color() );
632  break;
633  case 1:
634  mSwatchButton2->setColor( mColorPreview->color() );
635  break;
636  case 2:
637  mSwatchButton3->setColor( mColorPreview->color() );
638  break;
639  case 3:
640  mSwatchButton4->setColor( mColorPreview->color() );
641  break;
642  case 4:
643  mSwatchButton5->setColor( mColorPreview->color() );
644  break;
645  case 5:
646  mSwatchButton6->setColor( mColorPreview->color() );
647  break;
648  case 6:
649  mSwatchButton7->setColor( mColorPreview->color() );
650  break;
651  case 7:
652  mSwatchButton8->setColor( mColorPreview->color() );
653  break;
654  case 8:
655  mSwatchButton9->setColor( mColorPreview->color() );
656  break;
657  case 9:
658  mSwatchButton10->setColor( mColorPreview->color() );
659  break;
660  case 10:
661  mSwatchButton11->setColor( mColorPreview->color() );
662  break;
663  case 11:
664  mSwatchButton12->setColor( mColorPreview->color() );
665  break;
666  case 12:
667  mSwatchButton13->setColor( mColorPreview->color() );
668  break;
669  case 13:
670  mSwatchButton14->setColor( mColorPreview->color() );
671  break;
672  case 14:
673  mSwatchButton15->setColor( mColorPreview->color() );
674  break;
675  case 15:
676  mSwatchButton16->setColor( mColorPreview->color() );
677  break;
678  }
679  mLastCustomColorIndex++;
680  if ( mLastCustomColorIndex >= 16 )
681  {
682  mLastCustomColorIndex = 0;
683  }
684 }
685 
686 void QgsColorDialogV2::on_mSampleButton_clicked()
687 {
688  //activate picker color
689  QPixmap samplerPixmap = QPixmap(( const char ** ) sampler_cursor );
690  setCursor( QCursor( samplerPixmap, 0, 0 ) );
691  grabMouse();
692  grabKeyboard();
693  mPickingColor = true;
694  setMouseTracking( true );
695 }
696 
697 void QgsColorDialogV2::on_mTabWidget_currentChanged( int index )
698 {
699  //disable radio buttons if not using the first tab, as they have no meaning for other tabs
700  bool enabled = index == 0;
701  mRedRadio->setEnabled( enabled );
702  mBlueRadio->setEnabled( enabled );
703  mGreenRadio->setEnabled( enabled );
704  mHueRadio->setEnabled( enabled );
705  mSaturationRadio->setEnabled( enabled );
706  mValueRadio->setEnabled( enabled );
707 }
708 
709 void QgsColorDialogV2::saveSettings()
710 {
711  //save changes to scheme
712  if ( mSchemeList->isDirty() )
713  {
714  mSchemeList->saveColorsToScheme();
715  }
716 
717  QSettings settings;
718  settings.setValue( "/Windows/ColorDialog/geometry", saveGeometry() );
719 
720  //record active component
721  int activeRadio = 0;
722  if ( mHueRadio->isChecked() )
723  activeRadio = 0;
724  if ( mSaturationRadio->isChecked() )
725  activeRadio = 1;
726  if ( mValueRadio->isChecked() )
727  activeRadio = 2;
728  if ( mRedRadio->isChecked() )
729  activeRadio = 3;
730  if ( mGreenRadio->isChecked() )
731  activeRadio = 4;
732  if ( mBlueRadio->isChecked() )
733  activeRadio = 5;
734  settings.setValue( "/Windows/ColorDialog/activeComponent", activeRadio );
735 
736  //record current scheme
737  settings.setValue( "/Windows/ColorDialog/activeScheme", mSchemeComboBox->currentIndex() );
738 
739  //record current tab
740  settings.setValue( "/Windows/ColorDialog/activeTab", mTabWidget->currentIndex() );
741 
742  //record custom colors
743  settings.setValue( "/Windows/ColorDialog/customColor1", QVariant( mSwatchButton1->color() ) );
744  settings.setValue( "/Windows/ColorDialog/customColor2", QVariant( mSwatchButton2->color() ) );
745  settings.setValue( "/Windows/ColorDialog/customColor3", QVariant( mSwatchButton3->color() ) );
746  settings.setValue( "/Windows/ColorDialog/customColor4", QVariant( mSwatchButton4->color() ) );
747  settings.setValue( "/Windows/ColorDialog/customColor5", QVariant( mSwatchButton5->color() ) );
748  settings.setValue( "/Windows/ColorDialog/customColor6", QVariant( mSwatchButton6->color() ) );
749  settings.setValue( "/Windows/ColorDialog/customColor7", QVariant( mSwatchButton7->color() ) );
750  settings.setValue( "/Windows/ColorDialog/customColor8", QVariant( mSwatchButton8->color() ) );
751  settings.setValue( "/Windows/ColorDialog/customColor9", QVariant( mSwatchButton9->color() ) );
752  settings.setValue( "/Windows/ColorDialog/customColor10", QVariant( mSwatchButton10->color() ) );
753  settings.setValue( "/Windows/ColorDialog/customColor11", QVariant( mSwatchButton11->color() ) );
754  settings.setValue( "/Windows/ColorDialog/customColor12", QVariant( mSwatchButton12->color() ) );
755  settings.setValue( "/Windows/ColorDialog/customColor13", QVariant( mSwatchButton13->color() ) );
756  settings.setValue( "/Windows/ColorDialog/customColor14", QVariant( mSwatchButton14->color() ) );
757  settings.setValue( "/Windows/ColorDialog/customColor15", QVariant( mSwatchButton15->color() ) );
758  settings.setValue( "/Windows/ColorDialog/customColor16", QVariant( mSwatchButton16->color() ) );
759 
760  //sample radius
761  settings.setValue( "/Windows/ColorDialog/sampleRadius", mSpinBoxRadius->value() );
762 }
763 
764 void QgsColorDialogV2::stopPicking( const QPoint &eventPos, const bool takeSample )
765 {
766  //release mouse and keyboard, and reset cursor
767  releaseMouse();
768  releaseKeyboard();
769  unsetCursor();
770  setMouseTracking( false );
771  mPickingColor = false;
772 
773  if ( !takeSample )
774  {
775  //not sampling color, nothing more to do
776  return;
777  }
778 
779  //grab snapshot of pixel under mouse cursor
780  QColor snappedColor = sampleColor( eventPos );
781  mSamplePreview->setColor( snappedColor );
782  mColorPreview->setColor( snappedColor, true );
783 }
784 
785 void QgsColorDialogV2::setColor( const QColor &color )
786 {
787  if ( !color.isValid() )
788  {
789  return;
790  }
791 
792  QColor fixedColor = QColor( color );
793  if ( !mAllowAlpha )
794  {
795  //alpha disallowed, so don't permit transparent colors
796  fixedColor.setAlpha( 255 );
797  }
798  QList<QgsColorWidget*> colorWidgets = this->findChildren<QgsColorWidget *>();
799  foreach ( QgsColorWidget* widget, colorWidgets )
800  {
801  if ( widget == mSamplePreview )
802  {
803  continue;
804  }
805  widget->blockSignals( true );
806  widget->setColor( fixedColor );
807  widget->blockSignals( false );
808  }
809  emit currentColorChanged( fixedColor );
810 }
811 
812 void QgsColorDialogV2::closeEvent( QCloseEvent *e )
813 {
814  saveSettings();
815  QDialog::closeEvent( e );
816 }
817 
818 void QgsColorDialogV2::mousePressEvent( QMouseEvent *e )
819 {
820  if ( mPickingColor )
821  {
822  //don't show dialog if in color picker mode
823  e->accept();
824  return;
825  }
826 
827  QDialog::mousePressEvent( e );
828 }
829 
830 QColor QgsColorDialogV2::averageColor( const QImage &image ) const
831 {
832  QRgb tmpRgb;
833  int colorCount = 0;
834  int sumRed = 0;
835  int sumBlue = 0;
836  int sumGreen = 0;
837  //scan through image and sum rgb components
838  for ( int heightIndex = 0; heightIndex < image.height(); ++heightIndex )
839  {
840  QRgb* scanLine = ( QRgb* )image.constScanLine( heightIndex );
841  for ( int widthIndex = 0; widthIndex < image.width(); ++widthIndex )
842  {
843  tmpRgb = scanLine[widthIndex];
844  sumRed += qRed( tmpRgb );
845  sumBlue += qBlue( tmpRgb );
846  sumGreen += qGreen( tmpRgb );
847  colorCount++;
848  }
849  }
850  //calculate average components as floats
851  double avgRed = ( double )sumRed / ( 255.0 * colorCount );
852  double avgGreen = ( double )sumGreen / ( 255.0 * colorCount );
853  double avgBlue = ( double )sumBlue / ( 255.0 * colorCount );
854 
855  //create a new color representing the average
856  return QColor::fromRgbF( avgRed, avgGreen, avgBlue );
857 }
858 
859 QColor QgsColorDialogV2::sampleColor( const QPoint &point ) const
860 {
861  int sampleRadius = mSpinBoxRadius->value() - 1;
862  QPixmap snappedPixmap = QPixmap::grabWindow( QApplication::desktop()->winId(), point.x() - sampleRadius, point.y() - sampleRadius,
863  1 + sampleRadius * 2, 1 + sampleRadius * 2 );
864  QImage snappedImage = snappedPixmap.toImage();
865  //scan all pixels and take average color
866  return averageColor( snappedImage );
867 }
868 
869 void QgsColorDialogV2::mouseMoveEvent( QMouseEvent *e )
870 {
871  if ( mPickingColor )
872  {
873  //currently in color picker mode
874  //sample color under cursor update preview widget to give feedback to user
875  QColor hoverColor = sampleColor( e->globalPos() );
876  mSamplePreview->setColor( hoverColor );
877 
878  e->accept();
879  return;
880  }
881 
882  QDialog::mouseMoveEvent( e );
883 }
884 
886 {
887  if ( mPickingColor )
888  {
889  //end color picking operation by sampling the color under cursor
890  stopPicking( e->globalPos() );
891  e->accept();
892  return;
893  }
894 
895  QDialog::mouseReleaseEvent( e );
896 }
897 
899 {
900  if ( !mPickingColor )
901  {
902  //if not picking a color, use default tool button behaviour
903  QDialog::keyPressEvent( e );
904  return;
905  }
906 
907  //cancel picking, sampling the color if space was pressed
908  stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
909 }
910 
911 void QgsColorDialogV2::on_mHueRadio_toggled( bool checked )
912 {
913  if ( checked )
914  {
915  mColorBox->setComponent( QgsColorWidget::Hue );
916  mVerticalRamp->setComponent( QgsColorWidget::Hue );
917  }
918 }
919 
920 void QgsColorDialogV2::on_mSaturationRadio_toggled( bool checked )
921 {
922  if ( checked )
923  {
924  mColorBox->setComponent( QgsColorWidget::Saturation );
925  mVerticalRamp->setComponent( QgsColorWidget::Saturation );
926  }
927 }
928 
929 void QgsColorDialogV2::on_mValueRadio_toggled( bool checked )
930 {
931  if ( checked )
932  {
933  mColorBox->setComponent( QgsColorWidget::Value );
934  mVerticalRamp->setComponent( QgsColorWidget::Value );
935  }
936 }
937 
938 void QgsColorDialogV2::on_mRedRadio_toggled( bool checked )
939 {
940  if ( checked )
941  {
942  mColorBox->setComponent( QgsColorWidget::Red );
943  mVerticalRamp->setComponent( QgsColorWidget::Red );
944  }
945 }
946 
947 void QgsColorDialogV2::on_mGreenRadio_toggled( bool checked )
948 {
949  if ( checked )
950  {
951  mColorBox->setComponent( QgsColorWidget::Green );
952  mVerticalRamp->setComponent( QgsColorWidget::Green );
953  }
954 }
955 
956 void QgsColorDialogV2::on_mBlueRadio_toggled( bool checked )
957 {
958  if ( checked )
959  {
960  mColorBox->setComponent( QgsColorWidget::Blue );
961  mVerticalRamp->setComponent( QgsColorWidget::Blue );
962  }
963 }
964 
965 void QgsColorDialogV2::on_mAddColorToSchemeButton_clicked()
966 {
967  mSchemeList->addColor( mColorPreview->color(), QgsSymbolLayerV2Utils::colorToName( mColorPreview->color() ) );
968 }
A color scheme which stores its colors in a gpl palette file within the "palettes" subfolder off the ...
void setName(const QString &name)
Sets the name for the scheme.
static unsigned index
A base class for interactive color widgets.
bool erase()
Erases the associated gpl palette file from the users "palettes" folder.
A custom QGIS dialog for selecting a color.
QgsColorDialogV2(QWidget *parent=0, Qt::WindowFlags fl=QgisGui::ModalDialogFlags, const QColor &color=QColor())
Create a new color picker dialog.
Abstract base class for color schemes.
void currentColorChanged(const QColor &color)
Emitted when the dialog's color changes.
virtual QString schemeName() const
Gets the name for the color scheme.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
bool removeColorScheme(QgsColorScheme *scheme)
Removes all matching color schemes from the registry.
static const QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
void closeEvent(QCloseEvent *e)
void setAllowAlpha(const bool allowAlpha)
Sets whether alpha modification (transparency) is permitted for the color dialog. ...
virtual bool isEditable() const
Returns whether the color scheme is editable.
QColor color() const
Returns the current color for the dialog.
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
void addColorScheme(QgsColorScheme *scheme)
Adds a color scheme to the registry.
void mouseMoveEvent(QMouseEvent *e)
void keyPressEvent(QKeyEvent *e)
QString file
Definition: qgssvgcache.cpp:76
static QgsColorSchemeRegistry * instance()
Returns the global instance pointer, creating the object on the first call.
const char * sampler_cursor[]
Definition: qgscursors.cpp:183
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), const bool allowAlpha=false)
Return a color selection from a color dialog.
void mouseReleaseEvent(QMouseEvent *e)
void mousePressEvent(QMouseEvent *e)
static QColor getLiveColor(const QColor &initialColor, QObject *updateObject, const char *updateSlot, QWidget *parent=0, const QString &title=QString(), const bool allowAlpha=true)
Return a color selection from a color dialog, with live updating of interim selections.
static QColor getLiveColor(const QColor &initialColor, QObject *updateObject, const char *updateSlot, QWidget *parent=0, const QString &title="", QColorDialog::ColorDialogOptions options=0)
Return a color selection from a QColorDialog, with live updating of interim selections.
void setColor(const QColor &color)
Sets the current color for the dialog.
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
virtual bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor())
Sets the colors for the scheme.
virtual void setColor(const QColor &color, const bool emitSignals=false)
Sets the color for the widget.
void setTitle(const QString title)
Sets the title for the color dialog.
#define tr(sourceText)