44 mProjectStyle->deleteLater();
45 mProjectStyle =
nullptr;
54 return mDefaultMarkerSymbol ? mDefaultMarkerSymbol->clone() :
nullptr;
57 return mDefaultLineSymbol ? mDefaultLineSymbol->clone() :
nullptr;
60 return mDefaultFillSymbol ? mDefaultFillSymbol->clone() :
nullptr;
74 if ( mDefaultMarkerSymbol.get() == symbol )
77 mDefaultMarkerSymbol.reset( symbol ? symbol->
clone() : nullptr );
83 if ( mDefaultLineSymbol.get() == symbol )
86 mDefaultLineSymbol.reset( symbol ? symbol->
clone() : nullptr );
92 if ( mDefaultFillSymbol.get() == symbol )
95 mDefaultFillSymbol.reset( symbol ? symbol->
clone() : nullptr );
107 return mDefaultColorRamp ? mDefaultColorRamp->clone() :
nullptr;
112 if ( mDefaultColorRamp.get() == colorRamp )
115 mDefaultColorRamp.reset( colorRamp ? colorRamp->
clone() : nullptr );
122 return mDefaultTextFormat;
127 if ( mDefaultTextFormat == textFormat )
130 mDefaultTextFormat = textFormat;
140 mDefaultSymbolOpacity = opacity;
147 if ( mRandomizeDefaultSymbolColor == randomized )
150 mRandomizeDefaultSymbolColor = randomized;
157 mDefaultMarkerSymbol.reset();
158 mDefaultLineSymbol.reset();
159 mDefaultFillSymbol.reset();
160 mDefaultColorRamp.reset();
162 mRandomizeDefaultSymbolColor =
true;
163 mDefaultSymbolOpacity = 1.0;
169 const QString stylePath = mProject->
createAttachedFile( QStringLiteral(
"styles.db" ) );
172 style->
setName( tr(
"Project Style" ) );
185 delete mProjectStyle;
186 mProjectStyle =
nullptr;
195 mProjectStyle->deleteLater();
197 mProjectStyle = style;
198 mProjectStyle->
setName( tr(
"Project Styles" ) );
206 mCombinedStyleModel->
addStyle( mProjectStyle );
213 return mProjectStyle;
218 mRandomizeDefaultSymbolColor = element.attribute( QStringLiteral(
"RandomizeDefaultSymbolColor" ), QStringLiteral(
"0" ) ).toInt();
219 mDefaultSymbolOpacity = element.attribute( QStringLiteral(
"DefaultSymbolOpacity" ), QStringLiteral(
"1.0" ) ).toDouble();
222 QDomElement elem = element.firstChildElement( QStringLiteral(
"markerSymbol" ) );
223 if ( !elem.isNull() )
225 QDomElement symbolElem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
226 mDefaultMarkerSymbol.reset( !symbolElem.isNull() ? QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context ) : nullptr );
230 mDefaultMarkerSymbol.reset();
233 elem = element.firstChildElement( QStringLiteral(
"lineSymbol" ) );
234 if ( !elem.isNull() )
236 QDomElement symbolElem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
237 mDefaultLineSymbol.reset( !symbolElem.isNull() ? QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) : nullptr );
241 mDefaultLineSymbol.reset();
244 elem = element.firstChildElement( QStringLiteral(
"fillSymbol" ) );
245 if ( !elem.isNull() )
247 QDomElement symbolElem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
248 mDefaultFillSymbol.reset( !symbolElem.isNull() ? QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context ) : nullptr );
252 mDefaultFillSymbol.reset();
255 elem = element.firstChildElement( QStringLiteral(
"colorramp" ) );
258 elem = element.firstChildElement( QStringLiteral(
"text-style" ) );
259 if ( !elem.isNull() )
261 mDefaultTextFormat.
readXml( elem, context );
272 const QDomElement styleDatabases = element.firstChildElement( QStringLiteral(
"databases" ) );
273 if ( !styleDatabases.isNull() )
275 const QDomNodeList styleEntries = styleDatabases.childNodes();
276 for (
int i = 0; i < styleEntries.count(); ++i )
278 const QDomElement styleElement = styleEntries.at( i ).toElement();
279 const QString path = styleElement.attribute( QStringLiteral(
"path" ) );
282 mStyleDatabases.append( fullPath );
283 loadStyleAtPath( fullPath );
290 const QString projectStyleId = element.attribute( QStringLiteral(
"projectStyleId" ) );
293 if ( !projectStyleFile.isEmpty() && QFile::exists( projectStyleFile ) )
295 style->
load( projectStyleFile );
300 const QString stylePath = mProject->
createAttachedFile( QStringLiteral(
"styles.db" ) );
304 style->
setName( tr(
"Project Style" ) );
310 const QString iccProfileId = element.attribute( QStringLiteral(
"iccProfileId" ) );
312 if ( !mIccProfileFilePath.isEmpty() )
316 if ( !errorMsg.isEmpty() )
329 QDomElement element = doc.createElement( QStringLiteral(
"ProjectStyleSettings" ) );
331 element.setAttribute( QStringLiteral(
"RandomizeDefaultSymbolColor" ), mRandomizeDefaultSymbolColor ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
332 element.setAttribute( QStringLiteral(
"DefaultSymbolOpacity" ), QString::number( mDefaultSymbolOpacity ) );
334 element.setAttribute( QStringLiteral(
"colorModel" ),
qgsEnumValueToKey( mColorModel ) );
336 if ( mDefaultMarkerSymbol )
338 QDomElement markerSymbolElem = doc.createElement( QStringLiteral(
"markerSymbol" ) );
340 element.appendChild( markerSymbolElem );
343 if ( mDefaultLineSymbol )
345 QDomElement lineSymbolElem = doc.createElement( QStringLiteral(
"lineSymbol" ) );
347 element.appendChild( lineSymbolElem );
350 if ( mDefaultFillSymbol )
352 QDomElement fillSymbolElem = doc.createElement( QStringLiteral(
"fillSymbol" ) );
354 element.appendChild( fillSymbolElem );
357 if ( mDefaultColorRamp )
360 element.appendChild( colorRampElem );
363 if ( mDefaultTextFormat.
isValid() )
365 QDomElement textFormatElem = mDefaultTextFormat.
writeXml( doc, context );
366 element.appendChild( textFormatElem );
370 QDomElement styleDatabases = doc.createElement( QStringLiteral(
"databases" ) );
371 for (
const QString &db : mStyleDatabases )
373 QDomElement dbElement = doc.createElement( QStringLiteral(
"db" ) );
375 styleDatabases.appendChild( dbElement );
377 element.appendChild( styleDatabases );
380 if ( mProject && mProjectStyle )
387 element.setAttribute( QStringLiteral(
"iccProfileId" ), mProject->
attachmentIdentifier( mIccProfileFilePath ) );
395 QList< QgsStyle * > res;
396 res.reserve( mStyles.size() );
410 if ( mProjectStyle && path == mProjectStyle->
fileName() )
411 return mProjectStyle;
413 for (
QgsStyle *style : std::as_const( mStyles ) )
415 if ( style->fileName() == path )
424 if ( mStyleDatabases.contains( path ) )
428 mStyleDatabases.append( path );
429 loadStyleAtPath( path );
437 if ( paths == mStyleDatabases )
442 for (
const QString &path : paths )
445 mStyleDatabases.append( path );
446 loadStyleAtPath( path );
452void QgsProjectStyleSettings::loadStyleAtPath(
const QString &path )
456 const QFileInfo fileInfo( path );
457 if ( fileInfo.suffix().compare( QLatin1String(
"xml" ), Qt::CaseInsensitive ) == 0 )
468 style->
setName( fileInfo.completeBaseName() );
469 mStyles.append( style );
470 mCombinedStyleModel->
addStyle( style );
480void QgsProjectStyleSettings::clearStyles()
482 const QStringList pathsToRemove = mStyleDatabases;
483 for (
const QString &path : pathsToRemove )
486 mStyleDatabases.removeAll( path );
490 style->deleteLater();
491 mStyles.removeAll( style );
497 for (
QgsStyle *style : std::as_const( mStyles ) )
501 qDeleteAll( mStyles );
507 return mCombinedStyleModel;
519#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
539 QgsDebugError(
"Impossible to attach ICC profile, no project defined" );
543 auto clearIccProfile = [
this]()
546 mIccProfileFilePath.clear();
547 mColorSpace = QColorSpace();
550 if ( !mIccProfileFilePath.isEmpty() )
553#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
556 mColorSpace = ok ?
colorSpace : QColorSpace();
563 if ( !mColorSpace.isValid() )
566#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
571 mIccProfileFilePath = mProject->
createAttachedFile( QStringLiteral(
"profile.icc" ) );
572 QFile file( mIccProfileFilePath );
573 if ( !file.open( QIODevice::WriteOnly ) || file.write(
colorSpace.iccProfile() ) < 0 )
582void QgsProjectStyleSettings::makeDirty()
593 : QAbstractListModel( parent )
594 , mSettings( settings )
609 return ( mSettings ? mSettings->
styleDatabasePaths().count() : 0 ) + ( mProjectStyle ? 1 : 0 ) + ( mShowDefault ? 1 : 0 );
614 if ( index.row() < 0 || index.row() >=
rowCount( QModelIndex() ) )
617 const bool isProjectStyle = index.row() == 0 && mProjectStyle;
618 const bool isDefault = mShowDefault && ( ( index.row() == 0 && !mProjectStyle ) || ( index.row() == 1 && mProjectStyle ) );
619 const int styleRow = index.row() - ( mShowDefault ? 1 : 0 ) - ( mProjectStyle ? 1 : 0 );
623 case Qt::DisplayRole:
627 else if ( isProjectStyle )
628 return mProjectStyle->name();
630 return mSettings ? mSettings->
styles().at( styleRow )->name() : QVariant();
632 case Qt::ToolTipRole:
635 else if ( isProjectStyle )
636 return mProjectStyle->name();
638 return mSettings ? QDir::toNativeSeparators( mSettings->
styles().at( styleRow )->fileName() ) : QVariant();
644 else if ( isProjectStyle )
645 return QVariant::fromValue( mProjectStyle.data() );
646 else if (
QgsStyle *style = mSettings->
styles().value( styleRow ) )
647 return QVariant::fromValue( style );
655 else if ( isProjectStyle )
656 return mProjectStyle->fileName();
658 return mSettings ? mSettings->
styles().at( styleRow )->fileName() : QVariant();
667 if ( index.row() == 0 && mProjectStyle )
668 return mProjectStyle;
669 else if ( mShowDefault && ( ( index.row() == 0 && !mProjectStyle ) || ( index.row() == 1 && mProjectStyle ) ) )
671 else if (
QgsStyle *style = qobject_cast< QgsStyle * >( qvariant_cast<QObject *>(
data( index,
static_cast< int >(
CustomRole::Style ) ) ) ) )
679 if ( style == mProjectStyle )
680 return index( 0, 0, QModelIndex() );
682 return index( mProjectStyle ? 1 : 0, 0, QModelIndex() );
686 return QModelIndex();
689 const int r = mSettings->
styles().indexOf( style );
691 return QModelIndex();
693 QModelIndex idx = index( r + ( mShowDefault ? 1 : 0 ) + ( mProjectStyle ? 1 : 0 ), 0, QModelIndex() );
699 return QModelIndex();
704 if ( show == mShowDefault )
707 const int row = mProjectStyle ? 1 : 0;
710 beginInsertRows( QModelIndex(), row, row );
716 beginRemoveRows( QModelIndex(), row, row );
717 mShowDefault =
false;
722void QgsProjectStyleDatabaseModel::setProjectStyle(
QgsStyle *style )
724 if ( style == mProjectStyle )
730 disconnect( mProjectStyle, &QgsStyle::destroyed,
this, &QgsProjectStyleDatabaseModel::projectStyleDestroyed );
731 beginRemoveRows( QModelIndex(), 0, 0 );
732 mProjectStyle =
nullptr;
738 beginInsertRows( QModelIndex(), 0, 0 );
739 mProjectStyle = style;
743 connect( mProjectStyle, &QgsStyle::destroyed,
this, &QgsProjectStyleDatabaseModel::projectStyleDestroyed );
747void QgsProjectStyleDatabaseModel::styleDatabaseAboutToBeAdded(
const QString & )
749 int row = mSettings->
styles().count() + ( mShowDefault ? 1 : 0 ) + ( mProjectStyle ? 1 : 0 );
750 beginInsertRows( QModelIndex(), row, row );
753void QgsProjectStyleDatabaseModel::styleDatabaseAboutToBeRemoved(
const QString &path )
756 int row = mSettings->
styles().indexOf( style ) + ( mShowDefault ? 1 : 0 ) + ( mProjectStyle ? 1 : 0 );
758 beginRemoveRows( QModelIndex(), row, row );
761void QgsProjectStyleDatabaseModel::styleDatabaseAdded(
const QString & )
766void QgsProjectStyleDatabaseModel::styleDatabaseRemoved(
const QString & )
771void QgsProjectStyleDatabaseModel::projectStyleAboutToBeDestroyed()
773 beginRemoveRows( QModelIndex(), 0, 0 );
776void QgsProjectStyleDatabaseModel::projectStyleDestroyed()
781void QgsProjectStyleDatabaseModel::projectStyleChanged()
791 : QSortFilterProxyModel( parent )
793 setSourceModel( model );
794 setDynamicSortFilter(
true );
QFlags< ProjectReadFlag > ProjectReadFlags
Project load flags.
@ ProjectStyles
Enable the project embedded style library. Enabling this flag can increase the time required to clear...
ColorModel
Color model types.
Abstract base class for color ramps.
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
static Qgis::ColorModel toColorModel(QColorSpace::ColorModel colorModel, bool *ok=nullptr)
Convert and returns Qt colorModel to Qgis::ColorModel.
static QColorSpace iccProfile(const QString &iccProfileFilePath, QString &errorMsg)
Loads an ICC profile from iccProfileFilePath and returns associated color space.
A model which contains entities from multiple QgsStyle databases.
void removeStyle(QgsStyle *style)
Removes a style from the model.
void addStyle(QgsStyle *style)
Adds a style to the model.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
List model representing the style databases associated with a QgsProject.
QVariant data(const QModelIndex &index, int role) const override
void setShowDefaultStyle(bool show)
Sets whether the default style should also be included in the model.
QModelIndex indexFromStyle(QgsStyle *style) const
Returns the model index corresponding to a style.
QgsProjectStyleDatabaseModel(QgsProjectStyleSettings *settings, QObject *parent=nullptr)
Constructor for QgsProjectStyleDatabaseModel, showing the styles from the specified settings.
QgsStyle * styleFromIndex(const QModelIndex &index) const
Returns the style at the corresponding index.
int rowCount(const QModelIndex &parent) const override
@ FilterHideReadOnly
Hide read-only style databases.
QgsProjectStyleDatabaseProxyModel::Filters filters() const
Returns the current filters used for filtering available style.
QFlags< Filter > Filters
Available filter flags for filtering the model.
void setFilters(QgsProjectStyleDatabaseProxyModel::Filters filters)
Sets the current filters used for filtering available styles.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
QgsProjectStyleDatabaseProxyModel(QgsProjectStyleDatabaseModel *model, QObject *parent=nullptr)
Constructor for QgsProjectStyleDatabaseProxyModel, for the specified style database model.
Contains settings and properties relating to how a QgsProject should handle styling.
QColorSpace colorSpace() const
Returns the project's color space.
void setDefaultTextFormat(const QgsTextFormat &textFormat)
Sets the project default text format.
QList< QgsStyle * > styles() const
Returns a list of all the styles associated with the project.
void setStyleDatabasePaths(const QStringList &paths)
Sets the paths to all style databases associated with the project.
QgsStyle * styleAtPath(const QString &path)
Returns a reference to the style database associated with the project with matching file path.
QgsTextFormat defaultTextFormat() const
Returns the project default text format.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
~QgsProjectStyleSettings() override
void setProjectStyle(QgsStyle *style)
Sets the style database to use for the project style.
Qgis::ColorModel colorModel() const
Returns the project's color model.
void projectStyleChanged()
Emitted when the style returned by projectStyle() is changed.
QgsColorRamp * defaultColorRamp() const
Returns the project default color ramp.
QgsSymbol * defaultSymbol(Qgis::SymbolType symbolType) const
Returns the project default symbol for a given type.
void setDefaultSymbol(Qgis::SymbolType symbolType, QgsSymbol *symbol)
Sets the project default symbol for a given type.
QStringList styleDatabasePaths() const
Returns a list of all style databases (file paths) associated with the project.
void reset()
Resets the settings to a default state.
QgsProjectStyleSettings(QgsProject *project=nullptr)
Constructor for QgsProjectStyleSettings for the specified project.
void styleDatabaseAdded(const QString &path)
Emitted when a style database path is added.
void styleDatabaseAboutToBeRemoved(const QString &path)
Emitted when a style database path is about to be removed.
void removeProjectStyle()
Removes and deletes the project style database.
void setRandomizeDefaultSymbolColor(bool randomized)
Sets whether the default symbol fill color is randomized.
void setColorModel(Qgis::ColorModel colorModel)
Set the project's color model to colorModel.
void setColorSpace(const QColorSpace &colorSpace)
Set the project's current color space to colorSpace.
void setDefaultColorRamp(QgsColorRamp *colorRamp)
Sets the project default color ramp.
void addStyleDatabasePath(const QString &path)
Adds a style database path to the project.
void styleDatabaseRemoved(const QString &path)
Emitted when a style database path is removed.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Reads the settings's state from a DOM element.
QgsStyle * projectStyle()
Returns the style database to use for project specific styles.
QgsCombinedStyleModel * combinedStyleModel()
Returns the combined style model which includes all style databases associated with the project.
void setDefaultSymbolOpacity(double opacity)
Sets the default symbol opacity.
void styleDatabaseAboutToBeAdded(const QString &path)
Emitted when a style database path is about to be added.
void styleDatabasesChanged()
Emitted whenever the set of style databases associated with the project is changed.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
bool removeAttachedFile(const QString &path)
Removes the attached file.
QString createAttachedFile(const QString &nameTemplate)
Attaches a file to the project.
QString attachmentIdentifier(const QString &attachedFile) const
Returns an identifier for an attachment file path An attachment identifier is a string which does not...
QString resolveAttachmentIdentifier(const QString &identifier) const
Resolves an attachment identifier to a attachment file path.
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
Qgis::ProjectCapabilities capabilities() const
Returns the project's capabilities, which dictate optional functionality which can be selectively ena...
void setDirty(bool b=true)
Flag the project as dirty (modified).
The class is used as a container of context for various read/write operations on other objects.
void pushMessage(const QString &message, Qgis::MessageLevel level=Qgis::MessageLevel::Warning) const
Append a message to the context.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
void setFileName(const QString &filename)
Sets the current file name of the style database.
void aboutToBeDestroyed()
Emitted just before the style object is destroyed.
bool createDatabase(const QString &filename)
Creates an on-disk database.
void triggerIconRebuild()
Triggers emission of the rebuildIconPreviews() signal.
void setName(const QString &name)
Sets the name of the style.
QString fileName() const
Returns the current file name of the style database.
bool isReadOnly() const
Returns true if the style is considered a read-only library.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
bool createMemoryDatabase()
Creates a temporary memory database.
bool load(const QString &filename)
Loads a file into the style.
QString name() const
Returns the name of the style.
void setReadOnly(bool readOnly)
Sets whether the style is considered a read-only library.
bool importXml(const QString &filename)
Imports the symbols and colorramps into the default style database from the given XML file.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Abstract base class for all rendered symbols.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Container for all settings relating to text rendering.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
bool isValid() const
Returns true if the format is valid.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define QgsDebugError(str)