25 #include <QDomDocument>
26 #include <QDomElement>
27 #include <QDomImplementation>
28 #include <QTextStream>
47 mTransparencyLevel( 255 ),
49 mDataSource( source ),
50 mLayerOrigName( lyrname ),
53 mBlendMode( QPainter::CompositionMode_SourceOver )
63 QDateTime dt = QDateTime::currentDateTime();
64 mID = lyrname + dt.toString(
"yyyyMMddhhmmsszzz" );
71 mID.replace( QRegExp(
"[\\W]" ),
"_" );
103 QgsDebugMsg(
"new original name: '" + name +
"'" );
151 Q_UNUSED( rendererContext );
157 Q_UNUSED( rendererContext );
171 mnl = layerElement.namedItem(
"provider" );
172 mne = mnl.toElement();
173 provider = mne.text();
176 mnl = layerElement.namedItem(
"datasource" );
177 mne = mnl.toElement();
181 if ( provider ==
"spatialite" )
187 else if ( provider ==
"ogr" )
189 QStringList theURIParts =
mDataSource.split(
"|" );
193 else if ( provider ==
"delimitedtext" )
195 QUrl urlSource = QUrl::fromEncoded(
mDataSource.toAscii() );
200 urlSource.setScheme(
"file" );
201 urlSource.setPath( file.path() );
204 QUrl urlDest = QUrl::fromLocalFile(
QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
205 urlDest.setQueryItems( urlSource.queryItems() );
206 mDataSource = QString::fromAscii( urlDest.toEncoded() );
208 else if ( provider ==
"wms" )
223 QgsDebugMsg(
"Old WMS URI format detected -> converting to new format" );
228 QStringListIterator iter( parts );
229 while ( iter.hasNext() )
231 QString item = iter.next();
232 if ( item.startsWith(
"username=" ) )
234 uri.
setParam(
"username", item.mid( 9 ) );
236 else if ( item.startsWith(
"password=" ) )
238 uri.
setParam(
"password", item.mid( 9 ) );
240 else if ( item.startsWith(
"tiled=" ) )
246 QStringList params = item.mid( 6 ).split(
";" );
248 if ( params.size() == 2 )
250 uri.
setParam(
"maxWidth", params.takeFirst() );
251 uri.
setParam(
"maxHeight", params.takeFirst() );
253 else if ( params.size() > 2 )
257 uri.
setParam(
"tileMatrixSet",
"" );
260 else if ( item.startsWith(
"featureCount=" ) )
262 uri.
setParam(
"featureCount", item.mid( 13 ) );
264 else if ( item.startsWith(
"url=" ) )
266 uri.
setParam(
"url", item.mid( 4 ) );
268 else if ( item.startsWith(
"ignoreUrl=" ) )
270 uri.
setParam(
"ignoreUrl", item.mid( 10 ).split(
";" ) );
293 mnl = layerElement.namedItem(
"layername" );
294 mne = mnl.toElement();
296 QDomNode srsNode = layerElement.namedItem(
"srs" );
308 layerError = !
readXml( layerElement );
327 mnl = layerElement.namedItem(
"id" );
328 if ( ! mnl.isNull() )
330 mne = mnl.toElement();
331 if ( ! mne.isNull() && mne.text().length() > 10 )
343 mnl = layerElement.namedItem(
"layername" );
344 mne = mnl.toElement();
348 QDomElement titleElem = layerElement.firstChildElement(
"title" );
349 if ( !titleElem.isNull() )
351 mTitle = titleElem.text();
355 QDomElement abstractElem = layerElement.firstChildElement(
"abstract" );
356 if ( !abstractElem.isNull() )
362 QDomElement keywordListElem = layerElement.firstChildElement(
"keywordList" );
363 if ( !keywordListElem.isNull() )
366 for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
368 kwdList << n.toElement().text();
374 QDomElement dataUrlElem = layerElement.firstChildElement(
"dataUrl" );
375 if ( !dataUrlElem.isNull() )
382 QDomElement attribElem = layerElement.firstChildElement(
"attribution" );
383 if ( !attribElem.isNull() )
390 QDomElement metaUrlElem = layerElement.firstChildElement(
"metadataUrl" );
391 if ( !metaUrlElem.isNull() )
400 QDomNode transparencyNode = layer_node.namedItem(
"transparencyLevelInt" );
401 if ( ! transparencyNode.isNull() )
405 QDomElement myElement = transparencyNode.toElement();
406 setTransparency( myElement.text().toInt() );
418 Q_UNUSED( layer_node );
430 layerElement.setAttribute(
"minimumScale", QString::number(
minimumScale() ) );
431 layerElement.setAttribute(
"maximumScale", QString::number(
maximumScale() ) );
434 QDomElement layerId = document.createElement(
"id" );
435 QDomText layerIdText = document.createTextNode(
id() );
436 layerId.appendChild( layerIdText );
438 layerElement.appendChild( layerId );
441 QDomElement dataSource = document.createElement(
"datasource" );
456 QStringList theURIParts = src.split(
"|" );
458 src = theURIParts.join(
"|" );
460 else if ( vlayer && vlayer->
providerType() ==
"delimitedtext" )
462 QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
463 QUrl urlDest = QUrl::fromLocalFile(
QgsProject::instance()->writePath( urlSource.toLocalFile() ) );
464 urlDest.setQueryItems( urlSource.queryItems() );
465 src = QString::fromAscii( urlDest.toEncoded() );
472 QDomText dataSourceText = document.createTextNode( src );
473 dataSource.appendChild( dataSourceText );
475 layerElement.appendChild( dataSource );
479 QDomElement layerName = document.createElement(
"layername" );
480 QDomText layerNameText = document.createTextNode(
originalName() );
481 layerName.appendChild( layerNameText );
484 QDomElement layerTitle = document.createElement(
"title" ) ;
485 QDomText layerTitleText = document.createTextNode(
title() );
486 layerTitle.appendChild( layerTitleText );
489 QDomElement layerAbstract = document.createElement(
"abstract" );
490 QDomText layerAbstractText = document.createTextNode(
abstract() );
491 layerAbstract.appendChild( layerAbstractText );
493 layerElement.appendChild( layerName );
494 layerElement.appendChild( layerTitle );
495 layerElement.appendChild( layerAbstract );
498 QStringList keywordStringList =
keywordList().split(
"," );
499 if ( keywordStringList.size() > 0 )
501 QDomElement layerKeywordList = document.createElement(
"keywordList" );
502 for (
int i = 0; i < keywordStringList.size(); ++i )
504 QDomElement layerKeywordValue = document.createElement(
"value" );
505 QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
506 layerKeywordValue.appendChild( layerKeywordText );
507 layerKeywordList.appendChild( layerKeywordValue );
509 layerElement.appendChild( layerKeywordList );
514 if ( !aDataUrl.isEmpty() )
516 QDomElement layerDataUrl = document.createElement(
"dataUrl" ) ;
517 QDomText layerDataUrlText = document.createTextNode( aDataUrl );
518 layerDataUrl.appendChild( layerDataUrlText );
520 layerElement.appendChild( layerDataUrl );
525 if ( !aAttribution.isEmpty() )
527 QDomElement layerAttribution = document.createElement(
"attribution" ) ;
528 QDomText layerAttributionText = document.createTextNode( aAttribution );
529 layerAttribution.appendChild( layerAttributionText );
531 layerElement.appendChild( layerAttribution );
536 if ( !aMetadataUrl.isEmpty() )
538 QDomElement layerMetadataUrl = document.createElement(
"metadataUrl" ) ;
539 QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
540 layerMetadataUrl.appendChild( layerMetadataUrlText );
543 layerElement.appendChild( layerMetadataUrl );
549 QDomElement stamp = document.createElement(
"timestamp" );
550 QDomText stampText = document.createTextNode(
timestamp().toString( Qt::ISODate ) );
551 stamp.appendChild( stampText );
552 layerElement.appendChild( stamp );
555 layerElement.appendChild( layerName );
562 QDomElement mySrsElement = document.createElement(
"srs" );
564 layerElement.appendChild( mySrsElement );
568 QDomElement transparencyLevelIntElement = document.createElement(
"transparencyLevelInt" );
569 QDomText transparencyLevelIntText = document.createTextNode( QString::number( getTransparency() ) );
570 transparencyLevelIntElement.appendChild( transparencyLevelIntText );
571 maplayer.appendChild( transparencyLevelIntElement );
578 return writeXml( layerElement, document );
585 Q_UNUSED( layer_node );
586 Q_UNUSED( document );
660 return QStringList();
696 unsigned int QgsMapLayer::getTransparency()
701 void QgsMapLayer::setTransparency(
unsigned int theInt )
712 settings.value(
"/qgis/capitaliseLayerName", QVariant(
false ) ).toBool();
714 QString layerName( name );
716 if ( capitaliseLayerName )
717 layerName = layerName.left( 1 ).toUpper() + layerName.mid( 1 );
727 if ( myURI.startsWith(
"/vsigzip/", Qt::CaseInsensitive ) )
729 myURI.remove( 0, 9 );
731 else if ( myURI.startsWith(
"/vsizip/", Qt::CaseInsensitive ) &&
732 myURI.endsWith(
".zip", Qt::CaseInsensitive ) )
735 myURI.remove( 0, 8 );
737 else if ( myURI.startsWith(
"/vsitar/", Qt::CaseInsensitive ) &&
738 ( myURI.endsWith(
".tar", Qt::CaseInsensitive ) ||
739 myURI.endsWith(
".tar.gz", Qt::CaseInsensitive ) ||
740 myURI.endsWith(
".tgz", Qt::CaseInsensitive ) ) )
743 myURI.remove( 0, 8 );
746 QFileInfo myFileInfo( myURI );
749 if ( myFileInfo.exists() )
752 if ( myURI.endsWith(
".gz", Qt::CaseInsensitive ) )
754 else if ( myURI.endsWith(
".zip", Qt::CaseInsensitive ) )
756 else if ( myURI.endsWith(
".tar", Qt::CaseInsensitive ) )
758 else if ( myURI.endsWith(
".tar.gz", Qt::CaseInsensitive ) )
760 else if ( myURI.endsWith(
".tgz", Qt::CaseInsensitive ) )
762 else if ( myURI.endsWith(
".gz", Qt::CaseInsensitive ) )
764 myFileInfo.setFile( myURI );
766 key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() +
".qml";
783 QgsDebugMsg( QString(
"db = %1 uri = %2" ).arg( db ).arg( theURI ) );
785 bool theResultFlag =
false;
789 sqlite3_stmt *myPreparedStatement;
793 QgsDebugMsg( QString(
"Trying to load style for \"%1\" from \"%2\"" ).arg( theURI ).arg( db ) );
795 if ( !QFile( db ).exists() )
798 myResult = sqlite3_open_v2( db.toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, NULL );
799 if ( myResult != SQLITE_OK )
804 QString mySql =
"select qml from tbl_styles where style=?";
805 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
806 if ( myResult == SQLITE_OK )
808 QByteArray param = theURI.toUtf8();
810 if ( sqlite3_bind_text( myPreparedStatement, 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
811 sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
813 qml = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
814 theResultFlag =
true;
817 sqlite3_finalize( myPreparedStatement );
820 sqlite3_close( myDatabase );
822 return theResultFlag;
829 theResultFlag =
false;
831 QDomDocument myDocument(
"qgis" );
835 QString myErrorMessage;
837 QFile myFile( theURI );
838 if ( myFile.open( QFile::ReadOnly ) )
841 theResultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
842 if ( !theResultFlag )
843 myErrorMessage =
tr(
"%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
849 QgsDebugMsg( QString(
"project fileName: %1" ).arg( project.absoluteFilePath() ) );
853 ( project.exists() &&
loadNamedStyleFromDb( project.absoluteDir().absoluteFilePath( project.baseName() +
".qmldb" ), theURI, qml ) ) ||
856 theResultFlag = myDocument.setContent( qml, &myErrorMessage, &line, &column );
857 if ( !theResultFlag )
859 myErrorMessage =
tr(
"%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
864 myErrorMessage =
tr(
"style not found in database" );
868 if ( !theResultFlag )
870 return myErrorMessage;
874 QgsProjectVersion fileVersion( myDocument.firstChildElement(
"qgis" ).attribute(
"version" ) );
877 if ( thisVersion > fileVersion )
880 "version of qgis (saved in " + fileVersion.text() +
882 "). Problems may occur." );
886 styleFile.updateRevision( thisVersion );
892 QDomElement myRoot = myDocument.firstChildElement(
"qgis" );
893 if ( myRoot.isNull() )
895 myErrorMessage =
tr(
"Error: qgis element could not be found in %1" ).arg( theURI );
896 theResultFlag =
false;
897 return myErrorMessage;
907 QDomNode transparencyNode = myRoot.namedItem(
"transparencyLevelInt" );
908 if ( ! transparencyNode.isNull() )
912 QDomElement myElement = transparencyNode.toElement();
913 setTransparency( myElement.text().toInt() );
919 if ( !theResultFlag )
921 myErrorMessage =
tr(
"Loading style file %1 failed because:\n%2" ).arg( theURI ).arg( errorMsg );
922 return myErrorMessage;
930 QDomImplementation DomImplementation;
931 QDomDocumentType documentType = DomImplementation.createDocumentType(
"qgis",
"http://mrcc.com/qgis.dtd",
"SYSTEM" );
932 QDomDocument myDocument( documentType );
934 QDomElement myRootNode = myDocument.createElement(
"qgis" );
936 myDocument.appendChild( myRootNode );
939 myRootNode.setAttribute(
"minimumScale", QString::number(
minimumScale() ) );
940 myRootNode.setAttribute(
"maximumScale", QString::number(
maximumScale() ) );
944 QDomElement transparencyLevelIntElement = myDocument.createElement(
"transparencyLevelInt" );
945 QDomText transparencyLevelIntText = myDocument.createTextNode( QString::number( getTransparency() ) );
946 transparencyLevelIntElement.appendChild( transparencyLevelIntText );
947 myRootNode.appendChild( transparencyLevelIntElement );
952 errorMsg =
QObject::tr(
"Could not save symbology because:\n%1" ).arg( errorMsg );
965 QString myErrorMessage;
966 QDomDocument myDocument;
977 QStringList theURIParts = theURI.split(
"|" );
978 filename = theURIParts[0];
980 else if ( vlayer && vlayer->
providerType() ==
"delimitedtext" )
982 filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
989 QFileInfo myFileInfo( filename );
990 if ( myFileInfo.exists() || filename.endsWith(
".qml", Qt::CaseInsensitive ) )
992 QFileInfo myDirInfo( myFileInfo.path() );
993 if ( !myDirInfo.isWritable() )
995 return tr(
"The directory containing your dataset needs to be writable!" );
999 QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() +
".qml";
1001 QFile myFile( myFileName );
1002 if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1004 QTextStream myFileStream( &myFile );
1006 myDocument.save( myFileStream, 2 );
1008 theResultFlag =
true;
1009 return tr(
"Created default style file as %1" ).arg( myFileName );
1013 theResultFlag =
false;
1014 return tr(
"ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1019 QString qml = myDocument.toString();
1023 sqlite3_stmt *myPreparedStatement;
1028 if ( myResult != SQLITE_OK )
1030 return tr(
"User database could not be opened." );
1033 QByteArray param0 = theURI.toUtf8();
1034 QByteArray param1 = qml.toUtf8();
1036 QString mySql =
"create table if not exists tbl_styles(style varchar primary key,qml varchar)";
1037 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1038 if ( myResult == SQLITE_OK )
1040 if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
1042 sqlite3_finalize( myPreparedStatement );
1043 sqlite3_close( myDatabase );
1044 theResultFlag =
false;
1045 return tr(
"The style table could not be created." );
1049 sqlite3_finalize( myPreparedStatement );
1051 mySql =
"insert into tbl_styles(style,qml) values (?,?)";
1052 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1053 if ( myResult == SQLITE_OK )
1055 if ( sqlite3_bind_text( myPreparedStatement, 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1056 sqlite3_bind_text( myPreparedStatement, 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1057 sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1059 theResultFlag =
true;
1060 myErrorMessage =
tr(
"The style %1 was saved to database" ).arg( theURI );
1064 sqlite3_finalize( myPreparedStatement );
1066 if ( !theResultFlag )
1068 QString mySql =
"update tbl_styles set qml=? where style=?";
1069 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1070 if ( myResult == SQLITE_OK )
1072 if ( sqlite3_bind_text( myPreparedStatement, 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1073 sqlite3_bind_text( myPreparedStatement, 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1074 sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1076 theResultFlag =
true;
1077 myErrorMessage =
tr(
"The style %1 was updated in the database." ).arg( theURI );
1081 theResultFlag =
false;
1082 myErrorMessage =
tr(
"The style %1 could not be updated in the database." ).arg( theURI );
1087 theResultFlag =
false;
1088 myErrorMessage =
tr(
"The style %1 could not be inserted into database." ).arg( theURI );
1091 sqlite3_finalize( myPreparedStatement );
1094 sqlite3_close( myDatabase );
1097 return myErrorMessage;
1102 QDomDocument myDocument = QDomDocument();
1104 QDomNode header = myDocument.createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\"" );
1105 myDocument.appendChild( header );
1108 QDomElement root = myDocument.createElementNS(
"http://www.opengis.net/sld",
"StyledLayerDescriptor" );
1109 root.setAttribute(
"version",
"1.1.0" );
1110 root.setAttribute(
"xsi:schemaLocation",
"http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" );
1111 root.setAttribute(
"xmlns:ogc",
"http://www.opengis.net/ogc" );
1112 root.setAttribute(
"xmlns:se",
"http://www.opengis.net/se" );
1113 root.setAttribute(
"xmlns:xlink",
"http://www.w3.org/1999/xlink" );
1114 root.setAttribute(
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance" );
1115 myDocument.appendChild( root );
1118 QDomElement namedLayerNode = myDocument.createElement(
"NamedLayer" );
1119 root.appendChild( namedLayerNode );
1124 errorMsg =
tr(
"Could not save symbology because:\n%1" )
1125 .arg(
"Non-vector layers not supported yet" );
1129 if ( !vlayer->
writeSld( namedLayerNode, myDocument, errorMsg ) )
1131 errorMsg =
tr(
"Could not save symbology because:\n%1" ).arg( errorMsg );
1141 QDomDocument myDocument;
1143 if ( !errorMsg.isNull() )
1145 theResultFlag =
false;
1155 QStringList theURIParts = theURI.split(
"|" );
1156 filename = theURIParts[0];
1160 filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1167 QFileInfo myFileInfo( filename );
1168 if ( myFileInfo.exists() || filename.endsWith(
".sld", Qt::CaseInsensitive ) )
1170 QFileInfo myDirInfo( myFileInfo.path() );
1171 if ( !myDirInfo.isWritable() )
1173 return tr(
"The directory containing your dataset needs to be writable!" );
1177 QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() +
".sld";
1179 QFile myFile( myFileName );
1180 if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1182 QTextStream myFileStream( &myFile );
1184 myDocument.save( myFileStream, 2 );
1186 theResultFlag =
true;
1187 return tr(
"Created default style file as %1" ).arg( myFileName );
1191 theResultFlag =
false;
1192 return tr(
"ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1199 theResultFlag =
false;
1201 QDomDocument myDocument;
1205 QString myErrorMessage;
1207 QFile myFile( theURI );
1208 if ( myFile.open( QFile::ReadOnly ) )
1211 theResultFlag = myDocument.setContent( &myFile,
true, &myErrorMessage, &line, &column );
1212 if ( !theResultFlag )
1213 myErrorMessage =
tr(
"%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1218 myErrorMessage =
tr(
"Unable to open file %1" ).arg( theURI );
1221 if ( !theResultFlag )
1223 return myErrorMessage;
1227 QDomElement myRoot = myDocument.firstChildElement(
"StyledLayerDescriptor" );
1228 if ( myRoot.isNull() )
1230 myErrorMessage = QString(
"Error: StyledLayerDescriptor element not found in %1" ).arg( theURI );
1231 theResultFlag =
false;
1232 return myErrorMessage;
1237 QDomElement namedLayerElem = myRoot.firstChildElement(
"NamedLayer" );
1238 if ( namedLayerElem.isNull() )
1240 myErrorMessage = QString(
"Info: NamedLayer element not found." );
1241 theResultFlag =
false;
1242 return myErrorMessage;
1246 theResultFlag =
readSld( namedLayerElem, errorMsg );
1247 if ( !theResultFlag )
1249 myErrorMessage =
tr(
"Loading style file %1 failed because:\n%2" ).arg( theURI ).arg( errorMsg );
1250 return myErrorMessage;
1280 QDomNode propsNode = layerNode.namedItem(
"customproperties" );
1281 if ( propsNode.isNull() )
1284 if ( !keyStartsWith.isEmpty() )
1287 QStringList keysToRemove;
1291 if ( pIt.key().startsWith( keyStartsWith ) )
1293 keysToRemove.push_back( pIt.key() );
1297 QStringList::const_iterator sIt = keysToRemove.constBegin();
1298 for ( ; sIt != keysToRemove.constEnd(); ++sIt )
1308 QDomNodeList nodes = propsNode.childNodes();
1310 for (
int i = 0; i < nodes.size(); i++ )
1312 QDomNode propNode = nodes.at( i );
1313 if ( propNode.isNull() || propNode.nodeName() !=
"property" )
1315 QDomElement propElement = propNode.toElement();
1317 QString key = propElement.attribute(
"key" );
1318 if ( key.isEmpty() || key.startsWith( keyStartsWith ) )
1320 QString value = propElement.attribute(
"value" );
1330 QDomNodeList propertyList = layerNode.toElement().elementsByTagName(
"customproperties" );
1331 for (
int i = 0; i < propertyList.size(); ++i )
1333 layerNode.removeChild( propertyList.at( i ) );
1336 QDomElement propsElement = doc.createElement(
"customproperties" );
1340 QDomElement propElement = doc.createElement(
"property" );
1341 propElement.setAttribute(
"key", it.key() );
1342 propElement.setAttribute(
"value", it.value().toString() );
1343 propsElement.appendChild( propElement );
1346 layerNode.appendChild( propsElement );