Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/attributes/attributecontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,7 @@ void AttributeController::renamePhotos()
InputUtils::sanitizePath( newName );

const QFileInfo fi( src );
newName = QStringLiteral( "%1.%2" ).arg( newName, fi.completeSuffix() );
newName = QStringLiteral( "%1.%2" ).arg( newName, fi.suffix() );

const QString dst = CoreUtils::findUniquePath( InputUtils::getAbsolutePath( newName, targetDir ) );
if ( InputUtils::renameFile( src, dst ) )
Expand Down
44 changes: 44 additions & 0 deletions app/test/testattributecontroller.cpp

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice, but it would be better to improve TestCoreUtils::testFindUniquePath

Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,50 @@ void TestAttributeController::testPhotoRenaming()
}
}

void TestAttributeController::testPhotoRenamingCollisionWithDotInName()
{
QString projectName = QStringLiteral( "testPhotoRenamingCollisionWithDotInName" );
QString projectDir = QDir::tempPath() + "/MM_test_projects/" + projectName;

QDir tempDir( projectDir );
QVERIFY( tempDir.removeRecursively() );

QVERIFY( InputUtils::cpDir( TestUtils::testDataDir() + "/test_photo_rename", projectDir ) );
QVERIFY( QFile::exists( projectDir + QStringLiteral( "/image1.jpg" ) ) );

// "photo" naming expression is 'image_' + "notes", so a dot in notes lands in the name too
const QString collidingPath = projectDir + QStringLiteral( "/image_my.notes.jpg" );
QVERIFY( QFile::copy( projectDir + QStringLiteral( "/image1.jpg" ), collidingPath ) );
QVERIFY( QFile::exists( collidingPath ) );

QVERIFY( QgsProject::instance()->read( projectDir + QStringLiteral( "/test_photo_rename.qgz" ) ) );

QgsMapLayer *layer = QgsProject::instance()->mapLayersByName( QStringLiteral( "Survey" ) ).at( 0 );
QgsVectorLayer *surveyLayer = static_cast<QgsVectorLayer *>( layer );
QVERIFY( surveyLayer && surveyLayer->isValid() );

QgsFeature feat( surveyLayer->fields() );
FeatureLayerPair pair( feat, surveyLayer );

AttributeController controller;
controller.setFeatureLayerPair( pair );

const TabItem *tab = controller.tabItem( 0 );
const QVector<QUuid> items = tab->formItems();

controller.setFormValue( items.at( 2 ), QStringLiteral( "my.notes" ) );
controller.setFormValue( items.at( 3 ), QStringLiteral( "image1.jpg" ) );

controller.save();

const QgsFeature f = controller.featureLayerPair().feature();

QVERIFY( QFile::exists( collidingPath ) ); // untouched
QVERIFY( !QFile::exists( projectDir + QStringLiteral( "/image_my (1).notes.jpg" ) ) );
QVERIFY( QFile::exists( projectDir + QStringLiteral( "/image_my.notes (1).jpg" ) ) );
QCOMPARE( f.attribute( 3 ), QStringLiteral( "image_my.notes (1).jpg" ) );
}

void TestAttributeController::testHtmlAndTextWidgets()
{
QString projectDir = TestUtils::testDataDir() + "/expressions";
Expand Down
3 changes: 3 additions & 0 deletions app/test/testattributecontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class TestAttributeController: public QObject
void testRawValue();
void testFieldsOutsideForm();
void testPhotoRenaming();

//! A collision suffix must be inserted before the real extension, even if the name has a dot
void testPhotoRenamingCollisionWithDotInName();
void testHtmlAndTextWidgets();
void testVirtualFields();

Expand Down
2 changes: 1 addition & 1 deletion app/test/testcoreutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void TestCoreUtils::testFindUniquePath()
{ "folderA", "folderA (1)" },
{ "non.txt", "non.txt" },
{ "data.gpkg", "data.gpkg" },
{ "arch.tar.gz", "arch (1).tar.gz" },
{ "arch.tar.gz", "arch.tar (1).gz" },
{ "folderA/folder", "folderA/folder" },
{ "folderA/fileA.txt", "folderA/fileA (2).txt" },
{ "folderA/fileB.txt", "folderA/fileB (1).txt" },
Expand Down
3 changes: 2 additions & 1 deletion core/coreutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ QString CoreUtils::findUniquePath( const QString &path )
}
else // file
{
uniquePath = originalPath.path() + '/' + originalPath.baseName() + " (" + QString::number( i ) + ")." + originalPath.completeSuffix();
// split on the last dot, so a dot in the base name isn't mistaken for the extension
uniquePath = originalPath.path() + '/' + originalPath.completeBaseName() + " (" + QString::number( i ) + ")." + originalPath.suffix();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would replace this with: QStringLiteral("%1/%2 (%3).%4").arg(...)

}
f.setFile( uniquePath );
}
Expand Down
Loading