diff --git a/resources/sample_projects/bees.qgz.jpg b/resources/sample_projects/bees.qgz.jpg index 4750995062..dd145c2356 100644 Binary files a/resources/sample_projects/bees.qgz.jpg and b/resources/sample_projects/bees.qgz.jpg differ diff --git a/resources/sample_projects/datasets/qgep_reach.gpkg b/resources/sample_projects/datasets/qgep_reach.gpkg index b035b3adba..8a1f67e917 100644 Binary files a/resources/sample_projects/datasets/qgep_reach.gpkg and b/resources/sample_projects/datasets/qgep_reach.gpkg differ diff --git a/resources/sample_projects/datasets/qgep_wastewater_structure.gpkg b/resources/sample_projects/datasets/qgep_wastewater_structure.gpkg index 4a6f83e29e..c37e66e76a 100644 Binary files a/resources/sample_projects/datasets/qgep_wastewater_structure.gpkg and b/resources/sample_projects/datasets/qgep_wastewater_structure.gpkg differ diff --git a/resources/sample_projects/live_qfield_users_survey.qgs.jpg b/resources/sample_projects/live_qfield_users_survey.qgs.jpg index 4a6973aa9a..063f4e2e83 100644 Binary files a/resources/sample_projects/live_qfield_users_survey.qgs.jpg and b/resources/sample_projects/live_qfield_users_survey.qgs.jpg differ diff --git a/resources/sample_projects/wastewater.qgz b/resources/sample_projects/wastewater.qgz index bbd217ba36..9c0aff519a 100644 Binary files a/resources/sample_projects/wastewater.qgz and b/resources/sample_projects/wastewater.qgz differ diff --git a/resources/sample_projects/wastewater.qgz.jpg b/resources/sample_projects/wastewater.qgz.jpg index 2127b1dad2..199301adb6 100644 Binary files a/resources/sample_projects/wastewater.qgz.jpg and b/resources/sample_projects/wastewater.qgz.jpg differ diff --git a/resources/templates/layout.qpt b/resources/templates/layout.qpt new file mode 100644 index 0000000000..cc840c8fc0 --- /dev/null +++ b/resources/templates/layout.qpt @@ -0,0 +1,572 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/core/processing/processingalgorithm.cpp b/src/core/processing/processingalgorithm.cpp index 59c4aeb50c..98bef2cb56 100644 --- a/src/core/processing/processingalgorithm.cpp +++ b/src/core/processing/processingalgorithm.cpp @@ -177,7 +177,7 @@ bool ProcessingAlgorithm::run( bool previewMode ) -1, Qgis::ProcessingFeatureSourceDefinitionFlags(), Qgis::InvalidGeometryCheck(), - QStringLiteral( "$id IN (%1)" ).arg( featureIds.join( ',' ) ) ); + QStringLiteral( "@id IN (%1)" ).arg( featureIds.join( ',' ) ) ); parameters[QStringLiteral( "OUTPUT" )] = QStringLiteral( "memory:" ); if ( !previewMode ) @@ -273,7 +273,7 @@ bool ProcessingAlgorithm::run( bool previewMode ) -1, Qgis::ProcessingFeatureSourceDefinitionFlags(), Qgis::InvalidGeometryCheck(), - QStringLiteral( "$id IN (%1)" ).arg( featureIds.join( ',' ) ) ); + QStringLiteral( "@id IN (%1)" ).arg( featureIds.join( ',' ) ) ); parameters[QStringLiteral( "OUTPUT" )] = QStringLiteral( "memory:" ); bool ok; diff --git a/src/core/qgismobileapp.cpp b/src/core/qgismobileapp.cpp index cb277f427b..ed137463fa 100644 --- a/src/core/qgismobileapp.cpp +++ b/src/core/qgismobileapp.cpp @@ -158,6 +158,7 @@ #include #include #include +#include #include #include #include @@ -1029,6 +1030,7 @@ void QgisMobileapp::readProjectFile() mProject->setCrs( crs ); mProject->setEllipsoid( crs.ellipsoidAcronym() ); mProject->setTitle( mProjectFileName ); + mProject->setPresetHomePath( fi.absolutePath() ); mProject->writeEntry( QStringLiteral( "QField" ), QStringLiteral( "isDataset" ), true ); for ( QgsMapLayer *l : std::as_const( rasterLayers ) ) @@ -1245,12 +1247,40 @@ bool QgisMobileapp::print( const QString &layoutName ) { const QList printLayouts = mProject->layoutManager()->printLayouts(); QgsPrintLayout *layoutToPrint = nullptr; - for ( QgsPrintLayout *layout : printLayouts ) + std::unique_ptr templateLayout; + if ( layoutName.isEmpty() && printLayouts.isEmpty() ) { - if ( layout->name() == layoutName ) + QFile templateFile( QStringLiteral( "%1/qfield/templates/layout.qpt" ).arg( PlatformUtilities::instance()->systemSharedDataLocation() ) ); + QDomDocument templateDoc; + templateDoc.setContent( &templateFile ); + + templateLayout = std::make_unique( QgsProject::instance() ); + bool loadedOK = false; + QList items = templateLayout->loadFromTemplate( templateDoc, QgsReadWriteContext(), true, &loadedOK ); + if ( !loadedOK ) { - layoutToPrint = layout; - break; + return false; + } + + for ( QgsLayoutItem *item : items ) + { + if ( item->type() == QgsLayoutItemRegistry::LayoutLabel && item->id() == QStringLiteral( "Title" ) ) + { + QgsLayoutItemLabel *labelItem = qobject_cast( item ); + labelItem->setText( tr( "Map printed on %1 using QField" ).arg( "[%format_date(now(), 'yyyy-MM-dd @ hh:mm')%]" ) ); + } + } + layoutToPrint = templateLayout.get(); + } + else + { + for ( QgsPrintLayout *layout : printLayouts ) + { + if ( layout->name() == layoutName || layoutName.isEmpty() ) + { + layoutToPrint = layout; + break; + } } } @@ -1324,7 +1354,7 @@ bool QgisMobileapp::printAtlasFeatures( const QString &layoutName, const QListatlas()->filterExpression(); const bool priorFilterFeatures = layoutToPrint->atlas()->filterFeatures(); - layoutToPrint->atlas()->setFilterExpression( QStringLiteral( "$id IN (%1)" ).arg( ids.join( ',' ) ), error ); + layoutToPrint->atlas()->setFilterExpression( QStringLiteral( "@id IN (%1)" ).arg( ids.join( ',' ) ), error ); layoutToPrint->atlas()->setFilterFeatures( true ); layoutToPrint->atlas()->updateFeatures(); diff --git a/src/qml/qgismobileapp.qml b/src/qml/qgismobileapp.qml index 90741a4221..b1053c6342 100644 --- a/src/qml/qgismobileapp.qml +++ b/src/qml/qgismobileapp.qml @@ -2488,16 +2488,11 @@ ApplicationWindow { onShowPrintLayouts: p => { if (layoutListInstantiator.count > 1) { printMenu.popup(p.x, p.y); - } else if (layoutListInstantiator.count === 1) { + } else { mainMenu.close(); displayToast(qsTr('Printing...')); - printMenu.printName = layoutListInstantiator.model.titleAt(0); + printMenu.printName = layoutListInstantiator.count === 1 ? layoutListInstantiator.model.titleAt(0) : ""; printMenu.printTimer.restart(); - } else { - mainMenu.close(); - toast.show(qsTr('No print layout available'), 'info', qsTr('Learn more'), function () { - Qt.openUrlExternally('https://docs.qfield.org/how-to/print-to-pdf/'); - }); } } @@ -3113,7 +3108,7 @@ ApplicationWindow { height: 48 onTriggered: { - featureForm.model.setFeatures(menu.featureLayer, '$id = ' + menu.fid); + featureForm.model.setFeatures(menu.featureLayer, '@id = ' + menu.fid); featureForm.selection.focusedItem = 0; featureForm.state = "FeatureForm"; } @@ -3140,7 +3135,7 @@ ApplicationWindow { height: 48 onTriggered: { - featureForm.model.setFeatures(menu.featureLayer, '$id = ' + menu.fid); + featureForm.model.setFeatures(menu.featureLayer, '@id = ' + menu.fid); featureForm.selection.focusedItem = 0; featureForm.multiSelection = true; featureForm.selection.toggleSelectedItem(0);