void TestQgsProject::testPathResolver() { // Test resolver with a non existing file path QgsPathResolver resolverLegacy( QStringLiteral( "/home/qgis/test.qgs" ) ); QCOMPARE( resolverLegacy.readPath( QString() ), QString() ); QCOMPARE( resolverLegacy.writePath( QString() ), QString() ); QCOMPARE( resolverLegacy.writePath( "/home/qgis/file1.txt" ), QString( "./file1.txt" ) ); QCOMPARE( resolverLegacy.writePath( "/home/qgis/subdir/file1.txt" ), QString( "./subdir/file1.txt" ) ); QCOMPARE( resolverLegacy.writePath( "/home/file1.txt" ), QString( "../file1.txt" ) ); QCOMPARE( resolverLegacy.readPath( "./file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QCOMPARE( resolverLegacy.readPath( "./subdir/file1.txt" ), QString( "/home/qgis/subdir/file1.txt" ) ); QCOMPARE( resolverLegacy.readPath( "../file1.txt" ), QString( "/home/file1.txt" ) ); QCOMPARE( resolverLegacy.readPath( "/home/qgis/file1.txt" ), QString( "/home/qgis/file1.txt" ) ); // Test resolver with existing file path QTemporaryDir tmpDir; QString tmpDirName = tmpDir.path(); QDir dir( tmpDirName ); dir.mkpath( tmpDirName + "/home/qgis/" ); QgsPathResolver resolverRel( QString( tmpDirName + "/home/qgis/test.qgs" ) ); QCOMPARE( resolverRel.readPath( QString() ), QString() ); QCOMPARE( resolverRel.writePath( QString() ), QString() ); QCOMPARE( resolverRel.writePath( tmpDirName + "/home/qgis/file1.txt" ), QString( "./file1.txt" ) ); QCOMPARE( resolverRel.writePath( tmpDirName + "/home/qgis/subdir/file1.txt" ), QString( "./subdir/file1.txt" ) ); QCOMPARE( resolverRel.writePath( tmpDirName + "/home/file1.txt" ), QString( "../file1.txt" ) ); QCOMPARE( resolverRel.readPath( "./file1.txt" ), QString( tmpDirName + "/home/qgis/file1.txt" ) ); QCOMPARE( resolverRel.readPath( "./subdir/file1.txt" ), QString( tmpDirName + "/home/qgis/subdir/file1.txt" ) ); QCOMPARE( resolverRel.readPath( "../file1.txt" ), QString( tmpDirName + "/home/file1.txt" ) ); QCOMPARE( resolverRel.readPath( tmpDirName + "/home/qgis/file1.txt" ), QString( tmpDirName + "/home/qgis/file1.txt" ) ); // test older style relative path - file must exist for this to work QTemporaryFile tmpFile; tmpFile.open(); // fileName is not available until we open the file QString tmpName = tmpFile.fileName(); tmpFile.close(); QgsPathResolver tempRel( tmpName ); QFileInfo fi( tmpName ); QFile testFile( fi.path() + QStringLiteral( "/file1.txt" ) ); QVERIFY( testFile.open( QIODevice::WriteOnly | QIODevice::Text ) ); testFile.close(); QVERIFY( QFile::exists( fi.path() + QStringLiteral( "/file1.txt" ) ) ); QCOMPARE( tempRel.readPath( "file1.txt" ), fi.path() + QStringLiteral( "/file1.txt" ) ); QgsPathResolver resolverAbs; QCOMPARE( resolverAbs.writePath( "/home/qgis/file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QCOMPARE( resolverAbs.readPath( "/home/qgis/file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QCOMPARE( resolverAbs.readPath( "./file1.txt" ), QString( "./file1.txt" ) ); // TODO: test non-canonical paths - there are inconsistencies in the implementation // e.g. base filename "/home/qgis/../test.qgs" resolving "/home/qgis/../file1.txt" back and forth }
void TestQgsProject::testPathResolver() { QgsPathResolver resolverRel( QStringLiteral( "/home/qgis/test.qgs" ) ); QCOMPARE( resolverRel.writePath( "/home/qgis/file1.txt" ), QString( "./file1.txt" ) ); QCOMPARE( resolverRel.writePath( "/home/qgis/subdir/file1.txt" ), QString( "./subdir/file1.txt" ) ); QCOMPARE( resolverRel.writePath( "/home/file1.txt" ), QString( "../file1.txt" ) ); QCOMPARE( resolverRel.readPath( "./file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QCOMPARE( resolverRel.readPath( "./subdir/file1.txt" ), QString( "/home/qgis/subdir/file1.txt" ) ); QCOMPARE( resolverRel.readPath( "../file1.txt" ), QString( "/home/file1.txt" ) ); QCOMPARE( resolverRel.readPath( "/home/qgis/file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QgsPathResolver resolverAbs; QCOMPARE( resolverAbs.writePath( "/home/qgis/file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QCOMPARE( resolverAbs.readPath( "/home/qgis/file1.txt" ), QString( "/home/qgis/file1.txt" ) ); QCOMPARE( resolverAbs.readPath( "./file1.txt" ), QString( "./file1.txt" ) ); // TODO: test non-canonical paths - there are inconsistencies in the implementation // e.g. base filename "/home/qgis/../test.qgs" resolving "/home/qgis/../file1.txt" back and forth }
bool QgsLayoutItemPicture::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext &context ) { mPictureWidth = itemElem.attribute( QStringLiteral( "pictureWidth" ), QStringLiteral( "10" ) ).toDouble(); mPictureHeight = itemElem.attribute( QStringLiteral( "pictureHeight" ), QStringLiteral( "10" ) ).toDouble(); mResizeMode = QgsLayoutItemPicture::ResizeMode( itemElem.attribute( QStringLiteral( "resizeMode" ), QStringLiteral( "0" ) ).toInt() ); //when loading from xml, default to anchor point of middle to match pre 2.4 behavior mPictureAnchor = static_cast< QgsLayoutItem::ReferencePoint >( itemElem.attribute( QStringLiteral( "anchorPoint" ), QString::number( QgsLayoutItem::Middle ) ).toInt() ); mSvgFillColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "svgFillColor" ), QgsSymbolLayerUtils::encodeColor( QColor( 255, 255, 255 ) ) ) ); mSvgStrokeColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "svgBorderColor" ), QgsSymbolLayerUtils::encodeColor( QColor( 0, 0, 0 ) ) ) ); mSvgStrokeWidth = itemElem.attribute( QStringLiteral( "svgBorderWidth" ), QStringLiteral( "0.2" ) ).toDouble(); QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) ); if ( !composerItemList.isEmpty() ) { QDomElement composerItemElem = composerItemList.at( 0 ).toElement(); if ( !qgsDoubleNear( composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) ) { //in versions prior to 2.1 picture rotation was stored in the rotation attribute mPictureRotation = composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(); } } mDefaultSvgSize = QSize( 0, 0 ); if ( itemElem.hasAttribute( QStringLiteral( "sourceExpression" ) ) ) { //update pre 2.5 picture expression to use data defined expression QString sourceExpression = itemElem.attribute( QStringLiteral( "sourceExpression" ), QLatin1String( "" ) ); QString useExpression = itemElem.attribute( QStringLiteral( "useExpression" ) ); bool expressionActive; expressionActive = ( useExpression.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 ); mDataDefinedProperties.setProperty( QgsLayoutObject::PictureSource, QgsProperty::fromExpression( sourceExpression, expressionActive ) ); } QString imagePath = itemElem.attribute( QStringLiteral( "file" ) ); // convert from relative path to absolute. For SVG we also need to consider system SVG paths QgsPathResolver pathResolver = context.pathResolver(); if ( imagePath.endsWith( QLatin1String( ".svg" ), Qt::CaseInsensitive ) ) imagePath = QgsSymbolLayerUtils::svgSymbolNameToPath( imagePath, pathResolver ); else imagePath = pathResolver.readPath( imagePath ); mSourcePath = imagePath; //picture rotation if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "pictureRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) ) { mPictureRotation = itemElem.attribute( QStringLiteral( "pictureRotation" ), QStringLiteral( "0" ) ).toDouble(); } //rotation map mNorthMode = static_cast< NorthMode >( itemElem.attribute( QStringLiteral( "northMode" ), QStringLiteral( "0" ) ).toInt() ); mNorthOffset = itemElem.attribute( QStringLiteral( "northOffset" ), QStringLiteral( "0" ) ).toDouble(); mRotationMap = nullptr; mRotationMapId = -1; mRotationMapUuid.clear(); mRotationMapId = itemElem.attribute( QStringLiteral( "mapId" ), QStringLiteral( "-1" ) ).toInt(); mRotationMapUuid = itemElem.attribute( QStringLiteral( "mapUuid" ) ); return true; }