1 /***************************************************************************
2     qgscptcitycolorrampdialog.cpp
3     ---------------------
4     begin                : July 2012
5     copyright            : (C) 2012 by Etienne Tourigny
6     email                : etourigny dot dev at gmail.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 
16 #include "qgscptcitycolorrampdialog.h"
17 
18 #include "qgscptcityarchive.h"
19 #include "qgscolorramp.h"
20 #include "qgslogger.h"
21 #include "qgsapplication.h"
22 #include "qgsdialog.h"
23 #include "qgssymbollayerutils.h"
24 #include "qgssettings.h"
25 #include "qgsgui.h"
26 
27 #include <QPushButton>
28 #include <QTextEdit>
29 #include <QTime>
30 #include <QMessageBox>
31 #include <QSortFilterProxyModel>
32 
33 /////////
34 
35 // TODO
36 // - fix Diverging children when first show Selections
37 // - fix crash on Diverging?
38 
39 
QgsCptCityColorRampDialog(const QgsCptCityColorRamp & ramp,QWidget * parent)40 QgsCptCityColorRampDialog::QgsCptCityColorRampDialog( const QgsCptCityColorRamp &ramp, QWidget *parent )
41   : QDialog( parent )
42   , mRamp( ramp )
43   , mArchiveViewType( QgsCptCityBrowserModel::Selections )
44 {
45   setupUi( this );
46   QgsGui::instance()->enableAutoGeometryRestore( this );
47   connect( mTreeView, &QTreeView::clicked, this, &QgsCptCityColorRampDialog::mTreeView_clicked );
48   connect( mListWidget, &QListWidget::itemClicked, this, &QgsCptCityColorRampDialog::mListWidget_itemClicked );
49   connect( mListWidget, &QListWidget::itemSelectionChanged, this, &QgsCptCityColorRampDialog::mListWidget_itemSelectionChanged );
50   connect( tabBar, &QTabBar::currentChanged, this, &QgsCptCityColorRampDialog::tabBar_currentChanged );
51   connect( pbtnLicenseDetails, &QToolButton::pressed, this, &QgsCptCityColorRampDialog::pbtnLicenseDetails_pressed );
52   connect( cboVariantName, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsCptCityColorRampDialog::cboVariantName_currentIndexChanged );
53   connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsCptCityColorRampDialog::showHelp );
54 
55   mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
56 
57   const QgsSettings settings;
58   mSplitter->setSizes( QList<int>() << 250 << 550 );
59   mSplitter->restoreState( settings.value( QStringLiteral( "Windows/CptCityColorRampV2Dialog/splitter" ) ).toByteArray() );
60 
61   mModel = mAuthorsModel = mSelectionsModel = nullptr; //mListModel = 0;
62   mTreeFilter = nullptr;
63 
64   QgsCptCityArchive::initDefaultArchive();
65   mArchive = QgsCptCityArchive::defaultArchive();
66 
67   // show information on how to install cpt-city files if none are found
68   if ( ! mArchive || mArchive->isEmpty() )
69   {
70     // QgsDialog dlg( this );
71     // dlg.setWindowTitle( tr( "Cpt-city Gradient Files Not Found" ) );
72     QTextEdit *edit = new QTextEdit( nullptr );
73     edit->setReadOnly( true );
74     // not sure if we want this long string to be translated
75     const QString helpText = tr( "Error - cpt-city gradient files not found.\n\n"
76                                  "You have two means of installing them:\n\n"
77                                  "1) Install the \"Color Ramp Manager\" python plugin "
78                                  "(you must enable Experimental plugins in the plugin manager) "
79                                  "and use it to download latest cpt-city package.\n"
80                                  "You can install the entire cpt-city archive or a selection for QGIS.\n\n"
81                                  "2) Download the complete archive (in svg format) "
82                                  "and unzip it to your QGIS settings directory [%1] .\n\n"
83                                  "This file can be found at [%2]\nand current file is [%3]"
84                                ).arg( QgsApplication::qgisSettingsDirPath(),
85                                       QStringLiteral( "http://soliton.vm.bytemark.co.uk/pub/cpt-city/pkg/" ),
86                                       QStringLiteral( "http://soliton.vm.bytemark.co.uk/pub/cpt-city/pkg/cpt-city-svg-2.07.zip" ) );
87     edit->setText( helpText );
88     mStackedWidget->addWidget( edit );
89     mStackedWidget->setCurrentIndex( 1 );
90     tabBar->setVisible( false );
91     // dlg.layout()->addWidget( edit );
92     // dlg.resize(500,400);
93     // dlg.exec();
94     return;
95   }
96 
97   if ( ! mArchive )
98     return;
99   QgsDebugMsg( "archive: " + mArchive->archiveName() );
100 
101   QgsDebugMsg( QStringLiteral( "ramp name= %1 variant= %2 - %3 variants" ).arg( mRamp.schemeName(), mRamp.variantName() ).arg( mRamp.variantList().count() ) );
102 
103   // model / view
104   QgsDebugMsg( QStringLiteral( "loading model/view objects" ) );
105 
106   delete mAuthorsModel;
107   mAuthorsModel = new QgsCptCityBrowserModel( this, mArchive, QgsCptCityBrowserModel::Authors );
108 
109   delete mSelectionsModel;
110   mSelectionsModel = new QgsCptCityBrowserModel( this, mArchive, QgsCptCityBrowserModel::Selections );
111   setTreeModel( mSelectionsModel );
112 
113   mTreeView->setSelectionMode( QAbstractItemView::SingleSelection );
114   mTreeView->setColumnHidden( 1, true );
115   QgsDebugMsg( QStringLiteral( "done loading model/view objects" ) );
116 
117   // setup ui
118   tabBar->blockSignals( true );
119   tabBar->addTab( tr( "Selections by theme" ) );
120   tabBar->addTab( tr( "All by author" ) );
121   cboVariantName->setIconSize( QSize( 100, 15 ) );
122   lblPreview->installEventFilter( this ); // mouse click on preview label shows svg render
123 
124   updateUi();
125 
126   tabBar->blockSignals( false );
127 
128   connect( this, &QDialog::finished, this, &QgsCptCityColorRampDialog::onFinished );
129 
130 }
131 
setRamp(const QgsCptCityColorRamp & ramp)132 void QgsCptCityColorRampDialog::setRamp( const QgsCptCityColorRamp &ramp )
133 {
134   mRamp = ramp;
135   updateUi();
136 }
137 
populateVariants()138 void QgsCptCityColorRampDialog::populateVariants()
139 {
140   const QStringList variantList = mRamp.variantList();
141 
142   QgsDebugMsg( QStringLiteral( "ramp %1%2 has %3 variants" ).arg( mRamp.schemeName(), mRamp.variantName() ).arg( variantList.count() ) );
143 
144   cboVariantName->blockSignals( true );
145   cboVariantName->clear();
146 
147   if ( variantList.isEmpty() )
148   {
149     cboVariantName->setEnabled( false );
150     cboVariantName->setVisible( false );
151     cboVariantName_currentIndexChanged( -1 );
152   }
153   else
154   {
155     // populate variant combobox
156     const QString oldVariant = cboVariantName->currentText();
157     QgsCptCityColorRamp ramp( mRamp.schemeName(), mRamp.variantList(), QString() );
158     QPixmap blankPixmap( cboVariantName->iconSize() );
159     blankPixmap.fill( Qt::white );
160     const QIcon blankIcon( blankPixmap );
161     int index;
162 
163     const auto constVariantList = variantList;
164     for ( const QString &variant : constVariantList )
165     {
166       QString variantStr = variant;
167       if ( variantStr.startsWith( '-' ) || variantStr.startsWith( '_' ) )
168         variantStr.remove( 0, 1 );
169       cboVariantName->addItem( ' ' + variantStr );
170       index = cboVariantName->count() - 1;
171       cboVariantName->setItemData( index, variant, Qt::UserRole );
172 
173       ramp.setVariantName( variant );
174       if ( ramp.loadFile() )
175         cboVariantName->setItemIcon( index,
176                                      QgsSymbolLayerUtils::colorRampPreviewIcon( &ramp, cboVariantName->iconSize() ) );
177       else
178         cboVariantName->setItemIcon( index, blankIcon );
179       cboVariantName->setItemData( index, Qt::AlignHCenter, Qt::TextAlignmentRole );
180     }
181 
182     cboVariantName->blockSignals( false );
183 
184     // try to set the original variant again (if exists)
185     int idx = -1;
186     QString newVariant = mRamp.variantName();
187     QgsDebugMsg( QStringLiteral( "variant= %1 - %2 variants" ).arg( mRamp.variantName() ).arg( mRamp.variantList().count() ) );
188     if ( newVariant != QString() )
189     {
190       if ( newVariant.startsWith( '-' ) || newVariant.startsWith( '_' ) )
191         newVariant.remove( 0, 1 );
192       newVariant = ' ' + newVariant;
193       idx = cboVariantName->findText( newVariant );
194     }
195     else
196       idx = cboVariantName->findText( oldVariant );
197 
198     // if not found use the item in the middle
199     if ( idx == -1 )
200     {
201       idx = cboVariantName->count() / 2;
202     }
203     cboVariantName->setCurrentIndex( idx );
204     // updatePreview();
205 
206     cboVariantName->setEnabled( true );
207     cboVariantName->setVisible( true );
208   }
209 
210 }
211 
mTreeView_clicked(const QModelIndex & index)212 void QgsCptCityColorRampDialog::mTreeView_clicked( const QModelIndex &index )
213 {
214   const QModelIndex &sourceIndex = mTreeFilter->mapToSource( index );
215   QgsCptCityDataItem *item = mModel->dataItem( sourceIndex );
216   if ( ! item )
217     return;
218   QgsDebugMsg( QStringLiteral( "item %1 clicked" ).arg( item->name() ) );
219   mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
220   updateTreeView( item );
221 }
222 
updateTreeView(QgsCptCityDataItem * item,bool resetRamp)223 void QgsCptCityColorRampDialog::updateTreeView( QgsCptCityDataItem *item, bool resetRamp )
224 {
225   if ( ! item )
226   {
227     QgsDebugMsg( QStringLiteral( "invalid item" ) );
228     return;
229   }
230   if ( item->type() == QgsCptCityDataItem::Directory )
231   {
232     if ( resetRamp )
233     {
234       mRamp.setName( QString(), QString() );
235       QgsDebugMsg( QStringLiteral( "variant= %1 - %2 variants" ).arg( mRamp.variantName() ).arg( mRamp.variantList().count() ) );
236       lblSchemeName->clear();
237       populateVariants();
238     }
239     updateListWidget( item );
240     lblSchemePath->setText( item->path() );
241     lblCollectionInfo->setText( QStringLiteral( "%1 (%2)" ).arg( item->info() ).arg( item->leafCount() ) );
242     updateCopyingInfo( mArchive->copyingInfo( mArchive->copyingFileName( item->path() ) ) );
243   }
244   else if ( item->type() == QgsCptCityDataItem::Selection )
245   {
246     lblSchemePath->clear();
247     clearCopyingInfo();
248     updateListWidget( item );
249     lblCollectionInfo->setText( QStringLiteral( "%1 (%2)" ).arg( item->info() ).arg( item->leafCount() ) );
250   }
251   else if ( item->type() == QgsCptCityDataItem::AllRamps )
252   {
253     lblSchemePath->clear();
254     clearCopyingInfo();
255     updateListWidget( item );
256     lblCollectionInfo->setText( tr( "All Ramps (%1)" ).arg( item->leafCount() ) );
257   }
258   else
259   {
260     QgsDebugMsg( QStringLiteral( "item %1 has invalid type %2" ).arg( item->path() ).arg( static_cast<int>( item->type() ) ) );
261   }
262 }
263 
mListWidget_itemClicked(QListWidgetItem * item)264 void QgsCptCityColorRampDialog::mListWidget_itemClicked( QListWidgetItem *item )
265 {
266   QgsCptCityColorRampItem *rampItem = mListRamps.at( item->data( Qt::UserRole ).toInt() );
267   if ( rampItem )
268   {
269     mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( true );
270     lblSchemeName->setText( QFileInfo( rampItem->name() ).fileName() );
271     mRamp.copy( &rampItem->ramp() );
272     QgsDebugMsg( QStringLiteral( "variant= %1 - %2 variants" ).arg( mRamp.variantName() ).arg( mRamp.variantList().count() ) );
273     populateVariants();
274   }
275   else
276   {
277     QgsDebugMsg( QStringLiteral( "invalid item" ) );
278   }
279 }
280 
mListWidget_itemSelectionChanged()281 void QgsCptCityColorRampDialog::mListWidget_itemSelectionChanged()
282 {
283   if ( mListWidget->selectedItems().isEmpty() )
284   {
285     mRamp.setName( QString(), QString() );
286   }
287 }
288 
tabBar_currentChanged(int index)289 void QgsCptCityColorRampDialog::tabBar_currentChanged( int index )
290 {
291   if ( index == 0 )
292   {
293     setTreeModel( mSelectionsModel );
294     mArchiveViewType = QgsCptCityBrowserModel::Selections;
295   }
296   else if ( index == 1 )
297   {
298     setTreeModel( mAuthorsModel );
299     mArchiveViewType = QgsCptCityBrowserModel::Authors;
300   }
301   else
302   {
303     QgsDebugMsg( QStringLiteral( "invalid index %1" ).arg( index ) );
304     setTreeModel( mAuthorsModel );
305     mArchiveViewType = QgsCptCityBrowserModel::Authors;
306   }
307 
308   mListWidget->blockSignals( true );
309   updateRamp();
310   mListWidget->blockSignals( false );
311 }
312 
313 
pbtnLicenseDetails_pressed()314 void QgsCptCityColorRampDialog::pbtnLicenseDetails_pressed()
315 {
316   QString path, title, copyFile, descFile;
317 
318   // get basic information, depending on if is color ramp or directory
319   QgsCptCityDataItem *item = mModel->dataItem( mTreeFilter->mapToSource( mTreeView->currentIndex() ) );
320   if ( ! item )
321     return;
322 
323   path = item->path();
324   if ( item->type() == QgsCptCityDataItem::Directory )
325   {
326     title = tr( "%1 Directory Details" ).arg( item->path() );
327   }
328   else if ( item->type() == QgsCptCityColorRampItem::Directory )
329   {
330     title = tr( "%1 Gradient Details" ).arg( path );
331   }
332   else
333   {
334     return;
335   }
336   copyFile = mArchive->copyingFileName( path );
337   descFile = mArchive->descFileName( path );
338 
339   // prepare dialog
340   QgsDialog dlg( this, Qt::WindowFlags(), QDialogButtonBox::Close );
341   QVBoxLayout *layout = dlg.layout();
342   dlg.setWindowTitle( title );
343   QTextEdit *textEdit = new QTextEdit( &dlg );
344   textEdit->setReadOnly( true );
345   layout->addWidget( textEdit );
346 
347   // add contents of DESC.xml and COPYING.xml
348   QString copyText;
349   if ( ! copyFile.isNull() )
350   {
351     QFile file( copyFile );
352     if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
353     {
354       copyText = QString( file.readAll() );
355       file.close();
356     }
357   }
358   QString descText;
359   if ( ! descFile.isNull() )
360   {
361     QFile file( descFile );
362     if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
363     {
364       descText = QString( file.readAll() );
365       file.close();
366     }
367   }
368   textEdit->insertPlainText( title + "\n\n" );
369   textEdit->insertPlainText( QStringLiteral( "===================" ) );
370   textEdit->insertPlainText( QStringLiteral( " copying " ) );
371   textEdit->insertPlainText( QStringLiteral( "===================\n" ) );
372   textEdit->insertPlainText( copyText );
373   textEdit->insertPlainText( QStringLiteral( "\n" ) );
374   textEdit->insertPlainText( QStringLiteral( "==================" ) );
375   textEdit->insertPlainText( QStringLiteral( " description " ) );
376   textEdit->insertPlainText( QStringLiteral( "==================\n" ) );
377   textEdit->insertPlainText( descText );
378   textEdit->moveCursor( QTextCursor::Start );
379 
380   dlg.resize( 600, 600 );
381   dlg.exec();
382 }
383 
updatePreview(bool clear)384 void QgsCptCityColorRampDialog::updatePreview( bool clear )
385 {
386   const QSize size = lblPreview->size();
387 
388   if ( clear || mRamp.schemeName().isEmpty() )
389   {
390     lblSchemeName->clear();
391     lblSchemePath->clear();
392     lblLicensePreview->clear();
393     QPixmap blankPixmap( size );
394     blankPixmap.fill( Qt::transparent );
395     lblPreview->setPixmap( blankPixmap );
396     return;
397   }
398 
399   mRamp.loadFile();
400 
401   lblSchemePath->setText( mRamp.schemeName() + mRamp.variantName() );
402 
403   // update pixmap
404   // TODO draw checker-board/transparent background
405   // for transparent, add  [ pixmap.fill( Qt::transparent ); ] to QgsSymbolLayerUtils::colorRampPreviewPixmap
406   const QPixmap pixmap = QgsSymbolLayerUtils::colorRampPreviewPixmap( &mRamp, size );
407   lblPreview->setPixmap( pixmap );
408 
409   // add copyright information from COPYING.xml file
410   updateCopyingInfo( mRamp.copyingInfo() );
411 }
412 
clearCopyingInfo()413 void QgsCptCityColorRampDialog::clearCopyingInfo()
414 {
415   updateCopyingInfo( QMap< QString, QString >() );
416 }
417 
updateCopyingInfo(const QMap<QString,QString> & copyingMap)418 void QgsCptCityColorRampDialog::updateCopyingInfo( const QMap< QString, QString > &copyingMap )
419 {
420   QString authorStr = copyingMap.value( QStringLiteral( "authors" ) );
421   if ( authorStr.length() > 80 )
422     authorStr.replace( authorStr.indexOf( ' ', 80 ), 1, QStringLiteral( "\n" ) );
423   lblAuthorName->setText( authorStr );
424   QString licenseStr = copyingMap.value( QStringLiteral( "license/informal" ) );
425   if ( copyingMap.contains( QStringLiteral( "license/year" ) ) )
426     licenseStr += " (" + copyingMap.value( QStringLiteral( "license/year" ) ) + ')';
427   if ( licenseStr.length() > 80 )
428     licenseStr.replace( licenseStr.indexOf( ' ', 80 ), 1, QStringLiteral( "\n" ) );
429   if ( copyingMap.contains( QStringLiteral( "license/url" ) ) )
430     licenseStr += "\n[ " + copyingMap.value( QStringLiteral( "license/url" ) ) + " ]";
431   else
432     licenseStr += '\n';
433   lblLicenseName->setText( licenseStr );
434   licenseStr.replace( '\n', QLatin1String( "  " ) );
435   lblLicensePreview->setText( licenseStr );
436   lblLicensePreview->setCursorPosition( 0 );
437   if ( copyingMap.contains( QStringLiteral( "src/link" ) ) )
438     lblSrcLink->setText( copyingMap.value( QStringLiteral( "src/link" ) ) );
439   else
440     lblSrcLink->clear();
441 }
442 
cboVariantName_currentIndexChanged(int index)443 void QgsCptCityColorRampDialog::cboVariantName_currentIndexChanged( int index )
444 {
445   Q_UNUSED( index )
446   if ( cboVariantName->currentIndex() != -1 )
447     mRamp.setVariantName( cboVariantName->currentData( Qt::UserRole ).toString() );
448   QgsDebugMsg( QStringLiteral( "variant= %1 - %2 variants" ).arg( mRamp.variantName() ).arg( mRamp.variantList().count() ) );
449   updatePreview();
450   emit changed();
451 }
452 
onFinished()453 void QgsCptCityColorRampDialog::onFinished()
454 {
455   // save settings
456   QgsSettings settings;
457   settings.setValue( QStringLiteral( "Windows/CptCityColorRampV2Dialog/splitter" ), mSplitter->saveState() );
458 }
459 
showHelp()460 void QgsCptCityColorRampDialog::showHelp()
461 {
462   // show error message to use color ramp manager to get more gradients
463   const QString helpText = tr( "You can download a more complete set of cpt-city gradients "
464                                "by installing the \"Color Ramp Manager\" plugin "
465                                "(you must enable Experimental plugins in the plugin manager).\n\n"
466                              );
467   QMessageBox *msg = new QMessageBox( this );
468   msg->setWindowTitle( tr( "Download More Cpt-city Gradients" ) );
469   msg->setText( helpText );
470   msg->exec();
471 }
472 
updateUi()473 void QgsCptCityColorRampDialog::updateUi()
474 {
475   // look for item, if not found in selections archive, look for in authors
476   QgsDebugMsg( "looking for ramp " + mRamp.schemeName() );
477   if ( !mRamp.schemeName().isEmpty() )
478   {
479     bool found = updateRamp();
480     if ( ! found )
481     {
482       tabBar->setCurrentIndex( 1 );
483       setTreeModel( mAuthorsModel );
484       found = updateRamp();
485       // if not found, go back to selections model
486       if ( ! found )
487       {
488         tabBar->setCurrentIndex( 0 );
489         setTreeModel( mSelectionsModel );
490       }
491     }
492     if ( found )
493       mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( true );
494   }
495   else
496   {
497     updateRamp();
498   }
499 }
500 
saveAsGradientRamp() const501 bool QgsCptCityColorRampDialog::saveAsGradientRamp() const
502 {
503   QgsDebugMsg( QStringLiteral( "result: %1 checked: %2" ).arg( result() ).arg( cboConvertStandard->isChecked() ) );
504   // if "save as standard gradient" is checked, convert to QgsVectorGradientColorRamp
505   return ( result() == Accepted && cboConvertStandard->isChecked() );
506 }
507 
buttonBox() const508 QDialogButtonBox *QgsCptCityColorRampDialog::buttonBox() const
509 {
510   return mButtonBox;
511 }
512 
updateListWidget(QgsCptCityDataItem * item)513 void QgsCptCityColorRampDialog::updateListWidget( QgsCptCityDataItem *item )
514 {
515   mListWidget->blockSignals( true );
516   mListWidget->clear();
517   mListRamps.clear();
518   QgsCptCityCollectionItem *colItem = qobject_cast<QgsCptCityCollectionItem *>( item );
519   if ( colItem )
520   {
521     QgsDebugMsg( "path= " + item->path() );
522     // recursively get children ramps
523     QVector<QgsCptCityDataItem *> childrenRamps = colItem->childrenRamps( true );
524     for ( int i = 0; i < childrenRamps.count(); i++ )
525     {
526       QgsCptCityColorRampItem *rampItem = qobject_cast<QgsCptCityColorRampItem *>( childrenRamps[i] );
527       if ( ! rampItem )
528       {
529         QgsDebugMsg( "invalid item " + childrenRamps[i]->path() );
530         continue;
531       }
532       QListWidgetItem *listItem = new QListWidgetItem();
533       listItem->setText( rampItem->shortInfo() );
534       listItem->setIcon( rampItem->icon( QSize( 75, 50 ) ) );
535       listItem->setToolTip( rampItem->path() + '\n' + rampItem->info() );
536       listItem->setData( Qt::UserRole, QVariant( i ) );
537       mListWidget->addItem( listItem );
538       mListRamps << rampItem;
539     }
540   }
541   else
542   {
543     QgsDebugMsg( QStringLiteral( "invalid item" ) );
544   }
545   mListWidget->blockSignals( false );
546 }
547 
548 // this function is for a svg preview, available if the svg files have been processed with svgx
549 // e.g. for f in `ls */*/*/*/*.svg`; do echo $f ; svgx -p -t svg $f > tmp1.svg; mv tmp1.svg $f; done
550 // perhaps a future version of the cpt-city svg gradients will have them by default
eventFilter(QObject * obj,QEvent * event)551 bool QgsCptCityColorRampDialog::eventFilter( QObject *obj, QEvent *event )
552 {
553   const QSize size = lblPreview->size();
554 
555   if ( event->type() == QEvent::MouseButtonPress )
556   {
557     // create preview from svg file if supported - depends on file versions
558     const QPixmap pixmap( mRamp.fileName() );
559     if ( ! pixmap.isNull() )
560       lblPreview->setPixmap( pixmap.scaled( size ) );
561     return true;
562   }
563   else if ( event->type() == QEvent::MouseButtonRelease )
564   {
565     // restore preview
566     const QPixmap pixmap = QgsSymbolLayerUtils::colorRampPreviewPixmap( &mRamp, size );
567     lblPreview->setPixmap( pixmap );
568     return true;
569   }
570   else
571   {
572     // standard event processing
573     return QDialog::eventFilter( obj, event );
574   }
575 }
576 
updateRamp()577 bool QgsCptCityColorRampDialog::updateRamp()
578 {
579   mListWidget->clear();
580   mListRamps.clear();
581   cboVariantName->clear();
582   clearCopyingInfo();
583   lblCollectionInfo->clear();
584 
585   mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
586   updatePreview( true );
587 
588   QgsDebugMsg( "schemeName= " + mRamp.schemeName() );
589   if ( mRamp.schemeName().isEmpty() )
590   {
591     showAll();
592     return false;
593   }
594 
595   // search for item in model
596   const QModelIndex modelIndex = mModel->findPath( mRamp.schemeName() );
597   if ( modelIndex == QModelIndex() )
598   {
599     return false;
600   }
601   QgsCptCityColorRampItem *childItem =
602     qobject_cast<QgsCptCityColorRampItem *>( mModel->dataItem( modelIndex ) );
603   if ( ! childItem )
604     return false;
605   if ( mRamp.schemeName() != childItem->ramp().schemeName() )
606     return false;
607 
608   // found child, set mRamp variantList
609   // mRamp.copy( &childItem->ramp() );
610   mRamp.setVariantList( childItem->ramp().variantList() );
611 
612   // found child, update tree
613   QgsDebugMsg( QStringLiteral( "found item %1" ).arg( mRamp.schemeName() ) );
614   lblSchemeName->setText( QFileInfo( mRamp.schemeName() ).fileName() );
615   const QModelIndex parentIndex = modelIndex.parent();
616   const QModelIndex selIndex = mTreeFilter->mapFromSource( parentIndex );
617 
618   // QgsDebugMsg(QString("parent row=%1 path=%2 parentRow=%3").arg(parentIndex.row()).arg(mModel->dataItem( parentIndex )->path()).arg(parentIndex.parent().row()));
619   mTreeView->setCurrentIndex( selIndex );
620   mTreeView->setExpanded( selIndex, true );
621   mTreeView->scrollTo( selIndex, QAbstractItemView::PositionAtCenter );
622   updateTreeView( mModel->dataItem( parentIndex ), false );
623 
624   // update listWidget, find appropriate item in mListRamps
625   for ( int i = 0; i < mListRamps.count(); i++ )
626   {
627     if ( mListRamps.at( i ) == childItem )
628     {
629       QgsDebugMsg( QStringLiteral( "found matching item %1 target=%2" ).arg( mListRamps.at( i )->path(), childItem->path() ) );
630       QListWidgetItem *listItem = mListWidget->item( i );
631       mListWidget->setCurrentItem( listItem );
632       // mListWidget_itemClicked( listItem );
633       populateVariants();
634       mListWidget->scrollToItem( listItem, QAbstractItemView::EnsureVisible );
635       // mListView->selectionModel()->select( childIndex, QItemSelectionModel::Select );
636       mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( true );
637       emit changed();
638       return true;
639     }
640   }
641 
642   return false;
643 }
644 
showAll()645 void QgsCptCityColorRampDialog::showAll()
646 {
647   const QModelIndex modelIndex = mModel->findPath( QString() );
648   if ( modelIndex != QModelIndex() )
649   {
650     const QModelIndex selIndex = mTreeFilter->mapFromSource( modelIndex );
651     mTreeView->setCurrentIndex( selIndex );
652     mTreeView->setExpanded( selIndex, true );
653     mTreeView->scrollTo( selIndex, QAbstractItemView::PositionAtCenter );
654     updateTreeView( mModel->dataItem( modelIndex ), false );
655   }
656 }
657 
setTreeModel(QgsCptCityBrowserModel * model)658 void QgsCptCityColorRampDialog::setTreeModel( QgsCptCityBrowserModel *model )
659 {
660   mModel = model;
661 
662   delete mTreeFilter;
663   mTreeFilter = new TreeFilterProxyModel( this, mModel );
664   mTreeView->setModel( mTreeFilter );
665 }
666 
667 #if 0
668 void QgsCptCityColorRampDialog::refresh()
669 {
670   QApplication::setOverrideCursor( Qt::WaitCursor );
671   refreshModel( QModelIndex() );
672   QApplication::restoreOverrideCursor();
673 }
674 
675 void QgsCptCityColorRampDialog::refreshModel( const QModelIndex &index )
676 {
677   if ( index.isValid() )
678   {
679     QgsCptCityDataItem *item = mModel->dataItem( index );
680     if ( item )
681     {
682       QgsDebugMsg( "path = " + item->path() );
683     }
684     else
685     {
686       QgsDebugMsg( QStringLiteral( "invalid item" ) );
687     }
688   }
689 
690   mModel->refresh( index );
691 
692   for ( int i = 0; i < mModel->rowCount( index ); i++ )
693   {
694     QModelIndex idx = mModel->index( i, 0, index );
695     if ( mTreeView->isExpanded( idx ) || !mModel->hasChildren( idx ) )
696     {
697       refreshModel( idx );
698     }
699   }
700 }
701 #endif
702 
703 /// @cond PRIVATE
704 
TreeFilterProxyModel(QObject * parent,QgsCptCityBrowserModel * model)705 TreeFilterProxyModel::TreeFilterProxyModel( QObject *parent, QgsCptCityBrowserModel *model )
706   : QSortFilterProxyModel( parent )
707   , mModel( model )
708 {
709   setSourceModel( mModel );
710 }
711 
filterAcceptsRow(int sourceRow,const QModelIndex & sourceParent) const712 bool TreeFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
713 {
714   QgsCptCityDataItem *item = mModel->dataItem( mModel->index( sourceRow, 0, sourceParent ) );
715   return ( item && !( item->type() == QgsCptCityDataItem::ColorRamp ) );
716 }
717 
718 
719 ///@endcond
720