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);