17#include "ui_qgsstyleexportimportdialogbase.h"
33#include <QInputDialog>
35#include <QNetworkReply>
36#include <QProgressDialog>
38#include <QStandardItemModel>
39#include <QTemporaryFile>
42#include "moc_qgsstyleexportimportdialog.cpp"
53 QPushButton *pb =
nullptr;
54 pb =
new QPushButton( tr(
"Select All" ) );
55 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
58 pb =
new QPushButton( tr(
"Clear Selection" ) );
59 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
62 mTempStyle = std::make_unique<QgsStyle>();
63 mTempStyle->createMemoryDatabase();
66 mGroupSelectionDlg =
nullptr;
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" ) );
95 dialogStyle = mTempStyle.get();
99 setWindowTitle( tr(
"Export Item(s)" ) );
101 mLocationStackedEdit->setHidden(
true );
102 fromLabel->setHidden(
true );
103 importTypeCombo->setHidden(
true );
104 mLocationLabel->setHidden(
true );
106 mFavorite->setHidden(
true );
107 mIgnoreXMLTags->setHidden(
true );
109 pb =
new QPushButton( tr(
"Select by Group…" ) );
110 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
112 tagLabel->setHidden(
true );
113 mSymbolTags->setHidden(
true );
114 tagHintLabel->setHidden(
true );
116 buttonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Export" ) );
118 dialogStyle = mStyle;
122 listItems->setIconSize( QSize(
static_cast<int>( iconSize ),
static_cast<int>( iconSize * 0.9 ) ) );
124 listItems->setGridSize( QSize(
static_cast<int>( listItems->iconSize().width() * 1.4 ),
static_cast<int>( listItems->iconSize().height() * 1.7 ) ) );
125 listItems->setTextElideMode( Qt::TextElideMode::ElideRight );
129 mModel->addDesiredIconSize( listItems->iconSize() );
132 listItems->setModel( mModel );
134 connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsStyleExportImportDialog::selectionChanged );
137 disconnect( buttonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
139 buttonBox->button( QDialogButtonBox::Ok )->setEnabled(
false );
141 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsStyleExportImportDialog::showHelp );
146 QModelIndexList selection = listItems->selectionModel()->selectedIndexes();
147 if ( selection.isEmpty() )
149 QMessageBox::warning(
this, tr(
"Export/import Item(s)" ), tr(
"You should select at least one symbol/color ramp." ) );
153 if ( mDialogMode ==
Export )
156 const QString lastUsedDir = settings.
value( QStringLiteral(
"StyleManager/lastExportDir" ), QDir::homePath(),
QgsSettings::Gui ).toString();
157 QString fileName = QFileDialog::getSaveFileName(
this, tr(
"Save Styles" ), lastUsedDir, 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" ), tr(
"Error when saving selected symbols to file:\n%1" ).arg( mTempStyle->errorString() ) );
185 mCursorOverride.reset();
186 QMessageBox::information(
this, tr(
"Export Symbols" ), tr(
"The selected symbols were successfully exported to file:\n%1" ).arg( mFileName ) );
191 mCursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
192 moveStyles( &selection, mTempStyle.get(), mStyle );
195 mCursorOverride.reset();
202bool QgsStyleExportImportDialog::populateStyles()
209 if ( !mTempStyle->importXml( mFileName ) )
212 QMessageBox::warning(
this, tr(
"Import Symbols or Color Ramps" ), tr(
"An error occurred during import:\n%1" ).arg( mTempStyle->errorString() ) );
218void QgsStyleExportImportDialog::moveStyles( QModelIndexList *selection,
QgsStyle *src,
QgsStyle *dst )
220 QList<QgsStyleManagerDialog::ItemDetails> items;
221 items.reserve( selection->size() );
222 for (
int i = 0; i < selection->size(); ++i )
224 const QModelIndex index = selection->at( i );
226 QgsStyleManagerDialog::ItemDetails details;
230 details.name = mModel->data( mModel->index( index.row(),
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
234 QgsStyleManagerDialog::copyItems( items, src, dst,
this, mCursorOverride, mDialogMode ==
Import, mSymbolTags->text().split(
',' ), mFavorite->isChecked(), mIgnoreXMLTags->isChecked() );
240 delete mGroupSelectionDlg;
245 mImportFileWidget->setFilePath( path );
250 listItems->selectAll();
255 listItems->clearSelection();
260 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
262 const QModelIndex index = listItems->model()->index( row, 0 );
265 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
272 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
274 const QModelIndex index = listItems->model()->index( row, 0 );
277 const QItemSelection deselection( index, index );
278 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
285 const auto constSymbolNames = symbolNames;
286 for (
const QString &symbolName : constSymbolNames )
288 const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
289 const auto constIndexes = indexes;
290 for (
const QModelIndex &index : constIndexes )
292 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
299 const auto constSymbolNames = symbolNames;
300 for (
const QString &symbolName : constSymbolNames )
302 const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
303 const auto constIndexes = indexes;
304 for (
const QModelIndex &index : constIndexes )
306 const QItemSelection deselection( index, index );
307 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
314 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
316 const QModelIndex index = listItems->model()->index( row, 0 );
319 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
326 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
328 const QModelIndex index = listItems->model()->index( row, 0 );
331 const QItemSelection deselection( index, index );
332 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
339 QStringList symbolNames = mStyle->symbolsOfSmartgroup(
QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
349 QStringList symbolNames = mStyle->symbolsOfSmartgroup(
QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
359 if ( !mGroupSelectionDlg )
362 mGroupSelectionDlg->setWindowTitle( tr(
"Select Item(s) by Group" ) );
372 mGroupSelectionDlg->show();
373 mGroupSelectionDlg->raise();
374 mGroupSelectionDlg->activateWindow();
379 const ImportSource source =
static_cast<ImportSource
>( importTypeCombo->itemData( index ).toInt() );
383 case ImportSource::File:
385 mLocationStackedEdit->setCurrentIndex( 0 );
386 mLocationLabel->setText( tr(
"File" ) );
390 case ImportSource::Official:
392 btnBrowse->setText( QStringLiteral(
"Fetch Items" ) );
393 locationLineEdit->setEnabled(
false );
397 case ImportSource::Url:
399 mLocationStackedEdit->setCurrentIndex( 1 );
400 mLocationLabel->setText( tr(
"URL" ) );
406void QgsStyleExportImportDialog::fetch()
408 downloadStyleXml( QUrl( mUrlLineEdit->text() ) );
411void QgsStyleExportImportDialog::importFileChanged(
const QString &path )
413 if ( path.isEmpty() )
417 const QFileInfo pathInfo( mFileName );
418 const QString tag = pathInfo.fileName().remove( QStringLiteral(
".xml" ) );
419 mSymbolTags->setText( tag );
420 if ( QFileInfo::exists( mFileName ) )
424 mImportFileWidget->setDefaultRoot( pathInfo.absolutePath() );
425 QgsSettings settings;
430void QgsStyleExportImportDialog::downloadStyleXml(
const QUrl &url )
432 mTempFile =
new QTemporaryFile();
433 if ( mTempFile->open() )
435 mFileName = mTempFile->fileName();
437 QProgressDialog *progressDlg =
new QProgressDialog(
this );
438 progressDlg->setLabelText( tr(
"Downloading style…" ) );
439 progressDlg->setAutoClose(
true );
442 QgsNetworkContentFetcherTask *fetcher =
new QgsNetworkContentFetcherTask( url );
447 QNetworkReply *reply = fetcher->
reply();
448 if ( !reply || reply->error() != QNetworkReply::NoError )
453 QMessageBox::information(
this, tr(
"Import from URL" ), tr(
"HTTP Error! Download failed: %1." ).arg( reply->errorString() ) );
457 mTempFile->write( reply->readAll() );
462 progressDlg->deleteLater();
469void QgsStyleExportImportDialog::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
472 Q_UNUSED( deselected )
473 const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
474 buttonBox->button( QDialogButtonBox::Ok )->setDisabled( nothingSelected );
477void QgsStyleExportImportDialog::showHelp()
479 QgsHelp::openHelp( QStringLiteral(
"style_library/style_manager.html#sharing-style-items" ) );
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.