18#include "ui_qgsstyleexportimportdialogbase.h"
31#include <QInputDialog>
35#include <QNetworkReply>
36#include <QProgressDialog>
38#include <QStandardItemModel>
39#include <QTemporaryFile>
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 = std::make_unique< QgsStyle >();
61 mTempStyle->createMemoryDatabase();
64 mGroupSelectionDlg =
nullptr;
68 if ( mDialogMode ==
Import )
70 setWindowTitle( tr(
"Import Item(s)" ) );
72 importTypeCombo->addItem( tr(
"File" ), ImportSource::File );
74 importTypeCombo->addItem( tr(
"URL" ), ImportSource::Url );
78 mSymbolTags->setText( QStringLiteral(
"imported" ) );
80 connect( mButtonFetch, &QAbstractButton::clicked,
this, &QgsStyleExportImportDialog::fetch );
83 mImportFileWidget->setDialogTitle( tr(
"Load Styles" ) );
84 mImportFileWidget->setFilter( tr(
"XML files (*.xml *.XML)" ) );
87 mImportFileWidget->setDefaultRoot( settings.
value( QStringLiteral(
"StyleManager/lastImportDir" ), QDir::homePath(),
QgsSettings::Gui ).toString() );
90 label->setText( tr(
"Select items to import" ) );
91 buttonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Import" ) );
93 dialogStyle = mTempStyle.get();
97 setWindowTitle( tr(
"Export Item(s)" ) );
99 mLocationStackedEdit->setHidden(
true );
100 fromLabel->setHidden(
true );
101 importTypeCombo->setHidden(
true );
102 mLocationLabel->setHidden(
true );
104 mFavorite->setHidden(
true );
105 mIgnoreXMLTags->setHidden(
true );
107 pb =
new QPushButton( tr(
"Select by Group…" ) );
108 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
110 tagLabel->setHidden(
true );
111 mSymbolTags->setHidden(
true );
112 tagHintLabel->setHidden(
true );
114 buttonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Export" ) );
116 dialogStyle = mStyle;
120 listItems->setIconSize( QSize(
static_cast< int >(
iconSize ),
static_cast< int >(
iconSize * 0.9 ) ) );
122 listItems->setGridSize( QSize(
static_cast< int >( listItems->iconSize().width() * 1.4 ),
static_cast< int >( listItems->iconSize().height() * 1.7 ) ) );
123 listItems->setTextElideMode( Qt::TextElideMode::ElideRight );
130 listItems->setModel( mModel );
132 connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
133 this, &QgsStyleExportImportDialog::selectionChanged );
136 disconnect( buttonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
138 buttonBox->button( QDialogButtonBox::Ok )->setEnabled(
false );
140 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsStyleExportImportDialog::showHelp );
145 QModelIndexList selection = listItems->selectionModel()->selectedIndexes();
146 if ( selection.isEmpty() )
148 QMessageBox::warning(
this, tr(
"Export/import Item(s)" ),
149 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,
158 tr(
"XML files (*.xml *.XML)" ) );
159 if ( fileName.isEmpty() )
163 settings.
setValue( QStringLiteral(
"StyleManager/lastExportDir" ), QFileInfo( fileName ).absolutePath(),
QgsSettings::Gui );
166 if ( !fileName.endsWith( QLatin1String(
".xml" ), Qt::CaseInsensitive ) )
168 fileName += QLatin1String(
".xml" );
171 mFileName = fileName;
173 mCursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
174 moveStyles( &selection, mStyle, mTempStyle.get() );
175 if ( !mTempStyle->exportXml( mFileName ) )
177 mCursorOverride.reset();
178 QMessageBox::warning(
this, tr(
"Export Symbols" ),
179 tr(
"Error when saving selected symbols to file:\n%1" )
180 .arg( mTempStyle->errorString() ) );
185 mCursorOverride.reset();
186 QMessageBox::information(
this, tr(
"Export Symbols" ),
187 tr(
"The selected symbols were successfully exported to file:\n%1" )
193 mCursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
194 moveStyles( &selection, mTempStyle.get(), mStyle );
197 mCursorOverride.reset();
204bool QgsStyleExportImportDialog::populateStyles()
211 if ( !mTempStyle->importXml( mFileName ) )
214 QMessageBox::warning(
this, tr(
"Import Symbols or Color Ramps" ),
215 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,
238 mSymbolTags->text().split(
',' ), mFavorite->isChecked(), mIgnoreXMLTags->isChecked() );
244 delete mGroupSelectionDlg;
249 mImportFileWidget->setFilePath( path );
254 listItems->selectAll();
259 listItems->clearSelection();
264 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
266 const QModelIndex index = listItems->model()->index( row, 0 );
269 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
276 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
278 const QModelIndex index = listItems->model()->index( row, 0 );
281 const QItemSelection deselection( index, index );
282 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
289 const auto constSymbolNames = symbolNames;
290 for (
const QString &symbolName : constSymbolNames )
292 const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
293 const auto constIndexes = indexes;
294 for (
const QModelIndex &index : constIndexes )
296 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
303 const auto constSymbolNames = symbolNames;
304 for (
const QString &symbolName : constSymbolNames )
306 const QModelIndexList indexes = listItems->model()->match( listItems->model()->index( 0,
QgsStyleModel::Name ), Qt::DisplayRole, symbolName, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
307 const auto constIndexes = indexes;
308 for (
const QModelIndex &index : constIndexes )
310 const QItemSelection deselection( index, index );
311 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
318 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
320 const QModelIndex index = listItems->model()->index( row, 0 );
323 listItems->selectionModel()->select( index, QItemSelectionModel::Select );
330 for (
int row = 0; row < listItems->model()->rowCount(); ++row )
332 const QModelIndex index = listItems->model()->index( row, 0 );
335 const QItemSelection deselection( index, index );
336 listItems->selectionModel()->select( deselection, QItemSelectionModel::Deselect );
363 if ( ! mGroupSelectionDlg )
366 mGroupSelectionDlg->setWindowTitle( tr(
"Select Item(s) by Group" ) );
376 mGroupSelectionDlg->show();
377 mGroupSelectionDlg->raise();
378 mGroupSelectionDlg->activateWindow();
383 const ImportSource source =
static_cast< ImportSource
>( importTypeCombo->itemData( index ).toInt() );
387 case ImportSource::File:
389 mLocationStackedEdit->setCurrentIndex( 0 );
390 mLocationLabel->setText( tr(
"File" ) );
394 case ImportSource::Official:
396 btnBrowse->setText( QStringLiteral(
"Fetch Items" ) );
397 locationLineEdit->setEnabled(
false );
401 case ImportSource::Url:
403 mLocationStackedEdit->setCurrentIndex( 1 );
404 mLocationLabel->setText( tr(
"URL" ) );
410void QgsStyleExportImportDialog::fetch()
412 downloadStyleXml( QUrl( mUrlLineEdit->text() ) );
415void QgsStyleExportImportDialog::importFileChanged(
const QString &path )
417 if ( path.isEmpty() )
421 const QFileInfo pathInfo( mFileName );
422 const QString tag = pathInfo.fileName().remove( QStringLiteral(
".xml" ) );
423 mSymbolTags->setText( tag );
424 if ( QFileInfo::exists( mFileName ) )
428 mImportFileWidget->setDefaultRoot( pathInfo.absolutePath() );
434void QgsStyleExportImportDialog::downloadStyleXml(
const QUrl &url )
436 mTempFile =
new QTemporaryFile();
437 if ( mTempFile->open() )
439 mFileName = mTempFile->fileName();
441 QProgressDialog *progressDlg =
new QProgressDialog(
this );
442 progressDlg->setLabelText( tr(
"Downloading style…" ) );
443 progressDlg->setAutoClose(
true );
452 QNetworkReply *reply = fetcher->
reply();
453 if ( !reply || reply->error() != QNetworkReply::NoError )
458 QMessageBox::information( this, tr(
"Import from URL" ),
459 tr(
"HTTP Error! Download failed: %1." ).arg( reply->errorString() ) );
463 mTempFile->write( reply->readAll() );
468 progressDlg->deleteLater();
475void QgsStyleExportImportDialog::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
478 Q_UNUSED( deselected )
479 const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
480 buttonBox->button( QDialogButtonBox::Ok )->setDisabled( nothingSelected );
483void QgsStyleExportImportDialog::showHelp()
485 QgsHelp::openHelp( QStringLiteral(
"style_library/style_manager.html#sharing-style-items" ) );
SymbolType
Attribute editing capabilities which may be supported by vector data providers.
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.
Handles HTTP network content fetching in a background task.
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.
This class is a composition of two QSettings instances:
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.
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
@ TypeRole
Style entity type, see QgsStyle::StyleEntity.
@ IsFavoriteRole
Whether entity is flagged as a favorite.
@ SymbolTypeRole
Symbol type (for symbol or legend patch shape entities)
@ TagRole
String list of tags.
A QSortFilterProxyModel subclass for showing filtered symbol and color ramps entries from a QgsStyle ...
void addDesiredIconSize(QSize size)
Adds an additional icon size to generate for Qt::DecorationRole data.
void addTargetScreenProperties(const QgsScreenProperties &properties)
Adds additional target screen properties to use when generating icons for Qt::DecorationRole data.
QStringList symbolsOfSmartgroup(StyleEntity type, int id)
Returns the symbols for the smartgroup.
StyleEntity
Enum for Entities involved in a style.
@ TextFormatEntity
Text formats.
@ ColorrampEntity
Color ramps.
int smartgroupId(const QString &smartgroup)
Returns the database id for the given smartgroup name.
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.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.