25 #include "qgslayertree.h"
26 #include "qgslayertreeutils.h"
27 #include "qgslayertreeregistrybridge.h"
40 #include <QApplication>
44 #include <QTextStream>
64 QStringList keyTokens = QStringList( scope );
65 keyTokens += key.split(
'/', QString::SkipEmptyParts );
68 keyTokens.push_front(
"properties" );
95 while ( ! keySequence.isEmpty() )
99 if ( keySequence.first() == currentProperty->
name() )
102 keySequence.pop_front();
105 if ( 1 == keySequence.count() )
107 return currentProperty->
find( keySequence.front() );
113 else if ( keySequence.isEmpty() )
115 return currentProperty;
117 else if (( nextProperty = currentProperty->
find( keySequence.first() ) ) )
119 if ( nextProperty->
isKey() )
127 else if ( nextProperty->
isValue() && ( 1 == keySequence.count() ) )
129 return currentProperty;
172 while ( ! keySequence.isEmpty() )
176 if ( keySequence.first() == currentProperty->
name() )
179 keySequence.pop_front();
183 if ( 1 == keySequence.count() )
185 currentProperty->
setValue( keySequence.front(), value );
186 return currentProperty;
190 else if ( keySequence.isEmpty() )
194 return currentProperty;
196 else if (( newProperty = currentProperty->
find( keySequence.first() ) ) )
200 if ( currentProperty )
211 newProperty = currentProperty->
addKey( keySequence.first() );
244 while ( ! keySequence.isEmpty() )
248 if ( keySequence.first() == currentProperty->
name() )
251 keySequence.pop_front();
255 if ( 1 == keySequence.count() )
257 currentProperty->
removeKey( keySequence.front() );
262 else if ( keySequence.isEmpty() )
264 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
266 else if (( nextProperty = currentProperty->
find( keySequence.first() ) ) )
268 previousQgsPropertyKey = currentProperty;
271 if ( currentProperty )
324 file.setFileName( QString() );
338 , mRootGroup( new QgsLayerTreeGroup )
410 imp_->file.setFileName( name );
419 return imp_->file.fileName();
432 writeEntry(
"PositionPrecision",
"/Automatic",
true );
433 writeEntry(
"PositionPrecision",
"/DecimalPlaces", 2 );
446 topQgsPropertyKey.
dump();
486 QDomNodeList properties = doc.elementsByTagName(
"properties" );
488 if ( properties.count() > 1 )
490 QgsDebugMsg(
"there appears to be more than one ``properties'' XML tag ... bailing" );
493 else if ( properties.count() < 1 )
500 QDomNodeList scopes = properties.item( 0 ).childNodes();
502 if ( scopes.count() < 1 )
504 QgsDebugMsg(
"empty ``properties'' XML tag ... bailing" );
508 QDomNode propertyNode = properties.item( 0 );
510 if ( ! project_properties.
readXML( propertyNode ) )
512 QgsDebugMsg(
"Project_properties.readXML() failed" );
518 while ( i < scopes.count() )
520 QDomNode curr_scope_node = scopes.item( i );
522 qDebug(
"found %d property node(s) for scope %s",
523 curr_scope_node.childNodes().count(),
524 curr_scope_node.nodeName().utf8().constData() );
526 QString key( curr_scope_node.nodeName() );
536 currentKey = project_properties.
addKey( key );
540 qDebug(
"%s:%d unable to add key", __FILE__, __LINE__ );
544 if ( ! currentKey->readXML( curr_scope_node ) )
546 qDebug(
"%s:%d unable to read XML for property %s", __FILE__, __LINE__,
547 curr_scope_node.nodeName().utf8().constData() );
569 static void _getTitle( QDomDocument
const &doc, QString & title )
571 QDomNodeList nl = doc.elementsByTagName(
"title" );
581 QDomNode titleNode = nl.item( 0 );
583 if ( !titleNode.hasChildNodes() )
589 QDomNode titleTextNode = titleNode.firstChild();
591 if ( !titleTextNode.isText() )
597 QDomText titleText = titleTextNode.toText();
599 title = titleText.data();
610 QDomNodeList nl = doc.elementsByTagName(
"qgis" );
614 QgsDebugMsg(
" unable to find qgis element in project file" );
618 QDomNode qgisNode = nl.item( 0 );
620 QDomElement qgisElement = qgisNode.toElement();
622 return projectVersion;
679 QDomNodeList nl = doc.elementsByTagName(
"maplayer" );
685 QList<QDomNode> brokenNodes;
692 if ( 0 == nl.count() )
694 return qMakePair(
true, brokenNodes );
702 bool returnStatus =
true;
708 QList< QPair< QgsVectorLayer*, QDomElement > > vLayerList;
710 for (
int i = 0; i < nl.count(); i++ )
712 QDomNode node = nl.item( i );
713 QDomElement element = node.toElement();
715 QString name = node.namedItem(
"layername" ).toElement().text();
716 if ( !name.isNull() )
719 if ( element.attribute(
"embedded" ) ==
"1" )
726 if ( !
addLayer( element, brokenNodes, vLayerList ) )
728 returnStatus =
false;
736 QList< QPair< QgsVectorLayer*, QDomElement > >::iterator vIt = vLayerList.begin();
737 for ( ; vIt != vLayerList.end(); ++vIt )
739 vIt->first->createJoinCaches();
740 vIt->first->updateFields();
743 return qMakePair( returnStatus, brokenNodes );
747 bool QgsProject::addLayer(
const QDomElement& layerElem, QList<QDomNode>& brokenNodes, QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList )
749 QString type = layerElem.attribute(
"type" );
753 if ( type ==
"vector" )
757 else if ( type ==
"raster" )
761 else if ( type ==
"plugin" )
763 QString typeName = layerElem.attribute(
"name" );
774 Q_CHECK_PTR( mapLayer );
781 QList<QgsMapLayer *> myLayers;
782 myLayers << mapLayer;
787 vectorLayerList.push_back( qMakePair( vLayer, layerElem ) );
795 QgsDebugMsg(
"Unable to load " + type +
" layer" );
796 brokenNodes.push_back( layerElem );
807 imp_->file.setFileName( file.filePath() );
821 std::auto_ptr< QDomDocument > doc =
822 std::auto_ptr < QDomDocument > (
new QDomDocument(
"qgis" ) );
824 if ( !
imp_->file.open( QIODevice::ReadOnly | QIODevice::Text ) )
828 setError(
tr(
"Unable to open %1" ).arg(
imp_->file.fileName() ) );
837 if ( !doc->setContent( &
imp_->file, &errorMsg, &line, &column ) )
841 QMessageBox::critical( 0,
tr(
"Project File Read Error" ),
842 tr(
"%1 at line %2 column %3" ).arg( errorMsg ).arg( line ).arg( column ) );
845 QString errorString =
tr(
"Project file read error: %1 at line %2 column %3" )
846 .arg( errorMsg ).arg( line ).arg( column );
852 setError(
tr(
"%1 for file %2" ).arg( errorString ).arg(
imp_->file.fileName() ) );
867 if ( thisVersion > fileVersion )
870 "version of qgis (saved in " + fileVersion.
text() +
872 "). Problems may occur." );
878 QgsDebugMsg(
"Emitting oldProjectVersionWarning(oldVersion)." );
882 projectFile.updateRevision( thisVersion );
892 imp_->file.setFileName( fileName );
897 QgsDebugMsg( QString::number(
imp_->properties_.count() ) +
" properties read" );
906 mRootGroup->setCustomProperty(
"loading", 1 );
908 QDomElement layerTreeElem = doc->documentElement().firstChildElement(
"layer-tree-group" );
909 if ( !layerTreeElem.isNull() )
911 mRootGroup->readChildrenFromXML( layerTreeElem );
915 QgsLayerTreeUtils::readOldLegend(
mRootGroup, doc->documentElement().firstChildElement(
"legend" ) );
923 QPair< bool, QList<QDomNode> > getMapLayersResults =
_getMapLayers( *doc );
926 bool clean = getMapLayersResults.first;
930 QgsDebugMsg(
"Unable to get map layers from project file." );
932 if ( ! getMapLayersResults.second.isEmpty() )
934 QgsDebugMsg(
"there are " + QString::number( getMapLayersResults.second.size() ) +
" broken layers" );
948 QgsLayerTreeUtils::removeInvalidLayers(
mRootGroup );
950 mRootGroup->removeCustomProperty(
"loading" );
966 foreach ( QgsLayerTreeNode* child, group->children() )
968 if ( QgsLayerTree::isGroup( child ) )
970 QgsLayerTreeGroup* childGroup = QgsLayerTree::toGroup( child );
971 if ( childGroup->customProperty(
"embedded" ).toInt() )
974 QString projectPath =
readPath( childGroup->customProperty(
"embedded_project" ).toString() );
975 childGroup->setCustomProperty(
"embedded_project", projectPath );
980 QList<QgsLayerTreeNode*> clonedChildren;
981 foreach ( QgsLayerTreeNode* newGroupChild, newGroup->children() )
982 clonedChildren << newGroupChild->clone();
985 childGroup->insertChildNodes( 0, clonedChildren );
993 else if ( QgsLayerTree::isLayer( child ) )
995 if ( child->customProperty(
"embedded" ).toInt() )
997 QList<QDomNode> brokenNodes;
998 QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;
999 createEmbeddedLayer( QgsLayerTree::toLayer( child )->layerId(), child->customProperty(
"embedded_project" ).toString(), brokenNodes, vectorLayerList );
1008 foreach ( QgsLayerTreeNode* node, group->children() )
1010 if ( QgsLayerTree::isGroup( node ) )
1012 if ( !node->customProperty(
"embedded_project" ).toString().isEmpty() )
1015 QString newPath =
writePath( node->customProperty(
"embedded_project" ).toString() );
1016 node->setCustomProperty(
"embedded_project", newPath );
1027 QList<QDomNode> brokenNodes;
1028 QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;
1029 return addLayer( layerNode.toElement(), brokenNodes, vectorLayerList );
1036 imp_->file.setFileName( file.filePath() );
1050 if ( QFile::exists( backup ) )
1051 QFile::remove( backup );
1052 QFile::rename(
fileName(), backup );
1058 if ( !
imp_->file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1063 setError(
tr(
"Unable to save to file %1" ).arg(
imp_->file.fileName() ) );
1066 QFileInfo myFileInfo(
imp_->file );
1067 if ( !myFileInfo.isWritable() )
1072 setError(
tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
1073 .arg(
imp_->file.fileName() ) );
1079 QDomImplementation DomImplementation;
1080 DomImplementation.setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
1082 QDomDocumentType documentType =
1083 DomImplementation.createDocumentType(
"qgis",
"http://mrcc.com/qgis.dtd",
1085 std::auto_ptr < QDomDocument > doc =
1086 std::auto_ptr < QDomDocument > (
new QDomDocument( documentType ) );
1089 QDomElement qgisNode = doc->createElement(
"qgis" );
1090 qgisNode.setAttribute(
"projectname",
title() );
1093 doc->appendChild( qgisNode );
1096 QDomElement titleNode = doc->createElement(
"title" );
1097 qgisNode.appendChild( titleNode );
1099 QDomText titleText = doc->createTextNode(
title() );
1100 titleNode.appendChild( titleText );
1103 QgsLayerTreeNode* clonedRoot =
mRootGroup->clone();
1104 QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
1106 clonedRoot->writeXML( qgisNode );
1117 QDomElement projectLayersNode = doc->createElement(
"projectlayers" );
1118 projectLayersNode.setAttribute(
"layercount", qulonglong( layers.size() ) );
1120 QMap<QString, QgsMapLayer*>::ConstIterator li = layers.constBegin();
1121 while ( li != layers.end() )
1129 QHash< QString, QPair< QString, bool> >::const_iterator emIt =
mEmbeddedLayers.find( ml->
id() );
1133 QDomElement maplayerElem = doc->createElement(
"maplayer" );
1139 projectLayersNode.appendChild( maplayerElem );
1144 if ( emIt.value().second )
1146 QDomElement mapLayerElem = doc->createElement(
"maplayer" );
1147 mapLayerElem.setAttribute(
"embedded", 1 );
1148 mapLayerElem.setAttribute(
"project",
writePath( emIt.value().first ) );
1149 mapLayerElem.setAttribute(
"id", ml->
id() );
1150 projectLayersNode.appendChild( mapLayerElem );
1157 qgisNode.appendChild( projectLayersNode );
1163 QgsDebugMsg( QString(
"there are %1 property scopes" ).arg( static_cast<int>(
imp_->properties_.count() ) ) );
1165 if ( !
imp_->properties_.isEmpty() )
1168 imp_->properties_.writeXML(
"properties", qgisNode, *doc );
1180 QTextStream projectFileStream( &
imp_->file );
1183 doc->save( projectFileStream, 4 );
1190 if ( projectFileStream.pos() == -1 ||
imp_->file.error() != QFile::NoError )
1192 setError(
tr(
"Unable to save to file %1. Your project "
1193 "may be corrupted on disk. Try clearing some space on the volume and "
1194 "check file permissions before pressing save again." )
1195 .arg(
imp_->file.fileName() ) );
1222 return addKey_( scope, key, &
imp_->properties_, value );
1232 return addKey_( scope, key, &
imp_->properties_, value );
1241 return addKey_( scope, key, &
imp_->properties_, value );
1247 const QString & value )
1251 return addKey_( scope, key, &
imp_->properties_, value );
1257 const QStringList & value )
1261 return addKey_( scope, key, &
imp_->properties_, value );
1269 const QString & key,
1279 value =
property->value();
1282 bool valid = QVariant::StringList == value.type();
1291 return value.toStringList();
1300 const QString & key,
1301 const QString & def,
1310 value =
property->value();
1313 bool valid = value.canConvert( QVariant::String );
1322 return value.toString();
1325 return QString( def );
1339 value =
property->value();
1342 bool valid = value.canConvert( QVariant::String );
1351 return value.toInt();
1369 value =
property->value();
1372 bool valid = value.canConvert( QVariant::Double );
1381 return value.toDouble();
1398 value =
property->value();
1401 bool valid = value.canConvert( QVariant::Bool );
1410 return value.toBool();
1432 QStringList entries;
1434 if ( foundProperty )
1450 QStringList entries;
1452 if ( foundProperty )
1482 if ( ! vsiPrefix.isEmpty() )
1486 if ( src.startsWith(
"/vsi", Qt::CaseInsensitive ) )
1487 src.remove( 0, vsiPrefix.size() );
1493 if ( !src.startsWith(
"./" ) && !src.startsWith(
"../" ) )
1495 #if defined(Q_OS_WIN)
1496 if ( src.startsWith(
"\\\\" ) ||
1497 src.startsWith(
"//" ) ||
1498 ( src[0].isLetter() && src[1] ==
':' ) )
1501 return vsiPrefix + src;
1504 if ( src[0] ==
'/' )
1507 return vsiPrefix + src;
1516 if ( home.isNull() )
1517 return vsiPrefix + src;
1519 QFileInfo fi( home +
"/" + src );
1523 return vsiPrefix + src;
1527 return vsiPrefix + fi.canonicalFilePath();
1531 QString srcPath = src;
1534 if ( projPath.isEmpty() )
1536 return vsiPrefix + src;
1539 #if defined(Q_OS_WIN)
1540 srcPath.replace(
"\\",
"/" );
1541 projPath.replace(
"\\",
"/" );
1543 bool uncPath = projPath.startsWith(
"//" );
1546 QStringList srcElems = srcPath.split(
"/", QString::SkipEmptyParts );
1547 QStringList projElems = projPath.split(
"/", QString::SkipEmptyParts );
1549 #if defined(Q_OS_WIN)
1552 projElems.insert( 0,
"" );
1553 projElems.insert( 0,
"" );
1558 projElems.removeLast();
1561 projElems << srcElems;
1562 projElems.removeAll(
"." );
1566 while (( pos = projElems.indexOf(
".." ) ) > 0 )
1569 projElems.removeAt( pos - 1 );
1570 projElems.removeAt( pos - 1 );
1573 #if !defined(Q_OS_WIN)
1575 projElems.prepend(
"" );
1578 return vsiPrefix + projElems.join(
"/" );
1584 if (
readBoolEntry(
"Paths",
"/Absolute",
false ) || src.isEmpty() )
1589 QFileInfo srcFileInfo( src );
1590 QFileInfo projFileInfo(
fileName() );
1591 QString srcPath = srcFileInfo.canonicalFilePath();
1592 QString projPath = projFileInfo.canonicalFilePath();
1594 if ( projPath.isEmpty() )
1601 if ( ! vsiPrefix.isEmpty() )
1603 srcPath.remove( 0, vsiPrefix.size() );
1606 #if defined( Q_OS_WIN )
1607 const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
1609 srcPath.replace(
"\\",
"/" );
1611 if ( srcPath.startsWith(
"//" ) )
1614 srcPath =
"\\\\" + srcPath.mid( 2 );
1617 projPath.replace(
"\\",
"/" );
1618 if ( projPath.startsWith(
"//" ) )
1621 projPath =
"\\\\" + projPath.mid( 2 );
1624 const Qt::CaseSensitivity cs = Qt::CaseSensitive;
1627 QStringList projElems = projPath.split(
"/", QString::SkipEmptyParts );
1628 QStringList srcElems = srcPath.split(
"/", QString::SkipEmptyParts );
1631 projElems.removeLast();
1633 projElems.removeAll(
"." );
1634 srcElems.removeAll(
"." );
1638 while ( srcElems.size() > 0 &&
1639 projElems.size() > 0 &&
1640 srcElems[0].compare( projElems[0], cs ) == 0 )
1642 srcElems.removeFirst();
1643 projElems.removeFirst();
1653 if ( projElems.size() > 0 )
1656 for (
int i = 0; i < projElems.size(); i++ )
1658 srcElems.insert( 0,
".." );
1665 srcElems.insert( 0,
"." );
1668 return vsiPrefix + srcElems.join(
"/" );
1694 QHash< QString, QPair< QString, bool > >::const_iterator it =
mEmbeddedLayers.find(
id );
1699 return it.value().first;
1703 QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList,
bool saveFlag )
1705 QFile projectFile( projectFilePath );
1706 if ( !projectFile.open( QIODevice::ReadOnly ) )
1711 QDomDocument projectDocument;
1712 if ( !projectDocument.setContent( &projectFile ) )
1718 bool useAbsolutePathes =
true;
1719 QDomElement propertiesElem = projectDocument.documentElement().firstChildElement(
"properties" );
1720 if ( !propertiesElem.isNull() )
1722 QDomElement absElem = propertiesElem.firstChildElement(
"Paths" ).firstChildElement(
"Absolute" );
1723 if ( !absElem.isNull() )
1725 useAbsolutePathes = absElem.text().compare(
"true", Qt::CaseInsensitive ) == 0;
1729 QDomElement projectLayersElem = projectDocument.documentElement().firstChildElement(
"projectlayers" );
1730 if ( projectLayersElem.isNull() )
1735 QDomNodeList mapLayerNodes = projectLayersElem.elementsByTagName(
"maplayer" );
1736 for (
int i = 0; i < mapLayerNodes.size(); ++i )
1739 QDomElement mapLayerElem = mapLayerNodes.at( i ).toElement();
1740 QString
id = mapLayerElem.firstChildElement(
"id" ).text();
1741 if (
id == layerId )
1744 if ( mapLayerElem.attribute(
"embedded" ) ==
"1" )
1749 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
1752 if ( !useAbsolutePathes )
1754 QDomElement provider = mapLayerElem.firstChildElement(
"provider" );
1755 if ( provider.text() ==
"spatialite" )
1757 QDomElement dsElem = mapLayerElem.firstChildElement(
"datasource" );
1761 QFileInfo absoluteDs( QFileInfo( projectFilePath ).absolutePath() +
"/" + uri.database() );
1762 if ( absoluteDs.exists() )
1765 dsElem.removeChild( dsElem.childNodes().at( 0 ) );
1766 dsElem.appendChild( projectDocument.createTextNode( uri.uri() ) );
1771 QDomElement dsElem = mapLayerElem.firstChildElement(
"datasource" );
1772 QString debug( QFileInfo( projectFilePath ).absolutePath() +
"/" + dsElem.text() );
1773 QFileInfo absoluteDs( QFileInfo( projectFilePath ).absolutePath() +
"/" + dsElem.text() );
1774 if ( absoluteDs.exists() )
1776 dsElem.removeChild( dsElem.childNodes().at( 0 ) );
1777 dsElem.appendChild( projectDocument.createTextNode( absoluteDs.absoluteFilePath() ) );
1782 if (
addLayer( mapLayerElem, brokenNodes, vectorLayerList ) )
1801 QFile projectFile( projectFilePath );
1802 if ( !projectFile.open( QIODevice::ReadOnly ) )
1807 QDomDocument projectDocument;
1808 if ( !projectDocument.setContent( &projectFile ) )
1814 QSet<QString> embeddedIdentifyDisabledLayers;
1815 QDomElement disabledLayersElem = projectDocument.documentElement().firstChildElement(
"properties" ).firstChildElement(
"Identify" ).firstChildElement(
"disabledLayers" );
1816 if ( !disabledLayersElem.isNull() )
1818 QDomNodeList valueList = disabledLayersElem.elementsByTagName(
"value" );
1819 for (
int i = 0; i < valueList.size(); ++i )
1821 embeddedIdentifyDisabledLayers.insert( valueList.at( i ).toElement().text() );
1825 QgsLayerTreeGroup* root =
new QgsLayerTreeGroup;
1827 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement(
"layer-tree-group" );
1828 if ( !layerTreeElem.isNull() )
1830 root->readChildrenFromXML( layerTreeElem );
1834 QgsLayerTreeUtils::readOldLegend( root, projectDocument.documentElement().firstChildElement(
"legend" ) );
1837 QgsLayerTreeGroup* group = root->findGroup( groupName );
1838 if ( !group || group->customProperty(
"embedded" ).toBool() )
1846 QgsLayerTreeGroup* newGroup = QgsLayerTree::toGroup( group->clone() );
1850 newGroup->setCustomProperty(
"embedded", 1 );
1851 newGroup->setCustomProperty(
"embedded_project", projectFilePath );
1859 foreach ( QString layerId, newGroup->findLayerIds() )
1861 if ( embeddedIdentifyDisabledLayers.contains( layerId ) )
1864 thisProjectIdentifyDisabledLayers.append( layerId );
1874 foreach ( QgsLayerTreeNode* child, group->children() )
1877 child->setCustomProperty(
"embedded", 1 );
1879 if ( QgsLayerTree::isGroup( child ) )
1883 else if ( QgsLayerTree::isLayer( child ) )
1886 QList<QDomNode> brokenNodes;
1887 QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;
1888 createEmbeddedLayer( QgsLayerTree::toLayer( child )->layerId(), projectFilePath, brokenNodes, vectorLayerList,
false );
1895 QStringList layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList;
1896 snapSettings( layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList );
1897 int idx = layerIdList.indexOf( layerId );
1900 layerIdList.removeAt( idx );
1901 enabledList.removeAt( idx );
1902 snapTypeList.removeAt( idx );
1903 toleranceUnitList.removeAt( idx );
1904 toleranceList.removeAt( idx );
1905 avoidIntersectionList.removeOne( layerId );
1908 layerIdList.append( layerId );
1911 enabledList.append( enabled ?
"enabled" :
"disabled" );
1917 typeString =
"to_segment";
1921 typeString =
"to_vertex_and_segment";
1925 typeString =
"to_vertex";
1927 snapTypeList.append( typeString );
1933 toleranceList.append( QString::number( tolerance ) );
1936 if ( avoidIntersection )
1938 avoidIntersectionList.append( layerId );
1941 writeEntry(
"Digitizing",
"/LayerSnappingList", layerIdList );
1942 writeEntry(
"Digitizing",
"/LayerSnappingEnabledList", enabledList );
1943 writeEntry(
"Digitizing",
"/LayerSnappingToleranceList", toleranceList );
1944 writeEntry(
"Digitizing",
"/LayerSnappingToleranceUnitList", toleranceUnitList );
1945 writeEntry(
"Digitizing",
"/LayerSnapToList", snapTypeList );
1946 writeEntry(
"Digitizing",
"/AvoidIntersectionsList", avoidIntersectionList );
1951 bool& avoidIntersection )
const
1953 QStringList layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList;
1954 snapSettings( layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList );
1955 int idx = layerIdList.indexOf( layerId );
1962 int minListEntries = idx + 1;
1963 if ( layerIdList.size() < minListEntries || enabledList.size() < minListEntries || snapTypeList.size() < minListEntries ||
1964 toleranceUnitList.size() < minListEntries || toleranceList.size() < minListEntries )
1970 enabled = enabledList.at( idx ) ==
"enabled";
1973 QString snapType = snapTypeList.at( idx );
1974 if ( snapType ==
"to_segment" )
1978 else if ( snapType ==
"to_vertex_and_segment" )
1988 if ( toleranceUnitList.at( idx ) ==
"1" )
1998 tolerance = toleranceList.at( idx ).toDouble();
2001 avoidIntersection = ( avoidIntersectionList.indexOf( layerId ) != -1 );
2006 void QgsProject::snapSettings( QStringList& layerIdList, QStringList& enabledList, QStringList& snapTypeList, QStringList& toleranceUnitList, QStringList& toleranceList,
2007 QStringList& avoidIntersectionList )
const
2009 layerIdList =
readListEntry(
"Digitizing",
"/LayerSnappingList" );
2010 enabledList =
readListEntry(
"Digitizing",
"/LayerSnappingEnabledList" );
2011 toleranceList =
readListEntry(
"Digitizing",
"/LayerSnappingToleranceList" );
2012 toleranceUnitList =
readListEntry(
"Digitizing",
"/LayerSnappingToleranceUnitList" );
2013 snapTypeList =
readListEntry(
"Digitizing",
"/LayerSnapToList" );
2014 avoidIntersectionList =
readListEntry(
"Digitizing",
"/AvoidIntersectionsList" );
2036 if ( !pfi.exists() )
2037 return QString::null;
2039 return pfi.canonicalPath();
QgsLayerTreeGroup * createEmbeddedGroup(const QString &groupName, const QString &projectFilePath)
Create layer group instance defined in an arbitrary project file.
static const char * QGIS_VERSION
const QList< QgsVectorJoinInfo > & vectorJoins() const
bool topologicalEditing() const
Convenience function to query topological editing status.
void updateEmbeddedGroupsProjectPath(QgsLayerTreeGroup *group)
static QgsProperty * findKey_(QString const &scope, QString const &key, QgsPropertyKey &rootProperty)
return the property that matches the given key sequence, if any
void snapSettings(QStringList &layerIdList, QStringList &enabledList, QStringList &snapTypeList, QStringList &snapUnitList, QStringList &toleranceUnitList, QStringList &avoidIntersectionList) const
Base class for all map layer types.
QgsPluginLayer * createLayer(QString typeName)
return new layer if corresponding plugin has been found, else return NULL
QHash< QString, QPair< QString, bool > > mEmbeddedLayers
Embeded layers which are defined in other projects.
QgsPropertyKey properties_
property hierarchy
QgsLayerTreeRegistryBridge * mLayerTreeRegistryBridge
QgsPropertyKey * addKey(const QString &keyName)
add the given property key
void setTopologicalEditing(bool enabled)
Convenience function to set topological editing.
bool snapSettingsForLayer(const QString &layerId, bool &enabled, QgsSnapper::SnappingType &type, QgsTolerance::UnitType &units, double &tolerance, bool &avoidIntersection) const
Convenience function to query snap settings of a layer.
void entryList(QStringList &entries) const
return keys that do not contain other keys
static void _getProperties(QDomDocument const &doc, QgsPropertyKey &project_properties)
Restore any optional properties found in "doc" to "properties".
QgsPropertyValue * setValue(const QString &name, const QVariant &value)
set the value associated with this key
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
static QgsProperty * addKey_(QString const &scope, QString const &key, QgsPropertyKey *rootProperty, QVariant value)
add the given key and value
static void warning(const QString &msg)
Goes to qWarning.
void oldProjectVersionWarning(QString)
emitted when an old project file is read.
QPair< bool, QList< QDomNode > > _getMapLayers(QDomDocument const &doc)
Read map layers from project file.
void setDatabase(const QString &database)
Set database.
void setFileName(const QString &name)
Every project has an associated file that contains its XML.
UnitType
Type of unit of tolerance value from settings.
QString qgsVsiPrefix(QString path)
bool dirty
true if project has been modified since it has been read or saved
QString layerIsEmbedded(const QString &id) const
Returns project file path if layer is embedded from other project file.
void setSnapSettingsForLayer(const QString &layerId, bool enabled, QgsSnapper::SnappingType type, QgsTolerance::UnitType unit, double tolerance, bool avoidIntersection)
Convenience function to set snap settings per layer.
QString homePath() const
Return project's home path.
void clear()
clear project properties when a new project is started
static void _getTitle(QDomDocument const &doc, QString &title)
Get the project title.
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=0) const
void setDirty(bool b)
Set project as dirty (modified).
void projectSaved()
emitted when the project file has been written and closed
void loadEmbeddedNodes(QgsLayerTreeGroup *group)
QString readPath(QString filename) const
turn filename read from the project file to an absolute path
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=0) const
QgsLayerTreeGroup * mRootGroup
SnappingType
Snap to vertex, to segment or both.
bool writeEntry(const QString &scope, const QString &key, bool value)
QStringList readListEntry(const QString &scope, const QString &key, QStringList def=QStringList(), bool *ok=0) const
key value accessors
void dump(int tabs=0) const
dumps out the keys and values
bool createEmbeddedLayer(const QString &layerId, const QString &projectFilePath, QList< QDomNode > &brokenNodes, QList< QPair< QgsVectorLayer *, QDomElement > > &vectorLayerList, bool saveFlag=true)
Creates a maplayer instance defined in an arbitrary project file.
bool read()
presuming that the caller has already reset the map canvas, map registry, and legend ...
static QgsProjectVersion _getVersion(QDomDocument const &doc)
return the version string found in the given Dom document
void removeKey(const QString &keyName)
remove the given key
QStringList subkeyList(const QString &scope, const QString &key) const
return keys with keys – do not return keys that contain only values
void initializeEmbeddedSubtree(const QString &projectFilePath, QgsLayerTreeGroup *group)
bool writeLayerXML(QDomElement &layerElement, QDomDocument &document)
stores state in Dom node
Pixels unit of tolerance.
QList< QgsMapLayer * > addMapLayers(QList< QgsMapLayer * > theMapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
virtual void clearKeys()
delete any sub-nodes
A class to describe the version of a project.
void setBadLayerHandler(QgsProjectBadLayerHandler *handler)
Change handler for missing layers.
void readProject(const QDomDocument &)
emitted when project is being read
void layerLoaded(int i, int n)
emitted when a layer from a projects was read
QString writePath(QString filename) const
prepare a filename to save it to the project file
QString fileName() const
returns file name
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
bool removeEntry(const QString &scope, const QString &key)
remove the given key
Reads and writes project states.
bool readXML(QDomNode &keyNode)
restores property hierarchy to given Dom node
QFile file
current physical project file
void writeMapLayer(QgsMapLayer *mapLayer, QDomElement &layerElem, QDomDocument &doc)
Emitted, when a layer is being saved.
QString error() const
Return error message from previous read/write.
An Abstract Base Class for QGIS project property hierarchies.
QgsProjectBadLayerHandler * mBadLayerHandler
virtual void handleBadLayers(QList< QDomNode > layers, QDomDocument projectDom)
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=0) const
QgsProperty * find(QString &propertyName)
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
void subkeyList(QStringList &entries) const
return keys that contain other keys
void clearError()
Clear error message.
void setError(QString errorMessage)
Set error message from read/write operation.
bool isDirty() const
the dirty flag is true if the project has been modified since the last write()
bool addLayer(const QDomElement &layerElem, QList< QDomNode > &brokenNodes, QList< QPair< QgsVectorLayer *, QDomElement > > &vectorLayerList)
void writeProject(QDomDocument &)
emitted when project is being written
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=0) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
This class manages a set of relations between layers.
static QgsProject * theProject_
std::auto_ptr< Imp > imp_
implementation handle
static QgsProject * instance()
access to canonical QgsProject instance
static void removeKey_(QString const &scope, QString const &key, QgsPropertyKey &rootProperty)
void setTitle(const QString &title)
Set project title.
void loadingLayer(QString)
const QMap< QString, QgsMapLayer * > & mapLayers()
Retrieve the mapLayers collection (mainly intended for use by projection)
QStringList entryList(const QString &scope, const QString &key) const
return keys with values – do not return keys that contain other keys
bool readLayerXML(const QDomElement &layerElement)
sets state from Dom document
QString title
project title
const QString & title() const
returns title
QgsRelationManager * mRelationManager
void dumpProperties() const
dump out current project properties to stderr
void clearProperties()
syntactic sugar for property lists
static QgsPluginLayerRegistry * instance()
means of accessing canonical single instance
static QStringList makeKeyTokens_(QString const &scope, QString const &key)
Take the given scope and key and convert them to a string list of key tokens that will be used to nav...
const QString & name() const
every key has a name
void readMapLayer(QgsMapLayer *mapLayer, const QDomElement &layerNode)
Emitted, after the basic initialisation of a layer from the project file is done. ...
QgsLayerTreeGroup * layerTreeRoot() const
Return pointer to the root (invisible) node of the project's layer tree.
Default bad layer handler which ignores any missing layers.
virtual bool isKey() const =0
returns true if is a QgsPropertyKey
Represents a vector layer which manages a vector based data sets.
QgsRelationManager * relationManager() const
virtual bool isValue() const =0
returns true if is a QgsPropertyValue
static void dump_(QgsPropertyKey const &topQgsPropertyKey)
basically a debugging tool to dump property list values
void clear()
Clear the project.
Interface for classes that handle missing layer files when reading project file.
void snapSettingsChanged()
virtual void handleBadLayers(QList< QDomNode > layers, QDomDocument projectDom)=0