QGIS API Documentation
qgsvectorgradientcolorrampv2dialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorgradientcolorrampv2dialog.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
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 
17 
18 #include "qgsvectorcolorrampv2.h"
19 #include "qgsdialog.h"
20 #include "qgscolordialog.h"
21 #include "qgscptcityarchive.h"
22 
23 #include <QColorDialog>
24 #include <QInputDialog>
25 #include <QPainter>
26 #include <QSettings>
27 #include <QTableWidget>
28 #include <QTextEdit>
29 
31  : QDialog( parent )
32  , mRamp( ramp )
33  , mCurrentItem( nullptr )
34 {
35  setupUi( this );
36 #ifdef Q_OS_MAC
37  setWindowModality( Qt::WindowModal );
38 #endif
39 
40  btnColor1->setAllowAlpha( true );
41  btnColor1->setColorDialogTitle( tr( "Select ramp color" ) );
42  btnColor1->setContext( "symbology" );
43  btnColor1->setShowNoColor( true );
44  btnColor1->setNoColorString( tr( "Transparent" ) );
45  btnColor2->setAllowAlpha( true );
46  btnColor2->setColorDialogTitle( tr( "Select ramp color" ) );
47  btnColor2->setContext( "symbology" );
48  btnColor2->setShowNoColor( true );
49  btnColor2->setNoColorString( tr( "Transparent" ) );
50  connect( btnColor1, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor1( const QColor& ) ) );
51  connect( btnColor2, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor2( const QColor& ) ) );
52 
53  // handle stops
54  updateStops();
55  connect( groupStops, SIGNAL( toggled( bool ) ), this, SLOT( toggledStops( bool ) ) );
56  connect( btnAddStop, SIGNAL( clicked() ), this, SLOT( addStop() ) );
57  connect( btnRemoveStop, SIGNAL( clicked() ), this, SLOT( removeStop() ) );
58  connect( treeStops, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( stopDoubleClicked( QTreeWidgetItem*, int ) ) );
59 
60  // fill type combobox
61  cboType->blockSignals( true );
62  cboType->addItem( tr( "Discrete" ) );
63  cboType->addItem( tr( "Continuous" ) );
64  if ( mRamp->isDiscrete() )
65  cboType->setCurrentIndex( 0 );
66  else
67  cboType->setCurrentIndex( 1 );
68  cboType->blockSignals( false );
69 
70  // information button if needed
71  // QPushButton* button = buttonBox->addButton( tr( "Information" ), QDialogButtonBox::ActionRole );
72  if ( mRamp->info().isEmpty() )
73  btnInformation->setEnabled( false );
74  // else
75  // connect( button, SIGNAL( pressed() ), this, SLOT( showInformation() ) );
76 
77  updatePreview();
78 }
79 
81 {
82  if (( index == 0 && mRamp->isDiscrete() ) ||
83  ( index == 1 && !mRamp->isDiscrete() ) )
84  return;
85  mRamp->convertToDiscrete( index == 0 );
86  updateStops();
87  updatePreview();
88 }
89 
91 {
92  if ( mRamp->info().isEmpty() )
93  return;
94 
95  QgsDialog *dlg = new QgsDialog( this );
96  QLabel *label = nullptr;
97 
98  // information table
99  QTableWidget *tableInfo = new QTableWidget( dlg );
100  tableInfo->verticalHeader()->hide();
101  tableInfo->horizontalHeader()->hide();
102  tableInfo->setRowCount( mRamp->info().count() );
103  tableInfo->setColumnCount( 2 );
104  int i = 0;
105  QgsStringMap rampInfo = mRamp->info();
106  for ( QgsStringMap::const_iterator it = rampInfo.constBegin();
107  it != rampInfo.constEnd(); ++it )
108  {
109  if ( it.key().startsWith( "cpt-city" ) )
110  continue;
111  tableInfo->setItem( i, 0, new QTableWidgetItem( it.key() ) );
112  tableInfo->setItem( i, 1, new QTableWidgetItem( it.value() ) );
113  tableInfo->resizeRowToContents( i );
114  i++;
115  }
116  tableInfo->resizeColumnToContents( 0 );
117  tableInfo->horizontalHeader()->setStretchLastSection( true );
118  tableInfo->setRowCount( i );
119  tableInfo->setFixedHeight( tableInfo->rowHeight( 0 ) * i + 5 );
120  dlg->layout()->addWidget( tableInfo );
121  dlg->resize( 600, 250 );
122 
123  dlg->layout()->addSpacing( 5 );
124 
125  // gradient file
126  QString gradientFile = mRamp->info().value( "cpt-city-gradient" );
127  if ( ! gradientFile.isNull() )
128  {
129  QString fileName = gradientFile;
130  fileName.replace( "<cpt-city>", QgsCptCityArchive::defaultBaseDir() );
131  if ( ! QFile::exists( fileName ) )
132  {
133  fileName = gradientFile;
134  fileName.replace( "<cpt-city>", "http://soliton.vm.bytemark.co.uk/pub/cpt-city" );
135  }
136  label = new QLabel( tr( "Gradient file : %1" ).arg( fileName ), dlg );
137  label->setTextInteractionFlags( Qt::TextBrowserInteraction );
138  dlg->layout()->addSpacing( 5 );
139  dlg->layout()->addWidget( label );
140  }
141 
142  // license file
143  QString licenseFile = mRamp->info().value( "cpt-city-license" );
144  if ( !licenseFile.isNull() )
145  {
146  QString fileName = licenseFile;
147  fileName.replace( "<cpt-city>", QgsCptCityArchive::defaultBaseDir() );
148  if ( ! QFile::exists( fileName ) )
149  {
150  fileName = licenseFile;
151  fileName.replace( "<cpt-city>", "http://soliton.vm.bytemark.co.uk/pub/cpt-city" );
152  }
153  label = new QLabel( tr( "License file : %1" ).arg( fileName ), dlg );
154  label->setTextInteractionFlags( Qt::TextBrowserInteraction );
155  dlg->layout()->addSpacing( 5 );
156  dlg->layout()->addWidget( label );
157  if ( QFile::exists( fileName ) )
158  {
159  QTextEdit *textEdit = new QTextEdit( dlg );
160  textEdit->setReadOnly( true );
161  QFile file( fileName );
162  if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
163  {
164  textEdit->setText( file.readAll() );
165  file.close();
166  dlg->layout()->addSpacing( 5 );
167  dlg->layout()->addWidget( textEdit );
168  dlg->resize( 600, 500 );
169  }
170  }
171  }
172 
173  dlg->show(); //non modal
174 }
175 
177 {
178  QgsGradientStopsList stops = mRamp->stops();
179  groupStops->setChecked( !stops.isEmpty() );
180 
182  for ( QgsGradientStopsList::iterator it = stops.begin();
183  it != stops.end(); ++it )
184  {
185  double val = it->offset * 100.0;
186  QStringList lst;
187  lst << "." << QString(( val < 10 ) ? '0' + QString::number( val ) : QString::number( val ) );
188  QTreeWidgetItem* item = new QTreeWidgetItem( lst );
189 
190  setStopColor( item, it->color );
191  item->setData( 0, StopOffsetRole, it->offset );
192 
193  items.append( item );
194  }
195  treeStops->clear();
196  treeStops->insertTopLevelItems( 0, items );
197  treeStops->resizeColumnToContents( 0 );
198  treeStops->setColumnWidth( 0, treeStops->columnWidth( 0 ) + 20 );
199  treeStops->sortByColumn( 1, Qt::AscendingOrder );
200  treeStops->setSortingEnabled( true );
201 }
202 
204 {
205  // update ramp stops from the tree widget
206  QgsGradientStopsList stops;
207  if ( groupStops->isChecked() )
208  {
209  int count = treeStops->topLevelItemCount();
210  stops.reserve( count );
211  for ( int i = 0; i < count; i++ )
212  {
213  QTreeWidgetItem* item = treeStops->topLevelItem( i );
214  double offset = item->data( 0, StopOffsetRole ).toDouble();
215  QColor color = item->data( 0, StopColorRole ).value<QColor>();
216  stops.append( QgsGradientStop( offset, color ) );
217  }
218  }
219  mRamp->setStops( stops );
220 
221  // generate the preview
222  QSize size( 300, 40 );
223  lblPreview->setPixmap( QgsSymbolLayerV2Utils::colorRampPreviewPixmap( mRamp, size ) );
224 
225  btnColor1->blockSignals( true );
226  btnColor1->setColor( mRamp->color1() );
227  btnColor1->blockSignals( false );
228  btnColor2->blockSignals( true );
229  btnColor2->setColor( mRamp->color2() );
230  btnColor2->blockSignals( false );
231 }
232 
234 {
235  mRamp->setColor1( color );
236  updatePreview();
237 }
238 
240 {
241  mRamp->setColor2( color );
242  updatePreview();
243 }
244 
246 {
247  QSize iconSize( 16, 16 );
248  QPixmap pixmap( iconSize );
249  pixmap.fill( QColor( 0, 0, 0, 0 ) );
250  QRect rect( 1, 1, iconSize.width() - 2, iconSize.height() - 2 );
251 
252  // draw a slightly rounded rectangle
253  QPainter p;
254  p.begin( &pixmap );
255  p.setPen( Qt::NoPen );
256  p.setRenderHint( QPainter::Antialiasing );
257  p.setBrush( color );
258  p.drawRoundedRect( rect, 2, 2 );
259  p.end();
260 
261  item->setIcon( 0, QIcon( pixmap ) );
262  item->setData( 0, StopColorRole, color );
263  item->setText( 0, color.name() );
264 }
265 
267 {
268  if ( mCurrentItem )
269  {
270  setStopColor( mCurrentItem, newColor );
271  updatePreview();
272  }
273 }
274 
276 {
277  if ( column == 0 )
278  {
279  QColor color;
280 
281  QSettings settings;
282  //using native color dialogs?
283  bool useNative = settings.value( "/qgis/native_color_dialogs", false ).toBool();
284  if ( settings.value( "/qgis/live_color_dialogs", false ).toBool() )
285  {
286  mCurrentItem = item;
287  if ( useNative )
288  {
290  item->data( 0, StopColorRole ).value<QColor>(),
291  this, SLOT( setItemStopColor( const QColor& ) ),
292  this, tr( "Edit Stop Color" ), QColorDialog::ShowAlphaChannel );
293  }
294  else
295  {
297  item->data( 0, StopColorRole ).value<QColor>(), this, SLOT( setItemStopColor( const QColor& ) ),
298  this, tr( "Edit Stop Color" ), true );
299  }
300  mCurrentItem = nullptr;
301  }
302  else
303  {
304  color = QgsColorDialogV2::getColor( item->data( 0, StopColorRole ).value<QColor>(), this, tr( "Edit Stop Color" ), true );
305  }
306  if ( !color.isValid() )
307  return;
308  setStopColor( item, color );
309 
310  updatePreview();
311  }
312  else
313  {
314  bool ok;
315  double key = item->data( 0, StopOffsetRole ).toDouble();
316  // allow for floating-point values
317  double val = key * 100;
318  val = QInputDialog::getDouble( this, tr( "Offset of the stop" ),
319  tr( "Please enter offset in percents (%) of the new stop" ),
320  val, 0, 100, 2, &ok );
321  if ( !ok )
322  return;
323 
324  double newkey = val / 100.0;
325  item->setText( 1, ( val < 10 ) ? '0' + QString::number( val ) : QString::number( val ) );
326  item->setData( 0, StopOffsetRole, newkey );
327 
328  updatePreview();
329  }
330 }
331 
333 {
334 // Native Mac dialog works only for Qt Carbon
335 // Qt bug: http://bugreports.qt.nokia.com/browse/QTBUG-14889
336 // Qt 4.7 Mac Cocoa bug: calling QInputDialog::getInt after QColorDialog::getColor will freeze app
337 // workaround: call QColorDialog::getColor below instead of here,
338 // but not needed at this time because of the other Qt bug
339 // FIXME need to also check max QT_VERSION when Qt bug(s) fixed
340 #ifndef Q_OS_MAC
341  QColor color = QgsColorDialogV2::getColor( QColor(), this, tr( "Add Color Stop" ), true );
342 
343  if ( !color.isValid() )
344  return;
345  activateWindow();
346 #endif
347 
348  bool ok;
349  double val = 50.0;
350  val = QInputDialog::getDouble( this, tr( "Offset of the stop" ),
351  tr( "Please enter offset in percents (%) of the new stop" ),
352  val, 0, 100, 2, &ok );
353  if ( !ok )
354  return;
355  activateWindow();
356 
357  double key = val / 100.0;
358  QStringList lst;
359  lst << "." << QString(( val < 10 ) ? '0' + QString::number( val ) : QString::number( val ) );
360 
361 #ifdef Q_OS_MAC
362  QColor color = QgsColorDialogV2::getColor( QColor(), this, tr( "Add Color Stop" ), true );
363 
364  if ( !color.isValid() )
365  return;
366  activateWindow();
367 #endif
368 
369  QTreeWidgetItem* item = new QTreeWidgetItem( lst );
370 
371  setStopColor( item, color );
372  item->setData( 0, StopOffsetRole, key );
373 
374  treeStops->addTopLevelItem( item );
375 
376  treeStops->resizeColumnToContents( 0 );
377  treeStops->setColumnWidth( 0, treeStops->columnWidth( 0 ) + 20 );
378 
379  updatePreview();
380 }
381 
383 {
384  QTreeWidgetItem* item = treeStops->currentItem();
385  if ( !item )
386  return;
387  int index = treeStops->indexOfTopLevelItem( item );
388  treeStops->takeTopLevelItem( index );
389 
390  updatePreview();
391 }
392 
394 {
395  Q_UNUSED( on );
396  updatePreview();
397 }
static unsigned index
void setupUi(QWidget *widget)
int width() const
static QPixmap colorRampPreviewPixmap(QgsVectorColorRampV2 *ramp, QSize size)
Represents a color stop within a gradient color ramp.
void fill(const QColor &color)
QString name() const
void setWindowModality(Qt::WindowModality windowModality)
void setItem(int row, int column, QTableWidgetItem *item)
void reserve(int alloc)
static QString defaultBaseDir()
void resizeColumnToContents(int column)
const_iterator constBegin() const
void setIcon(int column, const QIcon &icon)
A generic dialog with layout and button box.
Definition: qgsdialog.h:30
T value() const
virtual void setData(int column, int role, const QVariant &value)
QHeaderView * verticalHeader() const
bool exists() const
void addSpacing(int size)
virtual QVariant data(int column, int role) const
void setColor2(const QColor &color)
Sets the gradient end color.
QString tr(const char *sourceText, const char *disambiguation, int n)
QgsStringMap info() const
Returns any additional info attached to the gradient ramp (eg authorship notes)
void setColor1(const QColor &color)
Sets the gradient start color.
bool isNull() const
int rowHeight(int row) const
void resize(int w, int h)
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QString number(int n, int base)
void append(const T &value)
bool isEmpty() const
const_iterator constEnd() const
QgsVectorGradientColorRampV2Dialog(QgsVectorGradientColorRampV2 *ramp, QWidget *parent=nullptr)
void setStops(const QgsGradientStopsList &stops)
Sets the list of intermediate gradient stops for the ramp.
QByteArray readAll()
double getDouble(QWidget *parent, const QString &title, const QString &label, double value, double min, double max, int decimals, bool *ok, QFlags< Qt::WindowType > flags)
void hide()
void convertToDiscrete(bool discrete)
Converts a gradient with existing color stops to or from discrete interpolation.
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QRect rect() const
iterator end()
virtual void close()
QgsGradientStopsList stops() const
Returns the list of intermediate gradient stops for the ramp.
void setColumnCount(int columns)
void setTextInteractionFlags(QFlags< Qt::TextInteractionFlag > flags)
QString & replace(int position, int n, QChar after)
QVariant value(const QString &key, const QVariant &defaultValue) const
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 activateWindow()
void setFixedHeight(int h)
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
QVBoxLayout * layout()
Returns the central layout. Widgets added to it must have this dialog as parent.
Definition: qgsdialog.h:40
int height() const
void setText(int column, const QString &text)
bool toBool() const
double toDouble(bool *ok) const
void show()
bool isEmpty() const
void setReadOnly(bool ro)
void resizeRowToContents(int row)
void setStretchLastSection(bool stretch)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setRowCount(int rows)
bool begin(QPaintDevice *device)
QHeaderView * horizontalHeader() const
void setText(const QString &text)
void stopDoubleClicked(QTreeWidgetItem *item, int column)
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QColor getLiveColor(const QColor &initialColor, QObject *updateObject, const char *updateSlot, QWidget *parent=nullptr, const QString &title="", const QColorDialog::ColorDialogOptions &options=nullptr)
Return a color selection from a QColorDialog, with live updating of interim selections.
QColor color2() const
Returns the gradient end color.
QColor color1() const
Returns the gradient start color.
int count(const Key &key) const
iterator begin()
static QColor getLiveColor(const QColor &initialColor, QObject *updateObject, const char *updateSlot, QWidget *parent=nullptr, const QString &title=QString(), const bool allowAlpha=true)
Return a color selection from a color dialog, with live updating of interim selections.
void setStopColor(QTreeWidgetItem *item, const QColor &color)
bool isValid() const
const T value(const Key &key) const