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 - - Without storage permission you will not be able to access previous projects - Sense permís d'emmagatzematge no podreu accedir als projectes anteriors - - - + Storage permission is permanently denied, please allow it in settings in order to load pictures from gallery El permís d'emmagatzematge està denegat permanentment. Permeteu-lo a la configuració per carregar imatges de la galeria - + Input needs a storage permission in order to load pictures from gallery Input necessita permís d'emmagatzematge per carregar imatges de la galeria - + Camera permission is permanently denied, please allow it in settings El permís per emprar la càmera s'ha denegat permanentment, autoritzeu-lo a la configuració - + We need a camera permission in order to take a photo 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. - + Value "%1" %4 could not be converted to a compatible value for field %2(%3). 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. - + Feature could not be added La característica no es pot afegir - + Cannot update feature No es pot actualitzar la característica - + Cannot start editing No es pot començar a editar @@ -303,35 +298,35 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment. BluetoothPositionProvider - - + + No connection Sense connexió - + Reconnecting Reconnectant - - + + No connection, reconnecting in (%1) Sense connexió, reconnectant en (%1) - + Could not connect to device, not paired No s'ha pogut connectar al dispositiu, no vinculat - + Connecting to %1 Connectant a %1 - - + + Connected Connectat @@ -794,52 +789,52 @@ No s'afegirà al projecte. ara fa %1 any - + screen resolution: %1x%2 px resolució de pantalla: %1x%2 px - + screen DPI: %1x%2 DPI de pantalla: %1x%2 - + screen size: %1x%2 mm mida de pantalla: %1x%2 mm - + reported device pixel ratio: %1 relació de píxels del dispositiu informada: %1 - + calculated device pixel ratio: %1 relació de píxels del dispositiu calculada: %1 - + used dp scale: %1 escala dp utilitzada: %1 - + You need to add at least %1 point(s) to every part. Heu d'afegir almenys %1 punt(s) a cada tros. - + You need to add at least %1 point(s). Heu d'afegir com a mínim %1 punt(s). @@ -865,8 +860,8 @@ No s'afegirà al projecte. InternalPositionProvider - - + + Connected Connectat @@ -915,39 +910,6 @@ No s'afegirà al projecte. Cerca a les capes - - LegacyFolderMigration - - - Insufficient space left on device - No queda prou espai al dispositiu - - - - Your device is running out of space, you need %1 of free space in order to see your projects. Remove some files and come back or click Help to see other ways how to resolve this issue. - 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. - - - - An error occured during update - S'ha produït un error durant l'actualització - - - - Your device run into a problem during applying an update. You will not be able to see your projects. Click Help to see how to resolve this issue. - 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. - - - - We are working on an important update, please do not close the application - Estem treballant en una actualització important, no tanqueu l'aplicació - - - - %1/%2 - %1/%2 - - LocalProjectsManager @@ -1015,60 +977,66 @@ No s'afegirà al projecte. MainPanel - - + + Projects Projectes - - + + GPS GPS - - + + Record Registre - - + + Zoom to project Zoom al projecte - - + + Local changes Canvis locals - - + + Layers Capes - - + + Map themes Temes de mapa - - + + + Position tracking + Seguiment de la posició + + + + Settings Configuració - + More Més - + Menu Menú @@ -1122,87 +1090,87 @@ No s'afegirà al projecte. MapWrapper - + GPS currently unavailable. GPS no disponible - + Successfully synchronized Correctament sincronitzat - + Up to date Actualitzat - + Somebody else is syncing, we will try again later Algú més s'està sincronitzant, ho tornarem a provar més tard - + There was an issue during synchronization, we will try again. Click to learn more Hi ha hagut un problema durant la sincronització, ho tornarem a provar. Feu clic per obtenir més informació - + Splitting done successfully Divisió realitzada amb èxit - + Create line to split the selected feature Crea una línia per dividir la geometria seleccionada - + Select some point to start editing the geometry Seleccioneu algun punt per començar a editar la geometria - + Record new geometry for the feature Enregistreu una geometria nova per a la característica - + Details Detalls - + Back Tornar - + Discard the changes? Descartar els canvis? - + Clicking ‘Yes’ discards your changes to the geometry. If you would like to save the changes instead, hit ‘No’ and then ‘Done’ in the toolbar. 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. - + Clicking ‘Yes’ discards your new geometry and no feature will be saved. If you would like to save the geometry instead, hit ‘No’ and then ‘Done’ in the toolbar. 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. - + Connecting to %1 Connectant amb %1 - + Connected, no position Connectat, sense posició - + Unknown accuracy Precisió desconeguda @@ -1255,12 +1223,12 @@ No s'afegirà al projecte. Projecte desvinculat de Mergin - + Workspace name contains invalid characters El nom de l'espai de treball conté caràcters no vàlids - + Workspace %1 already exists L'espai de treball %1 ja existeix @@ -1394,26 +1362,67 @@ Feu clic a "Sí" per carregar-lo. PositionProvidersModel - + Internal Intern - + GPS receiver of this device Receptor GPS d'aquest dispositiu - + Bluetooth device Dispositiu Bluetooth - + Bluetooth device Dispositiu Bluetooth + + PositionTrackingDrawer + + + Position tracking + Seguiment de la posició + + + + Mergin Maps can track your position on this project. + Mergin Maps pot fer un seguiment de la vostra posició en aquest projecte. + + + + Stop tracking + Atura el seguiment + + + + Start tracking + Començar el seguiment + + + + PositionTrackingManager + + + Could not find tracking layer for the project + No s'ha pogut trobar la capa de seguiment del projecte + + + + Tracking layer not found or invalid + La capa de seguiment no s'ha trobat o no és vàlida + + + + Failed to start tracking, please contact support + 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 - + No Changes Sense canvis - - - + + + Projects Projectes - - + + Home Inici - + My projects Els meus projectes - + Shared with me Compartit amb mi - + Shared Compartit - - + + Explore Explora - + Downloaded projects Projectes descarregats - + Public projects Projectes públics - + Your other projects are accessible%1by switching your workspace here 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 - + No data Sense dades - + No fix Sense posició - + GPS fix, no correction data Posició GPS, sense dades de correcció - + DGPS fix Posició DGPS - + PPS fix Posició PPS - + RTK fix Posició RTK - + RTK float RTK flotant - + Estimated fix (dead reckoning) Posició estimada (dead reckoning) - + Unknown fix Posició desconeguda @@ -2063,7 +2072,7 @@ Feu clic a "Sí" per carregar-lo. SimulatedPositionProvider - + Connected Connectat @@ -2515,58 +2524,64 @@ Aneu al lloc web de Mergin Maps per eliminar-lo manualment. main - - + + No Changes Cap canvi - + GPS auto-center mode on Mode autocentrat del GPS activat - + GPS auto-center mode off Mode autocentrat del GPS desactivat - + No editable layers found. No s'ha trobat cap nivell editable. - + + + not tracking + no seguiment + + + Stake out is disabled because location is unavailable! El replanteig està desactivat perquè la ubicació no està disponible! - + Failed to open the project No s'ha pogut obrir el projecte - + Failed to communicate with Mergin.%1Try improving your network connection. Error de comunicació amb Mergin.%1Proveu a millorar la vostra connexió de xarxa - + There were issues loading the project. Problemes en carregar el projecte. - + Could not read the project file: No s'ha pogut llegir el fitxer del projecte: - + Press back again to quit the app Premeu enrere un altre cop per sortir de l'aplicació - + PROJ Error 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 - - Without storage permission you will not be able to access previous projects - - - - + Storage permission is permanently denied, please allow it in settings in order to load pictures from gallery - + Input needs a storage permission in order to load pictures from gallery - + Camera permission is permanently denied, please allow it in settings - + We need a camera permission in order to take a photo @@ -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). 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 Feature could not be added - + Cannot update feature Cannot update feature - + Cannot start editing Cannot start editing @@ -300,35 +295,35 @@ Please go to the Mergin Maps website to remove it manually. BluetoothPositionProvider - - + + No connection - + Reconnecting - - + + No connection, reconnecting in (%1) - + Could not connect to device, not paired - + Connecting to %1 - - + + Connected @@ -790,50 +785,50 @@ Won't be added to the project. - + screen resolution: %1x%2 px screen resolution: %1x%2 px - + screen DPI: %1x%2 screen DPI: %1x%2 - + screen size: %1x%2 mm screen size: %1x%2 mm - + reported device pixel ratio: %1 - + calculated device pixel ratio: %1 - + used dp scale: %1 - + You need to add at least %1 point(s) to every part. - + You need to add at least %1 point(s). @@ -859,8 +854,8 @@ Won't be added to the project. InternalPositionProvider - - + + Connected @@ -909,39 +904,6 @@ Won't be added to the project. - - LegacyFolderMigration - - - Insufficient space left on device - - - - - Your device is running out of space, you need %1 of free space in order to see your projects. Remove some files and come back or click Help to see other ways how to resolve this issue. - - - - - An error occured during update - - - - - Your device run into a problem during applying an update. You will not be able to see your projects. Click Help to see how to resolve this issue. - - - - - We are working on an important update, please do not close the application - - - - - %1/%2 - - - LocalProjectsManager @@ -1009,60 +971,66 @@ Won't be added to the project. MainPanel - - + + Projects Projects - - + + GPS GPS - - + + Record Record - - + + Zoom to project Zoom to project - - + + Local changes - - + + Layers - - + + Map themes Map themes - - + + + Position tracking + + + + + Settings Settings - + More More - + Menu Menu @@ -1116,87 +1084,87 @@ Won't be added to the project. MapWrapper - + GPS currently unavailable. - + Successfully synchronized - + Up to date - + Somebody else is syncing, we will try again later - + There was an issue during synchronization, we will try again. Click to learn more - + Splitting done successfully - + Create line to split the selected feature - + Select some point to start editing the geometry - + Record new geometry for the feature - + Details - + Back - + Discard the changes? - + Clicking ‘Yes’ discards your changes to the geometry. If you would like to save the changes instead, hit ‘No’ and then ‘Done’ in the toolbar. - + Clicking ‘Yes’ discards your new geometry and no feature will be saved. If you would like to save the geometry instead, hit ‘No’ and then ‘Done’ in the toolbar. - + Connecting to %1 - + Connected, no position - + Unknown accuracy @@ -1249,12 +1217,12 @@ Won't be added to the project. - + Workspace name contains invalid characters - + Workspace %1 already exists @@ -1387,26 +1355,67 @@ Click 'Yes' to upload it. PositionProvidersModel - + Internal - + GPS receiver of this device - + Bluetooth device - + Bluetooth device + + PositionTrackingDrawer + + + Position tracking + + + + + Mergin Maps can track your position on this project. + + + + + Stop tracking + + + + + Start tracking + + + + + PositionTrackingManager + + + Could not find tracking layer for the project + + + + + Tracking layer not found or invalid + + + + + Failed to start tracking, please contact support + + + PreviewPanel @@ -1532,56 +1541,56 @@ Click 'Yes' to upload it. ProjectPanel - + No Changes No Changes - - - + + + Projects Projects - - + + Home Home - + My projects My projects - + Shared with me Shared with me - + Shared Shared - - + + Explore Explore - + Downloaded projects - + Public projects - + Your other projects are accessible%1by switching your workspace here @@ -1769,47 +1778,47 @@ Click 'Yes' to upload it. - + No data - + No fix - + GPS fix, no correction data - + DGPS fix - + PPS fix - + RTK fix - + RTK float - + Estimated fix (dead reckoning) - + Unknown fix @@ -2055,7 +2064,7 @@ Click 'Yes' to upload it. SimulatedPositionProvider - + Connected @@ -2503,58 +2512,64 @@ Please go to the Mergin Maps website to remove it manually. main - - + + No Changes No Changes - + GPS auto-center mode on - + GPS auto-center mode off - + No editable layers found. - + + + not tracking + + + + Stake out is disabled because location is unavailable! - + Failed to open the project - + Failed to communicate with Mergin.%1Try improving your network connection. - + There were issues loading the project. - + Could not read the project file: - + Press back again to quit the app - + PROJ Error 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 - + Your subscription was cancelled on %1 サブスクリプションは %1 でキャンセルされました - + My Account マイアカウント - + Your subscription will not auto-renew after %1 サブスクリプションは %1 を過ぎても自動更新されません - + Please update your %1billing details%2 as soon as possible できるだけ早く %1支払いの詳細%2 についてアップデートしてください。 - + Your next bill will be for %1 on %2 次の %1 の請求は %2 に行われます。 - + Using %1 / %2 %1 / %2 利用中 - + Manage Subscription サブスクリプションの管理 - + Working... 作業中... - + Subscription plans サブスクリプションプラン - + You can also %1restore%2 your purchases 購入したサブスクリプションを %1復元%2 することができます。 - + Sign out サインアウト + + + Delete account + アカウントを削除 + + + + Delete account? + アカウントを削除しますか? + + + + This action will delete your Mergin Maps account with all your projects, both on the device and on the server. This action cannot be undone. If you have an Apple subscription you need to cancel it manually. + +In order to delete your account, enter your username in the field below and click Yes. + この操作によって、あなたのMergin Mapsアカウントと、デバイス上とサーバー上のすべてのプロジェクトが削除されます。この操作は元に戻せません。Appleのサブスクリプションをお持ちの場合は、手動でキャンセルする必要があります。 + +アカウントを削除するには、下のフィールドにユーザー名を入力し、はいをクリックします。 + + + + Enter username + ユーザ名を入力 + + + + Failed to remove account + アカウントの削除に失敗しました + + + + An error occured while removing your account + アカウント削除中にエラーが起きました + + + + Can not close account because user is the only owner of an organisation. + +Please go to the Mergin Maps website to remove it manually. + ユーザーが組織の唯一の所有者であるため、アカウントを閉じることができません。 + +Mergin Mapsのウェブサイトから手動で削除してください。 + ActiveLayerPanel - + Choose Active Layer アクティブレイヤを選択 - + Could not find any editable layers in the project. See %1how to enable digitizing in your project%2. プロジェクトに編集可能なレイヤがありません。%1プロジェクトでデジタイズを有効にする方法%2 をご覧ください。 - AndroidUtils + AddPositionProviderPage + + + Connect to bluetooth device + Bluetooth機器に接続 + + + + You need to enable Bluetooth in order to connect new GPS receiver + 新しいGPSレシーバーを接続するには、Bluetoothを有効にする必要があります。 + + + + Unknown device + 不明なデバイス + + + + Looking for more devices + 他のデバイスを探しています + - - Without storage permission you will not be able to access previous projects - ストレージの許可がないと、過去のプロジェクトにアクセスできません + + Looking for devices + デバイスを探しています + + + AndroidUtils - + Storage permission is permanently denied, please allow it in settings in order to load pictures from gallery ストレージへのアクセス権限がありません。ギャラリーから写真を読み込むためにアクセスを許可してください - + Input needs a storage permission in order to load pictures from gallery Inputはギャラリーから写真を読み込むためにストレージへのアクセス権限が必要です - + Camera permission is permanently denied, please allow it in settings カメラへのアクセス権限がありません。アクセス許可を設定してください。 - + We need a camera permission in order to take a photo 写真を撮影するためにカメラへのアクセス権限が必要です。 @@ -117,51 +183,46 @@ AttributeController - + + Default value expression for %1:%2 has parser error: %3 %1:%2 のデフォルト値の式の変換でエラーが起きました: %3 - + + Default value expression for %1:%2 has evaluation error: %3 %1:%2 のデフォルト値の式の評価でエラーが起きました: %3 - + + + Value "%1" %4 could not be converted to a compatible value for field %2(%3). 値 "%1" %4 はフィールド%2(%3)のための互換値に変換できませんでした。 - + Cannot delete feature 地物を削除できません - - + + Feature could not be added 地物を追加できませんでした - + + Cannot update feature 地物を更新できません - - Feature %1 could not be fetched after commit - コミット後に地物 %1 を取得できませんでした - - - + Cannot start editing 編集を開始できません - - - Could not save changes. Rolling back. - 変更を保存できませんでした。ロールバックします。 - AuthPanel @@ -176,12 +237,12 @@ 登録 - + Please update Input to use the latest Mergin features. 最新のMerginの機能を使用するためにInputをアップデートしてください。 - + Mergin is currently unavailable - please try again later. 現在Merginは利用できません - 後で再度試して下さい. @@ -189,172 +250,183 @@ Banner - - %1<br><a href='%2' style="color: %3;">Learn more</a> - %1<br><a href='%2' style="color: %3;">さらに詳しく</a> + + Learn more + 詳細はこちら - BrowseDataLayersPanel - - - Layers - レイヤ - + BluetoothConnectionDialog - - No layers have been configured to allow browsing their features. See %1how to modify your project%2. - 地物が閲覧できるように設定されたレイヤがありません. %1 でプロジェクトの設定方法を参照して下さい %2. + + Connecting to + 接続中: - - - CodeReader - - Scan code - コードをスキャン + + Connected + 接続されました - - - DateTimePicker - - Cancel - キャンセル + + Failed to connect to + 接続に失敗しました: - - OK - OK + + You might be asked to pair your device during this process. + この過程でデバイスのペアリングを求められることがあります。 - - January - 1月 + + You can close this message, we will try to repeatedly connect to your device.%1 If you need more help, %2click here%3 + このメッセージを閉じることができます。繰り返しデバイスへの接続を試みます。%1 さらにヘルプが必要な場合は、%2ここをクリックしてください%3 - - February - 2月 + + We were not able to connect to the specified device. + Please make sure your device is powered on and can be connected to.%1 %2Learn more here%3. + 指定されたデバイスに接続できませんでした。 + デバイスの電源が入っていて、接続できることを確認してください。%1 %2詳細はこちら%3。 - - March - 3月 + + Close + 閉じる + + + BluetoothPositionProvider - - April - 4月 + + + No connection + 接続がありません - - May - 5月 + + Reconnecting + 再接続しています - - June - 6月 + + + No connection, reconnecting in (%1) + 接続がありません。(%1) で再接続しています。 - - July - 7月 + + Could not connect to device, not paired + デバイスに接続できず、ペアリングされていません - - August - 8月 + + Connecting to %1 + %1に接続中 - - September - 9月 + + + Connected + 接続されました + + + CodeScanner - - October - 10月 + + Scan code + コードをスキャン + + + CreateWorkspacePage - - November - 11月 + + Create a workspace + ワークスペースを作成 - - December - 12月 + + A Workspace is a place to store your projects. Colleagues can be invited to your workspace to collaborate on projects. A good candidate for a workspace name is the name of your team or organisation. + ワークスペースは、プロジェクトを保存する場所です。同僚をワークスペースに招待して、プロジェクトで共同作業を行うことができます。ワークスペース名の候補としては、あなたのチーム名や組織名が良いでしょう。 - - Sunday - 日曜日 + + My workspace name… + ワークスペース名... - - Monday - 月曜日 + + Create workspace + ワークスペースを作成 - - Tuesday - 火曜日 + + Empty workspace name + ワークスペース名が未入力です + + + DateTimePicker - - Wednesday - 水曜日 + + Cancel + キャンセル - - Thursday - 木曜日 + + OK + OK + + + ExternalResourceBundle - - Friday - 金曜日 + + Could not create directory %1. + ディレクトリ %1 を作成できませんでした。 - - Saturday - 土曜日 + + Failed to copy image file to %1. + 画像ファイルを %1 にコピーできませんでした。 - - - ExternalResourceBundle - + Open Image イメージを開く - + Image files (*.gif *.png *.jpg) イメージファイル (*.gif *.png *.jpg) - + Remove photo reference 写真への参照を削除する - + Also permanently delete photo from device? デバイスから写真を完全に削除しますか? + + + Failed to copy image + 画像ファイルをコピーできませんでした。 + FeatureForm - + Can not save the form, there are validation errors フォームを保存できません。入力エラーがあります。 - + Feature could not be saved, please check all required fields 地物を保存できません。入力必須項目全てを確認してください。 @@ -362,65 +434,84 @@ FeatureFormPage - + Edit Feature 地物の編集 - + Feature 地物 - + Save 保存 - + Delete feature 地物の削除 - + Are you sure you want to delete this feature? 本当にこの地物を削除しますか? - + Unsaved changes 保存されていない変更 - + Do you want to save changes? 変更内容を保存しますか? + + + Saving failed + 保存に失敗しました + + + + Failed to save changes. This should not happen normally. Please restart the app and try again — if that does not help, please contact support. + 変更の保存に失敗しました。通常、このようなことは起こらないはずです。アプリを再起動して再度お試しください。それでも解決しない場合は、サポートまでご連絡ください。 + FeatureToolbar - + Edit 編集 - + Delete 削除 - + + Edit geometry - 地物の編集 + ジオメトリの編集 + + + + + Advanced + 詳細 + + + + Split geometry + ジオメトリの分割 - - - FeaturesListPage - - Showing only the first %1 features - 最初の %1 個の地物を表示しています + + Redraw geometry + ジオメトリの再描画 @@ -441,20 +532,28 @@ リンクを削除 + + FeaturesListPageV2 + + + Add feature + 地物の追加 + + FieldsModel - + Please fill a name of previous field before adding a new field. 新しいフィールドを追加する前に、一つ前のフィールド名を入力してください。 - + Field %1 already exists. フィールド %1 は既に存在しています。 - + Field %1 already exists. Won't be added to the project. フィールド %1 は既に存在しています。 @@ -464,94 +563,140 @@ Won't be added to the project. GpsDataPage - + GPS info GPS情報 - - - - - - - - - - Loading data from GPS - GPSからデータを読み込んでいます - - - + Altitude 高度 - + Longitude 経度 - + + Source + ソース + + + + No receiver + 受信機がありません + + + + Status + 状態 + + + Latitude 緯度 - + X X - + Y Y - + Horizontal accuracy 水平精度 - - + + VDOP + VDOP + + + + PDOP + PDOP + + + + GPS antenna height + GPSアンテナの高さ + + + + Not set + 未設定 + + + + Manage GPS receivers + GPS受信機の管理 + + + + + + + + + + + + + + + + + + N/A N/A - + Vertical accuracy 垂直精度 - + + Fix quality + 品質を修正 + + + Satellites (in use/view) 衛星 (利用数/表示数) - + + HDOP + HDOP + + + Speed 速度 - + Last fix 最後の修正 - - - Date not available - 日付が不明です - InputHelp - + Report submitted.%1Please contact us on%1%2 リポートは送信されました。%1次のアドレスに連絡してください:%1%2 - + Failed to submit report.%1Please check your internet connection. リポートの送信に失敗しました。%1インターネット接続を確認してください。 @@ -577,144 +722,210 @@ Won't be added to the project. InputUtils - + just now たった今 - + %1 minutes ago %1 分前 - + %1 minute ago %1 分前 - + %1 hours ago %1 時間前 - + %1 hour ago %1 時間前 - - + + %1 days ago %1 日前 - - + + %1 day ago %1 日前 - + %1 weeks ago %1 週間前 - + %1 week ago %1 週間前 - + %1 months ago %1 ヶ月前 - + %1 month ago %1 ヶ月前 - + %1 years ago %1 年前 - + %1 year ago %1 年前 - + screen resolution: %1x%2 px スクリーン解像度: %1x%2 px - + screen DPI: %1x%2 スクリーンDPI: %1x%2 - + screen size: %1x%2 mm スクリーンサイズ: %1x%2 mm - + reported device pixel ratio: %1 取得したデバイスの画素数比率: %1 - + calculated device pixel ratio: %1 計算したデバイスの画素数比率: %1 - + used dp scale: %1 使用したdpスケール: %1 + + + You need to add at least %1 point(s) to every part. + すべてのパートに少なくとも%1ポイントを加える必要があります。 + + + + You need to add at least %1 point(s). + 少なくとも%1ポイントを加える必要があります。 + + + + InstallScannerAppDialog + + + Install scanner application + スキャナアプリのインストール + + + + You will be redirected to Google Play to install the Barcode Scanner app. + バーコードスキャナーアプリをインストールするためにGoogle Playにリダイレクトされます。 + + + + After the Barcode Scanner app is installed, close it and switch back to Mergin Maps. + バーコードスキャナーアプリがインストールされたら、アプリを終了し、Mergin Mapsに戻ります。 + + + + InternalPositionProvider + + + + Connected + 接続されました + - LegacyFolderMigration + LayerDetail + + + Settings + 設定 + + + + Visible on map + 地図上に表示 + + + + Legend + 凡例 + + + + Features + 地物 + - - Insufficient space left on device - デバイスに十分な空き容量がありません + + Layer info + レイヤ情報 + + + LayersListPageV2 - - Your device is running out of space, you need %1 of free space in order to see your projects. Remove some files and come back or click Help to see other ways how to resolve this issue. - デバイスの空き容量が不足しています。プロジェクトを表示するには %1 の空き容量が必要です。何らかのファイルを削除してから戻ってくるか、「ヘルプ」をクリックして、この問題を解決する他の方法を確認してください。 + + Layers + レイヤ + + + LayersListSearchPage - - An error occured during update - アップデート中にエラーが発生しました + + Search layers + レイヤの検索 + + + LocalProjectsManager - - Your device run into a problem during applying an update. You will not be able to see your projects. Click Help to see how to resolve this issue. - アップデートの適用中にデバイスに問題が発生しました。プロジェクトを見ることができなくなります。「ヘルプ」をクリックすると、この問題を解決する方法が表示されます。 + + Download failed, remove and retry + ダウンロード失敗,削除して再度試して下さい - - We are working on an important update, please do not close the application - 重要なアップデートを行っていますので、アプリを閉じないでください + + Found multiple QGIS project files + 複数のQGISプロジェクトファイルが見つかりました - - %1/%2 - %1/%2 + + Failed to find a QGIS project file + QGISプロジェクトファイルが見つかりません @@ -738,27 +949,27 @@ Won't be added to the project. LoginForm - - %1Mergin%2 provides cloud-based sync between your mobile and desktop. Also use it to share your projects with others and work collaboratively. - %1Mergin%2 はスマホとPC間のクラウドベースの同期機能を提供します。これを使うことでプロジェクトを他の人と共有し、共同で作業をすることができます。 + + Sync projects with your desktop computer and work collaboratively with others by logging in to your %1Mergin Maps%2 account. + %1Mergin Maps%2アカウントにログインすることで、デスクトップコンピュータとプロジェクトを同期し、他のユーザーと共同作業を行うことができます。 - + Username ユーザ名 - + Sign in サインイン - + Sign up for free 無料でサインアップ - + Forgot password? パスワードをお忘れですか? @@ -766,60 +977,101 @@ Won't be added to the project. MainPanel - - + + Projects プロジェクト - - + + GPS GPS - - + + Record 記録 - - + + Zoom to project プロジェクトにズーム - - Browse data - データの閲覧 + + + Local changes + ローカルの変更 + + + + + Layers + レイヤ - - + + Map themes 地図テーマ - - + + + Position tracking + 位置の追跡 + + + + Settings 設定 - + More さらに - + Menu メニュー + + + ManageInvitationsPage + + + Join a workspace + ワークスペースに参加 + + + + You have been invited to the following workspaces: + 次のワークスペースに招待されています: + + + + Workspace + ワークスペース + + + + Accept + 受け入れる + + + + Do you want to create a new workspace instead? + 代わりに新しいワークスペースを作成しますか? + - - Browse features - 地物の閲覧 + + Click here! + ここをクリック! @@ -830,7 +1082,7 @@ Won't be added to the project. 地図テーマ - + Project has no themes defined. See %1how to setup themes%2. プロジェクトに定義されたテーマがありません。%1テーマのセットアップの仕方%2をご覧ください。 @@ -838,154 +1090,452 @@ Won't be added to the project. MapWrapper - - - GPS currently unavailable.%1Try to allow GPS Location in your device settings. - GPSは現在使用できません。%1デバイスの設定でGPSロケーションを許可してください。 + + GPS currently unavailable. + GPSは現在使用できません。 - - Recorded feature is not valid - 記録された地物は有効ではありません + + Successfully synchronized + 同期に成功しました - - Low GPS position accuracy (%1 m)<br><br>Please make sure you have good view of the sky. - GPSの位置精度が低いです (%1 m)<br><br>空の見晴らしの良いところで使用してください。 + + Up to date + 更新する - - - PanelHeader - - Cancel - キャンセル + + Somebody else is syncing, we will try again later + 他の人が同期中なので、後で再試行します - - - PasswordField - - Password - パスワード + + There was an issue during synchronization, we will try again. Click to learn more + 同期中に問題が発生しました。後に再試行します。クリックして詳細を見る - - - PositionKit - - Unable to create default GPS Position Source - GPS位置情報をデフォルトで作成できません + + Splitting done successfully + 分割に成功しました - - - PreviewPanel - - No map tip available. - マップチップはありません + + Create line to split the selected feature + 選択した地物を分割するラインを作成 - - - ProjectDelegateItem - - Synchronize project - プロジェクトを同期 + + Select some point to start editing the geometry + ジオメトリの編集を開始するポイントを選択します。 - - Local changes - ローカルの変更 + + Record new geometry for the feature + 地物の新しいジオメトリを記録する - - Remove from device - デバイスから削除 + + Details + 詳細 - - Upload to Mergin - Merginにアップロード + + Back + 戻る - - Download from Mergin - Merginからダウンロード + + Discard the changes? + 変更を破棄しますか? - - Could not synchronize project, please make sure you are logged in and have sufficient rights. - プロジェクトを同期できませんでした。十分な権限を持ってログインしているか確認してください。 + + Clicking ‘Yes’ discards your changes to the geometry. If you would like to save the changes instead, hit ‘No’ and then ‘Done’ in the toolbar. + 「はい」をクリックすると、ジオメトリへの変更が破棄されます。代わりに変更を保存したい場合は、ツールバーの「いいえ」をクリックし、次に「完了」をクリックします。 - - - ProjectIssuesPanel - - Project Issues - プロジェクトの課題 + + Clicking ‘Yes’ discards your new geometry and no feature will be saved. If you would like to save the geometry instead, hit ‘No’ and then ‘Done’ in the toolbar. + 「はい」をクリックすると新しいジオメトリは破棄され、フィーチャーは保存されません。ジオメトリを保存したい場合は、ツールバーの「いいえ」、「完了」の順にクリックします。 - - QGIS log - QGISログ + + Connecting to %1 + %1に接続中 + + + + Connected, no position + 接続完了、位置情報はありません + + + + Unknown accuracy + 不明な精度 - ProjectList + MerginApi - - - Create project - プロジェクトを作成 + + Username must have at least 4 characters + ユーザー名は4文字以上でなければなりません。 - - No downloaded projects found.%1Learn %2how to create projects%3 and %4download them%3 onto your device. - ダウンロードされたプロジェクトはありません。%2プロジェクトの作り方%3 とデバイスへの %4ダウンロードの方法%3 を%1学びましょう。 + + Username contains invalid characters + ユーザー名に無効な文字が含まれています - - You can also create new project by clicking button below. - 下のボタンをクリックして、新しいプロジェクトを作成することもできます。 + + Please enter a valid email + 正しいメールを入力して下さい - - Unable to get the list of projects. - プロジェクトのリストを取得できません + + Password not strong enough. It must%1 be at least 8 characters long%1 contain lowercase characters%1 contain uppercase characters%1 contain digits or special characters + パスワードの強度が十分ではありません。少なくとも以下の要素を満たす必要があります。%1 8文字以上の長さ%1 小文字を含む%1 大文字を含む%1 数字または特殊文字を含む - - No projects found! - プロジェクトが見つかりません! + + Passwords do not match + パスワードが一致しません。 - - Retry - リトライ + + Please accept Terms and Privacy Policy + 利用規約と個人情報保護についてに同意してください。 - - Remove project - プロジェクトを削除 + + Registration successful + 登録が成功しました - - Any unsynchronized changes will be lost. - 同期されていない変更は失われます。 + + New registrations are not allowed on the selected Mergin server.%1Please check with your administrator. + 選択したMerginサーバーでは新規登録ができません。%1 管理者にご確認ください。 - - Download project - プロジェクトをダウンロード + + Project detached from Mergin + Merginから切り離されたプロジェクト - - Would you like to download the project - %1 ? - プロジェクトをダウンロードしますか - %1 ? + + Workspace name contains invalid characters + ワークスペース名に無効な文字が含まれています + + + + Workspace %1 already exists + ワークスペース %1 は既に存在しています。 + + + + MerginProjectStatusModel + + + Pending Changes + 保留している変更 + + + + Failed to determine changes + 変更点の判別に失敗しました + + + + MigrateToMerginDialog + + + Upload project to Mergin? + プロジェクトをMerginにアップロードしますか? + + + + This project is currently not uploaded on Mergin. Upload it to Mergin in order to activate synchronization and collaboration. +Click 'Yes' to upload it. + このプロジェクトは現在Merginにアップロードされていません。同期とコラボレーションを有効にするためにMerginにアップロードしてください。 +「はい」をクリックしてアップロードしてください。 + + + + MissingAuthDialog + + + Sign in to Mergin + Merginにサインイン + + + + You need to be signed in to your Mergin account in order to synchronize a project. Hit 'Yes' to sign in. + プロジェクトを同期するには、Merginアカウントにサインインする必要があります。「はい」を押してサインインしてください。 + + + + NoPermissionsDialog + + + No rights to access the project + プロジェクトにアクセスする権利がありません + + + + You are not allowed to synchronize your changes. Contact the Mergin project owner to assign you the correct permission. If you are the project owner, log into Mergin dashboard. + 変更を同期することは許可されていません。Merginプロジェクトオーナーに連絡して、正しい権限を割り当ててもらってください。あなたがプロジェクトオーナーの場合、Merginダッシュボードにログインしてください。 + + + + NoWorkspaceBanner + + + %1Workspace is required to use Mergin Maps. Click here to create one%2. + Merginマップを使用するには%1ワークスペースが必要です。作成するにはここをクリックしてください%2。 + + + + PanelHeader + + + Cancel + キャンセル + + + + PasswordField + + + Password + パスワード + + + + PositionProviderPage + + + GPS receivers + GPS受信機 + + + + Internal receivers + 内蔵受信機 + + + + External receivers + 外付け受信機 + + + + Unknown device + 不明なデバイス + + + + Connect new receiver + 新しい受信機を接続 + + + + Connecting to receivers via Bluetooth directly in Input is not possible on iOS. Your hardware vendor may provide a custom app that connects to the receiver and sets position. Input will still think it is the internal GPS of your phone/tablet.%1%2Click here to learn more.%3 + iOSでは、Inputで直接Bluetooth経由でレシーバーに接続することはできません。ハードウェアベンダーが、レシーバーに接続して位置を設定するカスタムアプリを提供している場合があります。Inputはまだあなたの携帯電話/タブレットの内蔵GPSだと考えています。%1%2詳細はこちらをクリックしてください。%3 + + + + Remove receiver + 受信機を取り外す + + + + Do you want to remove receiver from the list of recent receivers? + 最近の受信機リストから受信機を削除しますか? + + + + Internal + 内蔵 + + + + PositionProvidersModel + + + Internal + 内蔵 + + + + GPS receiver of this device + このデバイスのGPS受信機 + + + + Bluetooth device + ブルートゥース機器 + + + + Bluetooth device + ブルートゥース機器 + + + + PositionTrackingDrawer + + + Position tracking + 位置の追跡 + + + + Mergin Maps can track your position on this project. + Mergin Mapsはこのプロジェクトで現在位置を追跡することができます。 + + + + Stop tracking + 追跡の停止 + + + + Start tracking + 追跡を開始 + + + + PositionTrackingManager + + + Could not find tracking layer for the project + プロジェクトの追跡レイヤーが見つかりません + + + + Tracking layer not found or invalid + 追跡レイヤーが見つからないか、無効です + + + + Failed to start tracking, please contact support + 追跡の開始に失敗しました。サポートに連絡してください + + + + PreviewPanel + + + No map tip available. + マップチップはありません + + + + ProjectDelegateItem + + + Synchronize project + プロジェクトを同期 + + + + Local changes + ローカルの変更 + + + + Remove from device + デバイスから削除 + + + + Upload to Mergin + Merginにアップロード + + + + Download from Mergin + Merginからダウンロード + + + + Could not synchronize project, please make sure you are logged in and have sufficient rights. + プロジェクトを同期できませんでした。十分な権限を持ってログインしているか確認してください。 + + + + ProjectIssuesPanel + + + The following layers failed loading + 以下のレイヤーは読み込みに失敗した + + + + Project Issues + プロジェクトの課題 + + + + QGIS log + QGISログ + + + + ProjectList + + + + Create project + プロジェクトを作成 + + + + No downloaded projects found.%1Learn %2how to create projects%3 and %4download them%3 onto your device. + ダウンロードされたプロジェクトはありません。%2プロジェクトの作り方%3 とデバイスへの %4ダウンロードの方法%3 を%1学びましょう。 + + + + You can also create new project by clicking button below. + 下のボタンをクリックして、新しいプロジェクトを作成することもできます。 + + + + Unable to get the list of projects. + プロジェクトのリストを取得できません + + + + No projects found! + プロジェクトが見つかりません! + + + + Retry + リトライ + + + + Remove project + プロジェクトを削除 + + + + Any unsynchronized changes will be lost. + 同期されていない変更は失われます。 + + + + Download project + プロジェクトをダウンロード + + + + Would you like to download the project + %1 ? + プロジェクトをダウンロードしますか + %1 ? @@ -999,40 +1549,59 @@ Won't be added to the project. ProjectPanel - + No Changes 変更はありません - + + + Projects プロジェクト - + + Home ホーム - + My projects プロジェクト - + Shared with me 共有プロジェクト - + Shared 共有 - + + Explore 探す + + + Downloaded projects + ダウンロードされたプロジェクト + + + + Public projects + 公開プロジェクト + + + + Your other projects are accessible%1by switching your workspace here + ワークスペースをここに切り替えると、%1他のプロジェクトにアクセスできます。 + ProjectStatusPanel @@ -1050,7 +1619,12 @@ Won't be added to the project. ProjectWizard - + + Project name contains invalid characters + プロジェクト名に無効な文字が含まれています + + + Project %1 created プロジェクト %1 が作成されました @@ -1058,32 +1632,32 @@ Won't be added to the project. ProjectWizardPage - + Create Project プロジェクトを作成 - + Project name プロジェクト名 - + Fields フィールド - + Add field 追加する - + Create project プロジェクトを作成 - + Empty project name プロジェクト名が未入力です @@ -1091,8 +1665,8 @@ Won't be added to the project. ProjectsModel - - + + Updated %1 %1 を更新しました @@ -1100,27 +1674,27 @@ Won't be added to the project. Purchasing - + Failed to process payment details.%1Subscription is not purchased. 支払い処理できませんでした。%1サブスクリプションは購入されませんでした。 - + Successfully restored your subscription サブスクリプションを復元しました - + Successfully purchased subscription サブスクリプションを購入しました - + Failed to purchase subscription サブスクリプションの購入に失敗しました - + Unable to restore your subscription サブスクリプションを復元できませんでした @@ -1128,22 +1702,22 @@ Won't be added to the project. PurchasingPlan - + Monthly subscription 月間サブスクリプション - + Annual subscription 年間サブスクリプション - + month - + year @@ -1151,110 +1725,157 @@ Won't be added to the project. QObject - + Value must be a number 値は数値である必要があります - + Value must be lower than %1 値は %1 よりも小さい必要があります - + Value must be higher than %1 値は %1 よりも大きい必要があります - + Value is too large 値が大きすぎます - + Field can not contain decimal places フィールドには小数点以下を含めることはできません - + Can not be longer than %1 characters %1 文字以下である必要があります - + Field should not be empty フィールドが未入力です - + Field must not be empty フィールドは必須項目です - + Value should be unique 値はユニークである必要があります - + Value must be unique 値はユニークでなければなりません - - + + Unmet QGIS expression constraint QGIS式の制約を満たしていません - + Not a valid value 有効な値ではありません - - - QgsQuickMapCanvasMap - - Rendering - 描画しています + + No data + データがありません + + + + No fix + 修正はありません + + + + GPS fix, no correction data + GPSが修正されました、補正データはありません + + + + DGPS fix + DGPSが修正されました + + + + PPS fix + PPSが修正されました + + + + RTK fix + RTKが修正されました + + + + RTK float + RTKがフローティングしています - - - QgsQuickMapSettings - - - Map Canvas rotation is not supported. Resetting from %1 to 0. - 地図キャンバスの回転はサポートされていません. %1 を 0にリセットします. + + Estimated fix (dead reckoning) + 推定フィックス(推測航法) + + + + Unknown fix + 不明な修正 - RecordToolbar + RecordingToolbar - + GPS GPS - + Undo - 実行取り消し + 取り消し - - Add Point - 点の追加 + + Remove + 削除 - + + Add + 追加 + + + + Release + リリース + + + Done 完了 + + + RecordingTools - - Cancel - キャンセル + + Low GPS position accuracy (%1 m)<br><br>Please make sure you have good view of the sky. + GPSの位置精度が低いです (%1 m)<br><br>空の見晴らしの良いところで使用してください。 + + + + + GPS currently unavailable. + GPSは現在使用できません。 @@ -1301,79 +1922,218 @@ Won't be added to the project. 検索 + + SearchBoxV2 + + + Search + 検索 + + + + SettingsComboBoxItem + + + Time elapsed + 経過時間 + + + + Distance traveled + 移動距離 + + + + SettingsHeaderItem + + + New! + 新機能! + + SettingsPanel - + Settings 設定 - + GPS GPS - + Follow GPS with map GPSに追従する - + GPS accuracy GPS精度 - + Accuracy threshold 精度の閾値 - + Show accuracy warning 精度の警告を表示 - + + Select GPS receiver + GPS受信機を選択 + + + + GPS antenna height + GPSアンテナの高さ + + + + Includes pole height and GPS receiver's antenna height + ポールの高さとGPS受信機のアンテナの高さを含む + + + + Streaming mode + ストリーミング・モード + + + + Interval type + インターバル・タイプ + + + + Choose action when to add a new point + 新しいポイントを追加する際のアクションを選択する + + + + in meters + メートル単位 + + + + in seconds + 秒単位 + + + Recording 記録 - + Line rec. interval ラインを記録する間隔 - + Reuse last value option 最後の値を再利用する - + + Automatically sync changes + 変更を自動的に同期 + + + About このアプリについて - + Help ヘルプ - + Privacy policy 個人情報保護について - - Mergin terms of service - Mergin利用規約 + + Terms of service + 利用規約 - + Diagnostic log 診断ログ + + SimulatedPositionProvider + + + Connected + 接続されました + + + + SplittingFailedDialog + + + We could not split the feature + 地物を分割することができませんでした + + + + Please make sure that the split line crosses your feature. The feature needs to have a valid geometry in order to split it. + 分割線が地物を横切っていることを確認してください。地物を分割するには、その地物に有効なジオメトリが必要です。 + + + + SplittingToolbar + + + Undo + 取り消し + + + + Add Point + 点の追加 + + + + Done + 完了 + + + + SplittingTools + + + You need to add at least 2 points. + 少なくとも2点を加える必要があります。 + + + + StakeoutPanel + + + Stake out + ステイクアウト + + + + Feature + 地物 + + + + Distance + 距離 + + StorageLimitDialog @@ -1415,19 +2175,19 @@ Won't be added to the project. サブスクライブ - - + + Individual 個人 - - + + Professional プロフェッショナル - + Your Mergin subscription plan will renew automatically. You can cancel or change it at any time. %1Learn More%2 Merginのサブスクリプションのプランは自動で更新されます。いつでもキャンセルできます。 %1詳細を見る%2 @@ -1455,20 +2215,274 @@ Won't be added to the project. 電子メールサポート + + SwitchWorkspacePage + + + Select a workspace + ワークスペースを選択 + + + + You have a pending invitation + 保留中の招待があります + + + + Workspace + ワークスペース + + + + Accept + 受け入れる + + + + Reject + 拒否 + + + + Workspaces + ワークスペース + + + + Create new workspace + 新規のワークスペースを作成 + + + + SyncFailedDialog + + + Failed to synchronize your changes + 変更の同期に失敗しました + + + + Your changes could not be sent to server, make sure you are connected to internet and have write access to this project. + 変更がサーバーに送信されませんでした。インターネットに接続され、このプロジェクトへの書き込み権限があることを確認してください。 + + + + WhatsNewDialog + + + What's new + 新着情報 + + + + Ignore + 無視する + + + + Read more + 続きを読む + + + + WorkspaceAccountPage + + + My Account + マイアカウント + + + + Workspace + ワークスペース + + + + Switch workspace + ワークスペースを切り替え + + + + Your role + ロール + + + + Workspace storage + ワークスペースのストレージ + + + + Using %1 / %2 + %1 / %2 利用中 + + + + Subscription plan + サブスクリプションプラン + + + + + + + Subscription status + サブスクリプション・ステータス + + + + Your subscription will not auto-renew after %1 + サブスクリプションは %1 を過ぎても自動更新されません + + + + Please update your %1billing details%2 as soon as possible + できるだけ早く %1支払いの詳細%2 についてアップデートしてください。 + + + + Your next bill will be for %1 on %2 + 次の %1 の請求は %2 に行われます。 + + + + Your subscription was cancelled on %1 + サブスクリプションは %1 でキャンセルされました + + + + Subscriptions + サブスクリプション + + + + Account + アカウント + + + + Username + ユーザ名 + + + + Email + 電子メール + + + + Sign out + サインアウト + + + + Delete account + アカウントを削除 + + + + Delete account? + アカウントを削除しますか? + + + + This action will delete your Mergin Maps account with all your projects, both on the device and on the server. This action cannot be undone. If you have an Apple subscription you need to cancel it manually. + +In order to delete your account, enter your username in the field below and click Yes. + この操作によって、あなたのMergin Mapsアカウントと、デバイス上とサーバー上のすべてのプロジェクトが削除されます。この操作は元に戻せません。Appleのサブスクリプションをお持ちの場合は、手動でキャンセルする必要があります。 + +アカウントを削除するには、下のフィールドにユーザー名を入力し、はいをクリックします。 + + + + Enter username + ユーザ名を入力 + + + + Failed to remove account + アカウントの削除に失敗しました + + + + An error occured while removing your account + アカウント削除中にエラーが起きました + + + + Can not close account because user is the only owner of an organisation. + +Please go to the Mergin Maps website to remove it manually. + ユーザーが組織の唯一の所有者であるため、アカウントを閉じることができません。 + +Mergin Mapsのウェブサイトから手動で削除してください。 + + + + WorkspaceSubscribePage + + + Subscribe + サブスクライブ + + + + Individual + 個人 + + + + Professional + プロフェッショナル + + + + You can also %1restore%2 your purchases. + 購入したサブスクリプションを %1復元%2 することができます。 + + + + Your Mergin subscription plan will renew automatically. You can cancel or change it at any time. %1Learn More%2 + Merginのサブスクリプションのプランは自動で更新されます。いつでもキャンセルできます。 %1詳細を見る%2 + + + + WorkspaceSubscribePlanItem + + + Commercial use + 商業利用 + + + + Unlimited seats + ユーザー数無制限 + + + + Unlimited projects + プロジェクト数無制限 + + + + Email support + 電子メールサポート + + inputexternalresource - + Take a photo 写真撮影 - + From gallery ギャラリーから - + Image is not available: 画像はありません @@ -1476,17 +2490,17 @@ Won't be added to the project. inputrelation - + %1 more さらに %1 - + Add 追加 - + Linked features リンクされた地物 @@ -1510,32 +2524,64 @@ Won't be added to the project. main - + + + No Changes + 変更はありません + + + GPS auto-center mode on GPS自動センターモードをON - + GPS auto-center mode off GPS自動センターモードをOFF - + No editable layers found. 編集可能なレイヤがみつかりません. - + + + not tracking + 追跡していません + + + + Stake out is disabled because location is unavailable! + 位置情報が利用できないため、ステイクアウトは利用できません! + + + + Failed to open the project + プロジェクトを開けませんでした + + + Failed to communicate with Mergin.%1Try improving your network connection. Merginとの通信に失敗しました。%1 インターネット状況の確認をしてください。 - - Communication error - 通信エラー + + There were issues loading the project. + プロジェクトを読み込む上で問題が発生しました。 + + + + Could not read the project file: + プロジェクトファイルを読み込めませんでした: + + + + Press back again to quit the app + アプリを終了するには、もう一度戻るを押してください - + PROJ Error 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