18 #include "ui_qgsstyleexportimportdialogbase.h" 
   34 #include <QInputDialog> 
   35 #include <QCloseEvent> 
   36 #include <QFileDialog> 
   37 #include <QMessageBox> 
   38 #include <QNetworkReply> 
   39 #include <QProgressDialog> 
   40 #include <QPushButton> 
   41 #include <QStandardItemModel> 
   42 #include <QTemporaryFile> 
   54   QPushButton *pb = 
nullptr;
 
   55   pb = 
new QPushButton( tr( 
"Select All" ) );
 
   56   buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
 
   59   pb = 
new QPushButton( tr( 
"Clear Selection" ) );
 
   60   buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
 
   63   mTempStyle = std::make_unique< QgsStyle >();
 
   64   mTempStyle->createMemoryDatabase();
 
   67   mGroupSelectionDlg = 
nullptr;
 
   71   if ( mDialogMode == 
Import )
 
   73     setWindowTitle( tr( 
"Import Item(s)" ) );
 
   75     importTypeCombo->addItem( tr( 
"File" ), ImportSource::File );
 
   77     importTypeCombo->addItem( tr( 
"URL" ), ImportSource::Url );
 
   81     mSymbolTags->setText( QStringLiteral( 
"imported" ) );
 
   83     connect( mButtonFetch, &QAbstractButton::clicked, 
this, &QgsStyleExportImportDialog::fetch );
 
   86     mImportFileWidget->setDialogTitle( tr( 
"Load Styles" ) );
 
   87     mImportFileWidget->setFilter( tr( 
"XML files (*.xml *.XML)" ) );
 
   90     mImportFileWidget->setDefaultRoot( settings.
value( QStringLiteral( 
"StyleManager/lastImportDir" ), QDir::homePath(), 
QgsSettings::Gui ).toString() );
 
   93     label->setText( tr( 
"Select items to import" ) );
 
   94     buttonBox->button( QDialogButtonBox::Ok )->setText( tr( 
"Import" ) );
 
   96     dialogStyle = mTempStyle.get();
 
  100     setWindowTitle( tr( 
"Export Item(s)" ) );
 
  102     mLocationStackedEdit->setHidden( 
true );
 
  103     fromLabel->setHidden( 
true );
 
  104     importTypeCombo->setHidden( 
true );
 
  105     mLocationLabel->setHidden( 
true );
 
  107     mFavorite->setHidden( 
true );
 
  108     mIgnoreXMLTags->setHidden( 
true );
 
  110     pb = 
new QPushButton( tr( 
"Select by Group…" ) );
 
  111     buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
 
  113     tagLabel->setHidden( 
true );
 
  114     mSymbolTags->setHidden( 
true );
 
  115     tagHintLabel->setHidden( 
true );
 
  117     buttonBox->button( QDialogButtonBox::Ok )->setText( tr( 
"Export" ) );
 
  119     dialogStyle = mStyle;
 
  123   listItems->setIconSize( QSize( 
static_cast< int >( 
iconSize ), 
static_cast< int >( 
iconSize * 0.9 ) ) );  
 
  125   listItems->setGridSize( QSize( 
static_cast< int >( listItems->iconSize().width() * 1.4 ), 
static_cast< int >( listItems->iconSize().height() * 1.7 ) ) );
 
  126   listItems->setTextElideMode( Qt::TextElideMode::ElideRight );
 
  132   listItems->setModel( mModel );
 
  134   connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
 
  135            this, &QgsStyleExportImportDialog::selectionChanged );
 
  138   disconnect( buttonBox, &QDialogButtonBox::accepted, 
this, &QDialog::accept );
 
  140   buttonBox->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
  142   connect( buttonBox, &QDialogButtonBox::helpRequested, 
this, &QgsStyleExportImportDialog::showHelp );
 
  147   QModelIndexList selection = listItems->selectionModel()->selectedIndexes();
 
  148   if ( selection.isEmpty() )
 
  150     QMessageBox::warning( 
this, tr( 
"Export/import Item(s)" ),
 
  151                           tr( 
"You should select at least one symbol/color ramp." ) );
 
  155   if ( mDialogMode == 
Export )
 
  158     const QString lastUsedDir = settings.
value( QStringLiteral( 
"StyleManager/lastExportDir" ), QDir::homePath(), 
QgsSettings::Gui ).toString();
 
  159     QString fileName = QFileDialog::getSaveFileName( 
this, tr( 
"Save Styles" ), lastUsedDir,
 
  160                        tr( 
"XML files (*.xml *.XML)" ) );
 
  161     if ( fileName.isEmpty() )
 
  165     settings.
setValue( QStringLiteral( 
"StyleManager/lastExportDir" ), QFileInfo( fileName ).absolutePath(), 
QgsSettings::Gui );
 
  168     if ( !fileName.endsWith( QLatin1String( 
".xml" ), Qt::CaseInsensitive ) )
 
  170       fileName += QLatin1String( 
".xml" );
 
  173     mFileName = fileName;
 
  175     mCursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
 
  176     moveStyles( &selection, mStyle, mTempStyle.get() );
 
  177     if ( !mTempStyle->exportXml( mFileName ) )
 
  179       mCursorOverride.reset();
 
  180       QMessageBox::warning( 
this, tr( 
"Export Symbols" ),
 
  181                             tr( 
"Error when saving selected symbols to file:\n%1" )
 
  182                             .arg( mTempStyle->errorString() ) );
 
  187       mCursorOverride.reset();
 
  188       QMessageBox::information( 
this, tr( 
"Export Symbols" ),
 
  189                                 tr( 
"The selected symbols were successfully exported to file:\n%1" )
 
  195     mCursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
 
  196     moveStyles( &selection, mTempStyle.get(), mStyle );
 
  199     mCursorOverride.reset();
 
  206 bool QgsStyleExportImportDialog::populateStyles()
 
  213   if ( !mTempStyle->importXml( mFileName ) )
 
  216     QMessageBox::warning( 
this, tr( 
"Import Symbols or Color Ramps" ),
 
  217                           tr( 
"An error occurred during import:\n%1" ).arg( mTempStyle->errorString() ) );
 
  223 void QgsStyleExportImportDialog::moveStyles( QModelIndexList *selection, 
QgsStyle *src, 
QgsStyle *dst )
 
  225   QList< QgsStyleManagerDialog::ItemDetails > items;
 
  226   items.reserve( selection->size() );
 
  227   for ( 
int i = 0; i < selection->size(); ++i )
 
  229     const QModelIndex index = selection->at( i );
 
  231     QgsStyleManagerDialog::ItemDetails details;
 
  235     details.name = mModel->data( mModel->index( index.row(), 
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
 
  239   QgsStyleManagerDialog::copyItems( items, src, dst, 
this, mCursorOverride, mDialogMode == 
Import,
 
  240                                     mSymbolTags->text().split( 
',' ), mFavorite->isChecked(), mIgnoreXMLTags->isChecked() );
 
  246   delete mGroupSelectionDlg;
 
  251   mImportFileWidget->setFilePath( path );
 
  256   listItems->selectAll();
 
  261   listItems->clearSelection();
 
  266   for ( 
int row = 0; row < listItems->model()->rowCount(); ++row )
 
  268     const QModelIndex index = listItems->model()->index( row, 0 );
 
  271       listItems->selectionModel()->select( index, QItemSelectionModel::Select );
 
  278   for ( 
int row = 0; row < listItems->model()->rowCount(); ++row )
 
  280     const QModelIndex index = listItems->model()->index( row, 0 );
 
  283       const QItemSelection deselection( index, index );
 
  284       listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
 
  291   const auto constSymbolNames = symbolNames;
 
  292   for ( 
const QString &symbolName : constSymbolNames )
 
  294     const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0, 
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
 
  295     const auto constIndexes = indexes;
 
  296     for ( 
const QModelIndex &index : constIndexes )
 
  298       listItems->selectionModel()->select( index, QItemSelectionModel::Select );
 
  305   const auto constSymbolNames = symbolNames;
 
  306   for ( 
const QString &symbolName : constSymbolNames )
 
  308     const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0, 
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
 
  309     const auto constIndexes = indexes;
 
  310     for ( 
const QModelIndex &index : constIndexes )
 
  312       const QItemSelection deselection( index, index );
 
  313       listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
 
  320   for ( 
int row = 0; row < listItems->model()->rowCount(); ++row )
 
  322     const QModelIndex index = listItems->model()->index( row, 0 );
 
  325       listItems->selectionModel()->select( index, QItemSelectionModel::Select );
 
  332   for ( 
int row = 0; row < listItems->model()->rowCount(); ++row )
 
  334     const QModelIndex index = listItems->model()->index( row, 0 );
 
  337       const QItemSelection deselection( index, index );
 
  338       listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
 
  365   if ( ! mGroupSelectionDlg )
 
  368     mGroupSelectionDlg->setWindowTitle( tr( 
"Select Item(s) by Group" ) );
 
  378   mGroupSelectionDlg->show();
 
  379   mGroupSelectionDlg->raise();
 
  380   mGroupSelectionDlg->activateWindow();
 
  385   const ImportSource source = 
static_cast< ImportSource 
>( importTypeCombo->itemData( index ).toInt() );
 
  389     case ImportSource::File:
 
  391       mLocationStackedEdit->setCurrentIndex( 0 );
 
  392       mLocationLabel->setText( tr( 
"File" ) );
 
  396     case ImportSource::Official:
 
  398       btnBrowse->setText( QStringLiteral( 
"Fetch Items" ) );
 
  399       locationLineEdit->setEnabled( 
false );
 
  403     case ImportSource::Url:
 
  405       mLocationStackedEdit->setCurrentIndex( 1 );
 
  406       mLocationLabel->setText( tr( 
"URL" ) );
 
  412 void QgsStyleExportImportDialog::fetch()
 
  414   downloadStyleXml( QUrl( mUrlLineEdit->text() ) );
 
  417 void QgsStyleExportImportDialog::importFileChanged( 
const QString &path )
 
  419   if ( path.isEmpty() )
 
  423   const QFileInfo pathInfo( mFileName );
 
  424   const QString tag = pathInfo.fileName().remove( QStringLiteral( 
".xml" ) );
 
  425   mSymbolTags->setText( tag );
 
  426   if ( QFileInfo::exists( mFileName ) )
 
  430     mImportFileWidget->setDefaultRoot( pathInfo.absolutePath() );
 
  436 void QgsStyleExportImportDialog::downloadStyleXml( 
const QUrl &url )
 
  438   mTempFile = 
new QTemporaryFile();
 
  439   if ( mTempFile->open() )
 
  441     mFileName = mTempFile->fileName();
 
  443     QProgressDialog *progressDlg = 
new QProgressDialog( 
this );
 
  444     progressDlg->setLabelText( tr( 
"Downloading style…" ) );
 
  445     progressDlg->setAutoClose( 
true );
 
  454       QNetworkReply *reply = fetcher->
reply();
 
  455       if ( !reply || reply->error() != QNetworkReply::NoError )
 
  460           QMessageBox::information( this, tr( 
"Import from URL" ),
 
  461                                     tr( 
"HTTP Error! Download failed: %1." ).arg( reply->errorString() ) );
 
  465         mTempFile->write( reply->readAll() );
 
  470       progressDlg->deleteLater();
 
  477 void QgsStyleExportImportDialog::selectionChanged( 
const QItemSelection &selected, 
const QItemSelection &deselected )
 
  480   Q_UNUSED( deselected )
 
  481   const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
 
  482   buttonBox->button( QDialogButtonBox::Ok )->setDisabled( nothingSelected );
 
  485 void QgsStyleExportImportDialog::showHelp()
 
  487   QgsHelp::openHelp( QStringLiteral( 
"style_library/style_manager.html#sharing-style-items" ) );