17#include "ui_qgsstyleexportimportdialogbase.h"
33#include <QInputDialog>
35#include <QNetworkReply>
36#include <QProgressDialog>
38#include <QStandardItemModel>
40#include <QTemporaryFile>
43#include "moc_qgsstyleexportimportdialog.cpp"
45using namespace Qt::StringLiterals;
56 QPushButton *pb =
nullptr;
57 pb =
new QPushButton( tr(
"Select All" ) );
58 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
61 pb =
new QPushButton( tr(
"Clear Selection" ) );
62 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
65 mTempStyle = std::make_unique<QgsStyle>();
66 mTempStyle->createMemoryDatabase();
69 mGroupSelectionDlg =
nullptr;
73 if ( mDialogMode ==
Import )
75 setWindowTitle( tr(
"Import Item(s)" ) );
77 importTypeCombo->addItem( tr(
"File" ), ImportSource::File );
79 importTypeCombo->addItem( tr(
"URL" ), ImportSource::Url );
83 mSymbolTags->setText( u
"imported"_s );
85 connect( mButtonFetch, &QAbstractButton::clicked,
this, &QgsStyleExportImportDialog::fetch );
88 mImportFileWidget->setDialogTitle( tr(
"Load Styles" ) );
89 mImportFileWidget->setFilter( tr(
"XML files (*.xml *.XML)" ) );
92 mImportFileWidget->setDefaultRoot( settings.
value( u
"StyleManager/lastImportDir"_s, QDir::homePath(),
QgsSettings::Gui ).toString() );
95 label->setText( tr(
"Select items to import" ) );
96 buttonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Import" ) );
98 dialogStyle = mTempStyle.get();
102 setWindowTitle( tr(
"Export Item(s)" ) );
104 mLocationStackedEdit->setHidden(
true );
105 fromLabel->setHidden(
true );
106 importTypeCombo->setHidden(
true );
107 mLocationLabel->setHidden(
true );
109 mFavorite->setHidden(
true );
110 mIgnoreXMLTags->setHidden(
true );
112 pb =
new QPushButton( tr(
"Select by Group…" ) );
113 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
115 tagLabel->setHidden(
true );
116 mSymbolTags->setHidden(
true );
117 tagHintLabel->setHidden(
true );
119 buttonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Export" ) );
121 dialogStyle = mStyle;
125 listItems->setIconSize( QSize(
static_cast<int>( iconSize ),
static_cast<int>( iconSize * 0.9 ) ) );
127 listItems->setGridSize( QSize(
static_cast<int>( listItems->iconSize().width() * 1.4 ),
static_cast<int>( listItems->iconSize().height() * 1.7 ) ) );
128 listItems->setTextElideMode( Qt::TextElideMode::ElideRight );
132 mModel->addDesiredIconSize( listItems->iconSize() );
135 listItems->setModel( mModel );
137 connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsStyleExportImportDialog::selectionChanged );
140 disconnect( buttonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
142 buttonBox->button( QDialogButtonBox::Ok )->setEnabled(
false );
144 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsStyleExportImportDialog::showHelp );
149 QModelIndexList selection = listItems->selectionModel()->selectedIndexes();
150 if ( selection.isEmpty() )
152 QMessageBox::warning(
this, tr(
"Export/import Item(s)" ), tr(
"You should select at least one symbol/color ramp." ) );
156 if ( mDialogMode ==
Export )
159 const QString lastUsedDir = settings.
value( u
"StyleManager/lastExportDir"_s, QDir::homePath(),
QgsSettings::Gui ).toString();
160 QString fileName = QFileDialog::getSaveFileName(
this, tr(
"Save Styles" ), lastUsedDir, tr(
"XML files (*.xml *.XML)" ) );
164 if ( fileName.isEmpty() )
171 if ( !fileName.endsWith(
".xml"_L1, Qt::CaseInsensitive ) )
173 fileName +=
".xml"_L1;
176 mFileName = fileName;
178 mCursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
179 moveStyles( &selection, mStyle, mTempStyle.get() );
180 if ( !mTempStyle->exportXml( mFileName ) )
182 mCursorOverride.reset();
183 QMessageBox::warning(
this, tr(
"Export Symbols" ), tr(
"Error when saving selected symbols to file:\n%1" ).arg( mTempStyle->errorString() ) );
188 mCursorOverride.reset();
189 QMessageBox::information(
this, tr(
"Export Symbols" ), tr(
"The selected symbols were successfully exported to file:\n%1" ).arg( mFileName ) );
194 mCursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
195 moveStyles( &selection, mTempStyle.get(), mStyle );
198 mCursorOverride.reset();
205bool QgsStyleExportImportDialog::populateStyles()
212 if ( !mTempStyle->importXml( mFileName ) )
215 QMessageBox::warning(
this, tr(
"Import Symbols or Color Ramps" ), tr(
"An error occurred during import:\n%1" ).arg( mTempStyle->errorString() ) );
221void QgsStyleExportImportDialog::moveStyles( QModelIndexList *selection,
QgsStyle *src,
QgsStyle *dst )
223 QList<QgsStyleManagerDialog::ItemDetails> items;
224 items.reserve( selection->size() );
225 for (
int i = 0; i < selection->size(); ++i )
227 const QModelIndex index = selection->at( i );
229 QgsStyleManagerDialog::ItemDetails details;
233 details.name = mModel->data( mModel->index( index.row(),
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
237 QgsStyleManagerDialog::copyItems( items, src, dst,
this, mCursorOverride, mDialogMode ==
Import, mSymbolTags->text().split(
',' ), mFavorite->isChecked(), mIgnoreXMLTags->isChecked() );
243 delete mGroupSelectionDlg;
248 mImportFileWidget->setFilePath( path );
253 listItems->selectAll();
258 listItems->clearSelection();
263 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
265 const QModelIndex index = listItems->model()->index( row, 0 );
268 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
275 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
277 const QModelIndex index = listItems->model()->index( row, 0 );
280 const QItemSelection deselection( index, index );
281 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
288 const auto constSymbolNames = symbolNames;
289 for (
const QString &symbolName : constSymbolNames )
291 const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
292 const auto constIndexes = indexes;
293 for (
const QModelIndex &index : constIndexes )
295 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
302 const auto constSymbolNames = symbolNames;
303 for (
const QString &symbolName : constSymbolNames )
305 const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
306 const auto constIndexes = indexes;
307 for (
const QModelIndex &index : constIndexes )
309 const QItemSelection deselection( index, index );
310 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
317 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
319 const QModelIndex index = listItems->model()->index( row, 0 );
322 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
329 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
331 const QModelIndex index = listItems->model()->index( row, 0 );
334 const QItemSelection deselection( index, index );
335 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
342 QStringList symbolNames = mStyle->symbolsOfSmartgroup(
QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
352 QStringList symbolNames = mStyle->symbolsOfSmartgroup(
QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
362 if ( !mGroupSelectionDlg )
365 mGroupSelectionDlg->setWindowTitle( tr(
"Select Item(s) by Group" ) );
375 mGroupSelectionDlg->show();
376 mGroupSelectionDlg->raise();
377 mGroupSelectionDlg->activateWindow();
382 const ImportSource source =
static_cast<ImportSource
>( importTypeCombo->itemData( index ).toInt() );
386 case ImportSource::File:
388 mLocationStackedEdit->setCurrentIndex( 0 );
389 mLocationLabel->setText( tr(
"File" ) );
393 case ImportSource::Official:
395 btnBrowse->setText( u
"Fetch Items"_s );
396 locationLineEdit->setEnabled(
false );
400 case ImportSource::Url:
402 mLocationStackedEdit->setCurrentIndex( 1 );
403 mLocationLabel->setText( tr(
"URL" ) );
409void QgsStyleExportImportDialog::fetch()
411 downloadStyleXml( QUrl( mUrlLineEdit->text() ) );
414void QgsStyleExportImportDialog::importFileChanged(
const QString &path )
416 if ( path.isEmpty() )
420 const QFileInfo pathInfo( mFileName );
421 const QString tag = pathInfo.fileName().remove( u
".xml"_s );
422 mSymbolTags->setText( tag );
423 if ( QFileInfo::exists( mFileName ) )
427 mImportFileWidget->setDefaultRoot( pathInfo.absolutePath() );
428 QgsSettings settings;
433void QgsStyleExportImportDialog::downloadStyleXml(
const QUrl &url )
435 mTempFile =
new QTemporaryFile();
436 if ( mTempFile->open() )
438 mFileName = mTempFile->fileName();
440 QProgressDialog *progressDlg =
new QProgressDialog(
this );
441 progressDlg->setLabelText( tr(
"Downloading style…" ) );
442 progressDlg->setAutoClose(
true );
445 QgsNetworkContentFetcherTask *fetcher =
new QgsNetworkContentFetcherTask( url );
450 QNetworkReply *reply = fetcher->
reply();
451 if ( !reply || reply->error() != QNetworkReply::NoError )
456 QMessageBox::information(
this, tr(
"Import from URL" ), tr(
"HTTP Error! Download failed: %1." ).arg( reply->errorString() ) );
460 mTempFile->write( reply->readAll() );
465 progressDlg->deleteLater();
472void QgsStyleExportImportDialog::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
475 Q_UNUSED( deselected )
476 const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
477 buttonBox->button( QDialogButtonBox::Ok )->setDisabled( nothingSelected );
480void QgsStyleExportImportDialog::showHelp()
static const double UI_SCALE_FACTOR
UI scaling factor.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
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 fetched()
Emitted when the network content has been fetched, regardless of whether the fetch was successful or ...
QNetworkReply * reply()
Returns the network reply.
void cancel() override
Notifies the task that it should terminate.
Stores properties relating to a screen.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void clearSelection()
clearSelection deselects all symbols
void selectTag(const QString &tagName)
Select the symbols belonging to the given tag.
@ Export
Export existing symbols mode.
@ Import
Import xml file mode.
void deselectSymbols(const QStringList &symbolNames)
deselectSymbols deselect symbols by name
void importTypeChanged(int)
void selectAll()
selectAll selects all symbols
void selectSymbols(const QStringList &symbolNames)
selectSymbols select symbols by name
void selectSmartgroup(const QString &groupName)
selectSmartgroup selects all symbols from a smart group
void selectByGroup()
selectByGroup open select by group dialog
void deselectFavorites()
Deselects favorite symbols.
void setImportFilePath(const QString &path)
Sets the initial path to use for importing files, when the dialog is in a Import mode.
void deselectSmartgroup(const QString &groupName)
deselectSmartgroup deselects all symbols from a smart group
QgsStyleExportImportDialog(QgsStyle *style, QWidget *parent=nullptr, Mode mode=Export)
Constructor for QgsStyleExportImportDialog, with the specified parent widget.
void selectFavorites()
Selects favorite symbols.
~QgsStyleExportImportDialog() override
void deselectTag(const QString &tagName)
Deselect the symbols belonging to the given tag.
A dialog which presents available groups from a QgsStyle.
void favoritesDeselected()
Favorites has been deselected.
void allDeselected()
all deselected
void tagSelected(const QString &tagName)
tag with tagName has been selected
void tagDeselected(const QString &tagName)
tag with tagName has been deselected
void smartgroupDeselected(const QString &groupName)
smart group with groupName has been deselected
void favoritesSelected()
Favorites has need selected.
void smartgroupSelected(const QString &groupName)
smartgroup with groupName has been selected
void allSelected()
all selected
@ IsFavorite
Whether entity is flagged as a favorite.
@ SymbolType
Symbol type (for symbol or legend patch shape entities).
@ Type
Style entity type, see QgsStyle::StyleEntity.
@ Tag
String list of tags.
A QSortFilterProxyModel subclass for showing filtered symbol and color ramps entries from a QgsStyle ...
A database of saved style entities, including symbols, color ramps, text formats and others.
StyleEntity
Enum for Entities involved in a style.
@ TextFormatEntity
Text formats.
@ ColorrampEntity
Color ramps.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void progressChanged(double progress)
Will be emitted by task when its progress changes.
void setDescription(const QString &description)
Sets the task's description.
Temporarily sets a cursor override for the QApplication for the lifetime of the object.