diff --git a/.zenodo.json b/.zenodo.json
index f979fe056..6069ecc14 100644
--- a/.zenodo.json
+++ b/.zenodo.json
@@ -2,7 +2,7 @@
"description": "
Mergin Maps Input app is a QGIS based mobile app for Android and iOS devices.
",
"license": "GPLv3",
"title": "Mergin Maps Input: QGIS in your pocket",
- "version": "2.2.0",
+ "version": "2.3.0",
"upload_type": "software",
"publication_date": "2022-02-24",
"creators": [
@@ -43,7 +43,7 @@
"related_identifiers": [
{
"scheme": "url",
- "identifier": "https://github.com/MerginMaps/input/tree/2.2.0",
+ "identifier": "https://github.com/MerginMaps/input/tree/2.3.0",
"relation": "isSupplementTo"
},
{
diff --git a/CITATION.cff b/CITATION.cff
index 3c32ee9f1..981082bb8 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -1,4 +1,4 @@
-cff-version: 2.2.0
+cff-version: 2.3.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Martin"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 438b9fbb3..32b10e6ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.22)
# TODO automatically change with the scripts/update version script
set(MM_VERSION_MAJOR "2")
-set(MM_VERSION_MINOR "2")
+set(MM_VERSION_MINOR "3")
set(MM_VERSION_PATCH "0")
set(QT_VERSION_DEFAULT "6.4.2")
diff --git a/app/attributes/attributecontroller.cpp b/app/attributes/attributecontroller.cpp
index 90437fa35..2225a5223 100644
--- a/app/attributes/attributecontroller.cpp
+++ b/app/attributes/attributecontroller.cpp
@@ -848,7 +848,7 @@ void AttributeController::recalculateDerivedItems( bool isFormValueChange, bool
++i;
}
- if ( anyChanges )
+ if ( isFormValueChange )
emit formRecalculated();
}
@@ -941,6 +941,8 @@ bool AttributeController::save()
if ( !mFeatureLayerPair.layer() )
return false;
+ renamePhotos();
+
if ( !startEditing() )
{
return false;
@@ -1276,3 +1278,80 @@ void AttributeController::onFeatureAdded( QgsFeatureId newFeatureId )
setFeatureLayerPair( FeatureLayerPair( f, mFeatureLayerPair.layer() ) );
emit featureIdChanged();
}
+
+void AttributeController::renamePhotos()
+{
+ const QStringList photoNameFormat = QgsProject::instance()->entryList( QStringLiteral( "Mergin" ), QStringLiteral( "PhotoNaming/%1" ).arg( mFeatureLayerPair.layer()->id() ) );
+ if ( photoNameFormat.isEmpty() )
+ {
+ return;
+ }
+
+ QgsExpressionContext expressionContext = mFeatureLayerPair.layer()->createExpressionContext();
+ expressionContext << QgsExpressionContextUtils::formScope( mFeatureLayerPair.feature() );
+ if ( mVariablesManager )
+ expressionContext << mVariablesManager->positionScope();
+
+ expressionContext.setFields( mFeatureLayerPair.feature().fields() );
+ expressionContext.setFeature( mFeatureLayerPair.featureRef() );
+
+ // check for new photos
+ QMap>::iterator formItemsIterator = mFormItems.begin();
+ while ( formItemsIterator != mFormItems.end() )
+ {
+ std::shared_ptr item = formItemsIterator.value();
+ if ( item->type() == FormItem::Field && item->editorWidgetType() == QStringLiteral( "ExternalResource" ) )
+ {
+ QVariantMap config = item->editorWidgetConfig();
+ const QgsField field = item->field();
+ if ( !photoNameFormat.contains( field.name() ) )
+ {
+ formItemsIterator++;
+ continue;
+ }
+
+ if ( item->originalValue() != mFeatureLayerPair.feature().attribute( item->fieldIndex() ) )
+ {
+ QString expString = QgsProject::instance()->readEntry( QStringLiteral( "Mergin" ), QStringLiteral( "PhotoNaming/%1/%2" ).arg( mFeatureLayerPair.layer()->id() ).arg( field.name() ) );
+ QgsExpression exp( expString );
+ exp.prepare( &expressionContext );
+ if ( exp.hasParserError() )
+ {
+ CoreUtils::log( QStringLiteral( "Photo name format" ), QStringLiteral( "Expression for %1:%2 has parser error: %3" ).arg( mFeatureLayerPair.layer()->name() ).arg( field.name() ).arg( exp.parserErrorString() ) );
+ formItemsIterator++;
+ continue;
+ }
+
+ QVariant value = exp.evaluate( &expressionContext );
+ if ( exp.hasEvalError() )
+ {
+ CoreUtils::log( QStringLiteral( "Photo name format" ), QStringLiteral( "Expression for %1:%2 has evaluation error: %3" ).arg( mFeatureLayerPair.layer()->name() ).arg( field.name() ).arg( exp.evalErrorString() ) );
+ formItemsIterator++;
+ continue;
+ }
+
+ QVariant val( value );
+ if ( !field.convertCompatible( val ) )
+ {
+ CoreUtils::log( QStringLiteral( "Photo name format" ), QStringLiteral( "Value \"%1\" %4 could not be converted to a compatible value for field %2 (%3)." ).arg( value.toString() ).arg( field.name() ).arg( field.typeName() ).arg( value.isNull() ? "NULL" : "NOT NULL" ) );
+ formItemsIterator++;
+ continue;
+ }
+
+ const QString targetDir = InputUtils::resolveTargetDir( QgsProject::instance()->homePath(), config, mFeatureLayerPair, QgsProject::instance() );
+ const QString prefix = InputUtils::resolvePrefixForRelativePath( config[ QStringLiteral( "RelativeStorage" ) ].toInt(), QgsProject::instance()->homePath(), targetDir );
+ const QString src = InputUtils::getAbsolutePath( mFeatureLayerPair.feature().attribute( item->fieldIndex() ).toString(), prefix );
+ QFileInfo fi( src );
+ QString newName = QStringLiteral( "%1.%2" ).arg( val.toString() ).arg( fi.completeSuffix() );
+ const QString dst = InputUtils::getAbsolutePath( newName, prefix );
+ if ( InputUtils::renameFile( src, dst ) )
+ {
+ mFeatureLayerPair.featureRef().setAttribute( item->fieldIndex(), newName );
+ expressionContext.setFeature( featureLayerPair().featureRef() );
+ }
+ }
+ }
+
+ ++formItemsIterator;
+ }
+}
diff --git a/app/attributes/attributecontroller.h b/app/attributes/attributecontroller.h
index fac3eeaf1..f2ef64656 100644
--- a/app/attributes/attributecontroller.h
+++ b/app/attributes/attributecontroller.h
@@ -219,6 +219,9 @@ class AttributeController : public QObject
*/
bool allowTabs( QgsAttributeEditorContainer *container );
+ //! renames photos if necessary
+ void renamePhotos();
+
bool mConstraintsHardValid = false;
bool mConstraintsSoftValid = false;
bool mHasValidationErrors = false;
diff --git a/app/featuresmodel.cpp b/app/featuresmodel.cpp
index c942a72d6..bc02a335d 100644
--- a/app/featuresmodel.cpp
+++ b/app/featuresmodel.cpp
@@ -12,11 +12,18 @@
#include "qgsproject.h"
#include "qgsexpressioncontextutils.h"
+#include "qgsvectorlayerfeatureiterator.h"
+
+#include
+#include
+#include
+
FeaturesModel::FeaturesModel( QObject *parent )
: QAbstractListModel( parent ),
mLayer( nullptr )
{
+ connect( &mSearchResultWatcher, &QFutureWatcher::finished, this, &FeaturesModel::onFutureFinished );
}
FeaturesModel::~FeaturesModel() = default;
@@ -25,31 +32,77 @@ void FeaturesModel::populate()
{
if ( mLayer )
{
+ mFetchingResults = true;
+ emit fetchingResultsChanged( mFetchingResults );
beginResetModel();
mFeatures.clear();
+ endResetModel();
QgsFeatureRequest req;
setupFeatureRequest( req );
- QgsFeatureIterator it = mLayer->getFeatures( req );
- QgsFeature f;
+ int searchId = mNextSearchId.fetchAndAddOrdered( 1 );
+ QgsVectorLayerFeatureSource *source = new QgsVectorLayerFeatureSource( mLayer );
+ mSearchResultWatcher.setFuture( QtConcurrent::run( &FeaturesModel::fetchFeatures, this, source, req, searchId ) );
+ }
+}
+
+QgsFeatureList FeaturesModel::fetchFeatures( QgsVectorLayerFeatureSource *source, QgsFeatureRequest req, int searchId )
+{
+ std::unique_ptr fs( source );
+ QgsFeatureList fl;
+
+ // a search might have been queued if no threads were available in the pool, so we also
+ // check if canceled before we start as the first iteration can potentially be slow
+ bool canceled = searchId + 1 != mNextSearchId.loadAcquire();
+ if ( canceled )
+ {
+ qDebug() << QString( "Search (%1) was cancelled before it started!" ).arg( searchId );
+ return fl;
+ }
+
+ QElapsedTimer t;
+ t.start();
+ QgsFeatureIterator it = fs->getFeatures( req );
+ QgsFeature f;
- while ( it.nextFeature( f ) )
+ while ( it.nextFeature( f ) )
+ {
+ if ( searchId + 1 != mNextSearchId.loadAcquire() )
{
- if ( FID_IS_NEW( f.id() ) || FID_IS_NULL( f.id() ) )
- {
- continue; // ignore uncommited features
- }
+ canceled = true;
+ break;
+ }
- mFeatures << FeatureLayerPair( f, mLayer );
+ if ( FID_IS_NEW( f.id() ) || FID_IS_NULL( f.id() ) )
+ {
+ continue; // ignore uncommited features
}
- emit layerFeaturesCountChanged( layerFeaturesCount() );
+ fl.append( f );
+ }
- endResetModel();
+ qDebug() << QString( "Search (%1) %2 after %3ms, results: %4" ).arg( searchId ).arg( canceled ? "was canceled" : "completed" ).arg( t.elapsed() ).arg( fl.count() );
+ return fl;
+}
+
+void FeaturesModel::onFutureFinished()
+{
+ QFutureWatcher *watcher = static_cast< QFutureWatcher *>( sender() );
+ const QgsFeatureList features = watcher->future().result();
+ beginResetModel();
+ mFeatures.clear();
+ for ( const auto &f : features )
+ {
+ mFeatures << FeatureLayerPair( f, mLayer );
}
+ emit layerFeaturesCountChanged( layerFeaturesCount() );
+ endResetModel();
+ mFetchingResults = false;
+ emit fetchingResultsChanged( mFetchingResults );
}
+
void FeaturesModel::setup()
{
// define in submodels
@@ -111,7 +164,7 @@ QString FeaturesModel::searchResultPair( const FeatureLayerPair &pair ) const
return QString();
QgsFields fields = pair.feature().fields();
- QStringList words = mSearchExpression.split( ' ', Qt::SkipEmptyParts );
+ const QStringList words = mSearchExpression.split( ' ', Qt::SkipEmptyParts );
QStringList foundPairs;
for ( const QString &word : words )
@@ -145,30 +198,29 @@ QString FeaturesModel::buildSearchExpression()
QStringList expressionParts;
QStringList wordExpressions;
- QStringList words = mSearchExpression.split( ' ', Qt::SkipEmptyParts );
+ const QLocale locale;
+ const QStringList words = mSearchExpression.split( ' ', Qt::SkipEmptyParts );
for ( const QString &word : words )
{
bool searchExpressionIsNumeric;
- int filterInt = word.toInt( &searchExpressionIsNumeric );
- Q_UNUSED( filterInt ); // we only need to know if expression is numeric, int value is not used
+ // we only need to know if expression is numeric, return value is not used
+ locale.toFloat( word, &searchExpressionIsNumeric );
for ( const QgsField &field : fields )
{
- if ( field.configurationFlags().testFlag( QgsField::ConfigurationFlag::NotSearchable ) )
+ if ( field.configurationFlags().testFlag( QgsField::ConfigurationFlag::NotSearchable ) ||
+ ( field.isNumeric() && !searchExpressionIsNumeric ) )
continue;
-
- if ( field.isNumeric() && searchExpressionIsNumeric )
- expressionParts << QStringLiteral( "%1 ~ '%2.*'" ).arg( QgsExpression::quotedColumnRef( field.name() ), word );
- else if ( field.type() == QVariant::String )
+ else if ( field.type() == QVariant::String || field.isNumeric() )
expressionParts << QStringLiteral( "%1 ILIKE '%%2%'" ).arg( QgsExpression::quotedColumnRef( field.name() ), word );
}
wordExpressions << QStringLiteral( "(%1)" ).arg( expressionParts.join( QLatin1String( " ) OR ( " ) ) );
expressionParts.clear();
}
- QString expression = QStringLiteral( "(%1)" ).arg( wordExpressions.join( QLatin1String( " ) AND ( " ) ) );
+ const QString expression = QStringLiteral( "(%1)" ).arg( wordExpressions.join( QLatin1String( " ) AND ( " ) ) );
return expression;
}
@@ -255,7 +307,6 @@ void FeaturesModel::setSearchExpression( const QString &searchExpression )
{
mSearchExpression = searchExpression;
emit searchExpressionChanged( mSearchExpression );
-
populate();
}
}
diff --git a/app/featuresmodel.h b/app/featuresmodel.h
index 03f9e52e0..316f3d75a 100644
--- a/app/featuresmodel.h
+++ b/app/featuresmodel.h
@@ -11,12 +11,18 @@
#define FEATURESMODEL_H
#include
+#include
+#include
#include "qgsvectorlayer.h"
#include "featurelayerpair.h"
#include "inputconfig.h"
+
+class QgsVectorLayerFeatureSource;
+
+
/**
* FeaturesModel class fetches features from layer and provides them via Qt Model's interface
*/
@@ -38,6 +44,9 @@ class FeaturesModel : public QAbstractListModel
// Returns number of features in layer (property). Can be different number than rowCount() due to a searchExpression
Q_PROPERTY( int layerFeaturesCount READ layerFeaturesCount NOTIFY layerFeaturesCountChanged )
+ // Returns if there is a pending feature request that will populate the model
+ Q_PROPERTY( bool fetchingResults MEMBER mFetchingResults NOTIFY fetchingResultsChanged )
+
public:
enum ModelRoles
@@ -99,6 +108,9 @@ class FeaturesModel : public QAbstractListModel
void layerFeaturesCountChanged( int layerFeaturesCount );
+ //! \a isFetching is TRUE when still fetching results, FALSE when done fetching
+ bool fetchingResultsChanged( bool isFetching );
+
protected:
virtual void setupFeatureRequest( QgsFeatureRequest &request );
@@ -109,9 +121,15 @@ class FeaturesModel : public QAbstractListModel
virtual QVariant featureTitle( const FeatureLayerPair &featurePair ) const;
+ private slots:
+ void onFutureFinished();
+
private:
QString buildSearchExpression();
+ //! Performs getFeatures on layer. Takes ownership of \a layer and tries to move it to current thread.
+ QgsFeatureList fetchFeatures( QgsVectorLayerFeatureSource *layer, QgsFeatureRequest req, int searchId );
+
//! Returns found attribute and its value from search expression for feature
QString searchResultPair( const FeatureLayerPair &feat ) const;
@@ -120,6 +138,10 @@ class FeaturesModel : public QAbstractListModel
FeatureLayerPairs mFeatures;
QString mSearchExpression;
QgsVectorLayer *mLayer = nullptr;
+
+ QAtomicInt mNextSearchId = 0;
+ QFutureWatcher mSearchResultWatcher;
+ bool mFetchingResults = false;
};
#endif // FEATURESMODEL_H
diff --git a/app/i18n/input_ca.qm b/app/i18n/input_ca.qm
index 84501a6c3..dd55cb4b6 100644
Binary files a/app/i18n/input_ca.qm and b/app/i18n/input_ca.qm differ
diff --git a/app/i18n/input_ca.ts b/app/i18n/input_ca.ts
index af04f3560..1e67777f6 100644
--- a/app/i18n/input_ca.ts
+++ b/app/i18n/input_ca.ts
@@ -152,27 +152,22 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment.
AndroidUtils
-
-
- Sense permís d'emmagatzematge no podreu accedir als projectes anteriors
-
-
-
+
El permís d'emmagatzematge està denegat permanentment. Permeteu-lo a la configuració per carregar imatges de la galeria
-
+
Input necessita permís d'emmagatzematge per carregar imatges de la galeria
-
+
El permís per emprar la càmera s'ha denegat permanentment, autoritzeu-lo a la configuració
-
+
Necessitem permís per la càmera per tal de fer una foto
@@ -202,7 +197,7 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment.
-
+
El valor "%1" %4 no s'ha pogut convertir en un valor compatible per al camp %2(%3).
@@ -213,18 +208,18 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment.
-
+
La característica no es pot afegir
-
+
No es pot actualitzar la característica
-
+
No es pot començar a editar
@@ -303,35 +298,35 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment.
BluetoothPositionProvider
-
-
+
+
Sense connexió
-
+
Reconnectant
-
-
+
+
Sense connexió, reconnectant en (%1)
-
+
No s'ha pogut connectar al dispositiu, no vinculat
-
+
Connectant a %1
-
-
+
+
Connectat
@@ -794,52 +789,52 @@ No s'afegirà al projecte.
ara fa %1 any
-
+
resolució de pantalla: %1x%2 px
-
+
DPI de pantalla: %1x%2
-
+
mida de pantalla: %1x%2 mm
-
+
relació de píxels del dispositiu informada: %1
-
+
relació de píxels del dispositiu calculada: %1
-
+
escala dp utilitzada: %1
-
+
Heu d'afegir almenys %1 punt(s) a cada tros.
-
+
Heu d'afegir com a mínim %1 punt(s).
@@ -865,8 +860,8 @@ No s'afegirà al projecte.
InternalPositionProvider
-
-
+
+
Connectat
@@ -915,39 +910,6 @@ No s'afegirà al projecte.
Cerca a les capes
-
- LegacyFolderMigration
-
-
-
- No queda prou espai al dispositiu
-
-
-
-
- El vostre dispositiu s'està quedant sense espai, necessiteu %1 d'espai lliure per veure els vostres projectes. Esborreu alguns arxius i torneu-ho a provar o feu clic a Ajuda per veure altres maneres de resoldre aquest problema.
-
-
-
-
- S'ha produït un error durant l'actualització
-
-
-
-
- El vostre dispositiu ha patit un problema durant una actualització. No podreu veure els vostres projectes. Feu clic a Ajuda per veure com resoldre aquest problema.
-
-
-
-
- Estem treballant en una actualització important, no tanqueu l'aplicació
-
-
-
-
- %1/%2
-
-
LocalProjectsManager
@@ -1015,60 +977,66 @@ No s'afegirà al projecte.
MainPanel
-
-
+
+
Projectes
-
-
+
+
GPS
-
-
+
+
Registre
-
-
+
+
Zoom al projecte
-
-
+
+
Canvis locals
-
-
+
+
Capes
-
-
+
+
Temes de mapa
-
-
+
+
+
+ Seguiment de la posició
+
+
+
+
Configuració
-
+
Més
-
+
Menú
@@ -1122,87 +1090,87 @@ No s'afegirà al projecte.
MapWrapper
-
+
GPS no disponible
-
+
Correctament sincronitzat
-
+
Actualitzat
-
+
Algú més s'està sincronitzant, ho tornarem a provar més tard
-
+
Hi ha hagut un problema durant la sincronització, ho tornarem a provar. Feu clic per obtenir més informació
-
+
Divisió realitzada amb èxit
-
+
Crea una línia per dividir la geometria seleccionada
-
+
Seleccioneu algun punt per començar a editar la geometria
-
+
Enregistreu una geometria nova per a la característica
-
+
Detalls
-
+
Tornar
-
+
Descartar els canvis?
-
+
Si feu clic a "Sí", es descartarà els canvis a la geometria. Si voleu desar els canvis premeu "No", i després "Fet" a la barra d'eines.
-
+
Si feu clic a "Sí", es descarta la vostra nova geometria i no es desarà cap característica. Si voleu desar la geometria premeu "No", i després "Fet" a la barra d'eines.
-
+
Connectant amb %1
-
+
Connectat, sense posició
-
+
Precisió desconeguda
@@ -1255,12 +1223,12 @@ No s'afegirà al projecte.
Projecte desvinculat de Mergin
-
+
El nom de l'espai de treball conté caràcters no vàlids
-
+
L'espai de treball %1 ja existeix
@@ -1394,26 +1362,67 @@ Feu clic a "Sí" per carregar-lo.
PositionProvidersModel
-
+
Intern
-
+
Receptor GPS d'aquest dispositiu
-
+
Dispositiu Bluetooth
-
+
Dispositiu Bluetooth
+
+ PositionTrackingDrawer
+
+
+
+ Seguiment de la posició
+
+
+
+
+ Mergin Maps pot fer un seguiment de la vostra posició en aquest projecte.
+
+
+
+
+ Atura el seguiment
+
+
+
+
+ Començar el seguiment
+
+
+
+ PositionTrackingManager
+
+
+
+ No s'ha pogut trobar la capa de seguiment del projecte
+
+
+
+
+ La capa de seguiment no s'ha trobat o no és vàlida
+
+
+
+
+ No s'ha pogut iniciar el seguiment, contacteu amb l'assistència
+
+
PreviewPanel
@@ -1540,56 +1549,56 @@ Feu clic a "Sí" per carregar-lo.
ProjectPanel
-
+
Sense canvis
-
-
-
+
+
+
Projectes
-
-
+
+
Inici
-
+
Els meus projectes
-
+
Compartit amb mi
-
+
Compartit
-
-
+
+
Explora
-
+
Projectes descarregats
-
+
Projectes públics
-
+
Els altres projectes són accessibles%1 canviant el vostre espai de treball aquí
@@ -1777,47 +1786,47 @@ Feu clic a "Sí" per carregar-lo.
No és un valor vàlid
-
+
Sense dades
-
+
Sense posició
-
+
Posició GPS, sense dades de correcció
-
+
Posició DGPS
-
+
Posició PPS
-
+
Posició RTK
-
+
RTK flotant
-
+
Posició estimada (dead reckoning)
-
+
Posició desconeguda
@@ -2063,7 +2072,7 @@ Feu clic a "Sí" per carregar-lo.
SimulatedPositionProvider
-
+
Connectat
@@ -2515,58 +2524,64 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment.
main
-
-
+
+
Cap canvi
-
+
Mode autocentrat del GPS activat
-
+
Mode autocentrat del GPS desactivat
-
+
No s'ha trobat cap nivell editable.
-
+
+
+
+ no seguiment
+
+
+
El replanteig està desactivat perquè la ubicació no està disponible!
-
+
No s'ha pogut obrir el projecte
-
+
Error de comunicació amb Mergin.%1Proveu a millorar la vostra connexió de xarxa
-
+
Problemes en carregar el projecte.
-
+
No s'ha pogut llegir el fitxer del projecte:
-
+
Premeu enrere un altre cop per sortir de l'aplicació
-
+
Error de PROJ
diff --git a/app/i18n/input_cs.qm b/app/i18n/input_cs.qm
new file mode 100644
index 000000000..6d7d0d640
Binary files /dev/null and b/app/i18n/input_cs.qm differ
diff --git a/app/i18n/input_en.ts b/app/i18n/input_en.ts
index 1e0d893ef..f9304da99 100644
--- a/app/i18n/input_en.ts
+++ b/app/i18n/input_en.ts
@@ -150,27 +150,22 @@ Please go to the Mergin Maps website to remove it manually.
AndroidUtils
-
-
-
-
-
-
+
-
+
-
+
-
+
@@ -200,7 +195,7 @@ Please go to the Mergin Maps website to remove it manually.
-
+
Value "%1" %4 could not be converted to a compatible value for field %2(%3).
@@ -211,18 +206,18 @@ Please go to the Mergin Maps website to remove it manually.
-
+
Feature could not be added
-
+
Cannot update feature
-
+
Cannot start editing
@@ -300,35 +295,35 @@ Please go to the Mergin Maps website to remove it manually.
BluetoothPositionProvider
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
@@ -790,50 +785,50 @@ Won't be added to the project.
-
+
screen resolution: %1x%2 px
-
+
screen DPI: %1x%2
-
+
screen size: %1x%2 mm
-
+
-
+
-
+
-
+
-
+
@@ -859,8 +854,8 @@ Won't be added to the project.
InternalPositionProvider
-
-
+
+
@@ -909,39 +904,6 @@ Won't be added to the project.
-
- LegacyFolderMigration
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
LocalProjectsManager
@@ -1009,60 +971,66 @@ Won't be added to the project.
MainPanel
-
-
+
+
Projects
-
-
+
+
GPS
-
-
+
+
Record
-
-
+
+
Zoom to project
-
-
+
+
-
-
+
+
-
-
+
+
Map themes
-
-
+
+
+
+
+
+
+
+
Settings
-
+
More
-
+
Menu
@@ -1116,87 +1084,87 @@ Won't be added to the project.
MapWrapper
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -1249,12 +1217,12 @@ Won't be added to the project.
-
+
-
+
@@ -1387,26 +1355,67 @@ Click 'Yes' to upload it.
PositionProvidersModel
-
+
-
+
-
+
-
+
+
+ PositionTrackingDrawer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PositionTrackingManager
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PreviewPanel
@@ -1532,56 +1541,56 @@ Click 'Yes' to upload it.
ProjectPanel
-
+
No Changes
-
-
-
+
+
+
Projects
-
-
+
+
Home
-
+
My projects
-
+
Shared with me
-
+
Shared
-
-
+
+
Explore
-
+
-
+
-
+
@@ -1769,47 +1778,47 @@ Click 'Yes' to upload it.
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2055,7 +2064,7 @@ Click 'Yes' to upload it.
SimulatedPositionProvider
-
+
@@ -2503,58 +2512,64 @@ Please go to the Mergin Maps website to remove it manually.
main
-
-
+
+
No Changes
-
+
-
+
-
+
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/app/i18n/input_es.qm b/app/i18n/input_es.qm
index 9164c594f..9c214a7b3 100644
Binary files a/app/i18n/input_es.qm and b/app/i18n/input_es.qm differ
diff --git a/app/i18n/input_es_419.qm b/app/i18n/input_es_419.qm
index f1cd34e2d..f1b56e0d1 100644
Binary files a/app/i18n/input_es_419.qm and b/app/i18n/input_es_419.qm differ
diff --git a/app/i18n/input_es_ES.qm b/app/i18n/input_es_ES.qm
index 2ea133706..562c6edb2 100644
Binary files a/app/i18n/input_es_ES.qm and b/app/i18n/input_es_ES.qm differ
diff --git a/app/i18n/input_fi.qm b/app/i18n/input_fi.qm
index d622aa3a2..bf39c582f 100644
Binary files a/app/i18n/input_fi.qm and b/app/i18n/input_fi.qm differ
diff --git a/app/i18n/input_fi_FI.qm b/app/i18n/input_fi_FI.qm
index 243e91a1a..cc45b047b 100644
Binary files a/app/i18n/input_fi_FI.qm and b/app/i18n/input_fi_FI.qm differ
diff --git a/app/i18n/input_i18n.qrc b/app/i18n/input_i18n.qrc
index 2545b8480..45ec11bf6 100644
--- a/app/i18n/input_i18n.qrc
+++ b/app/i18n/input_i18n.qrc
@@ -35,6 +35,7 @@
input_zh.qm
input_fr.qm
input_nl.qm
+ input_cs.qm
input_az_AZ.qm
input_hu.qm
diff --git a/app/i18n/input_it.qm b/app/i18n/input_it.qm
index 0dace2b02..ffe412967 100644
Binary files a/app/i18n/input_it.qm and b/app/i18n/input_it.qm differ
diff --git a/app/i18n/input_ja_JP.qm b/app/i18n/input_ja_JP.qm
index 02bfcad10..835aacfdd 100644
Binary files a/app/i18n/input_ja_JP.qm and b/app/i18n/input_ja_JP.qm differ
diff --git a/app/i18n/input_ja_JP.ts b/app/i18n/input_ja_JP.ts
index 8bb7289da..59f0923f0 100644
--- a/app/i18n/input_ja_JP.ts
+++ b/app/i18n/input_ja_JP.ts
@@ -10,98 +10,164 @@
AccountPage
-
+
サブスクリプションは %1 でキャンセルされました
-
+
マイアカウント
-
+
サブスクリプションは %1 を過ぎても自動更新されません
-
+
できるだけ早く %1支払いの詳細%2 についてアップデートしてください。
-
+
次の %1 の請求は %2 に行われます。
-
+
%1 / %2 利用中
-
+
サブスクリプションの管理
-
+
作業中...
-
+
サブスクリプションプラン
-
+
購入したサブスクリプションを %1復元%2 することができます。
-
+
サインアウト
+
+
+
+ アカウントを削除
+
+
+
+
+ アカウントを削除しますか?
+
+
+
+
+ この操作によって、あなたのMergin Mapsアカウントと、デバイス上とサーバー上のすべてのプロジェクトが削除されます。この操作は元に戻せません。Appleのサブスクリプションをお持ちの場合は、手動でキャンセルする必要があります。
+
+アカウントを削除するには、下のフィールドにユーザー名を入力し、はいをクリックします。
+
+
+
+
+ ユーザ名を入力
+
+
+
+
+ アカウントの削除に失敗しました
+
+
+
+
+ アカウント削除中にエラーが起きました
+
+
+
+
+ ユーザーが組織の唯一の所有者であるため、アカウントを閉じることができません。
+
+Mergin Mapsのウェブサイトから手動で削除してください。
+
ActiveLayerPanel
-
+
アクティブレイヤを選択
-
+
プロジェクトに編集可能なレイヤがありません。%1プロジェクトでデジタイズを有効にする方法%2 をご覧ください。
- AndroidUtils
+ AddPositionProviderPage
+
+
+
+ Bluetooth機器に接続
+
+
+
+
+ 新しいGPSレシーバーを接続するには、Bluetoothを有効にする必要があります。
+
+
+
+
+ 不明なデバイス
+
+
+
+
+ 他のデバイスを探しています
+
-
-
- ストレージの許可がないと、過去のプロジェクトにアクセスできません
+
+
+ デバイスを探しています
+
+
+ AndroidUtils
-
+
ストレージへのアクセス権限がありません。ギャラリーから写真を読み込むためにアクセスを許可してください
-
+
Inputはギャラリーから写真を読み込むためにストレージへのアクセス権限が必要です
-
+
カメラへのアクセス権限がありません。アクセス許可を設定してください。
-
+
写真を撮影するためにカメラへのアクセス権限が必要です。
@@ -117,51 +183,46 @@
AttributeController
-
+
+
%1:%2 のデフォルト値の式の変換でエラーが起きました: %3
-
+
+
%1:%2 のデフォルト値の式の評価でエラーが起きました: %3
-
+
+
+
値 "%1" %4 はフィールド%2(%3)のための互換値に変換できませんでした。
-
+
地物を削除できません
-
-
+
+
地物を追加できませんでした
-
+
+
地物を更新できません
-
-
- コミット後に地物 %1 を取得できませんでした
-
-
-
+
編集を開始できません
-
-
-
- 変更を保存できませんでした。ロールバックします。
-
AuthPanel
@@ -176,12 +237,12 @@
登録
-
+
最新のMerginの機能を使用するためにInputをアップデートしてください。
-
+
現在Merginは利用できません - 後で再度試して下さい.
@@ -189,172 +250,183 @@
Banner
-
-
- %1<br><a href='%2' style="color: %3;">さらに詳しく</a>
+
+
+ 詳細はこちら
- BrowseDataLayersPanel
-
-
-
- レイヤ
-
+ BluetoothConnectionDialog
-
-
- 地物が閲覧できるように設定されたレイヤがありません. %1 でプロジェクトの設定方法を参照して下さい %2.
+
+
+ 接続中:
-
-
- CodeReader
-
-
- コードをスキャン
+
+
+ 接続されました
-
-
- DateTimePicker
-
-
- キャンセル
+
+
+ 接続に失敗しました:
-
-
- OK
+
+
+ この過程でデバイスのペアリングを求められることがあります。
-
-
- 1月
+
+
+ このメッセージを閉じることができます。繰り返しデバイスへの接続を試みます。%1 さらにヘルプが必要な場合は、%2ここをクリックしてください%3
-
-
- 2月
+
+
+ 指定されたデバイスに接続できませんでした。
+ デバイスの電源が入っていて、接続できることを確認してください。%1 %2詳細はこちら%3。
-
-
- 3月
+
+
+ 閉じる
+
+
+ BluetoothPositionProvider
-
-
- 4月
+
+
+
+ 接続がありません
-
-
- 5月
+
+
+ 再接続しています
-
-
- 6月
+
+
+
+ 接続がありません。(%1) で再接続しています。
-
-
- 7月
+
+
+ デバイスに接続できず、ペアリングされていません
-
-
- 8月
+
+
+ %1に接続中
-
-
- 9月
+
+
+
+ 接続されました
+
+
+ CodeScanner
-
-
- 10月
+
+
+ コードをスキャン
+
+
+ CreateWorkspacePage
-
-
- 11月
+
+
+ ワークスペースを作成
-
-
- 12月
+
+
+ ワークスペースは、プロジェクトを保存する場所です。同僚をワークスペースに招待して、プロジェクトで共同作業を行うことができます。ワークスペース名の候補としては、あなたのチーム名や組織名が良いでしょう。
-
-
- 日曜日
+
+
+ ワークスペース名...
-
-
- 月曜日
+
+
+ ワークスペースを作成
-
-
- 火曜日
+
+
+ ワークスペース名が未入力です
+
+
+ DateTimePicker
-
-
- 水曜日
+
+
+ キャンセル
-
-
- 木曜日
+
+
+ OK
+
+
+ ExternalResourceBundle
-
-
- 金曜日
+
+
+ ディレクトリ %1 を作成できませんでした。
-
-
- 土曜日
+
+
+ 画像ファイルを %1 にコピーできませんでした。
-
-
- ExternalResourceBundle
-
+
イメージを開く
-
+
イメージファイル (*.gif *.png *.jpg)
-
+
写真への参照を削除する
-
+
デバイスから写真を完全に削除しますか?
+
+
+
+ 画像ファイルをコピーできませんでした。
+
FeatureForm
-
+
フォームを保存できません。入力エラーがあります。
-
+
地物を保存できません。入力必須項目全てを確認してください。
@@ -362,65 +434,84 @@
FeatureFormPage
-
+
地物の編集
-
+
地物
-
+
保存
-
+
地物の削除
-
+
本当にこの地物を削除しますか?
-
+
保存されていない変更
-
+
変更内容を保存しますか?
+
+
+
+ 保存に失敗しました
+
+
+
+
+ 変更の保存に失敗しました。通常、このようなことは起こらないはずです。アプリを再起動して再度お試しください。それでも解決しない場合は、サポートまでご連絡ください。
+
FeatureToolbar
-
+
編集
-
+
削除
-
+
+
- 地物の編集
+ ジオメトリの編集
+
+
+
+
+
+ 詳細
+
+
+
+
+ ジオメトリの分割
-
-
- FeaturesListPage
-
-
- 最初の %1 個の地物を表示しています
+
+
+ ジオメトリの再描画
@@ -441,20 +532,28 @@
リンクを削除
+
+ FeaturesListPageV2
+
+
+
+ 地物の追加
+
+
FieldsModel
-
+
新しいフィールドを追加する前に、一つ前のフィールド名を入力してください。
-
+
フィールド %1 は既に存在しています。
-
+
フィールド %1 は既に存在しています。
@@ -464,94 +563,140 @@ Won't be added to the project.
GpsDataPage
-
+
GPS情報
-
-
-
-
-
-
-
-
-
-
- GPSからデータを読み込んでいます
-
-
-
+
高度
-
+
経度
-
+
+
+ ソース
+
+
+
+
+ 受信機がありません
+
+
+
+
+ 状態
+
+
+
緯度
-
+
X
-
+
Y
-
+
水平精度
-
-
+
+
+ VDOP
+
+
+
+
+ PDOP
+
+
+
+
+ GPSアンテナの高さ
+
+
+
+
+ 未設定
+
+
+
+
+ GPS受信機の管理
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
N/A
-
+
垂直精度
-
+
+
+ 品質を修正
+
+
+
衛星 (利用数/表示数)
-
+
+
+ HDOP
+
+
+
速度
-
+
最後の修正
-
-
-
- 日付が不明です
-
InputHelp
-
+
リポートは送信されました。%1次のアドレスに連絡してください:%1%2
-
+
リポートの送信に失敗しました。%1インターネット接続を確認してください。
@@ -577,144 +722,210 @@ Won't be added to the project.
InputUtils
-
+
たった今
-
+
%1 分前
-
+
%1 分前
-
+
%1 時間前
-
+
%1 時間前
-
-
+
+
%1 日前
-
-
+
+
%1 日前
-
+
%1 週間前
-
+
%1 週間前
-
+
%1 ヶ月前
-
+
%1 ヶ月前
-
+
%1 年前
-
+
%1 年前
-
+
スクリーン解像度: %1x%2 px
-
+
スクリーンDPI: %1x%2
-
+
スクリーンサイズ: %1x%2 mm
-
+
取得したデバイスの画素数比率: %1
-
+
計算したデバイスの画素数比率: %1
-
+
使用したdpスケール: %1
+
+
+
+ すべてのパートに少なくとも%1ポイントを加える必要があります。
+
+
+
+
+ 少なくとも%1ポイントを加える必要があります。
+
+
+
+ InstallScannerAppDialog
+
+
+
+ スキャナアプリのインストール
+
+
+
+
+ バーコードスキャナーアプリをインストールするためにGoogle Playにリダイレクトされます。
+
+
+
+
+ バーコードスキャナーアプリがインストールされたら、アプリを終了し、Mergin Mapsに戻ります。
+
+
+
+ InternalPositionProvider
+
+
+
+
+ 接続されました
+
- LegacyFolderMigration
+ LayerDetail
+
+
+
+ 設定
+
+
+
+
+ 地図上に表示
+
+
+
+
+ 凡例
+
+
+
+
+ 地物
+
-
-
- デバイスに十分な空き容量がありません
+
+
+ レイヤ情報
+
+
+ LayersListPageV2
-
-
- デバイスの空き容量が不足しています。プロジェクトを表示するには %1 の空き容量が必要です。何らかのファイルを削除してから戻ってくるか、「ヘルプ」をクリックして、この問題を解決する他の方法を確認してください。
+
+
+ レイヤ
+
+
+ LayersListSearchPage
-
-
- アップデート中にエラーが発生しました
+
+
+ レイヤの検索
+
+
+ LocalProjectsManager
-
-
- アップデートの適用中にデバイスに問題が発生しました。プロジェクトを見ることができなくなります。「ヘルプ」をクリックすると、この問題を解決する方法が表示されます。
+
+
+ ダウンロード失敗,削除して再度試して下さい
-
-
- 重要なアップデートを行っていますので、アプリを閉じないでください
+
+
+ 複数のQGISプロジェクトファイルが見つかりました
-
-
- %1/%2
+
+
+ QGISプロジェクトファイルが見つかりません
@@ -738,27 +949,27 @@ Won't be added to the project.
LoginForm
-
-
- %1Mergin%2 はスマホとPC間のクラウドベースの同期機能を提供します。これを使うことでプロジェクトを他の人と共有し、共同で作業をすることができます。
+
+
+ %1Mergin Maps%2アカウントにログインすることで、デスクトップコンピュータとプロジェクトを同期し、他のユーザーと共同作業を行うことができます。
-
+
ユーザ名
-
+
サインイン
-
+
無料でサインアップ
-
+
パスワードをお忘れですか?
@@ -766,60 +977,101 @@ Won't be added to the project.
MainPanel
-
-
+
+
プロジェクト
-
-
+
+
GPS
-
-
+
+
記録
-
-
+
+
プロジェクトにズーム
-
-
- データの閲覧
+
+
+
+ ローカルの変更
+
+
+
+
+
+ レイヤ
-
-
+
+
地図テーマ
-
-
+
+
+
+ 位置の追跡
+
+
+
+
設定
-
+
さらに
-
+
メニュー
+
+
+ ManageInvitationsPage
+
+
+
+ ワークスペースに参加
+
+
+
+
+ 次のワークスペースに招待されています:
+
+
+
+
+ ワークスペース
+
+
+
+
+ 受け入れる
+
+
+
+
+ 代わりに新しいワークスペースを作成しますか?
+
-
-
- 地物の閲覧
+
+
+ ここをクリック!
@@ -830,7 +1082,7 @@ Won't be added to the project.
地図テーマ
-
+
プロジェクトに定義されたテーマがありません。%1テーマのセットアップの仕方%2をご覧ください。
@@ -838,154 +1090,452 @@ Won't be added to the project.
MapWrapper
-
-
-
- GPSは現在使用できません。%1デバイスの設定でGPSロケーションを許可してください。
+
+
+ GPSは現在使用できません。
-
-
- 記録された地物は有効ではありません
+
+
+ 同期に成功しました
-
-
- GPSの位置精度が低いです (%1 m)<br><br>空の見晴らしの良いところで使用してください。
+
+
+ 更新する
-
-
- PanelHeader
-
-
- キャンセル
+
+
+ 他の人が同期中なので、後で再試行します
-
-
- PasswordField
-
-
- パスワード
+
+
+ 同期中に問題が発生しました。後に再試行します。クリックして詳細を見る
-
-
- PositionKit
-
-
- GPS位置情報をデフォルトで作成できません
+
+
+ 分割に成功しました
-
-
- PreviewPanel
-
-
- マップチップはありません
+
+
+ 選択した地物を分割するラインを作成
-
-
- ProjectDelegateItem
-
-
- プロジェクトを同期
+
+
+ ジオメトリの編集を開始するポイントを選択します。
-
-
- ローカルの変更
+
+
+ 地物の新しいジオメトリを記録する
-
-
- デバイスから削除
+
+
+ 詳細
-
-
- Merginにアップロード
+
+
+ 戻る
-
-
- Merginからダウンロード
+
+
+ 変更を破棄しますか?
-
-
- プロジェクトを同期できませんでした。十分な権限を持ってログインしているか確認してください。
+
+
+ 「はい」をクリックすると、ジオメトリへの変更が破棄されます。代わりに変更を保存したい場合は、ツールバーの「いいえ」をクリックし、次に「完了」をクリックします。
-
-
- ProjectIssuesPanel
-
-
- プロジェクトの課題
+
+
+ 「はい」をクリックすると新しいジオメトリは破棄され、フィーチャーは保存されません。ジオメトリを保存したい場合は、ツールバーの「いいえ」、「完了」の順にクリックします。
-
-
- QGISログ
+
+
+ %1に接続中
+
+
+
+
+ 接続完了、位置情報はありません
+
+
+
+
+ 不明な精度
- ProjectList
+ MerginApi
-
-
-
- プロジェクトを作成
+
+
+ ユーザー名は4文字以上でなければなりません。
-
-
- ダウンロードされたプロジェクトはありません。%2プロジェクトの作り方%3 とデバイスへの %4ダウンロードの方法%3 を%1学びましょう。
+
+
+ ユーザー名に無効な文字が含まれています
-
-
- 下のボタンをクリックして、新しいプロジェクトを作成することもできます。
+
+
+ 正しいメールを入力して下さい
-
-
- プロジェクトのリストを取得できません
+
+
+ パスワードの強度が十分ではありません。少なくとも以下の要素を満たす必要があります。%1 8文字以上の長さ%1 小文字を含む%1 大文字を含む%1 数字または特殊文字を含む
-
-
- プロジェクトが見つかりません!
+
+
+ パスワードが一致しません。
-
-
- リトライ
+
+
+ 利用規約と個人情報保護についてに同意してください。
-
-
- プロジェクトを削除
+
+
+ 登録が成功しました
-
-
- 同期されていない変更は失われます。
+
+
+ 選択したMerginサーバーでは新規登録ができません。%1 管理者にご確認ください。
-
-
- プロジェクトをダウンロード
+
+
+ Merginから切り離されたプロジェクト
-
-
- プロジェクトをダウンロードしますか
- %1 ?
+
+
+ ワークスペース名に無効な文字が含まれています
+
+
+
+
+ ワークスペース %1 は既に存在しています。
+
+
+
+ MerginProjectStatusModel
+
+
+
+ 保留している変更
+
+
+
+
+ 変更点の判別に失敗しました
+
+
+
+ MigrateToMerginDialog
+
+
+
+ プロジェクトをMerginにアップロードしますか?
+
+
+
+
+ このプロジェクトは現在Merginにアップロードされていません。同期とコラボレーションを有効にするためにMerginにアップロードしてください。
+「はい」をクリックしてアップロードしてください。
+
+
+
+ MissingAuthDialog
+
+
+
+ Merginにサインイン
+
+
+
+
+ プロジェクトを同期するには、Merginアカウントにサインインする必要があります。「はい」を押してサインインしてください。
+
+
+
+ NoPermissionsDialog
+
+
+
+ プロジェクトにアクセスする権利がありません
+
+
+
+
+ 変更を同期することは許可されていません。Merginプロジェクトオーナーに連絡して、正しい権限を割り当ててもらってください。あなたがプロジェクトオーナーの場合、Merginダッシュボードにログインしてください。
+
+
+
+ NoWorkspaceBanner
+
+
+
+ Merginマップを使用するには%1ワークスペースが必要です。作成するにはここをクリックしてください%2。
+
+
+
+ PanelHeader
+
+
+
+ キャンセル
+
+
+
+ PasswordField
+
+
+
+ パスワード
+
+
+
+ PositionProviderPage
+
+
+
+ GPS受信機
+
+
+
+
+ 内蔵受信機
+
+
+
+
+ 外付け受信機
+
+
+
+
+ 不明なデバイス
+
+
+
+
+ 新しい受信機を接続
+
+
+
+
+ iOSでは、Inputで直接Bluetooth経由でレシーバーに接続することはできません。ハードウェアベンダーが、レシーバーに接続して位置を設定するカスタムアプリを提供している場合があります。Inputはまだあなたの携帯電話/タブレットの内蔵GPSだと考えています。%1%2詳細はこちらをクリックしてください。%3
+
+
+
+
+ 受信機を取り外す
+
+
+
+
+ 最近の受信機リストから受信機を削除しますか?
+
+
+
+
+ 内蔵
+
+
+
+ PositionProvidersModel
+
+
+
+ 内蔵
+
+
+
+
+ このデバイスのGPS受信機
+
+
+
+
+ ブルートゥース機器
+
+
+
+
+ ブルートゥース機器
+
+
+
+ PositionTrackingDrawer
+
+
+
+ 位置の追跡
+
+
+
+
+ Mergin Mapsはこのプロジェクトで現在位置を追跡することができます。
+
+
+
+
+ 追跡の停止
+
+
+
+
+ 追跡を開始
+
+
+
+ PositionTrackingManager
+
+
+
+ プロジェクトの追跡レイヤーが見つかりません
+
+
+
+
+ 追跡レイヤーが見つからないか、無効です
+
+
+
+
+ 追跡の開始に失敗しました。サポートに連絡してください
+
+
+
+ PreviewPanel
+
+
+
+ マップチップはありません
+
+
+
+ ProjectDelegateItem
+
+
+
+ プロジェクトを同期
+
+
+
+
+ ローカルの変更
+
+
+
+
+ デバイスから削除
+
+
+
+
+ Merginにアップロード
+
+
+
+
+ Merginからダウンロード
+
+
+
+
+ プロジェクトを同期できませんでした。十分な権限を持ってログインしているか確認してください。
+
+
+
+ ProjectIssuesPanel
+
+
+
+ 以下のレイヤーは読み込みに失敗した
+
+
+
+
+ プロジェクトの課題
+
+
+
+
+ QGISログ
+
+
+
+ ProjectList
+
+
+
+
+ プロジェクトを作成
+
+
+
+
+ ダウンロードされたプロジェクトはありません。%2プロジェクトの作り方%3 とデバイスへの %4ダウンロードの方法%3 を%1学びましょう。
+
+
+
+
+ 下のボタンをクリックして、新しいプロジェクトを作成することもできます。
+
+
+
+
+ プロジェクトのリストを取得できません
+
+
+
+
+ プロジェクトが見つかりません!
+
+
+
+
+ リトライ
+
+
+
+
+ プロジェクトを削除
+
+
+
+
+ 同期されていない変更は失われます。
+
+
+
+
+ プロジェクトをダウンロード
+
+
+
+
+ プロジェクトをダウンロードしますか
+ %1 ?
@@ -999,40 +1549,59 @@ Won't be added to the project.
ProjectPanel
-
+
変更はありません
-
+
+
+
プロジェクト
-
+
+
ホーム
-
+
プロジェクト
-
+
共有プロジェクト
-
+
共有
-
+
+
探す
+
+
+
+ ダウンロードされたプロジェクト
+
+
+
+
+ 公開プロジェクト
+
+
+
+
+ ワークスペースをここに切り替えると、%1他のプロジェクトにアクセスできます。
+
ProjectStatusPanel
@@ -1050,7 +1619,12 @@ Won't be added to the project.
ProjectWizard
-
+
+
+ プロジェクト名に無効な文字が含まれています
+
+
+
プロジェクト %1 が作成されました
@@ -1058,32 +1632,32 @@ Won't be added to the project.
ProjectWizardPage
-
+
プロジェクトを作成
-
+
プロジェクト名
-
+
フィールド
-
+
追加する
-
+
プロジェクトを作成
-
+
プロジェクト名が未入力です
@@ -1091,8 +1665,8 @@ Won't be added to the project.
ProjectsModel
-
-
+
+
%1 を更新しました
@@ -1100,27 +1674,27 @@ Won't be added to the project.
Purchasing
-
+
支払い処理できませんでした。%1サブスクリプションは購入されませんでした。
-
+
サブスクリプションを復元しました
-
+
サブスクリプションを購入しました
-
+
サブスクリプションの購入に失敗しました
-
+
サブスクリプションを復元できませんでした
@@ -1128,22 +1702,22 @@ Won't be added to the project.
PurchasingPlan
-
+
月間サブスクリプション
-
+
年間サブスクリプション
-
+
月
-
+
年
@@ -1151,110 +1725,157 @@ Won't be added to the project.
QObject
-
+
値は数値である必要があります
-
+
値は %1 よりも小さい必要があります
-
+
値は %1 よりも大きい必要があります
-
+
値が大きすぎます
-
+
フィールドには小数点以下を含めることはできません
-
+
%1 文字以下である必要があります
-
+
フィールドが未入力です
-
+
フィールドは必須項目です
-
+
値はユニークである必要があります
-
+
値はユニークでなければなりません
-
-
+
+
QGIS式の制約を満たしていません
-
+
有効な値ではありません
-
-
- QgsQuickMapCanvasMap
-
-
- 描画しています
+
+
+ データがありません
+
+
+
+
+ 修正はありません
+
+
+
+
+ GPSが修正されました、補正データはありません
+
+
+
+
+ DGPSが修正されました
+
+
+
+
+ PPSが修正されました
+
+
+
+
+ RTKが修正されました
+
+
+
+
+ RTKがフローティングしています
-
-
- QgsQuickMapSettings
-
-
-
- 地図キャンバスの回転はサポートされていません. %1 を 0にリセットします.
+
+
+ 推定フィックス(推測航法)
+
+
+
+
+ 不明な修正
- RecordToolbar
+ RecordingToolbar
-
+
GPS
-
+
- 実行取り消し
+ 取り消し
-
-
- 点の追加
+
+
+ 削除
-
+
+
+ 追加
+
+
+
+
+ リリース
+
+
+
完了
+
+
+ RecordingTools
-
-
- キャンセル
+
+
+ GPSの位置精度が低いです (%1 m)<br><br>空の見晴らしの良いところで使用してください。
+
+
+
+
+
+ GPSは現在使用できません。
@@ -1301,79 +1922,218 @@ Won't be added to the project.
検索
+
+ SearchBoxV2
+
+
+
+ 検索
+
+
+
+ SettingsComboBoxItem
+
+
+
+ 経過時間
+
+
+
+
+ 移動距離
+
+
+
+ SettingsHeaderItem
+
+
+
+ 新機能!
+
+
SettingsPanel
-
+
設定
-
+
GPS
-
+
GPSに追従する
-
+
GPS精度
-
+
精度の閾値
-
+
精度の警告を表示
-
+
+
+ GPS受信機を選択
+
+
+
+
+ GPSアンテナの高さ
+
+
+
+
+ ポールの高さとGPS受信機のアンテナの高さを含む
+
+
+
+
+ ストリーミング・モード
+
+
+
+
+ インターバル・タイプ
+
+
+
+
+ 新しいポイントを追加する際のアクションを選択する
+
+
+
+
+ メートル単位
+
+
+
+
+ 秒単位
+
+
+
記録
-
+
ラインを記録する間隔
-
+
最後の値を再利用する
-
+
+
+ 変更を自動的に同期
+
+
+
このアプリについて
-
+
ヘルプ
-
+
個人情報保護について
-
-
- Mergin利用規約
+
+
+ 利用規約
-
+
診断ログ
+
+ SimulatedPositionProvider
+
+
+
+ 接続されました
+
+
+
+ SplittingFailedDialog
+
+
+
+ 地物を分割することができませんでした
+
+
+
+
+ 分割線が地物を横切っていることを確認してください。地物を分割するには、その地物に有効なジオメトリが必要です。
+
+
+
+ SplittingToolbar
+
+
+
+ 取り消し
+
+
+
+
+ 点の追加
+
+
+
+
+ 完了
+
+
+
+ SplittingTools
+
+
+
+ 少なくとも2点を加える必要があります。
+
+
+
+ StakeoutPanel
+
+
+
+ ステイクアウト
+
+
+
+
+ 地物
+
+
+
+
+ 距離
+
+
StorageLimitDialog
@@ -1415,19 +2175,19 @@ Won't be added to the project.
サブスクライブ
-
-
+
+
個人
-
-
+
+
プロフェッショナル
-
+
Merginのサブスクリプションのプランは自動で更新されます。いつでもキャンセルできます。 %1詳細を見る%2
@@ -1455,20 +2215,274 @@ Won't be added to the project.
電子メールサポート
+
+ SwitchWorkspacePage
+
+
+
+ ワークスペースを選択
+
+
+
+
+ 保留中の招待があります
+
+
+
+
+ ワークスペース
+
+
+
+
+ 受け入れる
+
+
+
+
+ 拒否
+
+
+
+
+ ワークスペース
+
+
+
+
+ 新規のワークスペースを作成
+
+
+
+ SyncFailedDialog
+
+
+
+ 変更の同期に失敗しました
+
+
+
+
+ 変更がサーバーに送信されませんでした。インターネットに接続され、このプロジェクトへの書き込み権限があることを確認してください。
+
+
+
+ WhatsNewDialog
+
+
+
+ 新着情報
+
+
+
+
+ 無視する
+
+
+
+
+ 続きを読む
+
+
+
+ WorkspaceAccountPage
+
+
+
+ マイアカウント
+
+
+
+
+ ワークスペース
+
+
+
+
+ ワークスペースを切り替え
+
+
+
+
+ ロール
+
+
+
+
+ ワークスペースのストレージ
+
+
+
+
+ %1 / %2 利用中
+
+
+
+
+ サブスクリプションプラン
+
+
+
+
+
+
+
+ サブスクリプション・ステータス
+
+
+
+
+ サブスクリプションは %1 を過ぎても自動更新されません
+
+
+
+
+ できるだけ早く %1支払いの詳細%2 についてアップデートしてください。
+
+
+
+
+ 次の %1 の請求は %2 に行われます。
+
+
+
+
+ サブスクリプションは %1 でキャンセルされました
+
+
+
+
+ サブスクリプション
+
+
+
+
+ アカウント
+
+
+
+
+ ユーザ名
+
+
+
+
+ 電子メール
+
+
+
+
+ サインアウト
+
+
+
+
+ アカウントを削除
+
+
+
+
+ アカウントを削除しますか?
+
+
+
+
+ この操作によって、あなたのMergin Mapsアカウントと、デバイス上とサーバー上のすべてのプロジェクトが削除されます。この操作は元に戻せません。Appleのサブスクリプションをお持ちの場合は、手動でキャンセルする必要があります。
+
+アカウントを削除するには、下のフィールドにユーザー名を入力し、はいをクリックします。
+
+
+
+
+ ユーザ名を入力
+
+
+
+
+ アカウントの削除に失敗しました
+
+
+
+
+ アカウント削除中にエラーが起きました
+
+
+
+
+ ユーザーが組織の唯一の所有者であるため、アカウントを閉じることができません。
+
+Mergin Mapsのウェブサイトから手動で削除してください。
+
+
+
+ WorkspaceSubscribePage
+
+
+
+ サブスクライブ
+
+
+
+
+ 個人
+
+
+
+
+ プロフェッショナル
+
+
+
+
+ 購入したサブスクリプションを %1復元%2 することができます。
+
+
+
+
+ Merginのサブスクリプションのプランは自動で更新されます。いつでもキャンセルできます。 %1詳細を見る%2
+
+
+
+ WorkspaceSubscribePlanItem
+
+
+
+ 商業利用
+
+
+
+
+ ユーザー数無制限
+
+
+
+
+ プロジェクト数無制限
+
+
+
+
+ 電子メールサポート
+
+
inputexternalresource
-
+
写真撮影
-
+
ギャラリーから
-
+
画像はありません
@@ -1476,17 +2490,17 @@ Won't be added to the project.
inputrelation
-
+
さらに %1
-
+
追加
-
+
リンクされた地物
@@ -1510,32 +2524,64 @@ Won't be added to the project.
main
-
+
+
+
+ 変更はありません
+
+
+
GPS自動センターモードをON
-
+
GPS自動センターモードをOFF
-
+
編集可能なレイヤがみつかりません.
-
+
+
+
+ 追跡していません
+
+
+
+
+ 位置情報が利用できないため、ステイクアウトは利用できません!
+
+
+
+
+ プロジェクトを開けませんでした
+
+
+
Merginとの通信に失敗しました。%1 インターネット状況の確認をしてください。
-
-
- 通信エラー
+
+
+ プロジェクトを読み込む上で問題が発生しました。
+
+
+
+
+ プロジェクトファイルを読み込めませんでした:
+
+
+
+
+ アプリを終了するには、もう一度戻るを押してください
-
+
PROJエラー
diff --git a/app/i18n/input_nl.qm b/app/i18n/input_nl.qm
index a5621f9f3..6e869aa81 100644
Binary files a/app/i18n/input_nl.qm and b/app/i18n/input_nl.qm differ
diff --git a/app/inpututils.cpp b/app/inpututils.cpp
index aed6b927a..59d84a402 100644
--- a/app/inpututils.cpp
+++ b/app/inpututils.cpp
@@ -709,6 +709,16 @@ QString InputUtils::renameWithDateTime( const QString &srcPath, const QDateTime
return QString();
}
+bool InputUtils::renameFile( const QString &srcPath, const QString &dstPath )
+{
+ QFileInfo fi( dstPath );
+ if ( !InputUtils::createDirectory( fi.absoluteDir().path() ) )
+ {
+ return false;
+ }
+ return QFile::rename( srcPath, dstPath );
+}
+
void InputUtils::showNotification( const QString &message )
{
emit showNotificationRequested( message );
diff --git a/app/inpututils.h b/app/inpututils.h
index 48b817e2a..6d62f5f42 100644
--- a/app/inpututils.h
+++ b/app/inpututils.h
@@ -127,6 +127,14 @@ class InputUtils: public QObject
*/
Q_INVOKABLE static QString renameWithDateTime( const QString &srcPath, const QDateTime &dateTime = QDateTime() );
+ /**
+ * Renames a file located at a given path to a given new name
+ * \param srcPath absolute path to a file.
+ * \param dstPath a new name of a file.
+ * \result true on success, false otherwise.
+ */
+ Q_INVOKABLE static bool renameFile( const QString &srcPath, const QString &dstPath );
+
/**
* Shows notification
*/
diff --git a/app/qml/components/SearchBoxV2.qml b/app/qml/components/SearchBoxV2.qml
index 91c37e6ba..84828c52b 100644
--- a/app/qml/components/SearchBoxV2.qml
+++ b/app/qml/components/SearchBoxV2.qml
@@ -74,4 +74,8 @@ Item {
function setActive() {
searchfield.forceActiveFocus()
}
+
+ function searchText() {
+ return searchfield.displayText
+ }
}
diff --git a/app/qml/editor/inputvaluerelationcombobox.qml b/app/qml/editor/inputvaluerelationcombobox.qml
index c18e64e2b..982934dc2 100644
--- a/app/qml/editor/inputvaluerelationcombobox.qml
+++ b/app/qml/editor/inputvaluerelationcombobox.qml
@@ -27,7 +27,6 @@ AbstractEditor {
if ( !root.isReadOnly )
{
vrModel.pair = root.featureLayerPair
- setIndex()
}
}
@@ -49,7 +48,6 @@ AbstractEditor {
onParentValueChanged: {
vrModel.pair = root.featureLayerPair
- setIndex()
}
enabled: !isReadOnly
@@ -71,6 +69,14 @@ AbstractEditor {
}
root.editorValueChanged( "", true )
}
+
+ onFetchingResultsChanged: {
+ if ( !isFetching )
+ {
+ // we need to re-set the current index every time the model is done re-populating
+ setIndex()
+ }
+ }
}
content: InputComboBox {
diff --git a/app/qml/editor/inputvaluerelationpage.qml b/app/qml/editor/inputvaluerelationpage.qml
index 5f1e4c846..3029aac2a 100644
--- a/app/qml/editor/inputvaluerelationpage.qml
+++ b/app/qml/editor/inputvaluerelationpage.qml
@@ -33,7 +33,6 @@ AbstractEditor {
if ( !root.isReadOnly )
{
vrModel.pair = root.featureLayerPair
- setText()
}
}
@@ -45,20 +44,17 @@ AbstractEditor {
function pushVrPage()
{
let props = {
- featuresModel: vrModel,
pageTitle: labelAlias,
allowMultiselect: root.allowMultivalue,
toolbarVisible: root.allowMultivalue,
preselectedFeatures: root.allowMultivalue ? vrModel.convertFromQgisType( root.parentValue, FeaturesModel.FeatureId ) : []
}
-
let obj = root.stackView.push( featuresPageComponent, props )
obj.forceActiveFocus()
}
onParentValueChanged: {
vrModel.pair = root.featureLayerPair
- setText()
}
onRightActionClicked: pushVrPage()
@@ -83,6 +79,13 @@ AbstractEditor {
}
root.editorValueChanged( "", true )
}
+
+ onFetchingResultsChanged: {
+ if ( !isFetching )
+ {
+ setText()
+ }
+ }
}
content: Text {
@@ -126,6 +129,13 @@ AbstractEditor {
FeaturesListPage {
id: featuresPage
+ featuresModel: ValueRelationFeaturesModel {
+ id: vrPageModel
+
+ config: root.fieldConfig
+ pair: root.featureLayerPair
+ }
+
pageTitle: qsTr( "Features" )
allowSearch: true
focus: true
@@ -155,7 +165,6 @@ AbstractEditor {
// We need to convert feature id to string prior to sending it to C++ in order to
// avoid conversion to scientific notation.
featureIds = featureIds.toString()
-
root.editorValueChanged( vrModel.convertToKey( featureIds ), false )
}
root.stackView.pop()
diff --git a/app/qml/layers/FeaturesListPageV2.qml b/app/qml/layers/FeaturesListPageV2.qml
index 7ad79750a..9bb335ef3 100644
--- a/app/qml/layers/FeaturesListPageV2.qml
+++ b/app/qml/layers/FeaturesListPageV2.qml
@@ -41,9 +41,7 @@ Page {
topMargin: InputStyle.panelMarginV2
}
- onSearchTextChanged: function ( searchText ) {
- featuresModel.searchExpression = searchText
- }
+ onSearchTextChanged: searchDelay.restart()
}
ListView {
@@ -128,6 +126,23 @@ Page {
}
}
+ Timer {
+ id: searchDelay
+ interval: 500
+ running: false
+ repeat: false
+ onTriggered: featuresModel.searchExpression = searchbox.searchText()
+ }
+
+ BusyIndicator {
+ id: busyIndicator
+ width: parent.width/8
+ height: width
+ running: featuresModel.fetchingResults
+ visible: running
+ anchors.centerIn: parent
+ }
+
Component {
id: addFeatureHeaderComponent
diff --git a/app/test/testattributecontroller.cpp b/app/test/testattributecontroller.cpp
index 8139836d7..91be1a481 100644
--- a/app/test/testattributecontroller.cpp
+++ b/app/test/testattributecontroller.cpp
@@ -25,7 +25,7 @@
#include "attributetabmodel.h"
#include "attributeformproxymodel.h"
#include "attributeformmodel.h"
-
+#include "inpututils.h"
void TestAttributeController::init()
{
@@ -694,3 +694,45 @@ void TestAttributeController::testFieldsOutsideForm()
}
}
}
+
+void TestAttributeController::testPhotoRenaming()
+{
+ QString projectName = QStringLiteral( "testPhotoRenaming" );
+ QString projectDir = QDir::tempPath() + "/" + projectName;
+ QString projectFileName = "project.qgz";
+
+ QDir tempDir( projectDir );
+ tempDir.removeRecursively();
+
+ InputUtils::cpDir( TestUtils::testDataDir() + "/test_photo_rename", projectDir );
+
+ QVERIFY( QFile::exists( projectDir + QStringLiteral( "/photo.jpg" ) ) );
+ QVERIFY( !QFile::exists( projectDir + QStringLiteral( "/image_test.jpg" ) ) );
+
+ QVERIFY( QgsProject::instance()->read( projectDir + QStringLiteral( "/test_photo_rename.qgz" ) ) );
+
+ QgsMapLayer *layer = QgsProject::instance()->mapLayersByName( QStringLiteral( "Survey" ) ).at( 0 );
+ QgsVectorLayer *surveyLayer = static_cast( layer );
+
+ QVERIFY( surveyLayer && surveyLayer->isValid() );
+
+ QgsFeature feat;
+ feat.setValid( true );
+ feat.setFields( surveyLayer->fields(), true );
+ FeatureLayerPair pair( feat, surveyLayer );
+
+ AttributeController controller;
+ controller.setFeatureLayerPair( pair );
+
+ const TabItem *tab = controller.tabItem( 0 );
+ const QVector items = tab->formItems();
+ QCOMPARE( items.size(), 4 );
+
+ controller.setFormValue( items.at( 2 ), QStringLiteral( "test" ) );
+ controller.setFormValue( items.at( 3 ), QStringLiteral( "photo.jpg" ) );
+ controller.save();
+
+ QVERIFY( !QFile::exists( projectDir + QStringLiteral( "/photo.jpg" ) ) );
+ QVERIFY( QFile::exists( projectDir + QStringLiteral( "/image_test.jpg" ) ) );
+ QCOMPARE( controller.featureLayerPair().feature().attribute( 3 ), QStringLiteral( "image_test.jpg" ) );
+}
diff --git a/app/test/testattributecontroller.h b/app/test/testattributecontroller.h
index cc14caf31..3ba3d0792 100644
--- a/app/test/testattributecontroller.h
+++ b/app/test/testattributecontroller.h
@@ -30,6 +30,7 @@ class TestAttributeController: public QObject
void testExpressions();
void testRawValue();
void testFieldsOutsideForm();
+ void testPhotoRenaming();
};
#endif // TESTATTRIBUTECONTROLLER_H
diff --git a/app/test/testformeditors.cpp b/app/test/testformeditors.cpp
index 0b3980504..4c4d22264 100644
--- a/app/test/testformeditors.cpp
+++ b/app/test/testformeditors.cpp
@@ -23,6 +23,7 @@
#include "qgsvectorlayer.h"
#include "qgsrelationmanager.h"
+
void TestFormEditors::init()
{
}
@@ -220,9 +221,11 @@ void TestFormEditors::testRelationsEditor()
// test relation features model - should fetch one feature
RelationFeaturesModel mainRelationModel;
+ QSignalSpy modelSpy( &mainRelationModel, &FeaturesModel::fetchingResultsChanged );
mainRelationModel.setRelation( mainRelation->relation() );
mainRelationModel.setParentFeatureLayerPair( mainPair );
+ modelSpy.wait();
int featuresCount = mainRelationModel.rowCount();
QVERIFY( featuresCount > 0 );
@@ -258,6 +261,7 @@ void TestFormEditors::testRelationsEditor()
QCOMPARE( catchFeatureIdSpy.count(), 1 );
QgsFeatureId addedFeatureId = catchFeatureIdSpy.takeFirst().at( 0 ).value();
+ modelSpy.wait();
int newFeaturesCount = mainRelationModel.rowCount();
QCOMPARE( newFeaturesCount, featuresCount + 1 ); // we have added one feature
@@ -271,6 +275,7 @@ void TestFormEditors::testRelationsEditor()
QVERIFY( subLayer->deleteFeature( addedFeatureId ) );
QVERIFY( subLayer->commitChanges() );
+ modelSpy.wait();
int reducedFeaturesCount = mainRelationModel.rowCount();
QCOMPARE( reducedFeaturesCount, featuresCount );
@@ -343,9 +348,11 @@ void TestFormEditors::testRelationsReferenceEditor()
// We want to test if relation reference models are filled with correct data
RelationReferenceFeaturesModel subRelationRefModel;
+ QSignalSpy subSpy( &subRelationRefModel, &FeaturesModel::fetchingResultsChanged );
subRelationRefModel.setConfig( subRelationRef->editorWidgetConfig() );
subRelationRefModel.setProject( QgsProject::instance() );
+ subSpy.wait();
QgsFeature parentFeat = mainLayer->getFeature( 1 ); // this is parent feature
QVariant fk = subRelationRefModel.foreignKeyFromAttribute( FeaturesModel::FeatureId, parentFeat.id() );
@@ -499,9 +506,12 @@ void TestFormEditors::testValueRelationsEditor()
const FormItem *subFkItem = controller.formItem( items.at( 2 ) );
ValueRelationFeaturesModel subVRModel;
+ QSignalSpy subSpy( &subVRModel, &FeaturesModel::fetchingResultsChanged );
+
subVRModel.setConfig( subFkItem->editorWidgetConfig() );
subVRModel.setPair( pair );
+ subSpy.wait();
QCOMPARE( subVRModel.rowCount(), subLayer->dataProvider()->featureCount() );
QCOMPARE( subVRModel.layer()->id(), subLayer->id() );
@@ -510,9 +520,11 @@ void TestFormEditors::testValueRelationsEditor()
const FormItem *subsubFkItem = controller.formItem( items.at( 4 ) );
ValueRelationFeaturesModel subsubVRModel;
+ QSignalSpy subsubSpy( &subsubVRModel, &FeaturesModel::fetchingResultsChanged );
subsubVRModel.setConfig( subsubFkItem->editorWidgetConfig() );
subsubVRModel.setPair( pair );
+ subsubSpy.wait();
QCOMPARE( subsubVRModel.rowCount(), 2 ); // due to a filter expression
QCOMPARE( subsubVRModel.layer()->id(), subsubLayer->id() );
@@ -526,6 +538,7 @@ void TestFormEditors::testValueRelationsEditor()
// test filter expression in combination with search
subsubVRModel.setSearchExpression( QStringLiteral( "2" ) );
+ subsubSpy.wait();
QCOMPARE( subsubVRModel.rowCount(), 1 );
// test title field on result
@@ -539,9 +552,11 @@ void TestFormEditors::testValueRelationsEditor()
const FormItem *anotherFkItem = controller.formItem( items.at( 3 ) );
ValueRelationFeaturesModel anotherVRModel;
+ QSignalSpy anotherSpy( &subsubVRModel, &FeaturesModel::fetchingResultsChanged );
anotherVRModel.setConfig( anotherFkItem->editorWidgetConfig() );
anotherVRModel.setPair( pair );
+ anotherSpy.wait();
QCOMPARE( anotherVRModel.rowCount(), anotherLayer->dataProvider()->featureCount() );
QCOMPARE( anotherVRModel.layer()->id(), anotherLayer->id() );
@@ -562,6 +577,7 @@ void TestFormEditors::testValueRelationsEditor()
subsubVRModel.setPair( controller.featureLayerPair() );
subsubVRModel.setSearchExpression( "" );
+ subsubSpy.wait();
QgsFeature bigF = subsubLayer->getFeature( 100000000 );
QCOMPARE( subsubVRModel.convertToKey( bigF.id() ), bigF.id() );
}
diff --git a/app/test/testmodels.cpp b/app/test/testmodels.cpp
index e9c9b1975..6140d1164 100644
--- a/app/test/testmodels.cpp
+++ b/app/test/testmodels.cpp
@@ -13,6 +13,7 @@
#include
+
void TestModels::init()
{
@@ -26,6 +27,7 @@ void TestModels::cleanup()
void TestModels::testFeaturesModel()
{
FeaturesModel fModel;
+ QSignalSpy spy( &fModel, &FeaturesModel::fetchingResultsChanged );
QString projectDir = TestUtils::testDataDir() + "/project_value_relations";
QgsVectorLayer *layer = new QgsVectorLayer( projectDir + "/db.gpkg|layername=main", "base", "ogr" );
@@ -34,15 +36,18 @@ void TestModels::testFeaturesModel()
fModel.setLayer( layer );
fModel.reloadFeatures();
+ spy.wait();
QCOMPARE( fModel.rowCount(), layer->dataProvider()->featureCount() );
fModel.setSearchExpression( QStringLiteral( "Seco" ) );
+ spy.wait();
QCOMPARE( fModel.rowCount(), 1 );
fModel.setSearchExpression( QLatin1String() );
+ spy.wait();
QCOMPARE( fModel.rowCount(), layer->dataProvider()->featureCount() );
QVariant title = fModel.data( fModel.index( 0 ), FeaturesModel::FeatureTitle );
diff --git a/cmake_templates/iOSInfo.plist.in b/cmake_templates/iOSInfo.plist.in
index 0eabc671a..784e3ec2b 100644
--- a/cmake_templates/iOSInfo.plist.in
+++ b/cmake_templates/iOSInfo.plist.in
@@ -83,6 +83,7 @@
az
az_AZ
hu
+ cs
UIFileSharingEnabled
diff --git a/core/merginapi.cpp b/core/merginapi.cpp
index 89fefa85b..14429f7e2 100644
--- a/core/merginapi.cpp
+++ b/core/merginapi.cpp
@@ -3096,13 +3096,14 @@ void MerginApi::finishProjectSync( const QString &projectFullName, bool syncSucc
QString projectDir = transaction.projectDir; // keep it before the transaction gets removed
ProjectDiff diff = transaction.diff;
int newVersion = syncSuccessful ? transaction.version : -1;
- mTransactionalStatus.remove( projectFullName );
- if ( transaction.gpkgSchemaChanged )
+ if ( transaction.gpkgSchemaChanged || projectFileHasBeenUpdated( diff ) )
{
emit projectReloadNeededAfterSync( projectFullName );
}
+ mTransactionalStatus.remove( projectFullName );
+
if ( pullBeforePush )
{
CoreUtils::log( "sync " + projectFullName, QStringLiteral( "Continue with push after pull" ) );
diff --git a/test/test_data/test_photo_rename/Survey_points.gpkg b/test/test_data/test_photo_rename/Survey_points.gpkg
new file mode 100644
index 000000000..b02047968
Binary files /dev/null and b/test/test_data/test_photo_rename/Survey_points.gpkg differ
diff --git a/test/test_data/test_photo_rename/photo.jpg b/test/test_data/test_photo_rename/photo.jpg
new file mode 100644
index 000000000..e4b7f3d3b
Binary files /dev/null and b/test/test_data/test_photo_rename/photo.jpg differ
diff --git a/test/test_data/test_photo_rename/test_photo_rename.qgz b/test/test_data/test_photo_rename/test_photo_rename.qgz
new file mode 100644
index 000000000..6bf45bd3c
Binary files /dev/null and b/test/test_data/test_photo_rename/test_photo_rename.qgz differ