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
1 change: 1 addition & 0 deletions app/android/src/uk/co/lutraconsulting/MMActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ public String importImage(Uri imageUri, String targetPath) {
String fileName = getFileName( imageUri );
File newCopyFile = new File( targetPath + "/" + fileName );
try {
newCopyFile.getParentFile().mkdirs();

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.

If needed, please create a separate PR

newCopyFile.createNewFile();
InputStream fileStream = getContentResolver().openInputStream( imageUri );
copyFile( fileStream, newCopyFile );
Expand Down
80 changes: 73 additions & 7 deletions app/attributes/attributecontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,8 @@ void AttributeController::updateOnFeatureChange()
const QVariant newVal = feature.attribute( fieldIndex );
mFormItems[itemData->id()]->setOriginalValue( newVal );
mFormItems[itemData->id()]->setRawValue( newVal ); // we need to set raw value as well, as we use it in form now
if ( mRememberAttributesController && isNewFeature() ) // this is a new feature
mFormItems[itemData->id()]->setReusedValue( false );
if ( mRememberAttributesController && isNewFeature() && newVal.toString().isEmpty() )

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.

won't the new condition somehow mess up other fieldtypes? or was it just expected until now?

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.

+1 to remove this - let's keep the logic as it was

{
QVariant rememberedValue;
bool shouldUseRememberedValue = mRememberAttributesController->rememberedValue(
Expand All @@ -622,8 +623,36 @@ void AttributeController::updateOnFeatureChange()
);
if ( shouldUseRememberedValue )
{
mFeatureLayerPair.featureRef().setAttribute( fieldIndex, rememberedValue );
itemData->setRawValue( rememberedValue );
QVariant valueToUse = rememberedValue;

if ( itemData->editorWidgetType() == QStringLiteral( "ExternalResource" ) && !rememberedValue.toString().isEmpty() )

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.

Check if valueToUse is a file

{
const QVariantMap config = itemData->editorWidgetConfig();
const FeatureLayerPair parentPair = mParentController ? mParentController->featureLayerPair() : FeatureLayerPair();
const QString targetDir = InputUtils::resolveTargetDir( QgsProject::instance()->homePath(), config, mFeatureLayerPair, parentPair, QgsProject::instance() );
const QString prefix = InputUtils::resolvePrefixForRelativePath( config[ QStringLiteral( "RelativeStorage" ) ].toInt(), QgsProject::instance()->homePath(), targetDir );
const QString src = InputUtils::getAbsolutePath( rememberedValue.toString(), prefix );
const QFileInfo fi( src );

static const QRegularExpression trailingCounter( QStringLiteral( "\\s\\(\\d+\\)$" ) );
QString baseName = fi.completeBaseName();
baseName.remove( trailingCounter );
const QString canonicalName = fi.suffix().isEmpty() ? baseName : QStringLiteral( "%1.%2" ).arg( baseName, fi.suffix() );

const QString dst = CoreUtils::findUniquePath( InputUtils::getAbsolutePath( canonicalName, targetDir ), true );
Comment on lines +637 to +642

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.

Set file name as the default timestamp, store it in the correct folder


if ( InputUtils::copyFile( src, dst ) )
{
valueToUse = InputUtils::getRelativePath( dst, prefix );
itemData->setReusedCopyPath( dst );
}
}

mFeatureLayerPair.featureRef().setAttribute( fieldIndex, valueToUse );

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.

Watch out, this code is run even if InputUtils::copy on line 644 fails

itemData->setRawValue( valueToUse );
itemData->setOriginalValue( valueToUse );
// an empty value means there's nothing to reuse, so don't mark it as such
itemData->setReusedValue( !valueToUse.toString().isEmpty() );
}
}
}
Expand Down Expand Up @@ -789,9 +818,11 @@ void AttributeController::recalculateDefaultValues(
const QgsField field = item->field();
const QgsDefaultValue defaultDefinition = field.defaultValueDefinition();

// don't let a Default Value expression overwrite a value we just reused
bool shouldApplyDefaultValue =
!defaultDefinition.expression().isEmpty() &&
( isFirstUpdateOfNewFeature || ( isFormValueChange && defaultDefinition.applyOnUpdate() ) );
( isFirstUpdateOfNewFeature || ( isFormValueChange && defaultDefinition.applyOnUpdate() ) ) &&
!item->isReusedValue();
Comment thread
xkello marked this conversation as resolved.

if ( shouldApplyDefaultValue )
{
Expand Down Expand Up @@ -1211,6 +1242,8 @@ bool AttributeController::deleteFeature()

bool AttributeController::rollback()
{
discardReusedPhotoCopies( true );

if ( !mFeatureLayerPair.layer() )
return false;

Expand Down Expand Up @@ -1293,6 +1326,12 @@ bool AttributeController::save()
disconnect( mFeatureLayerPair.layer(), &QgsVectorLayer::featureAdded, this, &AttributeController::onFeatureAdded );
}

if ( rv )
{
// catches a reused copy that got deleted/replaced before save
discardReusedPhotoCopies( false );
}
Comment thread
xkello marked this conversation as resolved.

// Store the feature attributes for future use
if ( featureIsNew && mRememberAttributesController )
{
Expand Down Expand Up @@ -1497,6 +1536,7 @@ bool AttributeController::setFormValue( const QUuid &id, QVariant value )
QgsField field = item->field();
QVariant val( value );

item->setReusedValue( false );
item->setRawValue( val );
emit formDataChanged( item->id(), { AttributeFormModel::RawValue } );

Expand Down Expand Up @@ -1576,6 +1616,27 @@ void AttributeController::onFeatureAdded( QgsFeatureId newFeatureId )
emit featureIdChanged();
}

void AttributeController::discardReusedPhotoCopies( bool force )

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.

drop

{
QMap<QUuid, std::shared_ptr<FormItem>>::const_iterator formItemsIterator = mFormItems.constBegin();
while ( formItemsIterator != mFormItems.constEnd() )
{
std::shared_ptr<FormItem> item = formItemsIterator.value();
const QString copyPath = item->reusedCopyPath();
if ( !copyPath.isEmpty() )
{
// isReusedValue() is cleared as soon as the field changes, so it already tells
// whether the copy is still the field's current value
if ( force || !item->isReusedValue() )
{
InputUtils::removeFile( copyPath );
}
item->setReusedCopyPath( QString() );
}
++formItemsIterator;
}
}

void AttributeController::renamePhotos()
{
const QStringList photoNameFormat = QgsProject::instance()->entryList( QStringLiteral( "Mergin" ), QStringLiteral( "PhotoNaming/%1" ).arg( mFeatureLayerPair.layer()->id() ) );
Expand Down Expand Up @@ -1608,7 +1669,7 @@ void AttributeController::renamePhotos()
continue;
}

if ( item->originalValue() != mFeatureLayerPair.feature().attribute( item->fieldIndex() ) )
if ( item->isReusedValue() || item->originalValue() != mFeatureLayerPair.feature().attribute( item->fieldIndex() ) )
{
const QString expString = QgsProject::instance()->readEntry( QStringLiteral( "Mergin" ), QStringLiteral( "PhotoNaming/%1/%2" ).arg( mFeatureLayerPair.layer()->id(), field.name() ) );
QgsExpression exp( expString );
Expand Down Expand Up @@ -1649,13 +1710,18 @@ 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 ) );
const QString dst = CoreUtils::findUniquePath( InputUtils::getAbsolutePath( newName, targetDir ), true );
if ( InputUtils::renameFile( src, dst ) )
{
const QString newValue = InputUtils::getRelativePath( dst, prefix );
setFormValue( item->id(), newValue );
// keep originalValue() in sync so this doesn't get renamed again on the next save
item->setOriginalValue( newValue );
// only clear if we actually renamed the tracked clone, not a replacement photo
if ( src == item->reusedCopyPath() )
item->setReusedCopyPath( QString() );
expressionContext.setFeature( featureLayerPair().featureRef() );
}
else
Expand Down
1 change: 1 addition & 0 deletions app/attributes/attributecontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class AttributeController : public QObject
*/
bool allowTabs( QgsAttributeEditorContainer *container );

void discardReusedPhotoCopies( bool force );

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.

Let's drop this

//! renames photos if necessary
void renamePhotos();
//! save temporary sketched image to original image
Expand Down
20 changes: 20 additions & 0 deletions app/attributes/attributedata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,26 @@ void FormItem::setOriginalValue( const QVariant &originalValue )
mOriginalValue = originalValue;
}

bool FormItem::isReusedValue() const
{
return mIsReusedValue;
}

void FormItem::setReusedValue( bool reused )
{
mIsReusedValue = reused;
}

QString FormItem::reusedCopyPath() const
{
return mReusedCopyPath;
}

void FormItem::setReusedCopyPath( const QString &path )
{
mReusedCopyPath = path;
}

QgsRelation FormItem::relation() const
{
return mRelation;
Expand Down
8 changes: 8 additions & 0 deletions app/attributes/attributedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ class FormItem
QVariant rawValue() const;
void setRawValue( const QVariant &rawValue );

bool isReusedValue() const;
void setReusedValue( bool reused );

QString reusedCopyPath() const;
void setReusedCopyPath( const QString &path );
Comment thread
xkello marked this conversation as resolved.
Comment on lines +155 to +159

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 part of the app should not be affected

Suggested change
bool isReusedValue() const;
void setReusedValue( bool reused );
QString reusedCopyPath() const;
void setReusedCopyPath( const QString &path );


QgsRelation relation() const;
QString fieldError() const;

Expand All @@ -178,6 +184,8 @@ class FormItem
bool mVisible = false;
QVariant mOriginalValue; // original unmodified value
QVariant mRawValue;
bool mIsReusedValue = false;
QString mReusedCopyPath;

const QgsRelation mRelation; // Only used for FormItemType::Relation
};
Expand Down
4 changes: 4 additions & 0 deletions app/inpututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,8 @@ QString InputUtils::resolveTargetDir( const QString &homePath, const QVariantMap
{
QString result = evaluateExpression( pair, parentPair, activeProject, expression );
sanitizePath( result );
if ( !result.isEmpty() && !QDir::isAbsolutePath( result ) )
result = QDir( homePath ).absoluteFilePath( result );
return result;
}
else
Expand All @@ -1029,6 +1031,8 @@ QString InputUtils::resolveTargetDir( const QString &homePath, const QVariantMap
}
else
{
if ( !QDir::isAbsolutePath( defaultRoot ) )
defaultRoot = QDir( homePath ).absoluteFilePath( defaultRoot );
return defaultRoot;
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/ios/iosviewdelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ - ( void )picker:( PHPickerViewController * )picker didFinishPicking:( NSArray<P
BOOL writeSuccess = NO;
if ( url && !error )
{
[[NSFileManager defaultManager] createDirectoryAtPath:targetDir withIntermediateDirectories:YES attributes:nil error:nil];

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.

If needed, please create a separate PR


NSError *copyError = nil;
[[NSFileManager defaultManager] copyItemAtURL:url toURL:[NSURL fileURLWithPath:imagePath] error:&copyError];
writeSuccess = ( copyError == nil );
Expand Down
Loading
Loading