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 )
315 properties_.
name() =
"properties";
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 );
1009 QList<QDomNode> brokenNodes;
1010 QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;
1011 return addLayer( layerNode.toElement(), brokenNodes, vectorLayerList );
1018 imp_->file.setFileName( file.filePath() );
1032 if ( QFile::exists( backup ) )
1033 QFile::remove( backup );
1034 QFile::rename(
fileName(), backup );
1040 if ( !
imp_->file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1045 setError(
tr(
"Unable to save to file %1" ).arg(
imp_->file.fileName() ) );
1048 QFileInfo myFileInfo(
imp_->file );
1049 if ( !myFileInfo.isWritable() )
1054 setError(
tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
1055 .arg(
imp_->file.fileName() ) );
1061 QDomImplementation DomImplementation;
1062 DomImplementation.setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
1064 QDomDocumentType documentType =
1065 DomImplementation.createDocumentType(
"qgis",
"http://mrcc.com/qgis.dtd",
1067 std::auto_ptr < QDomDocument > doc =
1068 std::auto_ptr < QDomDocument > (
new QDomDocument( documentType ) );
1071 QDomElement qgisNode = doc->createElement(
"qgis" );
1072 qgisNode.setAttribute(
"projectname",
title() );
1075 doc->appendChild( qgisNode );
1078 QDomElement titleNode = doc->createElement(
"title" );
1079 qgisNode.appendChild( titleNode );
1081 QDomText titleText = doc->createTextNode(
title() );
1082 titleNode.appendChild( titleText );
1085 QgsLayerTreeNode* clonedRoot =
mRootGroup->clone();
1086 QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
1087 QgsLayerTreeUtils::updateEmbeddedGroupsProjectPath( QgsLayerTree::toGroup( clonedRoot ) );
1088 clonedRoot->writeXML( qgisNode );
1099 QDomElement projectLayersNode = doc->createElement(
"projectlayers" );
1100 projectLayersNode.setAttribute(
"layercount", qulonglong( layers.size() ) );
1102 QMap<QString, QgsMapLayer*>::ConstIterator li = layers.constBegin();
1103 while ( li != layers.end() )
1111 QHash< QString, QPair< QString, bool> >::const_iterator emIt =
mEmbeddedLayers.find( ml->
id() );
1115 QDomElement maplayerElem = doc->createElement(
"maplayer" );
1121 projectLayersNode.appendChild( maplayerElem );
1126 if ( emIt.value().second )
1128 QDomElement mapLayerElem = doc->createElement(
"maplayer" );
1129 mapLayerElem.setAttribute(
"embedded", 1 );
1130 mapLayerElem.setAttribute(
"project",
writePath( emIt.value().first ) );
1131 mapLayerElem.setAttribute(
"id", ml->
id() );
1132 projectLayersNode.appendChild( mapLayerElem );
1139 qgisNode.appendChild( projectLayersNode );
1145 QgsDebugMsg( QString(
"there are %1 property scopes" ).arg( static_cast<int>(
imp_->properties_.count() ) ) );
1147 if ( !
imp_->properties_.isEmpty() )
1150 imp_->properties_.writeXML(
"properties", qgisNode, *doc );
1162 QTextStream projectFileStream( &
imp_->file );
1165 doc->save( projectFileStream, 4 );
1172 if ( projectFileStream.pos() == -1 ||
imp_->file.error() != QFile::NoError )
1174 setError(
tr(
"Unable to save to file %1. Your project "
1175 "may be corrupted on disk. Try clearing some space on the volume and "
1176 "check file permissions before pressing save again." )
1177 .arg(
imp_->file.fileName() ) );
1204 return addKey_( scope, key, &
imp_->properties_, value );
1214 return addKey_( scope, key, &
imp_->properties_, value );
1223 return addKey_( scope, key, &
imp_->properties_, value );
1229 const QString & value )
1233 return addKey_( scope, key, &
imp_->properties_, value );
1239 const QStringList & value )
1243 return addKey_( scope, key, &
imp_->properties_, value );
1251 const QString & key,
1261 value =
property->value();
1264 bool valid = QVariant::StringList == value.type();
1273 return value.toStringList();
1282 const QString & key,
1283 const QString & def,
1292 value =
property->value();
1295 bool valid = value.canConvert( QVariant::String );
1304 return value.toString();
1307 return QString( def );
1321 value =
property->value();
1324 bool valid = value.canConvert( QVariant::String );
1333 return value.toInt();
1351 value =
property->value();
1354 bool valid = value.canConvert( QVariant::Double );
1363 return value.toDouble();
1380 value =
property->value();
1383 bool valid = value.canConvert( QVariant::Bool );
1392 return value.toBool();
1414 QStringList entries;
1416 if ( foundProperty )
1432 QStringList entries;
1434 if ( foundProperty )
1464 if ( ! vsiPrefix.isEmpty() )
1468 if ( src.startsWith(
"/vsi", Qt::CaseInsensitive ) )
1469 src.remove( 0, vsiPrefix.size() );
1475 if ( !src.startsWith(
"./" ) && !src.startsWith(
"../" ) )
1477 #if defined(Q_OS_WIN)
1478 if ( src.startsWith(
"\\\\" ) ||
1479 src.startsWith(
"//" ) ||
1480 ( src[0].isLetter() && src[1] ==
':' ) )
1483 return vsiPrefix + src;
1486 if ( src[0] ==
'/' )
1489 return vsiPrefix + src;
1498 if ( home.isNull() )
1499 return vsiPrefix + src;
1501 QFileInfo fi( home +
"/" + src );
1505 return vsiPrefix + src;
1509 return vsiPrefix + fi.canonicalFilePath();
1513 QString srcPath = src;
1516 if ( projPath.isEmpty() )
1518 return vsiPrefix + src;
1521 #if defined(Q_OS_WIN)
1522 srcPath.replace(
"\\",
"/" );
1523 projPath.replace(
"\\",
"/" );
1525 bool uncPath = projPath.startsWith(
"//" );
1528 QStringList srcElems = srcPath.split(
"/", QString::SkipEmptyParts );
1529 QStringList projElems = projPath.split(
"/", QString::SkipEmptyParts );
1531 #if defined(Q_OS_WIN)
1534 projElems.insert( 0,
"" );
1535 projElems.insert( 0,
"" );
1540 projElems.removeLast();
1543 projElems << srcElems;
1544 projElems.removeAll(
"." );
1548 while (( pos = projElems.indexOf(
".." ) ) > 0 )
1551 projElems.removeAt( pos - 1 );
1552 projElems.removeAt( pos - 1 );
1555 #if !defined(Q_OS_WIN)
1557 projElems.prepend(
"" );
1560 return vsiPrefix + projElems.join(
"/" );
1566 if (
readBoolEntry(
"Paths",
"/Absolute",
false ) || src.isEmpty() )
1571 QFileInfo srcFileInfo( src );
1572 QFileInfo projFileInfo(
fileName() );
1573 QString srcPath = srcFileInfo.canonicalFilePath();
1574 QString projPath = projFileInfo.canonicalFilePath();
1576 if ( projPath.isEmpty() )
1583 if ( ! vsiPrefix.isEmpty() )
1585 srcPath.remove( 0, vsiPrefix.size() );
1588 #if defined( Q_OS_WIN )
1589 const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
1591 srcPath.replace(
"\\",
"/" );
1593 if ( srcPath.startsWith(
"//" ) )
1596 srcPath =
"\\\\" + srcPath.mid( 2 );
1599 projPath.replace(
"\\",
"/" );
1600 if ( projPath.startsWith(
"//" ) )
1603 projPath =
"\\\\" + projPath.mid( 2 );
1606 const Qt::CaseSensitivity cs = Qt::CaseSensitive;
1609 QStringList projElems = projPath.split(
"/", QString::SkipEmptyParts );
1610 QStringList srcElems = srcPath.split(
"/", QString::SkipEmptyParts );
1613 projElems.removeLast();
1615 projElems.removeAll(
"." );
1616 srcElems.removeAll(
"." );
1620 while ( srcElems.size() > 0 &&
1621 projElems.size() > 0 &&
1622 srcElems[0].compare( projElems[0], cs ) == 0 )
1624 srcElems.removeFirst();
1625 projElems.removeFirst();
1635 if ( projElems.size() > 0 )
1638 for (
int i = 0; i < projElems.size(); i++ )
1640 srcElems.insert( 0,
".." );
1647 srcElems.insert( 0,
"." );
1650 return vsiPrefix + srcElems.join(
"/" );
1676 QHash< QString, QPair< QString, bool > >::const_iterator it =
mEmbeddedLayers.find(
id );
1681 return it.value().first;
1685 QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList,
bool saveFlag )
1687 QFile projectFile( projectFilePath );
1688 if ( !projectFile.open( QIODevice::ReadOnly ) )
1693 QDomDocument projectDocument;
1694 if ( !projectDocument.setContent( &projectFile ) )
1700 bool useAbsolutePathes =
true;
1702 QDomElement propertiesElem = projectDocument.documentElement().firstChildElement(
"properties" );
1703 if ( !propertiesElem.isNull() )
1705 QDomElement absElem = propertiesElem.firstChildElement(
"Paths" ).firstChildElement(
"Absolute" );
1706 if ( !absElem.isNull() )
1708 useAbsolutePathes = absElem.text().compare(
"true", Qt::CaseInsensitive ) == 0;
1712 QDomElement projectLayersElem = projectDocument.documentElement().firstChildElement(
"projectlayers" );
1713 if ( projectLayersElem.isNull() )
1718 QDomNodeList mapLayerNodes = projectLayersElem.elementsByTagName(
"maplayer" );
1719 for (
int i = 0; i < mapLayerNodes.size(); ++i )
1722 QDomElement mapLayerElem = mapLayerNodes.at( i ).toElement();
1723 QString
id = mapLayerElem.firstChildElement(
"id" ).text();
1724 if (
id == layerId )
1727 if ( mapLayerElem.attribute(
"embedded" ) ==
"1" )
1732 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
1735 if ( !useAbsolutePathes )
1737 QDomElement provider = mapLayerElem.firstChildElement(
"provider" );
1738 if ( provider.text() ==
"spatialite" )
1740 QDomElement dsElem = mapLayerElem.firstChildElement(
"datasource" );
1744 QFileInfo absoluteDs( QFileInfo( projectFilePath ).absolutePath() +
"/" + uri.database() );
1745 if ( absoluteDs.exists() )
1748 dsElem.removeChild( dsElem.childNodes().at( 0 ) );
1749 dsElem.appendChild( projectDocument.createTextNode( uri.uri() ) );
1754 QDomElement dsElem = mapLayerElem.firstChildElement(
"datasource" );
1755 QString debug( QFileInfo( projectFilePath ).absolutePath() +
"/" + dsElem.text() );
1756 QFileInfo absoluteDs( QFileInfo( projectFilePath ).absolutePath() +
"/" + dsElem.text() );
1757 if ( absoluteDs.exists() )
1759 dsElem.removeChild( dsElem.childNodes().at( 0 ) );
1760 dsElem.appendChild( projectDocument.createTextNode( absoluteDs.absoluteFilePath() ) );
1765 if (
addLayer( mapLayerElem, brokenNodes, vectorLayerList ) )
1784 QFile projectFile( projectFilePath );
1785 if ( !projectFile.open( QIODevice::ReadOnly ) )
1790 QDomDocument projectDocument;
1791 if ( !projectDocument.setContent( &projectFile ) )
1797 QSet<QString> embeddedIdentifyDisabledLayers;
1798 QDomElement disabledLayersElem = projectDocument.documentElement().firstChildElement(
"properties" ).firstChildElement(
"Identify" ).firstChildElement(
"disabledLayers" );
1799 if ( !disabledLayersElem.isNull() )
1801 QDomNodeList valueList = disabledLayersElem.elementsByTagName(
"value" );
1802 for (
int i = 0; i < valueList.size(); ++i )
1804 embeddedIdentifyDisabledLayers.insert( valueList.at( i ).toElement().text() );
1808 QgsLayerTreeGroup* root =
new QgsLayerTreeGroup;
1810 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement(
"layer-tree-group" );
1811 if ( !layerTreeElem.isNull() )
1813 root->readChildrenFromXML( layerTreeElem );
1817 QgsLayerTreeUtils::readOldLegend( root, projectDocument.documentElement().firstChildElement(
"legend" ) );
1820 QgsLayerTreeGroup* group = root->findGroup( groupName );
1821 if ( !group || group->customProperty(
"embedded" ).toBool() )
1829 QgsLayerTreeGroup* newGroup = QgsLayerTree::toGroup( group->clone() );
1833 newGroup->setCustomProperty(
"embedded", 1 );
1834 newGroup->setCustomProperty(
"embedded_project", projectFilePath );
1842 foreach ( QString layerId, newGroup->findLayerIds() )
1844 if ( embeddedIdentifyDisabledLayers.contains( layerId ) )
1847 thisProjectIdentifyDisabledLayers.append( layerId );
1857 foreach ( QgsLayerTreeNode* child, group->children() )
1860 child->setCustomProperty(
"embedded", 1 );
1862 if ( QgsLayerTree::isGroup( child ) )
1866 else if ( QgsLayerTree::isLayer( child ) )
1869 QList<QDomNode> brokenNodes;
1870 QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;
1871 createEmbeddedLayer( QgsLayerTree::toLayer( child )->layerId(), projectFilePath, brokenNodes, vectorLayerList,
false );
1878 QStringList layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList;
1879 snapSettings( layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList );
1880 int idx = layerIdList.indexOf( layerId );
1883 layerIdList.removeAt( idx );
1884 enabledList.removeAt( idx );
1885 snapTypeList.removeAt( idx );
1886 toleranceUnitList.removeAt( idx );
1887 toleranceList.removeAt( idx );
1888 avoidIntersectionList.removeOne( layerId );
1891 layerIdList.append( layerId );
1894 enabledList.append( enabled ?
"enabled" :
"disabled" );
1900 typeString =
"to_segment";
1904 typeString =
"to_vertex_and_segment";
1908 typeString =
"to_vertex";
1910 snapTypeList.append( typeString );
1916 toleranceList.append( QString::number( tolerance ) );
1919 if ( avoidIntersection )
1921 avoidIntersectionList.append( layerId );
1924 writeEntry(
"Digitizing",
"/LayerSnappingList", layerIdList );
1925 writeEntry(
"Digitizing",
"/LayerSnappingEnabledList", enabledList );
1926 writeEntry(
"Digitizing",
"/LayerSnappingToleranceList", toleranceList );
1927 writeEntry(
"Digitizing",
"/LayerSnappingToleranceUnitList", toleranceUnitList );
1928 writeEntry(
"Digitizing",
"/LayerSnapToList", snapTypeList );
1929 writeEntry(
"Digitizing",
"/AvoidIntersectionsList", avoidIntersectionList );
1934 bool& avoidIntersection )
const
1936 QStringList layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList;
1937 snapSettings( layerIdList, enabledList, snapTypeList, toleranceUnitList, toleranceList, avoidIntersectionList );
1938 int idx = layerIdList.indexOf( layerId );
1945 int minListEntries = idx + 1;
1946 if ( layerIdList.size() < minListEntries || enabledList.size() < minListEntries || snapTypeList.size() < minListEntries ||
1947 toleranceUnitList.size() < minListEntries || toleranceList.size() < minListEntries )
1953 enabled = enabledList.at( idx ) ==
"enabled";
1956 QString snapType = snapTypeList.at( idx );
1957 if ( snapType ==
"to_segment" )
1961 else if ( snapType ==
"to_vertex_and_segment" )
1971 if ( toleranceUnitList.at( idx ) ==
"1" )
1981 tolerance = toleranceList.at( idx ).toDouble();
1984 avoidIntersection = ( avoidIntersectionList.indexOf( layerId ) != -1 );
1989 void QgsProject::snapSettings( QStringList& layerIdList, QStringList& enabledList, QStringList& snapTypeList, QStringList& toleranceUnitList, QStringList& toleranceList,
1990 QStringList& avoidIntersectionList )
const
1992 layerIdList =
readListEntry(
"Digitizing",
"/LayerSnappingList" );
1993 enabledList =
readListEntry(
"Digitizing",
"/LayerSnappingEnabledList" );
1994 toleranceList =
readListEntry(
"Digitizing",
"/LayerSnappingToleranceList" );
1995 toleranceUnitList =
readListEntry(
"Digitizing",
"/LayerSnappingToleranceUnitList" );
1996 snapTypeList =
readListEntry(
"Digitizing",
"/LayerSnapToList" );
1997 avoidIntersectionList =
readListEntry(
"Digitizing",
"/AvoidIntersectionsList" );
2019 if ( !pfi.exists() )
2020 return QString::null;
2022 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.
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.
Pixels unit of tolerance.
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.
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
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. ...
UnitType
Type of unit of tolerance value from settings.
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