18 #include "ui_qgsstyleexportimportdialogbase.h" 31 #include <QInputDialog> 32 #include <QCloseEvent> 33 #include <QFileDialog> 34 #include <QMessageBox> 35 #include <QProgressDialog> 36 #include <QPushButton> 37 #include <QStandardItemModel> 38 #include <QNetworkAccessManager> 39 #include <QNetworkReply> 51 QPushButton *pb =
nullptr;
52 pb =
new QPushButton( tr(
"Select All" ) );
53 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
56 pb =
new QPushButton( tr(
"Clear Selection" ) );
57 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
60 mTempStyle = qgis::make_unique< QgsStyle >();
61 mTempStyle->createMemoryDatabase();
64 mProgressDlg =
nullptr;
65 mGroupSelectionDlg =
nullptr;
67 mNetManager =
new QNetworkAccessManager(
this );
70 if ( mDialogMode ==
Import )
72 setWindowTitle( tr(
"Import Item(s)" ) );
74 importTypeCombo->addItem( tr(
"File" ), ImportSource::File );
76 importTypeCombo->addItem( tr(
"URL" ), ImportSource::Url );
80 mSymbolTags->setText( QStringLiteral(
"imported" ) );
82 connect( mButtonFetch, &QAbstractButton::clicked,
this, &QgsStyleExportImportDialog::fetch );
85 mImportFileWidget->setDialogTitle( tr(
"Load Styles" ) );
86 mImportFileWidget->setFilter( tr(
"XML files (*.xml *.XML)" ) );
89 mImportFileWidget->setDefaultRoot( settings.
value( QStringLiteral(
"StyleManager/lastImportDir" ), QDir::homePath(),
QgsSettings::Gui ).toString() );
92 label->setText( tr(
"Select items to import" ) );
93 buttonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Import" ) );
96 listItems->setModel( mModel );
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" ) );
123 listItems->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) );
126 listItems->setModel( mModel );
128 connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
129 this, &QgsStyleExportImportDialog::selectionChanged );
132 disconnect( buttonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
134 buttonBox->button( QDialogButtonBox::Ok )->setEnabled(
false );
136 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsStyleExportImportDialog::showHelp );
141 QModelIndexList selection = listItems->selectionModel()->selectedIndexes();
142 if ( selection.isEmpty() )
144 QMessageBox::warning(
this, tr(
"Export/import Item(s)" ),
145 tr(
"You should select at least one symbol/color ramp." ) );
149 if ( mDialogMode ==
Export )
151 QString fileName = QFileDialog::getSaveFileName(
this, tr(
"Save Styles" ), QDir::homePath(),
152 tr(
"XML files (*.xml *.XML)" ) );
153 if ( fileName.isEmpty() )
159 if ( !fileName.endsWith( QLatin1String(
".xml" ), Qt::CaseInsensitive ) )
161 fileName += QLatin1String(
".xml" );
164 mFileName = fileName;
166 mCursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
167 moveStyles( &selection, mStyle, mTempStyle.get() );
168 if ( !mTempStyle->exportXml( mFileName ) )
170 mCursorOverride.reset();
171 QMessageBox::warning(
this, tr(
"Export Symbols" ),
172 tr(
"Error when saving selected symbols to file:\n%1" )
173 .arg( mTempStyle->errorString() ) );
178 mCursorOverride.reset();
179 QMessageBox::information(
this, tr(
"Export Symbols" ),
180 tr(
"The selected symbols were successfully exported to file:\n%1" )
186 mCursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
187 moveStyles( &selection, mTempStyle.get(), mStyle );
190 mCursorOverride.reset();
197 bool QgsStyleExportImportDialog::populateStyles()
204 if ( !mTempStyle->importXml( mFileName ) )
207 QMessageBox::warning(
this, tr(
"Import Symbols or Color Ramps" ),
208 tr(
"An error occurred during import:\n%1" ).arg( mTempStyle->errorString() ) );
214 void QgsStyleExportImportDialog::moveStyles( QModelIndexList *selection,
QgsStyle *src,
QgsStyle *dst )
217 QStringList symbolTags;
220 bool isSymbol =
true;
222 bool overwrite =
true;
224 QStringList importTags = mSymbolTags->text().split(
',' );
229 for (
int i = 0; i < selection->size(); ++i )
231 index = selection->at( i );
233 std::unique_ptr< QgsSymbol > symbol( src->
symbol( symbolName ) );
234 std::unique_ptr< QgsColorRamp > ramp;
236 if ( !mIgnoreXMLTags->isChecked() )
245 if ( mDialogMode ==
Import )
247 symbolTags << importTags;
248 symbolFavorite = mFavorite->isChecked();
252 symbolFavorite = !symbol ? favoriteColorramps.contains( symbolName ) : favoriteSymbols.contains( symbolName );
258 ramp.reset( src->
colorRamp( symbolName ) );
263 if ( dst->
symbolNames().contains( symbolName ) && prompt )
265 mCursorOverride.reset();
266 int res = QMessageBox::warning(
this, tr(
"Export/import Symbols" ),
267 tr(
"Symbol with name '%1' already exists.\nOverwrite?" )
269 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
270 mCursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
273 case QMessageBox::Cancel:
275 case QMessageBox::No:
277 case QMessageBox::Yes:
280 dst->
addSymbol( symbolName, symbol.release() );
281 dst->
saveSymbol( symbolName, newSymbol, symbolFavorite, symbolTags );
284 case QMessageBox::YesToAll:
288 case QMessageBox::NoToAll:
295 if ( dst->
symbolNames().contains( symbolName ) && overwrite )
298 dst->
addSymbol( symbolName, symbol.release() );
299 dst->
saveSymbol( symbolName, newSymbol, symbolFavorite, symbolTags );
302 else if ( dst->
symbolNames().contains( symbolName ) && !overwrite )
309 dst->
addSymbol( symbolName, symbol.release() );
310 dst->
saveSymbol( symbolName, newSymbol, symbolFavorite, symbolTags );
318 mCursorOverride.reset();
319 int res = QMessageBox::warning(
this, tr(
"Export/import Color Ramps" ),
320 tr(
"Color ramp with name '%1' already exists.\nOverwrite?" )
322 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
323 mCursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
326 case QMessageBox::Cancel:
328 case QMessageBox::No:
330 case QMessageBox::Yes:
334 dst->
saveColorRamp( symbolName, newRamp, symbolFavorite, symbolTags );
337 case QMessageBox::YesToAll:
341 case QMessageBox::NoToAll:
352 dst->
saveColorRamp( symbolName, newRamp, symbolFavorite, symbolTags );
355 else if ( dst->
colorRampNames().contains( symbolName ) && !overwrite )
363 dst->
saveColorRamp( symbolName, newRamp, symbolFavorite, symbolTags );
373 delete mGroupSelectionDlg;
378 listItems->selectAll();
383 listItems->clearSelection();
388 Q_FOREACH (
const QString &symbolName, symbolNames )
390 QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
391 Q_FOREACH (
const QModelIndex &index, indexes )
393 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
400 Q_FOREACH (
const QString &symbolName, symbolNames )
402 QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
403 Q_FOREACH (
const QModelIndex &index, indexes )
405 QItemSelection deselection( index, index );
406 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
441 if ( ! mGroupSelectionDlg )
444 mGroupSelectionDlg->setWindowTitle( tr(
"Select Item(s) by Group" ) );
452 mGroupSelectionDlg->show();
453 mGroupSelectionDlg->raise();
454 mGroupSelectionDlg->activateWindow();
459 ImportSource source =
static_cast< ImportSource
>( importTypeCombo->itemData( index ).toInt() );
463 case ImportSource::File:
465 mLocationStackedEdit->setCurrentIndex( 0 );
466 mLocationLabel->setText( tr(
"File" ) );
470 case ImportSource::Official:
472 btnBrowse->setText( QStringLiteral(
"Fetch Items" ) );
473 locationLineEdit->setEnabled(
false );
477 case ImportSource::Url:
479 mLocationStackedEdit->setCurrentIndex( 1 );
480 mLocationLabel->setText( tr(
"URL" ) );
486 void QgsStyleExportImportDialog::fetch()
488 downloadStyleXml( QUrl( mUrlLineEdit->text() ) );
491 void QgsStyleExportImportDialog::importFileChanged(
const QString &path )
493 if ( path.isEmpty() )
497 QFileInfo pathInfo( mFileName );
498 QString tag = pathInfo.fileName().remove( QStringLiteral(
".xml" ) );
499 mSymbolTags->setText( tag );
500 if ( QFileInfo::exists( mFileName ) )
504 mImportFileWidget->setDefaultRoot( pathInfo.absolutePath() );
510 void QgsStyleExportImportDialog::downloadStyleXml(
const QUrl &url )
515 mTempFile =
new QTemporaryFile();
516 if ( mTempFile->open() )
518 mFileName = mTempFile->fileName();
522 QProgressDialog *dummy = mProgressDlg;
523 mProgressDlg =
nullptr;
526 mProgressDlg =
new QProgressDialog();
527 mProgressDlg->setLabelText( tr(
"Downloading style…" ) );
528 mProgressDlg->setAutoClose(
true );
530 connect( mProgressDlg, &QProgressDialog::canceled,
this, &QgsStyleExportImportDialog::downloadCanceled );
535 QNetworkReply *dummyReply = mNetReply;
539 mNetReply = mNetManager->get( QNetworkRequest( url ) );
541 connect( mNetReply, &QNetworkReply::finished,
this, &QgsStyleExportImportDialog::httpFinished );
542 connect( mNetReply, &QIODevice::readyRead,
this, &QgsStyleExportImportDialog::fileReadyRead );
543 connect( mNetReply, &QNetworkReply::downloadProgress,
this, &QgsStyleExportImportDialog::updateProgress );
547 void QgsStyleExportImportDialog::httpFinished()
549 if ( mNetReply->error() )
553 mProgressDlg->hide();
554 QMessageBox::information(
this, tr(
"Import from URL" ),
555 tr(
"HTTP Error! Download failed: %1." ).arg( mNetReply->errorString() ) );
567 void QgsStyleExportImportDialog::fileReadyRead()
569 mTempFile->write( mNetReply->readAll() );
572 void QgsStyleExportImportDialog::updateProgress( qint64 bytesRead, qint64 bytesTotal )
574 mProgressDlg->setMaximum( bytesTotal );
575 mProgressDlg->setValue( bytesRead );
578 void QgsStyleExportImportDialog::downloadCanceled()
585 void QgsStyleExportImportDialog::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
587 Q_UNUSED( selected );
588 Q_UNUSED( deselected );
589 bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
590 buttonBox->button( QDialogButtonBox::Ok )->setDisabled( nothingSelected );
593 void QgsStyleExportImportDialog::showHelp()
595 QgsHelp::openHelp( QStringLiteral(
"working_with_vector/style_library.html#share-symbols" ) );
A QAbstractItemModel subclass for showing symbol and color ramp entities contained within a QgsStyle ...
void selectByGroup()
selectByGroup open select by group dialog
void deselectSmartgroup(const QString &groupName)
deselectSmartgroup deselects all symbols from a smart group
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
bool addColorRamp(const QString &name, QgsColorRamp *colorRamp, bool update=false)
Adds a color ramp to the style.
QgsStyleExportImportDialog(QgsStyle *style, QWidget *parent=nullptr, Mode mode=Export)
Abstract base class for all rendered symbols.
static const double UI_SCALE_FACTOR
UI scaling factor.
This class is a composition of two QSettings instances:
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
Returns the tags associated with the symbol.
~QgsStyleExportImportDialog() override
Abstract base class for color ramps.
bool saveColorRamp(const QString &name, QgsColorRamp *ramp, bool favorite, const QStringList &tags)
Adds the colorramp to the DB.
void tagSelected(const QString &tagName)
tag with tagName has been selected
void clearSelection()
clearSelection deselects all symbols
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void smartgroupSelected(const QString &groupName)
smartgroup with groupName has been selected
QStringList symbolsWithTag(StyleEntity type, int tagid) const
Returns the symbol names with which have the given tag.
void selectSmartgroup(const QString &groupName)
selectSmartgroup selects all symbols from a smart group
void allDeselected()
all deselected
void deselectSymbols(const QStringList &symbolNames)
deselectSymbols deselect symbols by name
QStringList symbolNames()
Returns a list of names of symbols.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QStringList symbolsOfFavorite(StyleEntity type) const
Returns the symbol names which are flagged as favorite.
void allSelected()
all selected
QStringList colorRampNames()
Returns a list of names of color ramps.
QStringList symbolsOfSmartgroup(StyleEntity type, int id)
Returns the symbols for the smartgroup.
int smartgroupId(const QString &smartgroup)
Returns the DB id for the given smartgroup name.
int tagId(const QString &tag)
Returns the DB id for the given tag name.
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
void addDesiredIconSize(QSize size)
Adds an additional icon size to generate for Qt::DecorationRole data.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void selectTag(const QString &tagName)
Select the symbols belonging to the given tag.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
void selectSymbols(const QStringList &symbolNames)
selectSymbols select symbols by name
void deselectTag(const QString &tagName)
Deselect the symbols belonging to the given tag.
void selectAll()
selectAll selects all symbols
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
QVariant data(const QModelIndex &index, int role) const override
void smartgroupDeselected(const QString &groupName)
smart group with groupName has been deselected
bool saveSymbol(const QString &name, QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the DB with the tags.
void tagDeselected(const QString &tagName)
tag with tagName has been deselected
void importTypeChanged(int)