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 ), mRamp( ramp ), mCurrentItem( nullptr )
32 {
33  setupUi( this );
34 #ifdef Q_OS_MAC
35  setWindowModality( Qt::WindowModal );
36 #endif
37 
38  btnColor1->setAllowAlpha( true );
39  btnColor1->setColorDialogTitle( tr( "Select ramp color" ) );
40  btnColor1->setContext( "symbology" );
41  btnColor1->setShowNoColor( true );
42  btnColor1->setNoColorString( tr( "Transparent" ) );
43  btnColor2->setAllowAlpha( true );
44  btnColor2->setColorDialogTitle( tr( "Select ramp color" ) );
45  btnColor2->setContext( "symbology" );
46  btnColor2->setShowNoColor( true );
47  btnColor2->setNoColorString( tr( "Transparent" ) );
48  connect( btnColor1, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor1( const QColor& ) ) );
49  connect( btnColor2, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor2( const QColor& ) ) );
50 
51  // handle stops
52  updateStops();
53  connect( groupStops, SIGNAL( toggled( bool ) ), this, SLOT( toggledStops( bool ) ) );
54  connect( btnAddStop, SIGNAL( clicked() ), this, SLOT( addStop() ) );
55  connect( btnRemoveStop, SIGNAL( clicked() ), this, SLOT( removeStop() ) );
56  connect( treeStops, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( stopDoubleClicked( QTreeWidgetItem*, int ) ) );
57 
58  // fill type combobox
59  cboType->blockSignals( true );
60  cboType->addItem( tr( "Discrete" ) );
61  cboType->addItem( tr( "Continuous" ) );
62  if ( mRamp->isDiscrete() )
63  cboType->setCurrentIndex( 0 );
64  else
65  cboType->setCurrentIndex( 1 );
66  cboType->blockSignals( false );
67 
68  // information button if needed
69  // QPushButton* button = buttonBox->addButton( tr( "Information" ), QDialogButtonBox::ActionRole );
70  if ( mRamp->info().isEmpty() )
71  btnInformation->setEnabled( false );
72  // else
73  // connect( button, SIGNAL( pressed() ), this, SLOT( showInformation() ) );
74 
75  updatePreview();
76 }
77 
79 {
80  if (( index == 0 && mRamp->isDiscrete() ) ||
81  ( index == 1 && !mRamp->isDiscrete() ) )
82  return;
83  mRamp->convertToDiscrete( index == 0 );
84  updateStops();
85  updatePreview();
86 }
87 
89 {
90  if ( mRamp->info().isEmpty() )
91  return;
92 
93  QgsDialog *dlg = new QgsDialog( this );
94  QLabel *label = nullptr;
95 
96  // information table
97  QTableWidget *tableInfo = new QTableWidget( dlg );
98  tableInfo->verticalHeader()->hide();
99  tableInfo->horizontalHeader()->hide();
100  tableInfo->setRowCount( mRamp->info().count() );
101  tableInfo->setColumnCount( 2 );
102  int i = 0;
103  QgsStringMap rampInfo = mRamp->info();
104  for ( QgsStringMap::const_iterator it = rampInfo.constBegin();
105  it != rampInfo.constEnd(); ++it )
106  {
107  if ( it.key().startsWith( "cpt-city" ) )
108  continue;
109  tableInfo->setItem( i, 0, new QTableWidgetItem( it.key() ) );
110  tableInfo->setItem( i, 1, new QTableWidgetItem( it.value() ) );
111  tableInfo->resizeRowToContents( i );
112  i++;
113  }
114  tableInfo->resizeColumnToContents( 0 );
115  tableInfo->horizontalHeader()->setStretchLastSection( true );
116  tableInfo->setRowCount( i );
117  tableInfo->setFixedHeight( tableInfo->rowHeight( 0 ) * i + 5 );
118  dlg->layout()->addWidget( tableInfo );
119  dlg->resize( 600, 250 );
120 
121  dlg->layout()->addSpacing( 5 );
122 
123  // gradient file
124  QString gradientFile = mRamp->info().value( "cpt-city-gradient" );
125  if ( ! gradientFile.isNull() )
126  {
127  QString fileName = gradientFile;
128  fileName.replace( "<cpt-city>", QgsCptCityArchive::defaultBaseDir() );
129  if ( ! QFile::exists( fileName ) )
130  {
131  fileName = gradientFile;
132  fileName.replace( "<cpt-city>", "http://soliton.vm.bytemark.co.uk/pub/cpt-city" );
133  }
134  label = new QLabel( tr( "Gradient file : %1" ).arg( fileName ), dlg );
135  label->setTextInteractionFlags( Qt::TextBrowserInteraction );
136  dlg->layout()->addSpacing( 5 );
137  dlg->layout()->addWidget( label );
138  }
139 
140  // license file
141  QString licenseFile = mRamp->info().value( "cpt-city-license" );
142  if ( !licenseFile.isNull() )
143  {
144  QString fileName = licenseFile;
145  fileName.replace( "<cpt-city>", QgsCptCityArchive::defaultBaseDir() );
146  if ( ! QFile::exists( fileName ) )
147  {
148  fileName = licenseFile;
149  fileName.replace( "<cpt-city>", "http://soliton.vm.bytemark.co.uk/pub/cpt-city" );
150  }
151  label = new QLabel( tr( "License file : %1" ).arg( fileName ), dlg );
152  label->setTextInteractionFlags( Qt::TextBrowserInteraction );
153  dlg->layout()->addSpacing( 5 );
154  dlg->layout()->addWidget( label );
155  if ( QFile::exists( fileName ) )
156  {
157  QTextEdit *textEdit = new QTextEdit( dlg );
158  textEdit->setReadOnly( true );
159  QFile file( fileName );
160  if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
161  {
162  textEdit->setText( file.readAll() );
163  file.close();
164  dlg->layout()->addSpacing( 5 );
165  dlg->layout()->addWidget( textEdit );
166  dlg->resize( 600, 500 );
167  }
168  }
169  }
170 
171  dlg->show(); //non modal
172 }
173 
175 {
176  QgsGradientStopsList stops = mRamp->stops();
177  groupStops->setChecked( !stops.isEmpty() );
178 
180  for ( QgsGradientStopsList::iterator it = stops.begin();
181  it != stops.end(); ++it )
182  {
183  double val = it->offset * 100.0;
184  QStringList lst;
185  lst << "." << QString(( val < 10 ) ? '0' + QString::number( val ) : QString::number( val ) );
186  QTreeWidgetItem* item = new QTreeWidgetItem( lst );
187 
188  setStopColor( item, it->color );
189  item->setData( 0, StopOffsetRole, it->offset );
190 
191  items.append( item );
192  }
193  treeStops->clear();
194  treeStops->insertTopLevelItems( 0, items );
195  treeStops->resizeColumnToContents( 0 );
196  treeStops->setColumnWidth( 0, treeStops->columnWidth( 0 ) + 20 );
197  treeStops->sortByColumn( 1, Qt::AscendingOrder );
198  treeStops->setSortingEnabled( true );
199 }
200 
202 {
203  // update ramp stops from the tree widget
204  QgsGradientStopsList stops;
205  if ( groupStops->isChecked() )
206  {
207  int count = treeStops->topLevelItemCount();
208  stops.reserve( count );
209  for ( int i = 0; i < count; i++ )
210  {
211  QTreeWidgetItem* item = treeStops->topLevelItem( i );
212  double offset = item->data( 0, StopOffsetRole ).toDouble();
213  QColor color = item->data( 0, StopColorRole ).value<QColor>();
214  stops.append( QgsGradientStop( offset, color ) );
215  }
216  }
217  mRamp->setStops( stops );
218 
219  // generate the preview
220  QSize size( 300, 40 );
221  lblPreview->setPixmap( QgsSymbolLayerV2Utils::colorRampPreviewPixmap( mRamp, size ) );
222 
223  btnColor1->blockSignals( true );
224  btnColor1->setColor( mRamp->color1() );
225  btnColor1->blockSignals( false );
226  btnColor2->blockSignals( true );
227  btnColor2->setColor( mRamp->color2() );
228  btnColor2->blockSignals( false );
229 }
230 
232 {
233  mRamp->setColor1( color );
234  updatePreview();
235 }
236 
238 {
239  mRamp->setColor2( color );
240  updatePreview();
241 }
242 
244 {
245  QSize iconSize( 16, 16 );
246  QPixmap pixmap( iconSize );
247  pixmap.fill( QColor( 0, 0, 0, 0 ) );
248  QRect rect( 1, 1, iconSize.width() - 2, iconSize.height() - 2 );
249 
250  // draw a slightly rounded rectangle
251  QPainter p;
252  p.begin( &pixmap );
253  p.setPen( Qt::NoPen );
254  p.setRenderHint( QPainter::Antialiasing );
255  p.setBrush( color );
256  p.drawRoundedRect( rect, 2, 2 );
257  p.end();
258 
259  item->setIcon( 0, QIcon( pixmap ) );
260  item->setData( 0, StopColorRole, color );
261  item->setText( 0, color.name() );
262 }
263 
265 {
266  if ( mCurrentItem )
267  {
268  setStopColor( mCurrentItem, newColor );
269  updatePreview();
270  }
271 }
272 
274 {
275  if ( column == 0 )
276  {
277  QColor color;
278 
279  QSettings settings;
280  //using native color dialogs?
281  bool useNative = settings.value( "/qgis/native_color_dialogs", false ).toBool();
282  if ( settings.value( "/qgis/live_color_dialogs", false ).toBool() )
283  {
284  mCurrentItem = item;
285  if ( useNative )
286  {
288  item->data( 0, StopColorRole ).value<QColor>(),
289  this, SLOT( setItemStopColor( const QColor& ) ),
290  this, tr( "Edit Stop Color" ), QColorDialog::ShowAlphaChannel );
291  }
292  else
293  {
295  item->data( 0, StopColorRole ).value<QColor>(), this, SLOT( setItemStopColor( const QColor& ) ),
296  this, tr( "Edit Stop Color" ), true );
297  }
298  mCurrentItem = nullptr;
299  }
300  else
301  {
302  color = QgsColorDialogV2::getColor( item->data( 0, StopColorRole ).value<QColor>(), this, tr( "Edit Stop Color" ), true );
303  }
304  if ( !color.isValid() )
305  return;
306  setStopColor( item, color );
307 
308  updatePreview();
309  }
310  else
311  {
312  bool ok;
313  double key = item->data( 0, StopOffsetRole ).toDouble();
314  // allow for floating-point values
315  double val = key * 100;
316  val = QInputDialog::getDouble( this, tr( "Offset of the stop" ),
317  tr( "Please enter offset in percents (%) of the new stop" ),
318  val, 0, 100, 2, &ok );
319  if ( !ok )
320  return;
321 
322  double newkey = val / 100.0;
323  item->setText( 1, ( val < 10 ) ? '0' + QString::number( val ) : QString::number( val ) );
324  item->setData( 0, StopOffsetRole, newkey );
325 
326  updatePreview();
327  }
328 }
329 
331 {
332 // Native Mac dialog works only for Qt Carbon
333 // Qt bug: http://bugreports.qt.nokia.com/browse/QTBUG-14889
334 // Qt 4.7 Mac Cocoa bug: calling QInputDialog::getInt after QColorDialog::getColor will freeze app
335 // workaround: call QColorDialog::getColor below instead of here,
336 // but not needed at this time because of the other Qt bug
337 // FIXME need to also check max QT_VERSION when Qt bug(s) fixed
338 #ifndef Q_OS_MAC
339  QColor color = QgsColorDialogV2::getColor( QColor(), this, tr( "Add Color Stop" ), true );
340 
341  if ( !color.isValid() )
342  return;
343  activateWindow();
344 #endif
345 
346  bool ok;
347  double val = 50.0;
348  val = QInputDialog::getDouble( this, tr( "Offset of the stop" ),
349  tr( "Please enter offset in percents (%) of the new stop" ),
350  val, 0, 100, 2, &ok );
351  if ( !ok )
352  return;
353  activateWindow();
354 
355  double key = val / 100.0;
356  QStringList lst;
357  lst << "." << QString(( val < 10 ) ? '0' + QString::number( val ) : QString::number( val ) );
358 
359 #ifdef Q_OS_MAC
360  QColor color = QgsColorDialogV2::getColor( QColor(), this, tr( "Add Color Stop" ), true );
361 
362  if ( !color.isValid() )
363  return;
364  activateWindow();
365 #endif
366 
367  QTreeWidgetItem* item = new QTreeWidgetItem( lst );
368 
369  setStopColor( item, color );
370  item->setData( 0, StopOffsetRole, key );
371 
372  treeStops->addTopLevelItem( item );
373 
374  treeStops->resizeColumnToContents( 0 );
375  treeStops->setColumnWidth( 0, treeStops->columnWidth( 0 ) + 20 );
376 
377  updatePreview();
378 }
379 
381 {
382  QTreeWidgetItem* item = treeStops->currentItem();
383  if ( !item )
384  return;
385  int index = treeStops->indexOfTopLevelItem( item );
386  treeStops->takeTopLevelItem( index );
387 
388  updatePreview();
389 }
390 
392 {
393  Q_UNUSED( on );
394  updatePreview();
395 }
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