diff --git a/cmake/FindPyQt5.cmake b/cmake/FindPyQt5.cmake index 72e998e6efba..18322e92192b 100644 --- a/cmake/FindPyQt5.cmake +++ b/cmake/FindPyQt5.cmake @@ -47,13 +47,13 @@ ELSE(EXISTS PYQT5_VERSION) ENDIF(pyqt_config) IF(PYQT5_FOUND) - IF(NOT PYQT5_FIND_QUIETLY) + IF(NOT PyQt5_FIND_QUIETLY) MESSAGE(STATUS "Found PyQt5 version: ${PYQT5_VERSION_STR}") ENDIF(NOT PYQT5_FIND_QUIETLY) ELSE(PYQT5_FOUND) - IF(PYQT5_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find Python") - ENDIF(PYQT5_FIND_REQUIRED) + IF(PyQt5_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find PyQt5") + ENDIF(PyQt5_FIND_REQUIRED) ENDIF(PYQT5_FOUND) ENDIF(EXISTS PYQT5_VERSION) diff --git a/cmake/FindPyQt5.py b/cmake/FindPyQt5.py index b37f8a67acd9..c4df8591921e 100644 --- a/cmake/FindPyQt5.py +++ b/cmake/FindPyQt5.py @@ -52,6 +52,8 @@ if os.path.exists(os.path.join(p, "QtCore", "QtCoremod.sip")): sip_dir = p break + else: + sys.exit(1) cfg = { 'pyqt_version': PyQt5.QtCore.PYQT_VERSION, 'pyqt_version_str': PyQt5.QtCore.PYQT_VERSION_STR, diff --git a/debian/control.in b/debian/control.in index eb017936e4de..4a7b900d2ee4 100644 --- a/debian/control.in +++ b/debian/control.in @@ -462,19 +462,93 @@ Description: collection of data providers to QGIS - architecture-independent fil Package: qgis-server Architecture: any +Depends: + qgis-server-dummy (= ${binary:Version}), + qgis-server-wms (= ${binary:Version}), + qgis-server-wcs (= ${binary:Version}), + qgis-server-wfs (= ${binary:Version}), + qgis-server-wfs3 (= ${binary:Version}), + qgis-server-common (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: QGIS server providing various OGC services + QGIS is a Geographic Information System (GIS) which manages, analyzes and + display databases of geographic information. + . + This package is a meta-package depending on all QGIS Server components. + +Package: qgis-server-common +Architecture: any Depends: qgis-providers (= ${binary:Version}), python3-qgis (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} -Conflicts: qgis-mapserver -Provides: qgis-mapserver -Replaces: qgis-mapserver Description: QGIS server providing various OGC services QGIS is a Geographic Information System (GIS) which manages, analyzes and display databases of geographic information. . - This package contains the QGIS server. + This package contains the common QGIS server parts. + +Package: qgis-server-wms +Architecture: any +Depends: + qgis-server-common (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: QGIS server providing various OGC services + QGIS is a Geographic Information System (GIS) which manages, analyzes and + display databases of geographic information. + . + This package contains the wms service. + +Package: qgis-server-wfs +Architecture: any +Depends: + qgis-server-common (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: QGIS server providing various OGC services + QGIS is a Geographic Information System (GIS) which manages, analyzes and + display databases of geographic information. + . + This package contains the wfs service. + +Package: qgis-server-wfs3 +Architecture: any +Depends: + qgis-server-common (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: QGIS server providing various OGC services + QGIS is a Geographic Information System (GIS) which manages, analyzes and + display databases of geographic information. + . + This package contains the wfs 3 service. + +Package: qgis-server-wcs +Architecture: any +Depends: + qgis-server-common (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: QGIS server providing various OGC services + QGIS is a Geographic Information System (GIS) which manages, analyzes and + display databases of geographic information. + . + This package contains the wcs service. + +Package: qgis-server-dummy +Architecture: any +Depends: + qgis-server-common (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: QGIS server providing various OGC services + QGIS is a Geographic Information System (GIS) which manages, analyzes and + display databases of geographic information. + . + This package contains the sample service. Package: qgis-api-doc Architecture: all diff --git a/debian/qgis-server.install b/debian/qgis-server-common.install similarity index 85% rename from debian/qgis-server.install rename to debian/qgis-server-common.install index 247ceb00a343..75b95fa115ec 100644 --- a/debian/qgis-server.install +++ b/debian/qgis-server-common.install @@ -1,6 +1,5 @@ usr/lib/cgi-bin/admin.sld usr/lib/cgi-bin/qgis_mapserv.fcgi usr/lib/cgi-bin/wms_metadata.xml -usr/lib/qgis/server/*.so usr/share/qgis/resources/server/ usr/bin/qgis_mapserver diff --git a/debian/qgis-server-dummy.install b/debian/qgis-server-dummy.install new file mode 100644 index 000000000000..478159ce729b --- /dev/null +++ b/debian/qgis-server-dummy.install @@ -0,0 +1 @@ +usr/lib/qgis/server/libdummy.so diff --git a/debian/qgis-server-wcs.install b/debian/qgis-server-wcs.install new file mode 100644 index 000000000000..99c992a3e1f0 --- /dev/null +++ b/debian/qgis-server-wcs.install @@ -0,0 +1 @@ +usr/lib/qgis/server/libwcs.so diff --git a/debian/qgis-server-wfs.install b/debian/qgis-server-wfs.install new file mode 100644 index 000000000000..b46988a76458 --- /dev/null +++ b/debian/qgis-server-wfs.install @@ -0,0 +1 @@ +usr/lib/qgis/server/libwfs.so diff --git a/debian/qgis-server-wfs3.install b/debian/qgis-server-wfs3.install new file mode 100644 index 000000000000..5e271f97b5b2 --- /dev/null +++ b/debian/qgis-server-wfs3.install @@ -0,0 +1 @@ +usr/lib/qgis/server/libwfs3.so diff --git a/debian/qgis-server-wms.install b/debian/qgis-server-wms.install new file mode 100644 index 000000000000..fb127b776cc4 --- /dev/null +++ b/debian/qgis-server-wms.install @@ -0,0 +1 @@ +usr/lib/qgis/server/libwms.so diff --git a/debian/qgis-server-wmts.install b/debian/qgis-server-wmts.install new file mode 100644 index 000000000000..c72ff0283cf3 --- /dev/null +++ b/debian/qgis-server-wmts.install @@ -0,0 +1 @@ +usr/lib/qgis/server/libwmts.so diff --git a/debian/rules b/debian/rules index 74d0d9aca819..18ec3c3e90e8 100755 --- a/debian/rules +++ b/debian/rules @@ -120,7 +120,6 @@ ifneq (,$(findstring $(DISTRIBUTION),"sid buster bionic eoan focal")) -DWITH_3D=TRUE \ -DGEOS_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libgeos_c.so -ifneq (,$(findstring $(DISTRIBUTION),"buster eoan focal")) $(shell test -f /usr/include/$(DEB_BUILD_MULTIARCH)/qt5/Qt3DExtras/qt3dextrasversion.h) ifneq (0,$(.SHELLSTATUS)) # Qt3DExtras intentionally removed from debian (#895386) and in turn ubuntu @@ -129,7 +128,6 @@ ifneq (0,$(.SHELLSTATUS)) -DQT5_3DEXTRA_INCLUDE_DIR=$(realpath external/qt3dextra-headers) \ -DQT5_3DEXTRA_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libQt53DExtras.so endif -endif endif diff --git a/editors/QtCreator/templates/wizards/qgis/qgis_icon.svg b/editors/QtCreator/templates/wizards/qgis/qgis_icon.svg index 97b1461f96f8..0610325ee2e9 100644 --- a/editors/QtCreator/templates/wizards/qgis/qgis_icon.svg +++ b/editors/QtCreator/templates/wizards/qgis/qgis_icon.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/composer/missing_image.svg b/images/composer/missing_image.svg index a39dc84f6911..d508c6ddf7b0 100644 --- a/images/composer/missing_image.svg +++ b/images/composer/missing_image.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/flags/af.svg b/images/flags/af.svg index e3485c3b5352..773eff4a2f6a 100644 --- a/images/flags/af.svg +++ b/images/flags/af.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ar.svg b/images/flags/ar.svg index d2ef938d21cd..1def6ae52f47 100644 --- a/images/flags/ar.svg +++ b/images/flags/ar.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/bg.svg b/images/flags/bg.svg index 7af9ccecca6a..225efdd9c61b 100644 --- a/images/flags/bg.svg +++ b/images/flags/bg.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/flags/bn.svg b/images/flags/bn.svg index aa2bd647bc36..a0540c3bb676 100644 --- a/images/flags/bn.svg +++ b/images/flags/bn.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/bs.svg b/images/flags/bs.svg index e7324ee94de1..9d2326940282 100644 --- a/images/flags/bs.svg +++ b/images/flags/bs.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/flags/ca.svg b/images/flags/ca.svg index 17b7dbc223a0..b825d4f128ab 100644 --- a/images/flags/ca.svg +++ b/images/flags/ca.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/cs.svg b/images/flags/cs.svg index c18c40a31b7f..dbb10890f320 100644 --- a/images/flags/cs.svg +++ b/images/flags/cs.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/cy.svg b/images/flags/cy.svg index d243f715575d..1a797b62e715 100644 --- a/images/flags/cy.svg +++ b/images/flags/cy.svg @@ -1,9 +1,2 @@ - - - height="496.06" width="826.76" - - - - - - \ No newline at end of file +height="496.06" width="826.76" + \ No newline at end of file diff --git a/images/flags/da.svg b/images/flags/da.svg index a030dacbb429..4e6b32c3bf1b 100644 --- a/images/flags/da.svg +++ b/images/flags/da.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/flags/de.svg b/images/flags/de.svg index 8850b87b92eb..ad6754434fb7 100644 --- a/images/flags/de.svg +++ b/images/flags/de.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/flags/el.svg b/images/flags/el.svg index 532046f616fa..e6315843c8bf 100644 --- a/images/flags/el.svg +++ b/images/flags/el.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/en_US.svg b/images/flags/en_US.svg index a11cf5f9475a..dc3b02a3c93e 100644 --- a/images/flags/en_US.svg +++ b/images/flags/en_US.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/eo.svg b/images/flags/eo.svg index b603f74e973c..3a5d48b7074b 100644 --- a/images/flags/eo.svg +++ b/images/flags/eo.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/es.svg b/images/flags/es.svg index fba167dd6057..b10824750207 100644 --- a/images/flags/es.svg +++ b/images/flags/es.svg @@ -1,406 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/et.svg b/images/flags/et.svg index ef0abf4edf7d..4f64c6e3cc36 100644 --- a/images/flags/et.svg +++ b/images/flags/et.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/eu.svg b/images/flags/eu.svg index 9e445aed8a3f..bc8e8705b411 100644 --- a/images/flags/eu.svg +++ b/images/flags/eu.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/fa.svg b/images/flags/fa.svg index d60a8120c90c..9f3708297243 100644 --- a/images/flags/fa.svg +++ b/images/flags/fa.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/fi.svg b/images/flags/fi.svg index e7f293bf3eee..bac31dd816de 100644 --- a/images/flags/fi.svg +++ b/images/flags/fi.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/flags/fr.svg b/images/flags/fr.svg index b50bd7ed409b..8caef36731ef 100644 --- a/images/flags/fr.svg +++ b/images/flags/fr.svg @@ -1,2 +1 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ga.svg b/images/flags/ga.svg index 7f20c1a9ca70..1df55175aa43 100644 --- a/images/flags/ga.svg +++ b/images/flags/ga.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/gd.svg b/images/flags/gd.svg index 6e6100a1dffa..3df704984811 100644 --- a/images/flags/gd.svg +++ b/images/flags/gd.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/gl.svg b/images/flags/gl.svg index 6941199975c9..36971f7e7000 100644 --- a/images/flags/gl.svg +++ b/images/flags/gl.svg @@ -1,785 +1 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/flags/he.svg b/images/flags/he.svg index fedf057297b7..b1f1318fdf47 100644 --- a/images/flags/he.svg +++ b/images/flags/he.svg @@ -1,29 +1 @@ - - - - Flag of Israel - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/hr.svg b/images/flags/hr.svg index 429d77cc4a99..f9f4f22c3be4 100644 --- a/images/flags/hr.svg +++ b/images/flags/hr.svg @@ -1,241 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/hu.svg b/images/flags/hu.svg index 53c88344645b..2895e32b929a 100644 --- a/images/flags/hu.svg +++ b/images/flags/hu.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/id.svg b/images/flags/id.svg index 5d22cd6277ce..316e37260d89 100644 --- a/images/flags/id.svg +++ b/images/flags/id.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/is.svg b/images/flags/is.svg index 54cc6a6c53f6..76e0183c20c4 100644 --- a/images/flags/is.svg +++ b/images/flags/is.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/it.svg b/images/flags/it.svg index 4bab43b4723e..9e731e35fe4b 100644 --- a/images/flags/it.svg +++ b/images/flags/it.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ja.svg b/images/flags/ja.svg index 8f454752469e..f0de0fc2ba34 100644 --- a/images/flags/ja.svg +++ b/images/flags/ja.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ka.svg b/images/flags/ka.svg index 8e3e0189efc9..252cec6db45e 100644 --- a/images/flags/ka.svg +++ b/images/flags/ka.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/flags/km.svg b/images/flags/km.svg index 21c558463335..3223b029116a 100644 --- a/images/flags/km.svg +++ b/images/flags/km.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ko.svg b/images/flags/ko.svg index e48561222bc4..9eed2d37bb1d 100644 --- a/images/flags/ko.svg +++ b/images/flags/ko.svg @@ -1,12 +1 @@ - - -Flag of South Korea - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/lo.svg b/images/flags/lo.svg index 9e1e38a0d3a1..348d5a650180 100644 --- a/images/flags/lo.svg +++ b/images/flags/lo.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/flags/lt.svg b/images/flags/lt.svg index fef5385630d7..007b7fd4d812 100644 --- a/images/flags/lt.svg +++ b/images/flags/lt.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/lv.svg b/images/flags/lv.svg index 46b761b340ee..de4291c29768 100644 --- a/images/flags/lv.svg +++ b/images/flags/lv.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/mn.svg b/images/flags/mn.svg index 220bdb9147a8..4d27da113755 100644 --- a/images/flags/mn.svg +++ b/images/flags/mn.svg @@ -1,11 +1 @@ - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/mt.svg b/images/flags/mt.svg index 5e91347dbae3..fcc3baaf07fb 100644 --- a/images/flags/mt.svg +++ b/images/flags/mt.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/nb.svg b/images/flags/nb.svg index 4b124415c59d..29dfc3b7b757 100644 --- a/images/flags/nb.svg +++ b/images/flags/nb.svg @@ -1,9 +1 @@ - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/nl.svg b/images/flags/nl.svg index f19bd004e5ec..413fa06e83bb 100644 --- a/images/flags/nl.svg +++ b/images/flags/nl.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/pl.svg b/images/flags/pl.svg index dc2f73c5fe97..cb45f5a59f67 100644 --- a/images/flags/pl.svg +++ b/images/flags/pl.svg @@ -1,2 +1 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/pt_BR.svg b/images/flags/pt_BR.svg index c0445bad537e..fefbb2736fa3 100644 --- a/images/flags/pt_BR.svg +++ b/images/flags/pt_BR.svg @@ -1,45 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/flags/pt_PT.svg b/images/flags/pt_PT.svg index 5c19329c526e..c219fb538eb4 100644 --- a/images/flags/pt_PT.svg +++ b/images/flags/pt_PT.svg @@ -1,67 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ro.svg b/images/flags/ro.svg index 63a88cde0dcc..3f0d27ab5bee 100644 --- a/images/flags/ro.svg +++ b/images/flags/ro.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/ru.svg b/images/flags/ru.svg index 855b805a5542..b4bb087fac1b 100644 --- a/images/flags/ru.svg +++ b/images/flags/ru.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/sk.svg b/images/flags/sk.svg index b396baa45842..19402e2ff717 100644 --- a/images/flags/sk.svg +++ b/images/flags/sk.svg @@ -1,13 +1 @@ - - -Flag of Slovakia - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/sl.svg b/images/flags/sl.svg index dcab16baf247..140d93ac2385 100644 --- a/images/flags/sl.svg +++ b/images/flags/sl.svg @@ -1,25 +1 @@ - - - - Flag of Slovenia - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/flags/sq.svg b/images/flags/sq.svg index ff0fbb88f3b3..51d5c5758595 100644 --- a/images/flags/sq.svg +++ b/images/flags/sq.svg @@ -1,27 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/sr.svg b/images/flags/sr.svg index 1d975d314982..fbba77daf320 100644 --- a/images/flags/sr.svg +++ b/images/flags/sr.svg @@ -1,632 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/sv.svg b/images/flags/sv.svg index 521049b4dfef..25681399f748 100644 --- a/images/flags/sv.svg +++ b/images/flags/sv.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/flags/sw.svg b/images/flags/sw.svg index 96ca113ebccb..122ee35d5d49 100644 --- a/images/flags/sw.svg +++ b/images/flags/sw.svg @@ -1,7 +1 @@ - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/th.svg b/images/flags/th.svg index 2e8080055a89..0d8179477371 100644 --- a/images/flags/th.svg +++ b/images/flags/th.svg @@ -1,6 +1 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/tl.svg b/images/flags/tl.svg index a53d724b6ced..6ee48688daa9 100644 --- a/images/flags/tl.svg +++ b/images/flags/tl.svg @@ -1,35 +1 @@ - - - -Flag of the Philippines -Coding according to the official "description and specification of the FILIPINO flag" in Executive Order No. 23 from 1936 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/tr.svg b/images/flags/tr.svg index 19b9becf399a..b6a1c4fc49bd 100644 --- a/images/flags/tr.svg +++ b/images/flags/tr.svg @@ -1,7 +1 @@ - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/uk.svg b/images/flags/uk.svg index d1b537e7c7e9..d4f0011b25b1 100644 --- a/images/flags/uk.svg +++ b/images/flags/uk.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/vi.svg b/images/flags/vi.svg index 36fb2bf82cb2..5bf03d1e1b7d 100644 --- a/images/flags/vi.svg +++ b/images/flags/vi.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/flags/xh.svg b/images/flags/xh.svg index e3485c3b5352..773eff4a2f6a 100644 --- a/images/flags/xh.svg +++ b/images/flags/xh.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/images/flags/zh-Hant.svg b/images/flags/zh-Hant.svg index 0c465cdb08a2..4f772d6d77a4 100644 --- a/images/flags/zh-Hant.svg +++ b/images/flags/zh-Hant.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qbrowser_icon.svg b/images/icons/qbrowser_icon.svg index 3f4faabb203c..c72ed864b859 100644 --- a/images/icons/qbrowser_icon.svg +++ b/images/icons/qbrowser_icon.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_asc_icon.svg b/images/icons/qgis_asc_icon.svg index 25d56cbc3711..25bfb64f08a4 100644 --- a/images/icons/qgis_asc_icon.svg +++ b/images/icons/qgis_asc_icon.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_ddf_icon.svg b/images/icons/qgis_ddf_icon.svg index 71c0e71b38e2..761557bc1444 100644 --- a/images/icons/qgis_ddf_icon.svg +++ b/images/icons/qgis_ddf_icon.svg @@ -1,68 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DDF - +DDF \ No newline at end of file diff --git a/images/icons/qgis_dem_icon.svg b/images/icons/qgis_dem_icon.svg index 2fef6cf94982..ccd2e8da96aa 100644 --- a/images/icons/qgis_dem_icon.svg +++ b/images/icons/qgis_dem_icon.svg @@ -1,66 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DEM - - - - - - - - - - - - - +DEM \ No newline at end of file diff --git a/images/icons/qgis_dt0_icon.svg b/images/icons/qgis_dt0_icon.svg index 7b59d03727a3..a473372c0019 100644 --- a/images/icons/qgis_dt0_icon.svg +++ b/images/icons/qgis_dt0_icon.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_dxf_icon.svg b/images/icons/qgis_dxf_icon.svg index bcb1cc8a6381..4c9f18231d72 100644 --- a/images/icons/qgis_dxf_icon.svg +++ b/images/icons/qgis_dxf_icon.svg @@ -1,66 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_gml_icon.svg b/images/icons/qgis_gml_icon.svg index f505988fd6ff..87f3ab1356d4 100644 --- a/images/icons/qgis_gml_icon.svg +++ b/images/icons/qgis_gml_icon.svg @@ -1,66 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_icon.svg b/images/icons/qgis_icon.svg index 24c0ad96e928..59c3f188b42a 100644 --- a/images/icons/qgis_icon.svg +++ b/images/icons/qgis_icon.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_img_icon.svg b/images/icons/qgis_img_icon.svg index cba951561b3d..b3808e5728b6 100644 --- a/images/icons/qgis_img_icon.svg +++ b/images/icons/qgis_img_icon.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_jp2_icon.svg b/images/icons/qgis_jp2_icon.svg index e21f3f8bd786..9abbbe485a79 100644 --- a/images/icons/qgis_jp2_icon.svg +++ b/images/icons/qgis_jp2_icon.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_mif_icon.svg b/images/icons/qgis_mif_icon.svg index 1fdb98874238..1e1898b64f1a 100644 --- a/images/icons/qgis_mif_icon.svg +++ b/images/icons/qgis_mif_icon.svg @@ -1,66 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_mime_icon.svg b/images/icons/qgis_mime_icon.svg index 96a2a160abe9..4e61e4f2fc17 100644 --- a/images/icons/qgis_mime_icon.svg +++ b/images/icons/qgis_mime_icon.svg @@ -1,39 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_mldata_icon.svg b/images/icons/qgis_mldata_icon.svg index d2b0754e9e0a..ce2b09c780e5 100644 --- a/images/icons/qgis_mldata_icon.svg +++ b/images/icons/qgis_mldata_icon.svg @@ -1,74 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MLDATA - - - - - - - - - - - - - - - - - - - - - +MLDATA \ No newline at end of file diff --git a/images/icons/qgis_qgs_icon.svg b/images/icons/qgis_qgs_icon.svg index 0436e1d5c2af..5eaa7ca280d0 100644 --- a/images/icons/qgis_qgs_icon.svg +++ b/images/icons/qgis_qgs_icon.svg @@ -1,73 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_qlr_icon.svg b/images/icons/qgis_qlr_icon.svg index d11c24a858aa..5a80752692ad 100644 --- a/images/icons/qgis_qlr_icon.svg +++ b/images/icons/qgis_qlr_icon.svg @@ -1,72 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_qml_icon.svg b/images/icons/qgis_qml_icon.svg index 0695c137e859..333244798611 100644 --- a/images/icons/qgis_qml_icon.svg +++ b/images/icons/qgis_qml_icon.svg @@ -1,102 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_qpt_icon.svg b/images/icons/qgis_qpt_icon.svg index 9ad3a67ec37c..190cd4fda9ca 100644 --- a/images/icons/qgis_qpt_icon.svg +++ b/images/icons/qgis_qpt_icon.svg @@ -1,120 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_shp_icon.svg b/images/icons/qgis_shp_icon.svg index 2d3494ef7d2b..27f07da82bc8 100644 --- a/images/icons/qgis_shp_icon.svg +++ b/images/icons/qgis_shp_icon.svg @@ -1,66 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_sqlite_icon.svg b/images/icons/qgis_sqlite_icon.svg index 6419d55e2de8..1494d88dd5df 100644 --- a/images/icons/qgis_sqlite_icon.svg +++ b/images/icons/qgis_sqlite_icon.svg @@ -1,89 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/icons/qgis_tif_icon.svg b/images/icons/qgis_tif_icon.svg index c3aa558a5042..58fdc59c2781 100644 --- a/images/icons/qgis_tif_icon.svg +++ b/images/icons/qgis_tif_icon.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/images.qrc b/images/images.qrc index 4a427d5d437d..da2d9632deaa 100644 --- a/images/images.qrc +++ b/images/images.qrc @@ -877,6 +877,9 @@ themes/default/georeferencer/mActionDeleteGCPPoint.png themes/default/georeferencer/mActionMoveGCPPoint.png themes/default/georeferencer/mActionSaveGCPpointsAs.png + themes/default/mIconAlignBottom.svg + themes/default/mIconAlignTop.svg + themes/default/mIconAlignVCenter.svg qgis_tips/symbol_levels.png diff --git a/images/north_arrows/gpsarrow.svg b/images/north_arrows/gpsarrow.svg index 924ccb79c8df..c237346e17d2 100644 --- a/images/north_arrows/gpsarrow.svg +++ b/images/north_arrows/gpsarrow.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/north_arrows/gpsarrow2.svg b/images/north_arrows/gpsarrow2.svg index 4264b4803148..138e7973d99f 100644 --- a/images/north_arrows/gpsarrow2.svg +++ b/images/north_arrows/gpsarrow2.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/svg/crosses/Cross2.svg b/images/svg/crosses/Cross2.svg index 0c2e9f48b0c6..6456e230a2d8 100644 --- a/images/svg/crosses/Cross2.svg +++ b/images/svg/crosses/Cross2.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/svg/crosses/Star2.svg b/images/svg/crosses/Star2.svg index b0fe15624779..322a7b0a7dcb 100644 --- a/images/svg/crosses/Star2.svg +++ b/images/svg/crosses/Star2.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/svg/crosses/Star3.svg b/images/svg/crosses/Star3.svg index 2ab8cf48b230..d47d56796727 100644 --- a/images/svg/crosses/Star3.svg +++ b/images/svg/crosses/Star3.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/svg/gpsicons/plane_orange.svg b/images/svg/gpsicons/plane_orange.svg index 1b9f6837a6d1..6275f088dd37 100644 --- a/images/svg/gpsicons/plane_orange.svg +++ b/images/svg/gpsicons/plane_orange.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/svg/symbol/blue-marker.svg b/images/svg/symbol/blue-marker.svg index dd5ee6959d5c..0aad2a89b14d 100644 --- a/images/svg/symbol/blue-marker.svg +++ b/images/svg/symbol/blue-marker.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/svg/symbol/red-marker.svg b/images/svg/symbol/red-marker.svg index d8d0b5d1dad1..ac35bb2a3fa4 100644 --- a/images/svg/symbol/red-marker.svg +++ b/images/svg/symbol/red-marker.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/svg/transport/transport_bus_station.svg b/images/svg/transport/transport_bus_station.svg index 3dc28487954b..5943d5f54d01 100644 --- a/images/svg/transport/transport_bus_station.svg +++ b/images/svg/transport/transport_bus_station.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/3d.svg b/images/themes/default/3d.svg index 330ea19e6786..c3129fce2b87 100644 --- a/images/themes/default/3d.svg +++ b/images/themes/default/3d.svg @@ -1,38 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmAddGeometryAttributes.svg b/images/themes/default/algorithms/mAlgorithmAddGeometryAttributes.svg index e67eb9e9098d..d12046425161 100644 --- a/images/themes/default/algorithms/mAlgorithmAddGeometryAttributes.svg +++ b/images/themes/default/algorithms/mAlgorithmAddGeometryAttributes.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmCentroids.svg b/images/themes/default/algorithms/mAlgorithmCentroids.svg index 34af46c0db2b..d6d180789624 100644 --- a/images/themes/default/algorithms/mAlgorithmCentroids.svg +++ b/images/themes/default/algorithms/mAlgorithmCentroids.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmClip.svg b/images/themes/default/algorithms/mAlgorithmClip.svg index ba712b0202a9..3ffbeff8c4e9 100644 --- a/images/themes/default/algorithms/mAlgorithmClip.svg +++ b/images/themes/default/algorithms/mAlgorithmClip.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmCollect.svg b/images/themes/default/algorithms/mAlgorithmCollect.svg index f6555a350409..1e534a774523 100644 --- a/images/themes/default/algorithms/mAlgorithmCollect.svg +++ b/images/themes/default/algorithms/mAlgorithmCollect.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmConcaveHull.svg b/images/themes/default/algorithms/mAlgorithmConcaveHull.svg index 4c88a565a0d9..407f73fe75c1 100644 --- a/images/themes/default/algorithms/mAlgorithmConcaveHull.svg +++ b/images/themes/default/algorithms/mAlgorithmConcaveHull.svg @@ -1,134 +1 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmConstantRaster.svg b/images/themes/default/algorithms/mAlgorithmConstantRaster.svg index 874d31f60ee5..18d5962033ae 100644 --- a/images/themes/default/algorithms/mAlgorithmConstantRaster.svg +++ b/images/themes/default/algorithms/mAlgorithmConstantRaster.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmDelaunay.svg b/images/themes/default/algorithms/mAlgorithmDelaunay.svg index 6759d99a33a1..49afaef14e26 100644 --- a/images/themes/default/algorithms/mAlgorithmDelaunay.svg +++ b/images/themes/default/algorithms/mAlgorithmDelaunay.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmDifference.svg b/images/themes/default/algorithms/mAlgorithmDifference.svg index 6b7107551d13..55382345b023 100644 --- a/images/themes/default/algorithms/mAlgorithmDifference.svg +++ b/images/themes/default/algorithms/mAlgorithmDifference.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmDistanceMatrix.svg b/images/themes/default/algorithms/mAlgorithmDistanceMatrix.svg index 05308093c596..bec512c596c0 100644 --- a/images/themes/default/algorithms/mAlgorithmDistanceMatrix.svg +++ b/images/themes/default/algorithms/mAlgorithmDistanceMatrix.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmExtractLayerExtent.svg b/images/themes/default/algorithms/mAlgorithmExtractLayerExtent.svg index 6357e1c78ad5..11e92f026a61 100644 --- a/images/themes/default/algorithms/mAlgorithmExtractLayerExtent.svg +++ b/images/themes/default/algorithms/mAlgorithmExtractLayerExtent.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmExtractVertices.svg b/images/themes/default/algorithms/mAlgorithmExtractVertices.svg index d89d8a19ae07..2634ccfb854c 100644 --- a/images/themes/default/algorithms/mAlgorithmExtractVertices.svg +++ b/images/themes/default/algorithms/mAlgorithmExtractVertices.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFillNoData.svg b/images/themes/default/algorithms/mAlgorithmFillNoData.svg index f1f10a2d86ee..45a7de690010 100644 --- a/images/themes/default/algorithms/mAlgorithmFillNoData.svg +++ b/images/themes/default/algorithms/mAlgorithmFillNoData.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFuzzifyGaussian.svg b/images/themes/default/algorithms/mAlgorithmFuzzifyGaussian.svg index a47168a46beb..2d8e08e942f7 100644 --- a/images/themes/default/algorithms/mAlgorithmFuzzifyGaussian.svg +++ b/images/themes/default/algorithms/mAlgorithmFuzzifyGaussian.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFuzzifyLarge.svg b/images/themes/default/algorithms/mAlgorithmFuzzifyLarge.svg index 31d12437d550..01931df99ff2 100644 --- a/images/themes/default/algorithms/mAlgorithmFuzzifyLarge.svg +++ b/images/themes/default/algorithms/mAlgorithmFuzzifyLarge.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFuzzifyLinear.svg b/images/themes/default/algorithms/mAlgorithmFuzzifyLinear.svg index 5f1c89c4242a..b482f034e116 100644 --- a/images/themes/default/algorithms/mAlgorithmFuzzifyLinear.svg +++ b/images/themes/default/algorithms/mAlgorithmFuzzifyLinear.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFuzzifyNear.svg b/images/themes/default/algorithms/mAlgorithmFuzzifyNear.svg index 97a3e5cd7f30..23359e5d6326 100644 --- a/images/themes/default/algorithms/mAlgorithmFuzzifyNear.svg +++ b/images/themes/default/algorithms/mAlgorithmFuzzifyNear.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFuzzifyPower.svg b/images/themes/default/algorithms/mAlgorithmFuzzifyPower.svg index e0de0fd52145..304a141a209b 100644 --- a/images/themes/default/algorithms/mAlgorithmFuzzifyPower.svg +++ b/images/themes/default/algorithms/mAlgorithmFuzzifyPower.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmFuzzifySmall.svg b/images/themes/default/algorithms/mAlgorithmFuzzifySmall.svg index ee2155a9ab6e..1f821722540e 100644 --- a/images/themes/default/algorithms/mAlgorithmFuzzifySmall.svg +++ b/images/themes/default/algorithms/mAlgorithmFuzzifySmall.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmIntersect.svg b/images/themes/default/algorithms/mAlgorithmIntersect.svg index ba712b0202a9..3ffbeff8c4e9 100644 --- a/images/themes/default/algorithms/mAlgorithmIntersect.svg +++ b/images/themes/default/algorithms/mAlgorithmIntersect.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmLineDensity.svg b/images/themes/default/algorithms/mAlgorithmLineDensity.svg index 2615f2f5edc7..dc5b9b5bef89 100644 --- a/images/themes/default/algorithms/mAlgorithmLineDensity.svg +++ b/images/themes/default/algorithms/mAlgorithmLineDensity.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmLineIntersections.svg b/images/themes/default/algorithms/mAlgorithmLineIntersections.svg index 928a34a3eae7..202bdd6779d6 100644 --- a/images/themes/default/algorithms/mAlgorithmLineIntersections.svg +++ b/images/themes/default/algorithms/mAlgorithmLineIntersections.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmLineToPolygon.svg b/images/themes/default/algorithms/mAlgorithmLineToPolygon.svg index 7f58641e1385..e2beade21b8d 100644 --- a/images/themes/default/algorithms/mAlgorithmLineToPolygon.svg +++ b/images/themes/default/algorithms/mAlgorithmLineToPolygon.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmMeanCoordinates.svg b/images/themes/default/algorithms/mAlgorithmMeanCoordinates.svg index a6c7b2f30cff..e8296f06dd7d 100644 --- a/images/themes/default/algorithms/mAlgorithmMeanCoordinates.svg +++ b/images/themes/default/algorithms/mAlgorithmMeanCoordinates.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmMergeLayers.svg b/images/themes/default/algorithms/mAlgorithmMergeLayers.svg index 831ba6551a03..a190deda4d40 100644 --- a/images/themes/default/algorithms/mAlgorithmMergeLayers.svg +++ b/images/themes/default/algorithms/mAlgorithmMergeLayers.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmMultiToSingle.svg b/images/themes/default/algorithms/mAlgorithmMultiToSingle.svg index cef7ca3c7190..1f97bc68271a 100644 --- a/images/themes/default/algorithms/mAlgorithmMultiToSingle.svg +++ b/images/themes/default/algorithms/mAlgorithmMultiToSingle.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmNearestNeighbour.svg b/images/themes/default/algorithms/mAlgorithmNearestNeighbour.svg index fd6d0a50ec87..32458b8f4eb0 100644 --- a/images/themes/default/algorithms/mAlgorithmNearestNeighbour.svg +++ b/images/themes/default/algorithms/mAlgorithmNearestNeighbour.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmNetworkAnalysis.svg b/images/themes/default/algorithms/mAlgorithmNetworkAnalysis.svg index 1ecbadb6fa96..667dccb3440a 100644 --- a/images/themes/default/algorithms/mAlgorithmNetworkAnalysis.svg +++ b/images/themes/default/algorithms/mAlgorithmNetworkAnalysis.svg @@ -1,798 +1 @@ - - - - - Fast road - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - Fast road - 2012-08-13 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - vector - network - optimization - - - GIS icons 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmNormalRaster.svg b/images/themes/default/algorithms/mAlgorithmNormalRaster.svg index 96bbcdeac739..f00b054393e1 100644 --- a/images/themes/default/algorithms/mAlgorithmNormalRaster.svg +++ b/images/themes/default/algorithms/mAlgorithmNormalRaster.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmPolygonToLine.svg b/images/themes/default/algorithms/mAlgorithmPolygonToLine.svg index e108b115e66f..f68f2cea1890 100644 --- a/images/themes/default/algorithms/mAlgorithmPolygonToLine.svg +++ b/images/themes/default/algorithms/mAlgorithmPolygonToLine.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomExponentialRaster.svg b/images/themes/default/algorithms/mAlgorithmRandomExponentialRaster.svg index 506af126b701..731f8984f1a4 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomExponentialRaster.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomExponentialRaster.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomGammaRaster.svg b/images/themes/default/algorithms/mAlgorithmRandomGammaRaster.svg index 84ca27a8d7d3..56d4606dd233 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomGammaRaster.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomGammaRaster.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomPointsOnLines.svg b/images/themes/default/algorithms/mAlgorithmRandomPointsOnLines.svg index ebb78fed061b..d1059c87f377 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomPointsOnLines.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomPointsOnLines.svg @@ -1,120 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomPointsWithinExtent.svg b/images/themes/default/algorithms/mAlgorithmRandomPointsWithinExtent.svg index c4a7221af9cf..c28c471e7f60 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomPointsWithinExtent.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomPointsWithinExtent.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomPointsWithinPolygon.svg b/images/themes/default/algorithms/mAlgorithmRandomPointsWithinPolygon.svg index 3c32d991e2d9..8d318968a38b 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomPointsWithinPolygon.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomPointsWithinPolygon.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomPoissonRaster.svg b/images/themes/default/algorithms/mAlgorithmRandomPoissonRaster.svg index a164c2a76763..3aca8cbd4a08 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomPoissonRaster.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomPoissonRaster.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRandomRaster.svg b/images/themes/default/algorithms/mAlgorithmRandomRaster.svg index 35c11f30aaa2..2617b9606884 100644 --- a/images/themes/default/algorithms/mAlgorithmRandomRaster.svg +++ b/images/themes/default/algorithms/mAlgorithmRandomRaster.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRegularPoints.svg b/images/themes/default/algorithms/mAlgorithmRegularPoints.svg index c44690b86eac..2d477baf815d 100644 --- a/images/themes/default/algorithms/mAlgorithmRegularPoints.svg +++ b/images/themes/default/algorithms/mAlgorithmRegularPoints.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmRoundRastervalues.svg b/images/themes/default/algorithms/mAlgorithmRoundRastervalues.svg index 86a2c5148d0a..730d163f9ae6 100644 --- a/images/themes/default/algorithms/mAlgorithmRoundRastervalues.svg +++ b/images/themes/default/algorithms/mAlgorithmRoundRastervalues.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSelectLocation.svg b/images/themes/default/algorithms/mAlgorithmSelectLocation.svg index eb22d185d4e6..2610daf2bff6 100644 --- a/images/themes/default/algorithms/mAlgorithmSelectLocation.svg +++ b/images/themes/default/algorithms/mAlgorithmSelectLocation.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSelectRandom.svg b/images/themes/default/algorithms/mAlgorithmSelectRandom.svg index 73e3cfc74246..bbea7055c6da 100644 --- a/images/themes/default/algorithms/mAlgorithmSelectRandom.svg +++ b/images/themes/default/algorithms/mAlgorithmSelectRandom.svg @@ -1 +1 @@ -?? +?? \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSingleToMulti.svg b/images/themes/default/algorithms/mAlgorithmSingleToMulti.svg index 883753b98774..fb3889649ce5 100644 --- a/images/themes/default/algorithms/mAlgorithmSingleToMulti.svg +++ b/images/themes/default/algorithms/mAlgorithmSingleToMulti.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSplitLayer.svg b/images/themes/default/algorithms/mAlgorithmSplitLayer.svg index be29d90769b9..2b46396ddfef 100644 --- a/images/themes/default/algorithms/mAlgorithmSplitLayer.svg +++ b/images/themes/default/algorithms/mAlgorithmSplitLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSumLengthLines.svg b/images/themes/default/algorithms/mAlgorithmSumLengthLines.svg index 7d7a64a14959..4a38093803d1 100644 --- a/images/themes/default/algorithms/mAlgorithmSumLengthLines.svg +++ b/images/themes/default/algorithms/mAlgorithmSumLengthLines.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSumPoints.svg b/images/themes/default/algorithms/mAlgorithmSumPoints.svg index d89372d84e08..273414f1aaae 100644 --- a/images/themes/default/algorithms/mAlgorithmSumPoints.svg +++ b/images/themes/default/algorithms/mAlgorithmSumPoints.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmSymmetricalDifference.svg b/images/themes/default/algorithms/mAlgorithmSymmetricalDifference.svg index 7c4734d06dd6..95026435adc1 100644 --- a/images/themes/default/algorithms/mAlgorithmSymmetricalDifference.svg +++ b/images/themes/default/algorithms/mAlgorithmSymmetricalDifference.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmUnion.svg b/images/themes/default/algorithms/mAlgorithmUnion.svg index 441301857698..24102665c6ec 100644 --- a/images/themes/default/algorithms/mAlgorithmUnion.svg +++ b/images/themes/default/algorithms/mAlgorithmUnion.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmUniqueValues.svg b/images/themes/default/algorithms/mAlgorithmUniqueValues.svg index de876bfea2ab..30e17808f56a 100644 --- a/images/themes/default/algorithms/mAlgorithmUniqueValues.svg +++ b/images/themes/default/algorithms/mAlgorithmUniqueValues.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/algorithms/mAlgorithmVoronoi.svg b/images/themes/default/algorithms/mAlgorithmVoronoi.svg index b32cc63e6c52..bb74a97bbdb6 100644 --- a/images/themes/default/algorithms/mAlgorithmVoronoi.svg +++ b/images/themes/default/algorithms/mAlgorithmVoronoi.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/cadtools/cad.svg b/images/themes/default/cadtools/cad.svg index 07cc82ad7955..ac60a7a2b849 100644 --- a/images/themes/default/cadtools/cad.svg +++ b/images/themes/default/cadtools/cad.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/cadtools/construction.svg b/images/themes/default/cadtools/construction.svg index ff9d8d7237cc..0948113b4511 100644 --- a/images/themes/default/cadtools/construction.svg +++ b/images/themes/default/cadtools/construction.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/cadtools/delta.svg b/images/themes/default/cadtools/delta.svg index a7500ae27074..81f672ec6e18 100644 --- a/images/themes/default/cadtools/delta.svg +++ b/images/themes/default/cadtools/delta.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/cadtools/floater.svg b/images/themes/default/cadtools/floater.svg index 91377e7d822e..f679f5221a68 100644 --- a/images/themes/default/cadtools/floater.svg +++ b/images/themes/default/cadtools/floater.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/cadtools/lock.svg b/images/themes/default/cadtools/lock.svg index b9a39505e8b5..caef8263c0d8 100644 --- a/images/themes/default/cadtools/lock.svg +++ b/images/themes/default/cadtools/lock.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/cadtools/parallel.svg b/images/themes/default/cadtools/parallel.svg index b237ff931daf..b62732de40c8 100644 --- a/images/themes/default/cadtools/parallel.svg +++ b/images/themes/default/cadtools/parallel.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/cadtools/perpendicular.svg b/images/themes/default/cadtools/perpendicular.svg index b9950387b421..cd226d655138 100644 --- a/images/themes/default/cadtools/perpendicular.svg +++ b/images/themes/default/cadtools/perpendicular.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/cap_flat.svg b/images/themes/default/cap_flat.svg index 1ac58e7a7f82..8a97cea5a941 100644 --- a/images/themes/default/cap_flat.svg +++ b/images/themes/default/cap_flat.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cap_round.svg b/images/themes/default/cap_round.svg index 1ab2e62d5b17..659d9c654901 100644 --- a/images/themes/default/cap_round.svg +++ b/images/themes/default/cap_round.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/checks/InvalidGeometry.svg b/images/themes/default/checks/InvalidGeometry.svg index 8c0b9b3a3f0d..56246aad7abb 100644 --- a/images/themes/default/checks/InvalidGeometry.svg +++ b/images/themes/default/checks/InvalidGeometry.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/checks/MissingVertex.svg b/images/themes/default/checks/MissingVertex.svg index b21f1b87055e..a6709efa58d3 100644 --- a/images/themes/default/checks/MissingVertex.svg +++ b/images/themes/default/checks/MissingVertex.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/classification_methods/mClassificationEqualCount.svg b/images/themes/default/classification_methods/mClassificationEqualCount.svg index dd739f0903e9..c946b6f5403a 100644 --- a/images/themes/default/classification_methods/mClassificationEqualCount.svg +++ b/images/themes/default/classification_methods/mClassificationEqualCount.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/classification_methods/mClassificationEqualInterval.svg b/images/themes/default/classification_methods/mClassificationEqualInterval.svg index d275757178b2..e949de10ba57 100644 --- a/images/themes/default/classification_methods/mClassificationEqualInterval.svg +++ b/images/themes/default/classification_methods/mClassificationEqualInterval.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/classification_methods/mClassificationNaturalBreak.svg b/images/themes/default/classification_methods/mClassificationNaturalBreak.svg index dce0a2e2c84b..5b9f8c723e2e 100644 --- a/images/themes/default/classification_methods/mClassificationNaturalBreak.svg +++ b/images/themes/default/classification_methods/mClassificationNaturalBreak.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/classification_methods/mClassificationPrettyBreak.svg b/images/themes/default/classification_methods/mClassificationPrettyBreak.svg index d97c378e7e95..2aa79dc8dd37 100644 --- a/images/themes/default/classification_methods/mClassificationPrettyBreak.svg +++ b/images/themes/default/classification_methods/mClassificationPrettyBreak.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconClassBrowserConsole.svg b/images/themes/default/console/iconClassBrowserConsole.svg index cb3eca8f6c43..42bc5711d627 100644 --- a/images/themes/default/console/iconClassBrowserConsole.svg +++ b/images/themes/default/console/iconClassBrowserConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconClassConsole.svg b/images/themes/default/console/iconClassConsole.svg index 6e75c4a77e05..fecdb136bb04 100644 --- a/images/themes/default/console/iconClassConsole.svg +++ b/images/themes/default/console/iconClassConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconClassTreeWidgetConsole.svg b/images/themes/default/console/iconClassTreeWidgetConsole.svg index 0a7a23657807..04b76b23c816 100644 --- a/images/themes/default/console/iconClassTreeWidgetConsole.svg +++ b/images/themes/default/console/iconClassTreeWidgetConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconClearConsole.svg b/images/themes/default/console/iconClearConsole.svg index 789f81c187f3..c3bf459d6162 100644 --- a/images/themes/default/console/iconClearConsole.svg +++ b/images/themes/default/console/iconClearConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconCodepadConsole.svg b/images/themes/default/console/iconCodepadConsole.svg index 2579b545cde1..5c2960468c69 100644 --- a/images/themes/default/console/iconCodepadConsole.svg +++ b/images/themes/default/console/iconCodepadConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconCommentEditorConsole.svg b/images/themes/default/console/iconCommentEditorConsole.svg index f2408df7d39e..6094e84fedfe 100644 --- a/images/themes/default/console/iconCommentEditorConsole.svg +++ b/images/themes/default/console/iconCommentEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconFileTabsMenuConsole.svg b/images/themes/default/console/iconFileTabsMenuConsole.svg index f48c10f04e82..e1b0aa32a5c5 100644 --- a/images/themes/default/console/iconFileTabsMenuConsole.svg +++ b/images/themes/default/console/iconFileTabsMenuConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconFunctionTreeWidgetConsole.svg b/images/themes/default/console/iconFunctionTreeWidgetConsole.svg index 3015e50b1a25..fb722310e75b 100644 --- a/images/themes/default/console/iconFunctionTreeWidgetConsole.svg +++ b/images/themes/default/console/iconFunctionTreeWidgetConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconHideToolConsole.svg b/images/themes/default/console/iconHideToolConsole.svg index f4ffb3455b21..167e1d211766 100644 --- a/images/themes/default/console/iconHideToolConsole.svg +++ b/images/themes/default/console/iconHideToolConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconMethodTreeWidgetConsole.svg b/images/themes/default/console/iconMethodTreeWidgetConsole.svg index c27a4e47b210..3e903d9c828b 100644 --- a/images/themes/default/console/iconMethodTreeWidgetConsole.svg +++ b/images/themes/default/console/iconMethodTreeWidgetConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconNewTabEditorConsole.svg b/images/themes/default/console/iconNewTabEditorConsole.svg index edf7dc7f8985..a233b187296d 100644 --- a/images/themes/default/console/iconNewTabEditorConsole.svg +++ b/images/themes/default/console/iconNewTabEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconProcessingConsole.svg b/images/themes/default/console/iconProcessingConsole.svg index 551a7d45635f..9fad9723dbbe 100644 --- a/images/themes/default/console/iconProcessingConsole.svg +++ b/images/themes/default/console/iconProcessingConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconQtCoreConsole.svg b/images/themes/default/console/iconQtCoreConsole.svg index ad615efa3d15..ef11e73137d7 100644 --- a/images/themes/default/console/iconQtCoreConsole.svg +++ b/images/themes/default/console/iconQtCoreConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconQtGuiConsole.svg b/images/themes/default/console/iconQtGuiConsole.svg index f33751f442de..0df0da4ec084 100644 --- a/images/themes/default/console/iconQtGuiConsole.svg +++ b/images/themes/default/console/iconQtGuiConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconRestoreTabsConsole.svg b/images/themes/default/console/iconRestoreTabsConsole.svg index 0189b090733e..03983ab2e74c 100644 --- a/images/themes/default/console/iconRestoreTabsConsole.svg +++ b/images/themes/default/console/iconRestoreTabsConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconSearchEditorConsole.svg b/images/themes/default/console/iconSearchEditorConsole.svg index 0018114ac15e..5e85ef2111c7 100644 --- a/images/themes/default/console/iconSearchEditorConsole.svg +++ b/images/themes/default/console/iconSearchEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconSearchNextEditorConsole.svg b/images/themes/default/console/iconSearchNextEditorConsole.svg index ff8b90aeaf45..658a7a5c88c4 100644 --- a/images/themes/default/console/iconSearchNextEditorConsole.svg +++ b/images/themes/default/console/iconSearchNextEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconSearchPrevEditorConsole.svg b/images/themes/default/console/iconSearchPrevEditorConsole.svg index ba4ea657cd9a..0e49331f9624 100644 --- a/images/themes/default/console/iconSearchPrevEditorConsole.svg +++ b/images/themes/default/console/iconSearchPrevEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconSettingsConsole.svg b/images/themes/default/console/iconSettingsConsole.svg index a9e601cd93f1..60473f4bf6a9 100644 --- a/images/themes/default/console/iconSettingsConsole.svg +++ b/images/themes/default/console/iconSettingsConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconShowEditorConsole.svg b/images/themes/default/console/iconShowEditorConsole.svg index 4fad4e1dbe8f..b05a3e27b05d 100644 --- a/images/themes/default/console/iconShowEditorConsole.svg +++ b/images/themes/default/console/iconShowEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconSyntaxErrorConsole.svg b/images/themes/default/console/iconSyntaxErrorConsole.svg index 74d31939634a..f528ade3ba51 100644 --- a/images/themes/default/console/iconSyntaxErrorConsole.svg +++ b/images/themes/default/console/iconSyntaxErrorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconTabEditorConsole.svg b/images/themes/default/console/iconTabEditorConsole.svg index 9d1aad46be59..23e7ada0a4bb 100644 --- a/images/themes/default/console/iconTabEditorConsole.svg +++ b/images/themes/default/console/iconTabEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/console/iconUncommentEditorConsole.svg b/images/themes/default/console/iconUncommentEditorConsole.svg index 00cd678bea15..c54b9bc21fa6 100644 --- a/images/themes/default/console/iconUncommentEditorConsole.svg +++ b/images/themes/default/console/iconUncommentEditorConsole.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/copyright_label.svg b/images/themes/default/copyright_label.svg index d4263b4480ad..10d18ac0fd1d 100644 --- a/images/themes/default/copyright_label.svg +++ b/images/themes/default/copyright_label.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mCapturePoint.svg b/images/themes/default/cursors/mCapturePoint.svg index 660f6f2c05d1..935d38103129 100644 --- a/images/themes/default/cursors/mCapturePoint.svg +++ b/images/themes/default/cursors/mCapturePoint.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mCrossHair.svg b/images/themes/default/cursors/mCrossHair.svg index bdd35f59aa6a..71aa23427040 100644 --- a/images/themes/default/cursors/mCrossHair.svg +++ b/images/themes/default/cursors/mCrossHair.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mIdentify.svg b/images/themes/default/cursors/mIdentify.svg index d95b9853a3e8..3bb5f77332a5 100644 --- a/images/themes/default/cursors/mIdentify.svg +++ b/images/themes/default/cursors/mIdentify.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mSampler.svg b/images/themes/default/cursors/mSampler.svg index 61df80602d1d..f2c529c3880b 100644 --- a/images/themes/default/cursors/mSampler.svg +++ b/images/themes/default/cursors/mSampler.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mSelect.svg b/images/themes/default/cursors/mSelect.svg index d12d640222c9..6d0916726651 100644 --- a/images/themes/default/cursors/mSelect.svg +++ b/images/themes/default/cursors/mSelect.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mZoomIn.svg b/images/themes/default/cursors/mZoomIn.svg index 4c54dd914b2c..204a86fcbc88 100644 --- a/images/themes/default/cursors/mZoomIn.svg +++ b/images/themes/default/cursors/mZoomIn.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/cursors/mZoomOut.svg b/images/themes/default/cursors/mZoomOut.svg index d43f082f87d5..1d722c331931 100644 --- a/images/themes/default/cursors/mZoomOut.svg +++ b/images/themes/default/cursors/mZoomOut.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/dbmanager.svg b/images/themes/default/dbmanager.svg index fcef1cbf2eb9..3018057f41c4 100644 --- a/images/themes/default/dbmanager.svg +++ b/images/themes/default/dbmanager.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/dependencies.svg b/images/themes/default/dependencies.svg index fd588e934de3..64d1cec3bd48 100644 --- a/images/themes/default/dependencies.svg +++ b/images/themes/default/dependencies.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/diagramNone.svg b/images/themes/default/diagramNone.svg index 1dde1b5e13fe..e4a579cf9c37 100644 --- a/images/themes/default/diagramNone.svg +++ b/images/themes/default/diagramNone.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/downloading_svg.svg b/images/themes/default/downloading_svg.svg index 8f2a1beed81a..da8471a33ed6 100644 --- a/images/themes/default/downloading_svg.svg +++ b/images/themes/default/downloading_svg.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/extents.svg b/images/themes/default/extents.svg index e55a0abd36df..764c25fcfb97 100644 --- a/images/themes/default/extents.svg +++ b/images/themes/default/extents.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/gpsicons/barchart.svg b/images/themes/default/gpsicons/barchart.svg index b7aa791477d4..e81684f48dea 100644 --- a/images/themes/default/gpsicons/barchart.svg +++ b/images/themes/default/gpsicons/barchart.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/gpsicons/polarchart.svg b/images/themes/default/gpsicons/polarchart.svg index da35f9a7a0a9..f5498f15be59 100644 --- a/images/themes/default/gpsicons/polarchart.svg +++ b/images/themes/default/gpsicons/polarchart.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/grass_location.svg b/images/themes/default/grass_location.svg index 152f9c7feddc..10b3681aebbc 100644 --- a/images/themes/default/grass_location.svg +++ b/images/themes/default/grass_location.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/grass_mapset.svg b/images/themes/default/grass_mapset.svg index 725d80048244..9f76edb88f0e 100644 --- a/images/themes/default/grass_mapset.svg +++ b/images/themes/default/grass_mapset.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/grass_mapset_open.svg b/images/themes/default/grass_mapset_open.svg index a3e0bad2682c..56e29b1fee41 100644 --- a/images/themes/default/grass_mapset_open.svg +++ b/images/themes/default/grass_mapset_open.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/grass_mapset_search.svg b/images/themes/default/grass_mapset_search.svg index 16a865e2c810..93d9a7ab76eb 100644 --- a/images/themes/default/grass_mapset_search.svg +++ b/images/themes/default/grass_mapset_search.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/grid.svg b/images/themes/default/grid.svg index c2dfbe1ff8ee..a4e6ea403045 100644 --- a/images/themes/default/grid.svg +++ b/images/themes/default/grid.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/heatmap.svg b/images/themes/default/heatmap.svg index 2fa7f1a03177..026e09f2c5fe 100644 --- a/images/themes/default/heatmap.svg +++ b/images/themes/default/heatmap.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/histogram.svg b/images/themes/default/histogram.svg index 923837a06e54..ca5d1640c4af 100644 --- a/images/themes/default/histogram.svg +++ b/images/themes/default/histogram.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/join_bevel.svg b/images/themes/default/join_bevel.svg index 0db20d23b612..f91c0cf13661 100644 --- a/images/themes/default/join_bevel.svg +++ b/images/themes/default/join_bevel.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/join_miter.svg b/images/themes/default/join_miter.svg index 99cf80379390..037578f655ae 100644 --- a/images/themes/default/join_miter.svg +++ b/images/themes/default/join_miter.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/join_round.svg b/images/themes/default/join_round.svg index dd2611693af6..6aab79e6079e 100644 --- a/images/themes/default/join_round.svg +++ b/images/themes/default/join_round.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/labelingCalloutManhattan.svg b/images/themes/default/labelingCalloutManhattan.svg index 0aef510ffaa4..aa67cad9f205 100644 --- a/images/themes/default/labelingCalloutManhattan.svg +++ b/images/themes/default/labelingCalloutManhattan.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/labelingCalloutSimple.svg b/images/themes/default/labelingCalloutSimple.svg index d58a8e7b5ca9..9a80f8f2701e 100644 --- a/images/themes/default/labelingCalloutSimple.svg +++ b/images/themes/default/labelingCalloutSimple.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/labelingNone.svg b/images/themes/default/labelingNone.svg index 9b00b7a9bd79..12817f827cdb 100644 --- a/images/themes/default/labelingNone.svg +++ b/images/themes/default/labelingNone.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/labelingObstacle.svg b/images/themes/default/labelingObstacle.svg index 4dff3ebf00e8..554f9d2d3a0c 100644 --- a/images/themes/default/labelingObstacle.svg +++ b/images/themes/default/labelingObstacle.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/labelingRuleBased.svg b/images/themes/default/labelingRuleBased.svg index 85b7f6d729f9..ab80f8490951 100644 --- a/images/themes/default/labelingRuleBased.svg +++ b/images/themes/default/labelingRuleBased.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/labelingSingle.svg b/images/themes/default/labelingSingle.svg index 41371e9fcba9..ff07a38af080 100644 --- a/images/themes/default/labelingSingle.svg +++ b/images/themes/default/labelingSingle.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/legend.svg b/images/themes/default/legend.svg index 0c60f6992269..bf86cb658c36 100644 --- a/images/themes/default/legend.svg +++ b/images/themes/default/legend.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/locked.svg b/images/themes/default/locked.svg index 9be3458c735c..e3c0bcbcc075 100644 --- a/images/themes/default/locked.svg +++ b/images/themes/default/locked.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/lockedGray.svg b/images/themes/default/lockedGray.svg index c8ccb42187c4..248ee72e7965 100644 --- a/images/themes/default/lockedGray.svg +++ b/images/themes/default/lockedGray.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/locked_repeating.svg b/images/themes/default/locked_repeating.svg index b5965f405963..df440bf05a76 100644 --- a/images/themes/default/locked_repeating.svg +++ b/images/themes/default/locked_repeating.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mAction.svg b/images/themes/default/mAction.svg index 92ac961da78a..8d18df828d93 100644 --- a/images/themes/default/mAction.svg +++ b/images/themes/default/mAction.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mAction3DNavigation.svg b/images/themes/default/mAction3DNavigation.svg index 634fd57c5941..1b4ff94cdc09 100644 --- a/images/themes/default/mAction3DNavigation.svg +++ b/images/themes/default/mAction3DNavigation.svg @@ -1,82 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionActive.svg b/images/themes/default/mActionActive.svg index 0a0e45a45f64..3f10411d771f 100644 --- a/images/themes/default/mActionActive.svg +++ b/images/themes/default/mActionActive.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAdd.svg b/images/themes/default/mActionAdd.svg index 16b37c3d62cd..620f615b1750 100644 --- a/images/themes/default/mActionAdd.svg +++ b/images/themes/default/mActionAdd.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAdd3DMap.svg b/images/themes/default/mActionAdd3DMap.svg index 9f4ba71583c2..7340ceaae4df 100644 --- a/images/themes/default/mActionAdd3DMap.svg +++ b/images/themes/default/mActionAdd3DMap.svg @@ -1,163 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddAfsLayer.svg b/images/themes/default/mActionAddAfsLayer.svg index 69f43060395f..4f56438c51c4 100644 --- a/images/themes/default/mActionAddAfsLayer.svg +++ b/images/themes/default/mActionAddAfsLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddAllToOverview.svg b/images/themes/default/mActionAddAllToOverview.svg index 4916a84ded59..ab9bb597cc31 100644 --- a/images/themes/default/mActionAddAllToOverview.svg +++ b/images/themes/default/mActionAddAllToOverview.svg @@ -1,54 +1 @@ - - - - - - image/svg+xml - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddAmsLayer.svg b/images/themes/default/mActionAddAmsLayer.svg index 6c6522d5d17f..e3b84545c129 100644 --- a/images/themes/default/mActionAddAmsLayer.svg +++ b/images/themes/default/mActionAddAmsLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddArrow.svg b/images/themes/default/mActionAddArrow.svg index 4bd9ba0f880d..cf9658a4566e 100644 --- a/images/themes/default/mActionAddArrow.svg +++ b/images/themes/default/mActionAddArrow.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddBasicCircle.svg b/images/themes/default/mActionAddBasicCircle.svg index 32486d6bc6f6..f27e8bf5fb68 100644 --- a/images/themes/default/mActionAddBasicCircle.svg +++ b/images/themes/default/mActionAddBasicCircle.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddBasicRectangle.svg b/images/themes/default/mActionAddBasicRectangle.svg index 9a5ea2f1cc02..7f44f82816af 100644 --- a/images/themes/default/mActionAddBasicRectangle.svg +++ b/images/themes/default/mActionAddBasicRectangle.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddBasicShape.svg b/images/themes/default/mActionAddBasicShape.svg index 0690bbd786e9..1e23adf044fd 100644 --- a/images/themes/default/mActionAddBasicShape.svg +++ b/images/themes/default/mActionAddBasicShape.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddBasicTriangle.svg b/images/themes/default/mActionAddBasicTriangle.svg index 0de9116436eb..24aa7bba1877 100644 --- a/images/themes/default/mActionAddBasicTriangle.svg +++ b/images/themes/default/mActionAddBasicTriangle.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddDb2Layer.svg b/images/themes/default/mActionAddDb2Layer.svg index 5cd63b7ed4e8..c311376afdf4 100644 --- a/images/themes/default/mActionAddDb2Layer.svg +++ b/images/themes/default/mActionAddDb2Layer.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionAddDelimitedTextLayer.svg b/images/themes/default/mActionAddDelimitedTextLayer.svg index ca82deb28f64..8ffea0b8e8e8 100644 --- a/images/themes/default/mActionAddDelimitedTextLayer.svg +++ b/images/themes/default/mActionAddDelimitedTextLayer.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddExpression.svg b/images/themes/default/mActionAddExpression.svg index b1ea2c68c218..29d5bf372bfc 100644 --- a/images/themes/default/mActionAddExpression.svg +++ b/images/themes/default/mActionAddExpression.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionAddGeoPackageLayer.svg b/images/themes/default/mActionAddGeoPackageLayer.svg index 7e5678d68981..f0d8a9429271 100644 --- a/images/themes/default/mActionAddGeoPackageLayer.svg +++ b/images/themes/default/mActionAddGeoPackageLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddGeonodeLayer.svg b/images/themes/default/mActionAddGeonodeLayer.svg index 46c6caa319f7..f05502a2cc70 100644 --- a/images/themes/default/mActionAddGeonodeLayer.svg +++ b/images/themes/default/mActionAddGeonodeLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddGroup.svg b/images/themes/default/mActionAddGroup.svg index b787fdf24ee1..1349c323a779 100644 --- a/images/themes/default/mActionAddGroup.svg +++ b/images/themes/default/mActionAddGroup.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddHtml.svg b/images/themes/default/mActionAddHtml.svg index 6eaa02dbfcac..7ebf810eaa5f 100644 --- a/images/themes/default/mActionAddHtml.svg +++ b/images/themes/default/mActionAddHtml.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddImage.svg b/images/themes/default/mActionAddImage.svg index 424b73cefbd4..f975dd3b6c97 100644 --- a/images/themes/default/mActionAddImage.svg +++ b/images/themes/default/mActionAddImage.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddLayer.svg b/images/themes/default/mActionAddLayer.svg index d4249d631e1e..a8e538fe041c 100644 --- a/images/themes/default/mActionAddLayer.svg +++ b/images/themes/default/mActionAddLayer.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddLegend.svg b/images/themes/default/mActionAddLegend.svg index 75a87bb25bea..fcc33c3e63d5 100644 --- a/images/themes/default/mActionAddLegend.svg +++ b/images/themes/default/mActionAddLegend.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddManualTable.svg b/images/themes/default/mActionAddManualTable.svg index f3c812154e23..f152034034a4 100644 --- a/images/themes/default/mActionAddManualTable.svg +++ b/images/themes/default/mActionAddManualTable.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionAddMap.svg b/images/themes/default/mActionAddMap.svg index 9d8a02594bcb..d3794454ac9a 100644 --- a/images/themes/default/mActionAddMap.svg +++ b/images/themes/default/mActionAddMap.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddMarker.svg b/images/themes/default/mActionAddMarker.svg index 4f9ae01457b4..b048fa1d0f0f 100644 --- a/images/themes/default/mActionAddMarker.svg +++ b/images/themes/default/mActionAddMarker.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionAddMeshLayer.svg b/images/themes/default/mActionAddMeshLayer.svg index a9b215fd22bb..9d636b0d5c39 100644 --- a/images/themes/default/mActionAddMeshLayer.svg +++ b/images/themes/default/mActionAddMeshLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddMssqlLayer.svg b/images/themes/default/mActionAddMssqlLayer.svg index 2d9d595bbcc5..ffcebd4e0640 100644 --- a/images/themes/default/mActionAddMssqlLayer.svg +++ b/images/themes/default/mActionAddMssqlLayer.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddNodesItem.svg b/images/themes/default/mActionAddNodesItem.svg index 40d14a75770a..529835d53851 100644 --- a/images/themes/default/mActionAddNodesItem.svg +++ b/images/themes/default/mActionAddNodesItem.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddOgrLayer.svg b/images/themes/default/mActionAddOgrLayer.svg index 6469a34e73cf..b28c825345d4 100644 --- a/images/themes/default/mActionAddOgrLayer.svg +++ b/images/themes/default/mActionAddOgrLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddOracleLayer.svg b/images/themes/default/mActionAddOracleLayer.svg index fa397ffc11af..65cb507a6bde 100644 --- a/images/themes/default/mActionAddOracleLayer.svg +++ b/images/themes/default/mActionAddOracleLayer.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddPart.svg b/images/themes/default/mActionAddPart.svg index 42934597d08b..467d755b5169 100644 --- a/images/themes/default/mActionAddPart.svg +++ b/images/themes/default/mActionAddPart.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddPolygon.svg b/images/themes/default/mActionAddPolygon.svg index 8917a8d89798..2255a865acae 100644 --- a/images/themes/default/mActionAddPolygon.svg +++ b/images/themes/default/mActionAddPolygon.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddPolyline.svg b/images/themes/default/mActionAddPolyline.svg index 7206b418d1fc..beec39cbb908 100644 --- a/images/themes/default/mActionAddPolyline.svg +++ b/images/themes/default/mActionAddPolyline.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddPostgisLayer.svg b/images/themes/default/mActionAddPostgisLayer.svg index 447c136c87e7..7dc7d5a4b0e3 100644 --- a/images/themes/default/mActionAddPostgisLayer.svg +++ b/images/themes/default/mActionAddPostgisLayer.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddRasterLayer.svg b/images/themes/default/mActionAddRasterLayer.svg index 4a5eda3fcbe0..575302229af1 100644 --- a/images/themes/default/mActionAddRasterLayer.svg +++ b/images/themes/default/mActionAddRasterLayer.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddRing.svg b/images/themes/default/mActionAddRing.svg index d40443ab1d96..8db4ab425752 100644 --- a/images/themes/default/mActionAddRing.svg +++ b/images/themes/default/mActionAddRing.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddSpatiaLiteLayer.svg b/images/themes/default/mActionAddSpatiaLiteLayer.svg index 172a63fedd9a..091bba0eb6b9 100644 --- a/images/themes/default/mActionAddSpatiaLiteLayer.svg +++ b/images/themes/default/mActionAddSpatiaLiteLayer.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddTable.svg b/images/themes/default/mActionAddTable.svg index 4d2a7a2207ee..364be0d12d63 100644 --- a/images/themes/default/mActionAddTable.svg +++ b/images/themes/default/mActionAddTable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddVirtualLayer.svg b/images/themes/default/mActionAddVirtualLayer.svg index 4d55af701de1..8cdc9a6db2e5 100644 --- a/images/themes/default/mActionAddVirtualLayer.svg +++ b/images/themes/default/mActionAddVirtualLayer.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddWcsLayer.svg b/images/themes/default/mActionAddWcsLayer.svg index 75afe7510afb..e3be8de5a2d6 100644 --- a/images/themes/default/mActionAddWcsLayer.svg +++ b/images/themes/default/mActionAddWcsLayer.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAddWfsLayer.svg b/images/themes/default/mActionAddWfsLayer.svg index 2938aa2305b7..c1972ba53c8a 100644 --- a/images/themes/default/mActionAddWfsLayer.svg +++ b/images/themes/default/mActionAddWfsLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAddWmsLayer.svg b/images/themes/default/mActionAddWmsLayer.svg index ab34403d21ba..6ecb8eaf2ca2 100644 --- a/images/themes/default/mActionAddWmsLayer.svg +++ b/images/themes/default/mActionAddWmsLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAlignBottom.svg b/images/themes/default/mActionAlignBottom.svg index e8b41c423156..fea3443b33d5 100644 --- a/images/themes/default/mActionAlignBottom.svg +++ b/images/themes/default/mActionAlignBottom.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAlignHCenter.svg b/images/themes/default/mActionAlignHCenter.svg index b8970a867f1d..c3d925ca7bab 100644 --- a/images/themes/default/mActionAlignHCenter.svg +++ b/images/themes/default/mActionAlignHCenter.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAlignLeft.svg b/images/themes/default/mActionAlignLeft.svg index bb8f7318ec9f..039b3bf85c11 100644 --- a/images/themes/default/mActionAlignLeft.svg +++ b/images/themes/default/mActionAlignLeft.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAlignRight.svg b/images/themes/default/mActionAlignRight.svg index d134349ad3d8..5ed7bbcfcea7 100644 --- a/images/themes/default/mActionAlignRight.svg +++ b/images/themes/default/mActionAlignRight.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAlignTop.svg b/images/themes/default/mActionAlignTop.svg index 67f68023c3a7..d5395db913e9 100644 --- a/images/themes/default/mActionAlignTop.svg +++ b/images/themes/default/mActionAlignTop.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAlignVCenter.svg b/images/themes/default/mActionAlignVCenter.svg index 039e0d3219ea..b268a9baf6fa 100644 --- a/images/themes/default/mActionAlignVCenter.svg +++ b/images/themes/default/mActionAlignVCenter.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAllEdits.svg b/images/themes/default/mActionAllEdits.svg index 22f3a43d7b04..33cab762d26a 100644 --- a/images/themes/default/mActionAllEdits.svg +++ b/images/themes/default/mActionAllEdits.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAllowIntersections.svg b/images/themes/default/mActionAllowIntersections.svg index c6e23ea46967..d76e5ef1ec66 100644 --- a/images/themes/default/mActionAllowIntersections.svg +++ b/images/themes/default/mActionAllowIntersections.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAnnotation.svg b/images/themes/default/mActionAnnotation.svg index fa7692978edf..6f51a3e7a273 100644 --- a/images/themes/default/mActionAnnotation.svg +++ b/images/themes/default/mActionAnnotation.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionArrowDown.svg b/images/themes/default/mActionArrowDown.svg index 5ff205b49a5d..71ed78475b0f 100644 --- a/images/themes/default/mActionArrowDown.svg +++ b/images/themes/default/mActionArrowDown.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionArrowUp.svg b/images/themes/default/mActionArrowUp.svg index 24a10082a5b3..5bfb3aff6e8a 100644 --- a/images/themes/default/mActionArrowUp.svg +++ b/images/themes/default/mActionArrowUp.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionAtlasFirst.svg b/images/themes/default/mActionAtlasFirst.svg index 132a5bb60d34..f6d9865c5947 100644 --- a/images/themes/default/mActionAtlasFirst.svg +++ b/images/themes/default/mActionAtlasFirst.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAtlasLast.svg b/images/themes/default/mActionAtlasLast.svg index 5004814e9f08..ccb7f6c55409 100644 --- a/images/themes/default/mActionAtlasLast.svg +++ b/images/themes/default/mActionAtlasLast.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAtlasNext.svg b/images/themes/default/mActionAtlasNext.svg index 09f848ee5435..97f3257d0873 100644 --- a/images/themes/default/mActionAtlasNext.svg +++ b/images/themes/default/mActionAtlasNext.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAtlasPrev.svg b/images/themes/default/mActionAtlasPrev.svg index 172eafeb9afa..2b65201e4818 100644 --- a/images/themes/default/mActionAtlasPrev.svg +++ b/images/themes/default/mActionAtlasPrev.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mActionAtlasSettings.svg b/images/themes/default/mActionAtlasSettings.svg index 3831aa0610e7..b2cd8cfa2361 100644 --- a/images/themes/default/mActionAtlasSettings.svg +++ b/images/themes/default/mActionAtlasSettings.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAvoidIntersectionsCurrentLayer.svg b/images/themes/default/mActionAvoidIntersectionsCurrentLayer.svg index 2d03088f0334..015abdabf5be 100644 --- a/images/themes/default/mActionAvoidIntersectionsCurrentLayer.svg +++ b/images/themes/default/mActionAvoidIntersectionsCurrentLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionAvoidIntersectionsLayers.svg b/images/themes/default/mActionAvoidIntersectionsLayers.svg index 36b6dc0596ca..68e956c02691 100644 --- a/images/themes/default/mActionAvoidIntersectionsLayers.svg +++ b/images/themes/default/mActionAvoidIntersectionsLayers.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionCalculateField.svg b/images/themes/default/mActionCalculateField.svg index 32ac0e40484b..95fec2f24375 100644 --- a/images/themes/default/mActionCalculateField.svg +++ b/images/themes/default/mActionCalculateField.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCancelAllEdits.svg b/images/themes/default/mActionCancelAllEdits.svg index 138795be4984..198748223d1b 100644 --- a/images/themes/default/mActionCancelAllEdits.svg +++ b/images/themes/default/mActionCancelAllEdits.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCancelEdits.svg b/images/themes/default/mActionCancelEdits.svg index 1ba1c0b19ac0..6a93690e39bc 100644 --- a/images/themes/default/mActionCancelEdits.svg +++ b/images/themes/default/mActionCancelEdits.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCaptureLine.svg b/images/themes/default/mActionCaptureLine.svg index a43091b1801c..38520fb4bf32 100644 --- a/images/themes/default/mActionCaptureLine.svg +++ b/images/themes/default/mActionCaptureLine.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCapturePoint.svg b/images/themes/default/mActionCapturePoint.svg index 0a1a20ceb3e9..0a420ae6e696 100644 --- a/images/themes/default/mActionCapturePoint.svg +++ b/images/themes/default/mActionCapturePoint.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCapturePolygon.svg b/images/themes/default/mActionCapturePolygon.svg index 948cfe942d93..2ef533882015 100644 --- a/images/themes/default/mActionCapturePolygon.svg +++ b/images/themes/default/mActionCapturePolygon.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionChangeLabelProperties.svg b/images/themes/default/mActionChangeLabelProperties.svg index 5d2045336e82..d75a9106df25 100644 --- a/images/themes/default/mActionChangeLabelProperties.svg +++ b/images/themes/default/mActionChangeLabelProperties.svg @@ -1 +1 @@ -label abc +abc \ No newline at end of file diff --git a/images/themes/default/mActionCircle2Points.svg b/images/themes/default/mActionCircle2Points.svg index 2adbf2d7a11c..161abc4d8443 100644 --- a/images/themes/default/mActionCircle2Points.svg +++ b/images/themes/default/mActionCircle2Points.svg @@ -1,111 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircle2TangentsPoint.svg b/images/themes/default/mActionCircle2TangentsPoint.svg index eb13b731b5eb..5f09aab9bb52 100644 --- a/images/themes/default/mActionCircle2TangentsPoint.svg +++ b/images/themes/default/mActionCircle2TangentsPoint.svg @@ -1,116 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircle3Points.svg b/images/themes/default/mActionCircle3Points.svg index 826956ff31b7..616f9bab9424 100644 --- a/images/themes/default/mActionCircle3Points.svg +++ b/images/themes/default/mActionCircle3Points.svg @@ -1,116 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircle3Tangents.svg b/images/themes/default/mActionCircle3Tangents.svg index 7c29c2900e58..8d7e4958748a 100644 --- a/images/themes/default/mActionCircle3Tangents.svg +++ b/images/themes/default/mActionCircle3Tangents.svg @@ -1,116 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircleCenterPoint.svg b/images/themes/default/mActionCircleCenterPoint.svg index f3baa13448c8..b154d31b4e8a 100644 --- a/images/themes/default/mActionCircleCenterPoint.svg +++ b/images/themes/default/mActionCircleCenterPoint.svg @@ -1,111 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircleExtent.svg b/images/themes/default/mActionCircleExtent.svg index e7f029bbaf5c..e323581351c9 100644 --- a/images/themes/default/mActionCircleExtent.svg +++ b/images/themes/default/mActionCircleExtent.svg @@ -1,118 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircularStringCurvePoint.svg b/images/themes/default/mActionCircularStringCurvePoint.svg index 828dd2f67132..bc35f0d2cf5c 100644 --- a/images/themes/default/mActionCircularStringCurvePoint.svg +++ b/images/themes/default/mActionCircularStringCurvePoint.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCircularStringRadius.svg b/images/themes/default/mActionCircularStringRadius.svg index 4276762c4ce3..7e3d92e0cb99 100644 --- a/images/themes/default/mActionCircularStringRadius.svg +++ b/images/themes/default/mActionCircularStringRadius.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCollapseTree.svg b/images/themes/default/mActionCollapseTree.svg index 6571210b31c4..a2739bb75513 100644 --- a/images/themes/default/mActionCollapseTree.svg +++ b/images/themes/default/mActionCollapseTree.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionComposerManager.svg b/images/themes/default/mActionComposerManager.svg index fbc57bbde7b4..5ecd579dd88e 100644 --- a/images/themes/default/mActionComposerManager.svg +++ b/images/themes/default/mActionComposerManager.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionConditionalFormatting.svg b/images/themes/default/mActionConditionalFormatting.svg index addf2995dc7c..d2863526cb6d 100644 --- a/images/themes/default/mActionConditionalFormatting.svg +++ b/images/themes/default/mActionConditionalFormatting.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCreateMemory.svg b/images/themes/default/mActionCreateMemory.svg index adc5f21b61ee..9b6164f5bb3c 100644 --- a/images/themes/default/mActionCreateMemory.svg +++ b/images/themes/default/mActionCreateMemory.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionCreateTable.svg b/images/themes/default/mActionCreateTable.svg index 4fff4f5e5349..ba1f4901f8b0 100644 --- a/images/themes/default/mActionCreateTable.svg +++ b/images/themes/default/mActionCreateTable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionCustomProjection.svg b/images/themes/default/mActionCustomProjection.svg index aaadd2b9fa62..60779f5ca8f9 100644 --- a/images/themes/default/mActionCustomProjection.svg +++ b/images/themes/default/mActionCustomProjection.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDecreaseBrightness.svg b/images/themes/default/mActionDecreaseBrightness.svg index 947d3c955a87..228c0e6b9f48 100644 --- a/images/themes/default/mActionDecreaseBrightness.svg +++ b/images/themes/default/mActionDecreaseBrightness.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDecreaseContrast.svg b/images/themes/default/mActionDecreaseContrast.svg index a76f9c415648..e8bb16e34cf3 100644 --- a/images/themes/default/mActionDecreaseContrast.svg +++ b/images/themes/default/mActionDecreaseContrast.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDecreaseFont.svg b/images/themes/default/mActionDecreaseFont.svg index 978c1ccf68f2..f5d7e6a7ae34 100644 --- a/images/themes/default/mActionDecreaseFont.svg +++ b/images/themes/default/mActionDecreaseFont.svg @@ -1 +1 @@ -A− +A− \ No newline at end of file diff --git a/images/themes/default/mActionDeleteAttribute.svg b/images/themes/default/mActionDeleteAttribute.svg index ccecebb43c1e..82cd1bea317d 100644 --- a/images/themes/default/mActionDeleteAttribute.svg +++ b/images/themes/default/mActionDeleteAttribute.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDeletePart.svg b/images/themes/default/mActionDeletePart.svg index ccd5ff7aeded..3d8909bd05e7 100644 --- a/images/themes/default/mActionDeletePart.svg +++ b/images/themes/default/mActionDeletePart.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDeleteRing.svg b/images/themes/default/mActionDeleteRing.svg index 89378e938e51..f8b82da4eb1f 100644 --- a/images/themes/default/mActionDeleteRing.svg +++ b/images/themes/default/mActionDeleteRing.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDeleteSelected.svg b/images/themes/default/mActionDeleteSelected.svg index b442f19b9ccc..050fc4312c4f 100644 --- a/images/themes/default/mActionDeleteSelected.svg +++ b/images/themes/default/mActionDeleteSelected.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDeleteSelectedFeatures.svg b/images/themes/default/mActionDeleteSelectedFeatures.svg index f1a57a31d6dc..4b9d773ffafd 100644 --- a/images/themes/default/mActionDeleteSelectedFeatures.svg +++ b/images/themes/default/mActionDeleteSelectedFeatures.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionDeleteTable.svg b/images/themes/default/mActionDeleteTable.svg index 22c533ece901..826f8f587d69 100644 --- a/images/themes/default/mActionDeleteTable.svg +++ b/images/themes/default/mActionDeleteTable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDeselectActiveLayer.svg b/images/themes/default/mActionDeselectActiveLayer.svg index 7a6ef4ed19cf..621201d695a4 100644 --- a/images/themes/default/mActionDeselectActiveLayer.svg +++ b/images/themes/default/mActionDeselectActiveLayer.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDeselectAll.svg b/images/themes/default/mActionDeselectAll.svg index 229848dd6b45..fea34c2fa509 100644 --- a/images/themes/default/mActionDeselectAll.svg +++ b/images/themes/default/mActionDeselectAll.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDeselectAllTree.svg b/images/themes/default/mActionDeselectAllTree.svg index 234bccd5d399..967372ba7717 100644 --- a/images/themes/default/mActionDeselectAllTree.svg +++ b/images/themes/default/mActionDeselectAllTree.svg @@ -1,126 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeBottom.svg b/images/themes/default/mActionDistributeBottom.svg index 913211c5ed1a..29af246af02a 100644 --- a/images/themes/default/mActionDistributeBottom.svg +++ b/images/themes/default/mActionDistributeBottom.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeHCenter.svg b/images/themes/default/mActionDistributeHCenter.svg index 2920587c38bc..5ff4b53ad51d 100644 --- a/images/themes/default/mActionDistributeHCenter.svg +++ b/images/themes/default/mActionDistributeHCenter.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeHSpace.svg b/images/themes/default/mActionDistributeHSpace.svg index c990bdd97658..9c045acafffc 100644 --- a/images/themes/default/mActionDistributeHSpace.svg +++ b/images/themes/default/mActionDistributeHSpace.svg @@ -1,49 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeLeft.svg b/images/themes/default/mActionDistributeLeft.svg index 7bd5b8fdc76b..0e05049f6521 100644 --- a/images/themes/default/mActionDistributeLeft.svg +++ b/images/themes/default/mActionDistributeLeft.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeRight.svg b/images/themes/default/mActionDistributeRight.svg index aabc95cf353c..18339a8c843b 100644 --- a/images/themes/default/mActionDistributeRight.svg +++ b/images/themes/default/mActionDistributeRight.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeTop.svg b/images/themes/default/mActionDistributeTop.svg index 6753614a4531..b1ff210e3110 100644 --- a/images/themes/default/mActionDistributeTop.svg +++ b/images/themes/default/mActionDistributeTop.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeVCenter.svg b/images/themes/default/mActionDistributeVCenter.svg index 304abcaba5fb..8da753870ea2 100644 --- a/images/themes/default/mActionDistributeVCenter.svg +++ b/images/themes/default/mActionDistributeVCenter.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDistributeVSpace.svg b/images/themes/default/mActionDistributeVSpace.svg index 986dcecd8cbe..e39deca382bc 100644 --- a/images/themes/default/mActionDistributeVSpace.svg +++ b/images/themes/default/mActionDistributeVSpace.svg @@ -1,49 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDoubleArrowLeft.svg b/images/themes/default/mActionDoubleArrowLeft.svg index 530298dac679..5fa5f96c4c20 100644 --- a/images/themes/default/mActionDoubleArrowLeft.svg +++ b/images/themes/default/mActionDoubleArrowLeft.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDoubleArrowRight.svg b/images/themes/default/mActionDoubleArrowRight.svg index 566ed04fd174..08fd0b2df12d 100644 --- a/images/themes/default/mActionDoubleArrowRight.svg +++ b/images/themes/default/mActionDoubleArrowRight.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionDuplicateComposer.svg b/images/themes/default/mActionDuplicateComposer.svg index c2e57c6318b1..e97da7412ebe 100644 --- a/images/themes/default/mActionDuplicateComposer.svg +++ b/images/themes/default/mActionDuplicateComposer.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDuplicateFeature.svg b/images/themes/default/mActionDuplicateFeature.svg index bb5698ab007a..6841d416327c 100644 --- a/images/themes/default/mActionDuplicateFeature.svg +++ b/images/themes/default/mActionDuplicateFeature.svg @@ -1,141 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDuplicateFeatureDigitized.svg b/images/themes/default/mActionDuplicateFeatureDigitized.svg index 58e92c8583f3..5225530c7202 100644 --- a/images/themes/default/mActionDuplicateFeatureDigitized.svg +++ b/images/themes/default/mActionDuplicateFeatureDigitized.svg @@ -1,130 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionDuplicateLayer.svg b/images/themes/default/mActionDuplicateLayer.svg index 50ba3554224d..9e01ed8a5cdf 100644 --- a/images/themes/default/mActionDuplicateLayer.svg +++ b/images/themes/default/mActionDuplicateLayer.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEditCopy.svg b/images/themes/default/mActionEditCopy.svg index a872f3ddc622..dd335c8fda9d 100644 --- a/images/themes/default/mActionEditCopy.svg +++ b/images/themes/default/mActionEditCopy.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEditCut.svg b/images/themes/default/mActionEditCut.svg index 4b879d61ef07..762fcf3da798 100644 --- a/images/themes/default/mActionEditCut.svg +++ b/images/themes/default/mActionEditCut.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEditHelpContent.svg b/images/themes/default/mActionEditHelpContent.svg index 4233ee314613..d5a943f17052 100644 --- a/images/themes/default/mActionEditHelpContent.svg +++ b/images/themes/default/mActionEditHelpContent.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEditModelComponent.svg b/images/themes/default/mActionEditModelComponent.svg index cc9af01b02bc..a2848cbeaf53 100644 --- a/images/themes/default/mActionEditModelComponent.svg +++ b/images/themes/default/mActionEditModelComponent.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionEditNodesItem.svg b/images/themes/default/mActionEditNodesItem.svg index 30b14de11f48..73c927641839 100644 --- a/images/themes/default/mActionEditNodesItem.svg +++ b/images/themes/default/mActionEditNodesItem.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEditPaste.svg b/images/themes/default/mActionEditPaste.svg index 5307497fb21b..8465678acb63 100644 --- a/images/themes/default/mActionEditPaste.svg +++ b/images/themes/default/mActionEditPaste.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEditTable.svg b/images/themes/default/mActionEditTable.svg index 63be3af4c3d5..339ba67e5313 100644 --- a/images/themes/default/mActionEditTable.svg +++ b/images/themes/default/mActionEditTable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionEllipseCenter2Points.svg b/images/themes/default/mActionEllipseCenter2Points.svg index 3ecb59e29f5a..fa77e1ddd85c 100644 --- a/images/themes/default/mActionEllipseCenter2Points.svg +++ b/images/themes/default/mActionEllipseCenter2Points.svg @@ -1,124 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEllipseCenterPoint.svg b/images/themes/default/mActionEllipseCenterPoint.svg index 63809c80d4ea..d02becd9882d 100644 --- a/images/themes/default/mActionEllipseCenterPoint.svg +++ b/images/themes/default/mActionEllipseCenterPoint.svg @@ -1,120 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEllipseExtent.svg b/images/themes/default/mActionEllipseExtent.svg index a1844a312747..7d18bf5a91eb 100644 --- a/images/themes/default/mActionEllipseExtent.svg +++ b/images/themes/default/mActionEllipseExtent.svg @@ -1,126 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionEllipseFoci.svg b/images/themes/default/mActionEllipseFoci.svg index 47b1f15f45ec..ade2cc390439 100644 --- a/images/themes/default/mActionEllipseFoci.svg +++ b/images/themes/default/mActionEllipseFoci.svg @@ -1,118 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionExpandNewTree.svg b/images/themes/default/mActionExpandNewTree.svg index 11c60e2cf300..e047ff985229 100644 --- a/images/themes/default/mActionExpandNewTree.svg +++ b/images/themes/default/mActionExpandNewTree.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionExpandTree.svg b/images/themes/default/mActionExpandTree.svg index 55d5f0d9501e..68aceeba229e 100644 --- a/images/themes/default/mActionExpandTree.svg +++ b/images/themes/default/mActionExpandTree.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionExport.svg b/images/themes/default/mActionExport.svg index 7258194760f9..a18123763695 100644 --- a/images/themes/default/mActionExport.svg +++ b/images/themes/default/mActionExport.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionFileExit.svg b/images/themes/default/mActionFileExit.svg index 83fe1a831106..9fcc9c721aec 100644 --- a/images/themes/default/mActionFileExit.svg +++ b/images/themes/default/mActionFileExit.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionFileNew.svg b/images/themes/default/mActionFileNew.svg index 426eef006b54..954b8dc9b229 100644 --- a/images/themes/default/mActionFileNew.svg +++ b/images/themes/default/mActionFileNew.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFileOpen.svg b/images/themes/default/mActionFileOpen.svg index bae961870420..e2e6a202b72d 100644 --- a/images/themes/default/mActionFileOpen.svg +++ b/images/themes/default/mActionFileOpen.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFilePrint.svg b/images/themes/default/mActionFilePrint.svg index 25ce32b60f09..913734e63159 100644 --- a/images/themes/default/mActionFilePrint.svg +++ b/images/themes/default/mActionFilePrint.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFileSave.svg b/images/themes/default/mActionFileSave.svg index 103cc53e53a2..941edd7eb78c 100644 --- a/images/themes/default/mActionFileSave.svg +++ b/images/themes/default/mActionFileSave.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionFileSaveAs.svg b/images/themes/default/mActionFileSaveAs.svg index 8d1f5f298409..8a1240d87114 100644 --- a/images/themes/default/mActionFileSaveAs.svg +++ b/images/themes/default/mActionFileSaveAs.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionFillRing.svg b/images/themes/default/mActionFillRing.svg index 28c75fa38db3..33dd9095f5de 100644 --- a/images/themes/default/mActionFillRing.svg +++ b/images/themes/default/mActionFillRing.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFilter.svg b/images/themes/default/mActionFilter.svg index f0158c555d18..a64a66f3b350 100644 --- a/images/themes/default/mActionFilter.svg +++ b/images/themes/default/mActionFilter.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFilter2.svg b/images/themes/default/mActionFilter2.svg index 01695ee076d3..f40a327b9278 100644 --- a/images/themes/default/mActionFilter2.svg +++ b/images/themes/default/mActionFilter2.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFilterTableFields.svg b/images/themes/default/mActionFilterTableFields.svg index bd0f25071dfd..b02a8e0ea04f 100644 --- a/images/themes/default/mActionFilterTableFields.svg +++ b/images/themes/default/mActionFilterTableFields.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFindReplace.svg b/images/themes/default/mActionFindReplace.svg index 0018114ac15e..5e85ef2111c7 100644 --- a/images/themes/default/mActionFindReplace.svg +++ b/images/themes/default/mActionFindReplace.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionFirst.svg b/images/themes/default/mActionFirst.svg index e40a8a1dc981..dc794a7fe172 100644 --- a/images/themes/default/mActionFirst.svg +++ b/images/themes/default/mActionFirst.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionFolder.svg b/images/themes/default/mActionFolder.svg index 7b45e900e323..c303c173cd0f 100644 --- a/images/themes/default/mActionFolder.svg +++ b/images/themes/default/mActionFolder.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFormAnnotation.svg b/images/themes/default/mActionFormAnnotation.svg index cd2a57586edf..f53c4ba8c714 100644 --- a/images/themes/default/mActionFormAnnotation.svg +++ b/images/themes/default/mActionFormAnnotation.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFormView.svg b/images/themes/default/mActionFormView.svg index c1bc9a3a4914..3b30f20a4f11 100644 --- a/images/themes/default/mActionFormView.svg +++ b/images/themes/default/mActionFormView.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFromSelectedFeature.svg b/images/themes/default/mActionFromSelectedFeature.svg index 522e7448bb7f..d76fbb5fa28f 100644 --- a/images/themes/default/mActionFromSelectedFeature.svg +++ b/images/themes/default/mActionFromSelectedFeature.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionFullCumulativeCutStretch.svg b/images/themes/default/mActionFullCumulativeCutStretch.svg index b897c92c440d..6a3f9df0c8e6 100644 --- a/images/themes/default/mActionFullCumulativeCutStretch.svg +++ b/images/themes/default/mActionFullCumulativeCutStretch.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionFullHistogramStretch.svg b/images/themes/default/mActionFullHistogramStretch.svg index 08853b386949..8db98d296d6a 100644 --- a/images/themes/default/mActionFullHistogramStretch.svg +++ b/images/themes/default/mActionFullHistogramStretch.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionGroupItems.svg b/images/themes/default/mActionGroupItems.svg index d3a46b5ae744..7b477c8b0484 100644 --- a/images/themes/default/mActionGroupItems.svg +++ b/images/themes/default/mActionGroupItems.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHandleStoreFilterExpressionChecked.svg b/images/themes/default/mActionHandleStoreFilterExpressionChecked.svg index 857edd81fb30..5fb512723fcd 100644 --- a/images/themes/default/mActionHandleStoreFilterExpressionChecked.svg +++ b/images/themes/default/mActionHandleStoreFilterExpressionChecked.svg @@ -1,62 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHandleStoreFilterExpressionUnchecked.svg b/images/themes/default/mActionHandleStoreFilterExpressionUnchecked.svg index d7a81a5b877a..da433f1ab0bf 100644 --- a/images/themes/default/mActionHandleStoreFilterExpressionUnchecked.svg +++ b/images/themes/default/mActionHandleStoreFilterExpressionUnchecked.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionHelpAbout.svg b/images/themes/default/mActionHelpAbout.svg index 43d5e3921999..04d1030640f3 100644 --- a/images/themes/default/mActionHelpAbout.svg +++ b/images/themes/default/mActionHelpAbout.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHelpContents.svg b/images/themes/default/mActionHelpContents.svg index b77b190ecc74..da1ec52ad754 100644 --- a/images/themes/default/mActionHelpContents.svg +++ b/images/themes/default/mActionHelpContents.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHideAllLayers.svg b/images/themes/default/mActionHideAllLayers.svg index 8ba0ff640cd8..f1f844a15802 100644 --- a/images/themes/default/mActionHideAllLayers.svg +++ b/images/themes/default/mActionHideAllLayers.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHideDeselectedLayers.svg b/images/themes/default/mActionHideDeselectedLayers.svg index 8c63b0b0beca..88733d4c016b 100644 --- a/images/themes/default/mActionHideDeselectedLayers.svg +++ b/images/themes/default/mActionHideDeselectedLayers.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionHideSelectedLayers.svg b/images/themes/default/mActionHideSelectedLayers.svg index 89c7bbce3a4b..ad89d10bc6ee 100644 --- a/images/themes/default/mActionHideSelectedLayers.svg +++ b/images/themes/default/mActionHideSelectedLayers.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionHighlightFeature.svg b/images/themes/default/mActionHighlightFeature.svg index 7db29895d343..d00ac1485815 100644 --- a/images/themes/default/mActionHighlightFeature.svg +++ b/images/themes/default/mActionHighlightFeature.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHistory.svg b/images/themes/default/mActionHistory.svg index 04ffa8fdd681..74b98b6923b4 100644 --- a/images/themes/default/mActionHistory.svg +++ b/images/themes/default/mActionHistory.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionHtmlAnnotation.svg b/images/themes/default/mActionHtmlAnnotation.svg index 67b8b0cfcbef..15b57a2933d0 100644 --- a/images/themes/default/mActionHtmlAnnotation.svg +++ b/images/themes/default/mActionHtmlAnnotation.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIconView.svg b/images/themes/default/mActionIconView.svg index 1efe155e3a54..a7da21d365e3 100644 --- a/images/themes/default/mActionIconView.svg +++ b/images/themes/default/mActionIconView.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionIdentify.svg b/images/themes/default/mActionIdentify.svg index 18e0dab82313..27d385568900 100644 --- a/images/themes/default/mActionIdentify.svg +++ b/images/themes/default/mActionIdentify.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIdentifyByFreehand.svg b/images/themes/default/mActionIdentifyByFreehand.svg index de969b8d1123..1cd2d2f7fe79 100644 --- a/images/themes/default/mActionIdentifyByFreehand.svg +++ b/images/themes/default/mActionIdentifyByFreehand.svg @@ -1,63 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIdentifyByPolygon.svg b/images/themes/default/mActionIdentifyByPolygon.svg index 67a4a7e25501..c9cf82bf146a 100644 --- a/images/themes/default/mActionIdentifyByPolygon.svg +++ b/images/themes/default/mActionIdentifyByPolygon.svg @@ -1,63 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIdentifyByRadius.svg b/images/themes/default/mActionIdentifyByRadius.svg index b93d2aa67de7..0ec9eb61435e 100644 --- a/images/themes/default/mActionIdentifyByRadius.svg +++ b/images/themes/default/mActionIdentifyByRadius.svg @@ -1,68 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIdentifyByRectangle.svg b/images/themes/default/mActionIdentifyByRectangle.svg index 6ff7ef0c87fd..890f59e11c1f 100644 --- a/images/themes/default/mActionIdentifyByRectangle.svg +++ b/images/themes/default/mActionIdentifyByRectangle.svg @@ -1,59 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionInOverview.svg b/images/themes/default/mActionInOverview.svg index 36683a94867b..233818cee77f 100644 --- a/images/themes/default/mActionInOverview.svg +++ b/images/themes/default/mActionInOverview.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIncreaseBrightness.svg b/images/themes/default/mActionIncreaseBrightness.svg index c59643c4e23f..8cc0e6035f2d 100644 --- a/images/themes/default/mActionIncreaseBrightness.svg +++ b/images/themes/default/mActionIncreaseBrightness.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIncreaseContrast.svg b/images/themes/default/mActionIncreaseContrast.svg index ac558ab7668a..d4b7bd50e382 100644 --- a/images/themes/default/mActionIncreaseContrast.svg +++ b/images/themes/default/mActionIncreaseContrast.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionIncreaseFont.svg b/images/themes/default/mActionIncreaseFont.svg index e35b935e44cc..4c48332d2050 100644 --- a/images/themes/default/mActionIncreaseFont.svg +++ b/images/themes/default/mActionIncreaseFont.svg @@ -1 +1 @@ -A+ +A+ \ No newline at end of file diff --git a/images/themes/default/mActionInterfaceCustomization.svg b/images/themes/default/mActionInterfaceCustomization.svg index 13c73aa6dfed..fc8557f586d4 100644 --- a/images/themes/default/mActionInterfaceCustomization.svg +++ b/images/themes/default/mActionInterfaceCustomization.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionInvertSelection.svg b/images/themes/default/mActionInvertSelection.svg index a4798c041f81..d9f3f4106c16 100644 --- a/images/themes/default/mActionInvertSelection.svg +++ b/images/themes/default/mActionInvertSelection.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionKeyboardShortcuts.svg b/images/themes/default/mActionKeyboardShortcuts.svg index b05a1b331d41..89a03496eeef 100644 --- a/images/themes/default/mActionKeyboardShortcuts.svg +++ b/images/themes/default/mActionKeyboardShortcuts.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionLabel.svg b/images/themes/default/mActionLabel.svg index 6ad2e3f52419..eb436b83d028 100644 --- a/images/themes/default/mActionLabel.svg +++ b/images/themes/default/mActionLabel.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionLabeling.svg b/images/themes/default/mActionLabeling.svg index a0d4c68dc025..9d0b5af6eadb 100644 --- a/images/themes/default/mActionLabeling.svg +++ b/images/themes/default/mActionLabeling.svg @@ -1 +1 @@ -label abc +abc \ No newline at end of file diff --git a/images/themes/default/mActionLast.svg b/images/themes/default/mActionLast.svg index aed11f81a125..cc7fd7bc83ad 100644 --- a/images/themes/default/mActionLast.svg +++ b/images/themes/default/mActionLast.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionLink.svg b/images/themes/default/mActionLink.svg index 84d789ce00b8..d961794676e8 100644 --- a/images/themes/default/mActionLink.svg +++ b/images/themes/default/mActionLink.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionLocalCumulativeCutStretch.svg b/images/themes/default/mActionLocalCumulativeCutStretch.svg index 928ebd56b225..a3d325ea42d5 100644 --- a/images/themes/default/mActionLocalCumulativeCutStretch.svg +++ b/images/themes/default/mActionLocalCumulativeCutStretch.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionLocalHistogramStretch.svg b/images/themes/default/mActionLocalHistogramStretch.svg index 4a0e375d5c1c..d3b420b835dd 100644 --- a/images/themes/default/mActionLocalHistogramStretch.svg +++ b/images/themes/default/mActionLocalHistogramStretch.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionLockExtent.svg b/images/themes/default/mActionLockExtent.svg index 2fddab055128..7780fabf7e85 100644 --- a/images/themes/default/mActionLockExtent.svg +++ b/images/themes/default/mActionLockExtent.svg @@ -1,98 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionLockItems.svg b/images/themes/default/mActionLockItems.svg index abce5447c937..3a561c82198d 100644 --- a/images/themes/default/mActionLockItems.svg +++ b/images/themes/default/mActionLockItems.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionLowerItems.svg b/images/themes/default/mActionLowerItems.svg index 3b43ad5b9318..9b0cdea533f1 100644 --- a/images/themes/default/mActionLowerItems.svg +++ b/images/themes/default/mActionLowerItems.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMapIdentification.svg b/images/themes/default/mActionMapIdentification.svg index d45464643460..f60dcbb114a9 100644 --- a/images/themes/default/mActionMapIdentification.svg +++ b/images/themes/default/mActionMapIdentification.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionMapSettings.svg b/images/themes/default/mActionMapSettings.svg index f331cdb3f6c4..3c909bf1a5d4 100644 --- a/images/themes/default/mActionMapSettings.svg +++ b/images/themes/default/mActionMapSettings.svg @@ -1,177 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMapTips.svg b/images/themes/default/mActionMapTips.svg index 9014f012eff5..452ef022813e 100644 --- a/images/themes/default/mActionMapTips.svg +++ b/images/themes/default/mActionMapTips.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMeasure.svg b/images/themes/default/mActionMeasure.svg index da442cf50b45..202c802b1e0f 100644 --- a/images/themes/default/mActionMeasure.svg +++ b/images/themes/default/mActionMeasure.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMeasureAngle.svg b/images/themes/default/mActionMeasureAngle.svg index 2c5a496e5a9b..9d0c59cebd67 100644 --- a/images/themes/default/mActionMeasureAngle.svg +++ b/images/themes/default/mActionMeasureAngle.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMeasureArea.svg b/images/themes/default/mActionMeasureArea.svg index 76c4961157b7..00f390c32247 100644 --- a/images/themes/default/mActionMeasureArea.svg +++ b/images/themes/default/mActionMeasureArea.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMergeFeatureAttributes.svg b/images/themes/default/mActionMergeFeatureAttributes.svg index 3c3a30da81db..9d649b6791ca 100644 --- a/images/themes/default/mActionMergeFeatureAttributes.svg +++ b/images/themes/default/mActionMergeFeatureAttributes.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMergeFeatures.svg b/images/themes/default/mActionMergeFeatures.svg index 5d2443717f63..cb1a22ad69b3 100644 --- a/images/themes/default/mActionMergeFeatures.svg +++ b/images/themes/default/mActionMergeFeatures.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveFeature.svg b/images/themes/default/mActionMoveFeature.svg index fb4c3b096421..c064d236102c 100644 --- a/images/themes/default/mActionMoveFeature.svg +++ b/images/themes/default/mActionMoveFeature.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveFeatureCopy.svg b/images/themes/default/mActionMoveFeatureCopy.svg index e38b48b05c43..1689a5e69bc5 100644 --- a/images/themes/default/mActionMoveFeatureCopy.svg +++ b/images/themes/default/mActionMoveFeatureCopy.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveFeatureCopyLine.svg b/images/themes/default/mActionMoveFeatureCopyLine.svg index 124e4b2eb733..75b8039fd6a5 100644 --- a/images/themes/default/mActionMoveFeatureCopyLine.svg +++ b/images/themes/default/mActionMoveFeatureCopyLine.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveFeatureCopyPoint.svg b/images/themes/default/mActionMoveFeatureCopyPoint.svg index 371a61e09531..e0a00c076298 100644 --- a/images/themes/default/mActionMoveFeatureCopyPoint.svg +++ b/images/themes/default/mActionMoveFeatureCopyPoint.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveFeatureLine.svg b/images/themes/default/mActionMoveFeatureLine.svg index bdd206b25843..7c72c80d041f 100644 --- a/images/themes/default/mActionMoveFeatureLine.svg +++ b/images/themes/default/mActionMoveFeatureLine.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveFeaturePoint.svg b/images/themes/default/mActionMoveFeaturePoint.svg index 3df6c2947ba1..460047033cbf 100644 --- a/images/themes/default/mActionMoveFeaturePoint.svg +++ b/images/themes/default/mActionMoveFeaturePoint.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveItemContent.svg b/images/themes/default/mActionMoveItemContent.svg index 94004fe6a35e..95d40d5fddb6 100644 --- a/images/themes/default/mActionMoveItemContent.svg +++ b/images/themes/default/mActionMoveItemContent.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveItemsToBottom.svg b/images/themes/default/mActionMoveItemsToBottom.svg index 7f21e463d35f..ed6bc7950725 100644 --- a/images/themes/default/mActionMoveItemsToBottom.svg +++ b/images/themes/default/mActionMoveItemsToBottom.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveItemsToTop.svg b/images/themes/default/mActionMoveItemsToTop.svg index 77832f679ca2..fce02f64b4f1 100644 --- a/images/themes/default/mActionMoveItemsToTop.svg +++ b/images/themes/default/mActionMoveItemsToTop.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionMoveLabel.svg b/images/themes/default/mActionMoveLabel.svg index c06940541d22..b1cb7bb77d8a 100644 --- a/images/themes/default/mActionMoveLabel.svg +++ b/images/themes/default/mActionMoveLabel.svg @@ -1 +1 @@ -label abc +abc \ No newline at end of file diff --git a/images/themes/default/mActionMoveVertex.svg b/images/themes/default/mActionMoveVertex.svg index 6ce264dd5536..3467ba5af160 100644 --- a/images/themes/default/mActionMoveVertex.svg +++ b/images/themes/default/mActionMoveVertex.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionMultiEdit.svg b/images/themes/default/mActionMultiEdit.svg index 43ad5d9d524a..980825b5925b 100644 --- a/images/themes/default/mActionMultiEdit.svg +++ b/images/themes/default/mActionMultiEdit.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNew3DMap.svg b/images/themes/default/mActionNew3DMap.svg index b6d0c2cc3641..2c28089a09f5 100644 --- a/images/themes/default/mActionNew3DMap.svg +++ b/images/themes/default/mActionNew3DMap.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionNewAttribute.svg b/images/themes/default/mActionNewAttribute.svg index 223f556c5e14..699f1b4f62db 100644 --- a/images/themes/default/mActionNewAttribute.svg +++ b/images/themes/default/mActionNewAttribute.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNewComposer.svg b/images/themes/default/mActionNewComposer.svg index 17963085e231..4f946c6d85b9 100644 --- a/images/themes/default/mActionNewComposer.svg +++ b/images/themes/default/mActionNewComposer.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNewGeoPackageLayer.svg b/images/themes/default/mActionNewGeoPackageLayer.svg index 78ce7f3c4c3c..5d1332f8f1e6 100644 --- a/images/themes/default/mActionNewGeoPackageLayer.svg +++ b/images/themes/default/mActionNewGeoPackageLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionNewMap.svg b/images/themes/default/mActionNewMap.svg index 870684dce21a..f81fb0b7543e 100644 --- a/images/themes/default/mActionNewMap.svg +++ b/images/themes/default/mActionNewMap.svg @@ -1,98 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNewPage.svg b/images/themes/default/mActionNewPage.svg index d3652e7a30d8..f5d69c5afe5b 100644 --- a/images/themes/default/mActionNewPage.svg +++ b/images/themes/default/mActionNewPage.svg @@ -1,86 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNewSpatiaLiteLayer.svg b/images/themes/default/mActionNewSpatiaLiteLayer.svg index 1ae767a3b4b6..6ea3e7af8a84 100644 --- a/images/themes/default/mActionNewSpatiaLiteLayer.svg +++ b/images/themes/default/mActionNewSpatiaLiteLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionNewTableRow.svg b/images/themes/default/mActionNewTableRow.svg index 283c6e5d7ae9..49b7afabced0 100644 --- a/images/themes/default/mActionNewTableRow.svg +++ b/images/themes/default/mActionNewTableRow.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNewVectorLayer.svg b/images/themes/default/mActionNewVectorLayer.svg index 2bbf971e724c..9e751ee7c86e 100644 --- a/images/themes/default/mActionNewVectorLayer.svg +++ b/images/themes/default/mActionNewVectorLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionNewVirtualLayer.svg b/images/themes/default/mActionNewVirtualLayer.svg index 9455657a2f8f..6a4af8edd950 100644 --- a/images/themes/default/mActionNewVirtualLayer.svg +++ b/images/themes/default/mActionNewVirtualLayer.svg @@ -1,152 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionNext.svg b/images/themes/default/mActionNext.svg index d853600485b7..430d251bf6b2 100644 --- a/images/themes/default/mActionNext.svg +++ b/images/themes/default/mActionNext.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionOffsetCurve.svg b/images/themes/default/mActionOffsetCurve.svg index 829397e9489c..c9bb1c02abac 100644 --- a/images/themes/default/mActionOffsetCurve.svg +++ b/images/themes/default/mActionOffsetCurve.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionOffsetPointSymbols.svg b/images/themes/default/mActionOffsetPointSymbols.svg index 463a18178541..7dd9fed26160 100644 --- a/images/themes/default/mActionOffsetPointSymbols.svg +++ b/images/themes/default/mActionOffsetPointSymbols.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionOpenTable.svg b/images/themes/default/mActionOpenTable.svg index dbd42440826e..daa8b751608b 100644 --- a/images/themes/default/mActionOpenTable.svg +++ b/images/themes/default/mActionOpenTable.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionPan.svg b/images/themes/default/mActionPan.svg index c838d2290c8c..1950bffc2e37 100644 --- a/images/themes/default/mActionPan.svg +++ b/images/themes/default/mActionPan.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionPanHighlightFeature.svg b/images/themes/default/mActionPanHighlightFeature.svg index f2e78c0e99d1..ea9d0c302ec5 100644 --- a/images/themes/default/mActionPanHighlightFeature.svg +++ b/images/themes/default/mActionPanHighlightFeature.svg @@ -1,33 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionPanTo.svg b/images/themes/default/mActionPanTo.svg index 395067cfa15c..a3ce916bc6c0 100644 --- a/images/themes/default/mActionPanTo.svg +++ b/images/themes/default/mActionPanTo.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionPanToSelected.svg b/images/themes/default/mActionPanToSelected.svg index 063a361eb47a..b3e5b9123d0c 100644 --- a/images/themes/default/mActionPanToSelected.svg +++ b/images/themes/default/mActionPanToSelected.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionPinLabels.svg b/images/themes/default/mActionPinLabels.svg index efb02b6f9a12..ffbb495c452d 100644 --- a/images/themes/default/mActionPinLabels.svg +++ b/images/themes/default/mActionPinLabels.svg @@ -1 +1 @@ -label ab +ab \ No newline at end of file diff --git a/images/themes/default/mActionPlay.svg b/images/themes/default/mActionPlay.svg index aac9be0a1e6d..cb687b7d48e5 100644 --- a/images/themes/default/mActionPlay.svg +++ b/images/themes/default/mActionPlay.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionPrevious.svg b/images/themes/default/mActionPrevious.svg index eb2c5af77b06..aa50c59bb24b 100644 --- a/images/themes/default/mActionPrevious.svg +++ b/images/themes/default/mActionPrevious.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionProcessSelected.svg b/images/themes/default/mActionProcessSelected.svg index 8787beed369f..fa50ec542eb7 100644 --- a/images/themes/default/mActionProcessSelected.svg +++ b/images/themes/default/mActionProcessSelected.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionProjectProperties.svg b/images/themes/default/mActionProjectProperties.svg index 2cfc9b9783f5..5a39a3a0ff86 100644 --- a/images/themes/default/mActionProjectProperties.svg +++ b/images/themes/default/mActionProjectProperties.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionPropertiesWidget.svg b/images/themes/default/mActionPropertiesWidget.svg index b94cdfc960b7..d986e76f0661 100644 --- a/images/themes/default/mActionPropertiesWidget.svg +++ b/images/themes/default/mActionPropertiesWidget.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionPropertyItem.svg b/images/themes/default/mActionPropertyItem.svg index ef92d408b7be..a6ca4a5efc1c 100644 --- a/images/themes/default/mActionPropertyItem.svg +++ b/images/themes/default/mActionPropertyItem.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRaiseItems.svg b/images/themes/default/mActionRaiseItems.svg index 0258f320f8c5..810e67c18cf6 100644 --- a/images/themes/default/mActionRaiseItems.svg +++ b/images/themes/default/mActionRaiseItems.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRectangle3PointsDistance.svg b/images/themes/default/mActionRectangle3PointsDistance.svg index 06ff1a50b1b5..e08a0467b845 100644 --- a/images/themes/default/mActionRectangle3PointsDistance.svg +++ b/images/themes/default/mActionRectangle3PointsDistance.svg @@ -1,117 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRectangle3PointsProjected.svg b/images/themes/default/mActionRectangle3PointsProjected.svg index a07b35c760c7..0b02656e94f9 100644 --- a/images/themes/default/mActionRectangle3PointsProjected.svg +++ b/images/themes/default/mActionRectangle3PointsProjected.svg @@ -1,122 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRectangleCenter.svg b/images/themes/default/mActionRectangleCenter.svg index 718020292c1d..b82f916240bf 100644 --- a/images/themes/default/mActionRectangleCenter.svg +++ b/images/themes/default/mActionRectangleCenter.svg @@ -1,112 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRectangleExtent.svg b/images/themes/default/mActionRectangleExtent.svg index 9d73a9a6d915..e91cfa56e6f3 100644 --- a/images/themes/default/mActionRectangleExtent.svg +++ b/images/themes/default/mActionRectangleExtent.svg @@ -1,112 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRedo.svg b/images/themes/default/mActionRedo.svg index 92433cdce200..71b2ea206966 100644 --- a/images/themes/default/mActionRedo.svg +++ b/images/themes/default/mActionRedo.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRefresh.svg b/images/themes/default/mActionRefresh.svg index 231f9fb00c76..d2252e73318b 100644 --- a/images/themes/default/mActionRefresh.svg +++ b/images/themes/default/mActionRefresh.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionRegularPolygon2Points.svg b/images/themes/default/mActionRegularPolygon2Points.svg index d80c6c60914a..52b354ca496d 100644 --- a/images/themes/default/mActionRegularPolygon2Points.svg +++ b/images/themes/default/mActionRegularPolygon2Points.svg @@ -1,122 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRegularPolygonCenterCorner.svg b/images/themes/default/mActionRegularPolygonCenterCorner.svg index 565f915044ce..9a9f8eeb221d 100644 --- a/images/themes/default/mActionRegularPolygonCenterCorner.svg +++ b/images/themes/default/mActionRegularPolygonCenterCorner.svg @@ -1,122 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRegularPolygonCenterPoint.svg b/images/themes/default/mActionRegularPolygonCenterPoint.svg index b9ea3eaa2ffd..dd9de13c9920 100644 --- a/images/themes/default/mActionRegularPolygonCenterPoint.svg +++ b/images/themes/default/mActionRegularPolygonCenterPoint.svg @@ -1,122 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionReload.svg b/images/themes/default/mActionReload.svg index bfcf219d5b96..982019bbc8d4 100644 --- a/images/themes/default/mActionReload.svg +++ b/images/themes/default/mActionReload.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionRemove.svg b/images/themes/default/mActionRemove.svg index 480dceefaf2d..18b0a71be4f7 100644 --- a/images/themes/default/mActionRemove.svg +++ b/images/themes/default/mActionRemove.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRemoveAllFromOverview.svg b/images/themes/default/mActionRemoveAllFromOverview.svg index 3be421dee63b..249aaf3d8502 100644 --- a/images/themes/default/mActionRemoveAllFromOverview.svg +++ b/images/themes/default/mActionRemoveAllFromOverview.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRemoveLayer.svg b/images/themes/default/mActionRemoveLayer.svg index 5af9ff8fd077..ea9dfdd0077e 100644 --- a/images/themes/default/mActionRemoveLayer.svg +++ b/images/themes/default/mActionRemoveLayer.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRemoveSelectedFeature.svg b/images/themes/default/mActionRemoveSelectedFeature.svg index 89b89069c78a..db2c92285792 100644 --- a/images/themes/default/mActionRemoveSelectedFeature.svg +++ b/images/themes/default/mActionRemoveSelectedFeature.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionReshape.svg b/images/themes/default/mActionReshape.svg index 7a2b0923420b..74c4e78aac88 100644 --- a/images/themes/default/mActionReshape.svg +++ b/images/themes/default/mActionReshape.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionResizeNarrowest.svg b/images/themes/default/mActionResizeNarrowest.svg index 0e5f91aa257b..dba5d68d9c13 100644 --- a/images/themes/default/mActionResizeNarrowest.svg +++ b/images/themes/default/mActionResizeNarrowest.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionResizeShortest.svg b/images/themes/default/mActionResizeShortest.svg index 00f947db0d6a..61bb14430fbe 100644 --- a/images/themes/default/mActionResizeShortest.svg +++ b/images/themes/default/mActionResizeShortest.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionResizeTallest.svg b/images/themes/default/mActionResizeTallest.svg index ff7a7a770ca1..91d1ea7f5117 100644 --- a/images/themes/default/mActionResizeTallest.svg +++ b/images/themes/default/mActionResizeTallest.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionResizeWidest.svg b/images/themes/default/mActionResizeWidest.svg index ff58cfaaceef..ef7fad47f97d 100644 --- a/images/themes/default/mActionResizeWidest.svg +++ b/images/themes/default/mActionResizeWidest.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionReverseLine.svg b/images/themes/default/mActionReverseLine.svg index e40cab70bf6e..d2341531a65b 100644 --- a/images/themes/default/mActionReverseLine.svg +++ b/images/themes/default/mActionReverseLine.svg @@ -1,142 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRollbackAllEdits.svg b/images/themes/default/mActionRollbackAllEdits.svg index e17b29044cb7..46f3a30d4ac7 100644 --- a/images/themes/default/mActionRollbackAllEdits.svg +++ b/images/themes/default/mActionRollbackAllEdits.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRollbackEdits.svg b/images/themes/default/mActionRollbackEdits.svg index f129e5b2a66e..9d1936b08448 100644 --- a/images/themes/default/mActionRollbackEdits.svg +++ b/images/themes/default/mActionRollbackEdits.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRotateFeature.svg b/images/themes/default/mActionRotateFeature.svg index 8e05f1747de4..2681a358eb4a 100644 --- a/images/themes/default/mActionRotateFeature.svg +++ b/images/themes/default/mActionRotateFeature.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionRotateLabel.svg b/images/themes/default/mActionRotateLabel.svg index 55138e73c4f2..68be87c67e7a 100644 --- a/images/themes/default/mActionRotateLabel.svg +++ b/images/themes/default/mActionRotateLabel.svg @@ -1 +1 @@ -label abc +abc \ No newline at end of file diff --git a/images/themes/default/mActionRotatePointSymbols.svg b/images/themes/default/mActionRotatePointSymbols.svg index c748e7949ce5..fbdd2165f786 100644 --- a/images/themes/default/mActionRotatePointSymbols.svg +++ b/images/themes/default/mActionRotatePointSymbols.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSaveAllEdits.svg b/images/themes/default/mActionSaveAllEdits.svg index 624e835385be..0502c6a50c27 100644 --- a/images/themes/default/mActionSaveAllEdits.svg +++ b/images/themes/default/mActionSaveAllEdits.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSaveAsPDF.svg b/images/themes/default/mActionSaveAsPDF.svg index b414ae52b5e2..b78ed97060e8 100644 --- a/images/themes/default/mActionSaveAsPDF.svg +++ b/images/themes/default/mActionSaveAsPDF.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSaveAsPython.svg b/images/themes/default/mActionSaveAsPython.svg index 0cfec1d64094..b7c19bc60e72 100644 --- a/images/themes/default/mActionSaveAsPython.svg +++ b/images/themes/default/mActionSaveAsPython.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSaveAsSVG.svg b/images/themes/default/mActionSaveAsSVG.svg index 6843b12e4648..32d700be04bb 100644 --- a/images/themes/default/mActionSaveAsSVG.svg +++ b/images/themes/default/mActionSaveAsSVG.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSaveEdits.svg b/images/themes/default/mActionSaveEdits.svg index 84f24c19b5aa..2e5a3c5dd267 100644 --- a/images/themes/default/mActionSaveEdits.svg +++ b/images/themes/default/mActionSaveEdits.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSaveMapAsImage.svg b/images/themes/default/mActionSaveMapAsImage.svg index 32ba4aa4fdd4..fd801af3da62 100644 --- a/images/themes/default/mActionSaveMapAsImage.svg +++ b/images/themes/default/mActionSaveMapAsImage.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionScaleBar.svg b/images/themes/default/mActionScaleBar.svg index 24ffd1cafdc3..19a03cdd6db4 100644 --- a/images/themes/default/mActionScaleBar.svg +++ b/images/themes/default/mActionScaleBar.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionScaleHighlightFeature.svg b/images/themes/default/mActionScaleHighlightFeature.svg index 4f6d06452899..5b3b88264418 100644 --- a/images/themes/default/mActionScaleHighlightFeature.svg +++ b/images/themes/default/mActionScaleHighlightFeature.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionScriptOpen.svg b/images/themes/default/mActionScriptOpen.svg index a78187094e59..88fdc0189a38 100644 --- a/images/themes/default/mActionScriptOpen.svg +++ b/images/themes/default/mActionScriptOpen.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionSelect.svg b/images/themes/default/mActionSelect.svg index 34466739aac8..c6dcd683cb4a 100644 --- a/images/themes/default/mActionSelect.svg +++ b/images/themes/default/mActionSelect.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectAll.svg b/images/themes/default/mActionSelectAll.svg index 299acaccce4f..76c75e5eea57 100644 --- a/images/themes/default/mActionSelectAll.svg +++ b/images/themes/default/mActionSelectAll.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectAllTree.svg b/images/themes/default/mActionSelectAllTree.svg index 484410087289..77de360137ea 100644 --- a/images/themes/default/mActionSelectAllTree.svg +++ b/images/themes/default/mActionSelectAllTree.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectFreehand.svg b/images/themes/default/mActionSelectFreehand.svg index b36117a8f12f..799d711ac523 100644 --- a/images/themes/default/mActionSelectFreehand.svg +++ b/images/themes/default/mActionSelectFreehand.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectPan.svg b/images/themes/default/mActionSelectPan.svg index 3c94ae75a8cf..62d20532650e 100644 --- a/images/themes/default/mActionSelectPan.svg +++ b/images/themes/default/mActionSelectPan.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectPolygon.svg b/images/themes/default/mActionSelectPolygon.svg index 6c83855d03e9..94c226462cef 100644 --- a/images/themes/default/mActionSelectPolygon.svg +++ b/images/themes/default/mActionSelectPolygon.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectRadius.svg b/images/themes/default/mActionSelectRadius.svg index e318a364ea26..ef581de84630 100644 --- a/images/themes/default/mActionSelectRadius.svg +++ b/images/themes/default/mActionSelectRadius.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectRectangle.svg b/images/themes/default/mActionSelectRectangle.svg index 433f7657ce9c..9e05d62a975f 100644 --- a/images/themes/default/mActionSelectRectangle.svg +++ b/images/themes/default/mActionSelectRectangle.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSelectedToTop.svg b/images/themes/default/mActionSelectedToTop.svg index 3fc81c4e86b9..208b7a4778e3 100644 --- a/images/themes/default/mActionSelectedToTop.svg +++ b/images/themes/default/mActionSelectedToTop.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSetProjection.svg b/images/themes/default/mActionSetProjection.svg index ed9f271111ef..e72f3a14b617 100644 --- a/images/themes/default/mActionSetProjection.svg +++ b/images/themes/default/mActionSetProjection.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSetToCanvasExtent.svg b/images/themes/default/mActionSetToCanvasExtent.svg index e63c3742127a..a60c5fadf431 100644 --- a/images/themes/default/mActionSetToCanvasExtent.svg +++ b/images/themes/default/mActionSetToCanvasExtent.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionSetToCanvasScale.svg b/images/themes/default/mActionSetToCanvasScale.svg index 45403fcedf06..cda2c6f52325 100644 --- a/images/themes/default/mActionSetToCanvasScale.svg +++ b/images/themes/default/mActionSetToCanvasScale.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionSharing.svg b/images/themes/default/mActionSharing.svg index bc895239fc0f..6b04c950aa0f 100644 --- a/images/themes/default/mActionSharing.svg +++ b/images/themes/default/mActionSharing.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSharingExport.svg b/images/themes/default/mActionSharingExport.svg index 6850ff31e726..47cee6834ab5 100644 --- a/images/themes/default/mActionSharingExport.svg +++ b/images/themes/default/mActionSharingExport.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSharingImport.svg b/images/themes/default/mActionSharingImport.svg index 9945404d0fd9..d54c12e435b3 100644 --- a/images/themes/default/mActionSharingImport.svg +++ b/images/themes/default/mActionSharingImport.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionShowAllLayers.svg b/images/themes/default/mActionShowAllLayers.svg index d1defb3ecd1b..0eaf28e8bcb5 100644 --- a/images/themes/default/mActionShowAllLayers.svg +++ b/images/themes/default/mActionShowAllLayers.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionShowBookmarks.svg b/images/themes/default/mActionShowBookmarks.svg index d1471627200f..a639210c5bac 100644 --- a/images/themes/default/mActionShowBookmarks.svg +++ b/images/themes/default/mActionShowBookmarks.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionShowHideLabels.svg b/images/themes/default/mActionShowHideLabels.svg index 3e2564f663d0..4b657982215e 100644 --- a/images/themes/default/mActionShowHideLabels.svg +++ b/images/themes/default/mActionShowHideLabels.svg @@ -1 +1 @@ -label abc +abc \ No newline at end of file diff --git a/images/themes/default/mActionShowMeshCalculator.svg b/images/themes/default/mActionShowMeshCalculator.svg old mode 100755 new mode 100644 index 9f7cfa45eb63..5ef4919c340a --- a/images/themes/default/mActionShowMeshCalculator.svg +++ b/images/themes/default/mActionShowMeshCalculator.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionShowPinnedLabels.svg b/images/themes/default/mActionShowPinnedLabels.svg index 25f3d929f690..3944bb4db8f1 100644 --- a/images/themes/default/mActionShowPinnedLabels.svg +++ b/images/themes/default/mActionShowPinnedLabels.svg @@ -1 +1 @@ -ab \ No newline at end of file +ab \ No newline at end of file diff --git a/images/themes/default/mActionShowPluginManager.svg b/images/themes/default/mActionShowPluginManager.svg index 479d4f315d15..eb7be430fde8 100644 --- a/images/themes/default/mActionShowPluginManager.svg +++ b/images/themes/default/mActionShowPluginManager.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionShowSelectedLayers.svg b/images/themes/default/mActionShowSelectedLayers.svg index bc4c0e684e06..515484d41b74 100644 --- a/images/themes/default/mActionShowSelectedLayers.svg +++ b/images/themes/default/mActionShowSelectedLayers.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionShowUnplacedLabel.svg b/images/themes/default/mActionShowUnplacedLabel.svg index 59d6102f3b98..7265b98404d6 100644 --- a/images/themes/default/mActionShowUnplacedLabel.svg +++ b/images/themes/default/mActionShowUnplacedLabel.svg @@ -1 +1 @@ -abc \ No newline at end of file +abc \ No newline at end of file diff --git a/images/themes/default/mActionSimplify.svg b/images/themes/default/mActionSimplify.svg index ffb7ead2ef58..59dc775afd8d 100644 --- a/images/themes/default/mActionSimplify.svg +++ b/images/themes/default/mActionSimplify.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSplitFeatures.svg b/images/themes/default/mActionSplitFeatures.svg index ca0e26491716..bf6d3eb7f210 100644 --- a/images/themes/default/mActionSplitFeatures.svg +++ b/images/themes/default/mActionSplitFeatures.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSplitParts.svg b/images/themes/default/mActionSplitParts.svg index e5e3b4b49878..98867c1a0f39 100644 --- a/images/themes/default/mActionSplitParts.svg +++ b/images/themes/default/mActionSplitParts.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionStart.svg b/images/themes/default/mActionStart.svg index 3abe31727dcf..e529139e173b 100644 --- a/images/themes/default/mActionStart.svg +++ b/images/themes/default/mActionStart.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionStop.svg b/images/themes/default/mActionStop.svg index 93a3a46a7146..cfc08ec760e8 100644 --- a/images/themes/default/mActionStop.svg +++ b/images/themes/default/mActionStop.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionStyleManager.svg b/images/themes/default/mActionStyleManager.svg index 28bfca10d2b2..1dcc7a5c352d 100644 --- a/images/themes/default/mActionStyleManager.svg +++ b/images/themes/default/mActionStyleManager.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionSum.svg b/images/themes/default/mActionSum.svg index 7e54a2866be2..46efe0ca1ea7 100644 --- a/images/themes/default/mActionSum.svg +++ b/images/themes/default/mActionSum.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionSvgAnnotation.svg b/images/themes/default/mActionSvgAnnotation.svg index a77e9b29766d..66c681fffb68 100644 --- a/images/themes/default/mActionSvgAnnotation.svg +++ b/images/themes/default/mActionSvgAnnotation.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionTerminal.svg b/images/themes/default/mActionTerminal.svg index ec72c6a25382..baf8c289bbf9 100644 --- a/images/themes/default/mActionTerminal.svg +++ b/images/themes/default/mActionTerminal.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionTextAnnotation.svg b/images/themes/default/mActionTextAnnotation.svg index c7782401cea0..d017b351e02b 100644 --- a/images/themes/default/mActionTextAnnotation.svg +++ b/images/themes/default/mActionTextAnnotation.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionTiltDown.svg b/images/themes/default/mActionTiltDown.svg index be10056f12b3..7697121ee213 100644 --- a/images/themes/default/mActionTiltDown.svg +++ b/images/themes/default/mActionTiltDown.svg @@ -1,253 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionTiltUp.svg b/images/themes/default/mActionTiltUp.svg index 1f43de812507..f8ab0de384d2 100644 --- a/images/themes/default/mActionTiltUp.svg +++ b/images/themes/default/mActionTiltUp.svg @@ -1,253 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionToggleAllLayers.svg b/images/themes/default/mActionToggleAllLayers.svg index ca7dfa77df70..cab6eb843eab 100644 --- a/images/themes/default/mActionToggleAllLayers.svg +++ b/images/themes/default/mActionToggleAllLayers.svg @@ -1,165 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionToggleEditing.svg b/images/themes/default/mActionToggleEditing.svg index 980c468766e8..64883a9d2203 100644 --- a/images/themes/default/mActionToggleEditing.svg +++ b/images/themes/default/mActionToggleEditing.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionToggleSelectedLayers.svg b/images/themes/default/mActionToggleSelectedLayers.svg index e71939b9da76..df56d6cbc958 100644 --- a/images/themes/default/mActionToggleSelectedLayers.svg +++ b/images/themes/default/mActionToggleSelectedLayers.svg @@ -1,126 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionTracing.svg b/images/themes/default/mActionTracing.svg index 33ca82e93d5f..adb5cf62afe3 100644 --- a/images/themes/default/mActionTracing.svg +++ b/images/themes/default/mActionTracing.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionTrimExtendFeature.svg b/images/themes/default/mActionTrimExtendFeature.svg index 06959ebf1191..f93f284c3836 100644 --- a/images/themes/default/mActionTrimExtendFeature.svg +++ b/images/themes/default/mActionTrimExtendFeature.svg @@ -1,196 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionUndo.svg b/images/themes/default/mActionUndo.svg index 8ac778b9b2cf..00b017896640 100644 --- a/images/themes/default/mActionUndo.svg +++ b/images/themes/default/mActionUndo.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionUngroupItems.svg b/images/themes/default/mActionUngroupItems.svg index 14f635c6544f..11443646f948 100644 --- a/images/themes/default/mActionUngroupItems.svg +++ b/images/themes/default/mActionUngroupItems.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionUnlink.svg b/images/themes/default/mActionUnlink.svg index 5958eac28ca8..839721a6b2a2 100644 --- a/images/themes/default/mActionUnlink.svg +++ b/images/themes/default/mActionUnlink.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionUnlockAll.svg b/images/themes/default/mActionUnlockAll.svg index 4f55f11fd45c..8d49b2744d0b 100644 --- a/images/themes/default/mActionUnlockAll.svg +++ b/images/themes/default/mActionUnlockAll.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionVertexTool.svg b/images/themes/default/mActionVertexTool.svg index 7380841b2acc..392131080d90 100644 --- a/images/themes/default/mActionVertexTool.svg +++ b/images/themes/default/mActionVertexTool.svg @@ -1,137 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionVertexToolActiveLayer.svg b/images/themes/default/mActionVertexToolActiveLayer.svg index b455ee215ee7..ce2d8350950d 100644 --- a/images/themes/default/mActionVertexToolActiveLayer.svg +++ b/images/themes/default/mActionVertexToolActiveLayer.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionViewExtentInCanvas.svg b/images/themes/default/mActionViewExtentInCanvas.svg index 7c542517c29a..cec9efb0f46e 100644 --- a/images/themes/default/mActionViewExtentInCanvas.svg +++ b/images/themes/default/mActionViewExtentInCanvas.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionViewScaleInCanvas.svg b/images/themes/default/mActionViewScaleInCanvas.svg index 8a5060f39afa..a996511ed91e 100644 --- a/images/themes/default/mActionViewScaleInCanvas.svg +++ b/images/themes/default/mActionViewScaleInCanvas.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionWhatsThis.svg b/images/themes/default/mActionWhatsThis.svg index 0c8ec30a73af..d11a8ffbcdc1 100644 --- a/images/themes/default/mActionWhatsThis.svg +++ b/images/themes/default/mActionWhatsThis.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomActual.svg b/images/themes/default/mActionZoomActual.svg index 9c8b7df96535..053253a28203 100644 --- a/images/themes/default/mActionZoomActual.svg +++ b/images/themes/default/mActionZoomActual.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mActionZoomFullExtent.svg b/images/themes/default/mActionZoomFullExtent.svg index b5badc7db30a..083d35351591 100644 --- a/images/themes/default/mActionZoomFullExtent.svg +++ b/images/themes/default/mActionZoomFullExtent.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomIn.svg b/images/themes/default/mActionZoomIn.svg index e9ac66c06b00..c0b9b9937a80 100644 --- a/images/themes/default/mActionZoomIn.svg +++ b/images/themes/default/mActionZoomIn.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomLast.svg b/images/themes/default/mActionZoomLast.svg index 298098ae76c6..91d6b833bf33 100644 --- a/images/themes/default/mActionZoomLast.svg +++ b/images/themes/default/mActionZoomLast.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomNext.svg b/images/themes/default/mActionZoomNext.svg index cbb0b40407fe..c44f65c579c2 100644 --- a/images/themes/default/mActionZoomNext.svg +++ b/images/themes/default/mActionZoomNext.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomOut.svg b/images/themes/default/mActionZoomOut.svg index c316c7255af4..8a02e64a3e78 100644 --- a/images/themes/default/mActionZoomOut.svg +++ b/images/themes/default/mActionZoomOut.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomTo.svg b/images/themes/default/mActionZoomTo.svg index 6ec970723e31..b14339228685 100644 --- a/images/themes/default/mActionZoomTo.svg +++ b/images/themes/default/mActionZoomTo.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomToArea.svg b/images/themes/default/mActionZoomToArea.svg index 2e992d9f3f2d..da6c6805c51b 100644 --- a/images/themes/default/mActionZoomToArea.svg +++ b/images/themes/default/mActionZoomToArea.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomToBookmark.svg b/images/themes/default/mActionZoomToBookmark.svg index 0a0a3162f8b0..47017ffb2a48 100644 --- a/images/themes/default/mActionZoomToBookmark.svg +++ b/images/themes/default/mActionZoomToBookmark.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomToLayer.svg b/images/themes/default/mActionZoomToLayer.svg index aef511d051e2..b132d8d24593 100644 --- a/images/themes/default/mActionZoomToLayer.svg +++ b/images/themes/default/mActionZoomToLayer.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mActionZoomToSelected.svg b/images/themes/default/mActionZoomToSelected.svg index 2a3037ef0680..4a9d52b83bf4 100644 --- a/images/themes/default/mActionZoomToSelected.svg +++ b/images/themes/default/mActionZoomToSelected.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mAddToProject.svg b/images/themes/default/mAddToProject.svg index 850e2fda0d52..df9abd9c544b 100644 --- a/images/themes/default/mAddToProject.svg +++ b/images/themes/default/mAddToProject.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mDockify.svg b/images/themes/default/mDockify.svg index 721cd651bc7d..7b8f27dd7208 100644 --- a/images/themes/default/mDockify.svg +++ b/images/themes/default/mDockify.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mGeoPackage.svg b/images/themes/default/mGeoPackage.svg index f4449b943342..f6be7b8d3ec8 100644 --- a/images/themes/default/mGeoPackage.svg +++ b/images/themes/default/mGeoPackage.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconAfs.svg b/images/themes/default/mIconAfs.svg index 3a88f43b7bb6..aeb93667adaa 100644 --- a/images/themes/default/mIconAfs.svg +++ b/images/themes/default/mIconAfs.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconAlignBottom.svg b/images/themes/default/mIconAlignBottom.svg new file mode 100644 index 000000000000..18f8a133e8bd --- /dev/null +++ b/images/themes/default/mIconAlignBottom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/themes/default/mIconAlignCenter.svg b/images/themes/default/mIconAlignCenter.svg index 715096c1d397..4bf3a83eb647 100644 --- a/images/themes/default/mIconAlignCenter.svg +++ b/images/themes/default/mIconAlignCenter.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconAlignJustify.svg b/images/themes/default/mIconAlignJustify.svg index b9629d0aec86..2e3eccee198b 100644 --- a/images/themes/default/mIconAlignJustify.svg +++ b/images/themes/default/mIconAlignJustify.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconAlignLeft.svg b/images/themes/default/mIconAlignLeft.svg index 841fb91f4d86..1d60f4cbe75f 100644 --- a/images/themes/default/mIconAlignLeft.svg +++ b/images/themes/default/mIconAlignLeft.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconAlignRight.svg b/images/themes/default/mIconAlignRight.svg index b26eca8e989d..1307aaa4d899 100644 --- a/images/themes/default/mIconAlignRight.svg +++ b/images/themes/default/mIconAlignRight.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconAlignTop.svg b/images/themes/default/mIconAlignTop.svg new file mode 100644 index 000000000000..e261568e9985 --- /dev/null +++ b/images/themes/default/mIconAlignTop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/themes/default/mIconAlignVCenter.svg b/images/themes/default/mIconAlignVCenter.svg new file mode 100644 index 000000000000..165251953843 --- /dev/null +++ b/images/themes/default/mIconAlignVCenter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/themes/default/mIconAllRings.svg b/images/themes/default/mIconAllRings.svg index d80e8d63219f..825234b84b91 100644 --- a/images/themes/default/mIconAllRings.svg +++ b/images/themes/default/mIconAllRings.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconAms.svg b/images/themes/default/mIconAms.svg index 5bae1daea27d..e8432bad210b 100644 --- a/images/themes/default/mIconAms.svg +++ b/images/themes/default/mIconAms.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconArrangeSymbolsLeft.svg b/images/themes/default/mIconArrangeSymbolsLeft.svg index 2d5799c46f7e..c3a435a01a84 100644 --- a/images/themes/default/mIconArrangeSymbolsLeft.svg +++ b/images/themes/default/mIconArrangeSymbolsLeft.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconArrangeSymbolsRight.svg b/images/themes/default/mIconArrangeSymbolsRight.svg index 400c3d1041f5..02d37c71a2aa 100644 --- a/images/themes/default/mIconArrangeSymbolsRight.svg +++ b/images/themes/default/mIconArrangeSymbolsRight.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconAtlas.svg b/images/themes/default/mIconAtlas.svg index b71f43ec5878..d7d7870dc512 100644 --- a/images/themes/default/mIconAtlas.svg +++ b/images/themes/default/mIconAtlas.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconAutoPlacementSettings.svg b/images/themes/default/mIconAutoPlacementSettings.svg index e01e8340d6ea..7d26a1844d3b 100644 --- a/images/themes/default/mIconAutoPlacementSettings.svg +++ b/images/themes/default/mIconAutoPlacementSettings.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconAuxiliaryStorage.svg b/images/themes/default/mIconAuxiliaryStorage.svg index 0d485b2badf2..4867f4e9eedd 100644 --- a/images/themes/default/mIconAuxiliaryStorage.svg +++ b/images/themes/default/mIconAuxiliaryStorage.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconCertificate.svg b/images/themes/default/mIconCertificate.svg index c6c5a222d9b7..a6b3662ce76f 100644 --- a/images/themes/default/mIconCertificate.svg +++ b/images/themes/default/mIconCertificate.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconCertificateMissing.svg b/images/themes/default/mIconCertificateMissing.svg index 9db6b894378b..9c657289dfa2 100644 --- a/images/themes/default/mIconCertificateMissing.svg +++ b/images/themes/default/mIconCertificateMissing.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconCertificateTrusted.svg b/images/themes/default/mIconCertificateTrusted.svg index 001953e0b348..5928647a774c 100644 --- a/images/themes/default/mIconCertificateTrusted.svg +++ b/images/themes/default/mIconCertificateTrusted.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconCertificateUntrusted.svg b/images/themes/default/mIconCertificateUntrusted.svg index 21d1f4ba290f..84b55b91aac0 100644 --- a/images/themes/default/mIconCertificateUntrusted.svg +++ b/images/themes/default/mIconCertificateUntrusted.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconClearItem.svg b/images/themes/default/mIconClearItem.svg index 875f21991c23..dc4da352a6b6 100644 --- a/images/themes/default/mIconClearItem.svg +++ b/images/themes/default/mIconClearItem.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconClearText.svg b/images/themes/default/mIconClearText.svg index 7fa3d8c01fe3..9871c6a58141 100644 --- a/images/themes/default/mIconClearText.svg +++ b/images/themes/default/mIconClearText.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconClearTextHover.svg b/images/themes/default/mIconClearTextHover.svg index 3b2315d1adb5..659174c2ea74 100644 --- a/images/themes/default/mIconClearTextHover.svg +++ b/images/themes/default/mIconClearTextHover.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconClose.svg b/images/themes/default/mIconClose.svg index 1a67c81f1eb4..efeec309acf1 100644 --- a/images/themes/default/mIconClose.svg +++ b/images/themes/default/mIconClose.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconCloseTab.svg b/images/themes/default/mIconCloseTab.svg index 81e041dcae11..1bc7935c6e6a 100644 --- a/images/themes/default/mIconCloseTab.svg +++ b/images/themes/default/mIconCloseTab.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconCloseTabHover.svg b/images/themes/default/mIconCloseTabHover.svg index 11994ec38153..81f8229cf80d 100644 --- a/images/themes/default/mIconCloseTabHover.svg +++ b/images/themes/default/mIconCloseTabHover.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconCollapse.svg b/images/themes/default/mIconCollapse.svg index 7da1279d6eac..c56d17a914ba 100644 --- a/images/themes/default/mIconCollapse.svg +++ b/images/themes/default/mIconCollapse.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconCollapseSmall.svg b/images/themes/default/mIconCollapseSmall.svg index 0f64d0bf927f..2ec6479af999 100644 --- a/images/themes/default/mIconCollapseSmall.svg +++ b/images/themes/default/mIconCollapseSmall.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconColorPicker.svg b/images/themes/default/mIconColorPicker.svg index 9e8386c96d9f..98ae37935d26 100644 --- a/images/themes/default/mIconColorPicker.svg +++ b/images/themes/default/mIconColorPicker.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconColorSwatches.svg b/images/themes/default/mIconColorSwatches.svg index b830f63f8d12..529f1e845202 100644 --- a/images/themes/default/mIconColorSwatches.svg +++ b/images/themes/default/mIconColorSwatches.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconColorWheel.svg b/images/themes/default/mIconColorWheel.svg index 4e15e5f8f636..1ecb27c693f6 100644 --- a/images/themes/default/mIconColorWheel.svg +++ b/images/themes/default/mIconColorWheel.svg @@ -1,46 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconConnect.svg b/images/themes/default/mIconConnect.svg index fe11c3d3b4f0..c7596e7a6ed7 100644 --- a/images/themes/default/mIconConnect.svg +++ b/images/themes/default/mIconConnect.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconCritical.svg b/images/themes/default/mIconCritical.svg index 8c15d3d1a931..5ed0c91a7455 100644 --- a/images/themes/default/mIconCritical.svg +++ b/images/themes/default/mIconCritical.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefine.svg b/images/themes/default/mIconDataDefine.svg index 8cfc5e9c6e16..620762975976 100644 --- a/images/themes/default/mIconDataDefine.svg +++ b/images/themes/default/mIconDataDefine.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineColor.svg b/images/themes/default/mIconDataDefineColor.svg index daa1035035a6..bcbf9fa672a9 100644 --- a/images/themes/default/mIconDataDefineColor.svg +++ b/images/themes/default/mIconDataDefineColor.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineColorOn.svg b/images/themes/default/mIconDataDefineColorOn.svg index 52ef8cacac7e..afdd609ae86a 100644 --- a/images/themes/default/mIconDataDefineColorOn.svg +++ b/images/themes/default/mIconDataDefineColorOn.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineError.svg b/images/themes/default/mIconDataDefineError.svg index 9e45a9477fe2..dd35b2dc9f8e 100644 --- a/images/themes/default/mIconDataDefineError.svg +++ b/images/themes/default/mIconDataDefineError.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineExpression.svg b/images/themes/default/mIconDataDefineExpression.svg index 69e2b9a00566..7f4b21a3cc70 100644 --- a/images/themes/default/mIconDataDefineExpression.svg +++ b/images/themes/default/mIconDataDefineExpression.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineExpressionError.svg b/images/themes/default/mIconDataDefineExpressionError.svg index 7cdfed7dd450..9ea1615e9ca9 100644 --- a/images/themes/default/mIconDataDefineExpressionError.svg +++ b/images/themes/default/mIconDataDefineExpressionError.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineExpressionOn.svg b/images/themes/default/mIconDataDefineExpressionOn.svg index a4f4eb3b18ed..cce1d29788dc 100644 --- a/images/themes/default/mIconDataDefineExpressionOn.svg +++ b/images/themes/default/mIconDataDefineExpressionOn.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDataDefineOn.svg b/images/themes/default/mIconDataDefineOn.svg index 3bb4f42e2955..aaf82ff4e0bb 100644 --- a/images/themes/default/mIconDataDefineOn.svg +++ b/images/themes/default/mIconDataDefineOn.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDb2.svg b/images/themes/default/mIconDb2.svg index a4315a1e05ff..35a25359400d 100644 --- a/images/themes/default/mIconDb2.svg +++ b/images/themes/default/mIconDb2.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconDbSchema.svg b/images/themes/default/mIconDbSchema.svg index b95bc9cd1f53..c10de98a9ace 100644 --- a/images/themes/default/mIconDbSchema.svg +++ b/images/themes/default/mIconDbSchema.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconDelete.svg b/images/themes/default/mIconDelete.svg index 2b851abdddc2..6a7bd7fe7aa3 100644 --- a/images/themes/default/mIconDelete.svg +++ b/images/themes/default/mIconDelete.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconDeselected.svg b/images/themes/default/mIconDeselected.svg index 7fc0cb67863f..328ea6e55210 100644 --- a/images/themes/default/mIconDeselected.svg +++ b/images/themes/default/mIconDeselected.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mIconDropDownMenu.svg b/images/themes/default/mIconDropDownMenu.svg index bb7e73a66965..814b79d93f79 100644 --- a/images/themes/default/mIconDropDownMenu.svg +++ b/images/themes/default/mIconDropDownMenu.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mIconEditableEdits.svg b/images/themes/default/mIconEditableEdits.svg index 67f23d4b2e50..1a8ec8137476 100644 --- a/images/themes/default/mIconEditableEdits.svg +++ b/images/themes/default/mIconEditableEdits.svg @@ -1 +1 @@ -edit + \ No newline at end of file diff --git a/images/themes/default/mIconExpand.svg b/images/themes/default/mIconExpand.svg index e3ab0a9da281..7de004847d2c 100644 --- a/images/themes/default/mIconExpand.svg +++ b/images/themes/default/mIconExpand.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconExpandSmall.svg b/images/themes/default/mIconExpandSmall.svg index 5a633694dffe..dd0bb67c7e62 100644 --- a/images/themes/default/mIconExpandSmall.svg +++ b/images/themes/default/mIconExpandSmall.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconExpression.svg b/images/themes/default/mIconExpression.svg index 21923b75136a..65ebe80b22cc 100644 --- a/images/themes/default/mIconExpression.svg +++ b/images/themes/default/mIconExpression.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconExpressionFilter.svg b/images/themes/default/mIconExpressionFilter.svg index 47d4f6339359..b1d4ea6f86a2 100644 --- a/images/themes/default/mIconExpressionFilter.svg +++ b/images/themes/default/mIconExpressionFilter.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconExpressionPreview.svg b/images/themes/default/mIconExpressionPreview.svg index b4ed0b5eb79f..54e074e44778 100644 --- a/images/themes/default/mIconExpressionPreview.svg +++ b/images/themes/default/mIconExpressionPreview.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconExpressionSelect.svg b/images/themes/default/mIconExpressionSelect.svg index 3b3ec29b9fbf..189a25e6b044 100644 --- a/images/themes/default/mIconExpressionSelect.svg +++ b/images/themes/default/mIconExpressionSelect.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconExteriorRing.svg b/images/themes/default/mIconExteriorRing.svg index e757d513dbdb..66ad0f1af17d 100644 --- a/images/themes/default/mIconExteriorRing.svg +++ b/images/themes/default/mIconExteriorRing.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconFieldBinary.svg b/images/themes/default/mIconFieldBinary.svg index 993558a56e5d..9cbaecf2d9cb 100644 --- a/images/themes/default/mIconFieldBinary.svg +++ b/images/themes/default/mIconFieldBinary.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconFieldBool.svg b/images/themes/default/mIconFieldBool.svg index 394123e9c255..ea2a98fe7c16 100644 --- a/images/themes/default/mIconFieldBool.svg +++ b/images/themes/default/mIconFieldBool.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconFieldFloat.svg b/images/themes/default/mIconFieldFloat.svg index e44f7ef0c4f8..b2335ae16ebd 100644 --- a/images/themes/default/mIconFieldFloat.svg +++ b/images/themes/default/mIconFieldFloat.svg @@ -1 +1 @@ -1.2 \ No newline at end of file +1.2 \ No newline at end of file diff --git a/images/themes/default/mIconFieldInteger.svg b/images/themes/default/mIconFieldInteger.svg index fcd33b7d9aec..55105548e9f2 100644 --- a/images/themes/default/mIconFieldInteger.svg +++ b/images/themes/default/mIconFieldInteger.svg @@ -1 +1 @@ -123 \ No newline at end of file +123 \ No newline at end of file diff --git a/images/themes/default/mIconFieldText.svg b/images/themes/default/mIconFieldText.svg index ea0dfb22911c..776b28236095 100644 --- a/images/themes/default/mIconFieldText.svg +++ b/images/themes/default/mIconFieldText.svg @@ -1 +1 @@ -abc \ No newline at end of file +abc \ No newline at end of file diff --git a/images/themes/default/mIconFile.svg b/images/themes/default/mIconFile.svg index 7a4285727fe3..a1029d1dc899 100644 --- a/images/themes/default/mIconFile.svg +++ b/images/themes/default/mIconFile.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconFileLink.svg b/images/themes/default/mIconFileLink.svg index 7a3ecf1aaad6..1375504fdd6e 100644 --- a/images/themes/default/mIconFileLink.svg +++ b/images/themes/default/mIconFileLink.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconFolderHome.svg b/images/themes/default/mIconFolderHome.svg index e164a4c0cc62..fb1c4a153481 100644 --- a/images/themes/default/mIconFolderHome.svg +++ b/images/themes/default/mIconFolderHome.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconFolderOpen.svg b/images/themes/default/mIconFolderOpen.svg index f798da78373e..6d59bc7c5824 100644 --- a/images/themes/default/mIconFolderOpen.svg +++ b/images/themes/default/mIconFolderOpen.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconFormSelect.svg b/images/themes/default/mIconFormSelect.svg index 5b3b4d7193e9..7dace3bebbe3 100644 --- a/images/themes/default/mIconFormSelect.svg +++ b/images/themes/default/mIconFormSelect.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconGPU.svg b/images/themes/default/mIconGPU.svg index 898b2f5dcc9b..5efec1ab9433 100644 --- a/images/themes/default/mIconGPU.svg +++ b/images/themes/default/mIconGPU.svg @@ -1,14 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconGeonode.svg b/images/themes/default/mIconGeonode.svg index d8311e5e3c7e..23583cc5efd0 100644 --- a/images/themes/default/mIconGeonode.svg +++ b/images/themes/default/mIconGeonode.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconHamburgerMenu.svg b/images/themes/default/mIconHamburgerMenu.svg index 91ab308fcfc1..736d58108ec6 100644 --- a/images/themes/default/mIconHamburgerMenu.svg +++ b/images/themes/default/mIconHamburgerMenu.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconHistory.svg b/images/themes/default/mIconHistory.svg index 44c0ad35952f..faf7bce3049b 100644 --- a/images/themes/default/mIconHistory.svg +++ b/images/themes/default/mIconHistory.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconHtml.svg b/images/themes/default/mIconHtml.svg index 2c85503d2f57..aafcdb51cc44 100644 --- a/images/themes/default/mIconHtml.svg +++ b/images/themes/default/mIconHtml.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconInfo.svg b/images/themes/default/mIconInfo.svg index 405d043a0b43..ac07c8d6a480 100644 --- a/images/themes/default/mIconInfo.svg +++ b/images/themes/default/mIconInfo.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconInteriorRings.svg b/images/themes/default/mIconInteriorRings.svg index 3e68a665ce55..4c53864bf2bb 100644 --- a/images/themes/default/mIconInteriorRings.svg +++ b/images/themes/default/mIconInteriorRings.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconIterate.svg b/images/themes/default/mIconIterate.svg index 5ad34d826e61..df93265a60b0 100644 --- a/images/themes/default/mIconIterate.svg +++ b/images/themes/default/mIconIterate.svg @@ -1,61 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconJoinHasNotUpsertOnEdit.svg b/images/themes/default/mIconJoinHasNotUpsertOnEdit.svg index d3685c32e64c..13d0198f1749 100644 --- a/images/themes/default/mIconJoinHasNotUpsertOnEdit.svg +++ b/images/themes/default/mIconJoinHasNotUpsertOnEdit.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconJoinNotEditable.svg b/images/themes/default/mIconJoinNotEditable.svg index aa108f78dbb7..b279cc53502e 100644 --- a/images/themes/default/mIconJoinNotEditable.svg +++ b/images/themes/default/mIconJoinNotEditable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconJoinedLayerNotEditable.svg b/images/themes/default/mIconJoinedLayerNotEditable.svg index 0103cf13b3e8..b15ded528a6e 100644 --- a/images/themes/default/mIconJoinedLayerNotEditable.svg +++ b/images/themes/default/mIconJoinedLayerNotEditable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconLabelQuadrantCenter.svg b/images/themes/default/mIconLabelQuadrantCenter.svg index 0465578b58aa..9d2add3f1171 100644 --- a/images/themes/default/mIconLabelQuadrantCenter.svg +++ b/images/themes/default/mIconLabelQuadrantCenter.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconLabelQuadrantOffset.svg b/images/themes/default/mIconLabelQuadrantOffset.svg index cb5cbf5ec69e..5aabee15549c 100644 --- a/images/themes/default/mIconLabelQuadrantOffset.svg +++ b/images/themes/default/mIconLabelQuadrantOffset.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconLayout.svg b/images/themes/default/mIconLayout.svg index 218b576feced..ca09ce11bda8 100644 --- a/images/themes/default/mIconLayout.svg +++ b/images/themes/default/mIconLayout.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconLineLayer.svg b/images/themes/default/mIconLineLayer.svg index fa05e7d928af..502ee596eab3 100644 --- a/images/themes/default/mIconLineLayer.svg +++ b/images/themes/default/mIconLineLayer.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconListView.svg b/images/themes/default/mIconListView.svg index c53d39061ad2..debcecb4ef43 100644 --- a/images/themes/default/mIconListView.svg +++ b/images/themes/default/mIconListView.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconMeshLayer.svg b/images/themes/default/mIconMeshLayer.svg index fc52def944bf..3c80398d0dd6 100644 --- a/images/themes/default/mIconMeshLayer.svg +++ b/images/themes/default/mIconMeshLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconModelInput.svg b/images/themes/default/mIconModelInput.svg index 42fec1775544..faa5d49992f6 100644 --- a/images/themes/default/mIconModelInput.svg +++ b/images/themes/default/mIconModelInput.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconModelerCollapse.svg b/images/themes/default/mIconModelerCollapse.svg index 1cc42c97ce5e..6bab3c38f1c7 100644 --- a/images/themes/default/mIconModelerCollapse.svg +++ b/images/themes/default/mIconModelerCollapse.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconModelerExpand.svg b/images/themes/default/mIconModelerExpand.svg index eeb05d1a95d8..dc9be368bc66 100644 --- a/images/themes/default/mIconModelerExpand.svg +++ b/images/themes/default/mIconModelerExpand.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconMssql.svg b/images/themes/default/mIconMssql.svg index a6ea58b7e272..d987a7b0c9d4 100644 --- a/images/themes/default/mIconMssql.svg +++ b/images/themes/default/mIconMssql.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconNetworkLogger.svg b/images/themes/default/mIconNetworkLogger.svg index 32d1e04035c8..00b653c52aa9 100644 --- a/images/themes/default/mIconNetworkLogger.svg +++ b/images/themes/default/mIconNetworkLogger.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconNoPyramid.svg b/images/themes/default/mIconNoPyramid.svg index 08302897b274..0a5169ce9344 100644 --- a/images/themes/default/mIconNoPyramid.svg +++ b/images/themes/default/mIconNoPyramid.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconOracle.svg b/images/themes/default/mIconOracle.svg index fdeb0dc75322..efaeda43c069 100644 --- a/images/themes/default/mIconOracle.svg +++ b/images/themes/default/mIconOracle.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mIconOws.svg b/images/themes/default/mIconOws.svg index bb30abb7e5ec..e09c83bdcf20 100644 --- a/images/themes/default/mIconOws.svg +++ b/images/themes/default/mIconOws.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconPaintEffects.svg b/images/themes/default/mIconPaintEffects.svg index 720d934a06f3..7a14085359d8 100644 --- a/images/themes/default/mIconPaintEffects.svg +++ b/images/themes/default/mIconPaintEffects.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconPointLayer.svg b/images/themes/default/mIconPointLayer.svg index cfc390dd1da3..e04013133793 100644 --- a/images/themes/default/mIconPointLayer.svg +++ b/images/themes/default/mIconPointLayer.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconPolygonLayer.svg b/images/themes/default/mIconPolygonLayer.svg index 56fdc985afd1..ebcdaddffb77 100644 --- a/images/themes/default/mIconPolygonLayer.svg +++ b/images/themes/default/mIconPolygonLayer.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconPostgis.svg b/images/themes/default/mIconPostgis.svg index 5f16de057950..27320a3fd656 100644 --- a/images/themes/default/mIconPostgis.svg +++ b/images/themes/default/mIconPostgis.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconProjectionDisabled.svg b/images/themes/default/mIconProjectionDisabled.svg index 5f94c94ac404..391d6b9d13e2 100644 --- a/images/themes/default/mIconProjectionDisabled.svg +++ b/images/themes/default/mIconProjectionDisabled.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconProjectionEnabled.svg b/images/themes/default/mIconProjectionEnabled.svg index 39117e13a11a..d30c19d6ed30 100644 --- a/images/themes/default/mIconProjectionEnabled.svg +++ b/images/themes/default/mIconProjectionEnabled.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconProperties.svg b/images/themes/default/mIconProperties.svg index 3c554ea1a78d..67cfeeb606dc 100644 --- a/images/themes/default/mIconProperties.svg +++ b/images/themes/default/mIconProperties.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconPyramid.svg b/images/themes/default/mIconPyramid.svg index a01dfcc19c28..1db96575767c 100644 --- a/images/themes/default/mIconPyramid.svg +++ b/images/themes/default/mIconPyramid.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconPythonFile.svg b/images/themes/default/mIconPythonFile.svg index cf6f70323d82..bc19329fdd40 100644 --- a/images/themes/default/mIconPythonFile.svg +++ b/images/themes/default/mIconPythonFile.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconQgsProjectFile.svg b/images/themes/default/mIconQgsProjectFile.svg index 65c402af330b..ddae92eaee94 100644 --- a/images/themes/default/mIconQgsProjectFile.svg +++ b/images/themes/default/mIconQgsProjectFile.svg @@ -1,159 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconQptFile.svg b/images/themes/default/mIconQptFile.svg index 7f92ff957666..a497bd4daf8e 100644 --- a/images/themes/default/mIconQptFile.svg +++ b/images/themes/default/mIconQptFile.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconRaster.svg b/images/themes/default/mIconRaster.svg index e12ff52406ce..673f25f77ed2 100644 --- a/images/themes/default/mIconRaster.svg +++ b/images/themes/default/mIconRaster.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconRasterGroup.svg b/images/themes/default/mIconRasterGroup.svg index fe1b300bdad1..7eb78aa52843 100644 --- a/images/themes/default/mIconRasterGroup.svg +++ b/images/themes/default/mIconRasterGroup.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconRasterLayer.svg b/images/themes/default/mIconRasterLayer.svg index 9028438552f8..9106b9179bc0 100644 --- a/images/themes/default/mIconRasterLayer.svg +++ b/images/themes/default/mIconRasterLayer.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconRasterLink.svg b/images/themes/default/mIconRasterLink.svg index f79309551a66..914f18337151 100644 --- a/images/themes/default/mIconRasterLink.svg +++ b/images/themes/default/mIconRasterLink.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconRenderingDisabled.svg b/images/themes/default/mIconRenderingDisabled.svg index 2ac9f8f6f60d..007ccedd9aed 100644 --- a/images/themes/default/mIconRenderingDisabled.svg +++ b/images/themes/default/mIconRenderingDisabled.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconRenderingEnabled.svg b/images/themes/default/mIconRenderingEnabled.svg index 2ae8afe03369..1cec61b006e9 100644 --- a/images/themes/default/mIconRenderingEnabled.svg +++ b/images/themes/default/mIconRenderingEnabled.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - -X - - +X \ No newline at end of file diff --git a/images/themes/default/mIconSelectAdd.svg b/images/themes/default/mIconSelectAdd.svg index 4dec09f10073..69003b0b53c0 100644 --- a/images/themes/default/mIconSelectAdd.svg +++ b/images/themes/default/mIconSelectAdd.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSelectIntersect.svg b/images/themes/default/mIconSelectIntersect.svg index f3a9909686cd..391b813c68b2 100644 --- a/images/themes/default/mIconSelectIntersect.svg +++ b/images/themes/default/mIconSelectIntersect.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSelectRemove.svg b/images/themes/default/mIconSelectRemove.svg index b17a32792438..8d10cbe76b17 100644 --- a/images/themes/default/mIconSelectRemove.svg +++ b/images/themes/default/mIconSelectRemove.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSelected.svg b/images/themes/default/mIconSelected.svg index 7fb2c30a7cbf..85c003c1a2ca 100644 --- a/images/themes/default/mIconSelected.svg +++ b/images/themes/default/mIconSelected.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnapping.svg b/images/themes/default/mIconSnapping.svg index e9a72633b44c..f2f3535d5e3c 100644 --- a/images/themes/default/mIconSnapping.svg +++ b/images/themes/default/mIconSnapping.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingActiveLayer.svg b/images/themes/default/mIconSnappingActiveLayer.svg index 08eb446c2c10..92e8203bd3d9 100644 --- a/images/themes/default/mIconSnappingActiveLayer.svg +++ b/images/themes/default/mIconSnappingActiveLayer.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingAdvanced.svg b/images/themes/default/mIconSnappingAdvanced.svg index 303b4d152ebd..eb1dd1a874cd 100644 --- a/images/themes/default/mIconSnappingAdvanced.svg +++ b/images/themes/default/mIconSnappingAdvanced.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingAllLayers.svg b/images/themes/default/mIconSnappingAllLayers.svg index f164e656d53a..028d8681e1c9 100644 --- a/images/themes/default/mIconSnappingAllLayers.svg +++ b/images/themes/default/mIconSnappingAllLayers.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingArea.svg b/images/themes/default/mIconSnappingArea.svg index a6e4705be00d..a6028a7f4d8c 100644 --- a/images/themes/default/mIconSnappingArea.svg +++ b/images/themes/default/mIconSnappingArea.svg @@ -1,55 +1 @@ - - - - - - image/svg+xml - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingCentroid.svg b/images/themes/default/mIconSnappingCentroid.svg index 34af46c0db2b..d6d180789624 100644 --- a/images/themes/default/mIconSnappingCentroid.svg +++ b/images/themes/default/mIconSnappingCentroid.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingIntersection.svg b/images/themes/default/mIconSnappingIntersection.svg index ddc42ee62db2..304174c211e1 100644 --- a/images/themes/default/mIconSnappingIntersection.svg +++ b/images/themes/default/mIconSnappingIntersection.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingMiddle.svg b/images/themes/default/mIconSnappingMiddle.svg index 5021b2e67b0c..84d84510315c 100644 --- a/images/themes/default/mIconSnappingMiddle.svg +++ b/images/themes/default/mIconSnappingMiddle.svg @@ -1,75 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingOnScale.svg b/images/themes/default/mIconSnappingOnScale.svg index f2869a29e397..254141d6c3f2 100644 --- a/images/themes/default/mIconSnappingOnScale.svg +++ b/images/themes/default/mIconSnappingOnScale.svg @@ -1,158 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingSegment.svg b/images/themes/default/mIconSnappingSegment.svg index 849e2aea8802..8cb027425db2 100644 --- a/images/themes/default/mIconSnappingSegment.svg +++ b/images/themes/default/mIconSnappingSegment.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingSelf.svg b/images/themes/default/mIconSnappingSelf.svg index 0acabecae37c..d79323d7a385 100644 --- a/images/themes/default/mIconSnappingSelf.svg +++ b/images/themes/default/mIconSnappingSelf.svg @@ -1,141 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingVertex.svg b/images/themes/default/mIconSnappingVertex.svg index b5744e20d76a..26ce40ea2187 100644 --- a/images/themes/default/mIconSnappingVertex.svg +++ b/images/themes/default/mIconSnappingVertex.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSnappingVertexAndSegment.svg b/images/themes/default/mIconSnappingVertexAndSegment.svg index 0aeb8f7b419b..8fe69dfcfd7c 100644 --- a/images/themes/default/mIconSnappingVertexAndSegment.svg +++ b/images/themes/default/mIconSnappingVertexAndSegment.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconSpatialite.svg b/images/themes/default/mIconSpatialite.svg index e615c189e98f..817c27ee51e6 100644 --- a/images/themes/default/mIconSpatialite.svg +++ b/images/themes/default/mIconSpatialite.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconStopRendering.svg b/images/themes/default/mIconStopRendering.svg index beffbbca4534..06f8dbfa4240 100644 --- a/images/themes/default/mIconStopRendering.svg +++ b/images/themes/default/mIconStopRendering.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconStopwatch.svg b/images/themes/default/mIconStopwatch.svg index 2f89b7060270..d9bf6f87feb8 100644 --- a/images/themes/default/mIconStopwatch.svg +++ b/images/themes/default/mIconStopwatch.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconSuccess.svg b/images/themes/default/mIconSuccess.svg index 7e70ca92d39a..6cd3a174ee03 100644 --- a/images/themes/default/mIconSuccess.svg +++ b/images/themes/default/mIconSuccess.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIconTableLayer.svg b/images/themes/default/mIconTableLayer.svg index 01851343aeb1..04721728b00d 100644 --- a/images/themes/default/mIconTableLayer.svg +++ b/images/themes/default/mIconTableLayer.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconTimerContinue.svg b/images/themes/default/mIconTimerContinue.svg index 1bcd763561c0..9f4b27ad9084 100644 --- a/images/themes/default/mIconTimerContinue.svg +++ b/images/themes/default/mIconTimerContinue.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconTimerPause.svg b/images/themes/default/mIconTimerPause.svg index 7e3e2fd13b3c..a5032af62f40 100644 --- a/images/themes/default/mIconTimerPause.svg +++ b/images/themes/default/mIconTimerPause.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconTopologicalEditing.svg b/images/themes/default/mIconTopologicalEditing.svg index 531217a41337..9bd838534ae8 100644 --- a/images/themes/default/mIconTopologicalEditing.svg +++ b/images/themes/default/mIconTopologicalEditing.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconTreeView.svg b/images/themes/default/mIconTreeView.svg index f0f95dedb1c5..a663ccfe4376 100644 --- a/images/themes/default/mIconTreeView.svg +++ b/images/themes/default/mIconTreeView.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconVector.svg b/images/themes/default/mIconVector.svg index 91ae8b9316dd..318d631f1075 100644 --- a/images/themes/default/mIconVector.svg +++ b/images/themes/default/mIconVector.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconVirtualLayer.svg b/images/themes/default/mIconVirtualLayer.svg index c884d565fb69..dee8d10ba17d 100644 --- a/images/themes/default/mIconVirtualLayer.svg +++ b/images/themes/default/mIconVirtualLayer.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconWcs.svg b/images/themes/default/mIconWcs.svg index c2baff450675..8e27a7991eba 100644 --- a/images/themes/default/mIconWcs.svg +++ b/images/themes/default/mIconWcs.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIconWfs.svg b/images/themes/default/mIconWfs.svg index 9f6645d5c060..0cb7df2f5efe 100644 --- a/images/themes/default/mIconWfs.svg +++ b/images/themes/default/mIconWfs.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconWms.svg b/images/themes/default/mIconWms.svg index 716a9065e745..fbe28492b2fe 100644 --- a/images/themes/default/mIconWms.svg +++ b/images/themes/default/mIconWms.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIconZoom.svg b/images/themes/default/mIconZoom.svg index afc8c3ea234d..22c17faa3371 100644 --- a/images/themes/default/mIconZoom.svg +++ b/images/themes/default/mIconZoom.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIndicatorBadLayer.svg b/images/themes/default/mIndicatorBadLayer.svg index ad2436f5eb45..d3714fc49401 100644 --- a/images/themes/default/mIndicatorBadLayer.svg +++ b/images/themes/default/mIndicatorBadLayer.svg @@ -1,88 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIndicatorEmbedded.svg b/images/themes/default/mIndicatorEmbedded.svg index bfe87f14ad30..10b460e48114 100644 --- a/images/themes/default/mIndicatorEmbedded.svg +++ b/images/themes/default/mIndicatorEmbedded.svg @@ -1,66 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mIndicatorFilter.svg b/images/themes/default/mIndicatorFilter.svg index 851fd6e9b5c1..d83d5d1a747d 100644 --- a/images/themes/default/mIndicatorFilter.svg +++ b/images/themes/default/mIndicatorFilter.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIndicatorLayerError.svg b/images/themes/default/mIndicatorLayerError.svg index 696560319f1d..cd208b26c0ea 100644 --- a/images/themes/default/mIndicatorLayerError.svg +++ b/images/themes/default/mIndicatorLayerError.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIndicatorMemory.svg b/images/themes/default/mIndicatorMemory.svg index e87c86b94e68..74265f977779 100644 --- a/images/themes/default/mIndicatorMemory.svg +++ b/images/themes/default/mIndicatorMemory.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIndicatorNonRemovable.svg b/images/themes/default/mIndicatorNonRemovable.svg index 1ac4e2a36fd4..da6b5d69a3d2 100644 --- a/images/themes/default/mIndicatorNonRemovable.svg +++ b/images/themes/default/mIndicatorNonRemovable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mIndicatorTemporal.svg b/images/themes/default/mIndicatorTemporal.svg index 2407e400515b..bb55b16e9f6e 100644 --- a/images/themes/default/mIndicatorTemporal.svg +++ b/images/themes/default/mIndicatorTemporal.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mIndicatorTimeFromProject.svg b/images/themes/default/mIndicatorTimeFromProject.svg index 376097db6637..54c6ebe2f34b 100644 --- a/images/themes/default/mIndicatorTimeFromProject.svg +++ b/images/themes/default/mIndicatorTimeFromProject.svg @@ -1,82 +1 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItem.svg b/images/themes/default/mLayoutItem.svg index 608f8571b60f..c3205110364e 100644 --- a/images/themes/default/mLayoutItem.svg +++ b/images/themes/default/mLayoutItem.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItem3DMap.svg b/images/themes/default/mLayoutItem3DMap.svg index 971f96a8b163..db13da5baa8b 100644 --- a/images/themes/default/mLayoutItem3DMap.svg +++ b/images/themes/default/mLayoutItem3DMap.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemHtml.svg b/images/themes/default/mLayoutItemHtml.svg index 129456c29550..ce26e0636723 100644 --- a/images/themes/default/mLayoutItemHtml.svg +++ b/images/themes/default/mLayoutItemHtml.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemLegend.svg b/images/themes/default/mLayoutItemLegend.svg index da0ef1a8626f..d9a08aecfeab 100644 --- a/images/themes/default/mLayoutItemLegend.svg +++ b/images/themes/default/mLayoutItemLegend.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemMap.svg b/images/themes/default/mLayoutItemMap.svg index 134cb4b72a7a..9dab06729d82 100644 --- a/images/themes/default/mLayoutItemMap.svg +++ b/images/themes/default/mLayoutItemMap.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemMarker.svg b/images/themes/default/mLayoutItemMarker.svg index 00e286c67574..8ade59958c18 100644 --- a/images/themes/default/mLayoutItemMarker.svg +++ b/images/themes/default/mLayoutItemMarker.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemPolygon.svg b/images/themes/default/mLayoutItemPolygon.svg index 40397de53f80..72326079ab06 100644 --- a/images/themes/default/mLayoutItemPolygon.svg +++ b/images/themes/default/mLayoutItemPolygon.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemPolyline.svg b/images/themes/default/mLayoutItemPolyline.svg index 14950f824c6b..588fcf9683d0 100644 --- a/images/themes/default/mLayoutItemPolyline.svg +++ b/images/themes/default/mLayoutItemPolyline.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemShapeEllipse.svg b/images/themes/default/mLayoutItemShapeEllipse.svg index b66d5a870f1a..512cf3763740 100644 --- a/images/themes/default/mLayoutItemShapeEllipse.svg +++ b/images/themes/default/mLayoutItemShapeEllipse.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemShapeRectangle.svg b/images/themes/default/mLayoutItemShapeRectangle.svg index 608f8571b60f..c3205110364e 100644 --- a/images/themes/default/mLayoutItemShapeRectangle.svg +++ b/images/themes/default/mLayoutItemShapeRectangle.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemShapeTriangle.svg b/images/themes/default/mLayoutItemShapeTriangle.svg index d3afd19858ed..1beace0950bd 100644 --- a/images/themes/default/mLayoutItemShapeTriangle.svg +++ b/images/themes/default/mLayoutItemShapeTriangle.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mLayoutItemTable.svg b/images/themes/default/mLayoutItemTable.svg index 650a543f87dc..17597a2ddbe8 100644 --- a/images/themes/default/mLayoutItemTable.svg +++ b/images/themes/default/mLayoutItemTable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mMessageLog.svg b/images/themes/default/mMessageLog.svg index 29c91fe4cf30..71f8edd9c5b1 100644 --- a/images/themes/default/mMessageLog.svg +++ b/images/themes/default/mMessageLog.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mMessageLogRead.svg b/images/themes/default/mMessageLogRead.svg index 4f59b951da9d..c0d87f6d29d0 100644 --- a/images/themes/default/mMessageLogRead.svg +++ b/images/themes/default/mMessageLogRead.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/mSourceFields.svg b/images/themes/default/mSourceFields.svg index 6b615a6398c3..baa730363943 100644 --- a/images/themes/default/mSourceFields.svg +++ b/images/themes/default/mSourceFields.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mTaskCancel.svg b/images/themes/default/mTaskCancel.svg index 7e07459ff5e0..09d1360d707c 100644 --- a/images/themes/default/mTaskCancel.svg +++ b/images/themes/default/mTaskCancel.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/mTaskComplete.svg b/images/themes/default/mTaskComplete.svg index 0cb02e53d2ac..8968c44b9c6c 100644 --- a/images/themes/default/mTaskComplete.svg +++ b/images/themes/default/mTaskComplete.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mTaskOnHold.svg b/images/themes/default/mTaskOnHold.svg index a420300f10e6..f2980d1c105a 100644 --- a/images/themes/default/mTaskOnHold.svg +++ b/images/themes/default/mTaskOnHold.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mTaskQueued.svg b/images/themes/default/mTaskQueued.svg index d402dedc4afe..655b0d0af6f1 100644 --- a/images/themes/default/mTaskQueued.svg +++ b/images/themes/default/mTaskQueued.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mTaskRunning.svg b/images/themes/default/mTaskRunning.svg index aac9be0a1e6d..cb687b7d48e5 100644 --- a/images/themes/default/mTaskRunning.svg +++ b/images/themes/default/mTaskRunning.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mTaskTerminated.svg b/images/themes/default/mTaskTerminated.svg index 1f93e8f354db..82f88248ab1d 100644 --- a/images/themes/default/mTaskTerminated.svg +++ b/images/themes/default/mTaskTerminated.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/mTemporalNavigationAnimated.svg b/images/themes/default/mTemporalNavigationAnimated.svg index 5599dea1b49e..fdaed52c4203 100644 --- a/images/themes/default/mTemporalNavigationAnimated.svg +++ b/images/themes/default/mTemporalNavigationAnimated.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mTemporalNavigationFixedRange.svg b/images/themes/default/mTemporalNavigationFixedRange.svg index e63fa929d215..5dac4d178b12 100644 --- a/images/themes/default/mTemporalNavigationFixedRange.svg +++ b/images/themes/default/mTemporalNavigationFixedRange.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mTemporalNavigationOff.svg b/images/themes/default/mTemporalNavigationOff.svg index 88fc1626fa6f..0c6153e9341d 100644 --- a/images/themes/default/mTemporalNavigationOff.svg +++ b/images/themes/default/mTemporalNavigationOff.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/mesh/Depth.svg b/images/themes/default/mesh/Depth.svg index 53f13c197bf6..e6edd34a60f2 100644 --- a/images/themes/default/mesh/Depth.svg +++ b/images/themes/default/mesh/Depth.svg @@ -1,189 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/Elevation.svg b/images/themes/default/mesh/Elevation.svg index cdfd489a8315..5527cd5f5806 100644 --- a/images/themes/default/mesh/Elevation.svg +++ b/images/themes/default/mesh/Elevation.svg @@ -1,184 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/Height.svg b/images/themes/default/mesh/Height.svg index 02bdd6c0106a..3f702374f474 100644 --- a/images/themes/default/mesh/Height.svg +++ b/images/themes/default/mesh/Height.svg @@ -1,194 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/MultiBottom.svg b/images/themes/default/mesh/MultiBottom.svg index c7d1f63615ba..60bf2703e4e6 100644 --- a/images/themes/default/mesh/MultiBottom.svg +++ b/images/themes/default/mesh/MultiBottom.svg @@ -1,204 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/MultiTop.svg b/images/themes/default/mesh/MultiTop.svg index 8e5ec51e88f5..4fcd186399cb 100644 --- a/images/themes/default/mesh/MultiTop.svg +++ b/images/themes/default/mesh/MultiTop.svg @@ -1,179 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/Sigma.svg b/images/themes/default/mesh/Sigma.svg index 5b0ed9d6fa2a..0d6e26b80de6 100644 --- a/images/themes/default/mesh/Sigma.svg +++ b/images/themes/default/mesh/Sigma.svg @@ -1 +1 @@ --1m-2m-3m \ No newline at end of file +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/SingleBottom.svg b/images/themes/default/mesh/SingleBottom.svg index 9a51fd905ed1..bd251860888a 100644 --- a/images/themes/default/mesh/SingleBottom.svg +++ b/images/themes/default/mesh/SingleBottom.svg @@ -1,199 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/mesh/SingleTop.svg b/images/themes/default/mesh/SingleTop.svg index ad9c766c96f4..190513d7d381 100644 --- a/images/themes/default/mesh/SingleTop.svg +++ b/images/themes/default/mesh/SingleTop.svg @@ -1,184 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - -1m - -2m - -3m - - +-1m-2m-3m \ No newline at end of file diff --git a/images/themes/default/multieditChangedValues.svg b/images/themes/default/multieditChangedValues.svg index e97465c6c23c..273b701b24f1 100644 --- a/images/themes/default/multieditChangedValues.svg +++ b/images/themes/default/multieditChangedValues.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/multieditMixedValues.svg b/images/themes/default/multieditMixedValues.svg index 35229eebfd42..3b01dc2edec9 100644 --- a/images/themes/default/multieditMixedValues.svg +++ b/images/themes/default/multieditMixedValues.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/multieditSameValues.svg b/images/themes/default/multieditSameValues.svg index 28740a4b3358..921e1fd2dc54 100644 --- a/images/themes/default/multieditSameValues.svg +++ b/images/themes/default/multieditSameValues.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/north_arrow.svg b/images/themes/default/north_arrow.svg index 3a2515241ccd..9103fe55a262 100644 --- a/images/themes/default/north_arrow.svg +++ b/images/themes/default/north_arrow.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/pie-chart.svg b/images/themes/default/pie-chart.svg index 8d6d3b9d2963..39a28d4d1747 100644 --- a/images/themes/default/pie-chart.svg +++ b/images/themes/default/pie-chart.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/pluginDeprecated.svg b/images/themes/default/pluginDeprecated.svg index 291e64b3094a..fd43f9f5d7b2 100644 --- a/images/themes/default/pluginDeprecated.svg +++ b/images/themes/default/pluginDeprecated.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/pluginNew.svg b/images/themes/default/pluginNew.svg index 6c899adefe45..fa95e79dd798 100644 --- a/images/themes/default/pluginNew.svg +++ b/images/themes/default/pluginNew.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/pluginUpgrade.svg b/images/themes/default/pluginUpgrade.svg index a88cab35b948..c21e7e7cf7f9 100644 --- a/images/themes/default/pluginUpgrade.svg +++ b/images/themes/default/pluginUpgrade.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/processingAlgorithm.svg b/images/themes/default/processingAlgorithm.svg index f891c284c528..b9470f49e1bf 100644 --- a/images/themes/default/processingAlgorithm.svg +++ b/images/themes/default/processingAlgorithm.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/processingResult.svg b/images/themes/default/processingResult.svg index 4c2b3d0036d0..ce13b0ca5368 100644 --- a/images/themes/default/processingResult.svg +++ b/images/themes/default/processingResult.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/propertyicons/CRS.svg b/images/themes/default/propertyicons/CRS.svg index 698c790d3009..abf46bb8e3ac 100644 --- a/images/themes/default/propertyicons/CRS.svg +++ b/images/themes/default/propertyicons/CRS.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/action.svg b/images/themes/default/propertyicons/action.svg index aec920db4244..93e01c087521 100644 --- a/images/themes/default/propertyicons/action.svg +++ b/images/themes/default/propertyicons/action.svg @@ -1,51 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/attributes.svg b/images/themes/default/propertyicons/attributes.svg index 5985b5af6241..ac454d2d8fef 100644 --- a/images/themes/default/propertyicons/attributes.svg +++ b/images/themes/default/propertyicons/attributes.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/datadefined.svg b/images/themes/default/propertyicons/datadefined.svg index 5b289c6263f6..fb5a0232e694 100644 --- a/images/themes/default/propertyicons/datadefined.svg +++ b/images/themes/default/propertyicons/datadefined.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/diagram.svg b/images/themes/default/propertyicons/diagram.svg index 89f3fb0f75a3..13b8623cd032 100644 --- a/images/themes/default/propertyicons/diagram.svg +++ b/images/themes/default/propertyicons/diagram.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/digitizing.svg b/images/themes/default/propertyicons/digitizing.svg index 7693b932093b..b9480834c9fe 100644 --- a/images/themes/default/propertyicons/digitizing.svg +++ b/images/themes/default/propertyicons/digitizing.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/display.svg b/images/themes/default/propertyicons/display.svg index 866f4f5c8d04..dc9313f62b2a 100644 --- a/images/themes/default/propertyicons/display.svg +++ b/images/themes/default/propertyicons/display.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/editmetadata.svg b/images/themes/default/propertyicons/editmetadata.svg index cea1cbfb2888..95f16b542727 100644 --- a/images/themes/default/propertyicons/editmetadata.svg +++ b/images/themes/default/propertyicons/editmetadata.svg @@ -1,145 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/gdal.svg b/images/themes/default/propertyicons/gdal.svg index 2a554ffdcbd5..309cce6e67fd 100644 --- a/images/themes/default/propertyicons/gdal.svg +++ b/images/themes/default/propertyicons/gdal.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/general.svg b/images/themes/default/propertyicons/general.svg index 785a973e9a44..a2b6b557ac22 100644 --- a/images/themes/default/propertyicons/general.svg +++ b/images/themes/default/propertyicons/general.svg @@ -1,99 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/histogram.svg b/images/themes/default/propertyicons/histogram.svg index 35e01276c383..b3fddf3fa8bc 100644 --- a/images/themes/default/propertyicons/histogram.svg +++ b/images/themes/default/propertyicons/histogram.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/join.svg b/images/themes/default/propertyicons/join.svg index 2bc1e66c9ced..206d7ee014a1 100644 --- a/images/themes/default/propertyicons/join.svg +++ b/images/themes/default/propertyicons/join.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labelbackground.svg b/images/themes/default/propertyicons/labelbackground.svg index 98c0d7d1403d..9725f68b9f73 100644 --- a/images/themes/default/propertyicons/labelbackground.svg +++ b/images/themes/default/propertyicons/labelbackground.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labelcallout.svg b/images/themes/default/propertyicons/labelcallout.svg index 69face816b1d..bb3a4da55ffc 100644 --- a/images/themes/default/propertyicons/labelcallout.svg +++ b/images/themes/default/propertyicons/labelcallout.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labelformatting.svg b/images/themes/default/propertyicons/labelformatting.svg index 0127efc395aa..0bd709986058 100644 --- a/images/themes/default/propertyicons/labelformatting.svg +++ b/images/themes/default/propertyicons/labelformatting.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labelmask.svg b/images/themes/default/propertyicons/labelmask.svg index c9da45aff5c9..8332ee7fae2a 100644 --- a/images/themes/default/propertyicons/labelmask.svg +++ b/images/themes/default/propertyicons/labelmask.svg @@ -1,70 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labelplacement.svg b/images/themes/default/propertyicons/labelplacement.svg index e96f9e334c48..4dced8b4f12c 100644 --- a/images/themes/default/propertyicons/labelplacement.svg +++ b/images/themes/default/propertyicons/labelplacement.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labels.svg b/images/themes/default/propertyicons/labels.svg index 6119a84f8cd9..0b0d2d96c67d 100644 --- a/images/themes/default/propertyicons/labels.svg +++ b/images/themes/default/propertyicons/labels.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/labelshadow.svg b/images/themes/default/propertyicons/labelshadow.svg index 0878c287877e..6333949a5cd4 100644 --- a/images/themes/default/propertyicons/labelshadow.svg +++ b/images/themes/default/propertyicons/labelshadow.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/locale.svg b/images/themes/default/propertyicons/locale.svg index 8c369008905b..8e60f3321669 100644 --- a/images/themes/default/propertyicons/locale.svg +++ b/images/themes/default/propertyicons/locale.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/map_tools.svg b/images/themes/default/propertyicons/map_tools.svg index db4904291f8f..c38b3ef79ca8 100644 --- a/images/themes/default/propertyicons/map_tools.svg +++ b/images/themes/default/propertyicons/map_tools.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/meshaveraging.svg b/images/themes/default/propertyicons/meshaveraging.svg index 53f2ba6d085d..cc41485bda34 100644 --- a/images/themes/default/propertyicons/meshaveraging.svg +++ b/images/themes/default/propertyicons/meshaveraging.svg @@ -1,24 +1 @@ - - - - - -image/svg+xml - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/meshcontours.svg b/images/themes/default/propertyicons/meshcontours.svg index 066a388ddb9d..51c29c22aaa1 100644 --- a/images/themes/default/propertyicons/meshcontours.svg +++ b/images/themes/default/propertyicons/meshcontours.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - -image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/meshcontoursoff.svg b/images/themes/default/propertyicons/meshcontoursoff.svg index 5ffe60082548..4cca8500a012 100644 --- a/images/themes/default/propertyicons/meshcontoursoff.svg +++ b/images/themes/default/propertyicons/meshcontoursoff.svg @@ -1,27 +1 @@ - - -a - - - - - - - - - - - - - -image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/meshframe.svg b/images/themes/default/propertyicons/meshframe.svg index 6dd9a3bcbbbd..91c928616b4c 100644 --- a/images/themes/default/propertyicons/meshframe.svg +++ b/images/themes/default/propertyicons/meshframe.svg @@ -1,16 +1 @@ - - - - - -image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/meshvectors.svg b/images/themes/default/propertyicons/meshvectors.svg index 6f93efe85e3f..b2659f1e7f38 100644 --- a/images/themes/default/propertyicons/meshvectors.svg +++ b/images/themes/default/propertyicons/meshvectors.svg @@ -1,16 +1 @@ - - - - - -image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/meshvectorsoff.svg b/images/themes/default/propertyicons/meshvectorsoff.svg index 5fad13ce4236..e2366c5fdcd9 100644 --- a/images/themes/default/propertyicons/meshvectorsoff.svg +++ b/images/themes/default/propertyicons/meshvectorsoff.svg @@ -1,16 +1 @@ - - - - - -image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/metadata.svg b/images/themes/default/propertyicons/metadata.svg index 5d9289c259de..7e2d1d6463db 100644 --- a/images/themes/default/propertyicons/metadata.svg +++ b/images/themes/default/propertyicons/metadata.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/network_and_proxy.svg b/images/themes/default/propertyicons/network_and_proxy.svg index 56ff89433762..f280d5706c28 100644 --- a/images/themes/default/propertyicons/network_and_proxy.svg +++ b/images/themes/default/propertyicons/network_and_proxy.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/overlay.svg b/images/themes/default/propertyicons/overlay.svg index 395b129b4ff1..db8b59d2f3f2 100644 --- a/images/themes/default/propertyicons/overlay.svg +++ b/images/themes/default/propertyicons/overlay.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/plugin-incompatible.svg b/images/themes/default/propertyicons/plugin-incompatible.svg index d26c5b8299f7..465413f3e4d2 100644 --- a/images/themes/default/propertyicons/plugin-incompatible.svg +++ b/images/themes/default/propertyicons/plugin-incompatible.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/plugin-install_from_zip.svg b/images/themes/default/propertyicons/plugin-install_from_zip.svg index ee332d9a86b7..4603e4998047 100644 --- a/images/themes/default/propertyicons/plugin-install_from_zip.svg +++ b/images/themes/default/propertyicons/plugin-install_from_zip.svg @@ -1,89 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/plugin-installed.svg b/images/themes/default/propertyicons/plugin-installed.svg index c3a35a56518d..06347ed84bb1 100644 --- a/images/themes/default/propertyicons/plugin-installed.svg +++ b/images/themes/default/propertyicons/plugin-installed.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/plugin-upgrade.svg b/images/themes/default/propertyicons/plugin-upgrade.svg index 3a4e5a78ae6d..11196fe3ca84 100644 --- a/images/themes/default/propertyicons/plugin-upgrade.svg +++ b/images/themes/default/propertyicons/plugin-upgrade.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/plugin.svg b/images/themes/default/propertyicons/plugin.svg index b8699dc8fe87..a95926720ba4 100644 --- a/images/themes/default/propertyicons/plugin.svg +++ b/images/themes/default/propertyicons/plugin.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/plugins.svg b/images/themes/default/propertyicons/plugins.svg index 479d4f315d15..eb7be430fde8 100644 --- a/images/themes/default/propertyicons/plugins.svg +++ b/images/themes/default/propertyicons/plugins.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/pyramids.svg b/images/themes/default/propertyicons/pyramids.svg index d3cc8260174d..adc5ffd3d4e6 100644 --- a/images/themes/default/propertyicons/pyramids.svg +++ b/images/themes/default/propertyicons/pyramids.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/relations.svg b/images/themes/default/propertyicons/relations.svg index 1651d1c041cb..5e6225bffd1b 100644 --- a/images/themes/default/propertyicons/relations.svg +++ b/images/themes/default/propertyicons/relations.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/render.svg b/images/themes/default/propertyicons/render.svg index 392bac441a6a..d9bfdfcb3559 100644 --- a/images/themes/default/propertyicons/render.svg +++ b/images/themes/default/propertyicons/render.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/rendering.svg b/images/themes/default/propertyicons/rendering.svg index 9db598146898..b9d0e82181eb 100644 --- a/images/themes/default/propertyicons/rendering.svg +++ b/images/themes/default/propertyicons/rendering.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/propertyicons/settings.svg b/images/themes/default/propertyicons/settings.svg index cb066965c9bc..aa8d456786de 100644 --- a/images/themes/default/propertyicons/settings.svg +++ b/images/themes/default/propertyicons/settings.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/spacer.svg b/images/themes/default/propertyicons/spacer.svg index 34a11cc2a4ae..c180d51c6322 100644 --- a/images/themes/default/propertyicons/spacer.svg +++ b/images/themes/default/propertyicons/spacer.svg @@ -1,2 +1 @@ - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/stylepreset.svg b/images/themes/default/propertyicons/stylepreset.svg index 899c48b67416..6cdb28c84d53 100644 --- a/images/themes/default/propertyicons/stylepreset.svg +++ b/images/themes/default/propertyicons/stylepreset.svg @@ -1,56 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/symbology.svg b/images/themes/default/propertyicons/symbology.svg index bee99e5939a0..fb69cead2594 100644 --- a/images/themes/default/propertyicons/symbology.svg +++ b/images/themes/default/propertyicons/symbology.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/system.svg b/images/themes/default/propertyicons/system.svg index ead9e432b7b0..b78c4d8dcda5 100644 --- a/images/themes/default/propertyicons/system.svg +++ b/images/themes/default/propertyicons/system.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/propertyicons/temporal.svg b/images/themes/default/propertyicons/temporal.svg index ee51f16668df..b4b581a37db1 100644 --- a/images/themes/default/propertyicons/temporal.svg +++ b/images/themes/default/propertyicons/temporal.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/providerGdal.svg b/images/themes/default/providerGdal.svg index 60ac53823c94..ac75bd51ff5d 100644 --- a/images/themes/default/providerGdal.svg +++ b/images/themes/default/providerGdal.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/providerGrass.svg b/images/themes/default/providerGrass.svg index 55e886448051..ef5f01e098fe 100644 --- a/images/themes/default/providerGrass.svg +++ b/images/themes/default/providerGrass.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/providerOtb.svg b/images/themes/default/providerOtb.svg index cf72491c6ccf..e132313d8e02 100644 --- a/images/themes/default/providerOtb.svg +++ b/images/themes/default/providerOtb.svg @@ -1,104 +1 @@ - - - OTB logo 16x16 - - - - image/svg+xml - - OTB logo 16x16 - - 30/06/2020 - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/providerQgis.svg b/images/themes/default/providerQgis.svg index c49b84652960..315de6be450a 100644 --- a/images/themes/default/providerQgis.svg +++ b/images/themes/default/providerQgis.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/relation.svg b/images/themes/default/relation.svg index 1651d1c041cb..5e6225bffd1b 100644 --- a/images/themes/default/relation.svg +++ b/images/themes/default/relation.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/renderer25dSymbol.svg b/images/themes/default/renderer25dSymbol.svg index 226fd6a5377b..695384e9eea5 100644 --- a/images/themes/default/renderer25dSymbol.svg +++ b/images/themes/default/renderer25dSymbol.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererCategorizedSymbol.svg b/images/themes/default/rendererCategorizedSymbol.svg index d41fba05e0da..6d8accc45447 100644 --- a/images/themes/default/rendererCategorizedSymbol.svg +++ b/images/themes/default/rendererCategorizedSymbol.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererGraduatedSymbol.svg b/images/themes/default/rendererGraduatedSymbol.svg index 0fc5a44bf85d..ed3c53319c3c 100644 --- a/images/themes/default/rendererGraduatedSymbol.svg +++ b/images/themes/default/rendererGraduatedSymbol.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererGrassSymbol.svg b/images/themes/default/rendererGrassSymbol.svg index 6d70fc00cd7c..7e7d497fab41 100644 --- a/images/themes/default/rendererGrassSymbol.svg +++ b/images/themes/default/rendererGrassSymbol.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererHeatmapSymbol.svg b/images/themes/default/rendererHeatmapSymbol.svg index d0bcaa4a5e99..e3d9ea6a11a8 100644 --- a/images/themes/default/rendererHeatmapSymbol.svg +++ b/images/themes/default/rendererHeatmapSymbol.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererInvertedSymbol.svg b/images/themes/default/rendererInvertedSymbol.svg index ebc7977e36d4..37cf98dd386a 100644 --- a/images/themes/default/rendererInvertedSymbol.svg +++ b/images/themes/default/rendererInvertedSymbol.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererNullSymbol.svg b/images/themes/default/rendererNullSymbol.svg index a3fdbce7de29..7e80e2d226a4 100644 --- a/images/themes/default/rendererNullSymbol.svg +++ b/images/themes/default/rendererNullSymbol.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererPointClusterSymbol.svg b/images/themes/default/rendererPointClusterSymbol.svg index d18989513409..66db2928dc08 100644 --- a/images/themes/default/rendererPointClusterSymbol.svg +++ b/images/themes/default/rendererPointClusterSymbol.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererPointDisplacementSymbol.svg b/images/themes/default/rendererPointDisplacementSymbol.svg index 4b8cd3614ace..2af47d7b5afe 100644 --- a/images/themes/default/rendererPointDisplacementSymbol.svg +++ b/images/themes/default/rendererPointDisplacementSymbol.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererRuleBasedSymbol.svg b/images/themes/default/rendererRuleBasedSymbol.svg index 9ace7c7389be..e8eba0b362fc 100644 --- a/images/themes/default/rendererRuleBasedSymbol.svg +++ b/images/themes/default/rendererRuleBasedSymbol.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/rendererSingleSymbol.svg b/images/themes/default/rendererSingleSymbol.svg index 02343876e256..7b4d621f6abf 100644 --- a/images/themes/default/rendererSingleSymbol.svg +++ b/images/themes/default/rendererSingleSymbol.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/repositoryConnected.svg b/images/themes/default/repositoryConnected.svg index 224778155079..1006897c2d27 100644 --- a/images/themes/default/repositoryConnected.svg +++ b/images/themes/default/repositoryConnected.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/repositoryDisabled.svg b/images/themes/default/repositoryDisabled.svg index 7008f688aa66..23bed5130de6 100644 --- a/images/themes/default/repositoryDisabled.svg +++ b/images/themes/default/repositoryDisabled.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/repositoryUnavailable.svg b/images/themes/default/repositoryUnavailable.svg index 4b299cd6d563..2fc3dcad0ec6 100644 --- a/images/themes/default/repositoryUnavailable.svg +++ b/images/themes/default/repositoryUnavailable.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/search.svg b/images/themes/default/search.svg index b185bba190ae..884b1833cca6 100644 --- a/images/themes/default/search.svg +++ b/images/themes/default/search.svg @@ -1,66 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/sort-reverse.svg b/images/themes/default/sort-reverse.svg index ebb4dffb6695..3d1c34ace0d6 100644 --- a/images/themes/default/sort-reverse.svg +++ b/images/themes/default/sort-reverse.svg @@ -1,72 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/sort.svg b/images/themes/default/sort.svg index 6d7ca9391377..a4c076d3576b 100644 --- a/images/themes/default/sort.svg +++ b/images/themes/default/sort.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/images/themes/default/stacked-bar.svg b/images/themes/default/stacked-bar.svg index 36e0552f0d1e..862009fa6021 100644 --- a/images/themes/default/stacked-bar.svg +++ b/images/themes/default/stacked-bar.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/stars_empty.svg b/images/themes/default/stars_empty.svg index 0a4c37985e26..d38d948d58aa 100644 --- a/images/themes/default/stars_empty.svg +++ b/images/themes/default/stars_empty.svg @@ -1 +1 @@ -> +> \ No newline at end of file diff --git a/images/themes/default/stars_full.svg b/images/themes/default/stars_full.svg index 3904acb89d6e..3b51438d59a2 100644 --- a/images/themes/default/stars_full.svg +++ b/images/themes/default/stars_full.svg @@ -1 +1 @@ -> +> \ No newline at end of file diff --git a/images/themes/default/styleicons/color.svg b/images/themes/default/styleicons/color.svg index 5c559f4425fc..cd638095eee9 100644 --- a/images/themes/default/styleicons/color.svg +++ b/images/themes/default/styleicons/color.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/styleicons/multibandcolor.svg b/images/themes/default/styleicons/multibandcolor.svg index 1bb2a069cc9e..bac04a2a6496 100644 --- a/images/themes/default/styleicons/multibandcolor.svg +++ b/images/themes/default/styleicons/multibandcolor.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/styleicons/paletted.svg b/images/themes/default/styleicons/paletted.svg index 9aebb6b8fce5..663379168510 100644 --- a/images/themes/default/styleicons/paletted.svg +++ b/images/themes/default/styleicons/paletted.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/styleicons/singlebandgray.svg b/images/themes/default/styleicons/singlebandgray.svg index ceea2e2791eb..89dc531e7e6c 100644 --- a/images/themes/default/styleicons/singlebandgray.svg +++ b/images/themes/default/styleicons/singlebandgray.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/styleicons/singlebandpseudocolor.svg b/images/themes/default/styleicons/singlebandpseudocolor.svg index 4a9242225b96..a3118da44830 100644 --- a/images/themes/default/styleicons/singlebandpseudocolor.svg +++ b/images/themes/default/styleicons/singlebandpseudocolor.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/action.svg b/images/themes/default/svgbase/action.svg index 15104403064a..21d49537b2a7 100644 --- a/images/themes/default/svgbase/action.svg +++ b/images/themes/default/svgbase/action.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/delete.svg b/images/themes/default/svgbase/delete.svg index be4d8ef38b75..1ebd85a1f3c5 100644 --- a/images/themes/default/svgbase/delete.svg +++ b/images/themes/default/svgbase/delete.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/deselect.svg b/images/themes/default/svgbase/deselect.svg index 0b1f413d93a6..1891ae2d3a41 100644 --- a/images/themes/default/svgbase/deselect.svg +++ b/images/themes/default/svgbase/deselect.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/hammer.svg b/images/themes/default/svgbase/hammer.svg index c1ce0a4146a5..f4721dd3910b 100644 --- a/images/themes/default/svgbase/hammer.svg +++ b/images/themes/default/svgbase/hammer.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/mouse-pointer.svg b/images/themes/default/svgbase/mouse-pointer.svg index ec565e72bf91..481bf84abddf 100644 --- a/images/themes/default/svgbase/mouse-pointer.svg +++ b/images/themes/default/svgbase/mouse-pointer.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/qgismap.svg b/images/themes/default/svgbase/qgismap.svg index 06b36ef3f840..326103bc50e3 100644 --- a/images/themes/default/svgbase/qgismap.svg +++ b/images/themes/default/svgbase/qgismap.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/screwdriver.svg b/images/themes/default/svgbase/screwdriver.svg index 994901b387bc..606eae2d1183 100644 --- a/images/themes/default/svgbase/screwdriver.svg +++ b/images/themes/default/svgbase/screwdriver.svg @@ -1,72 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/vector-layer.svg b/images/themes/default/svgbase/vector-layer.svg index 610022e7056d..88498dee9f25 100644 --- a/images/themes/default/svgbase/vector-layer.svg +++ b/images/themes/default/svgbase/vector-layer.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/svgbase/worldmap.svg b/images/themes/default/svgbase/worldmap.svg index aab0082a049c..e510b7a81950 100644 --- a/images/themes/default/svgbase/worldmap.svg +++ b/images/themes/default/svgbase/worldmap.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/symbologyAdd.svg b/images/themes/default/symbologyAdd.svg index 08805968dc61..3d4564b8c7f6 100644 --- a/images/themes/default/symbologyAdd.svg +++ b/images/themes/default/symbologyAdd.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/symbologyEdit.svg b/images/themes/default/symbologyEdit.svg index 2cfc9b9783f5..5a39a3a0ff86 100644 --- a/images/themes/default/symbologyEdit.svg +++ b/images/themes/default/symbologyEdit.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/symbologyRemove.svg b/images/themes/default/symbologyRemove.svg index fbf9d5513023..39c3166d0ae4 100644 --- a/images/themes/default/symbologyRemove.svg +++ b/images/themes/default/symbologyRemove.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/images/themes/default/sync_views.svg b/images/themes/default/sync_views.svg index 7fd5f9a5fdfd..1f95ace1868d 100644 --- a/images/themes/default/sync_views.svg +++ b/images/themes/default/sync_views.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/temporal_navigation/back.svg b/images/themes/default/temporal_navigation/back.svg index e9d36241c2b6..55b6f499e8c2 100644 --- a/images/themes/default/temporal_navigation/back.svg +++ b/images/themes/default/temporal_navigation/back.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/temporal_navigation/forward.svg b/images/themes/default/temporal_navigation/forward.svg index aac9be0a1e6d..cb687b7d48e5 100644 --- a/images/themes/default/temporal_navigation/forward.svg +++ b/images/themes/default/temporal_navigation/forward.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/temporal_navigation/pause.svg b/images/themes/default/temporal_navigation/pause.svg index b7c0b4305dc1..dcfb1199f10e 100644 --- a/images/themes/default/temporal_navigation/pause.svg +++ b/images/themes/default/temporal_navigation/pause.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/temporal_navigation/stop.svg b/images/themes/default/temporal_navigation/stop.svg index f2975318a0e5..5760379c4391 100644 --- a/images/themes/default/temporal_navigation/stop.svg +++ b/images/themes/default/temporal_navigation/stop.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/text.svg b/images/themes/default/text.svg index 44f36ecac8cd..e07fc365a9cf 100644 --- a/images/themes/default/text.svg +++ b/images/themes/default/text.svg @@ -1,3 +1 @@ - -abc - +abc \ No newline at end of file diff --git a/images/themes/default/title_label.svg b/images/themes/default/title_label.svg index 285d45b5badb..275e5da7b264 100644 --- a/images/themes/default/title_label.svg +++ b/images/themes/default/title_label.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/tracking.svg b/images/themes/default/tracking.svg index 0dca60c010b6..9c36872c5013 100644 --- a/images/themes/default/tracking.svg +++ b/images/themes/default/tracking.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/transformed.svg b/images/themes/default/transformed.svg index 6ef7df026c8b..976728bce1b5 100644 --- a/images/themes/default/transformed.svg +++ b/images/themes/default/transformed.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/unlocked.svg b/images/themes/default/unlocked.svg index 1370370cd6ec..b1999520f1de 100644 --- a/images/themes/default/unlocked.svg +++ b/images/themes/default/unlocked.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/images/themes/default/unlockedGray.svg b/images/themes/default/unlockedGray.svg index 1cdb0a295e96..e1268c458529 100644 --- a/images/themes/default/unlockedGray.svg +++ b/images/themes/default/unlockedGray.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/user.svg b/images/themes/default/user.svg index 0bbf5bd4d825..077ec294fd12 100644 --- a/images/themes/default/user.svg +++ b/images/themes/default/user.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/images/themes/default/vector_grid.svg b/images/themes/default/vector_grid.svg index cfc672c72c7e..9c8f4e32e872 100644 --- a/images/themes/default/vector_grid.svg +++ b/images/themes/default/vector_grid.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/ms-windows/Installer-Files/sidelogomaster.svg b/ms-windows/Installer-Files/sidelogomaster.svg index 505e7ce7bc9e..c6044e4a13bb 100644 --- a/ms-windows/Installer-Files/sidelogomaster.svg +++ b/ms-windows/Installer-Files/sidelogomaster.svg @@ -1,220 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - QGIS - - +QGIS \ No newline at end of file diff --git a/ms-windows/osgeo4w/package-nightly.cmd b/ms-windows/osgeo4w/package-nightly.cmd index 89796e7ab5f8..4e8887179dba 100644 --- a/ms-windows/osgeo4w/package-nightly.cmd +++ b/ms-windows/osgeo4w/package-nightly.cmd @@ -254,7 +254,7 @@ for %%g IN (%GRASS_VERSIONS%) do ( sed -e 's/@package@/%PACKAGENAME%/g' -e 's/@version@/%VERSION%/g' python.bat.tmpl >%OSGEO4W_ROOT%\bin\python-%PACKAGENAME%.bat.tmpl if errorlevel 1 (echo creation of python wrapper template failed & goto error) -sed -e 's/@package@/%PACKAGENAME%/g' -e 's/@version@/%VERSION%/g' process.bat.tmpl >%OSGEO4W_ROOT%\bin\qgis_process-%PACKAGENAME%.bat.tmpl +sed -e 's/@package@/%PACKAGENAME%/g' -e 's/@version@/%VERSION%/g' -e 's/^call py3_env.bat/call gdal-dev-py3-env.bat/' process.bat.tmpl >%OSGEO4W_ROOT%\bin\qgis_process-%PACKAGENAME%.bat.tmpl if errorlevel 1 (echo creation of qgis process wrapper template failed & goto error) touch exclude diff --git a/python/3d/3d_auto.sip b/python/3d/3d_auto.sip index 77a86ed73608..caeb4dd2221e 100644 --- a/python/3d/3d_auto.sip +++ b/python/3d/3d_auto.sip @@ -1,5 +1,6 @@ // Include auto-generated SIP files %Include auto_generated/processing/qgs3dalgorithms.sip +%Include auto_generated/qgs3d.sip %Include auto_generated/qgs3dmapsettings.sip %Include auto_generated/qgs3dtypes.sip %Include auto_generated/qgsabstractvectorlayer3drenderer.sip diff --git a/python/3d/auto_generated/qgs3d.sip.in b/python/3d/auto_generated/qgs3d.sip.in new file mode 100644 index 000000000000..180660b15499 --- /dev/null +++ b/python/3d/auto_generated/qgs3d.sip.in @@ -0,0 +1,45 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/3d/qgs3d.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + +class Qgs3D +{ +%Docstring +Qgs3D is a singleton class containing various registries and other global members +related to 3D classes. + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgs3d.h" +%End + public: + + + + static Qgs3D *instance(); +%Docstring +Returns a pointer to the singleton instance. +%End + + ~Qgs3D(); + + private: + Qgs3D( const Qgs3D &other ); +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/3d/qgs3d.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/3d/auto_generated/qgs3dmapsettings.sip.in b/python/3d/auto_generated/qgs3dmapsettings.sip.in index fbe5ab5e2a23..ed41cdeea579 100644 --- a/python/3d/auto_generated/qgs3dmapsettings.sip.in +++ b/python/3d/auto_generated/qgs3dmapsettings.sip.in @@ -352,6 +352,21 @@ Returns whether to show camera's view center as a sphere (for debugging) .. versionadded:: 3.4 %End + + void setShowLightSourceOrigins( bool enabled ); +%Docstring +Sets whether to show light source origins as a sphere (for debugging) + +.. versionadded:: 3.16 +%End + + bool showLightSourceOrigins() const; +%Docstring +Returns whether to show light source origins as a sphere (for debugging) + +.. versionadded:: 3.16 +%End + void setShowLabels( bool enabled ); %Docstring Sets whether to display labels on terrain tiles @@ -491,6 +506,14 @@ Emitted when the flag whether camera's view center is shown has changed .. versionadded:: 3.4 %End + + void showLightSourceOriginsChanged(); +%Docstring +Emitted when the flag whether light source origins are shown has changed. + +.. versionadded:: 3.15 +%End + void showLabelsChanged(); %Docstring Emitted when the flag whether labels are displayed on terrain tiles has changed diff --git a/python/3d/auto_generated/qgsphongmaterialsettings.sip.in b/python/3d/auto_generated/qgsphongmaterialsettings.sip.in index 59843cb3439b..1a8eacc0615f 100644 --- a/python/3d/auto_generated/qgsphongmaterialsettings.sip.in +++ b/python/3d/auto_generated/qgsphongmaterialsettings.sip.in @@ -28,7 +28,11 @@ with three color components: ambient, diffuse and specular. #include "qgsphongmaterialsettings.h" %End public: + QgsPhongMaterialSettings(); +%Docstring +Constructor for QgsPhongMaterialSettings. +%End QColor ambient() const; %Docstring @@ -45,6 +49,60 @@ Returns specular color component float shininess() const; %Docstring Returns shininess of the surface +%End + + bool diffuseTextureEnabled() const; +%Docstring +Returns whether the diffuse texture is used. + +.. note:: + + Diffuse textures will only be used at render time if :py:func:`~QgsPhongMaterialSettings.diffuseTextureEnabled` is ``True`` + and a :py:func:`~QgsPhongMaterialSettings.texturePath` is non-empty. + +.. seealso:: :py:func:`shouldUseDiffuseTexture` + +.. seealso:: :py:func:`setDiffuseTextureEnabled` + +.. seealso:: :py:func:`texturePath` +%End + + bool shouldUseDiffuseTexture() const; +%Docstring +Returns whether the diffuse texture should be used during rendering. + +Diffuse textures will only be used at render time if :py:func:`~QgsPhongMaterialSettings.diffuseTextureEnabled` is ``True`` +and a :py:func:`~QgsPhongMaterialSettings.texturePath` is non-empty. + +.. seealso:: :py:func:`diffuseTextureEnabled` + +.. seealso:: :py:func:`texturePath` +%End + + QString texturePath() const; +%Docstring +Returns the diffuse texture path. + +.. note:: + + Diffuse textures will only be used at render time if :py:func:`~QgsPhongMaterialSettings.diffuseTextureEnabled` is ``True`` + and a :py:func:`~QgsPhongMaterialSettings.texturePath` is non-empty. + +.. seealso:: :py:func:`setTexturePath` + +.. seealso:: :py:func:`diffuseTextureEnabled` +%End + + float textureScale() const; +%Docstring +Returns the texture scale +The texture scale changes the size of the displayed texture in the 3D scene +If the texture scale is less than 1 the texture will be stretched +%End + + float textureRotation() const; +%Docstring +Returns the texture's rotation in degrees %End void setAmbient( const QColor &ambient ); @@ -62,6 +120,46 @@ Sets specular color component void setShininess( float shininess ); %Docstring Sets shininess of the surface +%End + + void setDiffuseTextureEnabled( bool used ); +%Docstring +Sets whether the diffuse texture is enabled. + +.. note:: + + Diffuse textures will only be used at render time if :py:func:`~QgsPhongMaterialSettings.diffuseTextureEnabled` is ``True`` + and a :py:func:`~QgsPhongMaterialSettings.texturePath` is non-empty. + +.. seealso:: :py:func:`diffuseTextureEnabled` + +.. seealso:: :py:func:`setTexturePath` +%End + + void setTexturePath( const QString &path ); +%Docstring +Sets the ``path`` of the texture. + +.. note:: + + Diffuse textures will only be used at render time if :py:func:`~QgsPhongMaterialSettings.diffuseTextureEnabled` is ``True`` + and a :py:func:`~QgsPhongMaterialSettings.texturePath` is non-empty. + +.. seealso:: :py:func:`texturePath` + +.. seealso:: :py:func:`setDiffuseTextureEnabled` +%End + + void setTextureScale( float scale ); +%Docstring +Sets the texture scale +The texture scale changes the size of the displayed texture in the 3D scene +If the texture scale is less than 1 the texture will be stretched +%End + + void setTextureRotation( float rotation ); +%Docstring +Sets the texture rotation in degrees %End void readXml( const QDomElement &elem ); diff --git a/python/3d/auto_generated/symbols/qgspolygon3dsymbol.sip.in b/python/3d/auto_generated/symbols/qgspolygon3dsymbol.sip.in index e8a1a9e51507..a74a88574446 100644 --- a/python/3d/auto_generated/symbols/qgspolygon3dsymbol.sip.in +++ b/python/3d/auto_generated/symbols/qgspolygon3dsymbol.sip.in @@ -158,6 +158,20 @@ Returns edge lines color Sets edge lines color .. versionadded:: 3.8 +%End + + void setRenderedFacade( int side ); +%Docstring +Sets which facade of the buildings is rendered (0 for None, 1 for Walls, 2 for Roofs, 3 for WallsAndRoofs) + +.. versionadded:: 3.16 +%End + + int renderedFacade() const; +%Docstring +Returns which facade of the buildings is rendered (0 for None, 1 for Walls, 2 for Roofs, 3 for WallsAndRoofs) + +.. versionadded:: 3.16 %End }; diff --git a/python/console/console_sci.py b/python/console/console_sci.py index c1182958f2cc..24d294504fc8 100644 --- a/python/console/console_sci.py +++ b/python/console/console_sci.py @@ -104,7 +104,8 @@ def __init__(self, parent=None): self.runsource(line) self.history = [] - self.historyIndex = 0 + self.softHistory = [] + self.softHistoryIndex = 0 # Read history command file self.readHistoryFile() @@ -342,7 +343,15 @@ def new_prompt(self, prompt): def displayPrompt(self, more=False): self.SendScintilla(QsciScintilla.SCI_MARGINSETTEXT, 0, str.encode("..." if more else ">>>")) - def updateHistory(self, command): + def syncSoftHistory(self): + self.softHistory = self.history[:] + self.softHistory.append('') + self.softHistoryIndex = len(self.softHistory) - 1 + + def updateSoftHistory(self): + self.softHistory[self.softHistoryIndex] = self.text() + + def updateHistory(self, command, skipSoftHistory=False): if isinstance(command, list): for line in command: self.history.append(line) @@ -350,7 +359,8 @@ def updateHistory(self, command): if len(self.history) <= 0 or \ command != self.history[-1]: self.history.append(command) - self.historyIndex = len(self.history) + if not skipSoftHistory: + self.syncSoftHistory() def writeHistoryFile(self, fromCloseConsole=False): ok = False @@ -374,13 +384,15 @@ def readHistoryFile(self): for line in rH: if line != "\n": l = line.rstrip('\n') - self.updateHistory(l) + self.updateHistory(l, True) + self.syncSoftHistory() else: return def clearHistory(self, clearSession=False): if clearSession: self.history = [] + self.syncSoftHistory() msgText = QCoreApplication.translate('PythonConsole', 'Session and file history cleared successfully.') self.parent.callWidgetMessageBar(msgText) @@ -401,27 +413,23 @@ def clearHistorySession(self): self.clearHistory(True) def showPrevious(self): - if self.historyIndex < len(self.history) and self.history: - self.historyIndex += 1 - if self.historyIndex == len(self.history): - self.setText("") - pass - else: - self.setText(self.history[self.historyIndex]) + if self.softHistoryIndex < len(self.softHistory) - 1 and self.softHistory: + self.softHistoryIndex += 1 + self.setText(self.softHistory[self.softHistoryIndex]) self.move_cursor_to_end() # self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def showNext(self): - if self.historyIndex > 0 and self.history: - self.historyIndex -= 1 - if self.historyIndex == len(self.history): - self.setText("") - else: - self.setText(self.history[self.historyIndex]) - self.move_cursor_to_start() + if self.softHistoryIndex > 0 and self.softHistory: + self.softHistoryIndex -= 1 + self.setText(self.softHistory[self.softHistoryIndex]) + self.move_cursor_to_end() # self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def keyPressEvent(self, e): + # update the live history + self.updateSoftHistory() + startLine, startPos, endLine, endPos = self.getSelection() # handle invalid cursor position and multiline selections @@ -472,16 +480,11 @@ def keyPressEvent(self, e): e.accept() elif e.key() == Qt.Key_Down and not self.isListActive(): - if self.is_cursor_at_end(): - self.showPrevious() - else: - QsciScintilla.keyPressEvent(self, e) + self.showPrevious() elif e.key() == Qt.Key_Up and not self.isListActive(): - if self.is_cursor_at_start(): - self.showNext() - else: - QsciScintilla.keyPressEvent(self, e) + self.showNext() + # TODO: press event for auto-completion file directory else: t = e.text() diff --git a/python/core/auto_additions/qgsabstractdatabaseproviderconnection.py b/python/core/auto_additions/qgsabstractdatabaseproviderconnection.py index 3cd014d9167d..48c1d19467cf 100644 --- a/python/core/auto_additions/qgsabstractdatabaseproviderconnection.py +++ b/python/core/auto_additions/qgsabstractdatabaseproviderconnection.py @@ -4,3 +4,6 @@ QgsAbstractDatabaseProviderConnection.Capability.baseClass = QgsAbstractDatabaseProviderConnection QgsAbstractDatabaseProviderConnection.Capabilities.baseClass = QgsAbstractDatabaseProviderConnection Capabilities = QgsAbstractDatabaseProviderConnection # dirty hack since SIP seems to introduce the flags in module +QgsAbstractDatabaseProviderConnection.GeometryColumnCapability.baseClass = QgsAbstractDatabaseProviderConnection +QgsAbstractDatabaseProviderConnection.GeometryColumnCapabilities.baseClass = QgsAbstractDatabaseProviderConnection +GeometryColumnCapabilities = QgsAbstractDatabaseProviderConnection # dirty hack since SIP seems to introduce the flags in module diff --git a/python/core/auto_additions/qgsattributeeditorelement.py b/python/core/auto_additions/qgsattributeeditorelement.py new file mode 100644 index 000000000000..297fd6acc13d --- /dev/null +++ b/python/core/auto_additions/qgsattributeeditorelement.py @@ -0,0 +1,4 @@ +# The following has been generated automatically from src/core/qgsattributeeditorelement.h +QgsAttributeEditorRelation.Button.baseClass = QgsAttributeEditorRelation +QgsAttributeEditorRelation.Buttons.baseClass = QgsAttributeEditorRelation +Buttons = QgsAttributeEditorRelation # dirty hack since SIP seems to introduce the flags in module diff --git a/python/core/auto_generated/geometry/qgsgeometry.sip.in b/python/core/auto_generated/geometry/qgsgeometry.sip.in index 0b0458e72c0e..7ac9c015e142 100644 --- a/python/core/auto_generated/geometry/qgsgeometry.sip.in +++ b/python/core/auto_generated/geometry/qgsgeometry.sip.in @@ -917,6 +917,9 @@ Returns the oriented minimum bounding box for the geometry, which is the smalles rotated rectangle which fully encompasses the geometry. The area, angle (clockwise in degrees from North), width and height of the rotated bounding box will also be returned. +If an error was encountered while creating the result, more information can be retrieved +by calling :py:func:`~QgsGeometry.lastError` on the returned geometry. + .. seealso:: :py:func:`boundingBox` .. versionadded:: 3.0 diff --git a/python/core/auto_generated/labeling/qgspallabeling.sip.in b/python/core/auto_generated/labeling/qgspallabeling.sip.in index c76bf2f47029..8e2495d15564 100644 --- a/python/core/auto_generated/labeling/qgspallabeling.sip.in +++ b/python/core/auto_generated/labeling/qgspallabeling.sip.in @@ -167,7 +167,8 @@ class QgsPalLayerSettings MultiLeft, MultiCenter, MultiRight, - MultiFollowPlacement + MultiFollowPlacement, + MultiJustify, }; diff --git a/python/core/auto_generated/layout/qgslayoutitemattributetable.sip.in b/python/core/auto_generated/layout/qgslayoutitemattributetable.sip.in index e35ba70f7d40..439a3378d8f1 100644 --- a/python/core/auto_generated/layout/qgslayoutitemattributetable.sip.in +++ b/python/core/auto_generated/layout/qgslayoutitemattributetable.sip.in @@ -291,6 +291,8 @@ be replaced by a line break. virtual QgsConditionalStyle conditionalCellStyle( int row, int column ) const; + virtual QgsExpressionContextScope *scopeForCell( int row, int column ) const /Factory/; + virtual QgsExpressionContext createExpressionContext() const; diff --git a/python/core/auto_generated/layout/qgslayoutitemmanualtable.sip.in b/python/core/auto_generated/layout/qgslayoutitemmanualtable.sip.in index 77297a2b9759..3eac43262cf3 100644 --- a/python/core/auto_generated/layout/qgslayoutitemmanualtable.sip.in +++ b/python/core/auto_generated/layout/qgslayoutitemmanualtable.sip.in @@ -139,6 +139,14 @@ Replaces the headers in the table with a specified list of :py:class:`QgsLayoutT virtual bool calculateMaxRowHeights(); + virtual QgsTextFormat textFormatForHeader( int column ) const; + + virtual QgsTextFormat textFormatForCell( int row, int column ) const; + + virtual Qt::Alignment horizontalAlignmentForCell( int row, int column ) const; + + virtual Qt::Alignment verticalAlignmentForCell( int row, int column ) const; + }; diff --git a/python/core/auto_generated/layout/qgslayoutitemmapgrid.sip.in b/python/core/auto_generated/layout/qgslayoutitemmapgrid.sip.in index a7ac44550773..9ebeb30ea676 100644 --- a/python/core/auto_generated/layout/qgslayoutitemmapgrid.sip.in +++ b/python/core/auto_generated/layout/qgslayoutitemmapgrid.sip.in @@ -565,32 +565,62 @@ Returns whether annotations are shown for the grid. .. seealso:: :py:func:`setAnnotationEnabled` %End - void setAnnotationFont( const QFont &font ); + void setAnnotationTextFormat( const QgsTextFormat &format ); +%Docstring +Sets the text ``format`` to use when rendering grid annotations. + +.. seealso:: :py:func:`annotationTextFormat` + +.. versionadded:: 3.16 +%End + + QgsTextFormat annotationTextFormat() const; +%Docstring +Returns the text format used when rendering grid annotations. + +.. seealso:: :py:func:`setAnnotationTextFormat` + +.. versionadded:: 3.16 +%End + + void setAnnotationFont( const QFont &font ) /Deprecated/; %Docstring Sets the ``font`` used for drawing grid annotations. .. seealso:: :py:func:`annotationFont` + +.. deprecated:: + use setAnnotationTextFormat() instead %End - QFont annotationFont() const; + QFont annotationFont() const /Deprecated/; %Docstring Returns the font used for drawing grid annotations. .. seealso:: :py:func:`setAnnotationFont` + +.. deprecated:: + use annotationTextFormat() instead %End - void setAnnotationFontColor( const QColor &color ); + void setAnnotationFontColor( const QColor &color ) /Deprecated/; %Docstring Sets the font ``color`` used for drawing grid annotations. .. seealso:: :py:func:`annotationFontColor` + +.. deprecated:: + use setAnnotationTextFormat() instead %End - QColor annotationFontColor() const; + QColor annotationFontColor() const /Deprecated/; %Docstring Returns the font color used for drawing grid annotations. .. seealso:: :py:func:`setAnnotationFontColor` + +.. deprecated:: + use annotationTextFormat() instead %End void setAnnotationPrecision( const int precision ); diff --git a/python/core/auto_generated/layout/qgslayouttable.sip.in b/python/core/auto_generated/layout/qgslayouttable.sip.in index 30f8494161a8..0c2297a517b9 100644 --- a/python/core/auto_generated/layout/qgslayouttable.sip.in +++ b/python/core/auto_generated/layout/qgslayouttable.sip.in @@ -194,25 +194,31 @@ Returns whether empty rows are drawn in the table. .. seealso:: :py:func:`setShowEmptyRows` %End - void setHeaderFont( const QFont &font ); + void setHeaderFont( const QFont &font ) /Deprecated/; %Docstring Sets the ``font`` used to draw header text in the table. .. seealso:: :py:func:`headerFont` .. seealso:: :py:func:`setContentFont` + +.. deprecated:: + use setHeaderTextFormat() instead %End - QFont headerFont() const; + QFont headerFont() const /Deprecated/; %Docstring Returns the font used to draw header text in the table. .. seealso:: :py:func:`setHeaderFont` .. seealso:: :py:func:`contentFont` + +.. deprecated:: + use headerTextFormat() instead %End - void setHeaderFontColor( const QColor &color ); + void setHeaderFontColor( const QColor &color ) /Deprecated/; %Docstring Sets the ``color`` used to draw header text in the table. @@ -221,9 +227,12 @@ Sets the ``color`` used to draw header text in the table. .. seealso:: :py:func:`setHeaderFont` .. seealso:: :py:func:`setContentFontColor` + +.. deprecated:: + use setHeaderTextFormat() instead %End - QColor headerFontColor() const; + QColor headerFontColor() const /Deprecated/; %Docstring Returns the color used to draw header text in the table. @@ -232,6 +241,31 @@ Returns the color used to draw header text in the table. .. seealso:: :py:func:`headerFont` .. seealso:: :py:func:`contentFontColor` + +.. deprecated:: + use headerTextFormat() instead +%End + + void setHeaderTextFormat( const QgsTextFormat &format ); +%Docstring +Sets the ``format`` used to draw header text in the table. + +.. seealso:: :py:func:`headerTextFormat` + +.. seealso:: :py:func:`setContentTextFormat` + +.. versionadded:: 3.16 +%End + + QgsTextFormat headerTextFormat() const; +%Docstring +Returns the format used to draw header text in the table. + +.. seealso:: :py:func:`setHeaderTextFormat` + +.. seealso:: :py:func:`contentTextFormat` + +.. versionadded:: 3.16 %End void setHeaderHAlignment( HeaderHAlignment alignment ); @@ -264,25 +298,31 @@ if and where headers are shown in the table. .. seealso:: :py:func:`setHeaderMode` %End - void setContentFont( const QFont &font ); + void setContentFont( const QFont &font ) /Deprecated/; %Docstring Sets the ``font`` used to draw text in table body cells. .. seealso:: :py:func:`contentFont` .. seealso:: :py:func:`setHeaderFont` + +.. deprecated:: + use setContentTextFormat() instead %End - QFont contentFont() const; + QFont contentFont() const /Deprecated/; %Docstring Returns the font used to draw text in table body cells. .. seealso:: :py:func:`setContentFont` .. seealso:: :py:func:`headerFont` + +.. deprecated:: + use contextTextFormat() instead %End - void setContentFontColor( const QColor &color ); + void setContentFontColor( const QColor &color ) /Deprecated/; %Docstring Sets the ``color`` used to draw text in table body cells. @@ -291,9 +331,12 @@ Sets the ``color`` used to draw text in table body cells. .. seealso:: :py:func:`setContentFont` .. seealso:: :py:func:`setHeaderFontColor` + +.. deprecated:: + use setContentTextFormat() instead %End - QColor contentFontColor() const; + QColor contentFontColor() const /Deprecated/; %Docstring Returns the color used to draw text in table body cells. @@ -302,6 +345,31 @@ Returns the color used to draw text in table body cells. .. seealso:: :py:func:`contentFont` .. seealso:: :py:func:`headerFontColor` + +.. deprecated:: + use contextTextFormat() instead +%End + + void setContentTextFormat( const QgsTextFormat &format ); +%Docstring +Sets the ``format`` used to draw content text in the table. + +.. seealso:: :py:func:`contentTextFormat` + +.. seealso:: :py:func:`setHeaderTextFormat` + +.. versionadded:: 3.16 +%End + + QgsTextFormat contentTextFormat() const; +%Docstring +Returns the format used to draw content text in the table. + +.. seealso:: :py:func:`setContentTextFormat` + +.. seealso:: :py:func:`headerTextFormat` + +.. versionadded:: 3.16 %End void setShowGrid( bool showGrid ); @@ -527,6 +595,13 @@ Fetches the contents used for the cells in the table. Returns the conditional style to use for the cell at ``row``, ``column``. .. versionadded:: 3.12 +%End + + virtual QgsExpressionContextScope *scopeForCell( int row, int column ) const /Factory/; +%Docstring +Creates a new QgsExpressionContextScope for the cell at ``row``, ``column``. + +.. versionadded:: 3.16 %End QgsLayoutTableContents &contents(); @@ -583,8 +658,6 @@ new data. - - @@ -602,11 +675,12 @@ Calculates the maximum height of text shown in rows. double totalHeight(); - int rowsVisible( double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const; + int rowsVisible( QgsRenderContext &context, double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const; %Docstring Calculates how many content rows would be visible within a frame of the specified height. +:param context: render context :param frameHeight: height of frame :param firstRow: index of first row visible in frame (where 0 = first row in table) :param includeHeader: set to ``True`` if frame would include a header row @@ -617,10 +691,11 @@ height. :return: number of visible content rows (excluding header row) %End - int rowsVisible( int frameIndex, int firstRow, bool includeEmptyRows ) const; + int rowsVisible( QgsRenderContext &context, int frameIndex, int firstRow, bool includeEmptyRows ) const; %Docstring Calculates how many content rows are visible within a given frame. +:param context: render context :param frameIndex: index number for frame :param firstRow: index of first row visible in frame (where 0 = first row in table) :param includeEmptyRows: set to ``True`` to also include rows which would be empty in the returned count. For instance, @@ -630,20 +705,21 @@ Calculates how many content rows are visible within a given frame. :return: number of visible content rows (excludes header rows) %End - QPair rowRange( int frameIndex ) const; + QPair rowRange( QgsRenderContext &context, int frameIndex ) const; %Docstring Calculates a range of rows which should be visible in a given frame. +:param context: render context :param frameIndex: index number for frame :return: row range %End - void drawHorizontalGridLines( QPainter *painter, int firstRow, int lastRow, bool drawHeaderLines ) const; + void drawHorizontalGridLines( QgsLayoutItemRenderContext &context, int firstRow, int lastRow, bool drawHeaderLines ) const; %Docstring Draws the horizontal grid lines for the table. -:param painter: destination painter for grid lines +:param context: destination render context :param firstRow: index corresponding to first row shown in frame :param lastRow: index corresponding to last row shown in frame. If greater than the number of content rows in the table, then the default row height will be used for the remaining rows. @@ -666,6 +742,42 @@ Checks whether a table contents contains a given row :param row: row to check for :return: ``True`` if contents contains rows +%End + + virtual QgsTextFormat textFormatForCell( int row, int column ) const; +%Docstring +Returns the text format to use for the cell at the specified ``row`` and ``column``. + +.. seealso:: :py:func:`textFormatForHeader` + +.. versionadded:: 3.16 +%End + + virtual QgsTextFormat textFormatForHeader( int column ) const; +%Docstring +Returns the text format to use for the header cell at the specified ``column``. + +.. seealso:: :py:func:`textFormatForCell` + +.. versionadded:: 3.16 +%End + + virtual Qt::Alignment horizontalAlignmentForCell( int row, int column ) const; +%Docstring +Returns the horizontal alignment to use for the cell at the specified ``row`` and ``column``. + +.. seealso:: :py:func:`verticalAlignmentForCell` + +.. versionadded:: 3.16 +%End + + virtual Qt::Alignment verticalAlignmentForCell( int row, int column ) const; +%Docstring +Returns the vertical alignment to use for the cell at the specified ``row`` and ``column``. + +.. seealso:: :py:func:`horizontalAlignmentForCell` + +.. versionadded:: 3.16 %End }; diff --git a/python/core/auto_generated/mesh/qgsmeshlayer.sip.in b/python/core/auto_generated/mesh/qgsmeshlayer.sip.in index a15ec95464ed..a2f495fd230e 100644 --- a/python/core/auto_generated/mesh/qgsmeshlayer.sip.in +++ b/python/core/auto_generated/mesh/qgsmeshlayer.sip.in @@ -28,9 +28,11 @@ yet support editing transactions. The main data providers supported by QGIS are listed below. -\section mesh_providers Mesh data providers +Mesh data providers +------------------- -\subsection mesh_memory Memory data providerType (mesh_memory) +Memory data providerType (mesh_memory) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The memory data provider is used to construct in memory data, for example scratch data. There is no inherent persistent storage of the data. The data source uri is constructed. @@ -52,7 +54,8 @@ E.g. to create mesh with one quad and one triangle ); QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "mesh_memory"); -\subsection mdal MDAL data provider (mdal) +MDAL data provider (mdal) +~~~~~~~~~~~~~~~~~~~~~~~~~ Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url is the MDAL connection string. QGIS must be built with MDAL support to allow this provider. diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index bd967c06d8a0..3ad07728d09f 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -181,6 +181,8 @@ Returns a double ``number``, rounded (as close as possible) to the specified num + + double qgsPermissiveToDouble( QString string, bool &ok ); %Docstring Converts a string to a double in a permissive way, e.g., allowing for incorrect diff --git a/python/core/auto_generated/qgsabstractdatabaseproviderconnection.sip.in b/python/core/auto_generated/qgsabstractdatabaseproviderconnection.sip.in index 1cfa07de3115..47645d6219d9 100644 --- a/python/core/auto_generated/qgsabstractdatabaseproviderconnection.sip.in +++ b/python/core/auto_generated/qgsabstractdatabaseproviderconnection.sip.in @@ -234,11 +234,24 @@ This information is calculated from the geometry columns types. CreateSpatialIndex, SpatialIndexExists, DeleteSpatialIndex, + DeleteField, + DeleteFieldCascade, + AddField, }; - typedef QFlags Capabilities; + enum GeometryColumnCapability + { + Z, + M, + SinglePart, + Curves + }; + + typedef QFlags GeometryColumnCapabilities; + + QgsAbstractDatabaseProviderConnection( const QString &name ); %Docstring Creates a new connection with ``name`` by reading its configuration from the settings. @@ -260,6 +273,13 @@ The connection is not automatically stored in the settings. Returns connection capabilities %End + virtual GeometryColumnCapabilities geometryColumnCapabilities(); +%Docstring +Returns connection geomerty column capabilities (Z, M, SinglePart, Curves) + +.. versionadded:: 3.16 +%End + virtual QString tableUri( const QString &schema, const QString &name ) const throw( QgsProviderConnectionException ); %Docstring @@ -357,6 +377,44 @@ Raises a QgsProviderConnectionException if any errors are encountered. :raises :: py:class:`QgsProviderConnectionException` %End + virtual void deleteField( const QString &fieldName, const QString &schema, const QString &tableName, bool force = false ) const throw( QgsProviderConnectionException ); +%Docstring +Deletes the field with the specified name. +Raises a QgsProviderConnectionException if any errors are encountered. + +:param fieldName: name of the field to be deleted +:param schema: name of the schema (schema is ignored if not supported by the backend). +:param tableName: name of the table +:param force: if ``True``, a DROP CASCADE will drop all related objects + +.. note:: + + it is responsibility of the caller to handle open layers and registry entries. + +:raises :: py:class:`QgsProviderConnectionException` + +.. versionadded:: 3.16 +%End + + virtual void addField( const QgsField &field, const QString &schema, const QString &tableName ) const throw( QgsProviderConnectionException ); +%Docstring +Adds a field +Raises a QgsProviderConnectionException if any errors are encountered. + +:param field: specification of the new field +:param schema: name of the schema (schema is ignored if not supported by the backend). +:param tableName: name of the table + +.. note:: + + it is responsibility of the caller to handle open layers and registry entries. + +:raises :: py:class:`QgsProviderConnectionException` + +.. versionadded:: 3.16 +%End + + virtual void renameSchema( const QString &name, const QString &newName ) const throw( QgsProviderConnectionException ); %Docstring Renames a schema with the specified ``name``. @@ -461,6 +519,37 @@ Returns information about the existing schemas. Raises a QgsProviderConnectionException if any errors are encountered. :raises :: py:class:`QgsProviderConnectionException` +%End + + virtual QgsFields fields( const QString &schema, const QString &table ) const throw( QgsProviderConnectionException ); +%Docstring +Returns the fields of a ``table`` and ``schema``. +Raises a QgsProviderConnectionException if any errors are encountered. + +.. note:: + + the default implementation creates a temporary vector layer, providers may + choose to override this method for a greater efficiency. + +.. versionadded:: 3.16 + +:raises :: py:class:`QgsProviderConnectionException` +%End + + virtual QList< QgsVectorDataProvider::NativeType > nativeTypes() const throw( QgsProviderConnectionException ) = 0; +%Docstring +Returns a list of native types supported by the connection. + +.. versionadded:: 3.16 + +:raises :: py:class:`QgsProviderConnectionException` +%End + + QString providerKey() const; +%Docstring +Returns the provider key + +.. versionadded:: 3.16 %End protected: diff --git a/python/core/auto_generated/qgsapplication.sip.in b/python/core/auto_generated/qgsapplication.sip.in index 3f17258fefb0..93c6a7284a89 100644 --- a/python/core/auto_generated/qgsapplication.sip.in +++ b/python/core/auto_generated/qgsapplication.sip.in @@ -695,6 +695,13 @@ Returns the application's image cache, used for caching resampled versions of ra .. seealso:: :py:func:`svgCache` .. versionadded:: 3.6 +%End + + static QgsSourceCache *sourceCache(); +%Docstring +Returns the application's source cache, used for caching embedded and remote source strings as local files + +.. versionadded:: 3.16 %End static QgsNetworkContentFetcherRegistry *networkContentFetcherRegistry() /KeepReference/; diff --git a/python/core/auto_generated/qgsattributeeditorelement.sip.in b/python/core/auto_generated/qgsattributeeditorelement.sip.in index 166a85a223dc..2233f7a23015 100644 --- a/python/core/auto_generated/qgsattributeeditorelement.sip.in +++ b/python/core/auto_generated/qgsattributeeditorelement.sip.in @@ -9,6 +9,7 @@ + class QgsAttributeEditorElement /Abstract/ { %Docstring @@ -282,6 +283,23 @@ This element will load a relation editor onto the form. #include "qgsattributeeditorelement.h" %End public: + static const QMetaObject staticMetaObject; + + public: + + enum Button + { + Link, + Unlink, + SaveChildEdits, + AddChildFeature, + DuplicateChildFeature, + DeleteChildFeature, + ZoomToChildFeature, + AllButtons + }; + typedef QFlags Buttons; + QgsAttributeEditorRelation( const QString &name, const QString &relationId, QgsAttributeEditorElement *parent ); %Docstring @@ -333,51 +351,87 @@ Initializes the relation from the id virtual QgsAttributeEditorElement *clone( QgsAttributeEditorElement *parent ) const /Factory/; - bool showLinkButton() const; + bool showLinkButton() const /Deprecated/; %Docstring Determines if the "link feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead %End - void setShowLinkButton( bool showLinkButton ); + void setShowLinkButton( bool showLinkButton ) /Deprecated/; %Docstring Determines if the "link feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - bool showUnlinkButton() const; + bool showUnlinkButton() const /Deprecated/; %Docstring Determines if the "unlink feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead %End - void setShowUnlinkButton( bool showUnlinkButton ); + void setShowUnlinkButton( bool showUnlinkButton ) /Deprecated/; %Docstring Determines if the "unlink feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - void setShowSaveChildEditsButton( bool showSaveChildEditsButton ); + void setShowSaveChildEditsButton( bool showChildEdits ) /Deprecated/; %Docstring -Determines if the "save child layer edits" button should be shown +Determines if the "Save child layer edits" button should be shown .. versionadded:: 3.14 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - bool showSaveChildEditsButton( ) const; + bool showSaveChildEditsButton() const /Deprecated/; %Docstring -Returns ``True`` if the "save child layer edits" button should be shown. +Determines if the "Save child layer edits" button should be shown .. versionadded:: 3.14 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead +%End + + void setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ); +%Docstring +Defines the buttons which are shown + +.. versionadded:: 3.16 +%End + + QgsAttributeEditorRelation::Buttons visibleButtons() const; +%Docstring +Returns the buttons which are shown + +.. versionadded:: 3.16 %End }; +QFlags operator|(QgsAttributeEditorRelation::Button f1, QFlags f2); + + + class QgsAttributeEditorQmlElement : QgsAttributeEditorElement { %Docstring diff --git a/python/core/auto_generated/qgsdataitem.sip.in b/python/core/auto_generated/qgsdataitem.sip.in index 459ed51ae756..d82f2c892147 100644 --- a/python/core/auto_generated/qgsdataitem.sip.in +++ b/python/core/auto_generated/qgsdataitem.sip.in @@ -49,6 +49,8 @@ Parent/children hierarchy is not based on QObject. Favorites, Project, Custom, + Fields, + Field, }; @@ -652,6 +654,77 @@ Shared home directory icon. %End }; + +class QgsDatabaseSchemaItem : QgsDataCollectionItem +{ +%Docstring +A Collection that represents a database schema item + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgsdataitem.h" +%End + public: + + QgsDatabaseSchemaItem( QgsDataItem *parent /TransferThis/, const QString &name, const QString &path = QString(), const QString &providerKey = QString() ); +%Docstring +Constructor for QgsDatabaseSchemaItem, with the specified ``parent`` item. + +The ``name`` argument specifies the text to show in the model for the item. A translated string should +be used wherever appropriate. + +The ``path`` argument gives the item path in the browser tree. The ``path`` string can take any form, +but QgsSchemaItem items pointing to different logical locations should always use a different item ``path``. + +The optional ``providerKey`` string can be used to specify the key for the QgsDataItemProvider that created this item. +%End + + ~QgsDatabaseSchemaItem(); + + + static QIcon iconDataCollection(); +%Docstring +Returns the standard browser data collection icon. + +.. seealso:: :py:func:`iconDir` +%End + +}; + + + +class QgsConnectionsRootItem : QgsDataCollectionItem +{ +%Docstring +A Collection that represents a root group of connections from a single data provider + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgsdataitem.h" +%End + public: + + QgsConnectionsRootItem( QgsDataItem *parent /TransferThis/, const QString &name, const QString &path = QString(), const QString &providerKey = QString() ); +%Docstring +Constructor for QgsConnectionsRootItem, with the specified ``parent`` item. + +The ``name`` argument specifies the text to show in the model for the item. A translated string should +be used wherever appropriate. + +The ``path`` argument gives the item path in the browser tree. The ``path`` string can take any form, +but QgsSchemaItem items pointing to different logical locations should always use a different item ``path``. + +The optional ``providerKey`` string can be used to specify the key for the QgsDataItemProvider that created this item. +%End + + ~QgsConnectionsRootItem(); +}; + + class QgsDirectoryItem : QgsDataCollectionItem { %Docstring @@ -900,6 +973,104 @@ Creates a new data item from the specified path. }; +class QgsFieldsItem : QgsDataItem +{ +%Docstring +A collection of field items with some internal logic to retrieve +the fields and a the vector layer instance from a connection URI, +the schema and the table name. + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgsdataitem.h" +%End + public: + + QgsFieldsItem( QgsDataItem *parent /TransferThis/, + const QString &path, + const QString &connectionUri, + const QString &providerKey, + const QString &schema, + const QString &tableName ); +%Docstring +Constructor for QgsFieldsItem, with the specified ``parent`` item. + +The ``path`` argument gives the item path in the browser tree. The ``path`` string can take any form, +but QgsDataItem items pointing to different logical locations should always use a different item ``path``. +The \connectionUri argument is the connection part of the layer URI that it is used internally to create +a connection and retrieve fields information. +The ``providerKey`` string can be used to specify the key for the QgsDataItemProvider that created this item. +The ``schema`` and ``tableName`` are used to retrieve the layer and field information from the ``connectionUri``. +%End + + ~QgsFieldsItem(); + + virtual QVector createChildren(); + + + virtual QIcon icon(); + + + QString schema() const; +%Docstring +Returns the schema name +%End + + QString tableName() const; +%Docstring +Returns the table name +%End + + QString connectionUri() const; +%Docstring +Returns the connection URI +%End + + QgsVectorLayer *layer() /Factory/; +%Docstring +Creates and returns a (possibly NULL) layer from the connection URI and schema/table information +%End + + +}; + + +class QgsFieldItem : QgsDataItem +{ +%Docstring +A layer field item, information about the connection URI, the schema and the +table as well as the layer instance the field belongs to can be retrieved +from the parent QgsFieldsItem object. + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgsdataitem.h" +%End + public: + + QgsFieldItem( QgsDataItem *parent /TransferThis/, + const QgsField &field ); +%Docstring +Constructor for QgsFieldItem, with the specified ``parent`` item and ``field``. + +.. note:: + + parent item must be a :py:class:`QgsFieldsItem` +%End + + ~QgsFieldItem(); + + virtual QIcon icon(); + + +}; + + + diff --git a/python/core/auto_generated/qgsfields.sip.in b/python/core/auto_generated/qgsfields.sip.in index 8a1c0b12a4f7..c14eed56800e 100644 --- a/python/core/auto_generated/qgsfields.sip.in +++ b/python/core/auto_generated/qgsfields.sip.in @@ -309,6 +309,14 @@ Returns an icon corresponding to a field index, based on the field's type and so } %End + + static QIcon iconForFieldType( const QVariant::Type &type ) /Factory/; +%Docstring +Returns an icon corresponding to a field ``type`` + +.. versionadded:: 3.16 +%End + operator QVariant() const; diff --git a/python/core/auto_generated/qgspropertycollection.sip.in b/python/core/auto_generated/qgspropertycollection.sip.in index 43594917dc03..343cb2179ca5 100644 --- a/python/core/auto_generated/qgspropertycollection.sip.in +++ b/python/core/auto_generated/qgspropertycollection.sip.in @@ -389,6 +389,9 @@ Copy constructor. %End + bool operator==( const QgsPropertyCollection &other ) const; + bool operator!=( const QgsPropertyCollection &other ) const; + int count() const; %Docstring Returns the number of properties contained within the collection. diff --git a/python/core/auto_generated/qgsrendercontext.sip.in b/python/core/auto_generated/qgsrendercontext.sip.in index 0261b2c5c008..2ee91f40a82d 100644 --- a/python/core/auto_generated/qgsrendercontext.sip.in +++ b/python/core/auto_generated/qgsrendercontext.sip.in @@ -45,6 +45,7 @@ to be rendered etc. RenderBlocking, RenderSymbolPreview, LosslessImageRendering, + ApplyScalingWorkaroundForTextRendering, }; typedef QFlags Flags; @@ -840,6 +841,26 @@ Sets a ``geometry`` to use to clip features at render time. .. seealso:: :py:func:`featureClipGeometry` +.. versionadded:: 3.16 +%End + + QPointF textureOrigin() const; +%Docstring +Returns the texture origin, which should be used as a brush transform when +rendering using QBrush objects. + +.. seealso:: :py:func:`setTextureOrigin` + +.. versionadded:: 3.16 +%End + + void setTextureOrigin( const QPointF &origin ); +%Docstring +Sets the texture ``origin``, which should be used as a brush transform when +rendering using QBrush objects. + +.. seealso:: :py:func:`textureOrigin` + .. versionadded:: 3.16 %End diff --git a/python/core/auto_generated/qgssourcecache.sip.in b/python/core/auto_generated/qgssourcecache.sip.in new file mode 100644 index 000000000000..6d31335f1e9d --- /dev/null +++ b/python/core/auto_generated/qgssourcecache.sip.in @@ -0,0 +1,56 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/qgssourcecache.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + +class QgsSourceCache : QgsAbstractContentCacheBase +{ +%Docstring +A cache for source strings that returns a local file path containing the source content. + +QgsSourceCache is not usually directly created, but rather accessed through +:py:func:`QgsApplication.sourceCache()`. + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgssourcecache.h" +%End + public: + + QgsSourceCache( QObject *parent /TransferThis/ = 0 ); +%Docstring +Constructor for QgsSourceCache, with the specified ``parent`` object. +%End + + QString localFilePath( const QString &path, bool blocking = false ); +%Docstring +Returns a local file path reflecting the content of a specified source ``path`` + +``path`` may be a local file, remote (HTTP) url, or a base 64 encoded string (with a "base64:" prefix). +%End + + signals: + + void remoteSourceFetched( const QString &url ); +%Docstring +Emitted when the cache has finished retrieving a 3D model from a remote ``url``. +%End + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/qgssourcecache.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/core/auto_generated/qgstablecell.sip.in b/python/core/auto_generated/qgstablecell.sip.in index 5adffefe4975..28c67603dc58 100644 --- a/python/core/auto_generated/qgstablecell.sip.in +++ b/python/core/auto_generated/qgstablecell.sip.in @@ -78,6 +78,32 @@ Sets the cell's foreground ``color``. Set an invalid ``color`` if a default color should be used for the foreground. .. seealso:: :py:func:`foregroundColor` +%End + + QgsTextFormat textFormat() const; +%Docstring +Returns the cell's text format. + +.. note:: + + The text format will only be used if :py:func:`~QgsTableCell.hasTextFormat` returns ``True``. + +.. seealso:: :py:func:`setTextFormat` + +.. versionadded:: 3.16 +%End + + void setTextFormat( const QgsTextFormat &format ); +%Docstring +Sets the cell's text ``format``. + +.. note:: + + The text format will only be used if :py:func:`~QgsTableCell.hasTextFormat` returns ``True``. + +.. seealso:: :py:func:`textFormat` + +.. versionadded:: 3.16 %End const QgsNumericFormat *numericFormat() const; @@ -94,6 +120,50 @@ Sets the numeric ``format`` used for numbers in the cell, or ``None`` if no spec Ownership of ``format`` is transferred to the cell. .. seealso:: :py:func:`numericFormat` +%End + + Qt::Alignment horizontalAlignment() const; +%Docstring +Returns the horizontal alignment for text in the cell. + +.. seealso:: :py:func:`setHorizontalAlignment` + +.. seealso:: :py:func:`verticalAlignment` + +.. versionadded:: 3.16 +%End + + void setHorizontalAlignment( Qt::Alignment alignment ); +%Docstring +Sets the horizontal ``alignment`` for text in the cell. + +.. seealso:: :py:func:`horizontalAlignment` + +.. seealso:: :py:func:`setVerticalAlignment` + +.. versionadded:: 3.16 +%End + + Qt::Alignment verticalAlignment() const; +%Docstring +Returns the vertical alignment for text in the cell. + +.. seealso:: :py:func:`setVerticalAlignment` + +.. seealso:: :py:func:`horizontalAlignment` + +.. versionadded:: 3.16 +%End + + void setVerticalAlignment( Qt::Alignment alignment ); +%Docstring +Sets the vertical ``alignment`` for text in the cell. + +.. seealso:: :py:func:`verticalAlignment` + +.. seealso:: :py:func:`setHorizontalAlignment` + +.. versionadded:: 3.16 %End QVariantMap properties( const QgsReadWriteContext &context ) const; diff --git a/python/core/auto_generated/qgstessellator.sip.in b/python/core/auto_generated/qgstessellator.sip.in index 226af0658b1e..7ae798b1c6c4 100644 --- a/python/core/auto_generated/qgstessellator.sip.in +++ b/python/core/auto_generated/qgstessellator.sip.in @@ -27,12 +27,14 @@ Optionally provides extrusion by adding triangles that serve as walls when extru #include "qgstessellator.h" %End public: - QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals = false, bool addBackFaces = false ); + QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false, + bool addTextureCoords = false, int facade = 3, float textureRotation = 0.0f ); %Docstring Creates tessellator with a specified origin point of the world (in map coordinates) %End - QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false ); + QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false, + bool addTextureCoords = false, int facade = 3, float textureRotation = 0.0f ); %Docstring Creates tessellator with a specified ``bounds`` of input geometry coordinates. This constructor allows the tessellator to map input coordinates to a desirable range for numerical diff --git a/python/core/auto_generated/qgsvectorfilewriter.sip.in b/python/core/auto_generated/qgsvectorfilewriter.sip.in index 1b4ba7bf00a2..ae31fbae3f79 100644 --- a/python/core/auto_generated/qgsvectorfilewriter.sip.in +++ b/python/core/auto_generated/qgsvectorfilewriter.sip.in @@ -431,7 +431,7 @@ Writes a layer out to a vector file. const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags = QgsFeatureSink::SinkFlags(), QString *newFilename = 0, - QString *newLayer = 0 ); + QString *newLayer = 0 ) /Factory/; %Docstring Create a new vector file writer. diff --git a/python/core/auto_generated/qgsvectorlayer.sip.in b/python/core/auto_generated/qgsvectorlayer.sip.in index 793388c9ec2e..ea5d3eb835a0 100644 --- a/python/core/auto_generated/qgsvectorlayer.sip.in +++ b/python/core/auto_generated/qgsvectorlayer.sip.in @@ -34,16 +34,18 @@ manages editing transactions. Sample usage of the QgsVectorLayer class: -.. code-block:: +.. code-block:: python - QString uri = "point?crs=epsg:4326&field=id:integer"; - QgsVectorLayer *scratchLayer = new QgsVectorLayer(uri, "Scratch point layer", "memory"); + uri = "point?crs=epsg:4326&field=id:integer" + scratchLayer = QgsVectorLayer(uri, "Scratch point layer", "memory") The main data providers supported by QGIS are listed below. -\section providers Vector data providers +Vector data providers +--------------------- -\subsection memory Memory data providerType (memory) +Memory data providerType (memory) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The memory data provider is used to construct in memory data, for example scratch data or data generated from spatial operations such as contouring. There is no @@ -70,7 +72,8 @@ trigger such warning, it is possible to suppress that by setting the following c layer.setCustomProperty("skipMemoryLayersCheck", 1) -\subsection ogr OGR data provider (ogr) +OGR data provider (ogr) +~~~~~~~~~~~~~~~~~~~~~~~ Accesses data using the OGR drivers (http://www.gdal.org/ogr/ogr_formats.html). The url is the OGR connection string. A wide variety of data formats can be accessed using this @@ -78,25 +81,29 @@ driver, including file based formats used by many GIS systems, database formats, web services. Some of these formats are also supported by custom data providers listed below. -\subsection spatialite SpatiaLite data provider (spatialite) +SpatiaLite data provider (spatialite) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Access data in a SpatiaLite database. The url defines the connection parameters, table, geometry column, and other attributes. The url can be constructed using the QgsDataSourceUri class. -\subsection postgres PostgreSQL data provider (postgres) +PostgreSQL data provider (postgres) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Connects to a PostgreSQL database. The url defines the connection parameters, table, geometry column, and other attributes. The url can be constructed using the QgsDataSourceUri class. -\subsection mssql Microsoft SQL server data provider (mssql) +Microsoft SQL server data provider (mssql) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Connects to a Microsoft SQL server database. The url defines the connection parameters, table, geometry column, and other attributes. The url can be constructed using the QgsDataSourceUri class. -\subsection wfs WFS (web feature service) data provider (wfs) +WFS (web feature service) data provider (wfs) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Used to access data provided by a web feature service. @@ -129,7 +136,8 @@ attribute operators, “BBOX, Disjoint, Intersects, Touches, Crosses, Contains, spatial binary operators and the QGIS local “geomFromWKT, geomFromGML” geometry constructor functions. -\subsection oapif OGC API - Features data provider (oapif) +OGC API - Features data provider (oapif) +~~~~~~~~-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Used to access data provided by a OGC API - Features server. @@ -154,7 +162,8 @@ Also note: - Use the special $geometry parameter to provide the layer geometry column as input into the spatial binary operators e.g intersects($geometry, geomFromWKT('POINT (5 6)')) -\subsection delimitedtext Delimited text file data provider (delimitedtext) +Delimited text file data provider (delimitedtext) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Accesses data in a delimited text file, for example CSV files generated by spreadsheets. The contents of the file are split into columns based on specified @@ -300,7 +309,8 @@ to monitor for changes. Errors encountered loading the file will not be reported in a user dialog if quiet is included (They will still be shown in the output log). -\subsection gpx GPX data provider (gpx) +GPX data provider (gpx) +~~~~~~~~~~~~~~~~~~~~~~~ Provider reads tracks, routes, and waypoints from a GPX file. The url defines the name of the file, and the type of data to retrieve from it @@ -308,7 +318,8 @@ defines the name of the file, and the type of data to retrieve from it An example url is "/home/user/data/holiday.gpx?type=route" -\subsection grass Grass data provider (grass) +Grass data provider (grass) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Provider to display vector data in a GRASS GIS layer. @@ -2661,6 +2672,13 @@ Emitted before changes are committed to the data provider. void beforeRollBack(); %Docstring Emitted before changes are rolled back. +%End + + void afterCommitChanges(); +%Docstring +Emitted after changes are commited to the data provider. + +.. versionadded:: 3.16 %End void afterRollBack(); diff --git a/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in b/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in index 28e287088bb4..b9d7101c7e66 100644 --- a/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in +++ b/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in @@ -759,6 +759,13 @@ Returns the stroke width map unit scale. virtual void applyDataDefinedSettings( QgsSymbolRenderContext &context ); %Docstring Custom stroke +%End + + virtual bool applyBrushTransformFromContext() const; +%Docstring +Returns ``True`` if the image brush should be transformed using the render context's texture origin. + +.. versionadded:: 3.16 %End private: @@ -1041,6 +1048,7 @@ Returns the map unit scale for the image's width. virtual void applyDataDefinedSettings( QgsSymbolRenderContext &context ); + virtual bool applyBrushTransformFromContext() const; }; diff --git a/python/core/auto_generated/textrenderer/qgstextbackgroundsettings.sip.in b/python/core/auto_generated/textrenderer/qgstextbackgroundsettings.sip.in index 5988f6d25353..6b145d9febc8 100644 --- a/python/core/auto_generated/textrenderer/qgstextbackgroundsettings.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextbackgroundsettings.sip.in @@ -63,6 +63,9 @@ Copy constructor. ~QgsTextBackgroundSettings(); + bool operator==( const QgsTextBackgroundSettings &other ) const; + bool operator!=( const QgsTextBackgroundSettings &other ) const; + bool enabled() const; %Docstring Returns whether the background is enabled. diff --git a/python/core/auto_generated/textrenderer/qgstextblock.sip.in b/python/core/auto_generated/textrenderer/qgstextblock.sip.in index 851fc9756b01..497508ca838d 100644 --- a/python/core/auto_generated/textrenderer/qgstextblock.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextblock.sip.in @@ -34,6 +34,13 @@ Constructor for an empty text block. explicit QgsTextBlock( const QgsTextFragment &fragment ); %Docstring Constructor for a QgsTextBlock consisting of a single text ``fragment``. +%End + + QString toPlainText() const; +%Docstring +Converts the block to plain text. + +.. versionadded:: 3.16 %End void append( const QgsTextFragment &fragment ); diff --git a/python/core/auto_generated/textrenderer/qgstextbuffersettings.sip.in b/python/core/auto_generated/textrenderer/qgstextbuffersettings.sip.in index 37c87c3b9695..954b8f115bde 100644 --- a/python/core/auto_generated/textrenderer/qgstextbuffersettings.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextbuffersettings.sip.in @@ -39,6 +39,9 @@ Copy constructor. ~QgsTextBufferSettings(); + bool operator==( const QgsTextBufferSettings &other ) const; + bool operator!=( const QgsTextBufferSettings &other ) const; + bool enabled() const; %Docstring Returns whether the buffer is enabled. diff --git a/python/core/auto_generated/textrenderer/qgstextcharacterformat.sip.in b/python/core/auto_generated/textrenderer/qgstextcharacterformat.sip.in index 68305ca00f1c..6287292c37db 100644 --- a/python/core/auto_generated/textrenderer/qgstextcharacterformat.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextcharacterformat.sip.in @@ -108,10 +108,15 @@ Sets whether the format has overline ``enabled``. .. seealso:: :py:func:`overline` %End - void updateFontForFormat( QFont &font ) const; + void updateFontForFormat( QFont &font, double scaleFactor = 1.0 ) const; %Docstring Updates the specified ``font`` in place, applying character formatting options which are applicable on a font level. + +The optional ``scaleFactor`` parameter can specify a font size scaling factor. It is recommended to set this to +QgsTextRenderer.FONT_WORKAROUND_SCALE and then manually calculations +based on the resultant font metrics. Failure to do so will result in poor quality text rendering +at small font sizes. %End }; diff --git a/python/core/auto_generated/textrenderer/qgstextformat.sip.in b/python/core/auto_generated/textrenderer/qgstextformat.sip.in index f8f61277a405..62bc3c3aa04d 100644 --- a/python/core/auto_generated/textrenderer/qgstextformat.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextformat.sip.in @@ -35,6 +35,10 @@ Container for all settings relating to text rendering. }; QgsTextFormat(); +%Docstring +Default constructor for QgsTextFormat. Creates a text format initially +set to an invalid state (see :py:func:`~QgsTextFormat.isValid`). +%End QgsTextFormat( const QgsTextFormat &other ); %Docstring @@ -46,6 +50,35 @@ Copy constructor. ~QgsTextFormat(); + bool operator==( const QgsTextFormat &other ) const; + bool operator!=( const QgsTextFormat &other ) const; + + bool isValid() const; +%Docstring +Returns ``True`` if the format is valid. + +A default constructed QgsTextFormat is invalid, until at least one or more properties +have been set on the format. An invalid state can be used as a representation of a "not set" +text format, e.g. for indicating that a default text format should be used. + +.. note:: + + Calling any setter on a QgsTextFormat object will automatically set the format as valid. + +.. seealso:: :py:func:`setValid` + +.. versionadded:: 3.16 +%End + + void setValid(); +%Docstring +Sets the format to a valid state, without changing any of the default format settings. + +.. seealso:: :py:func:`isValid` + +.. versionadded:: 3.16 +%End + QgsTextBufferSettings &buffer(); %Docstring Returns a reference to the text buffer settings. @@ -132,12 +165,16 @@ of rendered text. .. seealso:: :py:func:`toQFont` %End - QFont scaledFont( const QgsRenderContext &context ) const; + QFont scaledFont( const QgsRenderContext &context, double scaleFactor = 1.0 ) const; %Docstring Returns a font with the size scaled to match the format's size settings (including units and map unit scale) for a specified render context. :param context: destination render context +:param scaleFactor: optional font size scaling factor. It is recommended to set this to + QgsTextRenderer.FONT_WORKAROUND_SCALE and then manually scale painter devices or calculations + based on the resultant font metrics. Failure to do so will result in poor quality text rendering + at small font sizes. :return: font with scaled size @@ -520,6 +557,7 @@ Returns a pixmap preview for a text ``format``. }; + /************************************************************************ * This file has been generated automatically from * * * diff --git a/python/core/auto_generated/textrenderer/qgstextfragment.sip.in b/python/core/auto_generated/textrenderer/qgstextfragment.sip.in index f632199698cc..594e41595a95 100644 --- a/python/core/auto_generated/textrenderer/qgstextfragment.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextfragment.sip.in @@ -64,13 +64,18 @@ Sets the character ``format`` for the fragment. .. seealso:: :py:func:`characterFormat` %End - double horizontalAdvance( const QFont &font, bool fontHasBeenUpdatedForFragment = false ) const; + double horizontalAdvance( const QFont &font, bool fontHasBeenUpdatedForFragment = false, double scaleFactor = 1.0 ) const; %Docstring Returns the horizontal advance associated with this fragment, when rendered using the specified base ``font``. Set ``fontHasBeenUpdatedForFragment`` to ``True`` if ``font`` already represents the character format for this fragment. + +The optional ``scaleFactor`` parameter can specify a font size scaling factor. It is recommended to set this to +QgsTextRenderer.FONT_WORKAROUND_SCALE and then manually calculations +based on the resultant font metrics. Failure to do so will result in poor quality text rendering +at small font sizes. %End }; diff --git a/python/core/auto_generated/textrenderer/qgstextmasksettings.sip.in b/python/core/auto_generated/textrenderer/qgstextmasksettings.sip.in index 257c73136f3d..89ad31015733 100644 --- a/python/core/auto_generated/textrenderer/qgstextmasksettings.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextmasksettings.sip.in @@ -46,6 +46,9 @@ Copy constructor. ~QgsTextMaskSettings(); + bool operator==( const QgsTextMaskSettings &other ) const; + bool operator!=( const QgsTextMaskSettings &other ) const; + bool enabled() const; %Docstring Returns whether the mask is enabled. diff --git a/python/core/auto_generated/textrenderer/qgstextrenderer.sip.in b/python/core/auto_generated/textrenderer/qgstextrenderer.sip.in index fd8f6f6dd2dc..fd7be97552a3 100644 --- a/python/core/auto_generated/textrenderer/qgstextrenderer.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextrenderer.sip.in @@ -44,8 +44,34 @@ and background shapes. AlignLeft, AlignCenter, AlignRight, + AlignJustify, }; + static HAlignment convertQtHAlignment( Qt::Alignment alignment ); +%Docstring +Converts a Qt horizontal ``alignment`` flag to a QgsTextRenderer.HAlignment value. + +.. seealso:: :py:func:`convertQtVAlignment` + +.. versionadded:: 3.16 +%End + + enum VAlignment + { + AlignTop, + AlignVCenter, + AlignBottom, + }; + + static VAlignment convertQtVAlignment( Qt::Alignment alignment ); +%Docstring +Converts a Qt vertical ``alignment`` flag to a QgsTextRenderer.VAlignment value. + +.. seealso:: :py:func:`convertQtHAlignment` + +.. versionadded:: 3.16 +%End + static int sizeToPixel( double size, const QgsRenderContext &c, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &mapUnitScale = QgsMapUnitScale() ); %Docstring Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling) @@ -61,7 +87,7 @@ Calculates pixel size (considering output size should be in pixel or map units, static void drawText( const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, - bool drawAsOutlines = true ); + bool drawAsOutlines = true, VAlignment vAlignment = AlignTop ); %Docstring Draws text within a rectangle using the specified settings. @@ -75,6 +101,7 @@ Draws text within a rectangle using the specified settings. formats like SVG to maintain text as text objects, but at the cost of degraded rendering and may result in side effects like misaligned text buffers. This setting is deprecated and has no effect as of QGIS 3.4.3 and the text format should be set using :py:func:`QgsRenderContext.setTextRenderFormat()` instead. +:param vAlignment: vertical alignment (since QGIS 3.16) %End static void drawText( QPointF point, double rotation, HAlignment alignment, const QStringList &textLines, @@ -143,12 +170,17 @@ Draws a single component of rendered text using the specified settings. Private API only, will be removed in 4.0 %End - static QFontMetricsF fontMetrics( QgsRenderContext &context, const QgsTextFormat &format ); + static QFontMetricsF fontMetrics( QgsRenderContext &context, const QgsTextFormat &format, double scaleFactor = 1.0 ); %Docstring Returns the font metrics for the given text ``format``, when rendered in the specified render ``context``. The font metrics will take into account all scaling required by the render context. +The optional ``scaleFactor`` argument can specify a font size scaling factor. It is recommended to set this to +QgsTextRenderer.FONT_WORKAROUND_SCALE and then manually scale painter devices or calculations +based on the resultant font metrics. Failure to do so will result in poor quality text rendering +at small font sizes. + .. versionadded:: 3.2 %End @@ -175,6 +207,21 @@ Returns the height of a text based on a given format. :param fontMetrics: font metrics %End + static double textHeight( const QgsRenderContext &context, const QgsTextFormat &format, QChar character, bool includeEffects = false ); +%Docstring +Returns the height of a character when rendered with the specified text ``format``. + +:param context: render context +:param format: text format +:param character: character to determine height of. If ``character`` is invalid, then the maximum character height will be returned. +:param includeEffects: if ``True``, then the size of formatting effects such as buffers and shadows will be considered in the + returned height. If ``False``, then the returned size considers the character only. + +.. versionadded:: 3.16 +%End + + static const double FONT_WORKAROUND_SCALE; + }; diff --git a/python/core/auto_generated/textrenderer/qgstextshadowsettings.sip.in b/python/core/auto_generated/textrenderer/qgstextshadowsettings.sip.in index c8fccb8b708c..558bf9fc5b2a 100644 --- a/python/core/auto_generated/textrenderer/qgstextshadowsettings.sip.in +++ b/python/core/auto_generated/textrenderer/qgstextshadowsettings.sip.in @@ -47,6 +47,9 @@ Copy constructor. ~QgsTextShadowSettings(); + bool operator==( const QgsTextShadowSettings &other ) const; + bool operator!=( const QgsTextShadowSettings &other ) const; + bool enabled() const; %Docstring Returns whether the shadow is enabled. diff --git a/python/core/core_auto.sip b/python/core/core_auto.sip index a881f1952964..7b351dc27885 100644 --- a/python/core/core_auto.sip +++ b/python/core/core_auto.sip @@ -197,6 +197,7 @@ %Include auto_generated/qgsspatialindex.sip %Include auto_generated/qgsspatialindexkdbush.sip %Include auto_generated/qgsspatialindexkdbushdata.sip +%Include auto_generated/qgssourcecache.sip %Include auto_generated/qgssqliteutils.sip %Include auto_generated/qgssqlstatement.sip %Include auto_generated/qgsstatisticalsummary.sip diff --git a/python/gui/auto_generated/editorwidgets/qgsrelationwidgetwrapper.sip.in b/python/gui/auto_generated/editorwidgets/qgsrelationwidgetwrapper.sip.in index b4f0e9df0407..aa858d99fa6a 100644 --- a/python/gui/auto_generated/editorwidgets/qgsrelationwidgetwrapper.sip.in +++ b/python/gui/auto_generated/editorwidgets/qgsrelationwidgetwrapper.sip.in @@ -39,46 +39,78 @@ Only has an effect after :py:func:`~QgsRelationWidgetWrapper.widget` has been ca .. versionadded:: 2.18 %End - bool showLinkButton() const; + bool showLinkButton() const /Deprecated/; %Docstring Determines if the "link feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead %End - void setShowLinkButton( bool showLinkButton ); + void setShowLinkButton( bool showLinkButton ) /Deprecated/; %Docstring Determines if the "link feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead +%End + + bool showUnlinkButton() const /Deprecated/; +%Docstring +Determines if the "unlink feature" button should be shown + +.. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead +%End + + void setShowUnlinkButton( bool showUnlinkButton ) /Deprecated/; +%Docstring +Determines if the "unlink feature" button should be shown + +.. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - bool showSaveChildEditsButton() const; + void setShowSaveChildEditsButton( bool showChildEdits ) /Deprecated/; %Docstring -Determines if the "save child layer edits" button should be shown +Determines if the "Save child layer edits" button should be shown .. versionadded:: 3.14 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - void setShowSaveChildEditsButton( bool showSaveChildEditsButton ); + bool showSaveChildEditsButton() const /Deprecated/; %Docstring -Determines if the "save child layer edits" button should be shown +Determines if the "Save child layer edits" button should be shown .. versionadded:: 3.14 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead %End - bool showUnlinkButton() const; + void setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ); %Docstring -Determines if the "unlink feature" button should be shown +Defines the buttons which are shown -.. versionadded:: 2.18 +.. versionadded:: 3.16 %End - void setShowUnlinkButton( bool showUnlinkButton ); + QgsAttributeEditorRelation::Buttons visibleButtons() const; %Docstring -Determines if the "unlink feature" button should be shown +Returns the buttons which are shown -.. versionadded:: 2.18 +.. versionadded:: 3.16 %End QgsRelation relation() const; diff --git a/python/gui/auto_generated/processing/qgsprocessingwidgetwrapper.sip.in b/python/gui/auto_generated/processing/qgsprocessingwidgetwrapper.sip.in index 0f1c51987760..fb17ac63e1c0 100644 --- a/python/gui/auto_generated/processing/qgsprocessingwidgetwrapper.sip.in +++ b/python/gui/auto_generated/processing/qgsprocessingwidgetwrapper.sip.in @@ -588,6 +588,53 @@ and should give helpful text to users to indicate the expected results from the This is purely a text format and no expression validation is made against it. %End +}; + +class QgsProcessingHiddenWidgetWrapper: QgsAbstractProcessingParameterWidgetWrapper +{ +%Docstring + +An widget wrapper for hidden widgets. + +The hidden widget wrapper allows for creation of a widget wrapper which does not provide +a graphical widget, yet still implements the :py:class:`QgsAbstractProcessingParameterWidgetWrapper` +interface. + +.. versionadded:: 3.14 +%End + +%TypeHeaderCode +#include "qgsprocessingwidgetwrapper.h" +%End + public: + + QgsProcessingHiddenWidgetWrapper( const QgsProcessingParameterDefinition *parameter = 0, + QgsProcessingGui::WidgetType type = QgsProcessingGui::Standard, + QObject *parent /TransferThis/ = 0 ); +%Docstring +Constructor for QgsProcessingHiddenWidgetWrapper, for the specified +``parameter`` definition and dialog ``type``. +%End + + virtual void setWidgetValue( const QVariant &value, QgsProcessingContext &context ); + + virtual QVariant widgetValue() const; + + + virtual const QgsVectorLayer *linkedVectorLayer() const; + + + void setLinkedVectorLayer( const QgsVectorLayer *layer ); +%Docstring +Sets the vector layer linked to the wrapper. +%End + + protected: + virtual QWidget *createWidget(); + + virtual QLabel *createLabel(); + + }; /************************************************************************ diff --git a/python/gui/auto_generated/qgsattributedialog.sip.in b/python/gui/auto_generated/qgsattributedialog.sip.in index fca8b4e59a06..c1d6adc17963 100644 --- a/python/gui/auto_generated/qgsattributedialog.sip.in +++ b/python/gui/auto_generated/qgsattributedialog.sip.in @@ -73,6 +73,14 @@ Intercept window activate/deactivate events to show/hide the highlighted feature :param e: The event :return: The same as the parent QDialog +%End + + void setExtraContextScope( QgsExpressionContextScope *extraScope /Transfer/ ); +%Docstring +Sets ``extraScope`` as an additional expression context scope to be used +for calculations in this form. + +.. versionadded:: 3.16 %End public slots: diff --git a/python/gui/auto_generated/qgsattributeeditorcontext.sip.in b/python/gui/auto_generated/qgsattributeeditorcontext.sip.in index 3b6509d88579..96115b3b52cf 100644 --- a/python/gui/auto_generated/qgsattributeeditorcontext.sip.in +++ b/python/gui/auto_generated/qgsattributeeditorcontext.sip.in @@ -31,6 +31,7 @@ showing an embedded form due to relations) { SingleEditMode, AddFeatureMode, + FixAttributeMode, MultiEditMode, SearchMode, AggregateSearchMode, diff --git a/python/gui/auto_generated/qgsattributeform.sip.in b/python/gui/auto_generated/qgsattributeform.sip.in index f4957d4f34ff..2ee4d02c1dc6 100644 --- a/python/gui/auto_generated/qgsattributeform.sip.in +++ b/python/gui/auto_generated/qgsattributeform.sip.in @@ -167,6 +167,14 @@ In this case it will return a combined expression according to the chosen filter on all attribute widgets. .. versionadded:: 3.0 +%End + + void setExtraContextScope( QgsExpressionContextScope *extraScope /Transfer/ ); +%Docstring +Sets an additional expression context scope to be used +for calculations in this form. + +.. versionadded:: 3.16 %End signals: diff --git a/python/gui/auto_generated/qgsdataitemguiprovider.sip.in b/python/gui/auto_generated/qgsdataitemguiprovider.sip.in index 1bac74ef45f8..96d775afdd39 100644 --- a/python/gui/auto_generated/qgsdataitemguiprovider.sip.in +++ b/python/gui/auto_generated/qgsdataitemguiprovider.sip.in @@ -156,6 +156,15 @@ Caller takes responsibility of deleting created. The function is replacement of :py:func:`QgsDataItem.paramWidget()` .. versionadded:: 3.10 +%End + + static void notify( const QString &title, const QString &message, QgsDataItemGuiContext context, Qgis::MessageLevel level = Qgis::Info ); +%Docstring +Notify the user showing a ``message`` with ``title`` and ``level`` +If the context has a message bar the message will be shown in the message bar +else a message dialog will be used. + +.. versionadded:: 3.16 %End }; diff --git a/python/gui/auto_generated/qgsdoublevalidator.sip.in b/python/gui/auto_generated/qgsdoublevalidator.sip.in new file mode 100644 index 000000000000..0e5f28224706 --- /dev/null +++ b/python/gui/auto_generated/qgsdoublevalidator.sip.in @@ -0,0 +1,123 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsdoublevalidator.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + +class QgsDoubleValidator : QRegularExpressionValidator +{ +%Docstring + +QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator +and QRegularExpressionValidator to allow user to enter double with both +local and C interpretation as a fallback. + +.. versionadded:: 3.14 +%End + +%TypeHeaderCode +#include "qgsdoublevalidator.h" +%End + public: + + explicit QgsDoubleValidator( QObject *parent ); +%Docstring +Constructor for QgsDoubleValidator. +%End + + QgsDoubleValidator( const QRegularExpression &expression, double bottom, double top, QObject *parent ); +%Docstring +Constructor for QgsDoubleValidator. + +:param bottom: the minimal range limit accepted by the validator +:param top: the maximal range limit accepted by the validator +%End + + QgsDoubleValidator( double bottom, double top, QObject *parent ); +%Docstring +Constructor for QgsDoubleValidator. + +:param bottom: the minimal range limit accepted by the validator +:param top: the maximal range limit accepted by the validator +%End + + QgsDoubleValidator( double bottom, double top, int decimal, QObject *parent ); +%Docstring +Constructor for QgsDoubleValidator. + +:param bottom: the minimal range limit accepted by the validator +:param top: the maximal range limit accepted by the validator +:param decimal: the number of decimal accepted by the validator +%End + + + + QValidator::State validate( QString &input ) const; +%Docstring +Evaluates ``input`` string validity according to QRegularExpression +and ability to be converted in double value. +%End + + + static double toDouble( const QString &input ); +%Docstring +Converts ``input`` string to double value. +It used locale interpretation first +and C locale interpretation as fallback +%End + + void setBottom( double bottom ); +%Docstring +Set top range limit + +.. seealso:: :py:func:`setTop` + +.. seealso:: :py:func:`setRange` +%End + + void setTop( double top ); +%Docstring +Set top range limit + +.. seealso:: :py:func:`setBottom` + +.. seealso:: :py:func:`setRange` +%End + + virtual void setRange( double bottom, double top ); +%Docstring +Set bottom and top range limits + +.. seealso:: :py:func:`setBottom` + +.. seealso:: :py:func:`setTop` +%End + + double bottom() const; +%Docstring +Returns top range limit + +.. seealso:: :py:func:`setBottom` +%End + + double top() const; +%Docstring +Returns top range limit + +.. seealso:: :py:func:`setTop` +%End + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsdoublevalidator.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/qgsfontbutton.sip.in b/python/gui/auto_generated/qgsfontbutton.sip.in index d4dfe639055b..a6b534ca23c1 100644 --- a/python/gui/auto_generated/qgsfontbutton.sip.in +++ b/python/gui/auto_generated/qgsfontbutton.sip.in @@ -157,6 +157,51 @@ Register an expression context generator class that will be used to retrieve an expression context for the button when required. .. versionadded:: 3.10 +%End + + void setShowNullFormat( const bool show ); +%Docstring +Sets whether the "null format" option should be shown in the button's drop-down menu. This option +is only used for buttons set to the ModeTextRenderer :py:func:`~QgsFontButton.mode`. + +If selected, the "null format" option sets the button's format to an invalid :py:class:`QgsTextFormat`. This +can be used to represent a "use default format" state for the button. + +By default this option is not shown. + +.. seealso:: :py:func:`setNoFormatString` + +.. seealso:: :py:func:`showNullFormat` + +.. versionadded:: 3.16 +%End + + void setNoFormatString( const QString &string ); +%Docstring +Sets the ``string`` to use for the "null format" option in the button's drop-down menu. + +.. note:: + + The "null format" option is only shown if :py:func:`~QgsFontButton.showNullFormat` is ``True``. + +.. seealso:: :py:func:`setShowNullFormat` + +.. versionadded:: 3.16 +%End + + bool showNullFormat() const; +%Docstring +Returns whether the "null format" option will be shown in the button's drop-down menu. This option +is only used for buttons set to the ModeTextRenderer :py:func:`~QgsFontButton.mode`. + +If selected, the "null format" option sets the button's format to an invalid :py:class:`QgsTextFormat`. This +can be used to represent a "use default format" state for the button. + +By default this option is not shown. + +.. seealso:: :py:func:`setShowNullFormat` + +.. versionadded:: 3.16 %End public slots: @@ -167,6 +212,15 @@ Sets the current text ``format`` to show in the widget. This is only used when :py:func:`~QgsFontButton.mode` is ModeTextRenderer. .. seealso:: :py:func:`textFormat` +%End + + void setToNullFormat(); +%Docstring +Sets the text format to a null (invalid) :py:class:`QgsTextFormat`. + +This is only used when :py:func:`~QgsFontButton.mode` is ModeTextRenderer. + +.. versionadded:: 3.16 %End void setCurrentFont( const QFont &font ); diff --git a/python/gui/auto_generated/qgsmapcanvas.sip.in b/python/gui/auto_generated/qgsmapcanvas.sip.in index afcd7b723c19..affe6906e1f9 100644 --- a/python/gui/auto_generated/qgsmapcanvas.sip.in +++ b/python/gui/auto_generated/qgsmapcanvas.sip.in @@ -1145,6 +1145,16 @@ Emitted when the map canvas temporal range changes. .. versionadded:: 3.14 %End + + void contextMenuAboutToShow( QMenu *menu, QgsMapMouseEvent *event ); +%Docstring +Emitted before the map canvas context menu will be shown. +Can be used to extend the context menu. + +.. versionadded:: 3.16 +%End + + protected: virtual bool event( QEvent *e ); diff --git a/python/gui/auto_generated/qgsnewvectortabledialog.sip.in b/python/gui/auto_generated/qgsnewvectortabledialog.sip.in new file mode 100644 index 000000000000..67348244aac9 --- /dev/null +++ b/python/gui/auto_generated/qgsnewvectortabledialog.sip.in @@ -0,0 +1,124 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsnewvectortabledialog.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + +class QgsNewVectorTableDialog : QDialog +{ +%Docstring +The QgsNewVectorTableDialog class is a provider-agnostic database vector +and aspatial table designer dialog based on the connections API. + +It allows to design a new vector or aspatial database table by defining the schema +(if supported by the provider) and table name, the list of QgsFields, +the optional geometry type and SRID. + +The actual creation of the table is delegated to the connections API method +:py:func:`QgsAbstractDatabaseProviderConnection.createVectorTable()` + +.. versionadded:: 3.16 +%End + +%TypeHeaderCode +#include "qgsnewvectortabledialog.h" +%End + public: + + QgsNewVectorTableDialog( QgsAbstractDatabaseProviderConnection *conn, QWidget *parent /TransferThis/ = 0 ); +%Docstring +QgsNewVectorTableDialog constructor + +:param connection: DB connection, ownership is NOT transfered +:param parent: optional parent +%End + + void setSchemaName( const QString &name ); +%Docstring +Sets the schema ``name`` +%End + + void setTableName( const QString &name ); +%Docstring +Sets the table ``name`` +%End + + void setGeometryType( QgsWkbTypes::Type type ); +%Docstring +Sets the geometry ``type`` +%End + + void setCrs( const QgsCoordinateReferenceSystem &crs ); +%Docstring +Sets the CRS to ``crs`` +%End + + QgsCoordinateReferenceSystem crs() const; +%Docstring +Returns the CRS +%End + + QString tableName() const; +%Docstring +Returns the table name +%End + + QString schemaName() const; +%Docstring +Returns the schema name +%End + + QString geometryColumnName() const; +%Docstring +Returns the geometry column name +%End + + QgsFields fields() const; +%Docstring +Returns the fields +%End + + QgsWkbTypes::Type geometryType() const; +%Docstring +Returns the geometry type +%End + + void setFields( const QgsFields &fields ); +%Docstring +Sets the fields to ``fields`` +%End + + bool createSpatialIndex(); +%Docstring +Returns ``True`` if spatialindex checkbox is cheched +@return +%End + + QStringList validationErrors() const; +%Docstring +Returns the validation errors or an empty list if the dialog is valid +%End + + protected: + virtual void showEvent( QShowEvent *event ); + +}; + + + + + + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsnewvectortabledialog.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/qgsrelationeditorwidget.sip.in b/python/gui/auto_generated/qgsrelationeditorwidget.sip.in index 1cbca547d003..e32877e90f3b 100644 --- a/python/gui/auto_generated/qgsrelationeditorwidget.sip.in +++ b/python/gui/auto_generated/qgsrelationeditorwidget.sip.in @@ -34,6 +34,7 @@ class QgsRelationEditorWidget : QgsCollapsibleGroupBox %End public: + QgsRelationEditorWidget( QWidget *parent /TransferThis/ = 0 ); %Docstring @@ -108,46 +109,78 @@ Defines if a title label should be shown for this widget. .. versionadded:: 2.18 %End - bool showLinkButton() const; + bool showLinkButton() const /Deprecated/; %Docstring Determines if the "link feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead %End - void setShowLinkButton( bool showLinkButton ); + void setShowLinkButton( bool showLinkButton ) /Deprecated/; %Docstring Determines if the "link feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - bool showUnlinkButton() const; + bool showUnlinkButton() const /Deprecated/; %Docstring Determines if the "unlink feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead %End - void setShowUnlinkButton( bool showUnlinkButton ); + void setShowUnlinkButton( bool showUnlinkButton ) /Deprecated/; %Docstring Determines if the "unlink feature" button should be shown .. versionadded:: 2.18 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - void setShowSaveChildEditsButton( bool showChildEdits ); + void setShowSaveChildEditsButton( bool showChildEdits ) /Deprecated/; %Docstring Determines if the "Save child layer edits" button should be shown .. versionadded:: 3.14 + +.. deprecated:: QGIS 3.16 + use setVisibleButtons() instead %End - bool showSaveChildEditsButton() const; + bool showSaveChildEditsButton() const /Deprecated/; %Docstring Determines if the "Save child layer edits" button should be shown .. versionadded:: 3.14 + +.. deprecated:: QGIS 3.16 + use visibleButtons() instead +%End + + void setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ); +%Docstring +Defines the buttons which are shown + +.. versionadded:: 3.16 +%End + + QgsAttributeEditorRelation::Buttons visibleButtons() const; +%Docstring +Returns the buttons which are shown + +.. versionadded:: 3.16 %End QgsFeature feature() const; @@ -168,6 +201,7 @@ Called when an ``attribute`` value in the parent widget has changed to ``newValu }; + /************************************************************************ * This file has been generated automatically from * * * diff --git a/python/gui/auto_generated/tableeditor/qgstableeditordialog.sip.in b/python/gui/auto_generated/tableeditor/qgstableeditordialog.sip.in index cf89ee3cc814..e185c8385a13 100644 --- a/python/gui/auto_generated/tableeditor/qgstableeditordialog.sip.in +++ b/python/gui/auto_generated/tableeditor/qgstableeditordialog.sip.in @@ -116,6 +116,14 @@ Returns the table header values. Sets the table ``headers``. .. seealso:: :py:func:`tableHeaders` +%End + + void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator ); +%Docstring +Register an expression context generator class that will be used to retrieve +an expression context for the editor when required. + +.. versionadded:: 3.16 %End signals: diff --git a/python/gui/auto_generated/tableeditor/qgstableeditorwidget.sip.in b/python/gui/auto_generated/tableeditor/qgstableeditorwidget.sip.in index 666af0c0ee50..c0f2c3848bd5 100644 --- a/python/gui/auto_generated/tableeditor/qgstableeditorwidget.sip.in +++ b/python/gui/auto_generated/tableeditor/qgstableeditorwidget.sip.in @@ -98,6 +98,45 @@ invalid color will be returned. .. seealso:: :py:func:`setSelectionBackgroundColor` .. seealso:: :py:func:`selectionForegroundColor` +%End + + Qt::Alignment selectionHorizontalAlignment(); +%Docstring +Returns the horizontal alignment for the currently selected cells. + +If the returned value contains both horizontal and vertical alignment flags, then +the selected cells have a mix of different horizontal alignments. + +.. seealso:: :py:func:`selectionVerticalAlignment` +%End + + Qt::Alignment selectionVerticalAlignment(); +%Docstring +Returns the horizontal alignment for the currently selected cells. + +If the returned value contains both horizontal and vertical alignment flags, then +the selected cells have a mix of different vertical alignments. + +.. seealso:: :py:func:`selectionVerticalAlignment` +%End + + QgsProperty selectionCellProperty(); +%Docstring +Returns the QgsProperty used for the contents of the currently selected cells. + +If the returned value is a default constructed :py:class:`QgsProperty`, then the selected +cells have a mix of different properties. + +.. versionadded:: 3.16 +%End + + QgsTextFormat selectionTextFormat(); +%Docstring +Returns the text format for the currently selected cells. + +Returns an invalid QgsTextFormat if the selection has mixed text format. + +.. versionadded:: 3.16 %End double selectionRowHeight(); @@ -255,6 +294,42 @@ Sets the background color for the currently selected cells. .. seealso:: :py:func:`selectionBackgroundColor` .. seealso:: :py:func:`setSelectionForegroundColor` +%End + + void setSelectionHorizontalAlignment( Qt::Alignment alignment ); +%Docstring +Sets the horizontal alignment for the currently selected cells. + +.. seealso:: :py:func:`selectionHorizontalAlignment` + +.. seealso:: :py:func:`setSelectionVerticalAlignment` + +.. versionadded:: 3.16 +%End + + void setSelectionVerticalAlignment( Qt::Alignment alignment ); +%Docstring +Sets the vertical alignment for the currently selected cells. + +.. seealso:: :py:func:`selectionVerticalAlignment` + +.. seealso:: :py:func:`setSelectionHorizontalAlignment` + +.. versionadded:: 3.16 +%End + + void setSelectionCellProperty( const QgsProperty &property ); +%Docstring +Sets the cell contents QgsProperty for the currently selected cells. + +.. versionadded:: 3.16 +%End + + void setSelectionTextFormat( const QgsTextFormat &format ); +%Docstring +Sets the text ``format`` for the selected cells. + +.. versionadded:: 3.16 %End void setSelectionRowHeight( double height ); diff --git a/python/gui/auto_generated/vector/qgsvectorlayerproperties.sip.in b/python/gui/auto_generated/vector/qgsvectorlayerproperties.sip.in index 153fa9f56b42..430a039bea4c 100644 --- a/python/gui/auto_generated/vector/qgsvectorlayerproperties.sip.in +++ b/python/gui/auto_generated/vector/qgsvectorlayerproperties.sip.in @@ -42,7 +42,6 @@ Adds a properties page factory to the vector layer properties dialog. - public: }; diff --git a/python/gui/gui_auto.sip b/python/gui/gui_auto.sip index 6d206757b0f0..feb1b9659087 100644 --- a/python/gui/gui_auto.sip +++ b/python/gui/gui_auto.sip @@ -70,6 +70,7 @@ %Include auto_generated/qgsdial.sip %Include auto_generated/qgsdialog.sip %Include auto_generated/qgsdockwidget.sip +%Include auto_generated/qgsdoublevalidator.sip %Include auto_generated/qgsencodingfiledialog.sip %Include auto_generated/qgserrordialog.sip %Include auto_generated/qgsexpressionbuilderdialog.sip @@ -155,6 +156,7 @@ %Include auto_generated/qgsnewauxiliaryfielddialog.sip %Include auto_generated/qgsnewauxiliarylayerdialog.sip %Include auto_generated/qgsnewgeopackagelayerdialog.sip +%Include auto_generated/qgsnewvectortabledialog.sip %Include auto_generated/qgsnewhttpconnection.sip %Include auto_generated/qgsnewmemorylayerdialog.sip %Include auto_generated/qgsnewnamedialog.sip diff --git a/python/plugins/MetaSearch/dialogs/maindialog.py b/python/plugins/MetaSearch/dialogs/maindialog.py index 49c6502327f0..1c3ccbf0313b 100644 --- a/python/plugins/MetaSearch/dialogs/maindialog.py +++ b/python/plugins/MetaSearch/dialogs/maindialog.py @@ -285,6 +285,9 @@ def connection_info(self): self.textMetadata.document().setDefaultStyleSheet(style) self.textMetadata.setHtml(metadata) + # clear results in Search tab + self.clear_results() + def add_connection(self): """add new service""" @@ -541,6 +544,11 @@ def display_results(self): self.btnNext.setEnabled(disabled) self.btnLast.setEnabled(disabled) + def clear_results(self): + """clear search results""" + + self.treeRecords.clear() + def record_clicked(self): """record clicked signal""" diff --git a/python/plugins/MetaSearch/images/MetaSearch.svg b/python/plugins/MetaSearch/images/MetaSearch.svg index 15edee4df815..b5cbe3e99c99 100644 --- a/python/plugins/MetaSearch/images/MetaSearch.svg +++ b/python/plugins/MetaSearch/images/MetaSearch.svg @@ -1,350 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/python/plugins/db_manager/icons/dbmanager.svg b/python/plugins/db_manager/icons/dbmanager.svg index fcef1cbf2eb9..3018057f41c4 100644 --- a/python/plugins/db_manager/icons/dbmanager.svg +++ b/python/plugins/db_manager/icons/dbmanager.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/python/plugins/db_manager/icons/toolbar/mActionDBExport.svg b/python/plugins/db_manager/icons/toolbar/mActionDBExport.svg index c04d1fec4b20..e91f90fd40ec 100644 --- a/python/plugins/db_manager/icons/toolbar/mActionDBExport.svg +++ b/python/plugins/db_manager/icons/toolbar/mActionDBExport.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/python/plugins/db_manager/icons/toolbar/mActionDBImport.svg b/python/plugins/db_manager/icons/toolbar/mActionDBImport.svg index 406712cb835b..9daacad0346e 100644 --- a/python/plugins/db_manager/icons/toolbar/mActionDBImport.svg +++ b/python/plugins/db_manager/icons/toolbar/mActionDBImport.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/python/plugins/db_manager/icons/toolbar/mActionSQLWindow.svg b/python/plugins/db_manager/icons/toolbar/mActionSQLWindow.svg index 281eedb3386e..ef2831f13c91 100644 --- a/python/plugins/db_manager/icons/toolbar/mActionSQLWindow.svg +++ b/python/plugins/db_manager/icons/toolbar/mActionSQLWindow.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/python/plugins/processing/gui/AlgorithmDialog.py b/python/plugins/processing/gui/AlgorithmDialog.py index efab7596afc8..766863118233 100644 --- a/python/plugins/processing/gui/AlgorithmDialog.py +++ b/python/plugins/processing/gui/AlgorithmDialog.py @@ -72,6 +72,8 @@ def __init__(self, alg, in_place=False, parent=None): self.buttonBox().addButton(self.runAsBatchButton, QDialogButtonBox.ResetRole) # reset role to ensure left alignment else: + self.mainWidget().setParameters({'INPUT': self.active_layer}) + self.runAsBatchButton = None has_selection = self.active_layer and (self.active_layer.selectedFeatureCount() > 0) self.buttonBox().button(QDialogButtonBox.Ok).setText( @@ -84,8 +86,7 @@ def __init__(self, alg, in_place=False, parent=None): self.updateRunButtonVisibility() def getParametersPanel(self, alg, parent): - panel = ParametersPanel(parent, alg, self.in_place) - panel.active_layer = self.active_layer + panel = ParametersPanel(parent, alg, self.in_place, self.active_layer) return panel def runAsBatch(self): diff --git a/python/plugins/processing/gui/ParametersPanel.py b/python/plugins/processing/gui/ParametersPanel.py index 3f487c41d5f6..a074f1dee69f 100644 --- a/python/plugins/processing/gui/ParametersPanel.py +++ b/python/plugins/processing/gui/ParametersPanel.py @@ -35,7 +35,8 @@ QgsProcessingParametersWidget, QgsGui, QgsProcessingGui, - QgsProcessingParametersGenerator) + QgsProcessingParametersGenerator, + QgsProcessingHiddenWidgetWrapper) from qgis.utils import iface from processing.gui.wrappers import WidgetWrapperFactory, WidgetWrapper @@ -45,10 +46,10 @@ class ParametersPanel(QgsProcessingParametersWidget): - def __init__(self, parent, alg, in_place=False): + def __init__(self, parent, alg, in_place=False, active_layer=None): super().__init__(alg, parent) self.in_place = in_place - self.active_layer = None + self.active_layer = active_layer self.wrappers = {} @@ -101,6 +102,15 @@ def initWidgets(self): if param.isDestination(): continue else: + if self.in_place and param.name() in ('INPUT', 'OUTPUT'): + # don't show the input/output parameter widgets in in-place mode + # we still need to CREATE them, because other wrappers may need to interact + # with them (e.g. those parameters which need the input layer for field + # selections/crs properties/etc) + self.wrappers[param.name()] = QgsProcessingHiddenWidgetWrapper(param, QgsProcessingGui.Standard, self) + self.wrappers[param.name()].setLinkedVectorLayer(self.active_layer) + continue + wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent()) wrapper.setWidgetContext(widget_context) wrapper.registerProcessingContextGenerator(self.context_generator) @@ -119,13 +129,6 @@ def initWidgets(self): else: widget = wrapper.widget - if self.in_place and param.name() in ('INPUT', 'OUTPUT'): - # don't show the input/output parameter widgets in in-place mode - # we still need to CREATE them, because other wrappers may need to interact - # with them (e.g. those parameters which need the input layer for field - # selections/crs properties/etc) - continue - if widget is not None: if is_python_wrapper: widget.setToolTip(param.toolTip()) @@ -200,11 +203,6 @@ def createProcessingParameters(self): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if not param.isDestination(): - - if self.in_place and param.name() == 'INPUT': - parameters[param.name()] = self.active_layer - continue - try: wrapper = self.wrappers[param.name()] except KeyError: @@ -219,7 +217,7 @@ def createProcessingParameters(self): else: widget = wrapper.wrappedWidget() - if widget is None: + if not isinstance(wrapper, QgsProcessingHiddenWidgetWrapper) and widget is None: continue value = wrapper.parameterValue() diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests4.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests4.yaml index 9ad30d07c1d5..96f739a66b1a 100755 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests4.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests4.yaml @@ -2472,5 +2472,34 @@ tests: name: expected/filter_geom_lines_poly.gml type: vector + - algorithm: native:rescaleraster + name: Rescale raster (original nodata) + params: + BAND: 1 + INPUT: + name: dem.tif + type: raster + MAXIMUM: 65535.0 + MINIMUM: 0.0 + results: + OUTPUT: + hash: 63610fb1f7ec3d6530591b1eb479355b52cedfebf6331cec77f2b35c + type: rasterhash + + - algorithm: native:rescaleraster + name: Rescale raster (new nodata) + params: + BAND: 1 + INPUT: + name: dem.tif + type: raster + MAXIMUM: 65535.0 + MINIMUM: 0.0 + NODATA: -255.0 + results: + OUTPUT: + hash: 63610fb1f7ec3d6530591b1eb479355b52cedfebf6331cec77f2b35c + type: rasterhash + # See ../README.md for a description of the file format diff --git a/resources/cpt-city-qgis-min/bhw/bhw1/bhw1_w00t.svg b/resources/cpt-city-qgis-min/bhw/bhw1/bhw1_w00t.svg index 5b62d8912e77..00b0c190e740 100644 --- a/resources/cpt-city-qgis-min/bhw/bhw1/bhw1_w00t.svg +++ b/resources/cpt-city-qgis-min/bhw/bhw1/bhw1_w00t.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/bhw/bhw2/bhw2_39.svg b/resources/cpt-city-qgis-min/bhw/bhw2/bhw2_39.svg index 41365db85849..9322b77093d1 100644 --- a/resources/cpt-city-qgis-min/bhw/bhw2/bhw2_39.svg +++ b/resources/cpt-city-qgis-min/bhw/bhw2/bhw2_39.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_03.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_03.svg index 151b47d3f1d4..d709a7e35964 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_04.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_04.svg index 9ccf2502480f..b27d3f39401b 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_05.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_05.svg index 4b79e463b862..ea43f94eb0c6 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_06.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_06.svg index 98a1e6810ea3..b0ef0e302136 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_07.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_07.svg index 8f41158fe554..1c7c95fd4122 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_08.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_08.svg index 18726491039a..b074fa040796 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_09.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_09.svg index a4f6284b581c..41747bb33a0a 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_10.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_10.svg index a36ee229072b..f0c38927da5f 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/BrBG_11.svg b/resources/cpt-city-qgis-min/cb/div/BrBG_11.svg index 824202aa8191..133b005bd284 100644 --- a/resources/cpt-city-qgis-min/cb/div/BrBG_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/BrBG_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_03.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_03.svg index 6eb35b7808ef..ded2876cb6ed 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_04.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_04.svg index fcb6704b9a9e..296db31bd38d 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_05.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_05.svg index eb118dc5fbc5..9e8ecefcd9e3 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_06.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_06.svg index d23acb32e220..82bafc0999d9 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_07.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_07.svg index cbc67af82438..2d7607212428 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_08.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_08.svg index 43e3e17e2dba..e48ed6c190f2 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_09.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_09.svg index 37773e7ba8d3..55dbf65ef5fe 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_10.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_10.svg index 018718c6466f..88e9d1f50109 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PRGn_11.svg b/resources/cpt-city-qgis-min/cb/div/PRGn_11.svg index cb55562b9f44..5b1a4e3084df 100644 --- a/resources/cpt-city-qgis-min/cb/div/PRGn_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/PRGn_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_03.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_03.svg index 5cf3af673ba1..cb4cd8cf005e 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_04.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_04.svg index 9f2560083ca9..d7db928df45c 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_05.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_05.svg index 7142fa853269..cb66f385480f 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_06.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_06.svg index 5dd6a3576e28..1d146b30c8a2 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_07.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_07.svg index b1c9388b2708..1fde9e966cfa 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_08.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_08.svg index f2eac9d9196d..8fddf613bb3e 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_09.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_09.svg index 2c2119aaa0ca..cc01d00128ca 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_10.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_10.svg index b2e65d61cc47..0294c702eb9c 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PiYG_11.svg b/resources/cpt-city-qgis-min/cb/div/PiYG_11.svg index d9c218d569af..53ae9c0235b0 100644 --- a/resources/cpt-city-qgis-min/cb/div/PiYG_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/PiYG_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_03.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_03.svg index 42ce349ab057..913952850514 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_04.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_04.svg index ee600931d98a..3d00514e8492 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_05.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_05.svg index 3541d95afbe3..a1c99ab8045f 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_06.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_06.svg index 285733834f68..cf3b69404ff4 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_07.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_07.svg index a1d87a72cab0..14fb3b9a3209 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_08.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_08.svg index 99c28643a376..24190a901285 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_09.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_09.svg index c8f13dfb6387..1d79b73a7c1f 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_10.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_10.svg index d22c7a2ae635..462e8800f6c2 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/PuOr_11.svg b/resources/cpt-city-qgis-min/cb/div/PuOr_11.svg index e8630a049d70..65c5f66a9a1e 100644 --- a/resources/cpt-city-qgis-min/cb/div/PuOr_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/PuOr_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_03.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_03.svg index cbe3bdf1ca49..c72daedf4296 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_04.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_04.svg index 9621a105ffd0..a2b0195bae48 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_05.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_05.svg index a2de8d8dd673..eb132a8ede75 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_06.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_06.svg index 88e28132f9d3..c3e527cc300c 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_07.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_07.svg index d5c2d696dbe2..1bdb8611442c 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_08.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_08.svg index 1d43a75c5c03..3fe7ac995de2 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_09.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_09.svg index b0e4017524fc..d59c5c479338 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_10.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_10.svg index 0fac91925d8a..47f3fd01a77e 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdBu_11.svg b/resources/cpt-city-qgis-min/cb/div/RdBu_11.svg index 500b56055451..854dcb463f2b 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdBu_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdBu_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_03.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_03.svg index ba2f14a7297e..2af1ec0d7c74 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_04.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_04.svg index d68e103b7248..06b6f95a9cf2 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_05.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_05.svg index bcbff2aa4c24..5111c6fd6d8b 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_06.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_06.svg index 025fd33de73d..cbd2b7466a9d 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_07.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_07.svg index 25c1dccc65c6..bcf179f5b1ac 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_08.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_08.svg index 9ddc131daa05..a6fa07fb2964 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_09.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_09.svg index b7c6481dd9a7..40ceba2ba8b5 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_10.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_10.svg index 16a9f3f960b4..bef52cf6b38c 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdGy_11.svg b/resources/cpt-city-qgis-min/cb/div/RdGy_11.svg index 446c35de694e..b75dd517ae1f 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdGy_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdGy_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_03.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_03.svg index d202a05f1f17..4413b3338945 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_04.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_04.svg index f63fce468189..087f2ec69fcf 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_05.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_05.svg index dacd40a73bac..79ea8080389a 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_06.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_06.svg index 36dab0307da7..c683032aba25 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_07.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_07.svg index 603e9a4782ef..5f4e91f81b95 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_08.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_08.svg index 8302f8b4844c..b3a2e25584b0 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_09.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_09.svg index 6017a18e4b6f..90420fba8b59 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_10.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_10.svg index 9968d1a89675..cc7796244d56 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlBu_11.svg b/resources/cpt-city-qgis-min/cb/div/RdYlBu_11.svg index facb921829a3..34dbb871c749 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlBu_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlBu_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_03.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_03.svg index 6aaf206be87e..0d7707a5a0dd 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_04.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_04.svg index 37b988efc02e..e656ea4afd21 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_05.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_05.svg index a7466eae3ba9..4c4042267317 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_06.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_06.svg index c2b427cc74ff..1aaea3c5167f 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_07.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_07.svg index 23b6bfad4ec0..c0011f583e42 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_08.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_08.svg index 2239cfbbe04a..edbf066f084c 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_09.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_09.svg index 0e599e55f763..2455d37d71f1 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_10.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_10.svg index 4632d066d1ae..73728c9ee942 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/RdYlGn_11.svg b/resources/cpt-city-qgis-min/cb/div/RdYlGn_11.svg index 0671f465f617..e3a521812b9c 100644 --- a/resources/cpt-city-qgis-min/cb/div/RdYlGn_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/RdYlGn_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_03.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_03.svg index eb9cff8fb94d..53184c9fa273 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_03.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_04.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_04.svg index 6bc3f7fa6edd..ef8e18a09bdb 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_04.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_05.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_05.svg index 07c9ef41867b..7bdc680ba8d4 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_05.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_06.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_06.svg index b7efd5c2b81d..f7b423289477 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_06.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_07.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_07.svg index e0bfaab86bfb..56c1b399ce87 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_07.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_08.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_08.svg index ba9d8b9fbe47..475924e86064 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_08.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_09.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_09.svg index a2c00cbf4ea5..d1d996caf69b 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_09.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_10.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_10.svg index 21a5176818b9..676fc8b925fb 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_10.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/div/Spectral_11.svg b/resources/cpt-city-qgis-min/cb/div/Spectral_11.svg index ef040435bcf7..814067422587 100644 --- a/resources/cpt-city-qgis-min/cb/div/Spectral_11.svg +++ b/resources/cpt-city-qgis-min/cb/div/Spectral_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Accent_03.svg b/resources/cpt-city-qgis-min/cb/qual/Accent_03.svg index 50ea65bd6801..4e9690576056 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Accent_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Accent_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Accent_04.svg b/resources/cpt-city-qgis-min/cb/qual/Accent_04.svg index 7cac8bfb1cec..92c143a50795 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Accent_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Accent_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Accent_05.svg b/resources/cpt-city-qgis-min/cb/qual/Accent_05.svg index e0751c7d3fa5..96189db5bda6 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Accent_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Accent_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Accent_06.svg b/resources/cpt-city-qgis-min/cb/qual/Accent_06.svg index 547b3d2da953..8d547797fcf3 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Accent_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Accent_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Accent_07.svg b/resources/cpt-city-qgis-min/cb/qual/Accent_07.svg index b6d9e67ce2ea..94150e1cccc0 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Accent_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Accent_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Accent_08.svg b/resources/cpt-city-qgis-min/cb/qual/Accent_08.svg index 01af60b91737..2752aad51e04 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Accent_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Accent_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Dark2_03.svg b/resources/cpt-city-qgis-min/cb/qual/Dark2_03.svg index 92081017d8ee..f5e96ce49a93 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Dark2_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Dark2_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Dark2_04.svg b/resources/cpt-city-qgis-min/cb/qual/Dark2_04.svg index 0ff4ef449d13..32a4eb577c30 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Dark2_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Dark2_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Dark2_05.svg b/resources/cpt-city-qgis-min/cb/qual/Dark2_05.svg index 2175c31d0c39..bf9db56281f4 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Dark2_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Dark2_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Dark2_06.svg b/resources/cpt-city-qgis-min/cb/qual/Dark2_06.svg index fd9cd183cea6..93daf15a36a4 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Dark2_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Dark2_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Dark2_07.svg b/resources/cpt-city-qgis-min/cb/qual/Dark2_07.svg index ee7a0eb2952c..bac5fca118fa 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Dark2_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Dark2_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Dark2_08.svg b/resources/cpt-city-qgis-min/cb/qual/Dark2_08.svg index 953287b3326b..8621f97e867e 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Dark2_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Dark2_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_03.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_03.svg index 0eac11acccd2..127cc8419d33 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_04.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_04.svg index 27cf80783dc9..99cb038ed514 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_05.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_05.svg index c6b8a4671314..ac85c31492a1 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_06.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_06.svg index b76de371d2f1..6b17894f18a1 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_07.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_07.svg index 830a2dd8204a..f5e0f07da01e 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_08.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_08.svg index eb1b3a854d23..e1ded80deae2 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_09.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_09.svg index 3531e7b9ab37..5b9fda496dd7 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_09.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_10.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_10.svg index 14a9d6fc3f56..8bc931ed1c1f 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_10.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_11.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_11.svg index 842aeac308dc..c38109bfe081 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_11.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Paired_12.svg b/resources/cpt-city-qgis-min/cb/qual/Paired_12.svg index 444bcc373e13..0688bc853ae9 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Paired_12.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Paired_12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_03.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_03.svg index e78bb31cab9c..85f93ec4f53d 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_04.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_04.svg index d6342af0f29c..dcdd57e4e732 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_05.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_05.svg index 323a7eae0250..86ff4ee5bcc3 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_06.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_06.svg index 84fb3869bcff..a10d4a085800 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_07.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_07.svg index 16c8c5f8470d..3049cf18cd52 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_08.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_08.svg index cb0d1450120f..5bc2225e7f1b 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel1_09.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel1_09.svg index 2d9dbd418597..05da48bc99fb 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel1_09.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel1_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel2_03.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel2_03.svg index 3b41dd4fbd53..1408bed18e42 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel2_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel2_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel2_04.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel2_04.svg index 84116f16358f..76cdca544491 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel2_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel2_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel2_05.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel2_05.svg index 098f097065cf..e4a2b6784102 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel2_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel2_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel2_06.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel2_06.svg index e22de566b793..6f778f9ea915 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel2_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel2_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel2_07.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel2_07.svg index e88ffdcb1c83..4c6f94107e0a 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel2_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel2_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Pastel2_08.svg b/resources/cpt-city-qgis-min/cb/qual/Pastel2_08.svg index bde7b2e3921a..9318fc23ba6f 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Pastel2_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Pastel2_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_03.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_03.svg index 115725d69bef..2a8c061e4cf5 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_04.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_04.svg index fb0d1d4e1423..553e40ed3baf 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_05.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_05.svg index 8e2a8d23e9a6..bc013e098365 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_06.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_06.svg index 12934120e25f..0a03694e1982 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_07.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_07.svg index b4ac6b3a0ea8..c1fa444fc9e7 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_08.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_08.svg index 4096a1089e98..8beba9fcfe48 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set1_09.svg b/resources/cpt-city-qgis-min/cb/qual/Set1_09.svg index cbc8f8b4eb5e..344f91c2afce 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set1_09.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set1_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set2_03.svg b/resources/cpt-city-qgis-min/cb/qual/Set2_03.svg index 7be226e3ae1f..5ec6934da85b 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set2_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set2_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set2_04.svg b/resources/cpt-city-qgis-min/cb/qual/Set2_04.svg index ed5171c49d57..9398cbc90304 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set2_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set2_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set2_05.svg b/resources/cpt-city-qgis-min/cb/qual/Set2_05.svg index 1961b905b94a..9ed1d4c41569 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set2_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set2_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set2_06.svg b/resources/cpt-city-qgis-min/cb/qual/Set2_06.svg index ec1b777833aa..0ca3b2072af8 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set2_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set2_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set2_07.svg b/resources/cpt-city-qgis-min/cb/qual/Set2_07.svg index 262d422d606b..1d3094e1cff8 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set2_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set2_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set2_08.svg b/resources/cpt-city-qgis-min/cb/qual/Set2_08.svg index 52fa11cee455..3a8ed66d9291 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set2_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set2_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_03.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_03.svg index 870e58220b45..e4f9c2542a3e 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_03.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_04.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_04.svg index 2abad4cc361c..207ee781fdd3 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_04.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_05.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_05.svg index eb1e717c6f9d..11ad46a191d9 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_05.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_06.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_06.svg index 0976fc2b8fa2..0cd1d0a16a98 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_06.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_07.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_07.svg index b85e094ac7fd..13cfc2fc1b35 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_07.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_08.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_08.svg index dabc47bbda80..b0a92d3a487c 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_08.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_09.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_09.svg index fe4217cb19de..fd72eb910f60 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_09.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_10.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_10.svg index 7f8c910ffc95..e3bbca5ead29 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_10.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_11.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_11.svg index 072689214407..b32792fdb094 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_11.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/qual/Set3_12.svg b/resources/cpt-city-qgis-min/cb/qual/Set3_12.svg index 86ce6644494c..9c351a26d44f 100644 --- a/resources/cpt-city-qgis-min/cb/qual/Set3_12.svg +++ b/resources/cpt-city-qgis-min/cb/qual/Set3_12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_03.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_03.svg index dc2bd1492340..33e29a7e7e8e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_04.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_04.svg index 487c3e6ebdda..69d443d98a72 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_05.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_05.svg index 1953d11b9e10..66605572066a 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_06.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_06.svg index 011a52e3fb71..8bd78cbc8527 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_07.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_07.svg index 0a144b9f6b59..737ad6b52dbe 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_08.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_08.svg index 72971079fb5f..3823b13b836f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Blues_09.svg b/resources/cpt-city-qgis-min/cb/seq/Blues_09.svg index ef72333e00fb..24754222dd7f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Blues_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Blues_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_03.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_03.svg index d75835e042f1..e90a162bcdd1 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_04.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_04.svg index f067bba865f0..16487cecca51 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_05.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_05.svg index dd3351ca26c9..f85ac895245c 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_06.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_06.svg index 384ef1486bde..1c84ce1b418a 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_07.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_07.svg index 537d8a3e4543..1334f2806b91 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_08.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_08.svg index 512d37a07de4..bfda4eedbe51 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuGn_09.svg b/resources/cpt-city-qgis-min/cb/seq/BuGn_09.svg index 812886667c10..e8ce8312631f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuGn_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuGn_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_03.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_03.svg index aae71696be89..e7a750ec2fc4 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_04.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_04.svg index 97ed23c40504..d46c1a0c9c50 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_05.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_05.svg index 1a1645e00d1a..6d349ea317c0 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_06.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_06.svg index 5cec2730b646..c15ff29b0f84 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_07.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_07.svg index ad19eddb48d9..7296e003366f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_08.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_08.svg index d4a436fc71a2..b9d793671e05 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/BuPu_09.svg b/resources/cpt-city-qgis-min/cb/seq/BuPu_09.svg index 42e2bd318a43..c927ff599983 100644 --- a/resources/cpt-city-qgis-min/cb/seq/BuPu_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/BuPu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_03.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_03.svg index 33b7a81bee5b..f3f825111f93 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_04.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_04.svg index 7e6589442832..928cd49c7523 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_05.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_05.svg index 87a219a316ca..013daa90d11d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_06.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_06.svg index aab729182612..c1051951da95 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_07.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_07.svg index b9c21036eac2..ba7e6b56074d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_08.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_08.svg index 43e2cc29bf0e..8b45c7e92a17 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/GnBu_09.svg b/resources/cpt-city-qgis-min/cb/seq/GnBu_09.svg index 27d7f81ebae6..cd8cbb52d54d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/GnBu_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/GnBu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_03.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_03.svg index fc3b37c2f0a0..c6e660d38430 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_04.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_04.svg index 249a147896d6..73594e94aba0 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_05.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_05.svg index 821105ca70e5..9a1d8582126d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_06.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_06.svg index fd7b54f2e433..51043b0e4049 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_07.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_07.svg index 2b3e3d914895..767512b970d7 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_08.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_08.svg index 8006881feaf2..beca1fa40e2f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greens_09.svg b/resources/cpt-city-qgis-min/cb/seq/Greens_09.svg index bb381fca6049..f640f39ac180 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greens_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greens_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_03.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_03.svg index 5be43af44c34..94802eecbcab 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_04.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_04.svg index e5d4e0d1cf64..c89c26df31ec 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_05.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_05.svg index 0be359629158..ea91ff71ea93 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_06.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_06.svg index 6a9b853a702d..3321db012587 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_07.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_07.svg index 0e5fea3489f8..86132eb0fd8f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_08.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_08.svg index 863f17e6d7bd..c98ed975b9a2 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Greys_09.svg b/resources/cpt-city-qgis-min/cb/seq/Greys_09.svg index 50ce61b5f117..42bd18ba3e53 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Greys_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Greys_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_03.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_03.svg index a39c314ca69d..e4d0bf5245a0 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_04.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_04.svg index ed513d8960ea..1551c1d16b2f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_05.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_05.svg index 2c1d61c1c6ac..d455ffbdb52e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_06.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_06.svg index 6238478fd772..868ce65ef04d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_07.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_07.svg index 96381c50ee02..19c2f13b37f0 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_08.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_08.svg index 5dc76af9dd21..2a1dedd25b39 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/OrRd_09.svg b/resources/cpt-city-qgis-min/cb/seq/OrRd_09.svg index f154fca85619..aa823796a678 100644 --- a/resources/cpt-city-qgis-min/cb/seq/OrRd_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/OrRd_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_03.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_03.svg index 1057231cfba3..d3e18780911d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_04.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_04.svg index cede78405c84..64c1cc37bd0a 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_05.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_05.svg index b40b3445ec98..1f76f70ff008 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_06.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_06.svg index a4df8a7cdba1..a32bcd0b7c5b 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_07.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_07.svg index 1b7f48fc2053..a7a1aeb70348 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_08.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_08.svg index 7d92b5e988d4..c2c2ecdc84c0 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Oranges_09.svg b/resources/cpt-city-qgis-min/cb/seq/Oranges_09.svg index a148c8fa3da9..ca1ffb66ce86 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Oranges_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Oranges_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_03.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_03.svg index 04f2e89c12c7..b03f136b0d99 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_04.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_04.svg index a6eb70384090..02b3f3cf12b3 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_05.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_05.svg index 3704537318be..27d6be36e480 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_06.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_06.svg index 11d494b5b846..1353306a0716 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_07.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_07.svg index 6c77ae633c32..7079493ba8e5 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_08.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_08.svg index a2aaf8bace8a..00d9b8cfca2e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_09.svg b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_09.svg index 1aad23434c8a..5fe20ab073ca 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBuGn_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBuGn_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_03.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_03.svg index 483a5300b409..ef445820cf3d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_04.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_04.svg index fa2633ce53f4..e092393b936d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_05.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_05.svg index 09cd6b54816f..04cfa460e395 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_06.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_06.svg index b5d74968a784..9d3ff1772172 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_07.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_07.svg index 8cee13030d34..213cb33128b5 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_08.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_08.svg index 33205af930bb..73ef3fa82218 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuBu_09.svg b/resources/cpt-city-qgis-min/cb/seq/PuBu_09.svg index 4b0994087b8f..5e91a61102ae 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuBu_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuBu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_03.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_03.svg index baf590585892..d6988ec8cfcb 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_04.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_04.svg index 80a44fa19583..645afcaed026 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_05.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_05.svg index 30b9618f06f7..8f28f4c3723e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_06.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_06.svg index 9a24cf04f48a..55e2cdff9693 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_07.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_07.svg index 21e79554cca1..13fc8a889d3c 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_08.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_08.svg index 531677d65026..cc67703ff2ec 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/PuRd_09.svg b/resources/cpt-city-qgis-min/cb/seq/PuRd_09.svg index abd5c9a086e9..42ec36649956 100644 --- a/resources/cpt-city-qgis-min/cb/seq/PuRd_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/PuRd_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_03.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_03.svg index 626adf0cbfa8..157e133b1885 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_04.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_04.svg index ee7ecab0f08a..50b4b0fba33e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_05.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_05.svg index c8f743fff18a..8684a9d8b472 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_06.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_06.svg index b7ce24030171..8e4c187aed68 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_07.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_07.svg index bc15b1ace384..0abf592b996f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_08.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_08.svg index 9c5d6033b4d5..1abb2a077e06 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Purples_09.svg b/resources/cpt-city-qgis-min/cb/seq/Purples_09.svg index c774c227ca96..4a6ac574f6ee 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Purples_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Purples_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_03.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_03.svg index a74a87eaaf1e..b72cb539a000 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_04.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_04.svg index 4f00a61ceb78..dce084c4db4b 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_05.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_05.svg index d8cea7df5d26..242d23635804 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_06.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_06.svg index 2609d672ed62..3b1451dd77ea 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_07.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_07.svg index ad97258ef8c4..7b330bf29816 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_08.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_08.svg index 6997c9f1a543..e9eb5a74f100 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/RdPu_09.svg b/resources/cpt-city-qgis-min/cb/seq/RdPu_09.svg index 832483172bb3..bf269aa201fe 100644 --- a/resources/cpt-city-qgis-min/cb/seq/RdPu_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/RdPu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_03.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_03.svg index 67869eaa944c..de5688f6fb24 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_04.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_04.svg index b004e1dc445c..53ba6638c2a7 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_05.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_05.svg index 01ba2837a5a8..7cda07a13f2e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_06.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_06.svg index 407e4899ea95..5e10f2740fbd 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_07.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_07.svg index 87204d41d87d..5b5f350e67e5 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_08.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_08.svg index df5b61d6158d..7c547037206e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/Reds_09.svg b/resources/cpt-city-qgis-min/cb/seq/Reds_09.svg index bde2c91088fc..43d408df133e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/Reds_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/Reds_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_03.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_03.svg index f595533b93fc..85ddb2eecfcd 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_04.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_04.svg index 1ee71260eda2..6e58d593fc6d 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_05.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_05.svg index 434f0e2fa1dd..628eb4e251cf 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_06.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_06.svg index 42077f914e4b..c52c557fa1dc 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_07.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_07.svg index 5ab23b61c56e..d450e114c619 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_08.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_08.svg index 1baa1f7439ba..c0620f217b74 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_09.svg b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_09.svg index a5ad31891239..9ffec172c1f1 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGnBu_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGnBu_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_03.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_03.svg index e8049090e3e3..597daa484cf1 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_04.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_04.svg index 4515dd33093d..cf92455fb80c 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_05.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_05.svg index 5308d4f767e5..6785c6bb1856 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_06.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_06.svg index 9057ab635f25..e28d7a47c0c0 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_07.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_07.svg index ecfe0b0c25fe..0159e381575c 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_08.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_08.svg index 91c8aa138fda..697c61f14c9f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlGn_09.svg b/resources/cpt-city-qgis-min/cb/seq/YlGn_09.svg index 5b8015e8204f..9570db1243dd 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlGn_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlGn_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_03.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_03.svg index 5931dc8f71da..664e35e1e057 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_04.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_04.svg index 04b2fab76134..f79aacbf878f 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_05.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_05.svg index deeaa2e34494..6f4e455c377e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_06.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_06.svg index 26ba008bec34..ee804a03d343 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_07.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_07.svg index 9726714cd908..5a82ed802125 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_08.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_08.svg index f03ebe0252f1..c0e2abf605af 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_09.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_09.svg index 7c6d0e53cca0..7c89faea42ee 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrBr_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrBr_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_03.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_03.svg index 497324b0e0eb..d26de51e801b 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_03.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_03.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_04.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_04.svg index 5cfc3405fec0..716fdbae0764 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_04.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_04.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_05.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_05.svg index 1c86b0d1eedf..c6bde8f2a0fb 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_05.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_06.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_06.svg index 4267c2d33c63..242ac06b7b4e 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_06.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_07.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_07.svg index 7512f4484144..fb17a4bb284a 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_07.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_08.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_08.svg index 169a8a1450df..be75d7bf45bc 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_08.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_09.svg b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_09.svg index c04edae98bf3..af88030b4dde 100644 --- a/resources/cpt-city-qgis-min/cb/seq/YlOrRd_09.svg +++ b/resources/cpt-city-qgis-min/cb/seq/YlOrRd_09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/dg/ch05m151008.svg b/resources/cpt-city-qgis-min/dg/ch05m151008.svg index b8c2fca55552..18f894c5f3de 100644 --- a/resources/cpt-city-qgis-min/dg/ch05m151008.svg +++ b/resources/cpt-city-qgis-min/dg/ch05m151008.svg @@ -1,270 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/dg/ch05m151010.svg b/resources/cpt-city-qgis-min/dg/ch05m151010.svg index f5e53920be5d..753278b2e1d8 100644 --- a/resources/cpt-city-qgis-min/dg/ch05m151010.svg +++ b/resources/cpt-city-qgis-min/dg/ch05m151010.svg @@ -1,270 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ds9/b.svg b/resources/cpt-city-qgis-min/ds9/b.svg index a4710f23dd41..1492f2fe0f03 100644 --- a/resources/cpt-city-qgis-min/ds9/b.svg +++ b/resources/cpt-city-qgis-min/ds9/b.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ds9/he.svg b/resources/cpt-city-qgis-min/ds9/he.svg index 95ca3408f149..112789e94d01 100644 --- a/resources/cpt-city-qgis-min/ds9/he.svg +++ b/resources/cpt-city-qgis-min/ds9/he.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ds9/red.svg b/resources/cpt-city-qgis-min/ds9/red.svg index d6f587811b41..6f48427af268 100644 --- a/resources/cpt-city-qgis-min/ds9/red.svg +++ b/resources/cpt-city-qgis-min/ds9/red.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ds9/sls.svg b/resources/cpt-city-qgis-min/ds9/sls.svg index e079a1ec57c0..813b44a67bde 100644 --- a/resources/cpt-city-qgis-min/ds9/sls.svg +++ b/resources/cpt-city-qgis-min/ds9/sls.svg @@ -1,214 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/fme/feet/natural.svg b/resources/cpt-city-qgis-min/fme/feet/natural.svg index d7ecc554fd4e..9bdd31a2c6c3 100644 --- a/resources/cpt-city-qgis-min/fme/feet/natural.svg +++ b/resources/cpt-city-qgis-min/fme/feet/natural.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/fme/feet/neutral.svg b/resources/cpt-city-qgis-min/fme/feet/neutral.svg index d9ad45bd3089..2b7b928bb66a 100644 --- a/resources/cpt-city-qgis-min/fme/feet/neutral.svg +++ b/resources/cpt-city-qgis-min/fme/feet/neutral.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/fme/feet/textbook.svg b/resources/cpt-city-qgis-min/fme/feet/textbook.svg index 920f413b0a91..382d36c8a47a 100644 --- a/resources/cpt-city-qgis-min/fme/feet/textbook.svg +++ b/resources/cpt-city-qgis-min/fme/feet/textbook.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/fme/metres/natural.svg b/resources/cpt-city-qgis-min/fme/metres/natural.svg index d7ecc554fd4e..9bdd31a2c6c3 100644 --- a/resources/cpt-city-qgis-min/fme/metres/natural.svg +++ b/resources/cpt-city-qgis-min/fme/metres/natural.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gery/seismic.svg b/resources/cpt-city-qgis-min/gery/seismic.svg index 579d77498a1d..2931a16a0f75 100644 --- a/resources/cpt-city-qgis-min/gery/seismic.svg +++ b/resources/cpt-city-qgis-min/gery/seismic.svg @@ -1,68 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Aneurism.svg b/resources/cpt-city-qgis-min/ggr/Aneurism.svg index 68044cc1b86c..d34c089da470 100644 --- a/resources/cpt-city-qgis-min/ggr/Aneurism.svg +++ b/resources/cpt-city-qgis-min/ggr/Aneurism.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Blinds.svg b/resources/cpt-city-qgis-min/ggr/Blinds.svg index 44309c91af38..afb7dd7408fa 100644 --- a/resources/cpt-city-qgis-min/ggr/Blinds.svg +++ b/resources/cpt-city-qgis-min/ggr/Blinds.svg @@ -1,119 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Browns.svg b/resources/cpt-city-qgis-min/ggr/Browns.svg index 6b235df679d2..d77748c4e804 100644 --- a/resources/cpt-city-qgis-min/ggr/Browns.svg +++ b/resources/cpt-city-qgis-min/ggr/Browns.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/CD.svg b/resources/cpt-city-qgis-min/ggr/CD.svg index 871d98c0e6e8..3726237d217d 100644 --- a/resources/cpt-city-qgis-min/ggr/CD.svg +++ b/resources/cpt-city-qgis-min/ggr/CD.svg @@ -1,52 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Coffee.svg b/resources/cpt-city-qgis-min/ggr/Coffee.svg index b50eb9fe7f74..b9867b4322db 100644 --- a/resources/cpt-city-qgis-min/ggr/Coffee.svg +++ b/resources/cpt-city-qgis-min/ggr/Coffee.svg @@ -1,116 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Default.svg b/resources/cpt-city-qgis-min/ggr/Default.svg index b1bc01d6cef5..bdf995e5c380 100644 --- a/resources/cpt-city-qgis-min/ggr/Default.svg +++ b/resources/cpt-city-qgis-min/ggr/Default.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Golden.svg b/resources/cpt-city-qgis-min/ggr/Golden.svg index 54ebc4e104e3..7ffb52a87614 100644 --- a/resources/cpt-city-qgis-min/ggr/Golden.svg +++ b/resources/cpt-city-qgis-min/ggr/Golden.svg @@ -1,43 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Greens.svg b/resources/cpt-city-qgis-min/ggr/Greens.svg index 922c5a7de3a2..bc3f4d2f41d5 100644 --- a/resources/cpt-city-qgis-min/ggr/Greens.svg +++ b/resources/cpt-city-qgis-min/ggr/Greens.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Incandescent.svg b/resources/cpt-city-qgis-min/ggr/Incandescent.svg index 51ee2e0e7fe3..0b44ef8843f2 100644 --- a/resources/cpt-city-qgis-min/ggr/Incandescent.svg +++ b/resources/cpt-city-qgis-min/ggr/Incandescent.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Pastels.svg b/resources/cpt-city-qgis-min/ggr/Pastels.svg index 83e1cb17c0f8..99c68757ef59 100644 --- a/resources/cpt-city-qgis-min/ggr/Pastels.svg +++ b/resources/cpt-city-qgis-min/ggr/Pastels.svg @@ -1,43 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Purples.svg b/resources/cpt-city-qgis-min/ggr/Purples.svg index ae1511fdc19e..675f9aaa114d 100644 --- a/resources/cpt-city-qgis-min/ggr/Purples.svg +++ b/resources/cpt-city-qgis-min/ggr/Purples.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Skyline.svg b/resources/cpt-city-qgis-min/ggr/Skyline.svg index 3c3e385ab757..6d5eb8408f8c 100644 --- a/resources/cpt-city-qgis-min/ggr/Skyline.svg +++ b/resources/cpt-city-qgis-min/ggr/Skyline.svg @@ -1,61 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ggr/Sunrise.svg b/resources/cpt-city-qgis-min/ggr/Sunrise.svg index 8275f278d3e9..5350f084cf62 100644 --- a/resources/cpt-city-qgis-min/ggr/Sunrise.svg +++ b/resources/cpt-city-qgis-min/ggr/Sunrise.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gist/earth.svg b/resources/cpt-city-qgis-min/gist/earth.svg index 7a958df83bd6..33fab3ff544e 100644 --- a/resources/cpt-city-qgis-min/gist/earth.svg +++ b/resources/cpt-city-qgis-min/gist/earth.svg @@ -1,254 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gist/heat.svg b/resources/cpt-city-qgis-min/gist/heat.svg index f81f5cc21547..810df083c9fd 100644 --- a/resources/cpt-city-qgis-min/gist/heat.svg +++ b/resources/cpt-city-qgis-min/gist/heat.svg @@ -1,254 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_drywet.svg b/resources/cpt-city-qgis-min/gmt/GMT_drywet.svg index 9ad6595ac839..d80adb8897ec 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_drywet.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_drywet.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_gebco.svg b/resources/cpt-city-qgis-min/gmt/GMT_gebco.svg index 27e73c5292af..3ed17a16bc4d 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_gebco.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_gebco.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_globe.svg b/resources/cpt-city-qgis-min/gmt/GMT_globe.svg index 4db853a1355c..1e3c9453a050 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_globe.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_globe.svg @@ -1,77 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_haxby.svg b/resources/cpt-city-qgis-min/gmt/GMT_haxby.svg index 041a21706d3d..7e45bb1c758d 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_haxby.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_haxby.svg @@ -1,78 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_hot.svg b/resources/cpt-city-qgis-min/gmt/GMT_hot.svg index 92874409e2e0..4b7b145269b2 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_hot.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_hot.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_ocean.svg b/resources/cpt-city-qgis-min/gmt/GMT_ocean.svg index 36285a64182f..dac8f5f43a8d 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_ocean.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_ocean.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_panoply.svg b/resources/cpt-city-qgis-min/gmt/GMT_panoply.svg index 255c1d4edfbf..0d7fafd19146 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_panoply.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_panoply.svg @@ -1,46 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_polar.svg b/resources/cpt-city-qgis-min/gmt/GMT_polar.svg index 331ce114433b..14f88764b50d 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_polar.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_polar.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_relief.svg b/resources/cpt-city-qgis-min/gmt/GMT_relief.svg index 510caead8720..9a15fdc742f5 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_relief.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_relief.svg @@ -1,33 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gmt/GMT_wysiwyg.svg b/resources/cpt-city-qgis-min/gmt/GMT_wysiwyg.svg index 50fdbbd5a60b..fff687b7644f 100644 --- a/resources/cpt-city-qgis-min/gmt/GMT_wysiwyg.svg +++ b/resources/cpt-city-qgis-min/gmt/GMT_wysiwyg.svg @@ -1,54 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/go2/webtwo/green-g1-2.svg b/resources/cpt-city-qgis-min/go2/webtwo/green-g1-2.svg index 2652f0d0ed01..65218f3171a1 100644 --- a/resources/cpt-city-qgis-min/go2/webtwo/green-g1-2.svg +++ b/resources/cpt-city-qgis-min/go2/webtwo/green-g1-2.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/go2/webtwo/grey-g2-3.svg b/resources/cpt-city-qgis-min/go2/webtwo/grey-g2-3.svg index 05cd34d1b069..c166cd045028 100644 --- a/resources/cpt-city-qgis-min/go2/webtwo/grey-g2-3.svg +++ b/resources/cpt-city-qgis-min/go2/webtwo/grey-g2-3.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Eye-Blue.svg b/resources/cpt-city-qgis-min/gps/GPS-Eye-Blue.svg index d59bab92c3cf..3be51c87f921 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Eye-Blue.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Eye-Blue.svg @@ -1,68 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-FG-Glare.svg b/resources/cpt-city-qgis-min/gps/GPS-FG-Glare.svg index 15f70bf75ae3..5c002a4fb378 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-FG-Glare.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-FG-Glare.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Fire-Blueish.svg b/resources/cpt-city-qgis-min/gps/GPS-Fire-Blueish.svg index e47b1ec9486e..e7dac13c1ae6 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Fire-Blueish.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Fire-Blueish.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Fire-Burning-Cloud.svg b/resources/cpt-city-qgis-min/gps/GPS-Fire-Burning-Cloud.svg index 7be1620f649c..e69acd2767e1 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Fire-Burning-Cloud.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Fire-Burning-Cloud.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust-Blended.svg b/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust-Blended.svg index 8348ff9fb406..97bb3553bb02 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust-Blended.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust-Blended.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust.svg b/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust.svg index d948d73ea6ca..cc19d7d4d69c 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Fire-Dust.svg @@ -1,67 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Fire-Incandescent.svg b/resources/cpt-city-qgis-min/gps/GPS-Fire-Incandescent.svg index 64514455c35d..27b512941d81 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Fire-Incandescent.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Fire-Incandescent.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Fire-Life-Span.svg b/resources/cpt-city-qgis-min/gps/GPS-Fire-Life-Span.svg index 1b64213b16fa..8c88ca3e3cf0 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Fire-Life-Span.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Fire-Life-Span.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Haze-and-Atmosphere.svg b/resources/cpt-city-qgis-min/gps/GPS-Haze-and-Atmosphere.svg index d2a4e23a987e..2716134b8789 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Haze-and-Atmosphere.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Haze-and-Atmosphere.svg @@ -1,116 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Light-Saber.svg b/resources/cpt-city-qgis-min/gps/GPS-Light-Saber.svg index 80150cbb83b7..093527672aef 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Light-Saber.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Light-Saber.svg @@ -1,109 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Nature-Browns.svg b/resources/cpt-city-qgis-min/gps/GPS-Nature-Browns.svg index f6f060e27338..f60760e55d15 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Nature-Browns.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Nature-Browns.svg @@ -1,51 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Nature-Grass.svg b/resources/cpt-city-qgis-min/gps/GPS-Nature-Grass.svg index e1a54b654d25..631231ed8ba2 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Nature-Grass.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Nature-Grass.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Nature-Pure-Greens.svg b/resources/cpt-city-qgis-min/gps/GPS-Nature-Pure-Greens.svg index 445def46dfff..9a7bcf25f4c0 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Nature-Pure-Greens.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Nature-Pure-Greens.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Nature-Random-Greens.svg b/resources/cpt-city-qgis-min/gps/GPS-Nature-Random-Greens.svg index d57d7977a340..91bb89bf2e35 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Nature-Random-Greens.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Nature-Random-Greens.svg @@ -1,43 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Simple-Smoke.svg b/resources/cpt-city-qgis-min/gps/GPS-Simple-Smoke.svg index eaa07f19d890..6227076c6c1a 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Simple-Smoke.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Simple-Smoke.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/gps/GPS-Steel-Bars.svg b/resources/cpt-city-qgis-min/gps/GPS-Steel-Bars.svg index 47331dd90420..625e182319c3 100644 --- a/resources/cpt-city-qgis-min/gps/GPS-Steel-Bars.svg +++ b/resources/cpt-city-qgis-min/gps/GPS-Steel-Bars.svg @@ -1,112 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/aspect.svg b/resources/cpt-city-qgis-min/grass/aspect.svg index b8b57d4b73bf..0de7df7470cf 100644 --- a/resources/cpt-city-qgis-min/grass/aspect.svg +++ b/resources/cpt-city-qgis-min/grass/aspect.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/aspectcolr.svg b/resources/cpt-city-qgis-min/grass/aspectcolr.svg index 25d09dcf2dd4..8852ac23ba7b 100644 --- a/resources/cpt-city-qgis-min/grass/aspectcolr.svg +++ b/resources/cpt-city-qgis-min/grass/aspectcolr.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/bcyr.svg b/resources/cpt-city-qgis-min/grass/bcyr.svg index 604b6b8d02eb..cbac58d41f29 100644 --- a/resources/cpt-city-qgis-min/grass/bcyr.svg +++ b/resources/cpt-city-qgis-min/grass/bcyr.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/bgyr.svg b/resources/cpt-city-qgis-min/grass/bgyr.svg index fc2d299534db..f1b31ad6c96c 100644 --- a/resources/cpt-city-qgis-min/grass/bgyr.svg +++ b/resources/cpt-city-qgis-min/grass/bgyr.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/byg.svg b/resources/cpt-city-qgis-min/grass/byg.svg index 216379a08dca..05eb513afcbf 100644 --- a/resources/cpt-city-qgis-min/grass/byg.svg +++ b/resources/cpt-city-qgis-min/grass/byg.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/byr.svg b/resources/cpt-city-qgis-min/grass/byr.svg index c0bd1a0c94bb..2b77e48371f5 100644 --- a/resources/cpt-city-qgis-min/grass/byr.svg +++ b/resources/cpt-city-qgis-min/grass/byr.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/celsius.svg b/resources/cpt-city-qgis-min/grass/celsius.svg index df7081bf3c59..2d5dd5844c97 100644 --- a/resources/cpt-city-qgis-min/grass/celsius.svg +++ b/resources/cpt-city-qgis-min/grass/celsius.svg @@ -1,230 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/corine.svg b/resources/cpt-city-qgis-min/grass/corine.svg index 43f773779caa..e6893b8970bf 100644 --- a/resources/cpt-city-qgis-min/grass/corine.svg +++ b/resources/cpt-city-qgis-min/grass/corine.svg @@ -1,59 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/curvature.svg b/resources/cpt-city-qgis-min/grass/curvature.svg index 377bc958946c..c8c8fc4242a5 100644 --- a/resources/cpt-city-qgis-min/grass/curvature.svg +++ b/resources/cpt-city-qgis-min/grass/curvature.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/differences.svg b/resources/cpt-city-qgis-min/grass/differences.svg index 288ee56a2a0b..14f88764b50d 100644 --- a/resources/cpt-city-qgis-min/grass/differences.svg +++ b/resources/cpt-city-qgis-min/grass/differences.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/elevation.svg b/resources/cpt-city-qgis-min/grass/elevation.svg index 31deea45c670..3b3d4abe5bbc 100644 --- a/resources/cpt-city-qgis-min/grass/elevation.svg +++ b/resources/cpt-city-qgis-min/grass/elevation.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/etopo2.svg b/resources/cpt-city-qgis-min/grass/etopo2.svg index 364830dd0114..86f6e90e32d3 100644 --- a/resources/cpt-city-qgis-min/grass/etopo2.svg +++ b/resources/cpt-city-qgis-min/grass/etopo2.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/evi.svg b/resources/cpt-city-qgis-min/grass/evi.svg index 69346e1ba27c..1e89126c1459 100644 --- a/resources/cpt-city-qgis-min/grass/evi.svg +++ b/resources/cpt-city-qgis-min/grass/evi.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/gdd.svg b/resources/cpt-city-qgis-min/grass/gdd.svg index e8a9452526b6..eff864bb9e27 100644 --- a/resources/cpt-city-qgis-min/grass/gdd.svg +++ b/resources/cpt-city-qgis-min/grass/gdd.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/grey.svg b/resources/cpt-city-qgis-min/grass/grey.svg index bfafc344fb88..7f338c963c31 100644 --- a/resources/cpt-city-qgis-min/grass/grey.svg +++ b/resources/cpt-city-qgis-min/grass/grey.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/grey1.0.svg b/resources/cpt-city-qgis-min/grass/grey1.0.svg index 78b0cbd6265b..7f338c963c31 100644 --- a/resources/cpt-city-qgis-min/grass/grey1.0.svg +++ b/resources/cpt-city-qgis-min/grass/grey1.0.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/grey255.svg b/resources/cpt-city-qgis-min/grass/grey255.svg index ed80011434d9..7f338c963c31 100644 --- a/resources/cpt-city-qgis-min/grass/grey255.svg +++ b/resources/cpt-city-qgis-min/grass/grey255.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/gyr.svg b/resources/cpt-city-qgis-min/grass/gyr.svg index d1e503b71415..c35b75bdf6ca 100644 --- a/resources/cpt-city-qgis-min/grass/gyr.svg +++ b/resources/cpt-city-qgis-min/grass/gyr.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/haxby.svg b/resources/cpt-city-qgis-min/grass/haxby.svg index 7fde644f16ea..9bbef6bed9a6 100644 --- a/resources/cpt-city-qgis-min/grass/haxby.svg +++ b/resources/cpt-city-qgis-min/grass/haxby.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/ndvi.svg b/resources/cpt-city-qgis-min/grass/ndvi.svg index 5b08ad7df2f1..9fde0d4b4251 100644 --- a/resources/cpt-city-qgis-min/grass/ndvi.svg +++ b/resources/cpt-city-qgis-min/grass/ndvi.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/population.svg b/resources/cpt-city-qgis-min/grass/population.svg index 4a7b7b771e15..f12febcbf8f0 100644 --- a/resources/cpt-city-qgis-min/grass/population.svg +++ b/resources/cpt-city-qgis-min/grass/population.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/precipitation.svg b/resources/cpt-city-qgis-min/grass/precipitation.svg index 4ce3e3803783..744db668c6f3 100644 --- a/resources/cpt-city-qgis-min/grass/precipitation.svg +++ b/resources/cpt-city-qgis-min/grass/precipitation.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/precipitation_monthly.svg b/resources/cpt-city-qgis-min/grass/precipitation_monthly.svg index 481596400081..5752ce66fcd4 100644 --- a/resources/cpt-city-qgis-min/grass/precipitation_monthly.svg +++ b/resources/cpt-city-qgis-min/grass/precipitation_monthly.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/rainbow.svg b/resources/cpt-city-qgis-min/grass/rainbow.svg index 755a581f751c..51ca788dd33c 100644 --- a/resources/cpt-city-qgis-min/grass/rainbow.svg +++ b/resources/cpt-city-qgis-min/grass/rainbow.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/ramp.svg b/resources/cpt-city-qgis-min/grass/ramp.svg index 04c9c5e87749..30ea0ab44496 100644 --- a/resources/cpt-city-qgis-min/grass/ramp.svg +++ b/resources/cpt-city-qgis-min/grass/ramp.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/rstcurv.svg b/resources/cpt-city-qgis-min/grass/rstcurv.svg index 1b085c2dd178..9b5e60278d9e 100644 --- a/resources/cpt-city-qgis-min/grass/rstcurv.svg +++ b/resources/cpt-city-qgis-min/grass/rstcurv.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/ryb.svg b/resources/cpt-city-qgis-min/grass/ryb.svg index 55788b4aa45c..7287819f1c4a 100644 --- a/resources/cpt-city-qgis-min/grass/ryb.svg +++ b/resources/cpt-city-qgis-min/grass/ryb.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/ryg.svg b/resources/cpt-city-qgis-min/grass/ryg.svg index e54f4f076c07..164e9847c975 100644 --- a/resources/cpt-city-qgis-min/grass/ryg.svg +++ b/resources/cpt-city-qgis-min/grass/ryg.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/sepia.svg b/resources/cpt-city-qgis-min/grass/sepia.svg index 212036d6e2eb..32b2e4693150 100644 --- a/resources/cpt-city-qgis-min/grass/sepia.svg +++ b/resources/cpt-city-qgis-min/grass/sepia.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/slope.svg b/resources/cpt-city-qgis-min/grass/slope.svg index c0a62439c6ad..ebd9f98f2592 100644 --- a/resources/cpt-city-qgis-min/grass/slope.svg +++ b/resources/cpt-city-qgis-min/grass/slope.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/srtm.svg b/resources/cpt-city-qgis-min/grass/srtm.svg index adc2a4477132..b5ca58894efb 100644 --- a/resources/cpt-city-qgis-min/grass/srtm.svg +++ b/resources/cpt-city-qgis-min/grass/srtm.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/terrain.svg b/resources/cpt-city-qgis-min/grass/terrain.svg index 2778ff509b0a..d9abf56fc182 100644 --- a/resources/cpt-city-qgis-min/grass/terrain.svg +++ b/resources/cpt-city-qgis-min/grass/terrain.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/grass/wave.svg b/resources/cpt-city-qgis-min/grass/wave.svg index 1b8a5e71b092..100729499ff0 100644 --- a/resources/cpt-city-qgis-min/grass/wave.svg +++ b/resources/cpt-city-qgis-min/grass/wave.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/h5/dkbluered.svg b/resources/cpt-city-qgis-min/h5/dkbluered.svg index 7a4907970778..ce7dcef36ed7 100644 --- a/resources/cpt-city-qgis-min/h5/dkbluered.svg +++ b/resources/cpt-city-qgis-min/h5/dkbluered.svg @@ -1,45 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/h5/summer.svg b/resources/cpt-city-qgis-min/h5/summer.svg index b66ec228f088..287ec4122399 100644 --- a/resources/cpt-city-qgis-min/h5/summer.svg +++ b/resources/cpt-city-qgis-min/h5/summer.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG03.svg index 0a34ddd8b4a3..982a059245d4 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG04.svg index 7b9c7affe06f..063b7bdf1693 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG05.svg index 6a14d780722c..6a7dda961ad7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG06.svg index 66a3ee652858..c2750a682bb7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG07.svg index 5e1335225d05..38673be914d7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG08.svg index 61bee2cd389c..8b03a55b3ae2 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG09.svg index a3922f8cf311..f4c55b05b257 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG10.svg index 6bc734e76a28..9a321b3be934 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG11.svg index f51a87c6d882..e3faa956eaa4 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacBrBG11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn03.svg index eb11a9be8122..cea7db63ada9 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn04.svg index e0b0a6fe4282..1ed5a245a9bc 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn05.svg index f9c2838ca56e..ce3999d024c4 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn06.svg index 00756a160a2d..75f1599aafcb 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn07.svg index 0010409aab3c..ac3661f6268a 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn08.svg index 9a90f0d15671..f93d3dbf35a2 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn09.svg index ce0b91c7615a..e04aa8c89ef3 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn10.svg index 3ac8e5685dd9..67a3b9989794 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn11.svg index 9230f6fbad67..4cb404f1ff2c 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPRGn11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG03.svg index 1ad355fe8c89..2b5b42efe3a3 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG04.svg index 073cbefd4d41..7827ef49f0bc 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG05.svg index 4f4495f2652b..c511b95eca98 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG06.svg index ee6824658b07..64a2dce929e5 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG07.svg index ba81a88684cf..cab116168139 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG08.svg index 6fc81e89a239..307f55864cd7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG09.svg index 34059be3bc0f..0ca4449c2930 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG10.svg index b53084a3595f..378e291eca26 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG11.svg index 301365c3afd9..85d1b6f99d9b 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPiYG11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr03.svg index 33b38086973d..ce1f9f56d1de 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr04.svg index 6c037598d44a..ef1d4c9e28a3 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr05.svg index ea4cba860a92..3db717fe2ba2 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr06.svg index c48f870819a2..05eeb26c486d 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr07.svg index 291f8ea300ba..c13544f4f3de 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr08.svg index 870f14998af6..006db4e29a69 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr09.svg index 312481a4cc36..71080dd95e9d 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr10.svg index 8eafa67ad824..b7b4765d6ed5 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr11.svg index 030d0f8ed4f0..328ca512c12e 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacPuOr11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu03.svg index ed2ab292204f..58f5df7c3e61 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu04.svg index fe82789e3c66..f6048ef108da 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu05.svg index c256f9fb8d4e..59bbdb74f44c 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu06.svg index 29329b203a74..10f84362deea 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu07.svg index 9950d895af9d..48cda7024345 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu08.svg index 27e5a26cdc39..ea45e3d96485 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu09.svg index 6dac48849a8d..d66711c20554 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu10.svg index 079e4b6444aa..c2f0018e2989 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu11.svg index a0aece765231..80b98752acc6 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdBu11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy03.svg index 341fb1d595c0..1bcc5700df63 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy04.svg index 806bbfe0f923..e6f4a4826cb0 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy05.svg index 9e97f4fe85bf..78b6b55b465a 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy06.svg index c3f8e1904814..ccc5b7edf891 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy07.svg index a83bac6afc0f..bc06c5a078a1 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy08.svg index 69e7ef6aed25..d3c77cd01f2e 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy09.svg index c1074daebd7c..ed21ba1429af 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy10.svg index 6957536c5e8e..027969bfcd47 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy11.svg index 33dedc4a9239..ffd6c34083d7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdGy11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu03.svg index 1065b836b8ec..47a235d5ac57 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu04.svg index cfd24a51feea..ce19fd4c8be5 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu05.svg index 256bb20d3934..ea710df6cc8d 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu06.svg index 7daecbea15c3..b2b7da0693c9 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu07.svg index b4c33bbc139e..a0b1f134ee96 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu08.svg index 0f410831a693..4461f941c266 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu09.svg index 82fb71cd92b5..da7d468aeaa6 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu10.svg index 7cb7c0e0897c..40b0e56e3d77 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu11.svg index 424ee836f930..940a86bbe2ee 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlBu11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn03.svg index 24311738d0d3..531fa02d2aad 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn04.svg index 6bbfbfdad14e..e0997984d235 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn05.svg index a97facf651ac..646d7a8dfb58 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn06.svg index 6850fb68579a..9297e5ee0943 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn07.svg index e217e72217ca..71e09a2a85e9 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn08.svg index 1652ad646e5c..72c800799acd 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn09.svg index c5994ea266c4..44c795fa890e 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn10.svg index 91cb9cc5a96d..e5ccec6ce982 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn11.svg index 6e1ac320930e..b0ffe6e46c47 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacRdYlGn11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral03.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral03.svg index a1d971234757..3ed6a01d069b 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral03.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral03.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral04.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral04.svg index 39a3ef41f401..15ea0fa1cfca 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral04.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral04.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral05.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral05.svg index fdb98f72916e..48c2ac1953e7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral05.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral05.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral06.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral06.svg index 5e78ccc65b96..94a957f7758c 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral06.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral06.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral07.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral07.svg index 30b10f228403..6a63b118e46a 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral07.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral07.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral08.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral08.svg index 1f1948346a9e..d284da6441a3 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral08.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral08.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral09.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral09.svg index 7bfa7753952a..495e32e72da7 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral09.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral09.svg @@ -1,41 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral10.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral10.svg index 569ac6b2f5a8..52140a21851a 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral10.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral10.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral11.svg b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral11.svg index f7794297fe12..1e5989c92e28 100644 --- a/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral11.svg +++ b/resources/cpt-city-qgis-min/jjg/cbac/div/cbacSpectral11.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcBrBG.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcBrBG.svg index 9b3c88c95b47..61692fc2da39 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcBrBG.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcBrBG.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPRGn.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPRGn.svg index c197d3ffcea7..611225ad5cf5 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPRGn.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPRGn.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPiYG.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPiYG.svg index 12008fb53d1f..2d045bff6fbb 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPiYG.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPiYG.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPuOr.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPuOr.svg index dce2ce35af5a..16956781d7c0 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPuOr.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcPuOr.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdBu.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdBu.svg index 9b1a0c06ceda..b29757d8dfee 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdBu.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdBu.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdGy.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdGy.svg index 52672ab63857..f5fb0a22d15e 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdGy.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdGy.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlBu.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlBu.svg index 2bd9b3dad5c4..b7027d6ba9be 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlBu.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlBu.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlGn.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlGn.svg index ec4a67446a8d..9411cc331e21 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlGn.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcRdYlGn.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcSpectral.svg b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcSpectral.svg index 5a17080c28f5..d653baef74de 100644 --- a/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcSpectral.svg +++ b/resources/cpt-city-qgis-min/jjg/cbcont/div/cbcSpectral.svg @@ -1,37 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/dem/c3t1.svg b/resources/cpt-city-qgis-min/jjg/dem/c3t1.svg index 1433ccda3952..3cbdbca93fbc 100644 --- a/resources/cpt-city-qgis-min/jjg/dem/c3t1.svg +++ b/resources/cpt-city-qgis-min/jjg/dem/c3t1.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/dem/c3t3.svg b/resources/cpt-city-qgis-min/jjg/dem/c3t3.svg index 7477ac1fd2f9..55cb11d2ad38 100644 --- a/resources/cpt-city-qgis-min/jjg/dem/c3t3.svg +++ b/resources/cpt-city-qgis-min/jjg/dem/c3t3.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/dem/garish14.svg b/resources/cpt-city-qgis-min/jjg/dem/garish14.svg index 14d733d8cf6e..be89e84d5677 100644 --- a/resources/cpt-city-qgis-min/jjg/dem/garish14.svg +++ b/resources/cpt-city-qgis-min/jjg/dem/garish14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/dem/gebco-shelf.svg b/resources/cpt-city-qgis-min/jjg/dem/gebco-shelf.svg index 1e1c47976b35..3ed17a16bc4d 100644 --- a/resources/cpt-city-qgis-min/jjg/dem/gebco-shelf.svg +++ b/resources/cpt-city-qgis-min/jjg/dem/gebco-shelf.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/misc/rainfall.svg b/resources/cpt-city-qgis-min/jjg/misc/rainfall.svg index 9af3b572aa17..1f8a539647b2 100644 --- a/resources/cpt-city-qgis-min/jjg/misc/rainfall.svg +++ b/resources/cpt-city-qgis-min/jjg/misc/rainfall.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/misc/temperature.svg b/resources/cpt-city-qgis-min/jjg/misc/temperature.svg index e2e26e0b2283..823144c2759b 100644 --- a/resources/cpt-city-qgis-min/jjg/misc/temperature.svg +++ b/resources/cpt-city-qgis-min/jjg/misc/temperature.svg @@ -1,60 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/misc/voxpop.svg b/resources/cpt-city-qgis-min/jjg/misc/voxpop.svg index 0cfb568aed91..d1a7d605d513 100644 --- a/resources/cpt-city-qgis-min/jjg/misc/voxpop.svg +++ b/resources/cpt-city-qgis-min/jjg/misc/voxpop.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/physics/visspec.svg b/resources/cpt-city-qgis-min/jjg/physics/visspec.svg index d960e7ba7d05..530d99f286e3 100644 --- a/resources/cpt-city-qgis-min/jjg/physics/visspec.svg +++ b/resources/cpt-city-qgis-min/jjg/physics/visspec.svg @@ -1,414 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/BrBG.svg b/resources/cpt-city-qgis-min/jjg/polarity/BrBG.svg index 5a0ef1f2a8e1..80a1d3f5be1a 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/BrBG.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/BrBG.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/PRGn.svg b/resources/cpt-city-qgis-min/jjg/polarity/PRGn.svg index b0ac73e16812..28985db4bb2f 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/PRGn.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/PRGn.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/PiYG.svg b/resources/cpt-city-qgis-min/jjg/polarity/PiYG.svg index 59961f600d6a..78bbf59c09fd 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/PiYG.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/PiYG.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/PuOr.svg b/resources/cpt-city-qgis-min/jjg/polarity/PuOr.svg index 4e4c153c5d68..928b26d25f11 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/PuOr.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/PuOr.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/RdBu.svg b/resources/cpt-city-qgis-min/jjg/polarity/RdBu.svg index 2c4dfae336da..b2d514462195 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/RdBu.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/RdBu.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/RdGy.svg b/resources/cpt-city-qgis-min/jjg/polarity/RdGy.svg index 5b74544abcaf..b3ecec522987 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/RdGy.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/RdGy.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/RdYlBu.svg b/resources/cpt-city-qgis-min/jjg/polarity/RdYlBu.svg index ef57db6a8e9a..d43a03d03a17 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/RdYlBu.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/RdYlBu.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/RdYlGn.svg b/resources/cpt-city-qgis-min/jjg/polarity/RdYlGn.svg index ed770362dbc1..f4db38d16fac 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/RdYlGn.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/RdYlGn.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jjg/polarity/Spectral.svg b/resources/cpt-city-qgis-min/jjg/polarity/Spectral.svg index 5358e91367e7..68f45d8b91fb 100644 --- a/resources/cpt-city-qgis-min/jjg/polarity/Spectral.svg +++ b/resources/cpt-city-qgis-min/jjg/polarity/Spectral.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/ad/ad-a.svg b/resources/cpt-city-qgis-min/jm/ad/ad-a.svg index 8b18066da822..4a84edbe73bb 100644 --- a/resources/cpt-city-qgis-min/jm/ad/ad-a.svg +++ b/resources/cpt-city-qgis-min/jm/ad/ad-a.svg @@ -1,132 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/ao/ao-a.svg b/resources/cpt-city-qgis-min/jm/ao/ao-a.svg index a901d6215fdb..78276c755ced 100644 --- a/resources/cpt-city-qgis-min/jm/ao/ao-a.svg +++ b/resources/cpt-city-qgis-min/jm/ao/ao-a.svg @@ -1,86 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/cd/cd-a.svg b/resources/cpt-city-qgis-min/jm/cd/cd-a.svg index 0ff8774a4c1e..6ebfdc71c99a 100644 --- a/resources/cpt-city-qgis-min/jm/cd/cd-a.svg +++ b/resources/cpt-city-qgis-min/jm/cd/cd-a.svg @@ -1,110 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/db/db-a.svg b/resources/cpt-city-qgis-min/jm/db/db-a.svg index fec9bb492614..a345795fb4d6 100644 --- a/resources/cpt-city-qgis-min/jm/db/db-a.svg +++ b/resources/cpt-city-qgis-min/jm/db/db-a.svg @@ -1,108 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/o2/o2-a.svg b/resources/cpt-city-qgis-min/jm/o2/o2-a.svg index 03a7a3104522..8c20809dc6e1 100644 --- a/resources/cpt-city-qgis-min/jm/o2/o2-a.svg +++ b/resources/cpt-city-qgis-min/jm/o2/o2-a.svg @@ -1,153 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/sd/sd-a.svg b/resources/cpt-city-qgis-min/jm/sd/sd-a.svg index 4b6eaf211ad9..fb6c32f7e937 100644 --- a/resources/cpt-city-qgis-min/jm/sd/sd-a.svg +++ b/resources/cpt-city-qgis-min/jm/sd/sd-a.svg @@ -1,108 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/tv/tv-a.svg b/resources/cpt-city-qgis-min/jm/tv/tv-a.svg index 86ff60bceeeb..7dcf48ce3a1f 100644 --- a/resources/cpt-city-qgis-min/jm/tv/tv-a.svg +++ b/resources/cpt-city-qgis-min/jm/tv/tv-a.svg @@ -1,106 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/ws/ws-a.svg b/resources/cpt-city-qgis-min/jm/ws/ws-a.svg index ddfda1ac1f21..93b23ef27ac5 100644 --- a/resources/cpt-city-qgis-min/jm/ws/ws-a.svg +++ b/resources/cpt-city-qgis-min/jm/ws/ws-a.svg @@ -1,104 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/jm/wt/wt-a.svg b/resources/cpt-city-qgis-min/jm/wt/wt-a.svg index ebeddd3cfad2..03b0404777e2 100644 --- a/resources/cpt-city-qgis-min/jm/wt/wt-a.svg +++ b/resources/cpt-city-qgis-min/jm/wt/wt-a.svg @@ -1,96 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d05.svg b/resources/cpt-city-qgis-min/km/blue-tan-d05.svg index 18f316b85664..59a4ac63977c 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d05.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d06.svg b/resources/cpt-city-qgis-min/km/blue-tan-d06.svg index 0bf1b7ac9147..8671cea57450 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d06.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d07.svg b/resources/cpt-city-qgis-min/km/blue-tan-d07.svg index 51b059738576..ab2bdf7ac0ae 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d07.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d08.svg b/resources/cpt-city-qgis-min/km/blue-tan-d08.svg index 0405093d10af..9700507b585c 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d08.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d09.svg b/resources/cpt-city-qgis-min/km/blue-tan-d09.svg index 20c65dd65b4a..2fa5edc89d51 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d09.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d10.svg b/resources/cpt-city-qgis-min/km/blue-tan-d10.svg index b1b94249b200..540c804284b2 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d10.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d11.svg b/resources/cpt-city-qgis-min/km/blue-tan-d11.svg index 26c095a16f88..0cf69f5dc542 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d11.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d12.svg b/resources/cpt-city-qgis-min/km/blue-tan-d12.svg index df17cad05c31..e4f8db5b540c 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d12.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d13.svg b/resources/cpt-city-qgis-min/km/blue-tan-d13.svg index 63a0b073e971..121dbf87e5e2 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d13.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d14.svg b/resources/cpt-city-qgis-min/km/blue-tan-d14.svg index 41d3b7a16af4..5f504417772f 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d14.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan-d15.svg b/resources/cpt-city-qgis-min/km/blue-tan-d15.svg index 9a4159cacf5b..e9a4a8260e9c 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan-d15.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-tan.svg b/resources/cpt-city-qgis-min/km/blue-tan.svg index 678e50da440f..544073049c33 100644 --- a/resources/cpt-city-qgis-min/km/blue-tan.svg +++ b/resources/cpt-city-qgis-min/km/blue-tan.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d05.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d05.svg index ef19dc3b2191..6f2dd1d5c03d 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d05.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d06.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d06.svg index 32d1396f871a..04c017f61aa5 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d06.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d07.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d07.svg index f70960480745..1396226869b3 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d07.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d08.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d08.svg index 9af3143bd155..4cca2eb016ae 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d08.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d09.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d09.svg index 837bc6e78099..c19d16b50b3c 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d09.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d10.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d10.svg index d9e9eb7303b8..8183e095dd75 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d10.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d11.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d11.svg index 3f81204f9371..19ea90895144 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d11.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d12.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d12.svg index de116a07dc68..0fab94bb4464 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d12.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d13.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d13.svg index 0d31f7354b09..f7896e21b90c 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d13.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d14.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d14.svg index 4258dd375973..c7bd9cf532e3 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d14.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow-d15.svg b/resources/cpt-city-qgis-min/km/blue-yellow-d15.svg index e988e70855ce..c38d9d62ca45 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow-d15.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/blue-yellow.svg b/resources/cpt-city-qgis-min/km/blue-yellow.svg index 88be5791f9e3..6fd3e403e5bb 100644 --- a/resources/cpt-city-qgis-min/km/blue-yellow.svg +++ b/resources/cpt-city-qgis-min/km/blue-yellow.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d05.svg b/resources/cpt-city-qgis-min/km/cool-warm-d05.svg index 7150a01ee6fa..3d8aaf1a201a 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d05.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d06.svg b/resources/cpt-city-qgis-min/km/cool-warm-d06.svg index 49b639cfda91..75c169d1dfa7 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d06.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d07.svg b/resources/cpt-city-qgis-min/km/cool-warm-d07.svg index 162228bf0e79..fbed91d64601 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d07.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d08.svg b/resources/cpt-city-qgis-min/km/cool-warm-d08.svg index 3768ffb2a9c9..4030a425a492 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d08.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d09.svg b/resources/cpt-city-qgis-min/km/cool-warm-d09.svg index cd7f130bbe59..58f09de58143 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d09.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d10.svg b/resources/cpt-city-qgis-min/km/cool-warm-d10.svg index b855db1cc50e..acda9b15add4 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d10.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d11.svg b/resources/cpt-city-qgis-min/km/cool-warm-d11.svg index 8ca9e4559954..3b1e8ecc12e3 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d11.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d12.svg b/resources/cpt-city-qgis-min/km/cool-warm-d12.svg index 2bba07dda620..acd73b0dd2f0 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d12.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d13.svg b/resources/cpt-city-qgis-min/km/cool-warm-d13.svg index 44d4b5819570..bf1394855b16 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d13.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d14.svg b/resources/cpt-city-qgis-min/km/cool-warm-d14.svg index 6e38ea36a782..d04998b956c5 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d14.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm-d15.svg b/resources/cpt-city-qgis-min/km/cool-warm-d15.svg index 6554d6fb1151..8e1b5121a3cd 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm-d15.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cool-warm.svg b/resources/cpt-city-qgis-min/km/cool-warm.svg index 4927005d1ed3..4a42fa8750ad 100644 --- a/resources/cpt-city-qgis-min/km/cool-warm.svg +++ b/resources/cpt-city-qgis-min/km/cool-warm.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d05.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d05.svg index 6a2bd949f510..b1f91c3f4d4a 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d05.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d06.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d06.svg index d25f6e1472c4..3764f6c7a859 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d06.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d07.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d07.svg index bf938dcc0637..46a1606bfd29 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d07.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d08.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d08.svg index fe90c83a1616..ec4922c5c7ff 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d08.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d09.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d09.svg index 94e473c64df5..79fedb64b249 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d09.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d10.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d10.svg index 37f3a158aa2c..dd906613be04 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d10.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d11.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d11.svg index 64f522a8d115..341b594e4d7e 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d11.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d12.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d12.svg index 9a3aece29e13..d3e95c69e0d8 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d12.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d13.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d13.svg index 992840882657..6cc6aac1cfbb 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d13.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d14.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d14.svg index 1679c6c93ee5..914a60220b31 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d14.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve-d15.svg b/resources/cpt-city-qgis-min/km/cyan-mauve-d15.svg index 0584fbab52bd..16f4d6687b02 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve-d15.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/cyan-mauve.svg b/resources/cpt-city-qgis-min/km/cyan-mauve.svg index 3771d7048908..65f68642b831 100644 --- a/resources/cpt-city-qgis-min/km/cyan-mauve.svg +++ b/resources/cpt-city-qgis-min/km/cyan-mauve.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d05.svg b/resources/cpt-city-qgis-min/km/green-purple-d05.svg index 1b8afaff75f8..a32de1c66b82 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d05.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d06.svg b/resources/cpt-city-qgis-min/km/green-purple-d06.svg index b325222125fa..75b7ce172d50 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d06.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d07.svg b/resources/cpt-city-qgis-min/km/green-purple-d07.svg index 47c5a4c40ef2..a011923b7825 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d07.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d08.svg b/resources/cpt-city-qgis-min/km/green-purple-d08.svg index 970fa5288f86..698477b53d13 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d08.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d09.svg b/resources/cpt-city-qgis-min/km/green-purple-d09.svg index e6e4aab90b6d..4aaadeae0930 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d09.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d10.svg b/resources/cpt-city-qgis-min/km/green-purple-d10.svg index 9fdb421c27e1..2fba794e643e 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d10.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d11.svg b/resources/cpt-city-qgis-min/km/green-purple-d11.svg index c240be564f45..9ddd1f609cc0 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d11.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d12.svg b/resources/cpt-city-qgis-min/km/green-purple-d12.svg index 6f15cd2e759d..724e1d067482 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d12.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d13.svg b/resources/cpt-city-qgis-min/km/green-purple-d13.svg index e1324f1188c3..d1aa44194e33 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d13.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d14.svg b/resources/cpt-city-qgis-min/km/green-purple-d14.svg index d600cb09239b..77d697fbbd6a 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d14.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple-d15.svg b/resources/cpt-city-qgis-min/km/green-purple-d15.svg index d49c1a425628..fb4e3085415a 100644 --- a/resources/cpt-city-qgis-min/km/green-purple-d15.svg +++ b/resources/cpt-city-qgis-min/km/green-purple-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-purple.svg b/resources/cpt-city-qgis-min/km/green-purple.svg index 4ce73c8304bd..74c707c4d1af 100644 --- a/resources/cpt-city-qgis-min/km/green-purple.svg +++ b/resources/cpt-city-qgis-min/km/green-purple.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d05.svg b/resources/cpt-city-qgis-min/km/green-red-d05.svg index 671218a42b84..4a68ca20cb3f 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d05.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d06.svg b/resources/cpt-city-qgis-min/km/green-red-d06.svg index f7cd7df2c940..f4ab749b1a6c 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d06.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d07.svg b/resources/cpt-city-qgis-min/km/green-red-d07.svg index a35e5c47c11a..b674aeb0c1af 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d07.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d08.svg b/resources/cpt-city-qgis-min/km/green-red-d08.svg index 5066b16312d2..f6b7d86ecfaf 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d08.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d09.svg b/resources/cpt-city-qgis-min/km/green-red-d09.svg index b77772f99032..b4aa94201eda 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d09.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d10.svg b/resources/cpt-city-qgis-min/km/green-red-d10.svg index 3bba50d75c4b..1a773fb251a2 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d10.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d11.svg b/resources/cpt-city-qgis-min/km/green-red-d11.svg index c1a4a1f54cb3..53de69ca9fc6 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d11.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d12.svg b/resources/cpt-city-qgis-min/km/green-red-d12.svg index 6bda193abc59..177938199d6f 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d12.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d13.svg b/resources/cpt-city-qgis-min/km/green-red-d13.svg index 3a98266c9000..7954924bf7e4 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d13.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d14.svg b/resources/cpt-city-qgis-min/km/green-red-d14.svg index 228d19e29ce5..77b78af36153 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d14.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red-d15.svg b/resources/cpt-city-qgis-min/km/green-red-d15.svg index bf87c703c8c6..5a6b5a889ac2 100644 --- a/resources/cpt-city-qgis-min/km/green-red-d15.svg +++ b/resources/cpt-city-qgis-min/km/green-red-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/green-red.svg b/resources/cpt-city-qgis-min/km/green-red.svg index 6f21d7b98716..0fc26f12f664 100644 --- a/resources/cpt-city-qgis-min/km/green-red.svg +++ b/resources/cpt-city-qgis-min/km/green-red.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d05.svg b/resources/cpt-city-qgis-min/km/purple-orange-d05.svg index 95efe7a6bd72..51ec31083245 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d05.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d05.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d06.svg b/resources/cpt-city-qgis-min/km/purple-orange-d06.svg index de0692fc7422..8ec8673be495 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d06.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d06.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d07.svg b/resources/cpt-city-qgis-min/km/purple-orange-d07.svg index f3af7966fa58..cf4720ca701e 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d07.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d07.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d08.svg b/resources/cpt-city-qgis-min/km/purple-orange-d08.svg index 8d2a7c47ff5e..138753caaa95 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d08.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d08.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d09.svg b/resources/cpt-city-qgis-min/km/purple-orange-d09.svg index 2c1e17276bbd..981e73bb22c5 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d09.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d09.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d10.svg b/resources/cpt-city-qgis-min/km/purple-orange-d10.svg index 769723c1cf3d..dad5f08ea188 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d10.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d10.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d11.svg b/resources/cpt-city-qgis-min/km/purple-orange-d11.svg index 2b8f5484b3c8..13fa9de19148 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d11.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d11.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d12.svg b/resources/cpt-city-qgis-min/km/purple-orange-d12.svg index 70a77d1b7616..5787c332efa1 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d12.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d12.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d13.svg b/resources/cpt-city-qgis-min/km/purple-orange-d13.svg index e38954e2c443..b80564ac3b70 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d13.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d13.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d14.svg b/resources/cpt-city-qgis-min/km/purple-orange-d14.svg index 59b102a2ef94..b0d5759ec9ff 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d14.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d14.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange-d15.svg b/resources/cpt-city-qgis-min/km/purple-orange-d15.svg index 14477ee9c931..95a1d6721ca9 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange-d15.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange-d15.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/km/purple-orange.svg b/resources/cpt-city-qgis-min/km/purple-orange.svg index b2626252aff2..f48190ddb945 100644 --- a/resources/cpt-city-qgis-min/km/purple-orange.svg +++ b/resources/cpt-city-qgis-min/km/purple-orange.svg @@ -1,79 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/mby/mby.svg b/resources/cpt-city-qgis-min/mby/mby.svg index a4d7e9e6b260..424e41bcb40b 100644 --- a/resources/cpt-city-qgis-min/mby/mby.svg +++ b/resources/cpt-city-qgis-min/mby/mby.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/BlWhRe.svg b/resources/cpt-city-qgis-min/ncl/BlWhRe.svg index 7de561e6bfbf..77f3c7725c5e 100644 --- a/resources/cpt-city-qgis-min/ncl/BlWhRe.svg +++ b/resources/cpt-city-qgis-min/ncl/BlWhRe.svg @@ -1,216 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/BlueDarkRed18.svg b/resources/cpt-city-qgis-min/ncl/BlueDarkRed18.svg index c6382c5f7dd1..296ce814289f 100644 --- a/resources/cpt-city-qgis-min/ncl/BlueDarkRed18.svg +++ b/resources/cpt-city-qgis-min/ncl/BlueDarkRed18.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/BlueWhiteOrangeRed.svg b/resources/cpt-city-qgis-min/ncl/BlueWhiteOrangeRed.svg index 84fc6edab2cb..285551b942b0 100644 --- a/resources/cpt-city-qgis-min/ncl/BlueWhiteOrangeRed.svg +++ b/resources/cpt-city-qgis-min/ncl/BlueWhiteOrangeRed.svg @@ -1,499 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/BlueYellowRed.svg b/resources/cpt-city-qgis-min/ncl/BlueYellowRed.svg index 6150e7fd46e7..6207e679003e 100644 --- a/resources/cpt-city-qgis-min/ncl/BlueYellowRed.svg +++ b/resources/cpt-city-qgis-min/ncl/BlueYellowRed.svg @@ -1,522 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/GreenYellow.svg b/resources/cpt-city-qgis-min/ncl/GreenYellow.svg index 59fc0972a4c2..42909d7238be 100644 --- a/resources/cpt-city-qgis-min/ncl/GreenYellow.svg +++ b/resources/cpt-city-qgis-min/ncl/GreenYellow.svg @@ -1,518 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/WhiteGreen.svg b/resources/cpt-city-qgis-min/ncl/WhiteGreen.svg index 41ba8bce2255..798681ce8489 100644 --- a/resources/cpt-city-qgis-min/ncl/WhiteGreen.svg +++ b/resources/cpt-city-qgis-min/ncl/WhiteGreen.svg @@ -1,518 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/precip2_17lev.svg b/resources/cpt-city-qgis-min/ncl/precip2_17lev.svg index 17a9d0463612..096f4b27654c 100644 --- a/resources/cpt-city-qgis-min/ncl/precip2_17lev.svg +++ b/resources/cpt-city-qgis-min/ncl/precip2_17lev.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/precip_11lev.svg b/resources/cpt-city-qgis-min/ncl/precip_11lev.svg index 2b126c56eb03..9c8522826657 100644 --- a/resources/cpt-city-qgis-min/ncl/precip_11lev.svg +++ b/resources/cpt-city-qgis-min/ncl/precip_11lev.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/sunshine_diff_12lev.svg b/resources/cpt-city-qgis-min/ncl/sunshine_diff_12lev.svg index 641032393c7a..e6d40fd790e6 100644 --- a/resources/cpt-city-qgis-min/ncl/sunshine_diff_12lev.svg +++ b/resources/cpt-city-qgis-min/ncl/sunshine_diff_12lev.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/temp_19lev.svg b/resources/cpt-city-qgis-min/ncl/temp_19lev.svg index 29db259bfb16..8b88c103944f 100644 --- a/resources/cpt-city-qgis-min/ncl/temp_19lev.svg +++ b/resources/cpt-city-qgis-min/ncl/temp_19lev.svg @@ -1,54 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ncl/topo_15lev.svg b/resources/cpt-city-qgis-min/ncl/topo_15lev.svg index 7826a347706c..40dda8332d24 100644 --- a/resources/cpt-city-qgis-min/ncl/topo_15lev.svg +++ b/resources/cpt-city-qgis-min/ncl/topo_15lev.svg @@ -1,46 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/nd/atmospheric/GreyOClock.svg b/resources/cpt-city-qgis-min/nd/atmospheric/GreyOClock.svg index 753837d1220e..887c904a9ffc 100644 --- a/resources/cpt-city-qgis-min/nd/atmospheric/GreyOClock.svg +++ b/resources/cpt-city-qgis-min/nd/atmospheric/GreyOClock.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/nd/atmospheric/Sunset_Real.svg b/resources/cpt-city-qgis-min/nd/atmospheric/Sunset_Real.svg index 88608f5ceb96..d701efce9f1d 100644 --- a/resources/cpt-city-qgis-min/nd/atmospheric/Sunset_Real.svg +++ b/resources/cpt-city-qgis-min/nd/atmospheric/Sunset_Real.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ngdc/ETOPO1-Reed.svg b/resources/cpt-city-qgis-min/ngdc/ETOPO1-Reed.svg index d9374f39995e..4ae360757e89 100644 --- a/resources/cpt-city-qgis-min/ngdc/ETOPO1-Reed.svg +++ b/resources/cpt-city-qgis-min/ngdc/ETOPO1-Reed.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ngdc/ETOPO1.svg b/resources/cpt-city-qgis-min/ngdc/ETOPO1.svg index 620cb945b09b..4421df1cc336 100644 --- a/resources/cpt-city-qgis-min/ngdc/ETOPO1.svg +++ b/resources/cpt-city-qgis-min/ngdc/ETOPO1.svg @@ -1,57 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/americana.svg b/resources/cpt-city-qgis-min/ocal/americana.svg index b19523fba3a8..5086fe9e313c 100644 --- a/resources/cpt-city-qgis-min/ocal/americana.svg +++ b/resources/cpt-city-qgis-min/ocal/americana.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/aqua-blue-blue.svg b/resources/cpt-city-qgis-min/ocal/aqua-blue-blue.svg index e985c5c06841..bb6da3ff8862 100644 --- a/resources/cpt-city-qgis-min/ocal/aqua-blue-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/aqua-blue-blue.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/black-fade-out.svg b/resources/cpt-city-qgis-min/ocal/black-fade-out.svg index d97f9a00a17a..1e2f9b4ebb63 100644 --- a/resources/cpt-city-qgis-min/ocal/black-fade-out.svg +++ b/resources/cpt-city-qgis-min/ocal/black-fade-out.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/black-to-white.svg b/resources/cpt-city-qgis-min/ocal/black-to-white.svg index ea4cfa13eb46..7f338c963c31 100644 --- a/resources/cpt-city-qgis-min/ocal/black-to-white.svg +++ b/resources/cpt-city-qgis-min/ocal/black-to-white.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/blue-fade-out.svg b/resources/cpt-city-qgis-min/ocal/blue-fade-out.svg index 6d5e37662705..ede2ebcba052 100644 --- a/resources/cpt-city-qgis-min/ocal/blue-fade-out.svg +++ b/resources/cpt-city-qgis-min/ocal/blue-fade-out.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/blue-red-blue.svg b/resources/cpt-city-qgis-min/ocal/blue-red-blue.svg index b8d3b92a2cc8..da6b58de3df3 100644 --- a/resources/cpt-city-qgis-min/ocal/blue-red-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/blue-red-blue.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/blue.svg b/resources/cpt-city-qgis-min/ocal/blue.svg index cfefdff3a650..1bd57be16483 100644 --- a/resources/cpt-city-qgis-min/ocal/blue.svg +++ b/resources/cpt-city-qgis-min/ocal/blue.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/blues.svg b/resources/cpt-city-qgis-min/ocal/blues.svg index adefcb15e7bc..608f17b6bf3e 100644 --- a/resources/cpt-city-qgis-min/ocal/blues.svg +++ b/resources/cpt-city-qgis-min/ocal/blues.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/bruce-lee-game-of-death.svg b/resources/cpt-city-qgis-min/ocal/bruce-lee-game-of-death.svg index eee0dba7d9ba..c793e9a6399e 100644 --- a/resources/cpt-city-qgis-min/ocal/bruce-lee-game-of-death.svg +++ b/resources/cpt-city-qgis-min/ocal/bruce-lee-game-of-death.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/bumblebee.svg b/resources/cpt-city-qgis-min/ocal/bumblebee.svg index b92166ee2545..5413a0c6c329 100644 --- a/resources/cpt-city-qgis-min/ocal/bumblebee.svg +++ b/resources/cpt-city-qgis-min/ocal/bumblebee.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/canadian-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/canadian-flag-smooth.svg index 298a9d7be375..95404f546d11 100644 --- a/resources/cpt-city-qgis-min/ocal/canadian-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/canadian-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/canadian-flag.svg b/resources/cpt-city-qgis-min/ocal/canadian-flag.svg index f668229a5e0d..ad682aab9c1e 100644 --- a/resources/cpt-city-qgis-min/ocal/canadian-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/canadian-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/christmas-candy.svg b/resources/cpt-city-qgis-min/ocal/christmas-candy.svg index 86cb741178b7..d760915f9c6a 100644 --- a/resources/cpt-city-qgis-min/ocal/christmas-candy.svg +++ b/resources/cpt-city-qgis-min/ocal/christmas-candy.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/colour-red-green.svg b/resources/cpt-city-qgis-min/ocal/colour-red-green.svg index c00ed8e1cd01..189f0ad5f339 100644 --- a/resources/cpt-city-qgis-min/ocal/colour-red-green.svg +++ b/resources/cpt-city-qgis-min/ocal/colour-red-green.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/cyan-magenta-yellow-white.svg b/resources/cpt-city-qgis-min/ocal/cyan-magenta-yellow-white.svg index 7f970006e09f..540541e9de46 100644 --- a/resources/cpt-city-qgis-min/ocal/cyan-magenta-yellow-white.svg +++ b/resources/cpt-city-qgis-min/ocal/cyan-magenta-yellow-white.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/cyan-turquoise.svg b/resources/cpt-city-qgis-min/ocal/cyan-turquoise.svg index cbd3b0c78bbe..438752a8304a 100644 --- a/resources/cpt-city-qgis-min/ocal/cyan-turquoise.svg +++ b/resources/cpt-city-qgis-min/ocal/cyan-turquoise.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/french-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/french-flag-smooth.svg index 07063fb92e5e..14f88764b50d 100644 --- a/resources/cpt-city-qgis-min/ocal/french-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/french-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/french-flag.svg b/resources/cpt-city-qgis-min/ocal/french-flag.svg index c3b1f3fd20f3..e4645d63cfbf 100644 --- a/resources/cpt-city-qgis-min/ocal/french-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/french-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/fruit-salad.svg b/resources/cpt-city-qgis-min/ocal/fruit-salad.svg index 6b8f3f2e552a..f7f37287da23 100644 --- a/resources/cpt-city-qgis-min/ocal/fruit-salad.svg +++ b/resources/cpt-city-qgis-min/ocal/fruit-salad.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/german-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/german-flag-smooth.svg index 910025de70af..8ed48c8ee2a8 100644 --- a/resources/cpt-city-qgis-min/ocal/german-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/german-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/german-flag.svg b/resources/cpt-city-qgis-min/ocal/german-flag.svg index 921db9c8bbf0..1fd184d5e7d4 100644 --- a/resources/cpt-city-qgis-min/ocal/german-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/german-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/golden-yellow.svg b/resources/cpt-city-qgis-min/ocal/golden-yellow.svg index 1551fd0e5171..ff421a1ffd12 100644 --- a/resources/cpt-city-qgis-min/ocal/golden-yellow.svg +++ b/resources/cpt-city-qgis-min/ocal/golden-yellow.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/green.svg b/resources/cpt-city-qgis-min/ocal/green.svg index 49ee9d6bf470..97e5ad7db072 100644 --- a/resources/cpt-city-qgis-min/ocal/green.svg +++ b/resources/cpt-city-qgis-min/ocal/green.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/indigo-orange.svg b/resources/cpt-city-qgis-min/ocal/indigo-orange.svg index 9b70cf8b97ce..4707bc07b4b3 100644 --- a/resources/cpt-city-qgis-min/ocal/indigo-orange.svg +++ b/resources/cpt-city-qgis-min/ocal/indigo-orange.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/indigo.svg b/resources/cpt-city-qgis-min/ocal/indigo.svg index 9ac04c3e4c10..e768706d9ea2 100644 --- a/resources/cpt-city-qgis-min/ocal/indigo.svg +++ b/resources/cpt-city-qgis-min/ocal/indigo.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/irish-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/irish-flag-smooth.svg index c022ce6425cd..e4108e0fe811 100644 --- a/resources/cpt-city-qgis-min/ocal/irish-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/irish-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/irish-flag.svg b/resources/cpt-city-qgis-min/ocal/irish-flag.svg index faad5986cfdc..a3fa42806201 100644 --- a/resources/cpt-city-qgis-min/ocal/irish-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/irish-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/ivory.svg b/resources/cpt-city-qgis-min/ocal/ivory.svg index 4f29a88ec24c..0c9f7255cee3 100644 --- a/resources/cpt-city-qgis-min/ocal/ivory.svg +++ b/resources/cpt-city-qgis-min/ocal/ivory.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/lavender.svg b/resources/cpt-city-qgis-min/ocal/lavender.svg index dfa2d8298721..95559ffdacd8 100644 --- a/resources/cpt-city-qgis-min/ocal/lavender.svg +++ b/resources/cpt-city-qgis-min/ocal/lavender.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/lemon-lime.svg b/resources/cpt-city-qgis-min/ocal/lemon-lime.svg index c1b8e128d930..c86c628e9ea7 100644 --- a/resources/cpt-city-qgis-min/ocal/lemon-lime.svg +++ b/resources/cpt-city-qgis-min/ocal/lemon-lime.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/lime-lemon.svg b/resources/cpt-city-qgis-min/ocal/lime-lemon.svg index 35dcca9f34d4..247ee0448673 100644 --- a/resources/cpt-city-qgis-min/ocal/lime-lemon.svg +++ b/resources/cpt-city-qgis-min/ocal/lime-lemon.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/lime.svg b/resources/cpt-city-qgis-min/ocal/lime.svg index 769ff002d583..d5c85ac52798 100644 --- a/resources/cpt-city-qgis-min/ocal/lime.svg +++ b/resources/cpt-city-qgis-min/ocal/lime.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/metal-brass.svg b/resources/cpt-city-qgis-min/ocal/metal-brass.svg index 1f9ef4c305a3..18f6ef56ae77 100644 --- a/resources/cpt-city-qgis-min/ocal/metal-brass.svg +++ b/resources/cpt-city-qgis-min/ocal/metal-brass.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/metal-bronze.svg b/resources/cpt-city-qgis-min/ocal/metal-bronze.svg index 5bc4698dabcf..6161a71de09c 100644 --- a/resources/cpt-city-qgis-min/ocal/metal-bronze.svg +++ b/resources/cpt-city-qgis-min/ocal/metal-bronze.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/metal-chrome.svg b/resources/cpt-city-qgis-min/ocal/metal-chrome.svg index fb3985aded37..44eb36a0f591 100644 --- a/resources/cpt-city-qgis-min/ocal/metal-chrome.svg +++ b/resources/cpt-city-qgis-min/ocal/metal-chrome.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/metal-copper.svg b/resources/cpt-city-qgis-min/ocal/metal-copper.svg index fcfd703d56f2..c72e6125448c 100644 --- a/resources/cpt-city-qgis-min/ocal/metal-copper.svg +++ b/resources/cpt-city-qgis-min/ocal/metal-copper.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/metal-gold.svg b/resources/cpt-city-qgis-min/ocal/metal-gold.svg index b4a433e48e9f..7c9758cf0354 100644 --- a/resources/cpt-city-qgis-min/ocal/metal-gold.svg +++ b/resources/cpt-city-qgis-min/ocal/metal-gold.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/metal-silver.svg b/resources/cpt-city-qgis-min/ocal/metal-silver.svg index 5a5871fa57de..15790285bb0a 100644 --- a/resources/cpt-city-qgis-min/ocal/metal-silver.svg +++ b/resources/cpt-city-qgis-min/ocal/metal-silver.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/mexican-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/mexican-flag-smooth.svg index 9499554e6365..0bc9291c16c0 100644 --- a/resources/cpt-city-qgis-min/ocal/mexican-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/mexican-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/mexican-flag.svg b/resources/cpt-city-qgis-min/ocal/mexican-flag.svg index 6e691ca9735d..f3baa9f79e25 100644 --- a/resources/cpt-city-qgis-min/ocal/mexican-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/mexican-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/navy-blue.svg b/resources/cpt-city-qgis-min/ocal/navy-blue.svg index 56d5cb171c11..bd2ce94880de 100644 --- a/resources/cpt-city-qgis-min/ocal/navy-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/navy-blue.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/orange.svg b/resources/cpt-city-qgis-min/ocal/orange.svg index 72e7541895d2..0597e134b78c 100644 --- a/resources/cpt-city-qgis-min/ocal/orange.svg +++ b/resources/cpt-city-qgis-min/ocal/orange.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/other-city-by-night.svg b/resources/cpt-city-qgis-min/ocal/other-city-by-night.svg index ff5d9e42908e..4851991f876c 100644 --- a/resources/cpt-city-qgis-min/ocal/other-city-by-night.svg +++ b/resources/cpt-city-qgis-min/ocal/other-city-by-night.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/other-polar-bear-in-snowstorm.svg b/resources/cpt-city-qgis-min/ocal/other-polar-bear-in-snowstorm.svg index 346305cc5a25..869af8fefe40 100644 --- a/resources/cpt-city-qgis-min/ocal/other-polar-bear-in-snowstorm.svg +++ b/resources/cpt-city-qgis-min/ocal/other-polar-bear-in-snowstorm.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-blue.svg b/resources/cpt-city-qgis-min/ocal/pastel-blue.svg index 453764b442fc..8630b2413fb4 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-blue.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-green-blue.svg b/resources/cpt-city-qgis-min/ocal/pastel-green-blue.svg index 8747ff84c0e7..a5f3d6ba1c2c 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-green-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-green-blue.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-green.svg b/resources/cpt-city-qgis-min/ocal/pastel-green.svg index 66a4f23c3e10..25ea4a318d98 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-green.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-green.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-pink.svg b/resources/cpt-city-qgis-min/ocal/pastel-pink.svg index 5879b120fe33..95bea2a4b282 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-pink.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-pink.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-purple-blue.svg b/resources/cpt-city-qgis-min/ocal/pastel-purple-blue.svg index c0a077de4c5f..108416503a12 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-purple-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-purple-blue.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-yellow-pink.svg b/resources/cpt-city-qgis-min/ocal/pastel-yellow-pink.svg index f82f4f7d6bdb..f9eff909051c 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-yellow-pink.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-yellow-pink.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pastel-yellow.svg b/resources/cpt-city-qgis-min/ocal/pastel-yellow.svg index df53d0eb3113..949721115cdf 100644 --- a/resources/cpt-city-qgis-min/ocal/pastel-yellow.svg +++ b/resources/cpt-city-qgis-min/ocal/pastel-yellow.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/peach.svg b/resources/cpt-city-qgis-min/ocal/peach.svg index 7c96bbaa0083..e81c05c9e407 100644 --- a/resources/cpt-city-qgis-min/ocal/peach.svg +++ b/resources/cpt-city-qgis-min/ocal/peach.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pink.svg b/resources/cpt-city-qgis-min/ocal/pink.svg index f58dd88d5414..4aea64e0ac4a 100644 --- a/resources/cpt-city-qgis-min/ocal/pink.svg +++ b/resources/cpt-city-qgis-min/ocal/pink.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/plum-fade-out.svg b/resources/cpt-city-qgis-min/ocal/plum-fade-out.svg index 8fd3eba4b985..0bb70e0560e9 100644 --- a/resources/cpt-city-qgis-min/ocal/plum-fade-out.svg +++ b/resources/cpt-city-qgis-min/ocal/plum-fade-out.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/plum.svg b/resources/cpt-city-qgis-min/ocal/plum.svg index bc0cad67e1d6..4b8e1ba28e65 100644 --- a/resources/cpt-city-qgis-min/ocal/plum.svg +++ b/resources/cpt-city-qgis-min/ocal/plum.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/polish-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/polish-flag-smooth.svg index 0396a2b4fa82..6edfaa83eeb0 100644 --- a/resources/cpt-city-qgis-min/ocal/polish-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/polish-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/polish-flag.svg b/resources/cpt-city-qgis-min/ocal/polish-flag.svg index 553baec50fa5..6004dd5fd440 100644 --- a/resources/cpt-city-qgis-min/ocal/polish-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/polish-flag.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/portugese-flag.svg b/resources/cpt-city-qgis-min/ocal/portugese-flag.svg index e9311e992192..377c87866de5 100644 --- a/resources/cpt-city-qgis-min/ocal/portugese-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/portugese-flag.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/pumpkin.svg b/resources/cpt-city-qgis-min/ocal/pumpkin.svg index 09f2a7ccf8ba..a78048183598 100644 --- a/resources/cpt-city-qgis-min/ocal/pumpkin.svg +++ b/resources/cpt-city-qgis-min/ocal/pumpkin.svg @@ -1,27 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/purple.svg b/resources/cpt-city-qgis-min/ocal/purple.svg index e12032a94fb4..c0b0f8f402bf 100644 --- a/resources/cpt-city-qgis-min/ocal/purple.svg +++ b/resources/cpt-city-qgis-min/ocal/purple.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/radial-eclipse.svg b/resources/cpt-city-qgis-min/ocal/radial-eclipse.svg index 2fc898ab19fc..7f76f4a4d6e3 100644 --- a/resources/cpt-city-qgis-min/ocal/radial-eclipse.svg +++ b/resources/cpt-city-qgis-min/ocal/radial-eclipse.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/radial-eyeball-albino-red.svg b/resources/cpt-city-qgis-min/ocal/radial-eyeball-albino-red.svg index 28f9e9eb5fc2..55544b495f69 100644 --- a/resources/cpt-city-qgis-min/ocal/radial-eyeball-albino-red.svg +++ b/resources/cpt-city-qgis-min/ocal/radial-eyeball-albino-red.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/radial-eyeball-blue.svg b/resources/cpt-city-qgis-min/ocal/radial-eyeball-blue.svg index b58c30f3167f..c25a6c428ed2 100644 --- a/resources/cpt-city-qgis-min/ocal/radial-eyeball-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/radial-eyeball-blue.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/radial-eyeball-brown.svg b/resources/cpt-city-qgis-min/ocal/radial-eyeball-brown.svg index 95301b599cf4..ad8a47b188e4 100644 --- a/resources/cpt-city-qgis-min/ocal/radial-eyeball-brown.svg +++ b/resources/cpt-city-qgis-min/ocal/radial-eyeball-brown.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/radial-eyeball-green.svg b/resources/cpt-city-qgis-min/ocal/radial-eyeball-green.svg index 42ab173871cd..bc84a0054ee9 100644 --- a/resources/cpt-city-qgis-min/ocal/radial-eyeball-green.svg +++ b/resources/cpt-city-qgis-min/ocal/radial-eyeball-green.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/radial-eyeball-light-blue.svg b/resources/cpt-city-qgis-min/ocal/radial-eyeball-light-blue.svg index d3ddda2798e8..dade782b60ed 100644 --- a/resources/cpt-city-qgis-min/ocal/radial-eyeball-light-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/radial-eyeball-light-blue.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/red-green-blue.svg b/resources/cpt-city-qgis-min/ocal/red-green-blue.svg index ac88ff84d66c..8072e0665331 100644 --- a/resources/cpt-city-qgis-min/ocal/red-green-blue.svg +++ b/resources/cpt-city-qgis-min/ocal/red-green-blue.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/red-orange.svg b/resources/cpt-city-qgis-min/ocal/red-orange.svg index b57a76cca4ae..9373ecb6ab75 100644 --- a/resources/cpt-city-qgis-min/ocal/red-orange.svg +++ b/resources/cpt-city-qgis-min/ocal/red-orange.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/reds.svg b/resources/cpt-city-qgis-min/ocal/reds.svg index 4ca7699c54e4..5dc98254aead 100644 --- a/resources/cpt-city-qgis-min/ocal/reds.svg +++ b/resources/cpt-city-qgis-min/ocal/reds.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/rhubarb.svg b/resources/cpt-city-qgis-min/ocal/rhubarb.svg index 5904c5fa82aa..782f9daf126a 100644 --- a/resources/cpt-city-qgis-min/ocal/rhubarb.svg +++ b/resources/cpt-city-qgis-min/ocal/rhubarb.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/romanian-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/romanian-flag-smooth.svg index 4940f1d5df07..2b77e48371f5 100644 --- a/resources/cpt-city-qgis-min/ocal/romanian-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/romanian-flag-smooth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/romanian-flag.svg b/resources/cpt-city-qgis-min/ocal/romanian-flag.svg index 0b7814ce4dcd..c56b90695248 100644 --- a/resources/cpt-city-qgis-min/ocal/romanian-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/romanian-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/russian-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/russian-flag-smooth.svg index b9060874ab62..96ae2385f173 100644 --- a/resources/cpt-city-qgis-min/ocal/russian-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/russian-flag-smooth.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/russian-flag.svg b/resources/cpt-city-qgis-min/ocal/russian-flag.svg index f9de6c69f89a..1e9d8cad6483 100644 --- a/resources/cpt-city-qgis-min/ocal/russian-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/russian-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spanish-flag.svg b/resources/cpt-city-qgis-min/ocal/spanish-flag.svg index 80ccb66e8938..3c12203c67ea 100644 --- a/resources/cpt-city-qgis-min/ocal/spanish-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/spanish-flag.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spectrum-dark.svg b/resources/cpt-city-qgis-min/ocal/spectrum-dark.svg index 9f8915a3c6e4..4e80b0d6f03c 100644 --- a/resources/cpt-city-qgis-min/ocal/spectrum-dark.svg +++ b/resources/cpt-city-qgis-min/ocal/spectrum-dark.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spectrum-light.svg b/resources/cpt-city-qgis-min/ocal/spectrum-light.svg index 258f0e5ab45a..415600ab8f52 100644 --- a/resources/cpt-city-qgis-min/ocal/spectrum-light.svg +++ b/resources/cpt-city-qgis-min/ocal/spectrum-light.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spectrum-rainbow-medium.svg b/resources/cpt-city-qgis-min/ocal/spectrum-rainbow-medium.svg index c7b60ca80524..a2175eafba6d 100644 --- a/resources/cpt-city-qgis-min/ocal/spectrum-rainbow-medium.svg +++ b/resources/cpt-city-qgis-min/ocal/spectrum-rainbow-medium.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spectrum.svg b/resources/cpt-city-qgis-min/ocal/spectrum.svg index 169bfb09c1b9..ae180f8d4cb5 100644 --- a/resources/cpt-city-qgis-min/ocal/spectrum.svg +++ b/resources/cpt-city-qgis-min/ocal/spectrum.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spectrums-rainbow-002.svg b/resources/cpt-city-qgis-min/ocal/spectrums-rainbow-002.svg index 547090d56112..e877f50fc2bc 100644 --- a/resources/cpt-city-qgis-min/ocal/spectrums-rainbow-002.svg +++ b/resources/cpt-city-qgis-min/ocal/spectrums-rainbow-002.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/spectrums-rainbow.svg b/resources/cpt-city-qgis-min/ocal/spectrums-rainbow.svg index e62197b0ded9..9d7d993328e3 100644 --- a/resources/cpt-city-qgis-min/ocal/spectrums-rainbow.svg +++ b/resources/cpt-city-qgis-min/ocal/spectrums-rainbow.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/square-picture-frame-wood.svg b/resources/cpt-city-qgis-min/ocal/square-picture-frame-wood.svg index b3b539465741..662e1c51f6e6 100644 --- a/resources/cpt-city-qgis-min/ocal/square-picture-frame-wood.svg +++ b/resources/cpt-city-qgis-min/ocal/square-picture-frame-wood.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-eight.svg b/resources/cpt-city-qgis-min/ocal/stripes-eight.svg index a26c24b37635..44fd955c5a6f 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-eight.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-eight.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-five.svg b/resources/cpt-city-qgis-min/ocal/stripes-five.svg index 6d1430ab9cce..393fa355f12e 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-five.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-five.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-four.svg b/resources/cpt-city-qgis-min/ocal/stripes-four.svg index ab2d0849c23f..899f1351ec61 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-four.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-four.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-six.svg b/resources/cpt-city-qgis-min/ocal/stripes-six.svg index 132e0f6d1c14..d90bb4dfbbed 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-six.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-six.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-eight.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-eight.svg index cc902c0f5084..1f2798585f78 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-eight.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-eight.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-five.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-five.svg index 9cd20429c459..8ab36973cbc9 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-five.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-five.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-four.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-four.svg index 7f10f2f9505c..be14dc6569bb 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-four.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-four.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-six.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-six.svg index 87a53a7043f1..1d6e7c865f4f 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-six.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-six.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-ten.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-ten.svg index cb47dd0d0b3d..0d96ed0553ad 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-ten.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-ten.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-three.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-three.svg index f9010f98008b..9d646e7c1950 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-three.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-three.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-twelve.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-twelve.svg index 7481d02cd539..2ffd1a47f294 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-twelve.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-twelve.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-solid-two.svg b/resources/cpt-city-qgis-min/ocal/stripes-solid-two.svg index 97884d54870c..f295da8a0bd8 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-solid-two.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-solid-two.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-ten.svg b/resources/cpt-city-qgis-min/ocal/stripes-ten.svg index 9a0d678a21a6..6693af93cb24 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-ten.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-ten.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-three.svg b/resources/cpt-city-qgis-min/ocal/stripes-three.svg index bfd77ef45985..664fc7577a78 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-three.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-three.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-twelve.svg b/resources/cpt-city-qgis-min/ocal/stripes-twelve.svg index 27dbcb76b893..2ffd1a47f294 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-twelve.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-twelve.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/stripes-two.svg b/resources/cpt-city-qgis-min/ocal/stripes-two.svg index 0e9dbc0180a3..8d8127bd652d 100644 --- a/resources/cpt-city-qgis-min/ocal/stripes-two.svg +++ b/resources/cpt-city-qgis-min/ocal/stripes-two.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/superman.svg b/resources/cpt-city-qgis-min/ocal/superman.svg index 19c65a71dec2..dbfb845550e3 100644 --- a/resources/cpt-city-qgis-min/ocal/superman.svg +++ b/resources/cpt-city-qgis-min/ocal/superman.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/thai-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/thai-flag-smooth.svg index c079cdaac22a..2502a12865db 100644 --- a/resources/cpt-city-qgis-min/ocal/thai-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/thai-flag-smooth.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/thai-flag.svg b/resources/cpt-city-qgis-min/ocal/thai-flag.svg index 3979e0732862..e90e7116d268 100644 --- a/resources/cpt-city-qgis-min/ocal/thai-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/thai-flag.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/tiger.svg b/resources/cpt-city-qgis-min/ocal/tiger.svg index c653feb158e8..98d1e9a8a05d 100644 --- a/resources/cpt-city-qgis-min/ocal/tiger.svg +++ b/resources/cpt-city-qgis-min/ocal/tiger.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/ukranian-flag-smooth.svg b/resources/cpt-city-qgis-min/ocal/ukranian-flag-smooth.svg index 28e9f6ba1055..7f228fb46181 100644 --- a/resources/cpt-city-qgis-min/ocal/ukranian-flag-smooth.svg +++ b/resources/cpt-city-qgis-min/ocal/ukranian-flag-smooth.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/ukranian-flag.svg b/resources/cpt-city-qgis-min/ocal/ukranian-flag.svg index b22bad889ebb..db6f7eb88f55 100644 --- a/resources/cpt-city-qgis-min/ocal/ukranian-flag.svg +++ b/resources/cpt-city-qgis-min/ocal/ukranian-flag.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/violet-orange.svg b/resources/cpt-city-qgis-min/ocal/violet-orange.svg index ddad32de1cc9..f62a2c6b7a98 100644 --- a/resources/cpt-city-qgis-min/ocal/violet-orange.svg +++ b/resources/cpt-city-qgis-min/ocal/violet-orange.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/violet.svg b/resources/cpt-city-qgis-min/ocal/violet.svg index 1ef4fc2181f2..bf083fe56571 100644 --- a/resources/cpt-city-qgis-min/ocal/violet.svg +++ b/resources/cpt-city-qgis-min/ocal/violet.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/yellow-red-yellow.svg b/resources/cpt-city-qgis-min/ocal/yellow-red-yellow.svg index d754a99920bd..abf857629243 100644 --- a/resources/cpt-city-qgis-min/ocal/yellow-red-yellow.svg +++ b/resources/cpt-city-qgis-min/ocal/yellow-red-yellow.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/yellow.svg b/resources/cpt-city-qgis-min/ocal/yellow.svg index 1fa5d32e5199..cc506d8d1f53 100644 --- a/resources/cpt-city-qgis-min/ocal/yellow.svg +++ b/resources/cpt-city-qgis-min/ocal/yellow.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ocal/zebra.svg b/resources/cpt-city-qgis-min/ocal/zebra.svg index 8b4e72a91d26..18d5f7682d88 100644 --- a/resources/cpt-city-qgis-min/ocal/zebra.svg +++ b/resources/cpt-city-qgis-min/ocal/zebra.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/os/os250k-feet.svg b/resources/cpt-city-qgis-min/os/os250k-feet.svg index 8aad95d6c2a5..e3df87d588a2 100644 --- a/resources/cpt-city-qgis-min/os/os250k-feet.svg +++ b/resources/cpt-city-qgis-min/os/os250k-feet.svg @@ -1,28 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/pd/food/curry_house.svg b/resources/cpt-city-qgis-min/pd/food/curry_house.svg index 0c3c51a05123..3137530d1d1e 100644 --- a/resources/cpt-city-qgis-min/pd/food/curry_house.svg +++ b/resources/cpt-city-qgis-min/pd/food/curry_house.svg @@ -1,270 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/rf/pseudogrey.svg b/resources/cpt-city-qgis-min/rf/pseudogrey.svg index 63b0b07934c6..ab3b9cbb07b2 100644 --- a/resources/cpt-city-qgis-min/rf/pseudogrey.svg +++ b/resources/cpt-city-qgis-min/rf/pseudogrey.svg @@ -1,3584 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/saga/saga-08.svg b/resources/cpt-city-qgis-min/saga/saga-08.svg index 665193beaad5..6539765832e0 100644 --- a/resources/cpt-city-qgis-min/saga/saga-08.svg +++ b/resources/cpt-city-qgis-min/saga/saga-08.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/tp/tpsfhm.svg b/resources/cpt-city-qgis-min/tp/tpsfhm.svg index b617b8103227..68056410c146 100644 --- a/resources/cpt-city-qgis-min/tp/tpsfhm.svg +++ b/resources/cpt-city-qgis-min/tp/tpsfhm.svg @@ -1,34 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/tp/tpushuf.svg b/resources/cpt-city-qgis-min/tp/tpushuf.svg index a6360e9a36a6..328bf51d2b5a 100644 --- a/resources/cpt-city-qgis-min/tp/tpushuf.svg +++ b/resources/cpt-city-qgis-min/tp/tpushuf.svg @@ -1,87 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ukmo/wow/humidity.svg b/resources/cpt-city-qgis-min/ukmo/wow/humidity.svg index 95c3e9674f72..9b8c1ba16e4d 100644 --- a/resources/cpt-city-qgis-min/ukmo/wow/humidity.svg +++ b/resources/cpt-city-qgis-min/ukmo/wow/humidity.svg @@ -1,64 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ukmo/wow/rain-mmh.svg b/resources/cpt-city-qgis-min/ukmo/wow/rain-mmh.svg index fdc7372eda69..6427974e46de 100644 --- a/resources/cpt-city-qgis-min/ukmo/wow/rain-mmh.svg +++ b/resources/cpt-city-qgis-min/ukmo/wow/rain-mmh.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/ukmo/wow/temp-c.svg b/resources/cpt-city-qgis-min/ukmo/wow/temp-c.svg index 84db6d2ff010..d020ff5efdda 100644 --- a/resources/cpt-city-qgis-min/ukmo/wow/temp-c.svg +++ b/resources/cpt-city-qgis-min/ukmo/wow/temp-c.svg @@ -1,68 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/country/wiki-caucasus-bath.svg b/resources/cpt-city-qgis-min/wkp/country/wiki-caucasus-bath.svg index 15f061bcdc58..049c9ca2c122 100644 --- a/resources/cpt-city-qgis-min/wkp/country/wiki-caucasus-bath.svg +++ b/resources/cpt-city-qgis-min/wkp/country/wiki-caucasus-bath.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/country/wiki-france.svg b/resources/cpt-city-qgis-min/wkp/country/wiki-france.svg index 4bd1fc70217d..e0b5493e71e8 100644 --- a/resources/cpt-city-qgis-min/wkp/country/wiki-france.svg +++ b/resources/cpt-city-qgis-min/wkp/country/wiki-france.svg @@ -1,58 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/country/wiki-scotland.svg b/resources/cpt-city-qgis-min/wkp/country/wiki-scotland.svg index 8a6fb15287a4..0b4210fd3e2d 100644 --- a/resources/cpt-city-qgis-min/wkp/country/wiki-scotland.svg +++ b/resources/cpt-city-qgis-min/wkp/country/wiki-scotland.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/encyclopedia/meyers.svg b/resources/cpt-city-qgis-min/wkp/encyclopedia/meyers.svg index 97ad44d28a3e..8e390ecfa9af 100644 --- a/resources/cpt-city-qgis-min/wkp/encyclopedia/meyers.svg +++ b/resources/cpt-city-qgis-min/wkp/encyclopedia/meyers.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/encyclopedia/nordisk-familjebok.svg b/resources/cpt-city-qgis-min/wkp/encyclopedia/nordisk-familjebok.svg index 347d83347aad..971ef1c69dec 100644 --- a/resources/cpt-city-qgis-min/wkp/encyclopedia/nordisk-familjebok.svg +++ b/resources/cpt-city-qgis-min/wkp/encyclopedia/nordisk-familjebok.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/ice/wiki-ice-greenland.svg b/resources/cpt-city-qgis-min/wkp/ice/wiki-ice-greenland.svg index afbfdd44b33d..46a7473700df 100644 --- a/resources/cpt-city-qgis-min/wkp/ice/wiki-ice-greenland.svg +++ b/resources/cpt-city-qgis-min/wkp/ice/wiki-ice-greenland.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/jarke/pakistan.svg b/resources/cpt-city-qgis-min/wkp/jarke/pakistan.svg index 8af24c4d88bb..95113e104422 100644 --- a/resources/cpt-city-qgis-min/wkp/jarke/pakistan.svg +++ b/resources/cpt-city-qgis-min/wkp/jarke/pakistan.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/knutux/wiki-knutux.svg b/resources/cpt-city-qgis-min/wkp/knutux/wiki-knutux.svg index 60d60fb43bc9..2c17cdb009c3 100644 --- a/resources/cpt-city-qgis-min/wkp/knutux/wiki-knutux.svg +++ b/resources/cpt-city-qgis-min/wkp/knutux/wiki-knutux.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte-bath.svg b/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte-bath.svg index 46bba79c1894..26257fe7136a 100644 --- a/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte-bath.svg +++ b/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte-bath.svg @@ -1,23 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte.svg b/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte.svg index 2c0f3a3f87b6..b62e7ba24028 100644 --- a/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte.svg +++ b/resources/cpt-city-qgis-min/wkp/lilleskut/afrikakarte.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/plumbago/wiki-plumbago.svg b/resources/cpt-city-qgis-min/wkp/plumbago/wiki-plumbago.svg index d4e49c97c8c3..b7e1ee943fbc 100644 --- a/resources/cpt-city-qgis-min/wkp/plumbago/wiki-plumbago.svg +++ b/resources/cpt-city-qgis-min/wkp/plumbago/wiki-plumbago.svg @@ -1,74 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/precip/wiki-precip-mm.svg b/resources/cpt-city-qgis-min/wkp/precip/wiki-precip-mm.svg index 3e29aa4ae49e..9ebf6a505d77 100644 --- a/resources/cpt-city-qgis-min/wkp/precip/wiki-precip-mm.svg +++ b/resources/cpt-city-qgis-min/wkp/precip/wiki-precip-mm.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-cont.svg b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-cont.svg index 48cebc0a73c7..a446d6698a42 100644 --- a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-cont.svg +++ b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-cont.svg @@ -1,165 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d020.svg b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d020.svg index d7d050f8fc3e..3cd185a87295 100644 --- a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d020.svg +++ b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d020.svg @@ -1,164 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d050.svg b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d050.svg index 030a2ab01272..ddc0bfb3521f 100644 --- a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d050.svg +++ b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d050.svg @@ -1,74 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d100.svg b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d100.svg index 1f36433b76ea..e6497972ee8f 100644 --- a/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d100.svg +++ b/resources/cpt-city-qgis-min/wkp/schwarzwald/wiki-schwarzwald-d100.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/shadowxfox/colombia.svg b/resources/cpt-city-qgis-min/wkp/shadowxfox/colombia.svg index 3d6e40c17438..df9ba3f2a394 100644 --- a/resources/cpt-city-qgis-min/wkp/shadowxfox/colombia.svg +++ b/resources/cpt-city-qgis-min/wkp/shadowxfox/colombia.svg @@ -1,42 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/template/wiki-1.02.svg b/resources/cpt-city-qgis-min/wkp/template/wiki-1.02.svg index 0d554816b604..82a78dfffdcb 100644 --- a/resources/cpt-city-qgis-min/wkp/template/wiki-1.02.svg +++ b/resources/cpt-city-qgis-min/wkp/template/wiki-1.02.svg @@ -1,54 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/template/wiki-1.03.svg b/resources/cpt-city-qgis-min/wkp/template/wiki-1.03.svg index 99e272b783a1..3d07e361c0fe 100644 --- a/resources/cpt-city-qgis-min/wkp/template/wiki-1.03.svg +++ b/resources/cpt-city-qgis-min/wkp/template/wiki-1.03.svg @@ -1,70 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/template/wiki-2.0.svg b/resources/cpt-city-qgis-min/wkp/template/wiki-2.0.svg index feaf0cee32cd..e320f4541da3 100644 --- a/resources/cpt-city-qgis-min/wkp/template/wiki-2.0.svg +++ b/resources/cpt-city-qgis-min/wkp/template/wiki-2.0.svg @@ -1,72 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/cpt-city-qgis-min/wkp/tubs/nrwc.svg b/resources/cpt-city-qgis-min/wkp/tubs/nrwc.svg index c1e98371e69f..ecac29ed4707 100644 --- a/resources/cpt-city-qgis-min/wkp/tubs/nrwc.svg +++ b/resources/cpt-city-qgis-min/wkp/tubs/nrwc.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/resources/function_help/json/color_cmyk b/resources/function_help/json/color_cmyk index fb8c83818b31..f3fd3293b4ad 100644 --- a/resources/function_help/json/color_cmyk +++ b/resources/function_help/json/color_cmyk @@ -7,5 +7,5 @@ {"arg":"magenta","description":"magenta component of the color, as a percentage integer value from 0 to 100"}, {"arg":"yellow","description":"yellow component of the color, as a percentage integer value from 0 to 100"}, {"arg":"black","description":"black component of the color, as a percentage integer value from 0 to 100"}], - "examples": [ { "expression":"color_cmyk(100,50,0,10)", "returns":"0,115,230"}] + "examples": [ { "expression":"color_cmyk(100,50,0,10)", "returns":"'0,115,230'"}] } diff --git a/resources/function_help/json/color_cmyka b/resources/function_help/json/color_cmyka index 2235eb7ab704..7897553dadec 100644 --- a/resources/function_help/json/color_cmyka +++ b/resources/function_help/json/color_cmyka @@ -8,5 +8,5 @@ {"arg":"yellow","description":"yellow component of the color, as a percentage integer value from 0 to 100"}, {"arg":"black","description":"black component of the color, as a percentage integer value from 0 to 100"}, {"arg":"alpha","description":"alpha component as an integer value from 0 (completely transparent) to 255 (opaque)."}], - "examples": [ { "expression":"color_cmyk(100,50,0,10,200)", "returns":"0,115,230,200"}] + "examples": [ { "expression":"color_cmyk(100,50,0,10,200)", "returns":"'0,115,230,200'"}] } diff --git a/resources/function_help/json/color_grayscale_average b/resources/function_help/json/color_grayscale_average index 221093a0d4be..82733e048022 100644 --- a/resources/function_help/json/color_grayscale_average +++ b/resources/function_help/json/color_grayscale_average @@ -6,5 +6,5 @@ "arguments": [ {"arg":"color", "description":"a color string"} ], - "examples": [ { "expression":"color_grayscale_average('255,100,50')", "returns":"127,127,127,255"}] + "examples": [ { "expression":"color_grayscale_average('255,100,50')", "returns":"'135,135,135,255'"}] } diff --git a/resources/function_help/json/color_hsl b/resources/function_help/json/color_hsl index ee9dab03179a..56fd6560ecc1 100644 --- a/resources/function_help/json/color_hsl +++ b/resources/function_help/json/color_hsl @@ -6,5 +6,5 @@ "arguments": [ {"arg":"hue","description":"hue of the color, as an integer value from 0 to 360"}, {"arg":"saturation","description":"saturation percentage of the color as an integer value from 0 to 100"}, {"arg":"lightness","description":"lightness percentage of the color as an integer value from 0 to 100"}], - "examples": [ { "expression":"color_hsl(100,50,70)", "returns":"166,217,140"}] + "examples": [ { "expression":"color_hsl(100,50,70)", "returns":"'166,217,140'"}] } diff --git a/resources/function_help/json/color_hsla b/resources/function_help/json/color_hsla index 7139b13f6723..5a13239e12c8 100644 --- a/resources/function_help/json/color_hsla +++ b/resources/function_help/json/color_hsla @@ -7,5 +7,5 @@ {"arg":"saturation","description":"saturation percentage of the color as an integer value from 0 to 100"}, {"arg":"lightness","description":"lightness percentage of the color as an integer value from 0 to 100"}, {"arg":"alpha","description":"alpha component as an integer value from 0 (completely transparent) to 255 (opaque)."}], - "examples": [ { "expression":"color_hsla(100,50,70,200)", "returns":"166,217,140,200"}] + "examples": [ { "expression":"color_hsla(100,50,70,200)", "returns":"'166,217,140,200'"}] } diff --git a/resources/function_help/json/color_hsv b/resources/function_help/json/color_hsv index 1004f7f28af9..2f91a0197343 100644 --- a/resources/function_help/json/color_hsv +++ b/resources/function_help/json/color_hsv @@ -6,5 +6,5 @@ "arguments": [ {"arg":"hue","description":"hue of the color, as an integer value from 0 to 360"}, {"arg":"saturation","description":"saturation percentage of the color as an integer value from 0 to 100"}, {"arg":"value","description":"value percentage of the color as an integer from 0 to 100"}], - "examples": [ { "expression":"color_hsv(40,100,100)", "returns":"255,170,0"}] + "examples": [ { "expression":"color_hsv(40,100,100)", "returns":"'255,170,0'"}] } diff --git a/resources/function_help/json/color_hsva b/resources/function_help/json/color_hsva index 962486115572..6efa061cc6d3 100644 --- a/resources/function_help/json/color_hsva +++ b/resources/function_help/json/color_hsva @@ -7,6 +7,6 @@ {"arg":"saturation","description":"saturation percentage of the color as an integer value from 0 to 100"}, {"arg":"value","description":"value percentage of the color as an integer from 0 to 100"}, {"arg":"alpha","description":"alpha component as an integer value from 0 (completely transparent) to 255 (opaque)"}], - "examples": [ { "expression":"color_hsva(40,100,100,200)", "returns":"255,170,0,200"}] + "examples": [ { "expression":"color_hsva(40,100,100,200)", "returns":"'255,170,0,200'"}] } diff --git a/resources/function_help/json/color_mix_rgb b/resources/function_help/json/color_mix_rgb index 0416ef05bd4e..ac195fcc2f34 100644 --- a/resources/function_help/json/color_mix_rgb +++ b/resources/function_help/json/color_mix_rgb @@ -8,5 +8,5 @@ {"arg":"color2", "description":"a color string"}, {"arg":"ratio", "description":"a ratio"} ], - "examples": [ { "expression":"color_mix_rgb('0,0,0','255,255,255',0.5)", "returns":"127,127,127,255"}] + "examples": [ { "expression":"color_mix_rgb('0,0,0','255,255,255',0.5)", "returns":"'127,127,127,255'"}] } diff --git a/resources/function_help/json/color_rgb b/resources/function_help/json/color_rgb index 71389b7aa619..62d9a1287134 100644 --- a/resources/function_help/json/color_rgb +++ b/resources/function_help/json/color_rgb @@ -6,6 +6,6 @@ "arguments": [ {"arg":"red","description":"red component as an integer value from 0 to 255"}, {"arg":"green","description":"green component as an integer value from 0 to 255"}, {"arg":"blue","description":"blue component as an integer value from 0 to 255"}], - "examples": [ { "expression":"color_rgb(255,127,0)", "returns":"255,127,0"}] + "examples": [ { "expression":"color_rgb(255,127,0)", "returns":"'255,127,0'"}] } diff --git a/resources/function_help/json/color_rgba b/resources/function_help/json/color_rgba index eebf3f6e1b7a..252c944bc8b1 100644 --- a/resources/function_help/json/color_rgba +++ b/resources/function_help/json/color_rgba @@ -7,5 +7,5 @@ {"arg":"green","description":"green component as an integer value from 0 to 255"}, {"arg":"blue","description":"blue component as an integer value from 0 to 255"}, {"arg":"alpha","description":"alpha component as an integer value from 0 (completely transparent) to 255 (opaque)."}], - "examples": [ { "expression":"color_rgba(255,127,0,200)", "returns":"255,127,0,200"}] + "examples": [ { "expression":"color_rgba(255,127,0,200)", "returns":"'255,127,0,200'"}] } diff --git a/resources/function_help/json/create_ramp b/resources/function_help/json/create_ramp index 9f5098b547df..bef5a5cd882e 100644 --- a/resources/function_help/json/create_ramp +++ b/resources/function_help/json/create_ramp @@ -4,6 +4,6 @@ "groups": ["Color"], "description": "Returns a gradient ramp from a map of color strings and steps.", "arguments": [ {"arg":"map","description":"a map of color strings and steps"}, - {"arg":"discrete","optional":true,"description":"declare whether the color ramp is discrete"}], - "examples": [ { "expression":"ramp_color(create_array(map(0,'0,0,0',1,'255,0,0')),1)", "returns":"'255,0,0,255'"} ] + {"arg":"discrete","optional":true,"default":"false","description":"set this parameter to true to create a discrete color ramp"}], + "examples": [ { "expression":"ramp_color(create_ramp(map(0,'0,0,0',1,'255,0,0')),1)", "returns":"'255,0,0,255'"} ] } diff --git a/resources/function_help/json/display_expression b/resources/function_help/json/display_expression index c1df4150d499..19ac19c75bce 100644 --- a/resources/function_help/json/display_expression +++ b/resources/function_help/json/display_expression @@ -2,39 +2,36 @@ "name": "display_expression", "type": "function", "groups": ["Record and Attributes"], - "description": "Returns the display expression for a given feature in a layer. If called with no parameters, it evaluates the current feature. The expression is evaluated by default.", - "arguments": [ + "description": "Returns the display expression for a given feature in a layer. The expression is evaluated by default. Can be used with zero, one or more arguments, see below for details.", + "variants": [ { - "arg": "feature", - "optional": true, - "default": "current feature", - "description": "The feature which should be evaluated." + "variant": "No parameters", + "variant_description": "If called with no parameters, the function will evaluate the display expression of the current feature in the current layer.", + "arguments": [], + "examples": [ { "expression": "display_expression()", "returns" : "The display expression of the current feature in the current layer." } ] }, { - "arg": "layer", - "optional": true, - "default": "current layer", - "description": "The layer (or its id or name)." + "variant": "One 'feature' parameter", + "variant_description": "If called with a 'feature' parameter only, the function will evaluate the specified feature from the current layer.", + "arguments": [ { "arg": "feature", "description": "The feature which should be evaluated." } ], + "examples": [ { "expression": "display_expression(@atlas_feature)", "returns": "The display expression of the current atlas feature." } ] }, { - "arg": "evaluate", - "description": "If the expression must be evaluated. If false, the expression will be returned as a string literal only (which could potentially be later evaluated using the 'eval' function).", - "optional": true, - "default": "true" - } - ], - "examples": [ - { - "expression": "display_expression()", - "returns": "The display expression of the current feature." - }, - { - "expression": "display_expression(get_feature_by_id('streets', 1), 'streets')", - "returns": "The display expression of the feature with the ID 1 on the layer 'streets'." - }, - { - "expression": "display_expression('a_layer_id', $currentfeature, 'False')", - "returns": "The display expression of the given feature not evaluated." + "variant" : "Layer and feature parameters", + "variant_description": "If the function is called with both a layer and a feature, it will evaluate the specified feature from the specified layer.", + "arguments": [ + { "arg": "layer", "description": "The layer (or its ID or name)" }, + { "arg": "feature", "description": "The feature which should be evaluated." }, + { "arg": "evaluate", "description": "If the expression must be evaluated. If false, the expression will be returned as a string literal only (which could potentially be later evaluated using the 'eval' function).", "optional": true, "default": "true" } + ], + "examples": [ + { "expression": "display_expression( 'streets', get_feature_by_id('streets', 1))", + "returns": "The display expression of the feature with the ID 1 on the layer 'streets'." + }, + { "expression": "display_expression('a_layer_id', $currentfeature, 'False')", + "returns": "The display expression of the given feature not evaluated." + } + ] } ] } diff --git a/resources/function_help/json/main_angle b/resources/function_help/json/main_angle new file mode 100644 index 000000000000..7dbf923e4aa2 --- /dev/null +++ b/resources/function_help/json/main_angle @@ -0,0 +1,9 @@ +{ + "name": "main_angle", + "type": "function", + "groups": ["GeometryGroup"], + "description":"Returns the main angle of a geometry (clockwise, in degrees from North), which represents the angle of the oriented minimal bounding rectangle which completely covers the geometry.", + "arguments": [ {"arg":"geometry","description":"a geometry"} ], + "examples": [ { "expression":"main_angle(geom_from_wkt('Polygon ((321577 129614, 321581 129618, 321585 129615, 321581 129610, 321577 129614))'))", "returns":"38.66"}] +} + diff --git a/resources/function_help/json/maptip b/resources/function_help/json/maptip index 5e0d3dd7efae..086a491f6308 100644 --- a/resources/function_help/json/maptip +++ b/resources/function_help/json/maptip @@ -2,39 +2,36 @@ "name": "maptip", "type": "function", "groups": ["Record and Attributes"], - "description": "Returns the maptip for a given feature in a layer. If called with no parameters, it evaluates the current feature. The maptip is evaluated by default.", - "arguments": [ + "description": "Returns the maptip for a given feature in a layer. The expression is evaluated by default. Can be used with zero, one or more arguments, see below for details.", + "variants": [ { - "arg": "feature", - "optional": true, - "default": "current feature", - "description": "The feature which should be evaluated." + "variant": "No parameters", + "variant_description": "If called with no parameters, the function will evaluate the maptip of the current feature in the current layer.", + "arguments": [], + "examples": [ { "expression": "maptip()", "returns" : "The maptip of the current feature in the current layer." } ] }, { - "arg": "layer", - "optional": true, - "default": "current layer", - "description": "The layer (or its id or name)." + "variant": "One 'feature' parameter", + "variant_description": "If called with a 'feature' parameter only, the function will evaluate the specified feature from the current layer.", + "arguments": [ { "arg": "feature", "description": "The feature which should be evaluated." } ], + "examples": [ { "expression": "maptip(@atlas_feature)", "returns": "The maptip of the current atlas feature." } ] }, { - "arg": "evaluate", - "description": "If the expression must be evaluated. If false, the expression will be returned as a string literal only (which could potentially be later evaluated using the 'eval_template' function).", - "optional": true, - "default": "true" - } - ], - "examples": [ - { - "expression": "maptip()", - "returns": "The maptip of the current feature." - }, - { - "expression": "maptip(get_feature('streets', 1), 'streets')", - "returns": "The maptip of the feature with the ID 1 on the layer 'streets'." - }, - { - "expression": "maptip('a_layer_id', $currentfeature, 'False')", - "returns": "The maptip of the given feature not evaluated." + "variant" : "Layer and feature parameters", + "variant_description": "If the function is called with both a layer and a feature, it will evaluate the specified feature from the specified layer.", + "arguments": [ + { "arg": "layer", "description": "The layer (or its ID or name)" }, + { "arg": "feature", "description": "The feature which should be evaluated." }, + { "arg": "evaluate", "description": "If the expression must be evaluated. If false, the expression will be returned as a string literal only (which could potentially be later evaluated using the 'eval_template' function).", "optional": true, "default": "true" } + ], + "examples": [ + { "expression": "maptip('streets', get_feature_by_id('streets', 1))", + "returns": "The maptip of the feature with the ID 1 on the layer 'streets'." + }, + { "expression": "maptip('a_layer_id', $currentfeature, 'False')", + "returns": "The maptip of the given feature not evaluated." + } + ] } ] } diff --git a/resources/function_help/json/oriented_bbox b/resources/function_help/json/oriented_bbox index a9dd24216098..0676a3b1bec1 100644 --- a/resources/function_help/json/oriented_bbox +++ b/resources/function_help/json/oriented_bbox @@ -3,7 +3,7 @@ "type": "function", "groups": ["GeometryGroup"], "description":"Returns a geometry which represents the minimal oriented bounding box of an input geometry.", - "arguments": [ {"arg":"geom","description":"a geometry"} ], + "arguments": [ {"arg":"geometry","description":"a geometry"} ], "examples": [ { "expression":"geom_to_wkt( oriented_bbox( geom_from_wkt( 'MULTIPOINT(1 2, 3 4, 3 2)' ) ) )", "returns":"Polygon ((1 4, 1 2, 3 2, 3 4, 1 4))"}] } diff --git a/resources/function_help/json/project_color b/resources/function_help/json/project_color index 777bcf39cfcc..24e208b266ad 100644 --- a/resources/function_help/json/project_color +++ b/resources/function_help/json/project_color @@ -4,6 +4,6 @@ "groups": ["Color"], "description": "Returns a color from the project's color scheme.", "arguments": [ {"arg":"name","description":"a color name"}], - "examples": [ { "expression":"project_color('Logo color')", "returns":"20,140,50"} + "examples": [ { "expression":"project_color('Logo color')", "returns":"'20,140,50'"} ] } diff --git a/resources/function_help/json/set_color_part b/resources/function_help/json/set_color_part index c4ea9edbad78..aaa71fa0a73d 100644 --- a/resources/function_help/json/set_color_part +++ b/resources/function_help/json/set_color_part @@ -8,5 +8,5 @@ {"arg":"component", "description":"a string corresponding to the color component to set. Valid options are:
  • red: RGB red component (0-255)
  • green: RGB green component (0-255)
  • blue: RGB blue component (0-255)
  • alpha: alpha (transparency) value (0-255)
  • hue: HSV hue (0-360)
  • saturation: HSV saturation (0-100)
  • value: HSV value (0-100)
  • hsl_hue: HSL hue (0-360)
  • hsl_saturation: HSL saturation (0-100)
  • lightness: HSL lightness (0-100)
  • cyan: CMYK cyan component (0-100)
  • magenta: CMYK magenta component (0-100)
  • yellow: CMYK yellow component (0-100)
  • black: CMYK black component (0-100)
"}, {"arg":"value", "description":"new value for color component, respecting the ranges listed above"} ], - "examples": [ { "expression":"set_color_part('200,10,30','green',50)", "returns":"200,50,30"}] + "examples": [ { "expression":"set_color_part('200,10,30','green',50)", "returns":"'200,50,30,255'"}] } diff --git a/resources/server/api/ogc/schema.json b/resources/server/api/ogc/schema.json index 4726952d4bae..7f8b6d7f81d2 100644 --- a/resources/server/api/ogc/schema.json +++ b/resources/server/api/ogc/schema.json @@ -376,7 +376,7 @@ }, "sortby" : { "name" : "sortby", - "in" : "path", + "in" : "query", "description" : "Sort results by the specified field name", "required" : false, "schema" : { @@ -385,11 +385,11 @@ }, "sortdesc" : { "name" : "sortdesc", - "in" : "path", + "in" : "query", "description" : "Sort results in descending order, field name must be specified with 'sortby' parameter", "required" : false, "schema" : { - "type" : "bool" + "type" : "boolean" } }, "relations" : { diff --git a/resources/themes/Blend of Gray/style.qss b/resources/themes/Blend of Gray/style.qss index cb5a12b3d90b..85ac8590eca4 100644 --- a/resources/themes/Blend of Gray/style.qss +++ b/resources/themes/Blend of Gray/style.qss @@ -758,6 +758,12 @@ QAbstractItemView::selected, QListView::selected { outline: none; } +QAbstractItemView::indicator:checked, QListView::indicator:checked { + image: url(@theme_path/icons/qcheckbox-checked.svg) !important; +} +QAbstractItemView::indicator:unchecked, QListView::indicator:unchecked { + image: url(@theme_path/icons/qcheckbox-unchecked.svg); +} /* ==================================================================================== */ /* TREE VIEW */ diff --git a/resources/themes/Night Mapping/style.qss b/resources/themes/Night Mapping/style.qss index f5ed17546580..b6c2c3eae998 100644 --- a/resources/themes/Night Mapping/style.qss +++ b/resources/themes/Night Mapping/style.qss @@ -762,6 +762,15 @@ QAbstractItemView::selected, QListView::selected { outline: none; } +QAbstractItemView::indicator:checked, QListView::indicator:checked { + border: 1px solid @background; + image: url(@theme_path/icons/qcheckbox-checked.svg) !important; +} +QAbstractItemView::indicator:unchecked, QListView::indicator:unchecked { + border: 1px solid @background; + image: url(@theme_path/icons/qcheckbox-unchecked.svg); +} + /* ==================================================================================== */ /* TREE VIEW */ /* ==================================================================================== */ diff --git a/scripts/sipify.pl b/scripts/sipify.pl index 51cd8e3710bd..107fcecbb390 100755 --- a/scripts/sipify.pl +++ b/scripts/sipify.pl @@ -185,6 +185,14 @@ sub processDoxygenLine { # replace nullptr with None (nullptr means nothing to Python devs) $line =~ s/\bnullptr\b/None/g; + if ( $line =~ m/^\\(?sub)?section/) { + my $sep = "-"; + $sep = "~" if defined $+{SUB}; + $line =~ s/^\\(sub)?section \w+ //; + my $sep_line = $line =~ s/[\w ()]/$sep/gr; + $line .= "\n".$sep_line; + } + # convert ### style headings if ( $line =~ m/^###\s+(.*)$/) { $line = "$1\n".('-' x length($1)); diff --git a/src/3d/CMakeLists.txt b/src/3d/CMakeLists.txt index 3d9f99c23493..d0cb88415369 100644 --- a/src/3d/CMakeLists.txt +++ b/src/3d/CMakeLists.txt @@ -2,6 +2,7 @@ # sources SET(QGIS_3D_SRCS + qgs3d.cpp qgsaabb.cpp qgsabstract3dengine.cpp qgsabstractvectorlayer3drenderer.cpp @@ -75,6 +76,7 @@ SET(QGIS_3D_SRCS SET(QGIS_3D_HDRS processing/qgs3dalgorithms.h + qgs3d.h qgs3danimationsettings.h qgs3dmapscene.h qgs3dmapsettings.h diff --git a/src/3d/qgs3d.cpp b/src/3d/qgs3d.cpp new file mode 100644 index 000000000000..507ba886c90f --- /dev/null +++ b/src/3d/qgs3d.cpp @@ -0,0 +1,32 @@ +/*************************************************************************** + qgs3d.cpp + ---------- + begin : July 2020 + copyright : (C) 2020 by Nyall Dawson + email : nyall dot dawson at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgs3d.h" + +Qgs3D *Qgs3D::instance() +{ + static Qgs3D *sInstance( new Qgs3D() ); + return sInstance; +} + +Qgs3D::~Qgs3D() +{ +} + +Qgs3D::Qgs3D() +{ +} diff --git a/src/3d/qgs3d.h b/src/3d/qgs3d.h new file mode 100644 index 000000000000..97346bb8a99b --- /dev/null +++ b/src/3d/qgs3d.h @@ -0,0 +1,58 @@ +/*************************************************************************** + qgs3d.h + -------- + begin : July 2020 + copyright : (C) 2020 by Nyall Dawson + email : nyall dot dawson at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGS3D_H +#define QGS3D_H + +#include "qgis_3d.h" +#include "qgis_sip.h" + +/** + * \ingroup gui + * Qgs3D is a singleton class containing various registries and other global members + * related to 3D classes. + * \since QGIS 3.16 + */ +class _3D_EXPORT Qgs3D +{ + + public: + + //! Qgs3D cannot be copied + Qgs3D( const Qgs3D &other ) = delete; + + //! Qgs3D cannot be copied + Qgs3D &operator=( const Qgs3D &other ) = delete; + + /** + * Returns a pointer to the singleton instance. + */ + static Qgs3D *instance(); + + ~Qgs3D(); + + private: + + Qgs3D(); + +#ifdef SIP_RUN + Qgs3D( const Qgs3D &other ); +#endif + +}; + +#endif // QGS3D_H diff --git a/src/3d/qgs3dmapscene.cpp b/src/3d/qgs3dmapscene.cpp index 609c69389faa..3e2d10984f36 100644 --- a/src/3d/qgs3dmapscene.cpp +++ b/src/3d/qgs3dmapscene.cpp @@ -35,6 +35,7 @@ #include #include +#include "qgsapplication.h" #include "qgsaabb.h" #include "qgsabstract3dengine.h" #include "qgs3dmapscenepickhandler.h" @@ -47,7 +48,9 @@ #include "qgseventtracing.h" #include "qgsmeshlayer.h" #include "qgsmeshlayer3drenderer.h" +#include "qgspoint3dsymbol.h" #include "qgsrulebased3drenderer.h" +#include "qgssourcecache.h" #include "qgsterrainentity_p.h" #include "qgsterraingenerator.h" #include "qgstessellatedpolygongeometry.h" @@ -97,6 +100,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine * mCameraController->resetView( 1000 ); addCameraViewCenterEntity( mEngine->camera() ); + updateLights(); // create terrain entity @@ -109,9 +113,45 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine * connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain ); connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights ); connect( &map, &Qgs3DMapSettings::directionalLightsChanged, this, &Qgs3DMapScene::updateLights ); + connect( &map, &Qgs3DMapSettings::showLightSourceOriginsChanged, this, &Qgs3DMapScene::updateLights ); connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens ); connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged ); + connect( QgsApplication::instance()->sourceCache(), &QgsSourceCache::remoteSourceFetched, this, [ = ]( const QString & url ) + { + const QList modelVectorLayers = mModelVectorLayers; + for ( QgsMapLayer *layer : modelVectorLayers ) + { + QgsAbstract3DRenderer *renderer = layer->renderer3D(); + if ( renderer ) + { + if ( renderer->type() == QLatin1String( "vector" ) ) + { + const QgsPoint3DSymbol *pointSymbol = static_cast< const QgsPoint3DSymbol * >( static_cast< QgsVectorLayer3DRenderer *>( renderer )->symbol() ); + if ( pointSymbol->shapeProperties()[QStringLiteral( "model" )].toString() == url ) + { + removeLayerEntity( layer ); + addLayerEntity( layer ); + } + } + else if ( renderer->type() == QLatin1String( "rulebased" ) ) + { + const QgsRuleBased3DRenderer::RuleList rules = static_cast< QgsRuleBased3DRenderer *>( renderer )->rootRule()->descendants(); + for ( auto rule : rules ) + { + const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( rule->symbol() ); + if ( pointSymbol->shapeProperties()[QStringLiteral( "model" )].toString() == url ) + { + removeLayerEntity( layer ); + addLayerEntity( layer ); + break; + } + } + } + } + } + } ); + // create entities of renderers onRenderersChanged(); @@ -119,7 +159,6 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine * // listen to changes of layers in order to add/remove 3D renderer entities connect( &map, &Qgs3DMapSettings::layersChanged, this, &Qgs3DMapScene::onLayersChanged ); - updateLights(); #if 0 ChunkedEntity *testChunkEntity = new ChunkedEntity( AABB( -500, 0, -500, 500, 100, 500 ), 2.f, 3.f, 7, new TestChunkLoaderFactory ); @@ -381,7 +420,7 @@ void Qgs3DMapScene::onFrameTriggered( float dt ) { if ( entity->isEnabled() && entity->needsUpdate() ) { - qDebug() << "need for update"; + QgsDebugMsgLevel( QStringLiteral( "need for update" ), 2 ); entity->update( _sceneState( mCameraController ) ); } } @@ -457,6 +496,31 @@ void Qgs3DMapScene::updateLights() for ( Qt3DCore::QEntity *entity : qgis::as_const( mLightEntities ) ) entity->deleteLater(); mLightEntities.clear(); + for ( Qt3DCore::QEntity *entity : qgis::as_const( mLightOriginEntities ) ) + entity->deleteLater(); + mLightOriginEntities.clear(); + + auto createLightOriginEntity = [ = ]( QVector3D translation, const QColor & color )->Qt3DCore::QEntity * + { + Qt3DCore::QEntity *originEntity = new Qt3DCore::QEntity; + + Qt3DCore::QTransform *trLightOriginCenter = new Qt3DCore::QTransform; + trLightOriginCenter->setTranslation( translation ); + originEntity->addComponent( trLightOriginCenter ); + + Qt3DExtras::QPhongMaterial *materialLightOriginCenter = new Qt3DExtras::QPhongMaterial; + materialLightOriginCenter->setAmbient( color ); + originEntity->addComponent( materialLightOriginCenter ); + + Qt3DExtras::QSphereMesh *rendererLightOriginCenter = new Qt3DExtras::QSphereMesh; + rendererLightOriginCenter->setRadius( 20 ); + originEntity->addComponent( rendererLightOriginCenter ); + + originEntity->setEnabled( true ); + originEntity->setParent( this ); + + return originEntity; + }; const auto newPointLights = mMap.pointLights(); for ( const QgsPointLightSettings &pointLightSettings : newPointLights ) @@ -479,6 +543,9 @@ void Qgs3DMapScene::updateLights() lightEntity->addComponent( lightTransform ); lightEntity->setParent( this ); mLightEntities << lightEntity; + + if ( mMap.showLightSourceOrigins() ) + mLightOriginEntities << createLightOriginEntity( lightTransform->translation(), pointLightSettings.color() ); } const auto newDirectionalLights = mMap.directionalLights(); @@ -592,6 +659,31 @@ void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer ) ( renderer->type() == QLatin1String( "vector" ) || renderer->type() == QLatin1String( "rulebased" ) ) ) { static_cast( renderer )->setLayer( static_cast( layer ) ); + if ( renderer->type() == QLatin1String( "vector" ) ) + { + QgsVectorLayer *vlayer = qobject_cast( layer ); + if ( vlayer->geometryType() == QgsWkbTypes::PointGeometry ) + { + const QgsPoint3DSymbol *pointSymbol = static_cast< const QgsPoint3DSymbol * >( static_cast< QgsVectorLayer3DRenderer *>( renderer )->symbol() ); + if ( pointSymbol->shape() == QgsPoint3DSymbol::Model ) + { + mModelVectorLayers.append( layer ); + } + } + } + else if ( renderer->type() == QLatin1String( "rulebased" ) ) + { + const QgsRuleBased3DRenderer::RuleList rules = static_cast< QgsRuleBased3DRenderer *>( renderer )->rootRule()->descendants(); + for ( auto rule : rules ) + { + const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( rule->symbol() ); + if ( pointSymbol && pointSymbol->shape() == QgsPoint3DSymbol::Model ) + { + mModelVectorLayers.append( layer ); + break; + } + } + } } else if ( layer->type() == QgsMapLayerType::MeshLayer && renderer->type() == QLatin1String( "mesh" ) ) { @@ -667,6 +759,7 @@ void Qgs3DMapScene::removeLayerEntity( QgsMapLayer *layer ) { QgsVectorLayer *vlayer = qobject_cast( layer ); disconnect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged ); + mModelVectorLayers.removeAll( layer ); } if ( layer->type() == QgsMapLayerType::MeshLayer ) diff --git a/src/3d/qgs3dmapscene.h b/src/3d/qgs3dmapscene.h index 4f3e6767c9b8..4f3a67b9bc42 100644 --- a/src/3d/qgs3dmapscene.h +++ b/src/3d/qgs3dmapscene.h @@ -165,6 +165,9 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity QList mPickHandlers; //! List of lights in the scene QList mLightEntities; + //! List of light origins in the scene + QList mLightOriginEntities; + QList mModelVectorLayers; }; #endif // QGS3DMAPSCENE_H diff --git a/src/3d/qgs3dmapsettings.cpp b/src/3d/qgs3dmapsettings.cpp index 1c8ec2f58043..24b0ac7c8c91 100644 --- a/src/3d/qgs3dmapsettings.cpp +++ b/src/3d/qgs3dmapsettings.cpp @@ -47,6 +47,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other ) , mShowTerrainBoundingBoxes( other.mShowTerrainBoundingBoxes ) , mShowTerrainTileInfo( other.mShowTerrainTileInfo ) , mShowCameraViewCenter( other.mShowCameraViewCenter ) + , mShowLightSources( other.mShowLightSources ) , mShowLabels( other.mShowLabels ) , mPointLights( other.mPointLights ) , mDirectionalLights( other.mDirectionalLights ) @@ -215,6 +216,7 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte mShowTerrainBoundingBoxes = elemDebug.attribute( QStringLiteral( "bounding-boxes" ), QStringLiteral( "0" ) ).toInt(); mShowTerrainTileInfo = elemDebug.attribute( QStringLiteral( "terrain-tile-info" ), QStringLiteral( "0" ) ).toInt(); mShowCameraViewCenter = elemDebug.attribute( QStringLiteral( "camera-view-center" ), QStringLiteral( "0" ) ).toInt(); + mShowLightSources = elemDebug.attribute( QStringLiteral( "show-light-sources" ), QStringLiteral( "0" ) ).toInt(); QDomElement elemTemporalRange = elem.firstChildElement( QStringLiteral( "temporal-range" ) ); QDateTime start = QDateTime::fromString( elemTemporalRange.attribute( QStringLiteral( "start" ) ), Qt::ISODate ); @@ -308,6 +310,7 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon elemDebug.setAttribute( QStringLiteral( "bounding-boxes" ), mShowTerrainBoundingBoxes ? 1 : 0 ); elemDebug.setAttribute( QStringLiteral( "terrain-tile-info" ), mShowTerrainTileInfo ? 1 : 0 ); elemDebug.setAttribute( QStringLiteral( "camera-view-center" ), mShowCameraViewCenter ? 1 : 0 ); + elemDebug.setAttribute( QStringLiteral( "show-light-sources" ), mShowLightSources ? 1 : 0 ); elem.appendChild( elemDebug ); QDomElement elemTemporalRange = doc.createElement( QStringLiteral( "temporal-range" ) ); @@ -540,6 +543,15 @@ void Qgs3DMapSettings::setShowCameraViewCenter( bool enabled ) emit showCameraViewCenterChanged(); } +void Qgs3DMapSettings::setShowLightSourceOrigins( bool enabled ) +{ + if ( mShowLightSources == enabled ) + return; + + mShowLightSources = enabled; + emit showLightSourceOriginsChanged(); +} + void Qgs3DMapSettings::setShowLabels( bool enabled ) { if ( mShowLabels == enabled ) diff --git a/src/3d/qgs3dmapsettings.h b/src/3d/qgs3dmapsettings.h index 25c1e2bf17f9..d60913251bcf 100644 --- a/src/3d/qgs3dmapsettings.h +++ b/src/3d/qgs3dmapsettings.h @@ -315,6 +315,19 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec * \since QGIS 3.4 */ bool showCameraViewCenter() const { return mShowCameraViewCenter; } + + /** + * Sets whether to show light source origins as a sphere (for debugging) + * \since QGIS 3.16 + */ + void setShowLightSourceOrigins( bool enabled ); + + /** + * Returns whether to show light source origins as a sphere (for debugging) + * \since QGIS 3.16 + */ + bool showLightSourceOrigins() const { return mShowLightSources; } + //! Sets whether to display labels on terrain tiles void setShowLabels( bool enabled ); //! Returns whether to display labels on terrain tiles @@ -417,6 +430,13 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec * \since QGIS 3.4 */ void showCameraViewCenterChanged(); + + /** + * Emitted when the flag whether light source origins are shown has changed. + * \since QGIS 3.15 + */ + void showLightSourceOriginsChanged(); + //! Emitted when the flag whether labels are displayed on terrain tiles has changed void showLabelsChanged(); @@ -460,6 +480,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec bool mShowTerrainBoundingBoxes = false; //!< Whether to show bounding boxes of entities - useful for debugging bool mShowTerrainTileInfo = false; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging + bool mShowLightSources = false; //!< Whether to show the origin of light sources bool mShowLabels = false; //!< Whether to display labels on terrain tiles QList mPointLights; //!< List of point lights defined for the scene QList mDirectionalLights; //!< List of directional lights defined for the scene diff --git a/src/3d/qgsphongmaterialsettings.cpp b/src/3d/qgsphongmaterialsettings.cpp index 12714586dda2..e6e0bd6b5948 100644 --- a/src/3d/qgsphongmaterialsettings.cpp +++ b/src/3d/qgsphongmaterialsettings.cpp @@ -24,6 +24,10 @@ void QgsPhongMaterialSettings::readXml( const QDomElement &elem ) mDiffuse = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "diffuse" ) ) ); mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ) ) ); mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat(); + mDiffuseTextureEnabled = elem.attribute( QStringLiteral( "is_using_diffuse_texture" ), QStringLiteral( "0" ) ).toInt(); + mTexturePath = elem.attribute( QStringLiteral( "diffuse_texture_path" ), QString() ); + mTextureScale = elem.attribute( QStringLiteral( "texture_scale" ), QString( "1.0" ) ).toFloat(); + mTextureRotation = elem.attribute( QStringLiteral( "texture-rotation" ), QString( "0.0" ) ).toFloat(); } void QgsPhongMaterialSettings::writeXml( QDomElement &elem ) const @@ -32,4 +36,8 @@ void QgsPhongMaterialSettings::writeXml( QDomElement &elem ) const elem.setAttribute( QStringLiteral( "diffuse" ), QgsSymbolLayerUtils::encodeColor( mDiffuse ) ); elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) ); elem.setAttribute( QStringLiteral( "shininess" ), mShininess ); + elem.setAttribute( QStringLiteral( "is_using_diffuse_texture" ), mDiffuseTextureEnabled ); + elem.setAttribute( QStringLiteral( "diffuse_texture_path" ), mTexturePath ); + elem.setAttribute( QStringLiteral( "texture_scale" ), mTextureScale ); + elem.setAttribute( QStringLiteral( "texture-rotation" ), mTextureRotation ); } diff --git a/src/3d/qgsphongmaterialsettings.h b/src/3d/qgsphongmaterialsettings.h index 531a61a9a1b4..7dbf25713e2f 100644 --- a/src/3d/qgsphongmaterialsettings.h +++ b/src/3d/qgsphongmaterialsettings.h @@ -35,12 +35,11 @@ class QDomElement; class _3D_EXPORT QgsPhongMaterialSettings { public: - QgsPhongMaterialSettings() - : mAmbient( QColor::fromRgbF( 0.1f, 0.1f, 0.1f, 1.0f ) ) - , mDiffuse( QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) ) - , mSpecular( QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) ) - { - } + + /** + * Constructor for QgsPhongMaterialSettings. + */ + QgsPhongMaterialSettings() = default; //! Returns ambient color component QColor ambient() const { return mAmbient; } @@ -51,6 +50,50 @@ class _3D_EXPORT QgsPhongMaterialSettings //! Returns shininess of the surface float shininess() const { return mShininess; } + /** + * Returns whether the diffuse texture is used. + * + * \note Diffuse textures will only be used at render time if diffuseTextureEnabled() is TRUE + * and a texturePath() is non-empty. + * + * \see shouldUseDiffuseTexture() + * \see setDiffuseTextureEnabled() + * \see texturePath() + */ + bool diffuseTextureEnabled() const { return mDiffuseTextureEnabled; } + + /** + * Returns whether the diffuse texture should be used during rendering. + * + * Diffuse textures will only be used at render time if diffuseTextureEnabled() is TRUE + * and a texturePath() is non-empty. + * + * \see diffuseTextureEnabled() + * \see texturePath() + */ + bool shouldUseDiffuseTexture() const { return mDiffuseTextureEnabled && !mTexturePath.isEmpty(); } + + /** + * Returns the diffuse texture path. + * + * \note Diffuse textures will only be used at render time if diffuseTextureEnabled() is TRUE + * and a texturePath() is non-empty. + * + * \see setTexturePath() + * \see diffuseTextureEnabled() + */ + QString texturePath() const { return mTexturePath; } + + /** + * Returns the texture scale + * The texture scale changes the size of the displayed texture in the 3D scene + * If the texture scale is less than 1 the texture will be stretched + */ + float textureScale() const { return mTextureScale; } + + //! Returns the texture's rotation in degrees + float textureRotation() const { return mTextureRotation; } + //! Sets ambient color component void setAmbient( const QColor &ambient ) { mAmbient = ambient; } //! Sets diffuse color component @@ -60,6 +103,38 @@ class _3D_EXPORT QgsPhongMaterialSettings //! Sets shininess of the surface void setShininess( float shininess ) { mShininess = shininess; } + /** + * Sets whether the diffuse texture is enabled. + * + * \note Diffuse textures will only be used at render time if diffuseTextureEnabled() is TRUE + * and a texturePath() is non-empty. + * + * \see diffuseTextureEnabled() + * \see setTexturePath() + */ + void setDiffuseTextureEnabled( bool used ) { mDiffuseTextureEnabled = used; } + + /** + * Sets the \a path of the texture. + * + * \note Diffuse textures will only be used at render time if diffuseTextureEnabled() is TRUE + * and a texturePath() is non-empty. + * + * \see texturePath() + * \see setDiffuseTextureEnabled() + */ + void setTexturePath( const QString &path ) { mTexturePath = path; } + + /** + * Sets the texture scale + * The texture scale changes the size of the displayed texture in the 3D scene + * If the texture scale is less than 1 the texture will be stretched + */ + void setTextureScale( float scale ) { mTextureScale = scale; } + + //! Sets the texture rotation in degrees + void setTextureRotation( float rotation ) { mTextureRotation = rotation; } + //! Reads settings from a DOM element void readXml( const QDomElement &elem ); //! Writes settings to a DOM element @@ -70,14 +145,22 @@ class _3D_EXPORT QgsPhongMaterialSettings return mAmbient == other.mAmbient && mDiffuse == other.mDiffuse && mSpecular == other.mSpecular && - mShininess == other.mShininess; + mShininess == other.mShininess && + mDiffuseTextureEnabled == other.mDiffuseTextureEnabled && + mTexturePath == other.mTexturePath && + mTextureScale == other.mTextureScale && + mTextureRotation == other.mTextureRotation; } private: - QColor mAmbient; - QColor mDiffuse; - QColor mSpecular; + QColor mAmbient{ QColor::fromRgbF( 0.1f, 0.1f, 0.1f, 1.0f ) }; + QColor mDiffuse{ QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) }; + QColor mSpecular{ QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) }; float mShininess = 0.0f; + bool mDiffuseTextureEnabled{ false }; + QString mTexturePath; + float mTextureScale{ 1.0f }; + float mTextureRotation{ 0.0f }; }; diff --git a/src/3d/qgstessellatedpolygongeometry.cpp b/src/3d/qgstessellatedpolygongeometry.cpp index f87aa401f955..dfc0f1db7f87 100644 --- a/src/3d/qgstessellatedpolygongeometry.cpp +++ b/src/3d/qgstessellatedpolygongeometry.cpp @@ -25,8 +25,12 @@ #include "qgspolygon.h" -QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( QNode *parent ) - : Qt3DRender::QGeometry( parent ) +QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( bool _withNormals, bool _invertNormals, bool _addBackFaces, bool _addTextureCoords, QNode *parent ) + : Qt3DRender::QGeometry( parent ), + mWithNormals( _withNormals ), + mInvertNormals( _invertNormals ), + mAddBackFaces( _addBackFaces ), + mAddTextureCoords( _addTextureCoords ) { #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) mVertexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, this ); @@ -34,7 +38,7 @@ QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( QNode *parent ) mVertexBuffer = new Qt3DRender::QBuffer( this ); #endif - QgsTessellator tmpTess( 0, 0, mWithNormals ); + QgsTessellator tmpTess( 0, 0, mWithNormals, false, false, false, mAddTextureCoords ); const int stride = tmpTess.stride(); mPositionAttribute = new Qt3DRender::QAttribute( this ); @@ -58,6 +62,18 @@ QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( QNode *parent ) mNormalAttribute->setByteOffset( 3 * sizeof( float ) ); addAttribute( mNormalAttribute ); } + if ( mAddTextureCoords ) + { + mTextureCoordsAttribute = new Qt3DRender::QAttribute( this ); + mTextureCoordsAttribute->setName( Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName() ); + mTextureCoordsAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float ); + mTextureCoordsAttribute->setVertexSize( 2 ); + mTextureCoordsAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute ); + mTextureCoordsAttribute->setBuffer( mVertexBuffer ); + mTextureCoordsAttribute->setByteStride( stride ); + mTextureCoordsAttribute->setByteOffset( mWithNormals ? 6 * sizeof( float ) : 3 * sizeof( float ) ); + addAttribute( mTextureCoordsAttribute ); + } } void QgsTessellatedPolygonGeometry::setPolygons( const QList &polygons, const QList &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList &extrusionHeightPerPolygon ) @@ -66,7 +82,7 @@ void QgsTessellatedPolygonGeometry::setPolygons( const QList &poly mTriangleIndexStartingIndices.reserve( polygons.count() ); mTriangleIndexFids.reserve( polygons.count() ); - QgsTessellator tessellator( origin.x(), origin.y(), mWithNormals, mInvertNormals, mAddBackFaces ); + QgsTessellator tessellator( origin.x(), origin.y(), mWithNormals, mInvertNormals, mAddBackFaces, false, mAddTextureCoords ); for ( int i = 0; i < polygons.count(); ++i ) { Q_ASSERT( tessellator.dataVerticesCount() % 3 == 0 ); @@ -88,6 +104,8 @@ void QgsTessellatedPolygonGeometry::setPolygons( const QList &poly mPositionAttribute->setCount( nVerts ); if ( mNormalAttribute ) mNormalAttribute->setCount( nVerts ); + if ( mAddTextureCoords ) + mTextureCoordsAttribute->setCount( nVerts ); } void QgsTessellatedPolygonGeometry::setData( const QByteArray &vertexBufferData, int vertexCount, const QVector &triangleIndexFids, const QVector &triangleIndexStartingIndices ) @@ -99,6 +117,8 @@ void QgsTessellatedPolygonGeometry::setData( const QByteArray &vertexBufferData, mPositionAttribute->setCount( vertexCount ); if ( mNormalAttribute ) mNormalAttribute->setCount( vertexCount ); + if ( mTextureCoordsAttribute ) + mTextureCoordsAttribute->setCount( vertexCount ); } diff --git a/src/3d/qgstessellatedpolygongeometry.h b/src/3d/qgstessellatedpolygongeometry.h index f1a23e8f6d65..0521214ca44a 100644 --- a/src/3d/qgstessellatedpolygongeometry.h +++ b/src/3d/qgstessellatedpolygongeometry.h @@ -46,7 +46,7 @@ class QgsTessellatedPolygonGeometry : public Qt3DRender::QGeometry Q_OBJECT public: //! Constructor - QgsTessellatedPolygonGeometry( QNode *parent = nullptr ); + QgsTessellatedPolygonGeometry( bool _withNormals = true, bool invertNormals = false, bool addBackFaces = false, bool addTextureCoords = false, QNode *parent = nullptr ); //! Returns whether the normals of triangles will be inverted (useful for fixing clockwise / counter-clockwise face vertex orders) bool invertNormals() const { return mInvertNormals; } @@ -65,6 +65,12 @@ class QgsTessellatedPolygonGeometry : public Qt3DRender::QGeometry */ void setAddBackFaces( bool add ) { mAddBackFaces = add; } + /** + * Sets whether the texture coordinates will be generated + * \since QGIS 3.16 + */ + void setAddTextureCoords( bool add ) { mAddTextureCoords = add; } + //! Initializes vertex buffer from given polygons. Takes ownership of passed polygon geometries void setPolygons( const QList &polygons, const QList &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList &extrusionHeightPerPolygon = QList() ); @@ -86,6 +92,7 @@ class QgsTessellatedPolygonGeometry : public Qt3DRender::QGeometry Qt3DRender::QAttribute *mPositionAttribute = nullptr; Qt3DRender::QAttribute *mNormalAttribute = nullptr; + Qt3DRender::QAttribute *mTextureCoordsAttribute = nullptr; Qt3DRender::QBuffer *mVertexBuffer = nullptr; QVector mTriangleIndexFids; @@ -94,6 +101,7 @@ class QgsTessellatedPolygonGeometry : public Qt3DRender::QGeometry bool mWithNormals = true; bool mInvertNormals = false; bool mAddBackFaces = false; + bool mAddTextureCoords = false; }; #endif // QGSTESSELLATEDPOLYGONGEOMETRY_H diff --git a/src/3d/symbols/qgsline3dsymbol_p.cpp b/src/3d/symbols/qgsline3dsymbol_p.cpp index aab9ba6b89b9..422e48c1afac 100644 --- a/src/3d/symbols/qgsline3dsymbol_p.cpp +++ b/src/3d/symbols/qgsline3dsymbol_p.cpp @@ -182,7 +182,7 @@ void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, cons QByteArray data( ( const char * )out.tessellator->data().constData(), out.tessellator->data().count() * sizeof( float ) ); int nVerts = data.count() / out.tessellator->stride(); - QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry; + QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry( false, false, false, false ); geometry->setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices ); Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer; diff --git a/src/3d/symbols/qgslinevertexdata_p.cpp b/src/3d/symbols/qgslinevertexdata_p.cpp index 8af8bcc7a19a..30e1e9908f38 100644 --- a/src/3d/symbols/qgslinevertexdata_p.cpp +++ b/src/3d/symbols/qgslinevertexdata_p.cpp @@ -84,7 +84,7 @@ Qt3DRender::QGeometry *QgsLineVertexData::createGeometry( Qt3DCore::QNode *paren #endif indexBuffer->setData( createIndexBuffer() ); - QgsDebugMsg( QString( "vertex buffer %1 MB index buffer %2 MB " ).arg( vertexBuffer->data().count() / 1024. / 1024. ).arg( indexBuffer->data().count() / 1024. / 1024. ) ); + QgsDebugMsgLevel( QString( "vertex buffer %1 MB index buffer %2 MB " ).arg( vertexBuffer->data().count() / 1024. / 1024. ).arg( indexBuffer->data().count() / 1024. / 1024. ), 2 ); Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute( parent ); positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute ); diff --git a/src/3d/symbols/qgsmesh3dsymbol_p.cpp b/src/3d/symbols/qgsmesh3dsymbol_p.cpp index 89c6631eb887..18167dc3cba7 100644 --- a/src/3d/symbols/qgsmesh3dsymbol_p.cpp +++ b/src/3d/symbols/qgsmesh3dsymbol_p.cpp @@ -137,9 +137,7 @@ Qt3DRender::QGeometryRenderer *QgsMesh3DSymbolEntityNode::renderer( const Qgs3DM // Polygons from mesh are already triangles, but // call QgsTessellatedPolygonGeometry to // use symbol settings for back faces, normals, etc - mGeometry = new QgsTessellatedPolygonGeometry; - mGeometry->setInvertNormals( false ); - mGeometry->setAddBackFaces( symbol.addBackFaces() ); + mGeometry = new QgsTessellatedPolygonGeometry( true, false, symbol.addBackFaces(), symbol.material().shouldUseDiffuseTexture() ); QList extrusionHeightPerPolygon; mGeometry->setPolygons( polygons, fids, origin, 0.0, extrusionHeightPerPolygon ); diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index bf335541c55b..d6162e6e5193 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -44,12 +44,14 @@ #include "qgspoint3dsymbol.h" #include "qgs3dmapsettings.h" +#include "qgsapplication.h" #include "qgsvectorlayer.h" #include "qgspoint.h" #include "qgs3dutils.h" #include "qgsbillboardgeometry.h" #include "qgspoint3dbillboardmaterial.h" #include "qgslogger.h" +#include "qgssourcecache.h" #include "qgssymbol.h" #include "qgssymbollayerutils.h" #include "qgssymbollayer.h" @@ -440,19 +442,24 @@ void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettings &map Q_UNUSED( map ) for ( const QVector3D &position : positions ) { - // build the entity - Qt3DCore::QEntity *entity = new Qt3DCore::QEntity; + const QString source = QgsApplication::instance()->sourceCache()->localFilePath( symbol.shapeProperties()[QStringLiteral( "model" )].toString() ); + // if the source is remote, the Qgs3DMapScene will take care of refreshing this 3D symbol when the source is fetched + if ( !source.isEmpty() ) + { + // build the entity + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity; - QUrl url = QUrl::fromLocalFile( symbol.shapeProperties()[QStringLiteral( "model" )].toString() ); - Qt3DRender::QSceneLoader *modelLoader = new Qt3DRender::QSceneLoader; - modelLoader->setSource( url ); + QUrl url = QUrl::fromLocalFile( source ); + Qt3DRender::QSceneLoader *modelLoader = new Qt3DRender::QSceneLoader; + modelLoader->setSource( url ); - entity->addComponent( modelLoader ); - entity->addComponent( transform( position, symbol ) ); - entity->setParent( parent ); + entity->addComponent( modelLoader ); + entity->addComponent( transform( position, symbol ) ); + entity->setParent( parent ); // cppcheck wrongly believes entity will leak // cppcheck-suppress memleak + } } } @@ -470,20 +477,24 @@ void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DMapSettings &map, // get nodes for ( const QVector3D &position : positions ) { - // build the entity - Qt3DCore::QEntity *entity = new Qt3DCore::QEntity; + const QString source = QgsApplication::instance()->sourceCache()->localFilePath( symbol.shapeProperties()[QStringLiteral( "model" )].toString() ); + if ( !source.isEmpty() ) + { + // build the entity + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity; - QUrl url = QUrl::fromLocalFile( symbol.shapeProperties()[QStringLiteral( "model" )].toString() ); - Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh; - mesh->setSource( url ); + QUrl url = QUrl::fromLocalFile( source ); + Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh; + mesh->setSource( url ); - entity->addComponent( mesh ); - entity->addComponent( mat ); - entity->addComponent( transform( position, symbol ) ); - entity->setParent( parent ); + entity->addComponent( mesh ); + entity->addComponent( mat ); + entity->addComponent( transform( position, symbol ) ); + entity->setParent( parent ); // cppcheck wrongly believes entity will leak // cppcheck-suppress memleak + } } } diff --git a/src/3d/symbols/qgspolygon3dsymbol.cpp b/src/3d/symbols/qgspolygon3dsymbol.cpp index 81d6ed9b65c9..1a2290020687 100644 --- a/src/3d/symbols/qgspolygon3dsymbol.cpp +++ b/src/3d/symbols/qgspolygon3dsymbol.cpp @@ -37,6 +37,7 @@ void QgsPolygon3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext elemDataProperties.setAttribute( QStringLiteral( "culling-mode" ), Qgs3DUtils::cullingModeToString( mCullingMode ) ); elemDataProperties.setAttribute( QStringLiteral( "invert-normals" ), mInvertNormals ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ); elemDataProperties.setAttribute( QStringLiteral( "add-back-faces" ), mAddBackFaces ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ); + elemDataProperties.setAttribute( QStringLiteral( "rendered-facade" ), mRenderedFacade ); elem.appendChild( elemDataProperties ); QDomElement elemMaterial = doc.createElement( QStringLiteral( "material" ) ); @@ -66,6 +67,7 @@ void QgsPolygon3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteCon mCullingMode = Qgs3DUtils::cullingModeFromString( elemDataProperties.attribute( QStringLiteral( "culling-mode" ) ) ); mInvertNormals = elemDataProperties.attribute( QStringLiteral( "invert-normals" ) ).toInt(); mAddBackFaces = elemDataProperties.attribute( QStringLiteral( "add-back-faces" ) ).toInt(); + mRenderedFacade = elemDataProperties.attribute( QStringLiteral( "rendered-facade" ), "3" ).toInt(); QDomElement elemMaterial = elem.firstChildElement( QStringLiteral( "material" ) ); mMaterial.readXml( elemMaterial ); diff --git a/src/3d/symbols/qgspolygon3dsymbol.h b/src/3d/symbols/qgspolygon3dsymbol.h index 52e0d7694131..a3744e4f3ab8 100644 --- a/src/3d/symbols/qgspolygon3dsymbol.h +++ b/src/3d/symbols/qgspolygon3dsymbol.h @@ -128,6 +128,18 @@ class _3D_EXPORT QgsPolygon3DSymbol : public QgsAbstract3DSymbol */ void setEdgeColor( const QColor &color ) { mEdgeColor = color; } + /** + * Sets which facade of the buildings is rendered (0 for None, 1 for Walls, 2 for Roofs, 3 for WallsAndRoofs) + * \since QGIS 3.16 + */ + void setRenderedFacade( int side ) { mRenderedFacade = side; } + + /** + * Returns which facade of the buildings is rendered (0 for None, 1 for Walls, 2 for Roofs, 3 for WallsAndRoofs) + * \since QGIS 3.16 + */ + int renderedFacade() const { return mRenderedFacade; } + private: //! how to handle altitude of vector features Qgs3DTypes::AltitudeClamping mAltClamping = Qgs3DTypes::AltClampRelative; @@ -140,6 +152,7 @@ class _3D_EXPORT QgsPolygon3DSymbol : public QgsAbstract3DSymbol Qgs3DTypes::CullingMode mCullingMode = Qgs3DTypes::NoCulling; //!< Front/back culling mode bool mInvertNormals = false; bool mAddBackFaces = false; + int mRenderedFacade = 3; bool mEdgesEnabled = false; //!< Whether to highlight edges float mEdgeWidth = 1.f; //!< Width of edges in pixels diff --git a/src/3d/symbols/qgspolygon3dsymbol_p.cpp b/src/3d/symbols/qgspolygon3dsymbol_p.cpp index b7f1813348fa..c34537b56fba 100644 --- a/src/3d/symbols/qgspolygon3dsymbol_p.cpp +++ b/src/3d/symbols/qgspolygon3dsymbol_p.cpp @@ -20,9 +20,18 @@ #include "qgs3dmapsettings.h" #include "qgs3dutils.h" #include "qgstessellator.h" +#include "qgsapplication.h" +#include "qgsimagecache.h" #include +#include #include + +#include +#include +#include +#include + #include #include #include @@ -60,7 +69,7 @@ class QgsPolygon3DSymbolHandler : public QgsFeature3DHandler void processPolygon( QgsPolygon *polyClone, QgsFeatureId fid, float height, float extrusionHeight, const Qgs3DRenderContext &context, PolygonData &out ); void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PolygonData &out, bool selected ); - Qt3DExtras::QPhongMaterial *material( const QgsPolygon3DSymbol &symbol ) const; + Qt3DRender::QMaterial *material( const QgsPolygon3DSymbol &symbol, bool isSelected, const Qgs3DRenderContext &context ) const; // input specific for this class const QgsPolygon3DSymbol &mSymbol; @@ -80,8 +89,8 @@ bool QgsPolygon3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet outEdges.withAdjacency = true; outEdges.init( mSymbol.altitudeClamping(), mSymbol.altitudeBinding(), mSymbol.height(), &context.map() ); - outNormal.tessellator.reset( new QgsTessellator( context.map().origin().x(), context.map().origin().y(), true, mSymbol.invertNormals(), mSymbol.addBackFaces() ) ); - outSelected.tessellator.reset( new QgsTessellator( context.map().origin().x(), context.map().origin().y(), true, mSymbol.invertNormals(), mSymbol.addBackFaces() ) ); + outNormal.tessellator.reset( new QgsTessellator( context.map().origin().x(), context.map().origin().y(), true, mSymbol.invertNormals(), mSymbol.addBackFaces(), false, mSymbol.material().shouldUseDiffuseTexture(), mSymbol.renderedFacade(), mSymbol.material().textureRotation() ) ); + outSelected.tessellator.reset( new QgsTessellator( context.map().origin().x(), context.map().origin().y(), true, mSymbol.invertNormals(), mSymbol.addBackFaces(), false, mSymbol.material().shouldUseDiffuseTexture(), mSymbol.renderedFacade(), mSymbol.material().textureRotation() ) ); QSet attrs = mSymbol.dataDefinedProperties().referencedFields( context.expressionContext() ); attributeNames.unite( attrs ); @@ -219,21 +228,13 @@ void QgsPolygon3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs if ( out.tessellator->dataVerticesCount() == 0 ) return; // nothing to show - no need to create the entity - Qt3DExtras::QPhongMaterial *mat = material( mSymbol ); - if ( selected ) - { - // update the material with selection colors - mat->setDiffuse( context.map().selectionColor() ); - mat->setAmbient( context.map().selectionColor().darker() ); - } + Qt3DRender::QMaterial *mat = material( mSymbol, selected, context ); // extract vertex buffer data from tessellator QByteArray data( ( const char * )out.tessellator->data().constData(), out.tessellator->data().count() * sizeof( float ) ); int nVerts = data.count() / out.tessellator->stride(); - QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry; - geometry->setInvertNormals( mSymbol.invertNormals() ); - geometry->setAddBackFaces( mSymbol.addBackFaces() ); + QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry( true, mSymbol.invertNormals(), mSymbol.addBackFaces(), mSymbol.material().shouldUseDiffuseTexture() ); geometry->setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices ); Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer; @@ -264,11 +265,9 @@ static Qt3DRender::QCullFace::CullingMode _qt3DcullingMode( Qgs3DTypes::CullingM return Qt3DRender::QCullFace::NoCulling; } -Qt3DExtras::QPhongMaterial *QgsPolygon3DSymbolHandler::material( const QgsPolygon3DSymbol &symbol ) const +// front/back side culling +static void applyCullingMode( Qgs3DTypes::CullingMode cullingMode, Qt3DRender::QMaterial *material ) { - Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial; - - // front/back side culling auto techniques = material->effect()->techniques(); for ( auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit ) { @@ -276,16 +275,92 @@ Qt3DExtras::QPhongMaterial *QgsPolygon3DSymbolHandler::material( const QgsPolygo for ( auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit ) { Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace; - cullFace->setMode( _qt3DcullingMode( symbol.cullingMode() ) ); + cullFace->setMode( _qt3DcullingMode( cullingMode ) ); ( *rpit )->addRenderState( cullFace ); } } +} + + +class QgsQImageTextureImage : public Qt3DRender::QPaintedTextureImage +{ + public: + QgsQImageTextureImage( const QImage &image, Qt3DCore::QNode *parent = nullptr ) + : Qt3DRender::QPaintedTextureImage( parent ) + , mImage( image ) + { + setSize( mImage.size() ); + } + + void paint( QPainter *painter ) override + { + painter->drawImage( mImage.rect(), mImage, mImage.rect() ); + } + + private: + + QImage mImage; + +}; + + +Qt3DRender::QMaterial *QgsPolygon3DSymbolHandler::material( const QgsPolygon3DSymbol &symbol, bool isSelected, const Qgs3DRenderContext &context ) const +{ + bool fitsInCache = false; + QImage textureSourceImage; + + if ( symbol.material().shouldUseDiffuseTexture() ) + textureSourceImage = QgsApplication::imageCache()->pathAsImage( symbol.material().texturePath(), QSize(), true, 1.0, fitsInCache ); + ( void )fitsInCache; + + Qt3DRender::QMaterial *retMaterial = nullptr; + if ( !textureSourceImage.isNull() ) + { + Qt3DExtras::QDiffuseMapMaterial *material = new Qt3DExtras::QDiffuseMapMaterial; + + applyCullingMode( symbol.cullingMode(), material ); + + QgsQImageTextureImage *textureImage = new QgsQImageTextureImage( textureSourceImage ); + material->diffuse()->addTextureImage( textureImage ); + + material->diffuse()->wrapMode()->setX( Qt3DRender::QTextureWrapMode::Repeat ); + material->diffuse()->wrapMode()->setY( Qt3DRender::QTextureWrapMode::Repeat ); + material->diffuse()->wrapMode()->setZ( Qt3DRender::QTextureWrapMode::Repeat ); + material->setSpecular( symbol.material().specular() ); + material->setShininess( symbol.material().shininess() ); + material->setTextureScale( symbol.material().textureScale() ); + + if ( isSelected ) + { + // update the material with selection colors + // TODO : dampen the color of diffuse texture +// mat->setDiffuse( context.map().selectionColor() ); + material->setAmbient( context.map().selectionColor().darker() ); + } + + retMaterial = material; + } + else + { + Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial; + + applyCullingMode( symbol.cullingMode(), material ); + + material->setAmbient( symbol.material().ambient() ); + material->setDiffuse( symbol.material().diffuse() ); + material->setSpecular( symbol.material().specular() ); + material->setShininess( symbol.material().shininess() ); + + if ( isSelected ) + { + // update the material with selection colors + material->setDiffuse( context.map().selectionColor() ); + material->setAmbient( context.map().selectionColor().darker() ); + } + retMaterial = material; + } - material->setAmbient( symbol.material().ambient() ); - material->setDiffuse( symbol.material().diffuse() ); - material->setSpecular( symbol.material().specular() ); - material->setShininess( symbol.material().shininess() ); - return material; + return retMaterial; } diff --git a/src/analysis/CMakeLists.txt b/src/analysis/CMakeLists.txt index ffda58c489d2..d80a206cbc11 100644 --- a/src/analysis/CMakeLists.txt +++ b/src/analysis/CMakeLists.txt @@ -142,6 +142,7 @@ SET(QGIS_ANALYSIS_SRCS processing/qgsalgorithmrenamelayer.cpp processing/qgsalgorithmrenametablefield.cpp processing/qgsalgorithmrepairshapefile.cpp + processing/qgsalgorithmrescaleraster.cpp processing/qgsalgorithmreverselinedirection.cpp processing/qgsalgorithmrotate.cpp processing/qgsalgorithmroundrastervalues.cpp diff --git a/src/analysis/processing/qgsalgorithmdissolve.cpp b/src/analysis/processing/qgsalgorithmdissolve.cpp index bcdfb59c30ca..701c64390d7b 100644 --- a/src/analysis/processing/qgsalgorithmdissolve.cpp +++ b/src/analysis/processing/qgsalgorithmdissolve.cpp @@ -24,9 +24,9 @@ // QVariantMap QgsCollectorAlgorithm::processCollection( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback, - const std::function& )> &collector, int maxQueueLength ) + const std::function& )> &collector, int maxQueueLength, QgsProcessingFeatureSource::Flags sourceFlags ) { - std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); + std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !source ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); @@ -41,7 +41,7 @@ QVariantMap QgsCollectorAlgorithm::processCollection( const QVariantMap ¶met long count = source->featureCount(); QgsFeature f; - QgsFeatureIterator it = source->getFeatures(); + QgsFeatureIterator it = source->getFeatures( QgsFeatureRequest(), sourceFlags ); double step = count > 0 ? 100.0 / count : 1; int current = 0; @@ -281,7 +281,7 @@ QVariantMap QgsCollectAlgorithm::processAlgorithm( const QVariantMap ¶meters return processCollection( parameters, context, feedback, []( const QVector< QgsGeometry > &parts )->QgsGeometry { return QgsGeometry::collectGeometry( parts ); - } ); + }, 0, QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks ); } diff --git a/src/analysis/processing/qgsalgorithmdissolve.h b/src/analysis/processing/qgsalgorithmdissolve.h index ac3924b34596..ec324a44ae56 100644 --- a/src/analysis/processing/qgsalgorithmdissolve.h +++ b/src/analysis/processing/qgsalgorithmdissolve.h @@ -34,7 +34,7 @@ class QgsCollectorAlgorithm : public QgsProcessingAlgorithm protected: QVariantMap processCollection( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback, - const std::function& )> &collector, int maxQueueLength = 0 ); + const std::function& )> &collector, int maxQueueLength = 0, QgsProcessingFeatureSource::Flags sourceFlags = nullptr ); }; /** diff --git a/src/analysis/processing/qgsalgorithmrescaleraster.cpp b/src/analysis/processing/qgsalgorithmrescaleraster.cpp new file mode 100644 index 000000000000..b3215329979a --- /dev/null +++ b/src/analysis/processing/qgsalgorithmrescaleraster.cpp @@ -0,0 +1,180 @@ +/*************************************************************************** + qgsalgorithmrescaleraster.cpp + --------------------- + begin : July 2020 + copyright : (C) 2020 by Alexander Bruy + email : alexander dot bruy at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include "math.h" +#include "qgsalgorithmrescaleraster.h" +#include "qgsrasterfilewriter.h" + +///@cond PRIVATE + +QString QgsRescaleRasterAlgorithm::name() const +{ + return QStringLiteral( "rescaleraster" ); +} + +QString QgsRescaleRasterAlgorithm::displayName() const +{ + return QObject::tr( "Rescale raster" ); +} + +QStringList QgsRescaleRasterAlgorithm::tags() const +{ + return QObject::tr( "raster,rescale,minimum,maximum,range" ).split( ',' ); +} + +QString QgsRescaleRasterAlgorithm::group() const +{ + return QObject::tr( "Raster analysis" ); +} + +QString QgsRescaleRasterAlgorithm::groupId() const +{ + return QStringLiteral( "rasteranalysis" ); +} + +QString QgsRescaleRasterAlgorithm::shortHelpString() const +{ + return QObject::tr( "Rescales raster layer to a new value range, while preserving the shape " + "(distribution) of the raster's histogram (pixel values). Input values " + "are mapped using a linear interpolation from the source raster's minimum " + "and maximum pixel values to the destination minimum and maximum pixel range.\n\n" + "By default the algorithm preserves original the NODATA value, but there is " + "an option to override it." ); +} + +QgsRescaleRasterAlgorithm *QgsRescaleRasterAlgorithm::createInstance() const +{ + return new QgsRescaleRasterAlgorithm(); +} + +void QgsRescaleRasterAlgorithm::initAlgorithm( const QVariantMap & ) +{ + addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT" ), QStringLiteral( "Input raster" ) ) ); + addParameter( new QgsProcessingParameterBand( QStringLiteral( "BAND" ), QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT" ) ) ); + addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MINIMUM" ), QObject::tr( "New minimum value" ), QgsProcessingParameterNumber::Double, 0 ) ); + addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MAXIMUM" ), QObject::tr( "New maximum value" ), QgsProcessingParameterNumber::Double, 255 ) ); + addParameter( new QgsProcessingParameterNumber( QStringLiteral( "NODATA" ), QObject::tr( "New NODATA value" ), QgsProcessingParameterNumber::Double, QVariant(), true ) ); + addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Rescaled" ) ) ); +} + +bool QgsRescaleRasterAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) +{ + Q_UNUSED( feedback ); + + QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT" ), context ); + if ( !layer ) + throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT" ) ) ); + + mBand = parameterAsInt( parameters, QStringLiteral( "BAND" ), context ); + if ( mBand < 1 || mBand > layer->bandCount() ) + throw QgsProcessingException( QObject::tr( "Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ) + .arg( mBand ) + .arg( layer->bandCount() ) ); + + mMinimum = parameterAsDouble( parameters, QStringLiteral( "MINIMUM" ), context ); + mMaximum = parameterAsDouble( parameters, QStringLiteral( "MAXIMUM" ), context ); + + mInterface.reset( layer->dataProvider()->clone() ); + + mCrs = layer->crs(); + mLayerWidth = layer->width(); + mLayerHeight = layer->height(); + mExtent = layer->extent(); + if ( parameters.value( QStringLiteral( "NODATA" ) ).isValid() ) + { + mNoData = parameterAsDouble( parameters, QStringLiteral( "NODATA" ), context ); + } + else + { + mNoData = layer->dataProvider()->sourceNoDataValue( mBand ); + } + mXSize = mInterface->xSize(); + mYSize = mInterface->ySize(); + + return true; +} + +QVariantMap QgsRescaleRasterAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) +{ + feedback->pushInfo( QObject::tr( "Calculating raster minimum and maximum values…" ) ); + QgsRasterBandStats stats = mInterface->bandStatistics( mBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, QgsRectangle(), 0 ); + + feedback->pushInfo( QObject::tr( "Rescaling values…" ) ); + const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral( "OUTPUT" ), context ); + QFileInfo fi( outputFile ); + const QString outputFormat = QgsRasterFileWriter::driverForExtension( fi.suffix() ); + std::unique_ptr< QgsRasterFileWriter > writer = qgis::make_unique< QgsRasterFileWriter >( outputFile ); + writer->setOutputProviderKey( QStringLiteral( "gdal" ) ); + writer->setOutputFormat( outputFormat ); + std::unique_ptr provider( writer->createOneBandRaster( Qgis::Float32, mXSize, mYSize, mExtent, mCrs ) ); + if ( !provider ) + throw QgsProcessingException( QObject::tr( "Could not create raster output: %1" ).arg( outputFile ) ); + if ( !provider->isValid() ) + throw QgsProcessingException( QObject::tr( "Could not create raster output %1: %2" ).arg( outputFile, provider->error().message( QgsErrorMessage::Text ) ) ); + + QgsRasterDataProvider *destProvider = provider.get(); + destProvider->setEditable( true ); + destProvider->setNoDataValue( 1, mNoData ); + + int blockWidth = QgsRasterIterator::DEFAULT_MAXIMUM_TILE_WIDTH; + int blockHeight = QgsRasterIterator::DEFAULT_MAXIMUM_TILE_HEIGHT; + int numBlocksX = static_cast< int >( std::ceil( 1.0 * mLayerWidth / blockWidth ) ); + int numBlocksY = static_cast< int >( std::ceil( 1.0 * mLayerHeight / blockHeight ) ); + int numBlocks = numBlocksX * numBlocksY; + + QgsRasterIterator iter( mInterface.get() ); + iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent ); + int iterLeft = 0; + int iterTop = 0; + int iterCols = 0; + int iterRows = 0; + std::unique_ptr< QgsRasterBlock > block; + while ( iter.readNextRasterPart( mBand, iterCols, iterRows, block, iterLeft, iterTop ) ) + { + feedback->setProgress( 100 * ( ( iterTop / blockHeight * numBlocksX ) + iterLeft / blockWidth ) / numBlocks ); + + for ( int row = 0; row < iterRows; row++ ) + { + if ( feedback->isCanceled() ) + break; + + for ( int col = 0; col < iterCols; col++ ) + { + bool isNoData = false; + double val = block->valueAndNoData( row, col, isNoData ); + if ( isNoData ) + { + block->setValue( row, col, mNoData ); + } + else + { + double newValue = ( ( val - stats.minimumValue ) * ( mMaximum - mMinimum ) / ( stats.maximumValue - stats.minimumValue ) ) + mMinimum; + block->setValue( row, col, newValue ); + } + } + } + destProvider->writeBlock( block.get(), mBand, iterLeft, iterTop ); + } + destProvider->setEditable( false ); + + QVariantMap outputs; + outputs.insert( QStringLiteral( "OUTPUT" ), outputFile ); + return outputs; +} + +///@endcond diff --git a/src/analysis/processing/qgsalgorithmrescaleraster.h b/src/analysis/processing/qgsalgorithmrescaleraster.h new file mode 100644 index 000000000000..a82ef37ad2b3 --- /dev/null +++ b/src/analysis/processing/qgsalgorithmrescaleraster.h @@ -0,0 +1,71 @@ +/*************************************************************************** + qgsalgorithmrescaleraster.h + ------------------------------ + begin : July 2020 + copyright : (C) 2020 by Alexander Bruy + email : alexander dot bruy at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSALGORITHMRESCALERASTER_H +#define QGSALGORITHMRESCALERASTER_H + +#define SIP_NO_FILE + +#include "qgis_sip.h" +#include "qgsprocessingalgorithm.h" +#include "qgsapplication.h" + +///@cond PRIVATE + +/** + * Native rescale raster algorithm. + */ +class QgsRescaleRasterAlgorithm : public QgsProcessingAlgorithm +{ + + public: + + QgsRescaleRasterAlgorithm() = default; + void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override; + QString name() const override; + QString displayName() const override; + QStringList tags() const override; + QString group() const override; + QString groupId() const override; + QString shortHelpString() const override; + QgsRescaleRasterAlgorithm *createInstance() const override SIP_FACTORY; + + protected: + + bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; + QVariantMap processAlgorithm( const QVariantMap ¶meters, + QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; + + private: + + int mBand = 1; + int mLayerWidth = 0; + int mLayerHeight = 0; + int mXSize = 0; + int mYSize = 0; + double mNoData; + double mMinimum; + double mMaximum; + + QgsRectangle mExtent; + QgsCoordinateReferenceSystem mCrs; + std::unique_ptr< QgsRasterInterface > mInterface; +}; + +///@endcond PRIVATE + +#endif // QGSALGORITHMRESCALERASTER_H diff --git a/src/analysis/processing/qgsnativealgorithms.cpp b/src/analysis/processing/qgsnativealgorithms.cpp index 486d9bb08220..513da0a84d85 100644 --- a/src/analysis/processing/qgsnativealgorithms.cpp +++ b/src/analysis/processing/qgsnativealgorithms.cpp @@ -137,6 +137,7 @@ #include "qgsalgorithmrenamelayer.h" #include "qgsalgorithmrenametablefield.h" #include "qgsalgorithmrepairshapefile.h" +#include "qgsalgorithmrescaleraster.h" #include "qgsalgorithmreverselinedirection.h" #include "qgsalgorithmrotate.h" #include "qgsalgorithmroundrastervalues.h" @@ -371,6 +372,7 @@ void QgsNativeAlgorithms::loadAlgorithms() addAlgorithm( new QgsRenameLayerAlgorithm() ); addAlgorithm( new QgsRenameTableFieldAlgorithm() ); addAlgorithm( new QgsRepairShapefileAlgorithm() ); + addAlgorithm( new QgsRescaleRasterAlgorithm() ); addAlgorithm( new QgsReverseLineDirectionAlgorithm() ); addAlgorithm( new QgsRotateFeaturesAlgorithm() ); addAlgorithm( new QgsRoundRasterValuesAlgorithm() ); diff --git a/src/app/3d/qgs3dmapconfigwidget.cpp b/src/app/3d/qgs3dmapconfigwidget.cpp index 2af05fb47d2d..8aba815eff89 100644 --- a/src/app/3d/qgs3dmapconfigwidget.cpp +++ b/src/app/3d/qgs3dmapconfigwidget.cpp @@ -102,6 +102,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas chkShowTileInfo->setChecked( mMap->showTerrainTilesInfo() ); chkShowBoundingBoxes->setChecked( mMap->showTerrainBoundingBoxes() ); chkShowCameraViewCenter->setChecked( mMap->showCameraViewCenter() ); + chkShowLightSourceOrigins->setChecked( mMap->showLightSourceOrigins() ); groupTerrainShading->setChecked( mMap->isTerrainShadingEnabled() ); widgetTerrainMaterial->setDiffuseVisible( false ); @@ -222,7 +223,7 @@ void Qgs3DMapConfigWidget::apply() mMap->setShowTerrainTilesInfo( chkShowTileInfo->isChecked() ); mMap->setShowTerrainBoundingBoxes( chkShowBoundingBoxes->isChecked() ); mMap->setShowCameraViewCenter( chkShowCameraViewCenter->isChecked() ); - + mMap->setShowLightSourceOrigins( chkShowLightSourceOrigins->isChecked() ); mMap->setTerrainShadingEnabled( groupTerrainShading->isChecked() ); mMap->setTerrainShadingMaterial( widgetTerrainMaterial->material() ); diff --git a/src/app/3d/qgs3dmaptoolmeasureline.cpp b/src/app/3d/qgs3dmaptoolmeasureline.cpp index 1a34c5d41d64..c0e11ad75ec2 100644 --- a/src/app/3d/qgs3dmaptoolmeasureline.cpp +++ b/src/app/3d/qgs3dmaptoolmeasureline.cpp @@ -88,6 +88,7 @@ void Qgs3DMapToolMeasureLine::activate() // Initialize the line layer QString mapCRS = mCanvas->map()->crs().authid(); mMeasurementLayer = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=" ) + mapCRS, QStringLiteral( "Measurement" ), QStringLiteral( "memory" ) ); + QgsProject::instance()->addMapLayer( mMeasurementLayer ); // Add feature to layer mMeasurementLayer->startEditing(); @@ -206,6 +207,7 @@ void Qgs3DMapToolMeasureLine::updateMeasurementLayer() QgsGeometryMap geometryMap; geometryMap.insert( 1, lineGeometry ); mMeasurementLayer->dataProvider()->changeGeometryValues( geometryMap ); + mMeasurementLayer->reload(); mCanvas->map()->setRenderers( QList() << mMeasurementLayer->renderer3D()->clone() ); } diff --git a/src/app/3d/qgs3dmodelsourcelineedit.cpp b/src/app/3d/qgs3dmodelsourcelineedit.cpp new file mode 100644 index 000000000000..bd51f5dd414c --- /dev/null +++ b/src/app/3d/qgs3dmodelsourcelineedit.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + qgs3dmodelsourcelineedit.cpp + ----------------------- + begin : July 2020 + copyright : (C) 2020 by Mathieu Pellerin + email : nirvn dot asia at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgs3dmodelsourcelineedit.h" + +// +// Qgs3DModelSourceLineEdit +// + +///@cond PRIVATE + +QString Qgs3DModelSourceLineEdit::fileFilter() const +{ + return tr( "All files" ) + " (*.*)"; +} + +QString Qgs3DModelSourceLineEdit::selectFileTitle() const +{ + return tr( "Select 3D Model File" ); +} + +QString Qgs3DModelSourceLineEdit::fileFromUrlTitle() const +{ + return tr( "3D Model From URL" ); +} + +QString Qgs3DModelSourceLineEdit::fileFromUrlText() const +{ + return tr( "Enter 3D Model URL" ); +} + +QString Qgs3DModelSourceLineEdit::embedFileTitle() const +{ + return tr( "Embed 3D Model File" ); +} + +QString Qgs3DModelSourceLineEdit::extractFileTitle() const +{ + return tr( "Extract 3D Model File" ); +} + +QString Qgs3DModelSourceLineEdit::defaultSettingsKey() const +{ + return QStringLiteral( "/UI/last3DModelDir" ); +} + +///@endcond diff --git a/src/app/3d/qgs3dmodelsourcelineedit.h b/src/app/3d/qgs3dmodelsourcelineedit.h new file mode 100644 index 000000000000..41649176a3d7 --- /dev/null +++ b/src/app/3d/qgs3dmodelsourcelineedit.h @@ -0,0 +1,57 @@ +/*************************************************************************** + qgs3dmodelsourcelineedit.h + --------------------- + begin : July 2020 + copyright : (C) 2020 by Mathieu Pellerin + email : nirvn dot asia at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGS3DMODELSOURCELINEEDIT_H +#define QGS3DMODELSOURCELINEEDIT_H + +#include "qgsfilecontentsourcelineedit.h" + +#include + +/** + * \class Qgs3DModelSourceLineEdit + * A line edit widget with toolbutton for setting a 3D model source path. + * + * Designed for use with QgsSourceCache. + * + * \since QGIS 3.16 + */ +class Qgs3DModelSourceLineEdit : public QgsAbstractFileContentSourceLineEdit +{ + Q_OBJECT + public: + + /** + * Constructor for Qgs3DModelSourceLineEdit, with the specified \a parent widget. + */ + Qgs3DModelSourceLineEdit( QWidget *parent SIP_TRANSFERTHIS = nullptr ) + : QgsAbstractFileContentSourceLineEdit( parent ) + {} + + private: +#ifndef SIP_RUN +///@cond PRIVATE + QString fileFilter() const override; + QString selectFileTitle() const override; + QString fileFromUrlTitle() const override; + QString fileFromUrlText() const override; + QString embedFileTitle() const override; + QString extractFileTitle() const override; + QString defaultSettingsKey() const override; +///@endcond +#endif +}; + +#endif // QGS3DMODELSOURCELINEEDIT_H diff --git a/src/app/3d/qgsphongmaterialwidget.cpp b/src/app/3d/qgsphongmaterialwidget.cpp index 5398775e632d..bd6df4873435 100644 --- a/src/app/3d/qgsphongmaterialwidget.cpp +++ b/src/app/3d/qgsphongmaterialwidget.cpp @@ -24,11 +24,18 @@ QgsPhongMaterialWidget::QgsPhongMaterialWidget( QWidget *parent ) setupUi( this ); setMaterial( QgsPhongMaterialSettings() ); + textureScaleSpinBox->setClearValue( 0 ); + textureRotationSpinBox->setClearValue( 0 ); connect( btnDiffuse, &QgsColorButton::colorChanged, this, &QgsPhongMaterialWidget::changed ); connect( btnAmbient, &QgsColorButton::colorChanged, this, &QgsPhongMaterialWidget::changed ); connect( btnSpecular, &QgsColorButton::colorChanged, this, &QgsPhongMaterialWidget::changed ); connect( spinShininess, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPhongMaterialWidget::changed ); + connect( useDiffuseCheckBox, &QCheckBox::stateChanged, this, &QgsPhongMaterialWidget::changed ); + connect( textureFile, &QgsImageSourceLineEdit::sourceChanged, this, &QgsPhongMaterialWidget::changed ); + connect( textureScaleSpinBox, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPhongMaterialWidget::changed ); + connect( textureRotationSpinBox, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPhongMaterialWidget::changed ); + this->activateTexturingUI( false ); } void QgsPhongMaterialWidget::setDiffuseVisible( bool visible ) @@ -48,6 +55,10 @@ void QgsPhongMaterialWidget::setMaterial( const QgsPhongMaterialSettings &materi btnAmbient->setColor( material.ambient() ); btnSpecular->setColor( material.specular() ); spinShininess->setValue( material.shininess() ); + useDiffuseCheckBox->setCheckState( material.diffuseTextureEnabled() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked ); + textureFile->setSource( material.texturePath() ); + textureScaleSpinBox->setValue( material.textureScale() ); + textureRotationSpinBox->setValue( material.textureRotation() ); } QgsPhongMaterialSettings QgsPhongMaterialWidget::material() const @@ -57,5 +68,19 @@ QgsPhongMaterialSettings QgsPhongMaterialWidget::material() const m.setAmbient( btnAmbient->color() ); m.setSpecular( btnSpecular->color() ); m.setShininess( spinShininess->value() ); + m.setDiffuseTextureEnabled( useDiffuseCheckBox->checkState() == Qt::CheckState::Checked ); + m.setTexturePath( textureFile->source() ); + m.setTextureScale( textureScaleSpinBox->value() ); + m.setTextureRotation( textureRotationSpinBox->value() ); return m; } + +void QgsPhongMaterialWidget::activateTexturingUI( bool activated ) +{ + lblTextureScale->setVisible( activated ); + lblTextureRotation->setVisible( activated ); + textureScaleSpinBox->setVisible( activated ); + textureRotationSpinBox->setVisible( activated ); + useDiffuseCheckBox->setVisible( activated ); + textureFile->setVisible( activated ); +} diff --git a/src/app/3d/qgsphongmaterialwidget.h b/src/app/3d/qgsphongmaterialwidget.h index 596e298362be..1e4d1639c437 100644 --- a/src/app/3d/qgsphongmaterialwidget.h +++ b/src/app/3d/qgsphongmaterialwidget.h @@ -36,6 +36,8 @@ class QgsPhongMaterialWidget : public QWidget, private Ui::PhongMaterialWidget void setMaterial( const QgsPhongMaterialSettings &material ); QgsPhongMaterialSettings material() const; + //! activates the texturing UI (to make sure texturing UI isn't visible when the user doesn't need it like in the 3D configuration window) + void activateTexturingUI( bool activated ); signals: void changed(); diff --git a/src/app/3d/qgspoint3dsymbolwidget.cpp b/src/app/3d/qgspoint3dsymbolwidget.cpp index 95db34f84e74..4bb84b73f089 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.cpp +++ b/src/app/3d/qgspoint3dsymbolwidget.cpp @@ -63,8 +63,7 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) const auto constSpinWidgets = spinWidgets; for ( QDoubleSpinBox *spinBox : constSpinWidgets ) connect( spinBox, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPoint3DSymbolWidget::changed ); - connect( lineEditModel, static_cast( &QLineEdit::textChanged ), this, &QgsPoint3DSymbolWidget::changed ); - connect( btnModel, static_cast( &QToolButton::clicked ), this, &QgsPoint3DSymbolWidget::onChooseModelClicked ); + connect( lineEditModel, &QgsAbstractFileContentSourceLineEdit::sourceChanged, this, &QgsPoint3DSymbolWidget::changed ); connect( cbOverwriteMaterial, static_cast( &QCheckBox::stateChanged ), this, &QgsPoint3DSymbolWidget::onOverwriteMaterialChecked ); connect( widgetMaterial, &QgsPhongMaterialWidget::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( btnChangeSymbol, static_cast( &QgsSymbolButton::changed ), this, &QgsPoint3DSymbolWidget::changed ); @@ -74,29 +73,6 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) connect( spinTY, static_cast( &QDoubleSpinBox::valueChanged ), spinBillboardHeight, &QDoubleSpinBox::setValue ); } -void QgsPoint3DSymbolWidget::onChooseModelClicked( bool ) -{ - QgsSettings s; - QString lastDir = s.value( QStringLiteral( "/UI/lastModel3dDir" ), QDir::homePath() ).toString(); - - QString filePath = QFileDialog::getOpenFileName( this, tr( "Open 3d Model File" ), lastDir, QStringLiteral( "3D models (*.*)" ) ); - if ( filePath.isEmpty() ) - { - return; - } - - //check if file exists - QFileInfo fileInfo( filePath ); - if ( !fileInfo.exists() || !fileInfo.isReadable() ) - { - QMessageBox::critical( nullptr, tr( "Invalid File" ), tr( "Error, file does not exist or is not readable." ) ); - return; - } - - s.setValue( QStringLiteral( "/UI/lastModel3dDir" ), fileInfo.absolutePath() ); - lineEditModel->setText( filePath ); -} - void QgsPoint3DSymbolWidget::onOverwriteMaterialChecked( int state ) { if ( state == Qt::Checked ) @@ -144,7 +120,7 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsPoint3DSymbol &symbol ) break; case 6: // 3d model { - lineEditModel->setText( vm[QStringLiteral( "model" )].toString() ); + lineEditModel->setSource( vm[QStringLiteral( "model" )].toString() ); bool overwriteMaterial = vm[QStringLiteral( "overwriteMaterial" )].toBool(); widgetMaterial->setEnabled( overwriteMaterial ); cbOverwriteMaterial->setChecked( overwriteMaterial ); @@ -219,7 +195,7 @@ QgsPoint3DSymbol QgsPoint3DSymbolWidget::symbol() const vm[QStringLiteral( "minorRadius" )] = spinMinorRadius->value(); break; case 6: // 3d model - vm[QStringLiteral( "model" )] = lineEditModel->text(); + vm[QStringLiteral( "model" )] = lineEditModel->source(); vm[QStringLiteral( "overwriteMaterial" )] = cbOverwriteMaterial->isChecked(); break; case 7: // billboard @@ -253,7 +229,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius << labelLength << spinLength - << labelModel << lineEditModel << btnModel << cbOverwriteMaterial + << labelModel << lineEditModel << cbOverwriteMaterial << labelBillboardHeight << spinBillboardHeight << labelBillboardSymbol << btnChangeSymbol; widgetMaterial->setEnabled( true ); @@ -281,7 +257,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() activeWidgets << labelRadius << spinRadius << labelMinorRadius << spinMinorRadius; break; case 6: // 3d model - activeWidgets << labelModel << lineEditModel << btnModel << cbOverwriteMaterial; + activeWidgets << labelModel << lineEditModel << cbOverwriteMaterial; widgetMaterial->setEnabled( cbOverwriteMaterial->isChecked() ); break; case 7: // billboard diff --git a/src/app/3d/qgspoint3dsymbolwidget.h b/src/app/3d/qgspoint3dsymbolwidget.h index 082efc8ff422..5b297626c940 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.h +++ b/src/app/3d/qgspoint3dsymbolwidget.h @@ -37,7 +37,6 @@ class QgsPoint3DSymbolWidget : public QWidget, private Ui::Point3DSymbolWidget private slots: void onShapeChanged(); - void onChooseModelClicked( bool checked = false ); void onOverwriteMaterialChecked( int state ); }; diff --git a/src/app/3d/qgspolygon3dsymbolwidget.cpp b/src/app/3d/qgspolygon3dsymbolwidget.cpp index d8f8277d32a7..d52689c2fa61 100644 --- a/src/app/3d/qgspolygon3dsymbolwidget.cpp +++ b/src/app/3d/qgspolygon3dsymbolwidget.cpp @@ -32,6 +32,7 @@ QgsPolygon3DSymbolWidget::QgsPolygon3DSymbolWidget( QWidget *parent ) connect( cboAltClamping, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPolygon3DSymbolWidget::changed ); connect( cboAltBinding, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPolygon3DSymbolWidget::changed ); connect( cboCullingMode, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPolygon3DSymbolWidget::changed ); + connect( cboRenderedFacade, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPolygon3DSymbolWidget::changed ); connect( chkAddBackFaces, &QCheckBox::clicked, this, &QgsPolygon3DSymbolWidget::changed ); connect( chkInvertNormals, &QCheckBox::clicked, this, &QgsPolygon3DSymbolWidget::changed ); connect( widgetMaterial, &QgsPhongMaterialWidget::changed, this, &QgsPolygon3DSymbolWidget::changed ); @@ -40,6 +41,8 @@ QgsPolygon3DSymbolWidget::QgsPolygon3DSymbolWidget( QWidget *parent ) connect( groupEdges, &QGroupBox::clicked, this, &QgsPolygon3DSymbolWidget::changed ); connect( btnEdgeColor, &QgsColorButton::colorChanged, this, &QgsPolygon3DSymbolWidget::changed ); connect( spinEdgeWidth, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPolygon3DSymbolWidget::changed ); + + widgetMaterial->activateTexturingUI( true ); } void QgsPolygon3DSymbolWidget::setSymbol( const QgsPolygon3DSymbol &symbol, QgsVectorLayer *layer ) @@ -49,6 +52,8 @@ void QgsPolygon3DSymbolWidget::setSymbol( const QgsPolygon3DSymbol &symbol, QgsV cboAltClamping->setCurrentIndex( static_cast( symbol.altitudeClamping() ) ); cboAltBinding->setCurrentIndex( static_cast( symbol.altitudeBinding() ) ); cboCullingMode->setCurrentIndex( static_cast( symbol.cullingMode() ) ); + cboRenderedFacade->setCurrentIndex( symbol.renderedFacade() ); + chkAddBackFaces->setChecked( symbol.addBackFaces() ); chkInvertNormals->setChecked( symbol.invertNormals() ); widgetMaterial->setMaterial( symbol.material() ); @@ -69,6 +74,7 @@ QgsPolygon3DSymbol QgsPolygon3DSymbolWidget::symbol() const sym.setAltitudeClamping( static_cast( cboAltClamping->currentIndex() ) ); sym.setAltitudeBinding( static_cast( cboAltBinding->currentIndex() ) ); sym.setCullingMode( static_cast( cboCullingMode->currentIndex() ) ); + sym.setRenderedFacade( cboRenderedFacade->currentIndex() ); sym.setAddBackFaces( chkAddBackFaces->isChecked() ); sym.setInvertNormals( chkInvertNormals->isChecked() ); sym.setMaterial( widgetMaterial->material() ); diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 65feaffc4871..bfed52d3977b 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -268,6 +268,7 @@ IF (WITH_3D) 3d/qgs3dmaptoolidentify.cpp 3d/qgs3dmaptoolmeasureline.cpp 3d/qgs3dmeasuredialog.cpp + 3d/qgs3dmodelsourcelineedit.cpp 3d/qgs3dnavigationwidget.cpp 3d/qgslightswidget.cpp 3d/qgsline3dsymbolwidget.cpp diff --git a/src/app/browser/qgsinbuiltdataitemproviders.cpp b/src/app/browser/qgsinbuiltdataitemproviders.cpp index 6d6898a26f9c..a3807322b82b 100644 --- a/src/app/browser/qgsinbuiltdataitemproviders.cpp +++ b/src/app/browser/qgsinbuiltdataitemproviders.cpp @@ -37,13 +37,18 @@ #include "processing/qgsprojectstylealgorithms.h" #include "qgsstylemanagerdialog.h" #include "qgsproviderregistry.h" +#include "qgsaddattrdialog.h" +#include "qgsabstractdatabaseproviderconnection.h" +#include "qgsprovidermetadata.h" +#include "qgsnewvectortabledialog.h" +#include "qgsdataitemproviderregistry.h" #include #include #include -#include #include #include +#include QString QgsAppDirectoryItemGuiProvider::name() { @@ -72,11 +77,11 @@ void QgsAppDirectoryItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe QDir dir( directoryItem->dirPath() ); if ( QFileInfo::exists( dir.absoluteFilePath( name ) ) ) { - QMessageBox::critical( QgisApp::instance(), tr( "Create Directory" ), tr( "The path “%1” already exists." ).arg( QDir::toNativeSeparators( dir.absoluteFilePath( name ) ) ) ); + notify( tr( "Create Directory" ), tr( "The path “%1” already exists." ).arg( QDir::toNativeSeparators( dir.absoluteFilePath( name ) ) ), context, Qgis::MessageLevel::Warning ); } else if ( !dir.mkdir( name ) ) { - QMessageBox::critical( QgisApp::instance(), tr( "Create Directory" ), tr( "Could not create directory “%1”." ).arg( QDir::toNativeSeparators( dir.absoluteFilePath( name ) ) ) ); + notify( tr( "Create Directory" ), tr( "Could not create directory “%1”." ).arg( QDir::toNativeSeparators( dir.absoluteFilePath( name ) ) ), context, Qgis::MessageLevel::Critical ); } else { @@ -594,7 +599,7 @@ void QgsLayerItemGuiProvider::deleteLayers( const QStringList &itemPaths, QgsDat Q_NOWARN_DEPRECATED_POP if ( !res ) - QMessageBox::information( QgisApp::instance(), tr( "Delete Layer" ), tr( "Item Layer %1 cannot be deleted." ).arg( item->name() ) ); + notify( tr( "Delete Layer" ), tr( "Item Layer %1 cannot be deleted." ).arg( item->name() ), context, Qgis::MessageLevel::Warning ); } } } @@ -688,3 +693,232 @@ bool QgsProjectItemGuiProvider::handleDoubleClick( QgsDataItem *item, QgsDataIte return false; } } + +QString QgsFieldsItemGuiProvider::name() +{ + return QStringLiteral( "fields_item" ); +} + +void QgsFieldsItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &selectedItems, QgsDataItemGuiContext context ) +{ + Q_UNUSED( selectedItems ) + + if ( !item || item->type() != QgsDataItem::Type::Fields ) + return; + + + if ( QgsFieldsItem *fieldsItem = qobject_cast( item ) ) + { + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( fieldsItem->providerKey() ) }; + if ( md ) + { + std::unique_ptr conn { static_cast( md->createConnection( fieldsItem->connectionUri(), {} ) ) }; + // Check if it is supported + if ( conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::AddField ) ) + { + QAction *addColumnAction = new QAction( tr( "Add New Field…" ), menu ); + QPointeritemPtr { item }; + const QString itemName { item->name() }; + + connect( addColumnAction, &QAction::triggered, fieldsItem, [ md, fieldsItem, context, itemPtr, menu ] + { + std::unique_ptr layer { fieldsItem->layer() }; + if ( layer ) + { + QgsAddAttrDialog dialog( layer.get(), menu ); + if ( dialog.exec() == QDialog::Accepted ) + { + std::unique_ptr conn2 { static_cast( md->createConnection( fieldsItem->connectionUri(), {} ) ) }; + try + { + conn2->addField( dialog.field(), fieldsItem->schema(), fieldsItem->tableName() ); + if ( itemPtr ) + itemPtr->refresh(); + } + catch ( const QgsProviderConnectionException &ex ) + { + notify( tr( "New Field" ), tr( "Failed to add the new field to '%1': %2" ).arg( fieldsItem->tableName(), ex.what() ), context, Qgis::MessageLevel::Critical ); + } + } + } + else + { + notify( tr( "New Field" ), tr( "Failed to load layer'%1'. Check application logs and user permissions." ).arg( fieldsItem->tableName() ), context, Qgis::MessageLevel::Critical ); + } + } ); + menu->addAction( addColumnAction ); + } + } + } +} + +QString QgsFieldItemGuiProvider::name() +{ + return QStringLiteral( "field_item" ); +} + +void QgsFieldItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &selectedItems, QgsDataItemGuiContext context ) +{ + Q_UNUSED( selectedItems ) + + if ( !item || item->type() != QgsDataItem::Type::Field ) + return; + + if ( QgsFieldItem *fieldItem = qobject_cast( item ) ) + { + // Retrieve the connection from the parent + QgsFieldsItem *fieldsItem { static_cast( fieldItem->parent() ) }; + if ( fieldsItem ) + { + // Check if it is supported + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( fieldsItem->providerKey() ) }; + if ( md ) + { + std::unique_ptr conn { static_cast( md->createConnection( fieldsItem->connectionUri(), {} ) ) }; + if ( conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::DeleteField ) ) + { + QAction *deleteFieldAction = new QAction( tr( "Delete Field…" ), menu ); + const bool supportsCascade { conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::DeleteFieldCascade ) }; + const QString itemName { item->name() }; + + connect( deleteFieldAction, &QAction::triggered, fieldsItem, [ md, fieldsItem, itemName, context, supportsCascade ] + { + // Confirmation dialog + QMessageBox msgbox{QMessageBox::Icon::Question, tr( "Delete Field" ), tr( "Delete '%1' permanently?" ).arg( itemName ), QMessageBox::Ok | QMessageBox::Cancel }; + QCheckBox *cb = new QCheckBox( tr( "Delete all related objects (CASCADE)?" ) ); + msgbox.setCheckBox( cb ); + msgbox.setDefaultButton( QMessageBox::Cancel ); + + if ( ! supportsCascade ) + { + cb->hide(); + } + + if ( msgbox.exec() == QMessageBox::Ok ) + { + std::unique_ptr conn2 { static_cast( md->createConnection( fieldsItem->connectionUri(), {} ) ) }; + try + { + conn2->deleteField( itemName, fieldsItem->schema(), fieldsItem->tableName(), supportsCascade && cb->isChecked() ); + fieldsItem->refresh(); + } + catch ( const QgsProviderConnectionException &ex ) + { + notify( tr( "Delete Field" ), tr( "Failed to delete field '%1': %2" ).arg( itemName, ex.what() ), context, Qgis::MessageLevel::Critical ); + } + } + } ); + menu->addAction( deleteFieldAction ); + } + } + } + else + { + // This should never happen! + QgsDebugMsg( QStringLiteral( "Error getting parent fields for %1" ).arg( item->name() ) ); + } + } +} + +QString QgsDatabaseItemGuiProvider::name() +{ + return QStringLiteral( "database" ); +} + +void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &selectedItems, QgsDataItemGuiContext context ) +{ + Q_UNUSED( selectedItems ) + // Add create new table for collection items but not not if it is a root item + if ( ! qobject_cast( item ) ) + { + if ( QgsDataCollectionItem * collectionItem { qobject_cast( item ) } ) + { + // This is super messy: we need the QgsDataProvider key and NOT the QgsDataItemProvider key! + const QString dataProviderKey { QgsApplication::dataItemProviderRegistry()->dataProviderKey( collectionItem->providerKey() ) }; + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( dataProviderKey ) }; + if ( md ) + { + // Note: we could have used layerCollection() but casting to QgsDatabaseSchemaItem is more explicit + const bool isSchema { qobject_cast( item ) != nullptr }; + const QString connectionName { isSchema ? collectionItem->parent()->name() : collectionItem->name() }; + std::unique_ptr conn( static_cast( md->createConnection( connectionName ) ) ); + if ( conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateVectorTable ) ) + { + QAction *newTableAction = new QAction( QObject::tr( "New Table…" ), menu ); + QObject::connect( newTableAction, &QAction::triggered, collectionItem, [ collectionItem, connectionName, md, isSchema, context] + { + std::unique_ptr conn2 { static_cast( md->createConnection( connectionName ) ) }; + QgsNewVectorTableDialog dlg { conn2.get(), nullptr }; + dlg.setCrs( QgsProject::instance()->defaultCrsForNewLayers() ); + if ( isSchema ) + { + dlg.setSchemaName( collectionItem->name() ); + } + if ( dlg.exec() == QgsNewVectorTableDialog::DialogCode::Accepted ) + { + const QgsFields fields { dlg.fields() }; + const QString tableName { dlg.tableName() }; + const QString schemaName { dlg.schemaName() }; + const QString geometryColumn { dlg.geometryColumnName() }; + const QgsWkbTypes::Type geometryType { dlg.geometryType() }; + const bool createSpatialIndex { dlg.createSpatialIndex() && + geometryType != QgsWkbTypes::NoGeometry && + geometryType != QgsWkbTypes::Unknown }; + const QgsCoordinateReferenceSystem crs { dlg.crs( ) }; + // This flag tells to the provider that field types do not need conversion + QMap options { { QStringLiteral( "skipConvertFields" ), true } }; + + if ( ! geometryColumn.isEmpty() ) + { + options[ QStringLiteral( "geometryColumn" ) ] = geometryColumn; + } + + try + { + conn2->createVectorTable( schemaName, tableName, fields, geometryType, crs, true, &options ); + if ( createSpatialIndex && conn2->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateSpatialIndex ) ) + { + try + { + conn2->createSpatialIndex( schemaName, tableName ); + } + catch ( QgsProviderConnectionException &ex ) + { + notify( QObject::tr( "Create Spatial Index" ), QObject::tr( "Could not create spatial index for table '%1':%2." ).arg( tableName, ex.what() ), context, Qgis::MessageLevel::Warning ); + } + } + // Ok, here is the trick: we cannot refresh the connection item because the refresh is not + // recursive. + // So, we check if the item is a schema or not, if it's not it means we initiated the new table from + // the parent connection item, hence we search for the schema item and refresh it instead of refreshing + // the connection item (the parent) with no effects. + if ( ! isSchema && conn2->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::Schemas ) ) + { + const auto constChildren { collectionItem->children() }; + for ( const auto &c : constChildren ) + { + if ( c->name() == schemaName ) + { + c->refresh(); + } + } + } + else + { + collectionItem->refresh( ); + } + notify( QObject::tr( "New Table Created" ), QObject::tr( "Table '%1' was created successfully." ).arg( tableName ), context, Qgis::MessageLevel::Success ); + } + catch ( QgsProviderConnectionException &ex ) + { + notify( QObject::tr( "New Table Creation Error" ), QObject::tr( "Error creating new table '%1': %2" ).arg( tableName, ex.what() ), context, Qgis::MessageLevel::Critical ); + } + + } + } ); + menu->addAction( newTableAction ); + } + } + } + } +} diff --git a/src/app/browser/qgsinbuiltdataitemproviders.h b/src/app/browser/qgsinbuiltdataitemproviders.h index 76ad988ef347..fab96d473688 100644 --- a/src/app/browser/qgsinbuiltdataitemproviders.h +++ b/src/app/browser/qgsinbuiltdataitemproviders.h @@ -25,6 +25,8 @@ class QgsDirectoryItem; class QgsFavoriteItem; class QgsLayerItem; +class QgsFieldsItem; +class QgsFieldItem; class QgsAppDirectoryItemGuiProvider : public QObject, public QgsDataItemGuiProvider { @@ -105,6 +107,55 @@ class QgsLayerItemGuiProvider : public QObject, public QgsDataItemGuiProvider }; +class QgsFieldsItemGuiProvider : public QObject, public QgsDataItemGuiProvider +{ + Q_OBJECT + + public: + + QgsFieldsItemGuiProvider() = default; + + QString name() override; + + void populateContextMenu( QgsDataItem *item, QMenu *menu, + const QList &selectedItems, QgsDataItemGuiContext context ) override; + +}; + + +class QgsFieldItemGuiProvider : public QObject, public QgsDataItemGuiProvider +{ + Q_OBJECT + + public: + + QgsFieldItemGuiProvider() = default; + + QString name() override; + + void populateContextMenu( QgsDataItem *item, QMenu *menu, + const QList &selectedItems, QgsDataItemGuiContext context ) override; + +}; + + +class QgsDatabaseItemGuiProvider : public QObject, public QgsDataItemGuiProvider +{ + Q_OBJECT + + public: + + QgsDatabaseItemGuiProvider() = default; + + QString name() override; + + void populateContextMenu( QgsDataItem *item, QMenu *menu, + const QList &selectedItems, QgsDataItemGuiContext context ) override; + +}; + + + class QgsProjectItemGuiProvider : public QObject, public QgsDataItemGuiProvider { Q_OBJECT diff --git a/src/app/georeferencer/qgsgeorefmainwindow.cpp b/src/app/georeferencer/qgsgeorefmainwindow.cpp index 9a74a1525553..532aa7fbb351 100644 --- a/src/app/georeferencer/qgsgeorefmainwindow.cpp +++ b/src/app/georeferencer/qgsgeorefmainwindow.cpp @@ -401,16 +401,26 @@ void QgsGeoreferencerMainWindow::generateGDALScript() void QgsGeoreferencerMainWindow::setAddPointTool() { mCanvas->setMapTool( mToolAddPoint ); + QgsMapTool *activeQgisMapTool = QgisApp::instance()->mapCanvas()->mapTool(); + if ( activeQgisMapTool == mToolMovePointQgis ) + QgisApp::instance()->mapCanvas()->setMapTool( mPrevQgisMapTool ); } void QgsGeoreferencerMainWindow::setDeletePointTool() { mCanvas->setMapTool( mToolDeletePoint ); + QgsMapTool *activeQgisMapTool = QgisApp::instance()->mapCanvas()->mapTool(); + if ( activeQgisMapTool == mToolMovePointQgis ) + QgisApp::instance()->mapCanvas()->setMapTool( mPrevQgisMapTool ); } void QgsGeoreferencerMainWindow::setMovePointTool() { mCanvas->setMapTool( mToolMovePoint ); + QgsMapTool *activeQgisMapTool = QgisApp::instance()->mapCanvas()->mapTool(); + if ( activeQgisMapTool == mToolMovePointQgis ) + return; + mPrevQgisMapTool = activeQgisMapTool; QgisApp::instance()->mapCanvas()->setMapTool( mToolMovePointQgis ); } @@ -1554,8 +1564,10 @@ bool QgsGeoreferencerMainWindow::writePDFReportFile( const QString &fileName, co QFont tableHeaderFont; tableHeaderFont.setPointSize( 9 ); tableHeaderFont.setBold( true ); + QgsTextFormat tableHeaderFormat = QgsTextFormat::fromQFont( tableHeaderFont ); QFont tableContentFont; tableContentFont.setPointSize( 9 ); + QgsTextFormat tableContentFormat = QgsTextFormat::fromQFont( tableContentFont ); QgsSettings s; double leftMargin = s.value( QStringLiteral( "/Plugin-GeoReferencer/Config/LeftMarginPDF" ), "2.0" ).toDouble(); @@ -1636,8 +1648,8 @@ bool QgsGeoreferencerMainWindow::writePDFReportFile( const QString &fileName, co calculateMeanError( meanError ); parameterTable = new QgsLayoutItemTextTable( &layout ); - parameterTable->setHeaderFont( tableHeaderFont ); - parameterTable->setContentFont( tableContentFont ); + parameterTable->setHeaderTextFormat( tableHeaderFormat ); + parameterTable->setContentTextFormat( tableContentFormat ); QgsLayoutTableColumns columns; columns << QgsLayoutTableColumn( tr( "Translation x" ) ) @@ -1679,8 +1691,8 @@ bool QgsGeoreferencerMainWindow::writePDFReportFile( const QString &fileName, co resPlotItem->setConvertScaleToMapUnits( residualUnits == tr( "map units" ) ); QgsLayoutItemTextTable *gcpTable = new QgsLayoutItemTextTable( &layout ); - gcpTable->setHeaderFont( tableHeaderFont ); - gcpTable->setContentFont( tableContentFont ); + gcpTable->setHeaderTextFormat( tableHeaderFormat ); + gcpTable->setContentTextFormat( tableContentFormat ); gcpTable->setHeaderMode( QgsLayoutTable::AllFrames ); QgsLayoutTableColumns columns; columns << QgsLayoutTableColumn( tr( "ID" ) ) diff --git a/src/app/georeferencer/qgsgeorefmainwindow.h b/src/app/georeferencer/qgsgeorefmainwindow.h index e9cc54a1feeb..ab268f704832 100644 --- a/src/app/georeferencer/qgsgeorefmainwindow.h +++ b/src/app/georeferencer/qgsgeorefmainwindow.h @@ -235,6 +235,7 @@ class QgsGeoreferencerMainWindow : public QMainWindow, private Ui::QgsGeorefPlug QgsMapTool *mToolZoomIn = nullptr; QgsMapTool *mToolZoomOut = nullptr; QgsMapTool *mToolPan = nullptr; + QgsMapTool *mPrevQgisMapTool = nullptr; QgsGeorefToolAddPoint *mToolAddPoint = nullptr; QgsGeorefToolDeletePoint *mToolDeletePoint = nullptr; QgsGeorefToolMovePoint *mToolMovePoint = nullptr; diff --git a/src/app/labeling/qgslabelpropertydialog.cpp b/src/app/labeling/qgslabelpropertydialog.cpp index 36c892c26c55..94ec71b65e95 100644 --- a/src/app/labeling/qgslabelpropertydialog.cpp +++ b/src/app/labeling/qgslabelpropertydialog.cpp @@ -203,6 +203,9 @@ void QgsLabelPropertyDialog::init( const QString &layerId, const QString &provid case QgsPalLayerSettings::MultiRight: defaultMultilineAlign = QStringLiteral( "right" ); break; + case QgsPalLayerSettings::MultiJustify: + defaultMultilineAlign = QStringLiteral( "justify" ); + break; case QgsPalLayerSettings::MultiFollowPlacement: defaultMultilineAlign = QStringLiteral( "follow label placement" ); break; @@ -592,6 +595,7 @@ void QgsLabelPropertyDialog::fillMultiLineAlignComboBox() mMultiLineAlignComboBox->addItem( tr( "Left" ), "Left" ); mMultiLineAlignComboBox->addItem( tr( "Center" ), "Center" ); mMultiLineAlignComboBox->addItem( tr( "Right" ), "Right" ); + mMultiLineAlignComboBox->addItem( tr( "Justify" ), "Justify" ); } void QgsLabelPropertyDialog::fillHaliComboBox() diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 41458f378268..eb5999bf95d5 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -1212,6 +1212,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsFavoritesItemGuiProvider() ); QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsLayerItemGuiProvider() ); QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsBookmarksItemGuiProvider() ); + QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsFieldsItemGuiProvider() ); + QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsFieldItemGuiProvider() ); + QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsDatabaseItemGuiProvider() ); QShortcut *showBrowserDock = new QShortcut( QKeySequence( tr( "Ctrl+2" ) ), this ); connect( showBrowserDock, &QShortcut::activated, mBrowserWidget, &QgsDockWidget::toggleUserVisible ); @@ -10100,6 +10103,14 @@ void QgisApp::cutSelectionToClipboard( QgsMapLayer *layerContainingSelection ) if ( !selectionVectorLayer ) return; + if ( !selectionVectorLayer->isEditable() ) + { + visibleMessageBar()->pushMessage( tr( "Layer not editable" ), + tr( "The current layer is not editable. Choose 'Start editing' in the digitizing toolbar." ), + Qgis::Info, messageTimeout() ); + return; + } + clipboard()->replaceWithCopyOf( selectionVectorLayer ); selectionVectorLayer->beginEditCommand( tr( "Features cut" ) ); @@ -10128,6 +10139,14 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer ) if ( !pasteVectorLayer ) return; + if ( !pasteVectorLayer->isEditable() ) + { + visibleMessageBar()->pushMessage( tr( "Layer not editable" ), + tr( "The current layer is not editable. Choose 'Start editing' in the digitizing toolbar." ), + Qgis::Info, messageTimeout() ); + return; + } + pasteVectorLayer->beginEditCommand( tr( "Features pasted" ) ); QgsFeatureList features = clipboard()->transformedCopyOf( pasteVectorLayer->crs(), pasteVectorLayer->fields() ); int nTotalFeatures = features.count(); @@ -10254,32 +10273,38 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer ) void QgisApp::pasteFeatures( QgsVectorLayer *pasteVectorLayer, int invalidGeometriesCount, int nTotalFeatures, QgsFeatureList &features ) { - pasteVectorLayer->addFeatures( features ); - QgsFeatureIds newIds; - newIds.reserve( features.size() ); - for ( const QgsFeature &f : qgis::as_const( features ) ) + int nCopiedFeatures = features.count(); + if ( pasteVectorLayer->addFeatures( features ) ) { - newIds << f.id(); - } + QgsFeatureIds newIds; + newIds.reserve( features.size() ); + for ( const QgsFeature &f : qgis::as_const( features ) ) + { + newIds << f.id(); + } - pasteVectorLayer->selectByIds( newIds ); + pasteVectorLayer->selectByIds( newIds ); + } + else + { + nCopiedFeatures = 0; + } pasteVectorLayer->endEditCommand(); pasteVectorLayer->updateExtents(); - int nCopiedFeatures = features.count(); Qgis::MessageLevel level = ( nCopiedFeatures == 0 || invalidGeometriesCount > 0 ) ? Qgis::Warning : Qgis::Info; QString message; if ( nCopiedFeatures == 0 ) { - message = tr( "No features could be successfully pasted." ); + message = tr( "No features pasted." ); } else if ( nCopiedFeatures == nTotalFeatures ) { - message = tr( "%1 features were successfully pasted." ).arg( nCopiedFeatures ); + message = tr( "%1 features were pasted." ).arg( nCopiedFeatures ); } else { - message = tr( "%1 of %2 features could be successfully pasted." ).arg( nCopiedFeatures ).arg( nTotalFeatures ); + message = tr( "%1 of %2 features could be pasted." ).arg( nCopiedFeatures ).arg( nTotalFeatures ); } // warn the user if the pasted features have invalid geometries diff --git a/src/app/qgsfeatureaction.cpp b/src/app/qgsfeatureaction.cpp index c5083d86a5d4..e402c3e98d7f 100644 --- a/src/app/qgsfeatureaction.cpp +++ b/src/app/qgsfeatureaction.cpp @@ -255,6 +255,8 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, boo dialog->setAttribute( Qt::WA_DeleteOnClose ); dialog->setMode( QgsAttributeEditorContext::AddFeatureMode ); dialog->setEditCommandMessage( text() ); + if ( scope ) + dialog->setExtraContextScope( new QgsExpressionContextScope( *scope ) ); connect( dialog->attributeForm(), &QgsAttributeForm::featureSaved, this, &QgsFeatureAction::onFeatureSaved ); diff --git a/src/app/qgsfixattributedialog.cpp b/src/app/qgsfixattributedialog.cpp index 8ae9a90b5791..d9349030f3f9 100644 --- a/src/app/qgsfixattributedialog.cpp +++ b/src/app/qgsfixattributedialog.cpp @@ -52,7 +52,7 @@ void QgsFixAttributeDialog::init( QgsVectorLayer *layer, const QgsAttributeEdito infoLayout->addWidget( mProgressBar ); QgsFeature feature; mAttributeForm = new QgsAttributeForm( layer, *mCurrentFeature, context, this ); - mAttributeForm->setMode( QgsAttributeEditorContext::SingleEditMode ); + mAttributeForm->setMode( QgsAttributeEditorContext::FixAttributeMode ); mAttributeForm->disconnectButtonBox(); layout()->addWidget( mAttributeForm ); diff --git a/src/app/qgshandlebadlayers.cpp b/src/app/qgshandlebadlayers.cpp index 9fa17ce11fb3..a31ec65cd8d1 100644 --- a/src/app/qgshandlebadlayers.cpp +++ b/src/app/qgshandlebadlayers.cpp @@ -589,7 +589,7 @@ void QgsHandleBadLayers::autoFind() // Try first to change the datasource of the existing layers, this will // maintain the current status (checked/unchecked) and group - if ( QgsProject::instance()->mapLayer( layerId ) ) + if ( !datasource.isEmpty() && QgsProject::instance()->mapLayer( layerId ) ) { QgsDataProvider::ProviderOptions options; QgsMapLayer *mapLayer = QgsProject::instance()->mapLayer( layerId ); diff --git a/src/app/qgsrelationadddlg.cpp b/src/app/qgsrelationadddlg.cpp index b16e394a5472..9ad73c137f85 100644 --- a/src/app/qgsrelationadddlg.cpp +++ b/src/app/qgsrelationadddlg.cpp @@ -239,6 +239,8 @@ QList< QPair< QString, QString > > QgsRelationAddDlg::references() QList< QPair< QString, QString > > references; for ( int i = 0; i < mFieldPairWidgets.count(); i++ ) { + if ( !mFieldPairWidgets.at( i )->isPairEnabled() ) + continue; QString referencingField = mFieldPairWidgets.at( i )->referencingField(); QString referencedField = mFieldPairWidgets.at( i )->referencedField(); references << qMakePair( referencingField, referencedField ); diff --git a/src/app/qgsrelationmanagerdialog.cpp b/src/app/qgsrelationmanagerdialog.cpp index dccb69e60818..8791b64d4807 100644 --- a/src/app/qgsrelationmanagerdialog.cpp +++ b/src/app/qgsrelationmanagerdialog.cpp @@ -138,7 +138,9 @@ void QgsRelationManagerDialog::mBtnAddRelation_clicked() ++suffix; } relation.setId( relationId ); - relation.addFieldPair( addDlg.references().at( 0 ).first, addDlg.references().at( 0 ).second ); + const auto references = addDlg.references(); + for ( const auto &reference : references ) + relation.addFieldPair( reference.first, reference.second ); relation.setName( addDlg.relationName() ); relation.setStrength( addDlg.relationStrength() ); diff --git a/src/auth/oauth2/oauth2_resources/close.svg b/src/auth/oauth2/oauth2_resources/close.svg index 7fa4f854fb35..efeec309acf1 100644 --- a/src/auth/oauth2/oauth2_resources/close.svg +++ b/src/auth/oauth2/oauth2_resources/close.svg @@ -1,55 +1 @@ - - - -image/svg+xml - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/auth/oauth2/oauth2_resources/export.svg b/src/auth/oauth2/oauth2_resources/export.svg index 44d76a65616e..d0b54a019055 100644 --- a/src/auth/oauth2/oauth2_resources/export.svg +++ b/src/auth/oauth2/oauth2_resources/export.svg @@ -1,447 +1 @@ - - - Export icon - - - - - - - image/svg+xml - - Export icon - - - - slarosa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/auth/oauth2/oauth2_resources/fileopen.svg b/src/auth/oauth2/oauth2_resources/fileopen.svg index 4868f15923a3..e2e6a202b72d 100644 --- a/src/auth/oauth2/oauth2_resources/fileopen.svg +++ b/src/auth/oauth2/oauth2_resources/fileopen.svg @@ -1,534 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/src/auth/oauth2/oauth2_resources/hidden.svg b/src/auth/oauth2/oauth2_resources/hidden.svg index a16c5dcb24be..5ab9b0ae41d0 100644 --- a/src/auth/oauth2/oauth2_resources/hidden.svg +++ b/src/auth/oauth2/oauth2_resources/hidden.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/src/auth/oauth2/oauth2_resources/import.svg b/src/auth/oauth2/oauth2_resources/import.svg index 344f346e5b0f..a9c703949fa9 100644 --- a/src/auth/oauth2/oauth2_resources/import.svg +++ b/src/auth/oauth2/oauth2_resources/import.svg @@ -1,447 +1 @@ - - - Import icon - - - - - - - image/svg+xml - - Import icon - - - slarosa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/auth/oauth2/oauth2_resources/visible.svg b/src/auth/oauth2/oauth2_resources/visible.svg index 2e2ae67142ff..592565c5e789 100644 --- a/src/auth/oauth2/oauth2_resources/visible.svg +++ b/src/auth/oauth2/oauth2_resources/visible.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/src/auth/oauth2/oauth2_resources/visible_red.svg b/src/auth/oauth2/oauth2_resources/visible_red.svg index d7005cf47ea7..cd77b0483ec0 100644 --- a/src/auth/oauth2/oauth2_resources/visible_red.svg +++ b/src/auth/oauth2/oauth2_resources/visible_red.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 87c4518978b7..c3605fd2393c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -409,6 +409,7 @@ SET(QGIS_CORE_SRCS qgssqliteexpressioncompiler.cpp qgssqlstatement.cpp qgssqliteutils.cpp + qgssourcecache.cpp qgsspatialiteutils.cpp qgsstatisticalsummary.cpp qgsstoredexpressionmanager.cpp @@ -966,6 +967,7 @@ SET(QGIS_CORE_HDRS qgsspatialindexkdbush.h qgsspatialindexkdbushdata.h qgsspatialindexutils.h + qgssourcecache.h qgsspatialiteutils.h qgssqlexpressioncompiler.h qgssqliteutils.h diff --git a/src/core/diagram/qgsstackedbardiagram.cpp b/src/core/diagram/qgsstackedbardiagram.cpp index 62cc3f54ca67..46cec6ee5559 100644 --- a/src/core/diagram/qgsstackedbardiagram.cpp +++ b/src/core/diagram/qgsstackedbardiagram.cpp @@ -17,6 +17,7 @@ #include "qgsdiagramrenderer.h" #include "qgsrendercontext.h" #include "qgsexpression.h" +#include "qgssymbollayerutils.h" #include @@ -88,6 +89,13 @@ QSizeF QgsStackedBarDiagram::diagramSize( const QgsFeature &feature, const QgsRe } } + if ( s.showAxis() && s.axisLineSymbol() ) + { + const double maxBleed = QgsSymbolLayerUtils::estimateMaxSymbolBleed( s.axisLineSymbol(), c ) / painterUnitConversionScale; + size.setWidth( size.width() + 2 * maxBleed ); + size.setHeight( size.height() + 2 * maxBleed ); + } + return size; } @@ -201,6 +209,15 @@ void QgsStackedBarDiagram::renderDiagram( const QgsFeature &feature, QgsRenderCo double baseX = position.x(); double baseY = position.y(); + if ( s.showAxis() && s.axisLineSymbol() ) + { + // if showing axis, the diagram position needs shifting from the default base x so that the axis + // line stroke sits within the desired label engine rect (otherwise we risk overlaps of the axis line stroke) + const double maxBleed = QgsSymbolLayerUtils::estimateMaxSymbolBleed( s.axisLineSymbol(), c ); + baseX += maxBleed; + baseY -= maxBleed; + } + mPen.setColor( s.penColor ); setPenWidth( mPen, s, c ); p->setPen( mPen ); @@ -235,4 +252,35 @@ void QgsStackedBarDiagram::renderDiagram( const QgsFeature &feature, QgsRenderCo currentOffset += length + spacing; } + + if ( s.showAxis() && s.axisLineSymbol() ) + { + s.axisLineSymbol()->startRender( c ); + QPolygonF axisPoints; + switch ( s.diagramOrientation ) + { + case QgsDiagramSettings::Up: + axisPoints << QPointF( baseX, baseY - scaledMaxVal - spacing * std::max( 0, values.size() - 1 ) ) << QPointF( baseX, baseY ) << QPointF( baseX + scaledWidth, baseY ); + break; + + case QgsDiagramSettings::Down: + axisPoints << QPointF( baseX, baseY ) << QPointF( baseX, baseY - scaledMaxVal - spacing * std::max( 0, values.size() - 1 ) ) << QPointF( baseX + scaledWidth, baseY - scaledMaxVal - spacing * std::max( 0, values.size() - 1 ) ); + break; + + case QgsDiagramSettings::Right: + axisPoints << QPointF( baseX + scaledMaxVal + spacing * std::max( 0, values.size() - 1 ), baseY - scaledWidth ) + << QPointF( baseX, baseY - scaledWidth ) + << QPointF( baseX, baseY ); + break; + + case QgsDiagramSettings::Left: + axisPoints << QPointF( baseX, baseY - scaledWidth ) + << QPointF( baseX + scaledMaxVal + spacing * std::max( 0, values.size() - 1 ), baseY - scaledWidth ) + << QPointF( baseX + scaledMaxVal + spacing * std::max( 0, values.size() - 1 ), baseY ); + break; + } + + s.axisLineSymbol()->renderPolyline( axisPoints, nullptr, c ); + s.axisLineSymbol()->stopRender( c ); + } } diff --git a/src/core/expression/qgsexpression.cpp b/src/core/expression/qgsexpression.cpp index 5f99fb3879dc..ca0e5521bf91 100644 --- a/src/core/expression/qgsexpression.cpp +++ b/src/core/expression/qgsexpression.cpp @@ -793,6 +793,7 @@ void QgsExpression::initVariableHelp() sVariableHelpTexts()->insert( QStringLiteral( "row_number" ), QCoreApplication::translate( "variable_help", "Stores the number of the current row." ) ); sVariableHelpTexts()->insert( QStringLiteral( "grid_number" ), QCoreApplication::translate( "variable_help", "Current grid annotation value." ) ); sVariableHelpTexts()->insert( QStringLiteral( "grid_axis" ), QCoreApplication::translate( "variable_help", "Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) ); + sVariableHelpTexts()->insert( QStringLiteral( "column_number" ), QCoreApplication::translate( "variable_help", "Stores the number of the current column." ) ); // map canvas item variables sVariableHelpTexts()->insert( QStringLiteral( "canvas_cursor_point" ), QCoreApplication::translate( "variable_help", "Last cursor position on the canvas in the project's geographical coordinates." ) ); diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp index f83570d5b1cd..4f09311537ba 100644 --- a/src/core/expression/qgsexpressionfunction.cpp +++ b/src/core/expression/qgsexpressionfunction.cpp @@ -3853,6 +3853,25 @@ static QVariant fcnOrientedBBox( const QVariantList &values, const QgsExpression return result; } +static QVariant fcnMainAngle( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) +{ + const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent ); + + // we use the angle of the oriented minimum bounding box to calculate the polygon main angle. + // While ArcGIS uses a different approach ("the angle of longest collection of segments that have similar orientation"), this + // yields similar results to OMBB approach under the same constraints ("this tool is meant for primarily orthogonal polygons rather than organically shaped ones.") + + double area, angle, width, height; + const QgsGeometry geom = fGeom.orientedMinimumBoundingBox( area, angle, width, height ); + + if ( geom.isNull() ) + { + parent->setEvalErrorString( QObject::tr( "Error calculating polygon main angle: %1" ).arg( geom.lastError() ) ); + return QVariant(); + } + return angle; +} + static QVariant fcnDifference( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) { QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent ); @@ -6178,6 +6197,9 @@ const QList &QgsExpression::Functions() << new QgsStaticExpressionFunction( QStringLiteral( "oriented_bbox" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) ), fcnOrientedBBox, QStringLiteral( "GeometryGroup" ) ) + << new QgsStaticExpressionFunction( QStringLiteral( "main_angle" ), QgsExpressionFunction::ParameterList() + << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) ), + fcnMainAngle, QStringLiteral( "GeometryGroup" ) ) << new QgsStaticExpressionFunction( QStringLiteral( "minimal_circle" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "segments" ), true, 36 ), diff --git a/src/core/geometry/qgsgeometry.cpp b/src/core/geometry/qgsgeometry.cpp index f4742a8ccc74..201ab86c15f0 100644 --- a/src/core/geometry/qgsgeometry.cpp +++ b/src/core/geometry/qgsgeometry.cpp @@ -821,7 +821,9 @@ QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QVector &newGeometries, bool topological, QgsPointSequence &topologyTestPoints, bool splitFeature ) { @@ -970,61 +972,12 @@ QgsRectangle QgsGeometry::boundingBox() const QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle, double &width, double &height ) const { - QgsRectangle minRect; - area = std::numeric_limits::max(); - angle = 0; - width = std::numeric_limits::max(); - height = std::numeric_limits::max(); - - if ( !d->geometry || d->geometry->nCoordinates() < 2 ) - return QgsGeometry(); - - QgsGeometry hull = convexHull(); - if ( hull.isNull() ) - return QgsGeometry(); - - QgsVertexId vertexId; - QgsPoint pt0; - QgsPoint pt1; - QgsPoint pt2; - // get first point - hull.constGet()->nextVertex( vertexId, pt0 ); - pt1 = pt0; - double totalRotation = 0; - while ( hull.constGet()->nextVertex( vertexId, pt2 ) ) - { - double currentAngle = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ); - double rotateAngle = 180.0 / M_PI * currentAngle; - totalRotation += rotateAngle; - - QTransform t = QTransform::fromTranslate( pt0.x(), pt0.y() ); - t.rotate( rotateAngle ); - t.translate( -pt0.x(), -pt0.y() ); - - hull.get()->transform( t ); - - QgsRectangle bounds = hull.constGet()->boundingBox(); - double currentArea = bounds.width() * bounds.height(); - if ( currentArea < area ) - { - minRect = bounds; - area = currentArea; - angle = totalRotation; - width = bounds.width(); - height = bounds.height(); - } - - pt1 = hull.constGet()->vertexAt( vertexId ); - } - - QgsGeometry minBounds = QgsGeometry::fromRect( minRect ); - minBounds.rotate( angle, QgsPointXY( pt0.x(), pt0.y() ) ); - - // constrain angle to 0 - 180 - if ( angle > 180.0 ) - angle = std::fmod( angle, 180.0 ); - - return minBounds; + mLastError.clear(); + QgsInternalGeometryEngine engine( *this ); + const QgsGeometry res = engine.orientedMinimumBoundingBox( area, angle, width, height ); + if ( res.isNull() ) + mLastError = engine.lastError(); + return res; } QgsGeometry QgsGeometry::orientedMinimumBoundingBox() const @@ -3173,38 +3126,38 @@ QgsGeometry QgsGeometry::smooth( const unsigned int iterations, const double off case QgsWkbTypes::LineString: { - QgsLineString *lineString = static_cast< QgsLineString * >( d->geometry.get() ); + const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( geom.constGet() ); return QgsGeometry( smoothLine( *lineString, iterations, offset, minimumDistance, maxAngle ) ); } case QgsWkbTypes::MultiLineString: { - QgsMultiLineString *multiLine = static_cast< QgsMultiLineString * >( d->geometry.get() ); + const QgsMultiLineString *multiLine = qgsgeometry_cast< const QgsMultiLineString * >( geom.constGet() ); std::unique_ptr< QgsMultiLineString > resultMultiline = qgis::make_unique< QgsMultiLineString> (); resultMultiline->reserve( multiLine->numGeometries() ); for ( int i = 0; i < multiLine->numGeometries(); ++i ) { - resultMultiline->addGeometry( smoothLine( *( static_cast< QgsLineString * >( multiLine->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ).release() ); + resultMultiline->addGeometry( smoothLine( *( qgsgeometry_cast< const QgsLineString * >( multiLine->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ).release() ); } return QgsGeometry( std::move( resultMultiline ) ); } case QgsWkbTypes::Polygon: { - QgsPolygon *poly = static_cast< QgsPolygon * >( d->geometry.get() ); + const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( geom.constGet() ); return QgsGeometry( smoothPolygon( *poly, iterations, offset, minimumDistance, maxAngle ) ); } case QgsWkbTypes::MultiPolygon: { - QgsMultiPolygon *multiPoly = static_cast< QgsMultiPolygon * >( d->geometry.get() ); + const QgsMultiPolygon *multiPoly = qgsgeometry_cast< const QgsMultiPolygon * >( geom.constGet() ); std::unique_ptr< QgsMultiPolygon > resultMultiPoly = qgis::make_unique< QgsMultiPolygon >(); resultMultiPoly->reserve( multiPoly->numGeometries() ); for ( int i = 0; i < multiPoly->numGeometries(); ++i ) { - resultMultiPoly->addGeometry( smoothPolygon( *( static_cast< QgsPolygon * >( multiPoly->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ).release() ); + resultMultiPoly->addGeometry( smoothPolygon( *( qgsgeometry_cast< const QgsPolygon * >( multiPoly->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ).release() ); } return QgsGeometry( std::move( resultMultiPoly ) ); } diff --git a/src/core/geometry/qgsgeometry.h b/src/core/geometry/qgsgeometry.h index 8df622a1ebe2..98aaa1e3cf2c 100644 --- a/src/core/geometry/qgsgeometry.h +++ b/src/core/geometry/qgsgeometry.h @@ -943,6 +943,10 @@ class CORE_EXPORT QgsGeometry * Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) * rotated rectangle which fully encompasses the geometry. The area, angle (clockwise in degrees from North), * width and height of the rotated bounding box will also be returned. + * + * If an error was encountered while creating the result, more information can be retrieved + * by calling lastError() on the returned geometry. + * * \see boundingBox() * \since QGIS 3.0 */ @@ -951,6 +955,10 @@ class CORE_EXPORT QgsGeometry /** * Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) * rotated rectangle which fully encompasses the geometry. + * + * If an error was encountered while creating the result, more information can be retrieved + * by calling lastError() on the returned geometry. + * * \since QGIS 3.0 */ QgsGeometry orientedMinimumBoundingBox() const SIP_SKIP; diff --git a/src/core/geometry/qgsgeos.cpp b/src/core/geometry/qgsgeos.cpp index a3e315dd10a7..0383d4f76711 100644 --- a/src/core/geometry/qgsgeos.cpp +++ b/src/core/geometry/qgsgeos.cpp @@ -1055,8 +1055,18 @@ geos::unique_ptr QgsGeos::createGeosCollection( int typeId, const QVectorctxt, *geomIt ) ) + { + // don't add empty parts to a geos collection, it can cause crashes in GEOS + nNullGeoms++; + nNotNullGeoms--; + GEOSGeom_destroy_r( geosinit()->ctxt, *geomIt ); + } + else + { + geomarr[i] = *geomIt; + ++i; + } } } geos::unique_ptr geom; diff --git a/src/core/geometry/qgsinternalgeometryengine.cpp b/src/core/geometry/qgsinternalgeometryengine.cpp index b39190a82455..fa94e0559c77 100644 --- a/src/core/geometry/qgsinternalgeometryengine.cpp +++ b/src/core/geometry/qgsinternalgeometryengine.cpp @@ -28,6 +28,7 @@ #include "qgslogger.h" #include "qgstessellator.h" #include "qgsfeedback.h" +#include "qgsgeometryengine.h" #include #include #include @@ -40,6 +41,11 @@ QgsInternalGeometryEngine::QgsInternalGeometryEngine( const QgsGeometry &geometr } +QString QgsInternalGeometryEngine::lastError() const +{ + return mLastError; +} + /*************************************************************************** * This class is considered CRITICAL and any change MUST be accompanied with * full unit tests. @@ -48,6 +54,7 @@ QgsInternalGeometryEngine::QgsInternalGeometryEngine( const QgsGeometry &geometr QgsGeometry QgsInternalGeometryEngine::extrude( double x, double y ) const { + mLastError.clear(); QVector linesToProcess; const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry ); @@ -238,6 +245,7 @@ QgsPoint surfacePoleOfInaccessibility( const QgsSurface *surface, double precisi QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision, double *distanceFromBoundary ) const { + mLastError.clear(); if ( distanceFromBoundary ) *distanceFromBoundary = std::numeric_limits::max(); @@ -493,6 +501,7 @@ QgsAbstractGeometry *orthogonalizeGeom( const QgsAbstractGeometry *geom, int max QgsGeometry QgsInternalGeometryEngine::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const { + mLastError.clear(); if ( !mGeometry || ( QgsWkbTypes::geometryType( mGeometry->wkbType() ) != QgsWkbTypes::LineGeometry && QgsWkbTypes::geometryType( mGeometry->wkbType() ) != QgsWkbTypes::PolygonGeometry ) ) { @@ -650,6 +659,7 @@ QgsAbstractGeometry *densifyGeometry( const QgsAbstractGeometry *geom, int extra QgsGeometry QgsInternalGeometryEngine::densifyByCount( int extraNodesPerSegment ) const { + mLastError.clear(); if ( !mGeometry ) { return QgsGeometry(); @@ -685,6 +695,7 @@ QgsGeometry QgsInternalGeometryEngine::densifyByCount( int extraNodesPerSegment QgsGeometry QgsInternalGeometryEngine::densifyByDistance( double distance ) const { + mLastError.clear(); if ( !mGeometry ) { return QgsGeometry(); @@ -891,6 +902,7 @@ QVector generateSegmentCurve( const QgsPoint ¢er1, const double QgsGeometry QgsInternalGeometryEngine::variableWidthBuffer( int segments, const std::function< std::unique_ptr< double[] >( const QgsLineString *line ) > &widthFunction ) const { + mLastError.clear(); if ( !mGeometry ) { return QgsGeometry(); @@ -996,6 +1008,7 @@ QgsGeometry QgsInternalGeometryEngine::variableWidthBuffer( int segments, const QgsGeometry QgsInternalGeometryEngine::taperedBuffer( double start, double end, int segments ) const { + mLastError.clear(); start = std::fabs( start ); end = std::fabs( end ); @@ -1028,6 +1041,7 @@ QgsGeometry QgsInternalGeometryEngine::taperedBuffer( double start, double end, QgsGeometry QgsInternalGeometryEngine::variableWidthBufferByM( int segments ) const { + mLastError.clear(); auto widthByM = []( const QgsLineString * line )->std::unique_ptr< double [] > { std::unique_ptr< double [] > widths( new double[ line->nCoordinates() ] ); @@ -1394,6 +1408,7 @@ std::unique_ptr< QgsAbstractGeometry > convertGeometryToCurves( const QgsAbstrac QgsGeometry QgsInternalGeometryEngine::convertToCurves( double distanceTolerance, double angleTolerance ) const { + mLastError.clear(); if ( !mGeometry ) { return QgsGeometry(); @@ -1433,3 +1448,66 @@ QgsGeometry QgsInternalGeometryEngine::convertToCurves( double distanceTolerance return QgsGeometry( convertGeometryToCurves( mGeometry, distanceTolerance, angleTolerance ) ); } } + +QgsGeometry QgsInternalGeometryEngine::orientedMinimumBoundingBox( double &area, double &angle, double &width, double &height ) const +{ + mLastError.clear(); + + QgsRectangle minRect; + area = std::numeric_limits::max(); + angle = 0; + width = std::numeric_limits::max(); + height = std::numeric_limits::max(); + + if ( !mGeometry || mGeometry->nCoordinates() < 2 ) + return QgsGeometry(); + + std::unique_ptr< QgsGeometryEngine >engine( QgsGeometry::createGeometryEngine( mGeometry ) ); + QString error; + std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) ); + if ( !hull ) + return QgsGeometry(); + + QgsVertexId vertexId; + QgsPoint pt0; + QgsPoint pt1; + QgsPoint pt2; + // get first point + hull->nextVertex( vertexId, pt0 ); + pt1 = pt0; + double totalRotation = 0; + while ( hull->nextVertex( vertexId, pt2 ) ) + { + double currentAngle = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ); + double rotateAngle = 180.0 / M_PI * currentAngle; + totalRotation += rotateAngle; + + QTransform t = QTransform::fromTranslate( pt0.x(), pt0.y() ); + t.rotate( rotateAngle ); + t.translate( -pt0.x(), -pt0.y() ); + + hull->transform( t ); + + QgsRectangle bounds = hull->boundingBox(); + double currentArea = bounds.width() * bounds.height(); + if ( currentArea < area ) + { + minRect = bounds; + area = currentArea; + angle = totalRotation; + width = bounds.width(); + height = bounds.height(); + } + + pt1 = hull->vertexAt( vertexId ); + } + + QgsGeometry minBounds = QgsGeometry::fromRect( minRect ); + minBounds.rotate( angle, QgsPointXY( pt0.x(), pt0.y() ) ); + + // constrain angle to 0 - 180 + if ( angle > 180.0 ) + angle = std::fmod( angle, 180.0 ); + + return minBounds; +} diff --git a/src/core/geometry/qgsinternalgeometryengine.h b/src/core/geometry/qgsinternalgeometryengine.h index 5a92d14c025b..611396170d8b 100644 --- a/src/core/geometry/qgsinternalgeometryengine.h +++ b/src/core/geometry/qgsinternalgeometryengine.h @@ -49,6 +49,13 @@ class QgsInternalGeometryEngine */ explicit QgsInternalGeometryEngine( const QgsGeometry &geometry ); + /** + * Returns an error string referring to the last error encountered. + * + * \since QGIS 3.16 + */ + QString lastError() const; + /** * Will extrude a line or (segmentized) curve by a given offset and return a polygon * representation of it. @@ -189,8 +196,22 @@ class QgsInternalGeometryEngine */ QgsGeometry convertToCurves( double distanceTolerance, double angleTolerance ) const; + /** + * Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) + * rotated rectangle which fully encompasses the geometry. The area, angle (clockwise in degrees from North), + * width and height of the rotated bounding box will also be returned. + * + * If an error was encountered while creating the result, more information can be retrieved + * by calling lastError(). + * + * \since QGIS 3.16 + */ + QgsGeometry orientedMinimumBoundingBox( double &area SIP_OUT, double &angle SIP_OUT, double &width SIP_OUT, double &height SIP_OUT ) const; + private: const QgsAbstractGeometry *mGeometry = nullptr; + + mutable QString mLastError; }; /** diff --git a/src/core/labeling/qgspallabeling.cpp b/src/core/labeling/qgspallabeling.cpp index 13678db97f86..e808332fa55e 100644 --- a/src/core/labeling/qgspallabeling.cpp +++ b/src/core/labeling/qgspallabeling.cpp @@ -3188,6 +3188,10 @@ void QgsPalLayerSettings::parseTextFormatting( QgsRenderContext &context ) { aligntype = QgsPalLayerSettings::MultiFollowPlacement; } + else if ( str.compare( QLatin1String( "Justify" ), Qt::CaseInsensitive ) == 0 ) + { + aligntype = QgsPalLayerSettings::MultiJustify; + } dataDefinedValues.insert( QgsPalLayerSettings::MultiLineAlignment, QVariant( static_cast< int >( aligntype ) ) ); } } diff --git a/src/core/labeling/qgspallabeling.h b/src/core/labeling/qgspallabeling.h index d2a00718fe51..611233ef872b 100644 --- a/src/core/labeling/qgspallabeling.h +++ b/src/core/labeling/qgspallabeling.h @@ -311,8 +311,9 @@ class CORE_EXPORT QgsPalLayerSettings MultiLeft = 0, MultiCenter, MultiRight, - MultiFollowPlacement /*!< Alignment follows placement of label, e.g., labels to the left of a feature + MultiFollowPlacement, /*!< Alignment follows placement of label, e.g., labels to the left of a feature will be drawn with right alignment*/ + MultiJustify, //!< Justified }; //TODO QGIS 4.0 - Remove -- moved to QgsLabelEngineObstacleSettings @@ -358,7 +359,7 @@ class CORE_EXPORT QgsPalLayerSettings AutoWrapLength = 101, MultiLineHeight = 32, MultiLineAlignment = 33, - TextOrientation = 104, + TextOrientation = 110, DirSymbDraw = 34, DirSymbLeft = 35, DirSymbRight = 36, diff --git a/src/core/labeling/qgsvectorlayerlabelprovider.cpp b/src/core/labeling/qgsvectorlayerlabelprovider.cpp index 4b56670aad86..5012957153dd 100644 --- a/src/core/labeling/qgsvectorlayerlabelprovider.cpp +++ b/src/core/labeling/qgsvectorlayerlabelprovider.cpp @@ -618,6 +618,8 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q hAlign = QgsTextRenderer::AlignCenter; else if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiRight ) hAlign = QgsTextRenderer::AlignRight; + else if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiJustify ) + hAlign = QgsTextRenderer::AlignJustify; QgsTextRenderer::Component component; component.origin = outPt; @@ -637,7 +639,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q } QgsTextRenderer::drawTextInternal( drawType, context, tmpLyr.format(), component, document, labelfm, - hAlign, QgsTextRenderer::Label ); + hAlign, QgsTextRenderer::AlignTop, QgsTextRenderer::Label ); } if ( label->nextPart() ) diff --git a/src/core/layout/qgscompositionconverter.cpp b/src/core/layout/qgscompositionconverter.cpp index c43769c7f8fa..155ae7a11557 100644 --- a/src/core/layout/qgscompositionconverter.cpp +++ b/src/core/layout/qgscompositionconverter.cpp @@ -984,8 +984,21 @@ bool QgsCompositionConverter::readMapXml( QgsLayoutItemMap *layoutItem, const QD mapGrid->setAnnotationFrameDistance( annotationElem.attribute( QStringLiteral( "frameDistance" ), QStringLiteral( "0" ) ).toDouble() ); QFont annotationFont; annotationFont.fromString( annotationElem.attribute( QStringLiteral( "font" ), QString() ) ); - mapGrid->setAnnotationFont( annotationFont ); - mapGrid->setAnnotationFontColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "0,0,0,255" ) ) ) ); + + QgsTextFormat annotationFormat = mapGrid->annotationTextFormat(); + annotationFormat.setFont( annotationFont ); + if ( annotationFont.pointSizeF() > 0 ) + { + annotationFormat.setSize( annotationFont.pointSizeF() ); + annotationFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + } + else if ( annotationFont.pixelSize() > 0 ) + { + annotationFormat.setSize( annotationFont.pixelSize() ); + annotationFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); + } + annotationFormat.setColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "0,0,0,255" ) ) ) ); + mapGrid->setAnnotationTextFormat( annotationFormat ); mapGrid->setAnnotationPrecision( annotationElem.attribute( QStringLiteral( "precision" ), QStringLiteral( "3" ) ).toInt() ); } @@ -1408,18 +1421,48 @@ bool QgsCompositionConverter::readTableXml( QgsLayoutItemAttributeTable *layoutI layoutItem->setEmptyTableBehavior( static_cast( itemElem.attribute( QStringLiteral( "emptyTableMode" ), QStringLiteral( "0" ) ).toInt() ) ); layoutItem->setEmptyTableMessage( itemElem.attribute( QStringLiteral( "emptyTableMessage" ), QObject::tr( "No matching records" ) ) ); layoutItem->setShowEmptyRows( itemElem.attribute( QStringLiteral( "showEmptyRows" ), QStringLiteral( "0" ) ).toInt() ); - if ( !QgsFontUtils::setFromXmlChildNode( layoutItem->mHeaderFont, itemElem, QStringLiteral( "headerFontProperties" ) ) ) + QFont headerFont; + if ( !QgsFontUtils::setFromXmlChildNode( headerFont, itemElem, QStringLiteral( "headerFontProperties" ) ) ) + { + headerFont.fromString( itemElem.attribute( QStringLiteral( "headerFont" ), QString() ) ); + } + QgsTextFormat headerFormat = layoutItem->headerTextFormat(); + headerFormat.setFont( headerFont ); + if ( headerFont.pointSizeF() > 0 ) { - layoutItem->mHeaderFont.fromString( itemElem.attribute( QStringLiteral( "headerFont" ), QString() ) ); + headerFormat.setSize( headerFont.pointSizeF() ); + headerFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); } - layoutItem->setHeaderFontColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "headerFontColor" ), QStringLiteral( "0,0,0,255" ) ) ) ); + else if ( headerFont.pixelSize() > 0 ) + { + headerFormat.setSize( headerFont.pixelSize() ); + headerFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); + } + headerFormat.setColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "headerFontColor" ), QStringLiteral( "0,0,0,255" ) ) ) ); + layoutItem->setHeaderTextFormat( headerFormat ); layoutItem->setHeaderHAlignment( static_cast( itemElem.attribute( QStringLiteral( "headerHAlignment" ), QStringLiteral( "0" ) ).toInt() ) ) ; layoutItem->setHeaderMode( static_cast( itemElem.attribute( QStringLiteral( "headerMode" ), QStringLiteral( "0" ) ).toInt() ) ); - if ( !QgsFontUtils::setFromXmlChildNode( layoutItem->mContentFont, itemElem, QStringLiteral( "contentFontProperties" ) ) ) + + QFont contentFont; + if ( !QgsFontUtils::setFromXmlChildNode( contentFont, itemElem, QStringLiteral( "contentFontProperties" ) ) ) + { + contentFont.fromString( itemElem.attribute( QStringLiteral( "contentFont" ), QString() ) ); + } + QgsTextFormat contentFormat = layoutItem->contentTextFormat(); + contentFormat.setFont( contentFont ); + if ( contentFont.pointSizeF() > 0 ) { - layoutItem->mContentFont.fromString( itemElem.attribute( QStringLiteral( "contentFont" ), QString() ) ); + contentFormat.setSize( contentFont.pointSizeF() ); + contentFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); } - layoutItem->setContentFontColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "contentFontColor" ), QStringLiteral( "0,0,0,255" ) ) ) ); + else if ( contentFont.pixelSize() > 0 ) + { + contentFormat.setSize( contentFont.pixelSize() ); + contentFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); + } + contentFormat.setColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "contentFontColor" ), QStringLiteral( "0,0,0,255" ) ) ) ); + layoutItem->setContentTextFormat( contentFormat ); + layoutItem->setCellMargin( itemElem.attribute( QStringLiteral( "cellMargin" ), QStringLiteral( "1.0" ) ).toDouble() ); layoutItem->setGridStrokeWidth( itemElem.attribute( QStringLiteral( "gridStrokeWidth" ), QStringLiteral( "0.5" ) ).toDouble() ); layoutItem->setHorizontalGrid( itemElem.attribute( QStringLiteral( "horizontalGrid" ), QStringLiteral( "1" ) ).toInt() ); diff --git a/src/core/layout/qgslayoutitemattributetable.cpp b/src/core/layout/qgslayoutitemattributetable.cpp index d6736f5c2ea1..d1924f4a7554 100644 --- a/src/core/layout/qgslayoutitemattributetable.cpp +++ b/src/core/layout/qgslayoutitemattributetable.cpp @@ -486,8 +486,9 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont QgsFeatureIterator fit = layer->getFeatures( req ); mConditionalStyles.clear(); + mFeatures.clear(); - QVector< QVector< QPair< QVariant, QgsConditionalStyle > > > tempContents; + QVector< QVector< Cell > > tempContents; QgsLayoutTableContents existingContents; while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures ) @@ -539,7 +540,7 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont // correctly when this occurs // We also need a list of just the cell contents, so that we can do a quick check for row uniqueness (when the // corresponding option is enabled) - QVector< QPair< QVariant, QgsConditionalStyle > > currentRow; + QVector< Cell > currentRow; currentRow.reserve( mColumns.count() ); QgsLayoutTableRow rowContents; rowContents.reserve( mColumns.count() ); @@ -563,7 +564,7 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont } QVariant v = replaceWrapChar( val ); - currentRow << qMakePair( v, style ); + currentRow << Cell( v, style, f ); rowContents << v; } else @@ -574,7 +575,7 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont expression->prepare( &context ); QVariant value = expression->evaluate( &context ); - currentRow << qMakePair( value, rowStyle ); + currentRow << Cell( value, rowStyle, f ); rowContents << value; } } @@ -593,6 +594,7 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont // build final table contents contents.reserve( tempContents.size() ); mConditionalStyles.reserve( tempContents.size() ); + mFeatures.reserve( tempContents.size() ); for ( auto it = tempContents.constBegin(); it != tempContents.constEnd(); ++it ) { QgsLayoutTableRow row; @@ -602,8 +604,10 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont for ( auto cellIt = it->constBegin(); cellIt != it->constEnd(); ++cellIt ) { - row << cellIt->first; - rowStyles << cellIt->second; + row << cellIt->content; + rowStyles << cellIt->style; + if ( cellIt == it->constBegin() ) + mFeatures << cellIt->feature; } contents << row; mConditionalStyles << rowStyles; @@ -621,6 +625,14 @@ QgsConditionalStyle QgsLayoutItemAttributeTable::conditionalCellStyle( int row, return mConditionalStyles.at( row ).at( column ); } +QgsExpressionContextScope *QgsLayoutItemAttributeTable::scopeForCell( int row, int column ) const +{ + std::unique_ptr< QgsExpressionContextScope >scope( QgsLayoutTable::scopeForCell( row, column ) ); + scope->setFeature( mFeatures.value( row ) ); + scope->setFields( scope->feature().fields() ); + return scope.release(); +} + QgsExpressionContext QgsLayoutItemAttributeTable::createExpressionContext() const { QgsExpressionContext context = QgsLayoutTable::createExpressionContext(); diff --git a/src/core/layout/qgslayoutitemattributetable.h b/src/core/layout/qgslayoutitemattributetable.h index 3cfe1602f69f..4e1d25e71e26 100644 --- a/src/core/layout/qgslayoutitemattributetable.h +++ b/src/core/layout/qgslayoutitemattributetable.h @@ -280,6 +280,7 @@ class CORE_EXPORT QgsLayoutItemAttributeTable: public QgsLayoutTable bool getTableContents( QgsLayoutTableContents &contents ) override SIP_SKIP; QgsConditionalStyle conditionalCellStyle( int row, int column ) const override; + QgsExpressionContextScope *scopeForCell( int row, int column ) const override SIP_FACTORY; QgsExpressionContext createExpressionContext() const override; void finalizeRestoreFromXml() override; @@ -356,6 +357,20 @@ class CORE_EXPORT QgsLayoutItemAttributeTable: public QgsLayoutTable bool mUseConditionalStyling = false; QList< QList< QgsConditionalStyle > > mConditionalStyles; + QList< QgsFeature > mFeatures; + + struct Cell + { + Cell() = default; + + Cell( const QVariant &content, const QgsConditionalStyle &style, const QgsFeature &feature ) + : content( content ) + , style( style ) + , feature( feature ) {} + QVariant content; + QgsConditionalStyle style; + QgsFeature feature; + }; /** * Returns a list of attribute indices corresponding to displayed fields in the table. diff --git a/src/core/layout/qgslayoutitemmanualtable.cpp b/src/core/layout/qgslayoutitemmanualtable.cpp index 1b1deb235a5e..82b073d358d0 100644 --- a/src/core/layout/qgslayoutitemmanualtable.cpp +++ b/src/core/layout/qgslayoutitemmanualtable.cpp @@ -21,6 +21,7 @@ #include "qgslayouttablecolumn.h" #include "qgsnumericformat.h" #include "qgsxmlutils.h" +#include "qgsexpressioncontextutils.h" // // QgsLayoutItemManualTable @@ -63,18 +64,30 @@ bool QgsLayoutItemManualTable::getTableContents( QgsLayoutTableContents &content QgsNumericFormatContext numericContext; + QgsExpressionContext context = createExpressionContext(); + + int rowNumber = 0; for ( const QgsTableRow &row : qgis::as_const( mContents ) ) { QgsLayoutTableRow currentRow; - for ( int i = 0; i < mColumns.count(); ++i ) + for ( int columnNumber = 0; columnNumber < mColumns.count(); ++columnNumber ) { - if ( i < row.count() ) + if ( columnNumber < row.count() ) { - if ( row.at( i ).numericFormat() ) - currentRow << row.at( i ).numericFormat()->formatDouble( row.at( i ).content().toDouble(), numericContext ); + QVariant cellContent = row.at( columnNumber ).content(); + + if ( cellContent.canConvert< QgsProperty >() ) + { + // expression based cell content, evaluate now + QgsExpressionContextScopePopper popper( context, scopeForCell( rowNumber, columnNumber ) ); + cellContent = cellContent.value< QgsProperty >().value( context ); + } + + if ( row.at( columnNumber ).numericFormat() ) + currentRow << row.at( columnNumber ).numericFormat()->formatDouble( cellContent.toDouble(), numericContext ); else - currentRow << row.at( i ).content().toString(); + currentRow << cellContent.toString(); } else { @@ -82,6 +95,7 @@ bool QgsLayoutItemManualTable::getTableContents( QgsLayoutTableContents &content } } contents << currentRow; + rowNumber++; } recalculateTableSize(); @@ -304,6 +318,36 @@ bool QgsLayoutItemManualTable::calculateMaxRowHeights() return true; } +QgsTextFormat QgsLayoutItemManualTable::textFormatForHeader( int column ) const +{ +// if ( mHeaders.value( column ).) + return QgsLayoutTable::textFormatForHeader( column ); +} + +QgsTextFormat QgsLayoutItemManualTable::textFormatForCell( int row, int column ) const +{ + if ( mContents.value( row ).value( column ).textFormat().isValid() ) + return mContents.value( row ).value( column ).textFormat(); + + return QgsLayoutTable::textFormatForCell( row, column ); +} + +Qt::Alignment QgsLayoutItemManualTable::horizontalAlignmentForCell( int row, int column ) const +{ + if ( row < mContents.size() && column < mContents.at( row ).size() ) + return mContents.value( row ).value( column ).horizontalAlignment(); + + return QgsLayoutTable::horizontalAlignmentForCell( row, column ); +} + +Qt::Alignment QgsLayoutItemManualTable::verticalAlignmentForCell( int row, int column ) const +{ + if ( row < mContents.size() && column < mContents.at( row ).size() ) + return mContents.value( row ).value( column ).verticalAlignment(); + + return QgsLayoutTable::verticalAlignmentForCell( row, column ); +} + void QgsLayoutItemManualTable::refreshColumns() { // refresh columns diff --git a/src/core/layout/qgslayoutitemmanualtable.h b/src/core/layout/qgslayoutitemmanualtable.h index ba30902a32a3..a255841454d9 100644 --- a/src/core/layout/qgslayoutitemmanualtable.h +++ b/src/core/layout/qgslayoutitemmanualtable.h @@ -139,6 +139,10 @@ class CORE_EXPORT QgsLayoutItemManualTable: public QgsLayoutTable bool writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const override; bool readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context ) override; bool calculateMaxRowHeights() override; + QgsTextFormat textFormatForHeader( int column ) const override; + QgsTextFormat textFormatForCell( int row, int column ) const override; + Qt::Alignment horizontalAlignmentForCell( int row, int column ) const override; + Qt::Alignment verticalAlignmentForCell( int row, int column ) const override; private: diff --git a/src/core/layout/qgslayoutitemmapgrid.cpp b/src/core/layout/qgslayoutitemmapgrid.cpp index 754019364442..a833c96ca5a4 100644 --- a/src/core/layout/qgslayoutitemmapgrid.cpp +++ b/src/core/layout/qgslayoutitemmapgrid.cpp @@ -35,6 +35,7 @@ #include "qgssettings.h" #include "qgscoordinateformatter.h" #include "qgsstyleentityvisitor.h" +#include "qgstextrenderer.h" #include #include @@ -166,7 +167,9 @@ QgsLayoutItemMapGrid::QgsLayoutItemMapGrid( const QString &name, QgsLayoutItemMa QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString(); if ( !defaultFontString.isEmpty() ) { - mGridAnnotationFont.setFamily( defaultFontString ); + QFont font; + font.setFamily( defaultFontString ); + mAnnotationFormat.setFont( font ); } createDefaultGridLineSymbol(); @@ -268,8 +271,7 @@ bool QgsLayoutItemMapGrid::writeXml( QDomElement &elem, QDomDocument &doc, const mapGridElem.setAttribute( QStringLiteral( "topAnnotationDirection" ), mTopGridAnnotationDirection ); mapGridElem.setAttribute( QStringLiteral( "bottomAnnotationDirection" ), mBottomGridAnnotationDirection ); mapGridElem.setAttribute( QStringLiteral( "frameAnnotationDistance" ), QString::number( mAnnotationFrameDistance ) ); - mapGridElem.appendChild( QgsFontUtils::toXmlElement( mGridAnnotationFont, doc, QStringLiteral( "annotationFontProperties" ) ) ); - mapGridElem.setAttribute( QStringLiteral( "annotationFontColor" ), QgsSymbolLayerUtils::encodeColor( mGridAnnotationFontColor ) ); + mapGridElem.appendChild( mAnnotationFormat.writeXml( doc, context ) ); mapGridElem.setAttribute( QStringLiteral( "annotationPrecision" ), mGridAnnotationPrecision ); mapGridElem.setAttribute( QStringLiteral( "unit" ), mGridUnit ); mapGridElem.setAttribute( QStringLiteral( "blendMode" ), mBlendMode ); @@ -364,11 +366,24 @@ bool QgsLayoutItemMapGrid::readXml( const QDomElement &itemElem, const QDomDocum mTopGridAnnotationDirection = QgsLayoutItemMapGrid::AnnotationDirection( itemElem.attribute( QStringLiteral( "topAnnotationDirection" ), QStringLiteral( "0" ) ).toInt() ); mBottomGridAnnotationDirection = QgsLayoutItemMapGrid::AnnotationDirection( itemElem.attribute( QStringLiteral( "bottomAnnotationDirection" ), QStringLiteral( "0" ) ).toInt() ); mAnnotationFrameDistance = itemElem.attribute( QStringLiteral( "frameAnnotationDistance" ), QStringLiteral( "0" ) ).toDouble(); - if ( !QgsFontUtils::setFromXmlChildNode( mGridAnnotationFont, itemElem, QStringLiteral( "annotationFontProperties" ) ) ) + + if ( !itemElem.firstChildElement( "text-style" ).isNull() ) { - mGridAnnotationFont.fromString( itemElem.attribute( QStringLiteral( "annotationFont" ), QString() ) ); + mAnnotationFormat.readXml( itemElem, context ); } - mGridAnnotationFontColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "annotationFontColor" ), QStringLiteral( "0,0,0,255" ) ) ); + else + { + QFont font; + if ( !QgsFontUtils::setFromXmlChildNode( font, itemElem, "annotationFontProperties" ) ) + { + font.fromString( itemElem.attribute( "annotationFont", QString() ) ); + } + mAnnotationFormat.setFont( font ); + mAnnotationFormat.setSize( font.pointSizeF() ); + mAnnotationFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + mAnnotationFormat.setColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( "annotationFontColor", "0,0,0,255" ) ) ); + } + mGridAnnotationPrecision = itemElem.attribute( QStringLiteral( "annotationPrecision" ), QStringLiteral( "3" ) ).toInt(); int gridUnitInt = itemElem.attribute( QStringLiteral( "unit" ), QString::number( MapUnit ) ).toInt(); mGridUnit = ( gridUnitInt <= static_cast< int >( DynamicPageSizeBased ) ) ? static_cast< GridUnit >( gridUnitInt ) : MapUnit; @@ -585,6 +600,7 @@ void QgsLayoutItemMapGrid::draw( QPainter *p ) //setup render context QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( mLayout, p ); context.setForceVectorOutput( true ); + context.setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering, true ); QgsExpressionContext expressionContext = createExpressionContext(); context.setExpressionContext( expressionContext ); @@ -624,7 +640,7 @@ void QgsLayoutItemMapGrid::draw( QPainter *p ) if ( mShowGridAnnotation ) { - drawCoordinateAnnotations( p, horizontalLines, verticalLines, context.expressionContext() ); + drawCoordinateAnnotations( context, horizontalLines, verticalLines, context.expressionContext() ); } } @@ -1045,7 +1061,7 @@ void QgsLayoutItemMapGrid::drawGridFrameLineBorder( QPainter *p, QgsLayoutItemMa } } -void QgsLayoutItemMapGrid::drawCoordinateAnnotations( QPainter *p, const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines, QgsExpressionContext &expressionContext, +void QgsLayoutItemMapGrid::drawCoordinateAnnotations( QgsRenderContext &context, const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines, QgsExpressionContext &expressionContext, GridExtension *extension ) const { QString currentAnnotationString; @@ -1053,20 +1069,20 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotations( QPainter *p, const QList< for ( ; it != hLines.constEnd(); ++it ) { currentAnnotationString = gridAnnotationString( it->first, QgsLayoutItemMapGrid::Latitude, expressionContext ); - drawCoordinateAnnotation( p, it->second.p1(), currentAnnotationString, QgsLayoutItemMapGrid::Latitude, extension ); - drawCoordinateAnnotation( p, it->second.p2(), currentAnnotationString, QgsLayoutItemMapGrid::Latitude, extension ); + drawCoordinateAnnotation( context, it->second.p1(), currentAnnotationString, QgsLayoutItemMapGrid::Latitude, extension ); + drawCoordinateAnnotation( context, it->second.p2(), currentAnnotationString, QgsLayoutItemMapGrid::Latitude, extension ); } it = vLines.constBegin(); for ( ; it != vLines.constEnd(); ++it ) { currentAnnotationString = gridAnnotationString( it->first, QgsLayoutItemMapGrid::Longitude, expressionContext ); - drawCoordinateAnnotation( p, it->second.p1(), currentAnnotationString, QgsLayoutItemMapGrid::Longitude, extension ); - drawCoordinateAnnotation( p, it->second.p2(), currentAnnotationString, QgsLayoutItemMapGrid::Longitude, extension ); + drawCoordinateAnnotation( context, it->second.p1(), currentAnnotationString, QgsLayoutItemMapGrid::Longitude, extension ); + drawCoordinateAnnotation( context, it->second.p2(), currentAnnotationString, QgsLayoutItemMapGrid::Longitude, extension ); } } -void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos, const QString &annotationString, const AnnotationCoordinate coordinateType, GridExtension *extension ) const +void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QgsRenderContext &context, QPointF pos, const QString &annotationString, const AnnotationCoordinate coordinateType, GridExtension *extension ) const { if ( !mMap ) { @@ -1074,10 +1090,13 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos, c } QgsLayoutItemMapGrid::BorderSide frameBorder = borderForLineCoord( pos, coordinateType ); - double textWidth = QgsLayoutUtils::textWidthMM( mGridAnnotationFont, annotationString ); + double textWidth = QgsTextRenderer::textWidth( context, mAnnotationFormat, QStringList() << annotationString ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); + if ( extension ) + textWidth *= 1.1; // little bit of extra padding when we are calculating the bounding rect, to account for antialiasing //relevant for annotations is the height of digits - double textHeight = extension ? QgsLayoutUtils::fontAscentMM( mGridAnnotationFont ) - : QgsLayoutUtils::fontHeightCharacterMM( mGridAnnotationFont, QChar( '0' ) ); + const QFontMetricsF metrics = QgsTextRenderer::fontMetrics( context, mAnnotationFormat, QgsTextRenderer::FONT_WORKAROUND_SCALE ); + double textHeight = ( extension ? ( QgsTextRenderer::textHeight( context, mAnnotationFormat, QChar(), true ) ) + : ( QgsTextRenderer::textHeight( context, mAnnotationFormat, '0', false ) ) ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); double xpos = pos.x(); double ypos = pos.y(); int rotation = 0; @@ -1398,23 +1417,25 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos, c } } - if ( extension || !p ) + if ( extension || !context.painter() ) return; - drawAnnotation( p, QPointF( xpos, ypos ), rotation, annotationString ); + drawAnnotation( context, QPointF( xpos, ypos ), rotation, annotationString ); } -void QgsLayoutItemMapGrid::drawAnnotation( QPainter *p, QPointF pos, int rotation, const QString &annotationText ) const +void QgsLayoutItemMapGrid::drawAnnotation( QgsRenderContext &context, QPointF pos, int rotation, const QString &annotationText ) const { if ( !mMap ) { return; } - QgsScopedQPainterState painterState( p ); - p->translate( pos ); - p->rotate( rotation ); - QgsLayoutUtils::drawText( p, QPointF( 0, 0 ), annotationText, mGridAnnotationFont, mGridAnnotationFontColor ); + QgsScopedQPainterState painterState( context.painter() ); + context.painter()->translate( pos ); + context.painter()->rotate( rotation ); + + QgsScopedRenderContextScaleToPixels scale( context ); + QgsTextRenderer::drawText( QPointF( 0, 0 ), 0, QgsTextRenderer::AlignLeft, QStringList() << annotationText, context, mAnnotationFormat ); } QString QgsLayoutItemMapGrid::gridAnnotationString( double value, QgsLayoutItemMapGrid::AnnotationCoordinate coord, QgsExpressionContext &expressionContext ) const @@ -2122,6 +2143,36 @@ QgsMarkerSymbol *QgsLayoutItemMapGrid::markerSymbol() return mGridMarkerSymbol.get(); } +void QgsLayoutItemMapGrid::setAnnotationFont( const QFont &font ) +{ + mAnnotationFormat.setFont( font ); + if ( font.pointSizeF() > 0 ) + { + mAnnotationFormat.setSize( font.pointSizeF() ); + mAnnotationFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + } + else if ( font.pixelSize() > 0 ) + { + mAnnotationFormat.setSize( font.pixelSize() ); + mAnnotationFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); + } +} + +QFont QgsLayoutItemMapGrid::annotationFont() const +{ + return mAnnotationFormat.toQFont(); +} + +void QgsLayoutItemMapGrid::setAnnotationFontColor( const QColor &color ) +{ + mAnnotationFormat.setColor( color ); +} + +QColor QgsLayoutItemMapGrid::annotationFontColor() const +{ + return mAnnotationFormat.color(); +} + void QgsLayoutItemMapGrid::setAnnotationDisplay( const QgsLayoutItemMapGrid::DisplayMode display, const QgsLayoutItemMapGrid::BorderSide border ) { switch ( border ) @@ -2220,7 +2271,7 @@ void QgsLayoutItemMapGrid::calculateMaxExtension( double &top, double &right, do if ( mShowGridAnnotation ) { - drawCoordinateAnnotations( nullptr, horizontalLines, verticalLines, context.expressionContext(), &extension ); + drawCoordinateAnnotations( context, horizontalLines, verticalLines, context.expressionContext(), &extension ); } top = extension.top; diff --git a/src/core/layout/qgslayoutitemmapgrid.h b/src/core/layout/qgslayoutitemmapgrid.h index 31de40ce8363..db9e14cca8f1 100644 --- a/src/core/layout/qgslayoutitemmapgrid.h +++ b/src/core/layout/qgslayoutitemmapgrid.h @@ -22,6 +22,7 @@ #include "qgis_sip.h" #include "qgslayoutitemmapitem.h" #include "qgssymbol.h" +#include "qgstextformat.h" #include class QgsCoordinateTransform; @@ -561,29 +562,49 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem */ bool annotationEnabled() const { return mShowGridAnnotation; } + /** + * Sets the text \a format to use when rendering grid annotations. + * + * \see annotationTextFormat() + * \since QGIS 3.16 + */ + void setAnnotationTextFormat( const QgsTextFormat &format ) { mAnnotationFormat = format; } + + /** + * Returns the text format used when rendering grid annotations. + * + * \see setAnnotationTextFormat() + * \since QGIS 3.16 + */ + QgsTextFormat annotationTextFormat() const { return mAnnotationFormat; } + /** * Sets the \a font used for drawing grid annotations. * \see annotationFont() + * \deprecated use setAnnotationTextFormat() instead */ - void setAnnotationFont( const QFont &font ) { mGridAnnotationFont = font; } + Q_DECL_DEPRECATED void setAnnotationFont( const QFont &font ) SIP_DEPRECATED; /** * Returns the font used for drawing grid annotations. * \see setAnnotationFont() + * \deprecated use annotationTextFormat() instead */ - QFont annotationFont() const { return mGridAnnotationFont; } + Q_DECL_DEPRECATED QFont annotationFont() const SIP_DEPRECATED; /** * Sets the font \a color used for drawing grid annotations. * \see annotationFontColor() + * \deprecated use setAnnotationTextFormat() instead */ - void setAnnotationFontColor( const QColor &color ) { mGridAnnotationFontColor = color; } + Q_DECL_DEPRECATED void setAnnotationFontColor( const QColor &color ) SIP_DEPRECATED; /** * Returns the font color used for drawing grid annotations. * \see setAnnotationFontColor() + * \deprecated use annotationTextFormat() instead */ - QColor annotationFontColor() const { return mGridAnnotationFontColor; } + Q_DECL_DEPRECATED QColor annotationFontColor() const SIP_DEPRECATED; /** * Sets the coordinate \a precision for grid annotations. @@ -882,10 +903,10 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem double mGridOffsetX = 0.0; //! Grid line offset in y-direction double mGridOffsetY = 0.0; - //! Font for grid line annotation - QFont mGridAnnotationFont; - //! Font color for grid coordinates - QColor mGridAnnotationFontColor = Qt::black; + + //! Text format for grid annotations + QgsTextFormat mAnnotationFormat; + //! Digits after the dot int mGridAnnotationPrecision = 3; //! True if coordinate values should be drawn @@ -989,29 +1010,29 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem /** * Draw coordinates for mGridAnnotationType Coordinate - \param p drawing painter - \param hLines horizontal coordinate lines in item coordinates - \param vLines vertical coordinate lines in item coordinates - \param expressionContext expression context for evaluating custom annotation formats - \param extension optional. If specified, nothing will be drawn and instead the maximum extension for the grid - annotations will be stored in this variable. + * \param context destination render context + * \param hLines horizontal coordinate lines in item coordinates + * \param vLines vertical coordinate lines in item coordinates + * \param expressionContext expression context for evaluating custom annotation formats + * \param extension optional. If specified, nothing will be drawn and instead the maximum extension for the grid + * annotations will be stored in this variable. */ - void drawCoordinateAnnotations( QPainter *p, const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines, QgsExpressionContext &expressionContext, GridExtension *extension = nullptr ) const; + void drawCoordinateAnnotations( QgsRenderContext &context, const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines, QgsExpressionContext &expressionContext, GridExtension *extension = nullptr ) const; /** * Draw an annotation. If optional extension argument is specified, nothing will be drawn and instead * the extension of the annotation outside of the map frame will be stored in this variable. */ - void drawCoordinateAnnotation( QPainter *p, QPointF pos, const QString &annotationString, AnnotationCoordinate coordinateType, GridExtension *extension = nullptr ) const; + void drawCoordinateAnnotation( QgsRenderContext &context, QPointF pos, const QString &annotationString, AnnotationCoordinate coordinateType, GridExtension *extension = nullptr ) const; /** * Draws a single annotation - * \param p drawing painter + * \param context destination render context * \param pos item coordinates where to draw * \param rotation text rotation * \param annotationText the text to draw */ - void drawAnnotation( QPainter *p, QPointF pos, int rotation, const QString &annotationText ) const; + void drawAnnotation( QgsRenderContext &context, QPointF pos, int rotation, const QString &annotationText ) const; QString gridAnnotationString( double value, AnnotationCoordinate coord, QgsExpressionContext &expressionContext ) const; diff --git a/src/core/layout/qgslayouttable.cpp b/src/core/layout/qgslayouttable.cpp index 7cd9ad2bc52b..17eb249e44ad 100644 --- a/src/core/layout/qgslayouttable.cpp +++ b/src/core/layout/qgslayouttable.cpp @@ -15,6 +15,7 @@ * * ***************************************************************************/ +#include "qgsexpressioncontextutils.h" #include "qgslayouttable.h" #include "qgslayout.h" #include "qgslayoututils.h" @@ -24,6 +25,7 @@ #include "qgsfontutils.h" #include "qgssettings.h" #include "qgslayoutpagecollection.h" +#include "qgstextrenderer.h" // // QgsLayoutTableStyle @@ -52,15 +54,6 @@ bool QgsLayoutTableStyle::readXml( const QDomElement &styleElem ) QgsLayoutTable::QgsLayoutTable( QgsLayout *layout ) : QgsLayoutMultiFrame( layout ) { - //get default composer font from settings - QgsSettings settings; - QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString(); - if ( !defaultFontString.isEmpty() ) - { - mHeaderFont.setFamily( defaultFontString ); - mContentFont.setFamily( defaultFontString ); - } - initStyles(); } @@ -73,18 +66,24 @@ QgsLayoutTable::~QgsLayoutTable() mCellStyles.clear(); } -bool QgsLayoutTable::writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext & ) const +bool QgsLayoutTable::writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const { elem.setAttribute( QStringLiteral( "cellMargin" ), QString::number( mCellMargin ) ); elem.setAttribute( QStringLiteral( "emptyTableMode" ), QString::number( static_cast< int >( mEmptyTableMode ) ) ); elem.setAttribute( QStringLiteral( "emptyTableMessage" ), mEmptyTableMessage ); elem.setAttribute( QStringLiteral( "showEmptyRows" ), mShowEmptyRows ); - elem.appendChild( QgsFontUtils::toXmlElement( mHeaderFont, doc, QStringLiteral( "headerFontProperties" ) ) ); - elem.setAttribute( QStringLiteral( "headerFontColor" ), QgsSymbolLayerUtils::encodeColor( mHeaderFontColor ) ); + + QDomElement headerElem = doc.createElement( QStringLiteral( "headerTextFormat" ) ); + const QDomElement headerTextElem = mHeaderTextFormat.writeXml( doc, context ); + headerElem.appendChild( headerTextElem ); + elem.appendChild( headerElem ); elem.setAttribute( QStringLiteral( "headerHAlignment" ), QString::number( static_cast< int >( mHeaderHAlignment ) ) ); elem.setAttribute( QStringLiteral( "headerMode" ), QString::number( static_cast< int >( mHeaderMode ) ) ); - elem.appendChild( QgsFontUtils::toXmlElement( mContentFont, doc, QStringLiteral( "contentFontProperties" ) ) ); - elem.setAttribute( QStringLiteral( "contentFontColor" ), QgsSymbolLayerUtils::encodeColor( mContentFontColor ) ); + + QDomElement contentElem = doc.createElement( QStringLiteral( "contentTextFormat" ) ); + const QDomElement contentTextElem = mContentTextFormat.writeXml( doc, context ); + contentElem.appendChild( contentTextElem ); + elem.appendChild( contentElem ); elem.setAttribute( QStringLiteral( "gridStrokeWidth" ), QString::number( mGridStrokeWidth ) ); elem.setAttribute( QStringLiteral( "gridColor" ), QgsSymbolLayerUtils::encodeColor( mGridColor ) ); elem.setAttribute( QStringLiteral( "horizontalGrid" ), mHorizontalGrid ); @@ -131,23 +130,73 @@ bool QgsLayoutTable::writePropertiesToElement( QDomElement &elem, QDomDocument & return true; } -bool QgsLayoutTable::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext & ) +bool QgsLayoutTable::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext &context ) { mEmptyTableMode = QgsLayoutTable::EmptyTableMode( itemElem.attribute( QStringLiteral( "emptyTableMode" ), QStringLiteral( "0" ) ).toInt() ); mEmptyTableMessage = itemElem.attribute( QStringLiteral( "emptyTableMessage" ), tr( "No matching records" ) ); mShowEmptyRows = itemElem.attribute( QStringLiteral( "showEmptyRows" ), QStringLiteral( "0" ) ).toInt(); - if ( !QgsFontUtils::setFromXmlChildNode( mHeaderFont, itemElem, QStringLiteral( "headerFontProperties" ) ) ) + + const QDomElement headerTextFormat = itemElem.firstChildElement( QStringLiteral( "headerTextFormat" ) ); + if ( !headerTextFormat.isNull() ) { - mHeaderFont.fromString( itemElem.attribute( QStringLiteral( "headerFont" ), QString() ) ); + QDomNodeList textFormatNodeList = headerTextFormat.elementsByTagName( QStringLiteral( "text-style" ) ); + QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement(); + mHeaderTextFormat.readXml( textFormatElem, context ); + } + else + { + QFont headerFont; + if ( !QgsFontUtils::setFromXmlChildNode( headerFont, itemElem, QStringLiteral( "headerFontProperties" ) ) ) + { + headerFont.fromString( itemElem.attribute( QStringLiteral( "headerFont" ), QString() ) ); + } + QColor headerFontColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "headerFontColor" ), QStringLiteral( "0,0,0,255" ) ) ); + mHeaderTextFormat.setFont( headerFont ); + if ( headerFont.pointSizeF() > 0 ) + { + mHeaderTextFormat.setSize( headerFont.pointSizeF() ); + mHeaderTextFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + } + else if ( headerFont.pixelSize() > 0 ) + { + mHeaderTextFormat.setSize( headerFont.pixelSize() ); + mHeaderTextFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); + } + mHeaderTextFormat.setColor( headerFontColor ); } - mHeaderFontColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "headerFontColor" ), QStringLiteral( "0,0,0,255" ) ) ); + mHeaderHAlignment = QgsLayoutTable::HeaderHAlignment( itemElem.attribute( QStringLiteral( "headerHAlignment" ), QStringLiteral( "0" ) ).toInt() ); mHeaderMode = QgsLayoutTable::HeaderMode( itemElem.attribute( QStringLiteral( "headerMode" ), QStringLiteral( "0" ) ).toInt() ); - if ( !QgsFontUtils::setFromXmlChildNode( mContentFont, itemElem, QStringLiteral( "contentFontProperties" ) ) ) + + const QDomElement contentTextFormat = itemElem.firstChildElement( QStringLiteral( "contentTextFormat" ) ); + if ( !contentTextFormat.isNull() ) { - mContentFont.fromString( itemElem.attribute( QStringLiteral( "contentFont" ), QString() ) ); + QDomNodeList textFormatNodeList = contentTextFormat.elementsByTagName( QStringLiteral( "text-style" ) ); + QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement(); + mContentTextFormat.readXml( textFormatElem, context ); + } + else + { + QFont contentFont; + if ( !QgsFontUtils::setFromXmlChildNode( contentFont, itemElem, QStringLiteral( "contentFontProperties" ) ) ) + { + contentFont.fromString( itemElem.attribute( QStringLiteral( "contentFont" ), QString() ) ); + } + QColor contentFontColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "contentFontColor" ), QStringLiteral( "0,0,0,255" ) ) ); + mContentTextFormat.setFont( contentFont ); + if ( contentFont.pointSizeF() > 0 ) + { + mContentTextFormat.setSize( contentFont.pointSizeF() ); + mContentTextFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + } + else if ( contentFont.pixelSize() > 0 ) + { + mContentTextFormat.setSize( contentFont.pixelSize() ); + mContentTextFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); + } + mContentTextFormat.setColor( contentFontColor ); } - mContentFontColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "contentFontColor" ), QStringLiteral( "0,0,0,255" ) ) ); + mCellMargin = itemElem.attribute( QStringLiteral( "cellMargin" ), QStringLiteral( "1.0" ) ).toDouble(); mGridStrokeWidth = itemElem.attribute( QStringLiteral( "gridStrokeWidth" ), QStringLiteral( "0.5" ) ).toDouble(); mHorizontalGrid = itemElem.attribute( QStringLiteral( "horizontalGrid" ), QStringLiteral( "1" ) ).toInt(); @@ -233,14 +282,18 @@ void QgsLayoutTable::refresh() refreshAttributes(); } -int QgsLayoutTable::rowsVisible( double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const +int QgsLayoutTable::rowsVisible( QgsRenderContext &context, double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const { //calculate header height double headerHeight = 0; if ( includeHeader ) { - //frame has a header - headerHeight = 2 * ( mShowGrid && mHorizontalGrid ? mGridStrokeWidth : 0 ) + 2 * mCellMargin + QgsLayoutUtils::fontAscentMM( mHeaderFont ); + for ( int col = 0; col < mColumns.count(); ++ col ) + { + const QFontMetricsF headerFontMetrics = QgsTextRenderer::fontMetrics( context, textFormatForHeader( col ), QgsTextRenderer::FONT_WORKAROUND_SCALE ); + //frame has a header + headerHeight = std::max( headerHeight, 2 * ( mShowGrid && mHorizontalGrid ? mGridStrokeWidth : 0 ) + 2 * mCellMargin + headerFontMetrics.ascent() / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) / QgsTextRenderer::FONT_WORKAROUND_SCALE ); + } } else { @@ -263,14 +316,15 @@ int QgsLayoutTable::rowsVisible( double frameHeight, int firstRow, bool includeH if ( includeEmptyRows && contentHeight > 0 ) { - double rowHeight = ( mShowGrid && mHorizontalGrid ? mGridStrokeWidth : 0 ) + 2 * mCellMargin + QgsLayoutUtils::fontAscentMM( mContentFont ); + const QFontMetricsF emptyRowContentFontMetrics = QgsTextRenderer::fontMetrics( context, mContentTextFormat, QgsTextRenderer::FONT_WORKAROUND_SCALE ); + double rowHeight = ( mShowGrid && mHorizontalGrid ? mGridStrokeWidth : 0 ) + 2 * mCellMargin + emptyRowContentFontMetrics.ascent() / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) / QgsTextRenderer::FONT_WORKAROUND_SCALE; currentRow += std::max( std::floor( contentHeight / rowHeight ), 0.0 ); } return currentRow - firstRow - 1; } -int QgsLayoutTable::rowsVisible( int frameIndex, int firstRow, bool includeEmptyRows ) const +int QgsLayoutTable::rowsVisible( QgsRenderContext &context, int frameIndex, int firstRow, bool includeEmptyRows ) const { //get frame extent if ( frameIndex >= frameCount() ) @@ -285,10 +339,10 @@ int QgsLayoutTable::rowsVisible( int frameIndex, int firstRow, bool includeEmpty { includeHeader = true; } - return rowsVisible( frameExtent.height(), firstRow, includeHeader, includeEmptyRows ); + return rowsVisible( context, frameExtent.height(), firstRow, includeHeader, includeEmptyRows ); } -QPair QgsLayoutTable::rowRange( const int frameIndex ) const +QPair QgsLayoutTable::rowRange( QgsRenderContext &context, const int frameIndex ) const { //calculate row height if ( frameIndex >= frameCount() ) @@ -302,12 +356,12 @@ QPair QgsLayoutTable::rowRange( const int frameIndex ) const int rowsAlreadyShown = 0; for ( int idx = 0; idx < frameIndex; ++idx ) { - rowsAlreadyShown += rowsVisible( idx, rowsAlreadyShown, false ); + rowsAlreadyShown += rowsVisible( context, idx, rowsAlreadyShown, false ); } //using zero based indexes int firstVisible = std::min( rowsAlreadyShown, mTableContents.length() ); - int possibleRowsVisible = rowsVisible( frameIndex, rowsAlreadyShown, false ); + int possibleRowsVisible = rowsVisible( context, frameIndex, rowsAlreadyShown, false ); int lastVisible = std::min( firstVisible + possibleRowsVisible, mTableContents.length() ); return qMakePair( firstVisible, lastVisible ); @@ -329,13 +383,16 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & refreshAttributes(); } + const bool prevTextFormatScaleFlag = context.renderContext().testFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering ); + context.renderContext().setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering ); + //calculate which rows to show in this frame - QPair< int, int > rowsToShow = rowRange( frameIndex ); + QPair< int, int > rowsToShow = rowRange( context.renderContext(), frameIndex ); double gridSizeX = mShowGrid && mVerticalGrid ? mGridStrokeWidth : 0; double gridSizeY = mShowGrid && mHorizontalGrid ? mGridStrokeWidth : 0; - double cellHeaderHeight = mMaxRowHeightMap[0] + 2 * mCellMargin;//QgsLayoutUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin; - double cellBodyHeight = QgsLayoutUtils::fontAscentMM( mContentFont ) + 2 * mCellMargin; + double cellHeaderHeight = mMaxRowHeightMap[0] + 2 * mCellMargin; + double cellBodyHeightForEmptyRows = QgsTextRenderer::fontMetrics( context.renderContext(), mContentTextFormat, QgsTextRenderer::FONT_WORKAROUND_SCALE ).ascent() / context.renderContext().convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) / QgsTextRenderer::FONT_WORKAROUND_SCALE + 2 * mCellMargin; QRectF cell; //calculate whether a header is required @@ -348,7 +405,7 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & int numberEmptyRows = 0; if ( drawContents && mShowEmptyRows ) { - numberRowsToDraw = rowsVisible( frameIndex, rowsToShow.first, true ); + numberRowsToDraw = rowsVisible( context.renderContext(), frameIndex, rowsToShow.first, true ); numberEmptyRows = numberRowsToDraw - rowsToShow.second + rowsToShow.first; } bool mergeCells = false; @@ -376,6 +433,7 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & int col = 0; for ( const QgsLayoutTableColumn &column : qgis::as_const( mColumns ) ) { + const QgsTextFormat headerFormat = textFormatForHeader( col ); //draw background p->save(); p->setPen( Qt::NoPen ); @@ -388,32 +446,42 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight ); //calculate alignment of header - Qt::AlignmentFlag headerAlign = Qt::AlignLeft; + QgsTextRenderer::HAlignment headerAlign = QgsTextRenderer::AlignLeft; switch ( mHeaderHAlignment ) { case FollowColumn: - headerAlign = column.hAlignment(); + headerAlign = QgsTextRenderer::convertQtHAlignment( column.hAlignment() ); break; case HeaderLeft: - headerAlign = Qt::AlignLeft; + headerAlign = QgsTextRenderer::AlignLeft; break; case HeaderCenter: - headerAlign = Qt::AlignHCenter; + headerAlign = QgsTextRenderer::AlignCenter; break; case HeaderRight: - headerAlign = Qt::AlignRight; + headerAlign = QgsTextRenderer::AlignRight; break; } + const QRectF textCell = QRectF( currentX, currentY + mCellMargin, mMaxColumnWidthMap[col], cellHeaderHeight - 2 * mCellMargin ); + // disable text clipping to target text rectangle, because we manually clip to the full cell bounds below // and it's ok if text overlaps into the margin (e.g. extenders or italicized text) - QString str = column.heading(); - Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( Qt::TextDontClip ); - if ( ( mWrapBehavior != TruncateText || column.width() > 0 ) && textRequiresWrapping( str, column.width(), mHeaderFont ) ) + QStringList str = column.heading().split( '\n' ); + if ( ( mWrapBehavior != TruncateText || column.width() > 0 ) && textRequiresWrapping( context.renderContext(), column.heading(), column.width(), headerFormat ) ) + { + str = wrappedText( context.renderContext(), column.heading(), column.width(), headerFormat ); + } + + // scale to dots { - str = wrappedText( str, column.width(), mHeaderFont ); + QgsScopedRenderContextScaleToPixels scale( context.renderContext() ); + QgsTextRenderer::drawText( QRectF( textCell.left() * context.renderContext().scaleFactor(), + textCell.top() * context.renderContext().scaleFactor(), + textCell.width() * context.renderContext().scaleFactor(), + textCell.height() * context.renderContext().scaleFactor() ), 0, + headerAlign, str, context.renderContext(), headerFormat, true, QgsTextRenderer::AlignVCenter ); } - QgsLayoutUtils::drawText( p, cell, str, mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag ); currentX += mMaxColumnWidthMap[ col ]; currentX += mCellMargin; @@ -439,7 +507,6 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & //calculate row height double rowHeight = mMaxRowHeightMap[row + 1] + 2 * mCellMargin; - for ( const QgsLayoutTableColumn &column : qgis::as_const( mColumns ) ) { const QRectF fullCell( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, rowHeight ); @@ -454,14 +521,17 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & currentX += mCellMargin; QVariant cellContents = mTableContents.at( row ).at( col ); - QString str = cellContents.toString(); + QStringList str = cellContents.toString().split( '\n' ); + + QgsTextFormat cellFormat = textFormatForCell( row, col ); + QgsExpressionContextScopePopper popper( context.renderContext().expressionContext(), scopeForCell( row, col ) ); + cellFormat.updateDataDefinedProperties( context.renderContext() ); // disable text clipping to target text rectangle, because we manually clip to the full cell bounds below // and it's ok if text overlaps into the margin (e.g. extenders or italicized text) - Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( Qt::TextDontClip ); - if ( ( mWrapBehavior != TruncateText || column.width() > 0 ) && textRequiresWrapping( str, column.width(), mContentFont ) ) + if ( ( mWrapBehavior != TruncateText || column.width() > 0 ) && textRequiresWrapping( context.renderContext(), cellContents.toString(), column.width(), cellFormat ) ) { - str = wrappedText( str, column.width(), mContentFont ); + str = wrappedText( context.renderContext(), cellContents.toString(), column.width(), cellFormat ); } p->save(); @@ -469,11 +539,22 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & const QRectF textCell = QRectF( currentX, currentY + mCellMargin, mMaxColumnWidthMap[col], rowHeight - 2 * mCellMargin ); const QgsConditionalStyle style = conditionalCellStyle( row, col ); - QColor foreColor = mContentFontColor; + QColor foreColor = cellFormat.color(); if ( style.textColor().isValid() ) foreColor = style.textColor(); - QgsLayoutUtils::drawText( p, textCell, str, mContentFont, foreColor, column.hAlignment(), column.vAlignment(), textFlag ); + cellFormat.setColor( foreColor ); + + // scale to dots + { + QgsScopedRenderContextScaleToPixels scale( context.renderContext() ); + QgsTextRenderer::drawText( QRectF( textCell.left() * context.renderContext().scaleFactor(), + textCell.top() * context.renderContext().scaleFactor(), + textCell.width() * context.renderContext().scaleFactor(), + textCell.height() * context.renderContext().scaleFactor() ), 0, + QgsTextRenderer::convertQtHAlignment( horizontalAlignmentForCell( row, col ) ), str, context.renderContext(), cellFormat, true, + QgsTextRenderer::convertQtVAlignment( verticalAlignmentForCell( row, col ) ) ); + } p->restore(); currentX += mMaxColumnWidthMap[ col ]; @@ -500,7 +581,7 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & if ( mergeCells ) { p->setBrush( backgroundColor( row + 10000, 0 ) ); - p->drawRect( QRectF( gridSizeX, currentY, mTableSize.width() - 2 * gridSizeX, cellBodyHeight ) ); + p->drawRect( QRectF( gridSizeX, currentY, mTableSize.width() - 2 * gridSizeX, cellBodyHeightForEmptyRows ) ); } else { @@ -512,7 +593,7 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & //we use a bit of a hack here - since we don't want these extra blank rows to match the firstrow/lastrow rule, add 10000 to row number p->setBrush( backgroundColor( row + 10000, col ) ); - p->drawRect( QRectF( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, cellBodyHeight ) ); + p->drawRect( QRectF( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, cellBodyHeightForEmptyRows ) ); // currentY = gridSize; currentX += mMaxColumnWidthMap[ col ] + 2 * mCellMargin; @@ -520,7 +601,7 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & col++; } } - currentY += cellBodyHeight + gridSizeY; + currentY += cellBodyHeightForEmptyRows + gridSizeY; } p->restore(); } @@ -535,11 +616,11 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & p->setPen( gridPen ); if ( mHorizontalGrid ) { - drawHorizontalGridLines( p, rowsToShow.first, rowsToShow.second + numberEmptyRows, drawHeader ); + drawHorizontalGridLines( context, rowsToShow.first, rowsToShow.second + numberEmptyRows, drawHeader ); } if ( mVerticalGrid ) { - drawVerticalGridLines( p, mMaxColumnWidthMap, rowsToShow.first, rowsToShow.second + numberEmptyRows, drawHeader, mergeCells ); + drawVerticalGridLines( context, mMaxColumnWidthMap, rowsToShow.first, rowsToShow.second + numberEmptyRows, drawHeader, mergeCells ); } } @@ -548,9 +629,20 @@ void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF & { double messageX = gridSizeX + mCellMargin; double messageY = gridSizeY + ( drawHeader ? cellHeaderHeight + gridSizeY : 0 ); - cell = QRectF( messageX, messageY, mTableSize.width() - messageX, cellBodyHeight ); - QgsLayoutUtils::drawText( p, cell, mEmptyTableMessage, mContentFont, mContentFontColor, Qt::AlignHCenter, Qt::AlignVCenter, static_cast< Qt::TextFlag >( 0 ) ); + cell = QRectF( messageX, messageY, mTableSize.width() - messageX, cellBodyHeightForEmptyRows ); + + // scale to dots + { + QgsScopedRenderContextScaleToPixels scale( context.renderContext() ); + QgsTextRenderer::drawText( QRectF( cell.left() * context.renderContext().scaleFactor(), + cell.top() * context.renderContext().scaleFactor(), + cell.width() * context.renderContext().scaleFactor(), + cell.height() * context.renderContext().scaleFactor() ), 0, + QgsTextRenderer::AlignCenter, QStringList() << mEmptyTableMessage, context.renderContext(), mContentTextFormat, true, QgsTextRenderer::AlignVCenter ); + } } + + context.renderContext().setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering, prevTextFormatScaleFlag ); } void QgsLayoutTable::setCellMargin( const double margin ) @@ -612,31 +704,62 @@ void QgsLayoutTable::setShowEmptyRows( const bool showEmpty ) void QgsLayoutTable::setHeaderFont( const QFont &font ) { - if ( font == mHeaderFont ) + mHeaderTextFormat.setFont( font ); + if ( font.pointSizeF() > 0 ) { - return; + mHeaderTextFormat.setSize( font.pointSizeF() ); + mHeaderTextFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + } + else if ( font.pixelSize() > 0 ) + { + mHeaderTextFormat.setSize( font.pixelSize() ); + mHeaderTextFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); } - mHeaderFont = font; //since font attributes have changed, we need to recalculate the table size recalculateTableSize(); emit changed(); } +QFont QgsLayoutTable::headerFont() const +{ + return mHeaderTextFormat.toQFont(); +} + void QgsLayoutTable::setHeaderFontColor( const QColor &color ) { - if ( color == mHeaderFontColor ) + if ( color == mHeaderTextFormat.color() ) { return; } - mHeaderFontColor = color; + mHeaderTextFormat.setColor( color ); update(); emit changed(); } +QColor QgsLayoutTable::headerFontColor() const +{ + return mHeaderTextFormat.color(); +} + +void QgsLayoutTable::setHeaderTextFormat( const QgsTextFormat &format ) +{ + mHeaderTextFormat = format; + + //since font attributes have changed, we need to recalculate the table size + recalculateTableSize(); + + emit changed(); +} + +QgsTextFormat QgsLayoutTable::headerTextFormat() const +{ + return mHeaderTextFormat; +} + void QgsLayoutTable::setHeaderHAlignment( const QgsLayoutTable::HeaderHAlignment alignment ) { if ( alignment == mHeaderHAlignment ) @@ -665,31 +788,62 @@ void QgsLayoutTable::setHeaderMode( const QgsLayoutTable::HeaderMode mode ) void QgsLayoutTable::setContentFont( const QFont &font ) { - if ( font == mContentFont ) + mContentTextFormat.setFont( font ); + if ( font.pointSizeF() > 0 ) { - return; + mContentTextFormat.setSize( font.pointSizeF() ); + mContentTextFormat.setSizeUnit( QgsUnitTypes::RenderPoints ); + } + else if ( font.pixelSize() > 0 ) + { + mContentTextFormat.setSize( font.pixelSize() ); + mContentTextFormat.setSizeUnit( QgsUnitTypes::RenderPixels ); } - mContentFont = font; //since font attributes have changed, we need to recalculate the table size recalculateTableSize(); emit changed(); } +QFont QgsLayoutTable::contentFont() const +{ + return mContentTextFormat.toQFont(); +} + void QgsLayoutTable::setContentFontColor( const QColor &color ) { - if ( color == mContentFontColor ) + if ( color == mContentTextFormat.color() ) { return; } - mContentFontColor = color; + mContentTextFormat.setColor( color ); update(); emit changed(); } +QColor QgsLayoutTable::contentFontColor() const +{ + return mContentTextFormat.color(); +} + +void QgsLayoutTable::setContentTextFormat( const QgsTextFormat &format ) +{ + mContentTextFormat = format; + + //since spacing has changed, we need to recalculate the table size + recalculateTableSize(); + + emit changed(); +} + +QgsTextFormat QgsLayoutTable::contentTextFormat() const +{ + return mContentTextFormat; +} + void QgsLayoutTable::setShowGrid( const bool showGrid ) { if ( showGrid == mShowGrid ) @@ -837,6 +991,14 @@ QMap QgsLayoutTable::headerLabels() const return headers; } +QgsExpressionContextScope *QgsLayoutTable::scopeForCell( int row, int column ) const +{ + std::unique_ptr< QgsExpressionContextScope > cellScope = qgis::make_unique< QgsExpressionContextScope >(); + cellScope->setVariable( QStringLiteral( "row_number" ), row + 1, true ); + cellScope->setVariable( QStringLiteral( "column_number" ), column + 1, true ); + return cellScope.release(); +} + QgsConditionalStyle QgsLayoutTable::conditionalCellStyle( int, int ) const { return QgsConditionalStyle(); @@ -850,12 +1012,18 @@ QSizeF QgsLayoutTable::fixedFrameSize( const int frameIndex ) const QSizeF QgsLayoutTable::minFrameSize( const int frameIndex ) const { + QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( mLayout, nullptr ); + context.setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering ); + double height = 0; if ( ( mHeaderMode == QgsLayoutTable::FirstFrame && frameIndex < 1 ) || ( mHeaderMode == QgsLayoutTable::AllFrames ) ) { //header required, force frame to be high enough for header - height = 2 * ( mShowGrid ? mGridStrokeWidth : 0 ) + 2 * mCellMargin + QgsLayoutUtils::fontAscentMM( mHeaderFont ); + for ( int col = 0; col < mColumns.size(); ++ col ) + { + height = std::max( height, 2 * ( mShowGrid ? mGridStrokeWidth : 0 ) + 2 * mCellMargin + QgsTextRenderer::fontMetrics( context, textFormatForHeader( col ), QgsTextRenderer::FONT_WORKAROUND_SCALE ).ascent() / QgsTextRenderer::FONT_WORKAROUND_SCALE / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) ); + } } return QSizeF( 0, height ); } @@ -913,6 +1081,9 @@ bool QgsLayoutTable::calculateMaxColumnWidths() double currentCellTextWidth; + QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( mLayout, nullptr ); + context.setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering ); + //first, go through all the column headers and calculate the sizes int i = 0; for ( const QgsLayoutTableColumn &col : qgis::as_const( mColumns ) ) @@ -925,13 +1096,8 @@ bool QgsLayoutTable::calculateMaxColumnWidths() else if ( mHeaderMode != QgsLayoutTable::NoHeaders ) { //column width set to automatic, so check content size - QStringList multiLineSplit = col.heading().split( '\n' ); - currentCellTextWidth = 0; - const auto constMultiLineSplit = multiLineSplit; - for ( const QString &line : constMultiLineSplit ) - { - currentCellTextWidth = std::max( currentCellTextWidth, QgsLayoutUtils::textWidthMM( mHeaderFont, line ) ); - } + const QStringList multiLineSplit = col.heading().split( '\n' ); + currentCellTextWidth = QgsTextRenderer::textWidth( context, textFormatForHeader( i ), multiLineSplit ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); widths[i] = currentCellTextWidth; } else @@ -953,13 +1119,13 @@ bool QgsLayoutTable::calculateMaxColumnWidths() if ( mColumns.at( col ).width() <= 0 ) { //column width set to automatic, so check content size - QStringList multiLineSplit = ( *colIt ).toString().split( '\n' ); - currentCellTextWidth = 0; - const auto constMultiLineSplit = multiLineSplit; - for ( const QString &line : constMultiLineSplit ) - { - currentCellTextWidth = std::max( currentCellTextWidth, QgsLayoutUtils::textWidthMM( mContentFont, line ) ); - } + const QStringList multiLineSplit = ( *colIt ).toString().split( '\n' ); + + QgsTextFormat cellFormat = textFormatForCell( row - 1, col ); + QgsExpressionContextScopePopper popper( context.expressionContext(), scopeForCell( row - 1, col ) ); + cellFormat.updateDataDefinedProperties( context ); + + currentCellTextWidth = QgsTextRenderer::textWidth( context, cellFormat, multiLineSplit ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); widths[ row * cols + col ] = currentCellTextWidth; } else @@ -995,23 +1161,31 @@ bool QgsLayoutTable::calculateMaxRowHeights() int cells = cols * ( mTableContents.count() + 1 ); QVector< double > heights( cells ); + QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( mLayout, nullptr ); + context.setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering ); + //first, go through all the column headers and calculate the sizes int i = 0; for ( const QgsLayoutTableColumn &col : qgis::as_const( mColumns ) ) { + const QgsTextFormat cellFormat = textFormatForHeader( i ); + const double headerDescentMm = QgsTextRenderer::fontMetrics( context, cellFormat, QgsTextRenderer::FONT_WORKAROUND_SCALE ).descent() / QgsTextRenderer::FONT_WORKAROUND_SCALE / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); //height if ( mHeaderMode == QgsLayoutTable::NoHeaders ) { heights[i] = 0; } - else if ( textRequiresWrapping( col.heading(), mColumns.at( i ).width(), mHeaderFont ) ) + else if ( textRequiresWrapping( context, col.heading(), mColumns.at( i ).width(), cellFormat ) ) { //contents too wide for cell, need to wrap - heights[i] = QgsLayoutUtils::textHeightMM( mHeaderFont, wrappedText( col.heading(), mColumns.at( i ).width(), mHeaderFont ) ); + heights[i] = QgsTextRenderer::textHeight( context, cellFormat, wrappedText( context, col.heading(), mColumns.at( i ).width(), cellFormat ), QgsTextRenderer::Rect ) + / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) + - headerDescentMm; } else { - heights[i] = QgsLayoutUtils::textHeightMM( mHeaderFont, col.heading() ); + heights[i] = QgsTextRenderer::textHeight( context, cellFormat, QStringList() << col.heading(), QgsTextRenderer::Rect ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) + - headerDescentMm; } i++; } @@ -1025,14 +1199,19 @@ bool QgsLayoutTable::calculateMaxRowHeights() int i = 0; for ( ; colIt != rowIt->constEnd(); ++colIt ) { - if ( textRequiresWrapping( ( *colIt ).toString(), mColumns.at( i ).width(), mContentFont ) ) + QgsTextFormat cellFormat = textFormatForCell( row - 1, i ); + QgsExpressionContextScopePopper popper( context.expressionContext(), scopeForCell( row - 1, i ) ); + cellFormat.updateDataDefinedProperties( context ); + const double contentDescentMm = QgsTextRenderer::fontMetrics( context, cellFormat, QgsTextRenderer::FONT_WORKAROUND_SCALE ).descent() / QgsTextRenderer::FONT_WORKAROUND_SCALE / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); + + if ( textRequiresWrapping( context, ( *colIt ).toString(), mColumns.at( i ).width(), cellFormat ) ) { //contents too wide for cell, need to wrap - heights[ row * cols + i ] = QgsLayoutUtils::textHeightMM( mContentFont, wrappedText( ( *colIt ).toString(), mColumns.at( i ).width(), mContentFont ) ); + heights[ row * cols + i ] = QgsTextRenderer::textHeight( context, cellFormat, wrappedText( context, ( *colIt ).toString(), mColumns.at( i ).width(), cellFormat ), QgsTextRenderer::Rect ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) - contentDescentMm; } else { - heights[ row * cols + i ] = QgsLayoutUtils::textHeightMM( mContentFont, ( *colIt ).toString() ); + heights[ row * cols + i ] = QgsTextRenderer::textHeight( context, cellFormat, QStringList() << ( *colIt ).toString().split( '\n' ), QgsTextRenderer::Rect ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ) - contentDescentMm; } i++; @@ -1085,6 +1264,9 @@ double QgsLayoutTable::totalHeight() double height = 0; + QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( mLayout, nullptr ); + context.setFlag( QgsRenderContext::ApplyScalingWorkaroundForTextRendering ); + //loop through all existing frames to calculate how many rows are visible in each //as the entire height of a frame may not be utilized for content rows int rowsAlreadyShown = 0; @@ -1096,7 +1278,7 @@ double QgsLayoutTable::totalHeight() bool hasHeader = ( ( mHeaderMode == QgsLayoutTable::FirstFrame && idx == 0 ) || ( mHeaderMode == QgsLayoutTable::AllFrames ) ); heightOfLastFrame = frame( idx )->rect().height(); - rowsVisibleInLastFrame = rowsVisible( heightOfLastFrame, rowsAlreadyShown, hasHeader, false ); + rowsVisibleInLastFrame = rowsVisible( context, heightOfLastFrame, rowsAlreadyShown, hasHeader, false ); rowsAlreadyShown += rowsVisibleInLastFrame; height += heightOfLastFrame; if ( rowsAlreadyShown >= mTableContents.length() ) @@ -1130,7 +1312,7 @@ double QgsLayoutTable::totalHeight() { numberFramesMissing++; - rowsVisibleInLastFrame = rowsVisible( heightOfLastFrame, rowsAlreadyShown, hasHeader, false ); + rowsVisibleInLastFrame = rowsVisible( context, heightOfLastFrame, rowsAlreadyShown, hasHeader, false ); if ( rowsVisibleInLastFrame < 1 ) { //if no rows are visible in the last frame, calculation of missing frames @@ -1148,7 +1330,7 @@ double QgsLayoutTable::totalHeight() return height; } -void QgsLayoutTable::drawHorizontalGridLines( QPainter *painter, int firstRow, int lastRow, bool drawHeaderLines ) const +void QgsLayoutTable::drawHorizontalGridLines( QgsLayoutItemRenderContext &context, int firstRow, int lastRow, bool drawHeaderLines ) const { //horizontal lines if ( lastRow - firstRow < 1 && !drawHeaderLines ) @@ -1156,7 +1338,9 @@ void QgsLayoutTable::drawHorizontalGridLines( QPainter *painter, int firstRow, i return; } - double cellBodyHeight = QgsLayoutUtils::fontAscentMM( mContentFont ); + QPainter *painter = context.renderContext().painter(); + + double cellBodyHeightForEmptyRows = QgsTextRenderer::fontMetrics( context.renderContext(), mContentTextFormat, QgsTextRenderer::FONT_WORKAROUND_SCALE ).ascent() / QgsTextRenderer::FONT_WORKAROUND_SCALE / context.renderContext().convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); double halfGridStrokeWidth = ( mShowGrid ? mGridStrokeWidth : 0 ) / 2.0; double currentY = 0; currentY = halfGridStrokeWidth; @@ -1170,36 +1354,30 @@ void QgsLayoutTable::drawHorizontalGridLines( QPainter *painter, int firstRow, i { painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) ); currentY += ( mShowGrid ? mGridStrokeWidth : 0 ); - double rowHeight = row < mTableContents.count() ? mMaxRowHeightMap[row + 1] : cellBodyHeight; + double rowHeight = row < mTableContents.count() ? mMaxRowHeightMap[row + 1] : cellBodyHeightForEmptyRows; currentY += ( rowHeight + 2 * mCellMargin ); } painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF( mTableSize.width() - halfGridStrokeWidth, currentY ) ); } -bool QgsLayoutTable::textRequiresWrapping( const QString &text, double columnWidth, const QFont &font ) const +bool QgsLayoutTable::textRequiresWrapping( QgsRenderContext &context, const QString &text, double columnWidth, const QgsTextFormat &format ) const { if ( qgsDoubleNear( columnWidth, 0.0 ) || mWrapBehavior != WrapText ) return false; - QStringList multiLineSplit = text.split( '\n' ); - double currentTextWidth = 0; - const auto constMultiLineSplit = multiLineSplit; - for ( const QString &line : constMultiLineSplit ) - { - currentTextWidth = std::max( currentTextWidth, QgsLayoutUtils::textWidthMM( font, line ) ); - } - - return ( currentTextWidth > columnWidth ); + const QStringList multiLineSplit = text.split( '\n' ); + const double currentTextWidth = QgsTextRenderer::textWidth( context, format, multiLineSplit ) / context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); + return currentTextWidth > columnWidth; } -QString QgsLayoutTable::wrappedText( const QString &value, double columnWidth, const QFont &font ) const +QStringList QgsLayoutTable::wrappedText( QgsRenderContext &context, const QString &value, double columnWidth, const QgsTextFormat &format ) const { QStringList lines = value.split( '\n' ); QStringList outLines; const auto constLines = lines; for ( const QString &line : constLines ) { - if ( textRequiresWrapping( line, columnWidth, font ) ) + if ( textRequiresWrapping( context, line, columnWidth, format ) ) { //first step is to identify words which must be on their own line (too long to fit) QStringList words = line.split( ' ' ); @@ -1208,7 +1386,7 @@ QString QgsLayoutTable::wrappedText( const QString &value, double columnWidth, c const auto constWords = words; for ( const QString &word : constWords ) { - if ( textRequiresWrapping( word, columnWidth, font ) ) + if ( textRequiresWrapping( context, word, columnWidth, format ) ) { //too long to fit if ( !wordsInCurrentLine.isEmpty() ) @@ -1234,12 +1412,12 @@ QString QgsLayoutTable::wrappedText( const QString &value, double columnWidth, c while ( lastPos > -1 ) { //check if remaining text is short enough to go in one line - if ( !textRequiresWrapping( remainingText, columnWidth, font ) ) + if ( !textRequiresWrapping( context, remainingText, columnWidth, format ) ) { break; } - if ( !textRequiresWrapping( remainingText.left( lastPos ), columnWidth, font ) ) + if ( !textRequiresWrapping( context, remainingText.left( lastPos ), columnWidth, format ) ) { outLines << remainingText.left( lastPos ); remainingText = remainingText.mid( lastPos + 1 ); @@ -1256,7 +1434,7 @@ QString QgsLayoutTable::wrappedText( const QString &value, double columnWidth, c } } - return outLines.join( QStringLiteral( "\n" ) ); + return outLines; } QColor QgsLayoutTable::backgroundColor( int row, int column ) const @@ -1300,7 +1478,7 @@ QColor QgsLayoutTable::backgroundColor( int row, int column ) const return color; } -void QgsLayoutTable::drawVerticalGridLines( QPainter *painter, const QMap &maxWidthMap, int firstRow, int lastRow, bool hasHeader, bool mergeCells ) const +void QgsLayoutTable::drawVerticalGridLines( QgsLayoutItemRenderContext &context, const QMap &maxWidthMap, int firstRow, int lastRow, bool hasHeader, bool mergeCells ) const { //vertical lines if ( lastRow - firstRow < 1 && !hasHeader ) @@ -1308,6 +1486,8 @@ void QgsLayoutTable::drawVerticalGridLines( QPainter *painter, const QMap= 0 ); } +QgsTextFormat QgsLayoutTable::textFormatForCell( int, int ) const +{ + return mContentTextFormat; +} + +QgsTextFormat QgsLayoutTable::textFormatForHeader( int ) const +{ + return mHeaderTextFormat; +} + +Qt::Alignment QgsLayoutTable::horizontalAlignmentForCell( int, int column ) const +{ + return mColumns.value( column ).hAlignment(); +} + +Qt::Alignment QgsLayoutTable::verticalAlignmentForCell( int, int column ) const +{ + return mColumns.value( column ).vAlignment(); +} + diff --git a/src/core/layout/qgslayouttable.h b/src/core/layout/qgslayouttable.h index 9cc2fa80c513..766ab5b86c1b 100644 --- a/src/core/layout/qgslayouttable.h +++ b/src/core/layout/qgslayouttable.h @@ -22,6 +22,7 @@ #include "qgis_sip.h" #include "qgslayoutmultiframe.h" #include "qgsconditionalstyle.h" +#include "qgstextformat.h" #include #include #include @@ -237,31 +238,51 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame * Sets the \a font used to draw header text in the table. * \see headerFont() * \see setContentFont() + * \deprecated use setHeaderTextFormat() instead */ - void setHeaderFont( const QFont &font ); + Q_DECL_DEPRECATED void setHeaderFont( const QFont &font ) SIP_DEPRECATED; /** * Returns the font used to draw header text in the table. * \see setHeaderFont() * \see contentFont() + * \deprecated use headerTextFormat() instead */ - QFont headerFont() const { return mHeaderFont; } + Q_DECL_DEPRECATED QFont headerFont() const SIP_DEPRECATED; /** * Sets the \a color used to draw header text in the table. * \see headerFontColor() * \see setHeaderFont() * \see setContentFontColor() + * \deprecated use setHeaderTextFormat() instead */ - void setHeaderFontColor( const QColor &color ); + Q_DECL_DEPRECATED void setHeaderFontColor( const QColor &color ) SIP_DEPRECATED; /** * Returns the color used to draw header text in the table. * \see setHeaderFontColor() * \see headerFont() * \see contentFontColor() + * \deprecated use headerTextFormat() instead */ - QColor headerFontColor() const { return mHeaderFontColor; } + Q_DECL_DEPRECATED QColor headerFontColor() const SIP_DEPRECATED; + + /** + * Sets the \a format used to draw header text in the table. + * \see headerTextFormat() + * \see setContentTextFormat() + * \since QGIS 3.16 + */ + void setHeaderTextFormat( const QgsTextFormat &format ); + + /** + * Returns the format used to draw header text in the table. + * \see setHeaderTextFormat() + * \see contentTextFormat() + * \since QGIS 3.16 + */ + QgsTextFormat headerTextFormat() const; /** * Sets the horizontal \a alignment for table headers. @@ -293,31 +314,51 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame * Sets the \a font used to draw text in table body cells. * \see contentFont() * \see setHeaderFont() + * \deprecated use setContentTextFormat() instead */ - void setContentFont( const QFont &font ); + Q_DECL_DEPRECATED void setContentFont( const QFont &font ) SIP_DEPRECATED; /** * Returns the font used to draw text in table body cells. * \see setContentFont() * \see headerFont() + * \deprecated use contextTextFormat() instead */ - QFont contentFont() const { return mContentFont; } + Q_DECL_DEPRECATED QFont contentFont() const SIP_DEPRECATED; /** * Sets the \a color used to draw text in table body cells. * \see contentFontColor() * \see setContentFont() * \see setHeaderFontColor() + * \deprecated use setContentTextFormat() instead */ - void setContentFontColor( const QColor &color ); + Q_DECL_DEPRECATED void setContentFontColor( const QColor &color ) SIP_DEPRECATED; /** * Returns the color used to draw text in table body cells. * \see setContentFontColor() * \see contentFont() * \see headerFontColor() + * \deprecated use contextTextFormat() instead + */ + Q_DECL_DEPRECATED QColor contentFontColor() const SIP_DEPRECATED; + + /** + * Sets the \a format used to draw content text in the table. + * \see contentTextFormat() + * \see setHeaderTextFormat() + * \since QGIS 3.16 */ - QColor contentFontColor() const { return mContentFontColor; } + void setContentTextFormat( const QgsTextFormat &format ); + + /** + * Returns the format used to draw content text in the table. + * \see setContentTextFormat() + * \see headerTextFormat() + * \since QGIS 3.16 + */ + QgsTextFormat contentTextFormat() const; /** * Sets whether grid lines should be drawn in the table @@ -496,6 +537,13 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame */ virtual QgsConditionalStyle conditionalCellStyle( int row, int column ) const; + /** + * Creates a new QgsExpressionContextScope for the cell at \a row, \a column. + * + * \since QGIS 3.16 + */ + virtual QgsExpressionContextScope *scopeForCell( int row, int column ) const SIP_FACTORY; + /** * Returns the current contents of the table. Excludes header cells. */ @@ -535,11 +583,6 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame //! True if empty rows should be shown in the table bool mShowEmptyRows = false; - //! Header font - QFont mHeaderFont; - - //! Header font color - QColor mHeaderFontColor = Qt::black; //! Alignment for table headers HeaderHAlignment mHeaderHAlignment = FollowColumn; @@ -547,11 +590,8 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame //! Header display mode HeaderMode mHeaderMode = FirstFrame; - //! Table contents font - QFont mContentFont; - - //! Table contents font color - QColor mContentFontColor = Qt::black; + QgsTextFormat mHeaderTextFormat; + QgsTextFormat mContentTextFormat; //! True if grid should be shown bool mShowGrid = true; @@ -620,6 +660,7 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame /** * Calculates how many content rows would be visible within a frame of the specified * height. + * \param context render context * \param frameHeight height of frame * \param firstRow index of first row visible in frame (where 0 = first row in table) * \param includeHeader set to TRUE if frame would include a header row @@ -628,10 +669,11 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame * to TRUE would also include a count of these extra blank rows. * \returns number of visible content rows (excluding header row) */ - int rowsVisible( double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const; + int rowsVisible( QgsRenderContext &context, double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const; /** * Calculates how many content rows are visible within a given frame. + * \param context render context * \param frameIndex index number for frame * \param firstRow index of first row visible in frame (where 0 = first row in table) * \param includeEmptyRows set to TRUE to also include rows which would be empty in the returned count. For instance, @@ -639,29 +681,30 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame * to TRUE would also include a count of these extra blank rows. * \returns number of visible content rows (excludes header rows) */ - int rowsVisible( int frameIndex, int firstRow, bool includeEmptyRows ) const; + int rowsVisible( QgsRenderContext &context, int frameIndex, int firstRow, bool includeEmptyRows ) const; /** * Calculates a range of rows which should be visible in a given frame. + * \param context render context * \param frameIndex index number for frame * \returns row range */ - QPair rowRange( int frameIndex ) const; + QPair rowRange( QgsRenderContext &context, int frameIndex ) const; /** * Draws the horizontal grid lines for the table. - * \param painter destination painter for grid lines + * \param context destination render context * \param firstRow index corresponding to first row shown in frame * \param lastRow index corresponding to last row shown in frame. If greater than the number of content rows in the * table, then the default row height will be used for the remaining rows. * \param drawHeaderLines set to TRUE to include for the table header * \see drawVerticalGridLines() */ - void drawHorizontalGridLines( QPainter *painter, int firstRow, int lastRow, bool drawHeaderLines ) const; + void drawHorizontalGridLines( QgsLayoutItemRenderContext &context, int firstRow, int lastRow, bool drawHeaderLines ) const; /** * Draws the vertical grid lines for the table. - * \param painter destination painter for grid lines + * \param context destination render context * \param maxWidthMap QMap of int to double, where the int contains the column number and the double is the * maximum width of text present in the column. * \param firstRow index corresponding to first row shown in frame @@ -674,7 +717,7 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame * \see calculateMaxColumnWidths() * \note not available in Python bindings */ - void drawVerticalGridLines( QPainter *painter, const QMap &maxWidthMap, int firstRow, int lastRow, bool hasHeader, bool mergeCells = false ) const SIP_SKIP; + void drawVerticalGridLines( QgsLayoutItemRenderContext &context, const QMap &maxWidthMap, int firstRow, int lastRow, bool hasHeader, bool mergeCells = false ) const SIP_SKIP; /** * Recalculates and updates the size of the table and all table frames. @@ -689,6 +732,38 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame */ bool contentsContainsRow( const QgsLayoutTableContents &contents, const QgsLayoutTableRow &row ) const; + /** + * Returns the text format to use for the cell at the specified \a row and \a column. + * + * \see textFormatForHeader() + * \since QGIS 3.16 + */ + virtual QgsTextFormat textFormatForCell( int row, int column ) const; + + /** + * Returns the text format to use for the header cell at the specified \a column. + * + * \see textFormatForCell() + * \since QGIS 3.16 + */ + virtual QgsTextFormat textFormatForHeader( int column ) const; + + /** + * Returns the horizontal alignment to use for the cell at the specified \a row and \a column. + * + * \see verticalAlignmentForCell() + * \since QGIS 3.16 + */ + virtual Qt::Alignment horizontalAlignmentForCell( int row, int column ) const; + + /** + * Returns the vertical alignment to use for the cell at the specified \a row and \a column. + * + * \see horizontalAlignmentForCell() + * \since QGIS 3.16 + */ + virtual Qt::Alignment verticalAlignmentForCell( int row, int column ) const; + private: QMap< CellStyleGroup, QString > mCellStyleNames; @@ -696,9 +771,9 @@ class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame //! Initializes cell style map void initStyles(); - bool textRequiresWrapping( const QString &text, double columnWidth, const QFont &font ) const; + bool textRequiresWrapping( QgsRenderContext &context, const QString &text, double columnWidth, const QgsTextFormat &format ) const; - QString wrappedText( const QString &value, double columnWidth, const QFont &font ) const; + QStringList wrappedText( QgsRenderContext &context, const QString &value, double columnWidth, const QgsTextFormat &format ) const; /** * Returns the calculated background color for a row and column combination. diff --git a/src/core/providers/ogr/qgsgeopackagedataitems.cpp b/src/core/providers/ogr/qgsgeopackagedataitems.cpp index 70d33257166e..fee19c61c397 100644 --- a/src/core/providers/ogr/qgsgeopackagedataitems.cpp +++ b/src/core/providers/ogr/qgsgeopackagedataitems.cpp @@ -67,7 +67,7 @@ QgsDataItem *QgsGeoPackageDataItemProvider::createDataItem( const QString &path, } QgsGeoPackageRootItem::QgsGeoPackageRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "GPKG" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "GPKG" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mGeoPackage.svg" ); @@ -315,7 +315,16 @@ QgsGeoPackageCollectionItem *QgsGeoPackageAbstractLayerItem::collection() const QgsGeoPackageVectorLayerItem::QgsGeoPackageVectorLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType ) : QgsGeoPackageAbstractLayerItem( parent, name, path, uri, layerType, QStringLiteral( "ogr" ) ) { - mCapabilities |= Rename; + mCapabilities |= ( Rename | Fertile ); + setState( QgsDataItem::State::NotPopulated ); +} + + +QVector QgsGeoPackageVectorLayerItem::createChildren() +{ + QVector children; + children.push_back( new QgsFieldsItem( this, collection()->path() + QStringLiteral( "/columns/ " ), collection()->path(), providerKey(), QString(), name() ) ); + return children; } diff --git a/src/core/providers/ogr/qgsgeopackagedataitems.h b/src/core/providers/ogr/qgsgeopackagedataitems.h index 860d9c7a2ccc..2653069b7b44 100644 --- a/src/core/providers/ogr/qgsgeopackagedataitems.h +++ b/src/core/providers/ogr/qgsgeopackagedataitems.h @@ -126,6 +126,8 @@ class CORE_EXPORT QgsGeoPackageVectorLayerItem final: public QgsGeoPackageAbstra QgsGeoPackageVectorLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType ); bool executeDeleteLayer( QString &errCause ) override; + // QgsDataItem interface + QVector createChildren() override; }; /** @@ -142,7 +144,7 @@ class CORE_EXPORT QgsGeoPackageConnectionItem final: public QgsGeoPackageCollect }; -class CORE_EXPORT QgsGeoPackageRootItem final: public QgsDataCollectionItem +class CORE_EXPORT QgsGeoPackageRootItem final: public QgsConnectionsRootItem { Q_OBJECT diff --git a/src/core/providers/ogr/qgsgeopackageproviderconnection.cpp b/src/core/providers/ogr/qgsgeopackageproviderconnection.cpp index bfb97357d676..5b2fbfcd42fa 100644 --- a/src/core/providers/ogr/qgsgeopackageproviderconnection.cpp +++ b/src/core/providers/ogr/qgsgeopackageproviderconnection.cpp @@ -24,6 +24,7 @@ QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &name ) : QgsAbstractDatabaseProviderConnection( name ) { + mProviderKey = QStringLiteral( "ogr" ); setDefaultCapabilities(); QgsSettings settings; settings.beginGroup( QStringLiteral( "ogr" ), QgsSettings::Section::Providers ); @@ -36,6 +37,7 @@ QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &uri, const QVariantMap &configuration ): QgsAbstractDatabaseProviderConnection( uri, configuration ) { + mProviderKey = QStringLiteral( "ogr" ); // Cleanup the URI in case it contains other information other than the file path if ( uri.contains( '|' ) ) { @@ -186,8 +188,29 @@ void QgsGeoPackageProviderConnection::createSpatialIndex( const QString &schema, { QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info ); } + + QString geometryColumnName { options.geometryColumnName }; + if ( geometryColumnName.isEmpty() ) + { + // Can we guess it? + try + { + const auto tp { table( schema, name ) }; + geometryColumnName = tp.geometryColumn(); + } + catch ( QgsProviderConnectionException & ) + { + // pass + } + } + + if ( geometryColumnName.isEmpty() ) + { + throw QgsProviderConnectionException( QObject::tr( "Geometry column name not specified while creating spatial index" ) ); + } + executeGdalSqlPrivate( QStringLiteral( "SELECT CreateSpatialIndex(%1, %2)" ).arg( QgsSqliteUtils::quotedString( name ), - QgsSqliteUtils::quotedString( ( options.geometryColumnName ) ) ) ); + QgsSqliteUtils::quotedString( ( geometryColumnName ) ) ) ); } bool QgsGeoPackageProviderConnection::spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const @@ -315,11 +338,20 @@ void QgsGeoPackageProviderConnection::setDefaultCapabilities() Capability::ExecuteSql, Capability::CreateSpatialIndex, Capability::SpatialIndexExists, - Capability::DeleteSpatialIndex + Capability::DeleteSpatialIndex, + Capability::DeleteField, + Capability::AddField }; #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) mCapabilities |= Capability::DropRasterTable; #endif + mGeometryColumnCapabilities = + { + GeometryColumnCapability::Z, + GeometryColumnCapability::M, + GeometryColumnCapability::SinglePart, + GeometryColumnCapability::Curves + }; } QList QgsGeoPackageProviderConnection::executeGdalSqlPrivate( const QString &sql ) const @@ -376,3 +408,14 @@ QList QgsGeoPackageProviderConnection::executeGdalSqlPrivate( cons return results; } + +QList QgsGeoPackageProviderConnection::nativeTypes() const +{ + QList types; + QgsVectorLayer vl { uri(), QStringLiteral( "temp_layer" ), QStringLiteral( "ogr" ) }; + if ( ! vl.isValid() || ! vl.dataProvider() ) + { + throw QgsProviderConnectionException( QObject::tr( "Error retrieving native types for %1: %2" ).arg( uri() ).arg( vl.dataProvider()->errors().join( '\n' ) ) ); + } + return vl.dataProvider()->nativeTypes(); +} diff --git a/src/core/providers/ogr/qgsgeopackageproviderconnection.h b/src/core/providers/ogr/qgsgeopackageproviderconnection.h index 652a7676917b..da9cd381cc28 100644 --- a/src/core/providers/ogr/qgsgeopackageproviderconnection.h +++ b/src/core/providers/ogr/qgsgeopackageproviderconnection.h @@ -46,6 +46,7 @@ class QgsGeoPackageProviderConnection : public QgsAbstractDatabaseProviderConnec QList tables( const QString &schema = QString(), const TableFlags &flags = nullptr ) const override; QIcon icon() const override; + QList nativeTypes() const override; private: @@ -55,5 +56,7 @@ class QgsGeoPackageProviderConnection : public QgsAbstractDatabaseProviderConnec }; + + ///@endcond #endif // QGSGEOPACKAGEPROVIDERCONNECTION_H diff --git a/src/core/providers/ogr/qgsogrdataitems.cpp b/src/core/providers/ogr/qgsogrdataitems.cpp index 77205c33ddea..b73b6754860b 100644 --- a/src/core/providers/ogr/qgsogrdataitems.cpp +++ b/src/core/providers/ogr/qgsogrdataitems.cpp @@ -44,12 +44,36 @@ #include QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem *parent, - const QString &name, const QString &path, const QString &uri, LayerType layerType, bool isSubLayer ) + const QString &name, + const QString &path, + const QString &uri, + LayerType layerType, + const QString &driverName, + bool isSubLayer ) : QgsLayerItem( parent, name, path, uri, layerType, QStringLiteral( "ogr" ) ) + , mDriverName( driverName ) + , mIsSubLayer( isSubLayer ) { mIsSubLayer = isSubLayer; mToolTip = uri; - setState( Populated ); // children are not expected + const bool isIndex { QRegularExpression( R"(=idx_[^_]+_[^_]+.*$)" ).match( uri ).hasMatch() }; + setState( ( driverName == QStringLiteral( "SQLite" ) && ! isIndex ) ? NotPopulated : Populated ); // children are accepted except for sqlite +} + + +QVector QgsOgrLayerItem::createChildren() +{ + QVector children; + // Geopackage is handled by QgsGeoPackageVectorLayerItem and QgsGeoPackageRasterLayerItem + // Proxy to spatialite provider data items because it implements the connections API + if ( mDriverName == QStringLiteral( "SQLite" ) ) + { + children.push_back( new QgsFieldsItem( this, + path() + QStringLiteral( "/columns/ " ), + QStringLiteral( R"(dbname="%1")" ).arg( parent()->path().replace( '"', QStringLiteral( R"(\")" ) ) ), + QStringLiteral( "spatialite" ), QString(), name() ) ); + } + return children; } @@ -171,14 +195,14 @@ QList QgsOgrLayerItem::subLayers( const QString &path, cons uri += QStringLiteral( "|geometrytype=" ) + geometryType; } QgsDebugMsgLevel( QStringLiteral( "Adding %1 Vector item %2 %3 %4" ).arg( driver, name, uri, geometryType ), 3 ); - children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, layerType ) ); + children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, layerType, driver ) ); } } else { QgsDebugMsgLevel( QStringLiteral( "Layer type is not a supported %1 Vector layer %2" ).arg( driver, path ), 3 ); uri = QStringLiteral( "%1|layerid=%2|layername=%3" ).arg( path, layerId, name ); - children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, QgsLayerItem::LayerType::TableLayer ) ); + children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, QgsLayerItem::LayerType::TableLayer, driver ) ); } QgsDebugMsgLevel( QStringLiteral( "Adding %1 Vector item %2 %3 %4" ).arg( driver, name, uri, geometryType ), 3 ); } @@ -198,7 +222,7 @@ QList QgsOgrLayerItem::subLayers( const QString &path, cons QStringList pieces = uri.split( ':' ); QString name = pieces.value( pieces.length() - 1 ); QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Raster item %1 %2" ).arg( name, uri ), 3 ); - children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) ); + children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster, driver ) ); } } else if ( rlayer.isValid( ) ) @@ -232,7 +256,7 @@ QList QgsOgrLayerItem::subLayers( const QString &path, cons } QgsDebugMsgLevel( QStringLiteral( "Adding %1 Raster item %2 %3" ).arg( driver, name, path ), 3 ); - children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) ); + children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster, driver ) ); } } @@ -321,7 +345,7 @@ static QgsOgrLayerItem *dataItemForLayer( QgsDataItem *parentItem, QString name, QgsDebugMsgLevel( "OGR layer uri : " + layerUri, 2 ); - return new QgsOgrLayerItem( parentItem, name, path, layerUri, layerType, isSubLayer ); + return new QgsOgrLayerItem( parentItem, name, path, layerUri, layerType, driverName, isSubLayer ); } // ---- @@ -342,7 +366,7 @@ QVector QgsOgrDataCollectionItem::createChildren() CSLDestroy( papszOptions ); GDALDriverH hDriver = GDALGetDatasetDriver( hDataSource.get() ); - QString driverName = QString::fromUtf8( GDALGetDriverShortName( hDriver ) ); + const QString driverName = QString::fromUtf8( GDALGetDriverShortName( hDriver ) ); if ( driverName == QStringLiteral( "SQLite" ) ) { skippedLayerNames = QgsSqliteUtils::systemTables(); diff --git a/src/core/providers/ogr/qgsogrdataitems.h b/src/core/providers/ogr/qgsogrdataitems.h index e8c569b669f5..ada8428d3b40 100644 --- a/src/core/providers/ogr/qgsogrdataitems.h +++ b/src/core/providers/ogr/qgsogrdataitems.h @@ -30,13 +30,20 @@ class CORE_EXPORT QgsOgrDbLayerInfo { public: - QgsOgrDbLayerInfo( const QString &path, const QString &uri, const QString &name, const QString &theGeometryColumn, const QString &theGeometryType, const QgsLayerItem::LayerType &theLayerType ) + QgsOgrDbLayerInfo( const QString &path, + const QString &uri, + const QString &name, + const QString &theGeometryColumn, + const QString &theGeometryType, + const QgsLayerItem::LayerType &theLayerType, + const QString &driverName ) : mPath( path ) , mUri( uri ) , mName( name ) , mGeometryColumn( theGeometryColumn ) , mGeometryType( theGeometryType ) , mLayerType( theLayerType ) + , mDriverName( driverName ) { } const QString path() const { return mPath; } @@ -53,6 +60,7 @@ class CORE_EXPORT QgsOgrDbLayerInfo QString mGeometryColumn; QString mGeometryType; QgsLayerItem::LayerType mLayerType = QgsLayerItem::LayerType::NoType; + QString mDriverName; }; /** @@ -74,7 +82,7 @@ class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem { Q_OBJECT public: - QgsOgrLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, bool isSubLayer = false ); + QgsOgrLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &driverName = QString(), bool isSubLayer = false ); QString layerName() const override; @@ -87,11 +95,18 @@ class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType ); bool isSubLayer() const; + QVector createChildren() override; + private: + QString mDriverName; bool mIsSubLayer; + + }; + + class CORE_EXPORT QgsOgrDataCollectionItem final: public QgsDataCollectionItem { Q_OBJECT diff --git a/src/core/qgis.h b/src/core/qgis.h index c8090fa0d770..f9dea8fa220c 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -527,6 +527,34 @@ template T qgsEnumKeyToValue( const QString &key, const T &defaultValue return defaultValue; } +/** + * Returns the value for the given keys of a flag. + * \since QGIS 3.16 + */ +template QString qgsFlagValueToKeys( const T &value ) SIP_SKIP +{ + QMetaEnum metaEnum = QMetaEnum::fromType(); + Q_ASSERT( metaEnum.isValid() ); + return QString::fromUtf8( metaEnum.valueToKeys( static_cast( value ) ) ); +} + +/** + * Returns the value corresponding to the given \a keys of a flag. + * If the keys are invalid, it will return the \a defaultValue. + * \since QGIS 3.16 + */ +template T qgsFlagKeysToValue( const QString &keys, const T &defaultValue ) SIP_SKIP +{ + QMetaEnum metaEnum = QMetaEnum::fromType(); + Q_ASSERT( metaEnum.isValid() ); + bool ok = false; + T v = static_cast( metaEnum.keysToValue( keys.toUtf8().constData(), &ok ) ); + if ( ok ) + return v; + else + return defaultValue; +} + /** * Converts a string to a double in a permissive way, e.g., allowing for incorrect diff --git a/src/core/qgsabstractdatabaseproviderconnection.cpp b/src/core/qgsabstractdatabaseproviderconnection.cpp index 8e429ec7c1a8..2a83d8abfb06 100644 --- a/src/core/qgsabstractdatabaseproviderconnection.cpp +++ b/src/core/qgsabstractdatabaseproviderconnection.cpp @@ -14,7 +14,9 @@ * * ***************************************************************************/ #include "qgsabstractdatabaseproviderconnection.h" +#include "qgsvectorlayer.h" #include "qgsexception.h" +#include "qgslogger.h" #include #include @@ -34,6 +36,11 @@ QgsAbstractDatabaseProviderConnection::Capabilities QgsAbstractDatabaseProviderC return mCapabilities; } +QgsAbstractDatabaseProviderConnection::GeometryColumnCapabilities QgsAbstractDatabaseProviderConnection::geometryColumnCapabilities() +{ + return mGeometryColumnCapabilities; +} + QString QgsAbstractDatabaseProviderConnection::tableUri( const QString &schema, const QString &name ) const { Q_UNUSED( schema ) @@ -51,6 +58,11 @@ void QgsAbstractDatabaseProviderConnection::checkCapability( QgsAbstractDatabase throw QgsProviderConnectionException( QObject::tr( "Operation '%1' is not supported for this connection" ).arg( capName ) ); } } + +QString QgsAbstractDatabaseProviderConnection::providerKey() const +{ + return mProviderKey; +} ///@endcond void QgsAbstractDatabaseProviderConnection::createVectorTable( const QString &schema, @@ -148,6 +160,56 @@ bool QgsAbstractDatabaseProviderConnection::spatialIndexExists( const QString &, return false; } +void QgsAbstractDatabaseProviderConnection::deleteField( const QString &fieldName, const QString &schema, const QString &tableName, bool ) const +{ + checkCapability( Capability::DeleteField ); + + QgsVectorLayer::LayerOptions options { false, false }; + options.skipCrsValidation = true; + std::unique_ptr vl { qgis::make_unique( tableUri( schema, tableName ), QStringLiteral( "temp_layer" ), mProviderKey, options ) }; + if ( ! vl->isValid() ) + { + throw QgsProviderConnectionException( QObject::tr( "Could not create a vector layer for table '%1' in schema '%2'" ) + .arg( tableName, schema ) ); + } + if ( vl->fields().lookupField( fieldName ) == -1 ) + { + throw QgsProviderConnectionException( QObject::tr( "Could not find field '%1' in table '%2' in schema '%3'" ) + .arg( fieldName, tableName, schema ) ); + + } + if ( ! vl->dataProvider()->deleteAttributes( { vl->fields().lookupField( fieldName ) } ) ) + { + throw QgsProviderConnectionException( QObject::tr( "Unknown error deleting field '%1' in table '%2' in schema '%3'" ) + .arg( fieldName, tableName, schema ) ); + } +} + +void QgsAbstractDatabaseProviderConnection::addField( const QgsField &field, const QString &schema, const QString &tableName ) const +{ + checkCapability( Capability::AddField ); + + QgsVectorLayer::LayerOptions options { false, false }; + options.skipCrsValidation = true; + std::unique_ptr vl( qgis::make_unique( tableUri( schema, tableName ), QStringLiteral( "temp_layer" ), mProviderKey, options ) ); + if ( ! vl->isValid() ) + { + throw QgsProviderConnectionException( QObject::tr( "Could not create a vector layer for table '%1' in schema '%2'" ) + .arg( tableName, schema ) ); + } + if ( vl->fields().lookupField( field.name() ) != -1 ) + { + throw QgsProviderConnectionException( QObject::tr( "Field '%1' in table '%2' in schema '%3' already exists" ) + .arg( field.name(), tableName, schema ) ); + + } + if ( ! vl->dataProvider()->addAttributes( { field } ) ) + { + throw QgsProviderConnectionException( QObject::tr( "Unknown error adding field '%1' in table '%2' in schema '%3'" ) + .arg( field.name(), tableName, schema ) ); + } +} + QList QgsAbstractDatabaseProviderConnection::tables( const QString &, const QgsAbstractDatabaseProviderConnection::TableFlags & ) const { checkCapability( Capability::Tables ); @@ -167,8 +229,7 @@ QgsAbstractDatabaseProviderConnection::TableProperty QgsAbstractDatabaseProvider } } throw QgsProviderConnectionException( QObject::tr( "Table '%1' was not found in schema '%2'" ) - .arg( name ) - .arg( schema ) ); + .arg( name, schema ) ); } QList QgsAbstractDatabaseProviderConnection::tablesInt( const QString &schema, const int flags ) const @@ -212,6 +273,20 @@ QList return mGeometryColumnTypes; } +QgsFields QgsAbstractDatabaseProviderConnection::fields( const QString &schema, const QString &tableName ) const +{ + QgsVectorLayer::LayerOptions options { true, true }; + options.skipCrsValidation = true; + QgsVectorLayer vl { tableUri( schema, tableName ), QStringLiteral( "temp_layer" ), mProviderKey, options }; + if ( vl.isValid() ) + { + return vl.fields(); + } + else + { + throw QgsProviderConnectionException( QObject::tr( "Error retrieving fields information for uri: %1" ).arg( vl.publicSource() ) ); + } +} QString QgsAbstractDatabaseProviderConnection::TableProperty::defaultName() const { diff --git a/src/core/qgsabstractdatabaseproviderconnection.h b/src/core/qgsabstractdatabaseproviderconnection.h index fa9737d00b60..39461e1d2531 100644 --- a/src/core/qgsabstractdatabaseproviderconnection.h +++ b/src/core/qgsabstractdatabaseproviderconnection.h @@ -21,6 +21,7 @@ #include "qgis_core.h" #include "qgsfields.h" #include "qgsexception.h" +#include "qgsvectordataprovider.h" #include @@ -271,7 +272,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv }; /** - * The Capability enum represent the operations supported by the connection + * The Capability enum represents the operations supported by the connection */ enum Capability { @@ -293,12 +294,30 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv CreateSpatialIndex = 1 << 16, //!< The connection can create spatial indices SpatialIndexExists = 1 << 17, //!< The connection can determine if a spatial index exists DeleteSpatialIndex = 1 << 18, //!< The connection can delete spatial indices for tables + DeleteField = 1 << 19, //!< Can delete an existing field/column + DeleteFieldCascade = 1 << 20, //!< Can delete an existing field/column with cascade + AddField = 1 << 21, //!< Can add a new field/column }; - Q_ENUM( Capability ) Q_DECLARE_FLAGS( Capabilities, Capability ) Q_FLAG( Capabilities ) + /** + * The GeometryColumnCapability enum represents the geomery column features supported by the connection + * \since QGIS 3.16 + */ + enum GeometryColumnCapability + { + Z = 1 << 1, //! Supports Z dimension + M = 1 << 2, //! Supports M dimension + SinglePart = 1 << 3, //! Multi and single part types are distinct types + Curves = 1 << 4 //! Supports curves + }; + + Q_ENUM( GeometryColumnCapability ) + Q_DECLARE_FLAGS( GeometryColumnCapabilities, GeometryColumnCapability ) + Q_FLAG( GeometryColumnCapabilities ) + /** * Creates a new connection with \a name by reading its configuration from the settings. * If a connection with this name cannot be found, an empty connection will be returned. @@ -320,6 +339,12 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv */ Capabilities capabilities() const; + /** + * Returns connection geomerty column capabilities (Z, M, SinglePart, Curves) + * \since QGIS 3.16 + */ + virtual GeometryColumnCapabilities geometryColumnCapabilities(); + // Operations interface /** @@ -392,6 +417,32 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv */ virtual void dropSchema( const QString &name, bool force = false ) const SIP_THROW( QgsProviderConnectionException ); + /** + * Deletes the field with the specified name. + * Raises a QgsProviderConnectionException if any errors are encountered. + * \param fieldName name of the field to be deleted + * \param schema name of the schema (schema is ignored if not supported by the backend). + * \param tableName name of the table + * \param force if TRUE, a DROP CASCADE will drop all related objects + * \note it is responsibility of the caller to handle open layers and registry entries. + * \throws QgsProviderConnectionException + * \since QGIS 3.16 + */ + virtual void deleteField( const QString &fieldName, const QString &schema, const QString &tableName, bool force = false ) const SIP_THROW( QgsProviderConnectionException ); + + /** + * Adds a field + * Raises a QgsProviderConnectionException if any errors are encountered. + * \param field specification of the new field + * \param schema name of the schema (schema is ignored if not supported by the backend). + * \param tableName name of the table + * \note it is responsibility of the caller to handle open layers and registry entries. + * \throws QgsProviderConnectionException + * \since QGIS 3.16 + */ + virtual void addField( const QgsField &field, const QString &schema, const QString &tableName ) const SIP_THROW( QgsProviderConnectionException ); + + /** * Renames a schema with the specified \a name. * Raises a QgsProviderConnectionException if any errors are encountered. @@ -494,6 +545,29 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv */ virtual QStringList schemas() const SIP_THROW( QgsProviderConnectionException ); + /** + * Returns the fields of a \a table and \a schema. + * Raises a QgsProviderConnectionException if any errors are encountered. + * \note the default implementation creates a temporary vector layer, providers may + * choose to override this method for a greater efficiency. + * \since QGIS 3.16 + * \throws QgsProviderConnectionException + */ + virtual QgsFields fields( const QString &schema, const QString &table ) const SIP_THROW( QgsProviderConnectionException ); + + /** + * Returns a list of native types supported by the connection. + * \since QGIS 3.16 + * \throws QgsProviderConnectionException + */ + virtual QList< QgsVectorDataProvider::NativeType > nativeTypes() const SIP_THROW( QgsProviderConnectionException ) = 0; + + /** + * Returns the provider key + * \since QGIS 3.16 + */ + QString providerKey() const; + protected: ///@cond PRIVATE @@ -506,6 +580,8 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv ///@endcond Capabilities mCapabilities = nullptr SIP_SKIP; + GeometryColumnCapabilities mGeometryColumnCapabilities = nullptr SIP_SKIP; + QString mProviderKey; }; diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp index e1842bbed5f7..4bab72e67a3a 100644 --- a/src/core/qgsapplication.cpp +++ b/src/core/qgsapplication.cpp @@ -35,6 +35,7 @@ #include "qgsscalebarrendererregistry.h" #include "qgssvgcache.h" #include "qgsimagecache.h" +#include "qgssourcecache.h" #include "qgscolorschemeregistry.h" #include "qgspainteffectregistry.h" #include "qgsprojectstorageregistry.h" @@ -235,6 +236,7 @@ void QgsApplication::init( QString profileFolder ) qRegisterMetaTypeStreamOperators( "QgsProcessingModelChildParameterSource" ); qRegisterMetaType( "QgsRemappingSinkDefinition" ); qRegisterMetaType( "QgsProcessingModelChildDependency" ); + qRegisterMetaType( "QgsTextFormat" ); QMetaType::registerComparators(); QMetaType::registerEqualsComparator(); QMetaType::registerEqualsComparator(); @@ -2138,6 +2140,11 @@ QgsImageCache *QgsApplication::imageCache() return members()->mImageCache; } +QgsSourceCache *QgsApplication::sourceCache() +{ + return members()->mSourceCache; +} + QgsNetworkContentFetcherRegistry *QgsApplication::networkContentFetcherRegistry() { return members()->mNetworkContentFetcherRegistry; @@ -2286,6 +2293,11 @@ QgsApplication::ApplicationMembers::ApplicationMembers() mImageCache = new QgsImageCache(); profiler->end(); } + { + profiler->start( tr( "Setup source cache" ) ); + mSourceCache = new QgsSourceCache(); + profiler->end(); + } { profiler->start( tr( "Setup color scheme registry" ) ); mColorSchemeRegistry = new QgsColorSchemeRegistry(); diff --git a/src/core/qgsapplication.h b/src/core/qgsapplication.h index e75ccdab4505..c39ebf5576ad 100644 --- a/src/core/qgsapplication.h +++ b/src/core/qgsapplication.h @@ -36,6 +36,7 @@ class QgsLocalizedDataPathRegistry; class QgsRendererRegistry; class QgsSvgCache; class QgsImageCache; +class QgsSourceCache; class QgsSymbolLayerRegistry; class QgsRasterRendererRegistry; class QgsGpsConnectionRegistry; @@ -643,6 +644,13 @@ class CORE_EXPORT QgsApplication : public QApplication */ static QgsImageCache *imageCache(); + /** + * Returns the application's source cache, used for caching embedded and remote source strings as local files + * + * \since QGIS 3.16 + */ + static QgsSourceCache *sourceCache(); + /** * Returns the application's network content registry used for fetching temporary files during QGIS session * \since QGIS 3.2 @@ -942,6 +950,7 @@ class CORE_EXPORT QgsApplication : public QApplication QgsRendererRegistry *mRendererRegistry = nullptr; QgsSvgCache *mSvgCache = nullptr; QgsImageCache *mImageCache = nullptr; + QgsSourceCache *mSourceCache = nullptr; QgsSymbolLayerRegistry *mSymbolLayerRegistry = nullptr; QgsCalloutRegistry *mCalloutRegistry = nullptr; QgsTaskManager *mTaskManager = nullptr; diff --git a/src/core/qgsattributeeditorelement.cpp b/src/core/qgsattributeeditorelement.cpp index 79d9796d3486..dff01590fa4a 100644 --- a/src/core/qgsattributeeditorelement.cpp +++ b/src/core/qgsattributeeditorelement.cpp @@ -96,8 +96,7 @@ QgsAttributeEditorElement *QgsAttributeEditorRelation::clone( QgsAttributeEditor { QgsAttributeEditorRelation *element = new QgsAttributeEditorRelation( mRelationId, parent ); element->mRelation = mRelation; - element->mShowLinkButton = mShowLinkButton; - element->mShowUnlinkButton = mShowUnlinkButton; + element->mButtons = mButtons; return element; } @@ -133,9 +132,7 @@ void QgsAttributeEditorElement::setShowLabel( bool showLabel ) void QgsAttributeEditorRelation::saveConfiguration( QDomElement &elem ) const { elem.setAttribute( QStringLiteral( "relation" ), mRelation.id() ); - elem.setAttribute( QStringLiteral( "showLinkButton" ), mShowLinkButton ); - elem.setAttribute( QStringLiteral( "showUnlinkButton" ), mShowUnlinkButton ); - elem.setAttribute( QStringLiteral( "showSaveChildEditsButton" ), mShowSaveChildEditsButton ); + elem.setAttribute( QStringLiteral( "buttons" ), qgsFlagValueToKeys( mButtons ) ); } QString QgsAttributeEditorRelation::typeIdentifier() const @@ -145,32 +142,37 @@ QString QgsAttributeEditorRelation::typeIdentifier() const bool QgsAttributeEditorRelation::showLinkButton() const { - return mShowLinkButton; + return mButtons.testFlag( Button::Link ); } void QgsAttributeEditorRelation::setShowLinkButton( bool showLinkButton ) { - mShowLinkButton = showLinkButton; + mButtons.setFlag( Button::Link, showLinkButton ); } bool QgsAttributeEditorRelation::showUnlinkButton() const { - return mShowUnlinkButton; + return mButtons.testFlag( Button::Unlink ); } void QgsAttributeEditorRelation::setShowUnlinkButton( bool showUnlinkButton ) { - mShowUnlinkButton = showUnlinkButton; + mButtons.setFlag( Button::Unlink, showUnlinkButton ); } void QgsAttributeEditorRelation::setShowSaveChildEditsButton( bool showSaveChildEdits ) { - mShowSaveChildEditsButton = showSaveChildEdits; + mButtons.setFlag( Button::SaveChildEdits, showSaveChildEdits ); } bool QgsAttributeEditorRelation::showSaveChildEditsButton() const { - return mShowSaveChildEditsButton; + return mButtons.testFlag( Button::SaveChildEdits ); +} + +void QgsAttributeEditorRelation::setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ) +{ + mButtons = buttons; } QgsAttributeEditorElement *QgsAttributeEditorQmlElement::clone( QgsAttributeEditorElement *parent ) const diff --git a/src/core/qgsattributeeditorelement.h b/src/core/qgsattributeeditorelement.h index 66e5f4ccbaf9..bd63ae22d6cb 100644 --- a/src/core/qgsattributeeditorelement.h +++ b/src/core/qgsattributeeditorelement.h @@ -22,6 +22,7 @@ #include "qgspropertycollection.h" #include + class QgsRelationManager; /** @@ -332,8 +333,28 @@ class CORE_EXPORT QgsAttributeEditorField : public QgsAttributeEditorElement */ class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement { + Q_GADGET public: + /** + * Possible buttons shown in the relation editor + * \since QGIS 3.16 + */ + enum Button + { + Link = 1 << 1, //!< Link button + Unlink = 1 << 2, //!< Unlink button + SaveChildEdits = 1 << 3, //!< Save child edits button + AddChildFeature = 1 << 4, //!< Add child feature (as in some projects we only want to allow to link/unlink existing features) + DuplicateChildFeature = 1 << 5, //!< Duplicate child feature + DeleteChildFeature = 1 << 6, //!< Delete child feature button + ZoomToChildFeature = 1 << 7, //!< Zoom to child feature + AllButtons = Link | Unlink | SaveChildEdits | AddChildFeature | DuplicateChildFeature | DeleteChildFeature | ZoomToChildFeature //!< All buttons + }; + Q_ENUM( Button ) + Q_DECLARE_FLAGS( Buttons, Button ) + Q_FLAG( Buttons ) + /** * \deprecated since QGIS 3.0.2. The name parameter is not used for anything and overwritten by the relationId internally. */ @@ -394,45 +415,57 @@ class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement /** * Determines if the "link feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showLinkButton() const; + Q_DECL_DEPRECATED bool showLinkButton() const SIP_DEPRECATED; /** * Determines if the "link feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowLinkButton( bool showLinkButton ); + Q_DECL_DEPRECATED void setShowLinkButton( bool showLinkButton ) SIP_DEPRECATED; /** * Determines if the "unlink feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showUnlinkButton() const; + Q_DECL_DEPRECATED bool showUnlinkButton() const SIP_DEPRECATED; /** * Determines if the "unlink feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowUnlinkButton( bool showUnlinkButton ); + Q_DECL_DEPRECATED void setShowUnlinkButton( bool showUnlinkButton ) SIP_DEPRECATED; /** - * Determines if the "save child layer edits" button should be shown - * + * Determines if the "Save child layer edits" button should be shown * \since QGIS 3.14 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowSaveChildEditsButton( bool showSaveChildEditsButton ); + Q_DECL_DEPRECATED void setShowSaveChildEditsButton( bool showChildEdits ) SIP_DEPRECATED; /** - * Returns TRUE if the "save child layer edits" button should be shown. - * + * Determines if the "Save child layer edits" button should be shown * \since QGIS 3.14 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showSaveChildEditsButton( ) const; + Q_DECL_DEPRECATED bool showSaveChildEditsButton() const SIP_DEPRECATED; + + /** + * Defines the buttons which are shown + * \since QGIS 3.16 + */ + void setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ); + + /** + * Returns the buttons which are shown + * \since QGIS 3.16 + */ + QgsAttributeEditorRelation::Buttons visibleButtons() const {return mButtons;} private: @@ -440,11 +473,12 @@ class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement QString typeIdentifier() const override; QString mRelationId; QgsRelation mRelation; - bool mShowLinkButton = true; - bool mShowUnlinkButton = true; - bool mShowSaveChildEditsButton = true; + Buttons mButtons = Buttons( Button::AllButtons ); }; +Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAttributeEditorRelation::Buttons ) + + /** * \ingroup core * An attribute editor widget that will represent arbitrary QML code. diff --git a/src/core/qgsbrowserproxymodel.cpp b/src/core/qgsbrowserproxymodel.cpp index 17b82983061b..cb3197b2cace 100644 --- a/src/core/qgsbrowserproxymodel.cpp +++ b/src/core/qgsbrowserproxymodel.cpp @@ -289,17 +289,24 @@ void QgsBrowserProxyModel::setShownDataItemProviderKeyFilter( const QStringList { mShownDataItemsKeys = filter; invalidateFilter(); - } bool QgsBrowserProxyModel::hasChildren( const QModelIndex &parent ) const { bool isFertile { QSortFilterProxyModel::hasChildren( parent ) }; - if ( isFertile && ! mShowLayers && parent.isValid() ) + if ( isFertile && parent.isValid() ) { QgsDataItem *item = dataItem( parent ); - return ! item->layerCollection(); + if ( ! mShowLayers ) + { + return ! item->layerCollection(); + } + // Hide everything below layers if filter is set + else if ( mFilterByLayerType && qobject_cast< QgsLayerItem * >( item ) ) + { + return false; + } } return isFertile; } diff --git a/src/core/qgsdatadefinedsizelegend.cpp b/src/core/qgsdatadefinedsizelegend.cpp index a4119a307971..843a28ed5eec 100644 --- a/src/core/qgsdatadefinedsizelegend.cpp +++ b/src/core/qgsdatadefinedsizelegend.cpp @@ -318,8 +318,7 @@ void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, Q QRect rect( outputLargestSize + hLengthLine + hSpaceLineText, textCenterY[i] - textHeight / 2, maxTextWidth, textHeight ); - QgsTextRenderer::drawText( rect, 0, mTextAlignment == Qt::AlignRight ? QgsTextRenderer::AlignRight : - mTextAlignment == Qt::AlignHCenter ? QgsTextRenderer::AlignCenter : QgsTextRenderer::AlignLeft, + QgsTextRenderer::drawText( rect, 0, QgsTextRenderer::convertQtHAlignment( mTextAlignment ), QStringList() << c.label, context, format ); i++; } diff --git a/src/core/qgsdataitem.cpp b/src/core/qgsdataitem.cpp index 9590b7792a07..8e7b2b8f764e 100644 --- a/src/core/qgsdataitem.cpp +++ b/src/core/qgsdataitem.cpp @@ -43,6 +43,7 @@ #include "qgsanimatedicon.h" #include "qgsproject.h" #include "qgsvectorlayer.h" +#include "qgsprovidermetadata.h" // use GDAL VSI mechanism #define CPL_SUPRESS_CPLUSPLUS //#spellok @@ -110,6 +111,125 @@ QIcon QgsDataCollectionItem::iconDir() return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFolder.svg" ) ); } + +QgsFieldsItem::QgsFieldsItem( QgsDataItem *parent, + const QString &path, + const QString &connectionUri, + const QString &providerKey, + const QString &schema, + const QString &tableName ) + : QgsDataItem( QgsDataItem::Fields, parent, tr( "Fields" ), path, providerKey ) + , mSchema( schema ) + , mTableName( tableName ) + , mConnectionUri( connectionUri ) +{ + mCapabilities |= ( Fertile | Collapse ); +} + +QgsFieldsItem::~QgsFieldsItem() +{ + +} + +QVector QgsFieldsItem::createChildren() +{ + QVector children; + try + { + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey() ) }; + if ( md ) + { + std::unique_ptr conn { static_cast( md->createConnection( mConnectionUri, {} ) ) }; + if ( conn ) + { + int i = 0; + const QgsFields constFields { conn->fields( mSchema, mTableName ) }; + for ( const auto &f : constFields ) + { + QgsFieldItem *fieldItem { new QgsFieldItem( this, f ) }; + fieldItem->setSortKey( i++ ); + children.push_back( fieldItem ); + } + } + } + } + catch ( const QgsProviderConnectionException &ex ) + { + children.push_back( new QgsErrorItem( this, ex.what(), path() + QStringLiteral( "/error" ) ) ); + } + return children; +} + +QIcon QgsFieldsItem::icon() +{ + return QgsApplication::getThemeIcon( QStringLiteral( "mSourceFields.svg" ) ); +} + +QString QgsFieldsItem::connectionUri() const +{ + return mConnectionUri; +} + +QgsVectorLayer *QgsFieldsItem::layer() +{ + std::unique_ptr vl; + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey() ) }; + if ( md ) + { + try + { + std::unique_ptr conn { static_cast( md->createConnection( mConnectionUri, {} ) ) }; + if ( conn ) + { + vl.reset( new QgsVectorLayer( conn->tableUri( mSchema, mTableName ), QStringLiteral( "temp_layer" ), providerKey() ) ); + if ( vl->isValid() ) + { + return vl.release(); + } + } + } + catch ( const QgsProviderConnectionException &ex ) + { + // This should never happen! + QgsDebugMsg( QStringLiteral( "Error getting connection from %1" ).arg( mConnectionUri ) ); + } + } + else + { + // This should never happen! + QgsDebugMsg( QStringLiteral( "Error getting metadata for provider %1" ).arg( providerKey() ) ); + } + return nullptr; +} + +QString QgsFieldsItem::tableName() const +{ + return mTableName; +} + +QString QgsFieldsItem::schema() const +{ + return mSchema; +} + +QgsFieldItem::QgsFieldItem( QgsDataItem *parent, const QgsField &field ) + : QgsDataItem( QgsDataItem::Type::Field, parent, field.name(), parent->path() + '/' + field.name(), parent->providerKey() ) + , mField( field ) +{ + // Precondition + Q_ASSERT( static_cast( parent ) ); + setState( QgsDataItem::State::Populated ); +} + +QgsFieldItem::~QgsFieldItem() +{ +} + +QIcon QgsFieldItem::icon() +{ + return QgsFields::iconForFieldType( mField.type() ); +} + QIcon QgsFavoritesItem::iconFavorites() { return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFavourites.svg" ) ); @@ -1621,6 +1741,30 @@ QStringList QgsZipItem::getZipFileList() return mZipFileList; } + +QgsDatabaseSchemaItem::QgsDatabaseSchemaItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &providerKey ) + : QgsDataCollectionItem( parent, name, path, providerKey ) +{ + +} + +QgsDatabaseSchemaItem::~QgsDatabaseSchemaItem() +{ + +} + +QIcon QgsDatabaseSchemaItem::iconDataCollection() +{ + return QgsApplication::getThemeIcon( QStringLiteral( "/mIconDbSchema.svg" ) ); +} + + +QgsConnectionsRootItem::QgsConnectionsRootItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &providerKey ) + : QgsDataCollectionItem( parent, name, path, providerKey ) +{ +} + + ///@cond PRIVATE QgsProjectHomeItem::QgsProjectHomeItem( QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path ) diff --git a/src/core/qgsdataitem.h b/src/core/qgsdataitem.h index 49db5dabeaa6..68f99501b0ee 100644 --- a/src/core/qgsdataitem.h +++ b/src/core/qgsdataitem.h @@ -82,6 +82,8 @@ class CORE_EXPORT QgsDataItem : public QObject Favorites, //!< Represents a favorite item Project, //!< Represents a QGIS project Custom, //!< Custom item type + Fields, //!< Collection of fields + Field, //!< Vector layer field }; Q_ENUM( Type ) @@ -664,6 +666,70 @@ class CORE_EXPORT QgsDataCollectionItem : public QgsDataItem static QIcon homeDirIcon(); }; + +/** + * \ingroup core + * A Collection that represents a database schema item + * \since QGIS 3.16 +*/ +class CORE_EXPORT QgsDatabaseSchemaItem : public QgsDataCollectionItem +{ + Q_OBJECT + public: + + /** + * Constructor for QgsDatabaseSchemaItem, with the specified \a parent item. + * + * The \a name argument specifies the text to show in the model for the item. A translated string should + * be used wherever appropriate. + * + * The \a path argument gives the item path in the browser tree. The \a path string can take any form, + * but QgsSchemaItem items pointing to different logical locations should always use a different item \a path. + * + * The optional \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item. + */ + QgsDatabaseSchemaItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path = QString(), const QString &providerKey = QString() ); + + ~QgsDatabaseSchemaItem() override; + + + /** + * Returns the standard browser data collection icon. + * \see iconDir() + */ + static QIcon iconDataCollection(); + +}; + + + +/** + * \ingroup core + * A Collection that represents a root group of connections from a single data provider + * \since QGIS 3.16 +*/ +class CORE_EXPORT QgsConnectionsRootItem : public QgsDataCollectionItem +{ + Q_OBJECT + public: + + /** + * Constructor for QgsConnectionsRootItem, with the specified \a parent item. + * + * The \a name argument specifies the text to show in the model for the item. A translated string should + * be used wherever appropriate. + * + * The \a path argument gives the item path in the browser tree. The \a path string can take any form, + * but QgsSchemaItem items pointing to different logical locations should always use a different item \a path. + * + * The optional \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item. + */ + QgsConnectionsRootItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path = QString(), const QString &providerKey = QString() ); + + ~QgsConnectionsRootItem() override = default; +}; + + /** * \ingroup core * A directory: contains subdirectories and layers @@ -895,6 +961,102 @@ class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem }; +/** + * \ingroup core + * A collection of field items with some internal logic to retrieve + * the fields and a the vector layer instance from a connection URI, + * the schema and the table name. + * \since QGIS 3.16 +*/ +class CORE_EXPORT QgsFieldsItem : public QgsDataItem +{ + Q_OBJECT + + public: + + /** + * Constructor for QgsFieldsItem, with the specified \a parent item. + * + * The \a path argument gives the item path in the browser tree. The \a path string can take any form, + * but QgsDataItem items pointing to different logical locations should always use a different item \a path. + * The \connectionUri argument is the connection part of the layer URI that it is used internally to create + * a connection and retrieve fields information. + * The \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item. + * The \a schema and \a tableName are used to retrieve the layer and field information from the \a connectionUri. + */ + QgsFieldsItem( QgsDataItem *parent SIP_TRANSFERTHIS, + const QString &path, + const QString &connectionUri, + const QString &providerKey, + const QString &schema, + const QString &tableName ); + + ~QgsFieldsItem() override; + + QVector createChildren() override; + + QIcon icon() override; + + /** + * Returns the schema name + */ + QString schema() const; + + /** + * Returns the table name + */ + QString tableName() const; + + /** + * Returns the connection URI + */ + QString connectionUri() const; + + /** + * Creates and returns a (possibly NULL) layer from the connection URI and schema/table information + */ + QgsVectorLayer *layer() SIP_FACTORY; + + + private: + + QString mSchema; + QString mTableName; + QString mConnectionUri; +}; + + +/** + * \ingroup core + * A layer field item, information about the connection URI, the schema and the + * table as well as the layer instance the field belongs to can be retrieved + * from the parent QgsFieldsItem object. + * \since QGIS 3.16 +*/ +class CORE_EXPORT QgsFieldItem : public QgsDataItem +{ + Q_OBJECT + public: + + /** + * Constructor for QgsFieldItem, with the specified \a parent item and \a field. + * \note parent item must be a QgsFieldsItem + */ + QgsFieldItem( QgsDataItem *parent SIP_TRANSFERTHIS, + const QgsField &field ); + + ~QgsFieldItem() override; + + QIcon icon() override; + + private: + + const QgsField mField; + +}; + + + ///@cond PRIVATE #ifndef SIP_RUN diff --git a/src/core/qgseditformconfig.cpp b/src/core/qgseditformconfig.cpp index 81531193dd2d..f94da1203ea7 100644 --- a/src/core/qgseditformconfig.cpp +++ b/src/core/qgseditformconfig.cpp @@ -615,9 +615,20 @@ QgsAttributeEditorElement *QgsEditFormConfig::attributeEditorElementFromDomEleme // At this time, the relations are not loaded // So we only grab the id and delegate the rest to onRelationsLoaded() QgsAttributeEditorRelation *relElement = new QgsAttributeEditorRelation( elem.attribute( QStringLiteral( "relation" ), QStringLiteral( "[None]" ) ), parent ); - relElement->setShowLinkButton( elem.attribute( QStringLiteral( "showLinkButton" ), QStringLiteral( "1" ) ).toInt() ); - relElement->setShowUnlinkButton( elem.attribute( QStringLiteral( "showUnlinkButton" ), QStringLiteral( "1" ) ).toInt() ); - relElement->setShowSaveChildEditsButton( elem.attribute( QStringLiteral( "showSaveChildEditsButton" ), QStringLiteral( "1" ) ).toInt() ); + if ( elem.hasAttribute( "buttons" ) ) + { + QString buttonString = elem.attribute( QStringLiteral( "buttons" ), qgsFlagValueToKeys( QgsAttributeEditorRelation::Button::AllButtons ) ); + relElement->setVisibleButtons( qgsFlagKeysToValue( buttonString, QgsAttributeEditorRelation::Button::AllButtons ) ); + } + else + { + // pre QGIS 3.16 compatibility + QgsAttributeEditorRelation::Buttons buttons = QgsAttributeEditorRelation::Button::AllButtons; + buttons.setFlag( QgsAttributeEditorRelation::Button::Link, elem.attribute( QStringLiteral( "showLinkButton" ), QStringLiteral( "1" ) ).toInt() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::Unlink, elem.attribute( QStringLiteral( "showUnlinkButton" ), QStringLiteral( "1" ) ).toInt() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::SaveChildEdits, elem.attribute( QStringLiteral( "showSaveChildEditsButton" ), QStringLiteral( "1" ) ).toInt() ); + relElement->setVisibleButtons( buttons ); + } newElement = relElement; } else if ( elem.tagName() == QLatin1String( "attributeEditorQmlElement" ) ) diff --git a/src/core/qgsfeatureid.h b/src/core/qgsfeatureid.h index ccaafb8469fb..0a601e5b9072 100644 --- a/src/core/qgsfeatureid.h +++ b/src/core/qgsfeatureid.h @@ -21,7 +21,10 @@ email : matthias@opengis.ch // feature id (currently 64 bit) -// 64 bit feature ids +/** + * 64 bit feature ids + * negative numbers are used for uncommitted/newly added features + **/ typedef qint64 QgsFeatureId SIP_SKIP; #define FID_NULL std::numeric_limits::min() #define FID_IS_NULL(fid) ( fid == std::numeric_limits::min() ) diff --git a/src/core/qgsfields.cpp b/src/core/qgsfields.cpp index 0677b54dcdce..2bb0948d1eb0 100644 --- a/src/core/qgsfields.cpp +++ b/src/core/qgsfields.cpp @@ -274,7 +274,12 @@ QgsFields::iterator QgsFields::end() QIcon QgsFields::iconForField( int fieldIdx ) const { - switch ( d->fields.at( fieldIdx ).field.type() ) + return QgsFields::iconForFieldType( d->fields.at( fieldIdx ).field.type() ); +} + +QIcon QgsFields::iconForFieldType( const QVariant::Type &type ) +{ + switch ( type ) { case QVariant::Bool: return QgsApplication::getThemeIcon( "/mIconFieldBool.svg" ); diff --git a/src/core/qgsfields.h b/src/core/qgsfields.h index ca5b23de62a8..f20b3c17ab33 100644 --- a/src/core/qgsfields.h +++ b/src/core/qgsfields.h @@ -338,6 +338,13 @@ class CORE_EXPORT QgsFields % End #endif + + /** + * Returns an icon corresponding to a field \a type + * \since QGIS 3.16 + */ + static QIcon iconForFieldType( const QVariant::Type &type ) SIP_FACTORY; + //! Allows direct construction of QVariants from fields. operator QVariant() const { diff --git a/src/core/qgspointlocator.cpp b/src/core/qgspointlocator.cpp index 57223a46963e..941ca6ca6aa9 100644 --- a/src/core/qgspointlocator.cpp +++ b/src/core/qgspointlocator.cpp @@ -831,6 +831,10 @@ bool QgsPointLocator::init( int maxFeaturesToIndex, bool relaxed ) || mIsIndexing ) // already indexing, return! return true; + if ( !mLayer->dataProvider() + || !mLayer->dataProvider()->isValid() ) + return false; + mRenderer.reset( mLayer->renderer() ? mLayer->renderer()->clone() : nullptr ); mSource.reset( new QgsVectorLayerFeatureSource( mLayer ) ); diff --git a/src/core/qgspropertycollection.cpp b/src/core/qgspropertycollection.cpp index 0b9d6ddf3387..27a2b3e45138 100644 --- a/src/core/qgspropertycollection.cpp +++ b/src/core/qgspropertycollection.cpp @@ -144,6 +144,16 @@ QgsPropertyCollection &QgsPropertyCollection::operator=( const QgsPropertyCollec return *this; } +bool QgsPropertyCollection::operator==( const QgsPropertyCollection &other ) const +{ + return mProperties == other.mProperties; +} + +bool QgsPropertyCollection::operator!=( const QgsPropertyCollection &other ) const +{ + return !( *this == other ); +} + int QgsPropertyCollection::count() const { if ( !mDirty ) diff --git a/src/core/qgspropertycollection.h b/src/core/qgspropertycollection.h index a0c056ed61cb..44270675ab87 100644 --- a/src/core/qgspropertycollection.h +++ b/src/core/qgspropertycollection.h @@ -332,6 +332,9 @@ class CORE_EXPORT QgsPropertyCollection : public QgsAbstractPropertyCollection QgsPropertyCollection &operator=( const QgsPropertyCollection &other ); + bool operator==( const QgsPropertyCollection &other ) const; + bool operator!=( const QgsPropertyCollection &other ) const; + /** * Returns the number of properties contained within the collection. */ diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index 5189a35c716e..fad78a13e46d 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -69,6 +69,7 @@ QgsRenderContext::QgsRenderContext( const QgsRenderContext &rh ) , mDisabledSymbolLayers() , mClippingRegions( rh.mClippingRegions ) , mFeatureClipGeometry( rh.mFeatureClipGeometry ) + , mTextureOrigin( rh.mTextureOrigin ) #ifdef QGISDEBUG , mHasTransformContext( rh.mHasTransformContext ) #endif @@ -104,6 +105,7 @@ QgsRenderContext &QgsRenderContext::operator=( const QgsRenderContext &rh ) mCustomRenderingFlags = rh.mCustomRenderingFlags; mClippingRegions = rh.mClippingRegions; mFeatureClipGeometry = rh.mFeatureClipGeometry; + mTextureOrigin = rh.mTextureOrigin; setIsTemporal( rh.isTemporal() ); if ( isTemporal() ) setTemporalRange( rh.temporalRange() ); @@ -534,4 +536,14 @@ void QgsRenderContext::setFeatureClipGeometry( const QgsGeometry &geometry ) mFeatureClipGeometry = geometry; } +QPointF QgsRenderContext::textureOrigin() const +{ + return mTextureOrigin; +} + +void QgsRenderContext::setTextureOrigin( const QPointF &origin ) +{ + mTextureOrigin = origin; +} + diff --git a/src/core/qgsrendercontext.h b/src/core/qgsrendercontext.h index 0d86cb8c329a..85c44590c2ee 100644 --- a/src/core/qgsrendercontext.h +++ b/src/core/qgsrendercontext.h @@ -82,6 +82,7 @@ class CORE_EXPORT QgsRenderContext : public QgsTemporalRangeObject RenderBlocking = 0x400, //!< Render and load remote sources in the same thread to ensure rendering remote sources (svg and images). WARNING: this flag must NEVER be used from GUI based applications (like the main QGIS application) or crashes will result. Only for use in external scripts or QGIS server. RenderSymbolPreview = 0x800, //!< The render is for a symbol preview only and map based properties may not be available, so care should be taken to handle map unit based sizes in an appropriate way. LosslessImageRendering = 0x1000, //!< Render images losslessly whenever possible, instead of the default lossy jpeg rendering used for some destination devices (e.g. PDF). This flag only works with builds based on Qt 5.13 or later. + ApplyScalingWorkaroundForTextRendering = 0x2000, //!< Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters scaled out by a large amount) when rendering text. Generally this is recommended, but it may incur some performance cost. }; Q_DECLARE_FLAGS( Flags, Flag ) @@ -835,6 +836,24 @@ class CORE_EXPORT QgsRenderContext : public QgsTemporalRangeObject */ void setFeatureClipGeometry( const QgsGeometry &geometry ); + /** + * Returns the texture origin, which should be used as a brush transform when + * rendering using QBrush objects. + * + * \see setTextureOrigin() + * \since QGIS 3.16 + */ + QPointF textureOrigin() const; + + /** + * Sets the texture \a origin, which should be used as a brush transform when + * rendering using QBrush objects. + * + * \see textureOrigin() + * \since QGIS 3.16 + */ + void setTextureOrigin( const QPointF &origin ); + private: Flags mFlags; @@ -929,6 +948,8 @@ class CORE_EXPORT QgsRenderContext : public QgsTemporalRangeObject QList< QgsMapClippingRegion > mClippingRegions; QgsGeometry mFeatureClipGeometry; + QPointF mTextureOrigin; + #ifdef QGISDEBUG bool mHasTransformContext = false; #endif diff --git a/src/core/qgssourcecache.cpp b/src/core/qgssourcecache.cpp new file mode 100644 index 000000000000..7b00c94912ac --- /dev/null +++ b/src/core/qgssourcecache.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** + qgssourcecache.cpp + ----------------- + begin : July 2020 + copyright : (C) 2020 by Mathieu Pellerin + email : nirvn dot asia at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgssourcecache.h" + +#include "qgis.h" +#include "qgslogger.h" + +#include +#include +#include + +///@cond PRIVATE + +QgsSourceCacheEntry::QgsSourceCacheEntry( const QString &path ) + : QgsAbstractContentCacheEntry( path ) +{ +} + +bool QgsSourceCacheEntry::isEqual( const QgsAbstractContentCacheEntry *other ) const +{ + const QgsSourceCacheEntry *otherSource = dynamic_cast< const QgsSourceCacheEntry * >( other ); + // cheapest checks first! + if ( !otherSource || otherSource->filePath != filePath ) + return false; + + return true; +} + +int QgsSourceCacheEntry::dataSize() const +{ + return filePath.size(); +} + +void QgsSourceCacheEntry::dump() const +{ + QgsDebugMsgLevel( QStringLiteral( "path: %1" ).arg( path ), 3 ); +} + +///@endcond + +QgsSourceCache::QgsSourceCache( QObject *parent ) + : QgsAbstractContentCache< QgsSourceCacheEntry >( parent, QObject::tr( "Source" ) ) +{ + temporaryDir.reset( new QTemporaryDir() ); + + connect( this, &QgsAbstractContentCacheBase::remoteContentFetched, this, &QgsSourceCache::remoteSourceFetched ); +} + +QString QgsSourceCache::localFilePath( const QString &path, bool blocking ) +{ + const QString file = path.trimmed(); + if ( file.isEmpty() ) + return QString(); + + QMutexLocker locker( &mMutex ); + + QgsSourceCacheEntry *currentEntry = findExistingEntry( new QgsSourceCacheEntry( file ) ); + + //if current entry's temporary file is empty, create it + if ( currentEntry->filePath.isEmpty() ) + { + bool isBroken; + QString filePath = fetchSource( file, isBroken, blocking ); + currentEntry->filePath = filePath; + } + + return currentEntry->filePath; +} + +QString QgsSourceCache::fetchSource( const QString &path, bool &isBroken, bool blocking ) const +{ + QString filePath; + + if ( !path.startsWith( QStringLiteral( "base64:" ) ) && QFile::exists( path ) ) + { + filePath = path; + } + else + { + QByteArray ba = getContent( path, QByteArray( "broken" ), QByteArray( "fetching" ), blocking ); + + if ( ba == "broken" ) + { + isBroken = true; + } + else + { + int id = 1; + filePath = temporaryDir->filePath( QString::number( id ) ); + while ( QFile::exists( filePath ) ) + filePath = temporaryDir->filePath( QString::number( ++id ) ); + + QFile file( filePath ); + file.open( QIODevice::WriteOnly ); + file.write( ba ); + file.close(); + } + } + + return filePath; +} diff --git a/src/core/qgssourcecache.h b/src/core/qgssourcecache.h new file mode 100644 index 000000000000..3bad8a700247 --- /dev/null +++ b/src/core/qgssourcecache.h @@ -0,0 +1,103 @@ +/*************************************************************************** + qgssourcecache.h + --------------- + begin : July 2020 + copyright : (C) 2020 by Mathieu Pellerin + email : nirvn dot asia at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSSOURCECACHE_H +#define QGSSOURCECACHE_H + +#include "qgsabstractcontentcache.h" +#include "qgis_sip.h" +#include "qgis_core.h" + +#ifndef SIP_RUN + +///@cond PRIVATE + +/** + * \ingroup core + * \class QgsSourceCacheEntry + * An entry for a QgsSourceCache, representing a given source's file path + * \since QGIS 3.16 + */ +class CORE_EXPORT QgsSourceCacheEntry : public QgsAbstractContentCacheEntry +{ + public: + + /** + * Constructor for QgsSourceCacheEntry, corresponding to the specified \a path. + */ + QgsSourceCacheEntry( const QString &path ) ; + + //! The local file path of the source string + QString filePath; + + int dataSize() const override; + void dump() const override; + bool isEqual( const QgsAbstractContentCacheEntry *other ) const override; + +}; + +///@endcond +#endif + +/** + * \class QgsSourceCache + * \ingroup core + * A cache for source strings that returns a local file path containing the source content. + * + * QgsSourceCache is not usually directly created, but rather accessed through + * QgsApplication::sourceCache(). + * + * \since QGIS 3.16 +*/ +#ifdef SIP_RUN +class CORE_EXPORT QgsSourceCache : public QgsAbstractContentCacheBase // for sip we skip to the base class and avoid the template difficulty +{ +#else +class CORE_EXPORT QgsSourceCache : public QgsAbstractContentCache< QgsSourceCacheEntry > +{ +#endif + Q_OBJECT + + public: + + /** + * Constructor for QgsSourceCache, with the specified \a parent object. + */ + QgsSourceCache( QObject *parent SIP_TRANSFERTHIS = nullptr ); + + /** + * Returns a local file path reflecting the content of a specified source \a path + * + * \a path may be a local file, remote (HTTP) url, or a base 64 encoded string (with a "base64:" prefix). + */ + QString localFilePath( const QString &path, bool blocking = false ); + + signals: + + /** + * Emitted when the cache has finished retrieving a 3D model from a remote \a url. + */ + void remoteSourceFetched( const QString &url ); + + private: + + QString fetchSource( const QString &path, bool &isBroken, bool blocking = false ) const; + + std::unique_ptr< QTemporaryDir > temporaryDir; +}; + +#endif // QGSSOURCECACHE_H diff --git a/src/core/qgstablecell.cpp b/src/core/qgstablecell.cpp index 8c6174da5be7..6dcef9814343 100644 --- a/src/core/qgstablecell.cpp +++ b/src/core/qgstablecell.cpp @@ -17,6 +17,7 @@ #include "qgsapplication.h" #include "qgsnumericformatregistry.h" #include "qgsnumericformat.h" +#include "qgsreadwritecontext.h" QgsTableCell::QgsTableCell( const QVariant &content ) : mContent( content ) @@ -26,7 +27,10 @@ QgsTableCell::QgsTableCell( const QgsTableCell &other ) : mContent( other.mContent ) , mBackgroundColor( other.mBackgroundColor ) , mForegroundColor( other.mForegroundColor ) + , mTextFormat( other.mTextFormat ) , mFormat( other.mFormat ? other.mFormat->clone() : nullptr ) + , mHAlign( other.mHAlign ) + , mVAlign( other.mVAlign ) {} QgsTableCell::~QgsTableCell() = default; @@ -35,8 +39,11 @@ QgsTableCell &QgsTableCell::operator=( const QgsTableCell &other ) { mContent = other.mContent; mBackgroundColor = other.mBackgroundColor; - mForegroundColor = other.mForegroundColor; + mForegroundColor = other.mForegroundColor; + mTextFormat = other.mTextFormat; mFormat.reset( other.mFormat ? other.mFormat->clone() : nullptr ); + mHAlign = other.mHAlign; + mVAlign = other.mVAlign; return *this; } @@ -54,21 +61,48 @@ QVariantMap QgsTableCell::properties( const QgsReadWriteContext &context ) const { QVariantMap res; res.insert( QStringLiteral( "content" ), mContent ); - res.insert( QStringLiteral( "foreground" ), mForegroundColor ); res.insert( QStringLiteral( "background" ), mBackgroundColor ); + res.insert( QStringLiteral( "foreground" ), mForegroundColor ); if ( mFormat ) { res.insert( QStringLiteral( "format_type" ), mFormat->id() ); res.insert( QStringLiteral( "format" ), mFormat->configuration( context ) ); } + + if ( mTextFormat.isValid() ) + { + QDomDocument textDoc; + QDomElement textElem = mTextFormat.writeXml( textDoc, context ); + textDoc.appendChild( textElem ); + res.insert( QStringLiteral( "text_format" ), textDoc.toString() ); + } + + res.insert( QStringLiteral( "halign" ), static_cast< int >( mHAlign ) ); + res.insert( QStringLiteral( "valign" ), static_cast< int >( mVAlign ) ); + return res; } void QgsTableCell::setProperties( const QVariantMap &properties, const QgsReadWriteContext &context ) { mContent = properties.value( QStringLiteral( "content" ) ); - mForegroundColor = properties.value( QStringLiteral( "foreground" ) ).value< QColor >(); mBackgroundColor = properties.value( QStringLiteral( "background" ) ).value< QColor >(); + mForegroundColor = properties.value( QStringLiteral( "foreground" ) ).value< QColor >(); + + QDomDocument doc; + QDomElement elem; + const QString textXml = properties.value( QStringLiteral( "text_format" ) ).toString(); + if ( !textXml.isEmpty() ) + { + doc.setContent( textXml ); + elem = doc.documentElement(); + mTextFormat.readXml( elem, context ); + } + else + { + mTextFormat = QgsTextFormat(); + } + if ( properties.contains( QStringLiteral( "format_type" ) ) ) { @@ -80,4 +114,27 @@ void QgsTableCell::setProperties( const QVariantMap &properties, const QgsReadWr { mFormat.reset(); } + + mHAlign = static_cast< Qt::Alignment >( properties.value( QStringLiteral( "halign" ), Qt::AlignLeft ).toInt() ); + mVAlign = static_cast< Qt::Alignment >( properties.value( QStringLiteral( "valign" ), Qt::AlignVCenter ).toInt() ); +} + +Qt::Alignment QgsTableCell::horizontalAlignment() const +{ + return mHAlign; +} + +void QgsTableCell::setHorizontalAlignment( Qt::Alignment alignment ) +{ + mHAlign = alignment; +} + +Qt::Alignment QgsTableCell::verticalAlignment() const +{ + return mVAlign; +} + +void QgsTableCell::setVerticalAlignment( Qt::Alignment alignment ) +{ + mVAlign = alignment; } diff --git a/src/core/qgstablecell.h b/src/core/qgstablecell.h index eddad1a2e25b..0692c9f099b3 100644 --- a/src/core/qgstablecell.h +++ b/src/core/qgstablecell.h @@ -17,6 +17,7 @@ #include "qgis_core.h" #include "qgis_sip.h" +#include "qgstextformat.h" #include #include #include @@ -94,6 +95,26 @@ class CORE_EXPORT QgsTableCell */ void setForegroundColor( const QColor &color ) { mForegroundColor = color; } + /** + * Returns the cell's text format. + * + * \note The text format will only be used if hasTextFormat() returns TRUE. + * + * \see setTextFormat() + * \since QGIS 3.16 + */ + QgsTextFormat textFormat() const { return mTextFormat; } + + /** + * Sets the cell's text \a format. + * + * \note The text format will only be used if hasTextFormat() returns TRUE. + * + * \see textFormat() + * \since QGIS 3.16 + */ + void setTextFormat( const QgsTextFormat &format ) { mTextFormat = format; } + /** * Returns the numeric format used for numbers in the cell, or NULLPTR if no format is set. * @@ -110,6 +131,42 @@ class CORE_EXPORT QgsTableCell */ void setNumericFormat( QgsNumericFormat *format SIP_TRANSFER ); + /** + * Returns the horizontal alignment for text in the cell. + * + * \see setHorizontalAlignment() + * \see verticalAlignment() + * \since QGIS 3.16 + */ + Qt::Alignment horizontalAlignment() const; + + /** + * Sets the horizontal \a alignment for text in the cell. + * + * \see horizontalAlignment() + * \see setVerticalAlignment() + * \since QGIS 3.16 + */ + void setHorizontalAlignment( Qt::Alignment alignment ); + + /** + * Returns the vertical alignment for text in the cell. + * + * \see setVerticalAlignment() + * \see horizontalAlignment() + * \since QGIS 3.16 + */ + Qt::Alignment verticalAlignment() const; + + /** + * Sets the vertical \a alignment for text in the cell. + * + * \see verticalAlignment() + * \see setHorizontalAlignment() + * \since QGIS 3.16 + */ + void setVerticalAlignment( Qt::Alignment alignment ); + /** * Returns the properties of the cell. * @@ -138,7 +195,12 @@ class CORE_EXPORT QgsTableCell QVariant mContent; QColor mBackgroundColor; QColor mForegroundColor; + QgsTextFormat mTextFormat; std::unique_ptr< QgsNumericFormat > mFormat; + + Qt::Alignment mHAlign = Qt::AlignLeft; + Qt::Alignment mVAlign = Qt::AlignVCenter; + }; /** diff --git a/src/core/qgstessellator.cpp b/src/core/qgstessellator.cpp index 9b4dbfa27957..f73d50d1d0a2 100644 --- a/src/core/qgstessellator.cpp +++ b/src/core/qgstessellator.cpp @@ -30,11 +30,23 @@ #include #include #include +#include #include #include +static std::pair rotateCoords( float x, float y, float origin_x, float origin_y, float r ) +{ + r = qDegreesToRadians( r ); + float x0 = x - origin_x, y0 = y - origin_y; + // p0 = x0 + i * y0 + // rot = cos(r) + i * sin(r) + // p0 * rot = x0 * cos(r) - y0 * sin(r) + i * [ x0 * sin(r) + y0 * cos(r) ] + float x1 = origin_x + x0 * qCos( r ) - y0 * qSin( r ); + float y1 = origin_y + x0 * qSin( r ) + y0 * qCos( r ); + return std::make_pair( x1, y1 ); +} -static void make_quad( float x0, float y0, float z0, float x1, float y1, float z1, float height, QVector &data, bool addNormals ) +static void make_quad( float x0, float y0, float z0, float x1, float y1, float z1, float height, QVector &data, bool addNormals, bool addTextureCoords, float textureRotation ) { float dx = x1 - x0; float dy = -( y1 - y0 ); @@ -44,48 +56,139 @@ static void make_quad( float x0, float y0, float z0, float x1, float y1, float z vn = -vn; vn.normalize(); + float u0, v0; + float u1, v1; + float u2, v2; + float u3, v3; + + QVector textureCoordinates; + textureCoordinates.reserve( 12 ); + // select which side of the coordinates to use (x, z or y, z) depending on which side is smaller + if ( fabsf( dy ) <= fabsf( dx ) ) + { + // consider x and z as the texture coordinates + u0 = x0; + v0 = z0 + height; + + u1 = x1; + v1 = z1 + height; + + u2 = x0; + v2 = z0; + + u3 = x1; + v3 = z1; + } + else + { + // consider y and z as the texture coowallsTextureRotationrdinates + u0 = -y0; + v0 = z0 + height; + + u1 = -y1; + v1 = z1 + height; + + u2 = -y0; + v2 = z0; + + u3 = -y1; + v3 = z1; + } + + textureCoordinates.push_back( u0 ); + textureCoordinates.push_back( v0 ); + + textureCoordinates.push_back( u1 ); + textureCoordinates.push_back( v1 ); + + textureCoordinates.push_back( u2 ); + textureCoordinates.push_back( v2 ); + + textureCoordinates.push_back( u2 ); + textureCoordinates.push_back( v2 ); + + textureCoordinates.push_back( u1 ); + textureCoordinates.push_back( v1 ); + + textureCoordinates.push_back( u3 ); + textureCoordinates.push_back( v3 ); + + for ( int i = 0; i < textureCoordinates.size(); i += 2 ) + { + std::pair rotated = rotateCoords( textureCoordinates[i], textureCoordinates[i + 1], 0, 0, textureRotation ); + textureCoordinates[i] = rotated.first; + textureCoordinates[i + 1] = rotated.second; + } + // triangle 1 + // vertice 1 data << x0 << z0 + height << -y0; if ( addNormals ) data << vn.x() << vn.y() << vn.z(); + if ( addTextureCoords ) + data << textureCoordinates[0] << textureCoordinates[1]; + // vertice 2 data << x1 << z1 + height << -y1; if ( addNormals ) data << vn.x() << vn.y() << vn.z(); + if ( addTextureCoords ) + data << textureCoordinates[2] << textureCoordinates[3]; + // verice 3 data << x0 << z0 << -y0; if ( addNormals ) data << vn.x() << vn.y() << vn.z(); + if ( addTextureCoords ) + data << textureCoordinates[4] << textureCoordinates[5]; // triangle 2 + // vertice 1 data << x0 << z0 << -y0; if ( addNormals ) data << vn.x() << vn.y() << vn.z(); + if ( addTextureCoords ) + data << textureCoordinates[6] << textureCoordinates[7]; + // vertice 2 data << x1 << z1 + height << -y1; if ( addNormals ) data << vn.x() << vn.y() << vn.z(); + if ( addTextureCoords ) + data << textureCoordinates[8] << textureCoordinates[9]; + // vertice 3 data << x1 << z1 << -y1; if ( addNormals ) data << vn.x() << vn.y() << vn.z(); + if ( addTextureCoords ) + data << textureCoordinates[10] << textureCoordinates[11]; } -QgsTessellator::QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals, bool addBackFaces ) +QgsTessellator::QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals, bool addBackFaces, bool noZ, + bool addTextureCoords, int facade, float textureRotation ) : mOriginX( originX ) , mOriginY( originY ) , mAddNormals( addNormals ) , mInvertNormals( invertNormals ) , mAddBackFaces( addBackFaces ) + , mAddTextureCoords( addTextureCoords ) + , mNoZ( noZ ) + , mTessellatedFacade( facade ) + , mTextureRotation( textureRotation ) { init(); } -QgsTessellator::QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals, bool addBackFaces, bool noZ ) +QgsTessellator::QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals, bool addBackFaces, bool noZ, + bool addTextureCoords, int facade, float textureRotation ) : mBounds( bounds ) , mOriginX( mBounds.xMinimum() ) , mOriginY( mBounds.yMinimum() ) , mAddNormals( addNormals ) , mInvertNormals( invertNormals ) , mAddBackFaces( addBackFaces ) + , mAddTextureCoords( addTextureCoords ) , mNoZ( noZ ) + , mTessellatedFacade( facade ) + , mTextureRotation( textureRotation ) { init(); } @@ -95,6 +198,8 @@ void QgsTessellator::init() mStride = 3 * sizeof( float ); if ( mAddNormals ) mStride += 3 * sizeof( float ); + if ( mAddTextureCoords ) + mStride += 2 * sizeof( float ); } static bool _isRingCounterClockWise( const QgsCurve &ring ) @@ -113,7 +218,8 @@ static bool _isRingCounterClockWise( const QgsCurve &ring ) return a > 0; // clockwise if a is negative } -static void _makeWalls( const QgsLineString &ring, bool ccw, float extrusionHeight, QVector &data, bool addNormals, double originX, double originY ) +static void _makeWalls( const QgsLineString &ring, bool ccw, float extrusionHeight, QVector &data, + bool addNormals, bool addTextureCoords, double originX, double originY, float textureRotation ) { // we need to find out orientation of the ring so that the triangles we generate // face the right direction @@ -131,7 +237,7 @@ static void _makeWalls( const QgsLineString &ring, bool ccw, float extrusionHeig float z1 = std::isnan( pt.z() ) ? 0 : pt.z(); // make a quad - make_quad( x0, y0, z0, x1, y1, z1, extrusionHeight, data, addNormals ); + make_quad( x0, y0, z0, x1, y1, z1, extrusionHeight, data, addNormals, addTextureCoords, textureRotation ); ptPrev = pt; } } @@ -419,7 +525,6 @@ double _minimum_distance_between_coordinates( const QgsPolygon &polygon ) return min_d != 1e20 ? std::sqrt( min_d ) : 1e20; } - void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeight ) { const QgsLineString *exterior = qgsgeometry_cast< const QgsLineString * >( polygon.exteriorRing() ); @@ -434,23 +539,94 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh float zMin = std::numeric_limits::max(); float zMax = std::numeric_limits::min(); - if ( pCount == 4 && polygon.numInteriorRings() == 0 ) + const float scale = mBounds.isNull() ? 1.0 : std::max( 10000.0 / mBounds.width(), 10000.0 / mBounds.height() ); + + std::unique_ptr toNewBase, toOldBase; + QgsPoint ptStart, pt0; + std::unique_ptr polygonNew; + auto rotatePolygonToXYPlane = [&]() + { + if ( !mNoZ && pNormal != QVector3D( 0, 0, 1 ) ) + { + // this is not a horizontal plane - need to reproject the polygon to a new base so that + // we can do the triangulation in a plane + QVector3D pXVector, pYVector; + _normalVectorToXYVectors( pNormal, pXVector, pYVector ); + + // so now we have three orthogonal unit vectors defining new base + // let's build transform matrix. We actually need just a 3x3 matrix, + // but Qt does not have good support for it, so using 4x4 matrix instead. + toNewBase.reset( new QMatrix4x4( + pXVector.x(), pXVector.y(), pXVector.z(), 0, + pYVector.x(), pYVector.y(), pYVector.z(), 0, + pNormal.x(), pNormal.y(), pNormal.z(), 0, + 0, 0, 0, 0 ) ); + + // our 3x3 matrix is orthogonal, so for inverse we only need to transpose it + toOldBase.reset( new QMatrix4x4( toNewBase->transposed() ) ); + } + + ptStart = QgsPoint( exterior->startPoint() ); + pt0 = QgsPoint( QgsWkbTypes::PointZ, ptStart.x(), ptStart.y(), std::isnan( ptStart.z() ) ? 0 : ptStart.z() ); + + // subtract ptFirst from geometry for better numerical stability in triangulation + // and apply new 3D vector base if the polygon is not horizontal + + polygonNew.reset( _transform_polygon_to_new_base( polygon, pt0, toNewBase.get(), scale ) ); + }; + + if ( !mNoZ && !qgsDoubleNear( pNormal.length(), 1, 0.001 ) ) + return; // this should not happen - pNormal should be normalized to unit length + + QVector3D upVector( 0, 0, 1 ); + float pNormalUpVectorDotProduct = QVector3D::dotProduct( upVector, pNormal ); + float radsBetwwenUpNormal = qAcos( pNormalUpVectorDotProduct ); + + float detectionDelta = qDegreesToRadians( 10.0f ); + int facade = 0; + if ( radsBetwwenUpNormal > M_PI_2 - detectionDelta && radsBetwwenUpNormal < M_PI_2 + detectionDelta ) facade = 1; + else if ( radsBetwwenUpNormal > - M_PI_2 - detectionDelta && radsBetwwenUpNormal < -M_PI_2 + detectionDelta ) facade = 1; + else facade = 2; + + if ( pCount == 4 && polygon.numInteriorRings() == 0 && ( mTessellatedFacade & facade ) ) { + QgsLineString *triangle = nullptr; + if ( mAddTextureCoords ) + { + rotatePolygonToXYPlane(); + triangle = qgsgeometry_cast< QgsLineString * >( polygonNew->exteriorRing() ); + Q_ASSERT( polygonNew->exteriorRing()->numPoints() >= 3 ); + } + // polygon is a triangle - write vertices to the output data array without triangulation const double *xData = exterior->xData(); const double *yData = exterior->yData(); const double *zData = !mNoZ ? exterior->zData() : nullptr; for ( int i = 0; i < 3; i++ ) { - float z = ( !zData ? 0 : *zData++ ); + float z = mNoZ ? 0 : *zData; if ( z < zMin ) zMin = z; if ( z > zMax ) zMax = z; - mData << *xData++ - mOriginX << z << - *yData++ + mOriginY; + mData << *xData - mOriginX << z << - *yData + mOriginY; if ( mAddNormals ) mData << pNormal.x() << pNormal.z() << - pNormal.y(); + if ( mAddTextureCoords ) + { + std::pair p( triangle->xAt( i ), triangle->yAt( i ) ); + if ( facade & 1 ) + { + p = rotateCoords( p.first, p.second, 0.0f, 0.0f, mTextureRotation ); + } + else if ( facade & 2 ) + { + p = rotateCoords( p.first, p.second, 0.0f, 0.0f, mTextureRotation ); + } + mData << p.first << p.second; + } + xData++; yData++; zData++; } if ( mAddBackFaces ) @@ -461,45 +637,26 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh mData << exterior->xAt( i ) - mOriginX << ( mNoZ ? 0 : exterior->zAt( i ) ) << - exterior->yAt( i ) + mOriginY; if ( mAddNormals ) mData << -pNormal.x() << -pNormal.z() << pNormal.y(); + if ( mAddTextureCoords ) + { + std::pair p( triangle->xAt( i ), triangle->yAt( i ) ); + if ( facade & 1 ) + { + p = rotateCoords( p.first, p.second, 0.0f, 0.0f, mTextureRotation ); + } + else if ( facade & 2 ) + { + p = rotateCoords( p.first, p.second, 0.0f, 0.0f, mTextureRotation ); + } + mData << p.first << p.second; + } } } } - else + else if ( mTessellatedFacade & facade ) { - if ( !mNoZ && !qgsDoubleNear( pNormal.length(), 1, 0.001 ) ) - return; // this should not happen - pNormal should be normalized to unit length - - std::unique_ptr toNewBase, toOldBase; - if ( !mNoZ && pNormal != QVector3D( 0, 0, 1 ) ) - { - // this is not a horizontal plane - need to reproject the polygon to a new base so that - // we can do the triangulation in a plane - QVector3D pXVector, pYVector; - _normalVectorToXYVectors( pNormal, pXVector, pYVector ); - - // so now we have three orthogonal unit vectors defining new base - // let's build transform matrix. We actually need just a 3x3 matrix, - // but Qt does not have good support for it, so using 4x4 matrix instead. - toNewBase.reset( new QMatrix4x4( - pXVector.x(), pXVector.y(), pXVector.z(), 0, - pYVector.x(), pYVector.y(), pYVector.z(), 0, - pNormal.x(), pNormal.y(), pNormal.z(), 0, - 0, 0, 0, 0 ) ); - - // our 3x3 matrix is orthogonal, so for inverse we only need to transpose it - toOldBase.reset( new QMatrix4x4( toNewBase->transposed() ) ); - } - - const QgsPoint ptStart( exterior->startPoint() ); - const QgsPoint pt0( QgsWkbTypes::PointZ, ptStart.x(), ptStart.y(), std::isnan( ptStart.z() ) ? 0 : ptStart.z() ); - - const float scale = mBounds.isNull() ? 1.0 : std::max( 10000.0 / mBounds.width(), 10000.0 / mBounds.height() ); - - // subtract ptFirst from geometry for better numerical stability in triangulation - // and apply new 3D vector base if the polygon is not horizontal - - std::unique_ptr polygonNew( _transform_polygon_to_new_base( polygon, pt0, toNewBase.get(), scale ) ); + rotatePolygonToXYPlane(); if ( _minimum_distance_between_coordinates( *polygonNew ) < 0.001 ) { @@ -563,7 +720,7 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh std::vector triangles = cdt->GetTriangles(); - mData.reserve( mData.size() + triangles.size() * ( ( mAddNormals ? 6 : 3 ) * ( mAddBackFaces ? 2 : 1 ) ) ); + mData.reserve( mData.size() + 3 * triangles.size() * ( stride() / sizeof( float ) ) ); for ( size_t i = 0; i < triangles.size(); ++i ) { p2t::Triangle *t = triangles[i]; @@ -584,6 +741,11 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh mData << fx << fz << -fy; if ( mAddNormals ) mData << pNormal.x() << pNormal.z() << - pNormal.y(); + if ( mAddTextureCoords ) + { + std::pair pr = rotateCoords( p->x, p->y, 0.0f, 0.0f, mTextureRotation ); + mData << pr.first << pr.second; + } } if ( mAddBackFaces ) @@ -601,6 +763,11 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh mData << fx << fz << -fy; if ( mAddNormals ) mData << -pNormal.x() << -pNormal.z() << pNormal.y(); + if ( mAddTextureCoords ) + { + std::pair pr = rotateCoords( p->x, p->y, 0.0f, 0.0f, mTextureRotation ); + mData << pr.first << pr.second; + } } } } @@ -615,12 +782,12 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh } // add walls if extrusion is enabled - if ( extrusionHeight != 0 ) + if ( extrusionHeight != 0 && ( mTessellatedFacade & 1 ) ) { - _makeWalls( *exterior, false, extrusionHeight, mData, mAddNormals, mOriginX, mOriginY ); + _makeWalls( *exterior, false, extrusionHeight, mData, mAddNormals, mAddTextureCoords, mOriginX, mOriginY, mTextureRotation ); for ( int i = 0; i < polygon.numInteriorRings(); ++i ) - _makeWalls( *qgsgeometry_cast< const QgsLineString * >( polygon.interiorRing( i ) ), true, extrusionHeight, mData, mAddNormals, mOriginX, mOriginY ); + _makeWalls( *qgsgeometry_cast< const QgsLineString * >( polygon.interiorRing( i ) ), true, extrusionHeight, mData, mAddNormals, mAddTextureCoords, mOriginX, mOriginY, mTextureRotation ); zMax += extrusionHeight; } @@ -645,7 +812,7 @@ QgsPoint getPointFromData( QVector< float >::const_iterator &it ) int QgsTessellator::dataVerticesCount() const { - return mData.size() / ( mAddNormals ? 6 : 3 ); + return mData.size() / ( stride() / sizeof( float ) ); } std::unique_ptr QgsTessellator::asMultiPolygon() const diff --git a/src/core/qgstessellator.h b/src/core/qgstessellator.h index 3f3a84557c0b..3312652ed3b7 100644 --- a/src/core/qgstessellator.h +++ b/src/core/qgstessellator.h @@ -41,7 +41,8 @@ class CORE_EXPORT QgsTessellator { public: //! Creates tessellator with a specified origin point of the world (in map coordinates) - QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals = false, bool addBackFaces = false ); + QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false, + bool addTextureCoords = false, int facade = 3, float textureRotation = 0.0f ); /** * Creates tessellator with a specified \a bounds of input geometry coordinates. @@ -52,7 +53,8 @@ class CORE_EXPORT QgsTessellator * * \since QGIS 3.10 */ - QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false ); + QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false, + bool addTextureCoords = false, int facade = 3, float textureRotation = 0.0f ); //! Tessellates a triangle and adds its vertex entries to the output data array void addPolygon( const QgsPolygon &polygon, float extrusionHeight ); @@ -95,9 +97,12 @@ class CORE_EXPORT QgsTessellator bool mAddNormals = false; bool mInvertNormals = false; bool mAddBackFaces = false; + bool mAddTextureCoords = false; QVector mData; int mStride; bool mNoZ = false; + int mTessellatedFacade = 3; + float mTextureRotation = 0.0f; float mZMin = std::numeric_limits::max(); float mZMax = std::numeric_limits::min(); diff --git a/src/core/qgsvectorfilewriter.h b/src/core/qgsvectorfilewriter.h index 80e6d643e85a..a9e3a6144e28 100644 --- a/src/core/qgsvectorfilewriter.h +++ b/src/core/qgsvectorfilewriter.h @@ -635,7 +635,7 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags = QgsFeatureSink::SinkFlags(), QString *newFilename = nullptr, - QString *newLayer = nullptr ); + QString *newLayer = nullptr ) SIP_FACTORY; /** * Writes a layer out to a vector file. diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 7c885e48aa35..007cc3e4f77b 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -3367,6 +3367,7 @@ bool QgsVectorLayer::commitChanges() delete mEditBuffer; mEditBuffer = nullptr; undoStack()->clear(); + emit afterCommitChanges(); emit editingStopped(); } else @@ -5335,6 +5336,12 @@ void QgsVectorLayer::emitDataChanged() mDataChangedFired = false; } +void QgsVectorLayer::onAfterCommitChangesDependency() +{ + mDataChangedFired = true; + reload(); +} + bool QgsVectorLayer::setDependencies( const QSet &oDeps ) { QSet deps; @@ -5358,6 +5365,7 @@ bool QgsVectorLayer::setDependencies( const QSet &oDeps ) disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged ); disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged ); disconnect( lyr, &QgsVectorLayer::repaintRequested, this, &QgsVectorLayer::triggerRepaint ); + disconnect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency ); } // assign new dependencies @@ -5378,6 +5386,7 @@ bool QgsVectorLayer::setDependencies( const QSet &oDeps ) connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged ); connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged ); connect( lyr, &QgsVectorLayer::repaintRequested, this, &QgsVectorLayer::triggerRepaint ); + connect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency ); } // if new layers are present, emit a data change diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index ceccacba74d7..a6c00996090b 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -101,9 +101,9 @@ typedef QSet QgsAttributeIds; * * Sample usage of the QgsVectorLayer class: * - * \code - * QString uri = "point?crs=epsg:4326&field=id:integer"; - * QgsVectorLayer *scratchLayer = new QgsVectorLayer(uri, "Scratch point layer", "memory"); + * \code{.py} + * uri = "point?crs=epsg:4326&field=id:integer" + * scratchLayer = QgsVectorLayer(uri, "Scratch point layer", "memory") * \endcode * * The main data providers supported by QGIS are listed below. @@ -2482,6 +2482,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte //! Emitted before changes are rolled back. void beforeRollBack(); + /** + * Emitted after changes are commited to the data provider. + * \since QGIS 3.16 + */ + void afterCommitChanges(); + /** * Emitted after changes are rolled back. * \since QGIS 3.4 @@ -2709,6 +2715,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte void onSymbolsCounted(); void onDirtyTransaction( const QString &sql, const QString &name ); void emitDataChanged(); + void onAfterCommitChangesDependency(); private: void updateDefaultValues( QgsFeatureId fid, QgsFeature feature = QgsFeature() ); diff --git a/src/core/qgsvectorlayerjoininfo.cpp b/src/core/qgsvectorlayerjoininfo.cpp index 20f0e97de7b4..caee469760b7 100644 --- a/src/core/qgsvectorlayerjoininfo.cpp +++ b/src/core/qgsvectorlayerjoininfo.cpp @@ -100,11 +100,15 @@ QStringList QgsVectorLayerJoinInfo::joinFieldNamesSubset( const QgsVectorLayerJo } else { - for ( const QgsField &f : info.joinLayer()->fields() ) + if ( info.joinLayer() ) { - if ( !info.joinFieldNamesBlockList().contains( f.name() ) - && f.name() != info.joinFieldName() ) - fieldNames.append( f.name() ); + const QgsFields fields { info.joinLayer()->fields() }; + for ( const QgsField &f : fields ) + { + if ( !info.joinFieldNamesBlockList().contains( f.name() ) + && f.name() != info.joinFieldName() ) + fieldNames.append( f.name() ); + } } } } diff --git a/src/core/raster/qgsbrightnesscontrastfilter.cpp b/src/core/raster/qgsbrightnesscontrastfilter.cpp index 14044550f0fe..9862caf5a7a1 100644 --- a/src/core/raster/qgsbrightnesscontrastfilter.cpp +++ b/src/core/raster/qgsbrightnesscontrastfilter.cpp @@ -183,7 +183,7 @@ int QgsBrightnessContrastFilter::adjustColorComponent( int colorComponent, int a double adjustedColor = colorComponent / alphaFactor; // Make sure to return a premultiplied color - return alphaFactor * qBound( 0., std::pow( ( ( ( ( ( ( adjustedColor / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ) / 255, gammaCorrection ), 255. ); + return alphaFactor * qBound( 0., 255 * std::pow( ( ( ( ( ( ( adjustedColor / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ) / 255, gammaCorrection ), 255. ); } } diff --git a/src/core/raster/qgspalettedrasterrenderer.cpp b/src/core/raster/qgspalettedrasterrenderer.cpp index d20c4ddc6b42..558bf25937fe 100644 --- a/src/core/raster/qgspalettedrasterrenderer.cpp +++ b/src/core/raster/qgspalettedrasterrenderer.cpp @@ -499,7 +499,7 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromRas int count = histogram.histogramVector.at( idx ); if ( count > 0 ) { - data << Class( currentValue, QColor(), QString::number( currentValue ) ); + data << Class( currentValue, QColor(), QLocale().toString( currentValue ) ); presentValues++; } currentValue += interval; diff --git a/src/core/symbology/qgsfillsymbollayer.cpp b/src/core/symbology/qgsfillsymbollayer.cpp index a118f23c5f64..c64a3865d409 100644 --- a/src/core/symbology/qgsfillsymbollayer.cpp +++ b/src/core/symbology/qgsfillsymbollayer.cpp @@ -1597,7 +1597,14 @@ void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF &points, const QVec p->setPen( QPen( Qt::NoPen ) ); QTransform bkTransform = mBrush.transform(); - if ( context.renderContext().testFlag( QgsRenderContext::RenderMapTile ) ) + if ( applyBrushTransformFromContext() && !context.renderContext().textureOrigin().isNull() ) + { + QPointF leftCorner = context.renderContext().textureOrigin(); + QTransform t = mBrush.transform(); + t.translate( leftCorner.x(), leftCorner.y() ); + mBrush.setTransform( t ); + } + else if ( context.renderContext().testFlag( QgsRenderContext::RenderMapTile ) ) { //transform brush to upper left corner of geometry bbox QPointF leftCorner = points.boundingRect().topLeft(); @@ -1744,6 +1751,11 @@ bool QgsImageFillSymbolLayer::hasDataDefinedProperties() const return false; } +bool QgsImageFillSymbolLayer::applyBrushTransformFromContext() const +{ + return true; +} + //QgsSVGFillSymbolLayer @@ -4164,6 +4176,11 @@ void QgsRasterFillSymbolLayer::applyDataDefinedSettings( QgsSymbolRenderContext applyPattern( mBrush, file, width, opacity, context ); } +bool QgsRasterFillSymbolLayer::applyBrushTransformFromContext() const +{ + return false; +} + void QgsRasterFillSymbolLayer::applyPattern( QBrush &brush, const QString &imageFilePath, const double width, const double alpha, const QgsSymbolRenderContext &context ) { QSize size; diff --git a/src/core/symbology/qgsfillsymbollayer.h b/src/core/symbology/qgsfillsymbollayer.h index 3a214f466f25..180010b96b08 100644 --- a/src/core/symbology/qgsfillsymbollayer.h +++ b/src/core/symbology/qgsfillsymbollayer.h @@ -710,6 +710,13 @@ class CORE_EXPORT QgsImageFillSymbolLayer: public QgsFillSymbolLayer virtual void applyDataDefinedSettings( QgsSymbolRenderContext &context ) { Q_UNUSED( context ) } + /** + * Returns TRUE if the image brush should be transformed using the render context's texture origin. + * + * \since QGIS 3.16 + */ + virtual bool applyBrushTransformFromContext() const; + private: #ifdef SIP_RUN QgsImageFillSymbolLayer( const QgsImageFillSymbolLayer &other ); @@ -922,7 +929,7 @@ class CORE_EXPORT QgsRasterFillSymbolLayer: public QgsImageFillSymbolLayer protected: void applyDataDefinedSettings( QgsSymbolRenderContext &context ) override; - + bool applyBrushTransformFromContext() const override; private: //! Path to the image file diff --git a/src/core/symbology/qgssymbol.cpp b/src/core/symbology/qgssymbol.cpp index a3602dc64b53..c2b1a52b1e29 100644 --- a/src/core/symbology/qgssymbol.cpp +++ b/src/core/symbology/qgssymbol.cpp @@ -832,6 +832,20 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont bool usingSegmentizedGeometry = false; context.setGeometry( geom.constGet() ); + if ( geom.type() != QgsWkbTypes::PointGeometry && !geom.boundingBox().isNull() ) + { + try + { + const QPointF boundsOrigin = _getPoint( context, QgsPoint( geom.boundingBox().xMinimum(), geom.boundingBox().yMinimum() ) ); + if ( std::isfinite( boundsOrigin.x() ) && std::isfinite( boundsOrigin.y() ) ) + context.setTextureOrigin( boundsOrigin ); + } + catch ( QgsCsException & ) + { + + } + } + bool tileMapRendering = context.testFlag( QgsRenderContext::RenderMapTile ); //convert curve types to normal point/line/polygon ones diff --git a/src/core/textrenderer/qgstextbackgroundsettings.cpp b/src/core/textrenderer/qgstextbackgroundsettings.cpp index 968ee9c0b960..4b8565234824 100644 --- a/src/core/textrenderer/qgstextbackgroundsettings.cpp +++ b/src/core/textrenderer/qgstextbackgroundsettings.cpp @@ -44,6 +44,49 @@ QgsTextBackgroundSettings::~QgsTextBackgroundSettings() //NOLINT } +bool QgsTextBackgroundSettings::operator==( const QgsTextBackgroundSettings &other ) const +{ + if ( !d->enabled == other.enabled() + || d->type != other.type() + || d->svgFile != other.svgFile() + || d->sizeType != other.sizeType() + || d->size != other.size() + || d->sizeUnits != other.sizeUnit() + || d->sizeMapUnitScale != other.sizeMapUnitScale() + || d->rotationType != other.rotationType() + || d->rotation != other.rotation() + || d->offset != other.offset() + || d->offsetUnits != other.offsetUnit() + || d->offsetMapUnitScale != other.offsetMapUnitScale() + || d->radii != other.radii() + || d->radiiUnits != other.radiiUnit() + || d->radiiMapUnitScale != other.radiiMapUnitScale() + || d->blendMode != other.blendMode() + || d->fillColor != other.fillColor() + || d->strokeColor != other.strokeColor() + || d->opacity != other.opacity() + || d->strokeWidth != other.strokeWidth() + || d->strokeWidthUnits != other.strokeWidthUnit() + || d->strokeWidthMapUnitScale != other.strokeWidthMapUnitScale() + || d->joinStyle != other.joinStyle() ) + return false; + + if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() ) + || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) ) + return false; + + if ( static_cast< bool >( d->markerSymbol ) != static_cast< bool >( other.markerSymbol() ) + || ( d->markerSymbol && QgsSymbolLayerUtils::symbolProperties( d->markerSymbol.get() ) != QgsSymbolLayerUtils::symbolProperties( other.markerSymbol() ) ) ) + return false; + + return true; +} + +bool QgsTextBackgroundSettings::operator!=( const QgsTextBackgroundSettings &other ) const +{ + return !( *this == other ); +} + bool QgsTextBackgroundSettings::enabled() const { return d->enabled; diff --git a/src/core/textrenderer/qgstextbackgroundsettings.h b/src/core/textrenderer/qgstextbackgroundsettings.h index da553596bead..fd99f93a8ac4 100644 --- a/src/core/textrenderer/qgstextbackgroundsettings.h +++ b/src/core/textrenderer/qgstextbackgroundsettings.h @@ -91,6 +91,9 @@ class CORE_EXPORT QgsTextBackgroundSettings ~QgsTextBackgroundSettings(); + bool operator==( const QgsTextBackgroundSettings &other ) const; + bool operator!=( const QgsTextBackgroundSettings &other ) const; + /** * Returns whether the background is enabled. * \see setEnabled() diff --git a/src/core/textrenderer/qgstextblock.cpp b/src/core/textrenderer/qgstextblock.cpp index cac6ef27d838..673aebd53245 100644 --- a/src/core/textrenderer/qgstextblock.cpp +++ b/src/core/textrenderer/qgstextblock.cpp @@ -21,6 +21,16 @@ QgsTextBlock::QgsTextBlock( const QgsTextFragment &fragment ) mFragments.append( fragment ); } +QString QgsTextBlock::toPlainText() const +{ + QString res; + for ( const QgsTextFragment &fragment : mFragments ) + { + res.append( fragment.text() ); + } + return res; +} + void QgsTextBlock::append( const QgsTextFragment &fragment ) { mFragments.append( fragment ); diff --git a/src/core/textrenderer/qgstextblock.h b/src/core/textrenderer/qgstextblock.h index 7bb849ccf70b..a879884e2709 100644 --- a/src/core/textrenderer/qgstextblock.h +++ b/src/core/textrenderer/qgstextblock.h @@ -46,6 +46,13 @@ class CORE_EXPORT QgsTextBlock */ explicit QgsTextBlock( const QgsTextFragment &fragment ); + /** + * Converts the block to plain text. + * + * \since QGIS 3.16 + */ + QString toPlainText() const; + /** * Appends a \a fragment to the block. */ diff --git a/src/core/textrenderer/qgstextbuffersettings.cpp b/src/core/textrenderer/qgstextbuffersettings.cpp index d3bc58eff066..c9cc082305b9 100644 --- a/src/core/textrenderer/qgstextbuffersettings.cpp +++ b/src/core/textrenderer/qgstextbuffersettings.cpp @@ -44,6 +44,31 @@ QgsTextBufferSettings::~QgsTextBufferSettings() //NOLINT } +bool QgsTextBufferSettings::operator==( const QgsTextBufferSettings &other ) const +{ + if ( d->enabled != other.enabled() + || d->size != other.size() + || d->sizeUnit != other.sizeUnit() + || d->sizeMapUnitScale != other.sizeMapUnitScale() + || d->color != other.color() + || d->opacity != other.opacity() + || d->fillBufferInterior != other.fillBufferInterior() + || d->joinStyle != other.joinStyle() + || d->blendMode != other.blendMode() ) + return false; + + if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() ) + || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) ) + return false; + + return true; +} + +bool QgsTextBufferSettings::operator!=( const QgsTextBufferSettings &other ) const +{ + return !( *this == other ); +} + bool QgsTextBufferSettings::enabled() const { return d->enabled; diff --git a/src/core/textrenderer/qgstextbuffersettings.h b/src/core/textrenderer/qgstextbuffersettings.h index a2dd979e7060..34ce727498db 100644 --- a/src/core/textrenderer/qgstextbuffersettings.h +++ b/src/core/textrenderer/qgstextbuffersettings.h @@ -59,6 +59,9 @@ class CORE_EXPORT QgsTextBufferSettings ~QgsTextBufferSettings(); + bool operator==( const QgsTextBufferSettings &other ) const; + bool operator!=( const QgsTextBufferSettings &other ) const; + /** * Returns whether the buffer is enabled. * \see setEnabled() diff --git a/src/core/textrenderer/qgstextcharacterformat.cpp b/src/core/textrenderer/qgstextcharacterformat.cpp index ba51602304dd..1eeb30210daa 100644 --- a/src/core/textrenderer/qgstextcharacterformat.cpp +++ b/src/core/textrenderer/qgstextcharacterformat.cpp @@ -72,8 +72,9 @@ void QgsTextCharacterFormat::setOverline( QgsTextCharacterFormat::BooleanValue e mOverline = enabled; } -void QgsTextCharacterFormat::updateFontForFormat( QFont &font ) const +void QgsTextCharacterFormat::updateFontForFormat( QFont &font, const double scaleFactor ) const { + Q_UNUSED( scaleFactor ); #if 0 // settings which affect font metrics are disabled for now if ( mItalic != QgsTextCharacterFormat::BooleanValue::NotSet ) font.setItalic( mItalic == QgsTextCharacterFormat::BooleanValue::SetTrue ); diff --git a/src/core/textrenderer/qgstextcharacterformat.h b/src/core/textrenderer/qgstextcharacterformat.h index 57d8e53de7df..70e149773423 100644 --- a/src/core/textrenderer/qgstextcharacterformat.h +++ b/src/core/textrenderer/qgstextcharacterformat.h @@ -156,8 +156,13 @@ class CORE_EXPORT QgsTextCharacterFormat /** * Updates the specified \a font in place, applying character formatting options which * are applicable on a font level. + * + * The optional \a scaleFactor parameter can specify a font size scaling factor. It is recommended to set this to + * QgsTextRenderer::FONT_WORKAROUND_SCALE and then manually calculations + * based on the resultant font metrics. Failure to do so will result in poor quality text rendering + * at small font sizes. */ - void updateFontForFormat( QFont &font ) const; + void updateFontForFormat( QFont &font, double scaleFactor = 1.0 ) const; private: diff --git a/src/core/textrenderer/qgstextformat.cpp b/src/core/textrenderer/qgstextformat.cpp index 6adca8a198aa..792693501286 100644 --- a/src/core/textrenderer/qgstextformat.cpp +++ b/src/core/textrenderer/qgstextformat.cpp @@ -59,22 +59,123 @@ QgsTextFormat::~QgsTextFormat() //NOLINT } +bool QgsTextFormat::operator==( const QgsTextFormat &other ) const +{ + if ( d->isValid != other.isValid() + || d->textFont != other.font() + || namedStyle() != other.namedStyle() + || d->fontSizeUnits != other.sizeUnit() + || d->fontSizeMapUnitScale != other.sizeMapUnitScale() + || d->fontSize != other.size() + || d->textColor != other.color() + || d->opacity != other.opacity() + || d->blendMode != other.blendMode() + || d->multilineHeight != other.lineHeight() + || d->orientation != other.orientation() + || d->previewBackgroundColor != other.previewBackgroundColor() + || d->allowHtmlFormatting != other.allowHtmlFormatting() + || mBufferSettings != other.mBufferSettings + || mBackgroundSettings != other.mBackgroundSettings + || mShadowSettings != other.mShadowSettings + || mMaskSettings != other.mMaskSettings + || d->mDataDefinedProperties != other.dataDefinedProperties() ) + return false; + + return true; +} + +bool QgsTextFormat::operator!=( const QgsTextFormat &other ) const +{ + return !( *this == other ); +} + +bool QgsTextFormat::isValid() const +{ + return d->isValid; +} + +void QgsTextFormat::setValid() +{ + d->isValid = true; +} + +QgsTextBufferSettings &QgsTextFormat::buffer() +{ + d->isValid = true; + return mBufferSettings; +} + +void QgsTextFormat::setBuffer( const QgsTextBufferSettings &bufferSettings ) +{ + d->isValid = true; + mBufferSettings = bufferSettings; +} + +QgsTextBackgroundSettings &QgsTextFormat::background() +{ + d->isValid = true; + return mBackgroundSettings; +} + +void QgsTextFormat::setBackground( const QgsTextBackgroundSettings &backgroundSettings ) +{ + d->isValid = true; + mBackgroundSettings = backgroundSettings; +} + +QgsTextShadowSettings &QgsTextFormat::shadow() +{ + d->isValid = true; + return mShadowSettings; +} + +void QgsTextFormat::setShadow( const QgsTextShadowSettings &shadowSettings ) +{ + d->isValid = true; + mShadowSettings = shadowSettings; +} + +QgsTextMaskSettings &QgsTextFormat::mask() +{ + d->isValid = true; + return mMaskSettings; +} + +void QgsTextFormat::setMask( const QgsTextMaskSettings &maskSettings ) +{ + d->isValid = true; + mMaskSettings = maskSettings; +} + QFont QgsTextFormat::font() const { return d->textFont; } -QFont QgsTextFormat::scaledFont( const QgsRenderContext &context ) const +QFont QgsTextFormat::scaledFont( const QgsRenderContext &context, double scaleFactor ) const { QFont font = d->textFont; - int fontPixelSize = QgsTextRenderer::sizeToPixel( d->fontSize, context, d->fontSizeUnits, - d->fontSizeMapUnitScale ); - font.setPixelSize( fontPixelSize ); + if ( scaleFactor == 1 ) + { + int fontPixelSize = QgsTextRenderer::sizeToPixel( d->fontSize, context, d->fontSizeUnits, + d->fontSizeMapUnitScale ); + font.setPixelSize( fontPixelSize ); + } + else + { + double fontPixelSize = context.convertToPainterUnits( d->fontSize, d->fontSizeUnits, d->fontSizeMapUnitScale ); + font.setPixelSize( std::round( scaleFactor * fontPixelSize + 0.5 ) ); + } + + font.setLetterSpacing( QFont::AbsoluteSpacing, context.convertToPainterUnits( d->textFont.letterSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor ); + font.setWordSpacing( context.convertToPainterUnits( d->textFont.wordSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor * scaleFactor ); + return font; } void QgsTextFormat::setFont( const QFont &font ) { + d->isValid = true; d->textFont = font; } @@ -89,6 +190,7 @@ QString QgsTextFormat::namedStyle() const void QgsTextFormat::setNamedStyle( const QString &style ) { + d->isValid = true; QgsFontUtils::updateFontViaStyle( d->textFont, style ); d->textNamedStyle = style; } @@ -100,6 +202,7 @@ QgsUnitTypes::RenderUnit QgsTextFormat::sizeUnit() const void QgsTextFormat::setSizeUnit( QgsUnitTypes::RenderUnit unit ) { + d->isValid = true; d->fontSizeUnits = unit; } @@ -110,6 +213,7 @@ QgsMapUnitScale QgsTextFormat::sizeMapUnitScale() const void QgsTextFormat::setSizeMapUnitScale( const QgsMapUnitScale &scale ) { + d->isValid = true; d->fontSizeMapUnitScale = scale; } @@ -120,6 +224,7 @@ double QgsTextFormat::size() const void QgsTextFormat::setSize( double size ) { + d->isValid = true; d->fontSize = size; } @@ -130,6 +235,7 @@ QColor QgsTextFormat::color() const void QgsTextFormat::setColor( const QColor &color ) { + d->isValid = true; d->textColor = color; } @@ -140,6 +246,7 @@ double QgsTextFormat::opacity() const void QgsTextFormat::setOpacity( double opacity ) { + d->isValid = true; d->opacity = opacity; } @@ -150,6 +257,7 @@ QPainter::CompositionMode QgsTextFormat::blendMode() const void QgsTextFormat::setBlendMode( QPainter::CompositionMode mode ) { + d->isValid = true; d->blendMode = mode; } @@ -160,6 +268,7 @@ double QgsTextFormat::lineHeight() const void QgsTextFormat::setLineHeight( double height ) { + d->isValid = true; d->multilineHeight = height; } @@ -170,6 +279,7 @@ QgsTextFormat::TextOrientation QgsTextFormat::orientation() const void QgsTextFormat::setOrientation( TextOrientation orientation ) { + d->isValid = true; d->orientation = orientation; } @@ -180,6 +290,7 @@ bool QgsTextFormat::allowHtmlFormatting() const void QgsTextFormat::setAllowHtmlFormatting( bool allow ) { + d->isValid = true; d->allowHtmlFormatting = allow; } @@ -190,11 +301,13 @@ QColor QgsTextFormat::previewBackgroundColor() const void QgsTextFormat::setPreviewBackgroundColor( const QColor &color ) { + d->isValid = true; d->previewBackgroundColor = color; } void QgsTextFormat::readFromLayer( QgsVectorLayer *layer ) { + d->isValid = true; QFont appFont = QApplication::font(); mTextFontFamily = layer->customProperty( QStringLiteral( "labeling/fontFamily" ), QVariant( appFont.family() ) ).toString(); QString fontFamily = mTextFontFamily; @@ -278,6 +391,7 @@ void QgsTextFormat::readFromLayer( QgsVectorLayer *layer ) void QgsTextFormat::readXml( const QDomElement &elem, const QgsReadWriteContext &context ) { + d->isValid = true; QDomElement textStyleElem; if ( elem.nodeName() == QStringLiteral( "text-style" ) ) textStyleElem = elem; @@ -568,6 +682,7 @@ bool QgsTextFormat::containsAdvancedEffects() const QgsPropertyCollection &QgsTextFormat::dataDefinedProperties() { + d->isValid = true; return d->mDataDefinedProperties; } @@ -588,11 +703,13 @@ QSet QgsTextFormat::referencedFields( const QgsRenderContext &context ) void QgsTextFormat::setDataDefinedProperties( const QgsPropertyCollection &collection ) { + d->isValid = true; d->mDataDefinedProperties = collection; } void QgsTextFormat::updateDataDefinedProperties( QgsRenderContext &context ) { + d->isValid = true; if ( !d->mDataDefinedProperties.hasActiveProperties() ) return; @@ -821,7 +938,9 @@ QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSi context.setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 ); context.setUseAdvancedEffects( true ); + context.setFlag( QgsRenderContext::Antialiasing, true ); context.setPainter( &painter ); + context.setFlag( QgsRenderContext::Antialiasing, true ); // slightly inset text to account for buffer/background double xtrans = 0; diff --git a/src/core/textrenderer/qgstextformat.h b/src/core/textrenderer/qgstextformat.h index eb93c5da4c16..905cc9100444 100644 --- a/src/core/textrenderer/qgstextformat.h +++ b/src/core/textrenderer/qgstextformat.h @@ -47,6 +47,10 @@ class CORE_EXPORT QgsTextFormat RotationBasedOrientation, //!< Horizontally or vertically oriented text based on rotation (only available for map labeling) }; + /** + * Default constructor for QgsTextFormat. Creates a text format initially + * set to an invalid state (see isValid()). + */ QgsTextFormat(); /** @@ -59,11 +63,36 @@ class CORE_EXPORT QgsTextFormat ~QgsTextFormat(); + bool operator==( const QgsTextFormat &other ) const; + bool operator!=( const QgsTextFormat &other ) const; + + /** + * Returns TRUE if the format is valid. + * + * A default constructed QgsTextFormat is invalid, until at least one or more properties + * have been set on the format. An invalid state can be used as a representation of a "not set" + * text format, e.g. for indicating that a default text format should be used. + * + * \note Calling any setter on a QgsTextFormat object will automatically set the format as valid. + * + * \see setValid() + * \since QGIS 3.16 + */ + bool isValid() const; + + /** + * Sets the format to a valid state, without changing any of the default format settings. + * + * \see isValid() + * \since QGIS 3.16 + */ + void setValid(); + /** * Returns a reference to the text buffer settings. * \see setBuffer() */ - QgsTextBufferSettings &buffer() { return mBufferSettings; } + QgsTextBufferSettings &buffer(); /** * Returns a reference to the text buffer settings. @@ -76,13 +105,13 @@ class CORE_EXPORT QgsTextFormat * \param bufferSettings buffer settings * \see buffer() */ - void setBuffer( const QgsTextBufferSettings &bufferSettings ) { mBufferSettings = bufferSettings; } + void setBuffer( const QgsTextBufferSettings &bufferSettings ); /** * Returns a reference to the text background settings. * \see setBackground() */ - QgsTextBackgroundSettings &background() { return mBackgroundSettings; } + QgsTextBackgroundSettings &background(); /** * Returns a reference to the text background settings. @@ -95,13 +124,13 @@ class CORE_EXPORT QgsTextFormat * \param backgroundSettings background settings * \see background() */ - void setBackground( const QgsTextBackgroundSettings &backgroundSettings ) { mBackgroundSettings = backgroundSettings; } + void setBackground( const QgsTextBackgroundSettings &backgroundSettings ); /** * Returns a reference to the text drop shadow settings. * \see setShadow() */ - QgsTextShadowSettings &shadow() { return mShadowSettings; } + QgsTextShadowSettings &shadow(); /** * Returns a reference to the text drop shadow settings. @@ -114,13 +143,13 @@ class CORE_EXPORT QgsTextFormat * \param shadowSettings shadow settings * \see shadow() */ - void setShadow( const QgsTextShadowSettings &shadowSettings ) { mShadowSettings = shadowSettings; } + void setShadow( const QgsTextShadowSettings &shadowSettings ); /** * Returns a reference to the masking settings. * \see setMask() */ - QgsTextMaskSettings &mask() { return mMaskSettings; } + QgsTextMaskSettings &mask(); /** * Returns a reference to the masking settings. @@ -137,7 +166,7 @@ class CORE_EXPORT QgsTextFormat * \see mask() * \since QGIS 3.12 */ - void setMask( const QgsTextMaskSettings &maskSettings ) { mMaskSettings = maskSettings; } + void setMask( const QgsTextMaskSettings &maskSettings ); /** * Returns the font used for rendering text. Note that the size of the font @@ -154,11 +183,15 @@ class CORE_EXPORT QgsTextFormat * Returns a font with the size scaled to match the format's size settings (including * units and map unit scale) for a specified render context. * \param context destination render context + * \param scaleFactor optional font size scaling factor. It is recommended to set this to + * QgsTextRenderer::FONT_WORKAROUND_SCALE and then manually scale painter devices or calculations + * based on the resultant font metrics. Failure to do so will result in poor quality text rendering + * at small font sizes. * \returns font with scaled size * \see font() * \see size() */ - QFont scaledFont( const QgsRenderContext &context ) const; + QFont scaledFont( const QgsRenderContext &context, double scaleFactor = 1.0 ) const; /** * Sets the font used for rendering text. Note that the size of the font @@ -482,4 +515,6 @@ class CORE_EXPORT QgsTextFormat }; +Q_DECLARE_METATYPE( QgsTextFormat ) + #endif // QGSTEXTFORMAT_H diff --git a/src/core/textrenderer/qgstextfragment.cpp b/src/core/textrenderer/qgstextfragment.cpp index b64c05957c33..8029a66c892b 100644 --- a/src/core/textrenderer/qgstextfragment.cpp +++ b/src/core/textrenderer/qgstextfragment.cpp @@ -44,7 +44,7 @@ void QgsTextFragment::setCharacterFormat( const QgsTextCharacterFormat &charForm mCharFormat = charFormat; } -double QgsTextFragment::horizontalAdvance( const QFont &font, bool fontHasBeenUpdatedForFragment ) const +double QgsTextFragment::horizontalAdvance( const QFont &font, bool fontHasBeenUpdatedForFragment, double scaleFactor ) const { if ( fontHasBeenUpdatedForFragment ) { @@ -58,7 +58,7 @@ double QgsTextFragment::horizontalAdvance( const QFont &font, bool fontHasBeenUp else { QFont updatedFont = font; - mCharFormat.updateFontForFormat( updatedFont ); + mCharFormat.updateFontForFormat( updatedFont, scaleFactor ); QFontMetricsF fm( updatedFont ); #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) return fm.width( mText ); diff --git a/src/core/textrenderer/qgstextfragment.h b/src/core/textrenderer/qgstextfragment.h index 3fd8aae7b4a3..ede938ef2101 100644 --- a/src/core/textrenderer/qgstextfragment.h +++ b/src/core/textrenderer/qgstextfragment.h @@ -79,8 +79,13 @@ class CORE_EXPORT QgsTextFragment * * Set \a fontHasBeenUpdatedForFragment to TRUE if \a font already represents the character * format for this fragment. + * + * The optional \a scaleFactor parameter can specify a font size scaling factor. It is recommended to set this to + * QgsTextRenderer::FONT_WORKAROUND_SCALE and then manually calculations + * based on the resultant font metrics. Failure to do so will result in poor quality text rendering + * at small font sizes. */ - double horizontalAdvance( const QFont &font, bool fontHasBeenUpdatedForFragment = false ) const; + double horizontalAdvance( const QFont &font, bool fontHasBeenUpdatedForFragment = false, double scaleFactor = 1.0 ) const; private: diff --git a/src/core/textrenderer/qgstextmasksettings.cpp b/src/core/textrenderer/qgstextmasksettings.cpp index bd0392c0dcee..d00b0c1521b2 100644 --- a/src/core/textrenderer/qgstextmasksettings.cpp +++ b/src/core/textrenderer/qgstextmasksettings.cpp @@ -37,6 +37,30 @@ QgsTextMaskSettings &QgsTextMaskSettings::operator=( const QgsTextMaskSettings & return *this; } +bool QgsTextMaskSettings::operator==( const QgsTextMaskSettings &other ) const +{ + if ( d->enabled != other.enabled() + || d->type != other.type() + || d->size != other.size() + || d->sizeUnit != other.sizeUnit() + || d->sizeMapUnitScale != other.sizeMapUnitScale() + || d->joinStyle != other.joinStyle() + || d->opacity != other.opacity() + || d->maskedSymbolLayers != other.maskedSymbolLayers() ) + return false; + + if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() ) + || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) ) + return false; + + return true; +} + +bool QgsTextMaskSettings::operator!=( const QgsTextMaskSettings &other ) const +{ + return !( *this == other ); +} + bool QgsTextMaskSettings::enabled() const { return d->enabled; diff --git a/src/core/textrenderer/qgstextmasksettings.h b/src/core/textrenderer/qgstextmasksettings.h index e2552d5d737d..9ca63a0f74b9 100644 --- a/src/core/textrenderer/qgstextmasksettings.h +++ b/src/core/textrenderer/qgstextmasksettings.h @@ -66,6 +66,9 @@ class CORE_EXPORT QgsTextMaskSettings ~QgsTextMaskSettings(); + bool operator==( const QgsTextMaskSettings &other ) const; + bool operator!=( const QgsTextMaskSettings &other ) const; + /** * Returns whether the mask is enabled. */ diff --git a/src/core/textrenderer/qgstextrenderer.cpp b/src/core/textrenderer/qgstextrenderer.cpp index dfe10035c4a0..80a7cbf163c5 100644 --- a/src/core/textrenderer/qgstextrenderer.cpp +++ b/src/core/textrenderer/qgstextrenderer.cpp @@ -37,12 +37,42 @@ static void _fixQPictureDPI( QPainter *p ) static_cast< double >( qt_defaultDpiY() ) / p->device()->logicalDpiY() ); } +QgsTextRenderer::HAlignment QgsTextRenderer::convertQtHAlignment( Qt::Alignment alignment ) +{ + if ( alignment & Qt::AlignLeft ) + return AlignLeft; + else if ( alignment & Qt::AlignRight ) + return AlignRight; + else if ( alignment & Qt::AlignHCenter ) + return AlignCenter; + else if ( alignment & Qt::AlignJustify ) + return AlignJustify; + + // not supported? + return AlignLeft; +} + +QgsTextRenderer::VAlignment QgsTextRenderer::convertQtVAlignment( Qt::Alignment alignment ) +{ + if ( alignment & Qt::AlignTop ) + return AlignTop; + else if ( alignment & Qt::AlignBottom ) + return AlignBottom; + else if ( alignment & Qt::AlignVCenter ) + return AlignVCenter; + //not supported + else if ( alignment & Qt::AlignBaseline ) + return AlignBottom; + + return AlignTop; +} + int QgsTextRenderer::sizeToPixel( double size, const QgsRenderContext &c, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &mapUnitScale ) { return static_cast< int >( c.convertToPainterUnits( size, unit, mapUnitScale ) + 0.5 ); //NOLINT } -void QgsTextRenderer::drawText( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool ) +void QgsTextRenderer::drawText( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool, VAlignment vAlignment ) { QgsTextFormat tmpFormat = format; if ( format.dataDefinedProperties().hasActiveProperties() ) // note, we use format instead of tmpFormat here, it's const and potentially avoids a detach @@ -53,15 +83,15 @@ void QgsTextRenderer::drawText( const QRectF &rect, double rotation, QgsTextRend if ( tmpFormat.background().enabled() ) { - drawPart( rect, rotation, alignment, document, context, tmpFormat, Background ); + drawPart( rect, rotation, alignment, vAlignment, document, context, tmpFormat, Background ); } if ( tmpFormat.buffer().enabled() ) { - drawPart( rect, rotation, alignment, document, context, tmpFormat, Buffer ); + drawPart( rect, rotation, alignment, vAlignment, document, context, tmpFormat, Buffer ); } - drawPart( rect, rotation, alignment, document, context, tmpFormat, Text ); + drawPart( rect, rotation, alignment, vAlignment, document, context, tmpFormat, Text ); } void QgsTextRenderer::drawText( QPointF point, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool ) @@ -112,10 +142,10 @@ void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, HAlignment { const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines ); - drawPart( rect, rotation, alignment, document, context, format, part ); + drawPart( rect, rotation, alignment, AlignTop, document, context, format, part ); } -void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, const QgsTextDocument &document, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part ) +void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, VAlignment vAlignment, const QgsTextDocument &document, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part ) { if ( !context.painter() ) { @@ -168,11 +198,10 @@ void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, QgsTextRend case Text: case Shadow: { - QFontMetricsF fm( format.scaledFont( context ) ); drawTextInternal( part, context, format, component, document, - &fm, - alignment ); + nullptr, + alignment, vAlignment ); break; } } @@ -217,20 +246,19 @@ void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer case Text: case Shadow: { - QFontMetricsF fm( format.scaledFont( context ) ); drawTextInternal( part, context, format, component, document, - &fm, - alignment, + nullptr, + alignment, AlignTop, Point ); break; } } } -QFontMetricsF QgsTextRenderer::fontMetrics( QgsRenderContext &context, const QgsTextFormat &format ) +QFontMetricsF QgsTextRenderer::fontMetrics( QgsRenderContext &context, const QgsTextFormat &format, const double scaleFactor ) { - return QFontMetricsF( format.scaledFont( context ), context.painter() ? context.painter()->device() : nullptr ); + return QFontMetricsF( format.scaledFont( context, scaleFactor ), context.painter() ? context.painter()->device() : nullptr ); } double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRenderer::Component &component, const QgsTextFormat &format ) @@ -256,9 +284,10 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend QgsTextBufferSettings buffer = format.buffer(); - double penSize = context.convertToPainterUnits( buffer.size(), buffer.sizeUnit(), buffer.sizeMapUnitScale() ); + const double penSize = context.convertToPainterUnits( buffer.size(), buffer.sizeUnit(), buffer.sizeMapUnitScale() ); - const QFont font = format.scaledFont( context ); + const double scaleFactor = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1.0; + const QFont font = format.scaledFont( context, scaleFactor ); QPainterPath path; path.setFillRule( Qt::WindingFill ); @@ -271,11 +300,14 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend for ( const QgsTextFragment &fragment : component.block ) { QFont fragmentFont = font; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, scaleFactor ); + + if ( component.extraWordSpacing || component.extraLetterSpacing ) + applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing ); path.addText( xOffset, 0, fragmentFont, fragment.text() ); - xOffset += fragment.horizontalAdvance( fragmentFont, true ); + xOffset += fragment.horizontalAdvance( fragmentFont, true, scaleFactor ); } advance = xOffset; break; @@ -285,11 +317,11 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend case QgsTextFormat::RotationBasedOrientation: { double letterSpacing = font.letterSpacing(); - double partYOffset = component.offset.y(); + double partYOffset = component.offset.y() * scaleFactor; for ( const QgsTextFragment &fragment : component.block ) { QFont fragmentFont = font; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, scaleFactor ); QFontMetricsF fragmentMetrics( fragmentFont ); const double labelWidth = fragmentMetrics.maxWidth(); @@ -302,7 +334,7 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend partYOffset += fragmentMetrics.ascent() + letterSpacing; } } - advance = partYOffset - component.offset.y(); + advance = partYOffset - component.offset.y() * scaleFactor; break; } } @@ -310,7 +342,7 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend QColor bufferColor = buffer.color(); bufferColor.setAlphaF( buffer.opacity() ); QPen pen( bufferColor ); - pen.setWidthF( penSize ); + pen.setWidthF( penSize * scaleFactor ); pen.setJoinStyle( buffer.joinStyle() ); QColor tmpColor( bufferColor ); // honor pref for whether to fill buffer interior @@ -323,7 +355,6 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend QPicture buffPict; QPainter buffp; buffp.begin( &buffPict ); - if ( buffer.paintEffect() && buffer.paintEffect()->enabled() ) { context.setPainter( &buffp ); @@ -331,13 +362,19 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend buffer.paintEffect()->begin( context ); context.painter()->setPen( pen ); context.painter()->setBrush( tmpColor ); + if ( scaleFactor != 1.0 ) + context.painter()->scale( 1 / scaleFactor, 1 / scaleFactor ); context.painter()->drawPath( path ); + if ( scaleFactor != 1.0 ) + context.painter()->scale( scaleFactor, scaleFactor ); buffer.paintEffect()->end( context ); context.setPainter( p ); } else { + if ( scaleFactor != 1.0 ) + buffp.scale( 1 / scaleFactor, 1 / scaleFactor ); buffp.setPen( pen ); buffp.setBrush( tmpColor ); buffp.drawPath( path ); @@ -371,7 +408,7 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend _fixQPictureDPI( p ); p->drawPicture( 0, 0, buffPict ); - return advance; + return advance / scaleFactor; } void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer::Component &component, const QgsTextFormat &format ) @@ -390,15 +427,17 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer QPainterPath path; path.setFillRule( Qt::WindingFill ); + const double scaleFactor = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1.0; + // TODO: vertical text mode was ignored when masking feature was added. // Hopefully Oslandia come back and fix this? Hint hint... - const QFont font = format.scaledFont( context ); + const QFont font = format.scaledFont( context, scaleFactor ); double xOffset = 0; for ( const QgsTextFragment &fragment : component.block ) { QFont fragmentFont = font; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, scaleFactor ); path.addText( xOffset, 0, fragmentFont, fragment.text() ); @@ -412,7 +451,7 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer QBrush brush; brush.setColor( bufferColor ); pen.setColor( bufferColor ); - pen.setWidthF( penSize ); + pen.setWidthF( penSize * scaleFactor ); pen.setJoinStyle( mask.joinStyle() ); QgsScopedQPainterState painterState( p ); @@ -425,16 +464,25 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer QgsPainterSwapper swapper( context, p ); { QgsEffectPainter effectPainter( context, mask.paintEffect() ); + if ( scaleFactor != 1.0 ) + context.painter()->scale( 1 / scaleFactor, 1 / scaleFactor ); context.painter()->setPen( pen ); context.painter()->setBrush( brush ); context.painter()->drawPath( path ); + if ( scaleFactor != 1.0 ) + context.painter()->scale( scaleFactor, scaleFactor ); } } else { + if ( scaleFactor != 1.0 ) + p->scale( 1 / scaleFactor, 1 / scaleFactor ); p->setPen( pen ); p->setBrush( brush ); p->drawPath( path ); + if ( scaleFactor != 1.0 ) + p->scale( scaleFactor, scaleFactor ); + } } @@ -453,7 +501,8 @@ double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTex double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTextFormat &format, const QgsTextDocument &document ) { //calculate max width of text lines - const QFont baseFont = format.scaledFont( context ); + const double scaleFactor = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1.0; + const QFont baseFont = format.scaledFont( context, scaleFactor ); double width = 0; switch ( format.orientation() ) @@ -466,7 +515,7 @@ double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTex double blockWidth = 0; for ( const QgsTextFragment &fragment : block ) { - blockWidth += fragment.horizontalAdvance( baseFont ); + blockWidth += fragment.horizontalAdvance( baseFont, scaleFactor ); } maxLineWidth = std::max( maxLineWidth, blockWidth ); } @@ -484,7 +533,7 @@ double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTex for ( const QgsTextFragment &fragment : block ) { QFont fragmentFont = baseFont; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, scaleFactor ); blockWidth = std::max( QFontMetricsF( fragmentFont ).maxWidth(), blockWidth ); } @@ -502,7 +551,7 @@ double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTex } } - return width; + return width / scaleFactor; } double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode, QFontMetricsF * ) @@ -517,11 +566,45 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe } } +double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTextFormat &format, QChar character, bool includeEffects ) +{ + const double scaleFactor = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1.0; + const QFont baseFont = format.scaledFont( context, scaleFactor ); + const QFontMetrics fm( baseFont ); + const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor; + + if ( !includeEffects ) + return height; + + double maxExtension = 0; + if ( format.buffer().enabled() ) + { + maxExtension += context.convertToPainterUnits( format.buffer().size(), format.buffer().sizeUnit(), format.buffer().sizeMapUnitScale() ); + } + if ( format.shadow().enabled() ) + { + maxExtension += context.convertToPainterUnits( format.shadow().offsetDistance(), format.shadow().offsetUnit(), format.shadow().offsetMapUnitScale() ) + + context.convertToPainterUnits( format.shadow().blurRadius(), format.shadow().blurRadiusUnit(), format.shadow().blurRadiusMapUnitScale() ); + } + if ( format.background().enabled() ) + { + maxExtension += context.convertToPainterUnits( std::fabs( format.background().offset().y() ), format.background().offsetUnit(), format.background().offsetMapUnitScale() ) + + context.convertToPainterUnits( format.background().strokeWidth(), format.background().strokeWidthUnit(), format.background().strokeWidthMapUnitScale() ) / 2.0; + if ( format.background().sizeType() == QgsTextBackgroundSettings::SizeBuffer && format.background().size().height() > 0 ) + { + maxExtension += context.convertToPainterUnits( format.background().size().height(), format.background().sizeUnit(), format.background().sizeMapUnitScale() ); + } + } + + return height + maxExtension; +} + double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTextFormat &format, const QgsTextDocument &document, DrawMode mode ) { //calculate max height of text lines + const double scaleFactor = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1.0; - const QFont baseFont = format.scaledFont( context ); + const QFont baseFont = format.scaledFont( context, scaleFactor ); switch ( format.orientation() ) { @@ -529,20 +612,26 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe { int blockIndex = 0; double totalHeight = 0; + double lastLineLeading = 0; for ( const QgsTextBlock &block : document ) { double maxBlockHeight = 0; double maxBlockLineSpacing = 0; + double maxBlockLeading = 0; for ( const QgsTextFragment &fragment : block ) { QFont fragmentFont = baseFont; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, scaleFactor ); const QFontMetricsF fm( fragmentFont ); const double fragmentHeight = fm.ascent() + fm.descent(); // ignore +1 for baseline maxBlockHeight = std::max( maxBlockHeight, fragmentHeight ); - maxBlockLineSpacing = std::max( maxBlockLineSpacing, fm.lineSpacing() ); + if ( fm.lineSpacing() > maxBlockLineSpacing ) + { + maxBlockLineSpacing = fm.lineSpacing(); + maxBlockLeading = fm.leading(); + } } switch ( mode ) @@ -558,13 +647,15 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe case Point: // standard rendering - designed to exactly replicate QPainter's drawText method totalHeight += blockIndex == 0 ? maxBlockHeight : maxBlockLineSpacing * format.lineHeight(); + if ( blockIndex > 0 ) + lastLineLeading = maxBlockLeading; break; } blockIndex++; } - return totalHeight; + return ( totalHeight - lastLineLeading ) / scaleFactor; } case QgsTextFormat::VerticalOrientation: @@ -577,7 +668,7 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe for ( const QgsTextFragment &fragment : block ) { QFont fragmentFont = baseFont; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, scaleFactor ); const QFontMetricsF fm( fragmentFont ); const double labelHeight = fm.ascent(); @@ -590,7 +681,7 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe maxBlockHeight = std::max( maxBlockHeight, blockHeight ); } - return maxBlockHeight; + return maxBlockHeight / scaleFactor; } case QgsTextFormat::RotationBasedOrientation: @@ -632,10 +723,12 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer component.rotationOffset = background.rotation(); } + const double scaleFactor = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1; + if ( mode != Label ) { // need to calculate size of text - QFontMetricsF fm( format.scaledFont( context ) ); + QFontMetricsF fm( format.scaledFont( context, scaleFactor ) ); double width = textWidth( context, format, document ); double height = textHeight( context, format, document, mode ); @@ -645,6 +738,7 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer switch ( component.hAlign ) { case AlignLeft: + case AlignJustify: component.center = QPointF( component.origin.x() + width / 2.0, component.origin.y() + height / 2.0 ); break; @@ -663,10 +757,11 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer case Point: { - double originAdjust = fm.ascent() / 2.0 - fm.leading() / 2.0; + double originAdjust = fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0; switch ( component.hAlign ) { case AlignLeft: + case AlignJustify: component.center = QPointF( component.origin.x() + width / 2.0, component.origin.y() - height / 2.0 + originAdjust ); break; @@ -1121,487 +1216,635 @@ void QgsTextRenderer::drawShadow( QgsRenderContext &context, const QgsTextRender #endif } + void QgsTextRenderer::drawTextInternal( TextPart drawType, QgsRenderContext &context, const QgsTextFormat &format, const Component &component, const QgsTextDocument &document, const QFontMetricsF *fontMetrics, - HAlignment alignment, DrawMode mode ) + HAlignment alignment, VAlignment vAlignment, DrawMode mode ) { if ( !context.painter() ) { return; } - QPainter *maskPainter = context.maskPainter( context.currentMaskId() ); + double fontScale = 1.0; + std::unique_ptr< QFontMetricsF > tmpMetrics; + if ( !fontMetrics ) + { + fontScale = ( context.flags() & QgsRenderContext::ApplyScalingWorkaroundForTextRendering ) ? FONT_WORKAROUND_SCALE : 1.0; + const QFont f = format.scaledFont( context, fontScale ); + tmpMetrics = qgis::make_unique< QFontMetricsF >( f ); + fontMetrics = tmpMetrics.get(); + } - QgsTextFormat::TextOrientation orientation = format.orientation(); - double rotation = -component.rotation * 180 / M_PI; - if ( format.orientation() == QgsTextFormat::RotationBasedOrientation ) + double rotation = 0; + const QgsTextFormat::TextOrientation orientation = calculateRotationAndOrientationForComponent( format, component, rotation ); + switch ( orientation ) { - // Between 45 to 135 and 235 to 315 degrees, rely on vertical orientation - if ( rotation >= -315 && rotation < -90 ) - { - rotation -= 90; - orientation = QgsTextFormat::VerticalOrientation; - } - else if ( rotation >= -90 && rotation < -45 ) + case QgsTextFormat::HorizontalOrientation: { - rotation += 90; - orientation = QgsTextFormat::VerticalOrientation; + drawTextInternalHorizontal( context, format, drawType, mode, component, document, fontScale, fontMetrics, alignment, vAlignment, rotation ); + break; } - else + + case QgsTextFormat::VerticalOrientation: + case QgsTextFormat::RotationBasedOrientation: { - orientation = QgsTextFormat::HorizontalOrientation; + drawTextInternalVertical( context, format, drawType, mode, component, document, fontScale, fontMetrics, alignment, vAlignment, rotation ); + break; } } +} - const QStringList textLines = document.toPlainText(); +QgsTextFormat::TextOrientation QgsTextRenderer::calculateRotationAndOrientationForComponent( const QgsTextFormat &format, const QgsTextRenderer::Component &component, double &rotation ) +{ + rotation = -component.rotation * 180 / M_PI; - switch ( orientation ) + switch ( format.orientation() ) { - case QgsTextFormat::HorizontalOrientation: + case QgsTextFormat::RotationBasedOrientation: { - double labelWidest = 0.0; - switch ( mode ) + // Between 45 to 135 and 235 to 315 degrees, rely on vertical orientation + if ( rotation >= -315 && rotation < -90 ) { - case Label: - case Point: - for ( const QString &line : textLines ) - { - double labelWidth = fontMetrics->width( line ); - if ( labelWidth > labelWidest ) - { - labelWidest = labelWidth; - } - } - break; - - case Rect: - labelWidest = component.size.width(); - break; + rotation -= 90; + return QgsTextFormat::VerticalOrientation; + } + else if ( rotation >= -90 && rotation < -45 ) + { + rotation += 90; + return QgsTextFormat::VerticalOrientation; } - double labelHeight = fontMetrics->ascent() + fontMetrics->descent(); // ignore +1 for baseline - // double labelHighest = labelfm->height() + ( double )(( lines - 1 ) * labelHeight * tmpLyr.multilineHeight ); + return QgsTextFormat::HorizontalOrientation; + } - // needed to move bottom of text's descender to within bottom edge of label - double ascentOffset = 0.25 * fontMetrics->ascent(); // labelfm->descent() is not enough + case QgsTextFormat::HorizontalOrientation: + case QgsTextFormat::VerticalOrientation: + return format.orientation(); + } + return QgsTextFormat::HorizontalOrientation; +} - int i = 0; +void QgsTextRenderer::calculateExtraSpacingForLineJustification( const double spaceToDistribute, const QgsTextBlock &block, double &extraWordSpace, double &extraLetterSpace ) +{ + const QString blockText = block.toPlainText(); + QTextBoundaryFinder finder( QTextBoundaryFinder::Word, blockText ); + finder.toStart(); + int wordBoundaries = 0; + while ( finder.toNextBoundary() != -1 ) + { + if ( finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem ) + wordBoundaries++; + } - bool adjustForAlignment = alignment != AlignLeft && ( mode != Label || textLines.size() > 1 ); + if ( wordBoundaries > 0 ) + { + // word boundaries found => justify by padding word spacing + extraWordSpace = spaceToDistribute / wordBoundaries; + } + else + { + // no word boundaries found => justify by letter spacing + QTextBoundaryFinder finder( QTextBoundaryFinder::Grapheme, blockText ); + finder.toStart(); - for ( const QString &line : qgis::as_const( textLines ) ) - { - const QgsTextBlock block = document.at( i ); + int graphemeBoundaries = 0; + while ( finder.toNextBoundary() != -1 ) + { + if ( finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem ) + graphemeBoundaries++; + } - QgsScopedQPainterState painterState( context.painter() ); - context.setPainterFlagsUsingContext(); - context.painter()->translate( component.origin ); - if ( !qgsDoubleNear( rotation, 0.0 ) ) - context.painter()->rotate( rotation ); + if ( graphemeBoundaries > 0 ) + { + extraLetterSpace = spaceToDistribute / graphemeBoundaries; + } + } +} + +void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font, double extraWordSpace, double extraLetterSpace ) +{ + const double prevWordSpace = font.wordSpacing(); + font.setWordSpacing( prevWordSpace + extraWordSpace ); + const double prevLetterSpace = font.letterSpacing(); + font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace ); +} - // apply to the mask painter the same transformations - if ( maskPainter ) +void QgsTextRenderer::drawTextInternalHorizontal( QgsRenderContext &context, const QgsTextFormat &format, TextPart drawType, DrawMode mode, const Component &component, const QgsTextDocument &document, double fontScale, const QFontMetricsF *fontMetrics, HAlignment hAlignment, + VAlignment vAlignment, double rotation ) +{ + QPainter *maskPainter = context.maskPainter( context.currentMaskId() ); + const QStringList textLines = document.toPlainText(); + + double labelWidest = 0.0; + switch ( mode ) + { + case Label: + case Point: + for ( const QString &line : textLines ) + { + double labelWidth = fontMetrics->width( line ) / fontScale; + if ( labelWidth > labelWidest ) { - maskPainter->save(); - maskPainter->translate( component.origin ); - if ( !qgsDoubleNear( rotation, 0.0 ) ) - maskPainter->rotate( rotation ); + labelWidest = labelWidth; } + } + break; - // figure x offset for horizontal alignment of multiple lines - double xMultiLineOffset = 0.0; - double labelWidth = fontMetrics->width( line ); - if ( adjustForAlignment ) - { - double labelWidthDiff = labelWidest - labelWidth; - if ( alignment == AlignCenter ) + case Rect: + labelWidest = component.size.width(); + break; + } + + double labelHeight = ( fontMetrics->ascent() + fontMetrics->descent() ) / fontScale; // ignore +1 for baseline + // double labelHighest = labelfm->height() + ( double )(( lines - 1 ) * labelHeight * tmpLyr.multilineHeight ); + + // needed to move bottom of text's descender to within bottom edge of label + double ascentOffset = 0.25 * fontMetrics->ascent() / fontScale; // labelfm->descent() is not enough + + int i = 0; + + bool adjustForAlignment = hAlignment != AlignLeft && ( mode != Label || textLines.size() > 1 ); + + if ( mode == Rect && vAlignment != AlignTop ) + { + // need to calculate overall text height in advance so that we can adjust for vertical alignment + const double overallHeight = textHeight( context, format, textLines, Rect ); + switch ( vAlignment ) + { + case AlignTop: + break; + + case AlignVCenter: + ascentOffset = -( component.size.height() - overallHeight ) * 0.5 + ascentOffset; + break; + + case AlignBottom: + ascentOffset = -( component.size.height() - overallHeight ) + ascentOffset; + break; + } + } + + for ( const QString &line : qgis::as_const( textLines ) ) + { + const QgsTextBlock block = document.at( i ); + + const bool isFinalLine = i == document.size() - 1; + + QgsScopedQPainterState painterState( context.painter() ); + context.setPainterFlagsUsingContext(); + context.painter()->translate( component.origin ); + if ( !qgsDoubleNear( rotation, 0.0 ) ) + context.painter()->rotate( rotation ); + + // apply to the mask painter the same transformations + if ( maskPainter ) + { + maskPainter->save(); + maskPainter->translate( component.origin ); + if ( !qgsDoubleNear( rotation, 0.0 ) ) + maskPainter->rotate( rotation ); + } + + // figure x offset for horizontal alignment of multiple lines + double xMultiLineOffset = 0.0; + double labelWidth = fontMetrics->width( line ) / fontScale; + double extraWordSpace = 0; + double extraLetterSpace = 0; + if ( adjustForAlignment ) + { + double labelWidthDiff = 0; + switch ( hAlignment ) + { + case AlignCenter: + labelWidthDiff = ( labelWidest - labelWidth ) * 0.5; + break; + + case AlignRight: + labelWidthDiff = labelWidest - labelWidth; + break; + + case AlignJustify: + if ( !isFinalLine && labelWidest > labelWidth ) { - labelWidthDiff /= 2; + calculateExtraSpacingForLineJustification( labelWidest - labelWidth, block, extraWordSpace, extraLetterSpace ); } - switch ( mode ) + break; + + case AlignLeft: + break; + } + + switch ( mode ) + { + case Label: + case Rect: + xMultiLineOffset = labelWidthDiff; + break; + + case Point: + { + switch ( hAlignment ) { - case Label: - case Rect: - xMultiLineOffset = labelWidthDiff; + case AlignRight: + xMultiLineOffset = labelWidthDiff - labelWidest; break; - case Point: - if ( alignment == AlignRight ) - xMultiLineOffset = labelWidthDiff - labelWidest; - else if ( alignment == AlignCenter ) - xMultiLineOffset = labelWidthDiff - labelWidest / 2.0; + case AlignCenter: + xMultiLineOffset = labelWidthDiff - labelWidest / 2.0; + break; + case AlignLeft: + case AlignJustify: break; } - //QgsDebugMsgLevel( QStringLiteral( "xMultiLineOffset: %1" ).arg( xMultiLineOffset ), 4 ); } + break; + } + } - double yMultiLineOffset = ascentOffset; - switch ( mode ) - { - case Label: - // rendering labels needs special handling - in this case text should be - // drawn with the bottom left corner coinciding with origin, vs top left - // for standard text rendering. Line height is also slightly different. - yMultiLineOffset = - ascentOffset - ( textLines.size() - 1 - i ) * labelHeight * format.lineHeight(); - break; + double yMultiLineOffset = ascentOffset; + switch ( mode ) + { + case Label: + // rendering labels needs special handling - in this case text should be + // drawn with the bottom left corner coinciding with origin, vs top left + // for standard text rendering. Line height is also slightly different. + yMultiLineOffset = - ascentOffset - ( textLines.size() - 1 - i ) * labelHeight * format.lineHeight(); + break; - case Rect: - // standard rendering - designed to exactly replicate QPainter's drawText method - yMultiLineOffset = - ascentOffset + labelHeight - 1 /*baseline*/ + format.lineHeight() * fontMetrics->lineSpacing() * i; - break; + case Rect: + // standard rendering - designed to exactly replicate QPainter's drawText method + yMultiLineOffset = - ascentOffset + labelHeight - 1 /*baseline*/ + format.lineHeight() * fontMetrics->lineSpacing() * i / fontScale; + break; - case Point: - // standard rendering - designed to exactly replicate QPainter's drawText rect method - yMultiLineOffset = 0 - ( textLines.size() - 1 - i ) * fontMetrics->lineSpacing() * format.lineHeight(); - break; + case Point: + // standard rendering - designed to exactly replicate QPainter's drawText rect method + yMultiLineOffset = 0 - ( textLines.size() - 1 - i ) * fontMetrics->lineSpacing() * format.lineHeight() / fontScale; + break; - } + } - context.painter()->translate( QPointF( xMultiLineOffset, yMultiLineOffset ) ); - if ( maskPainter ) - maskPainter->translate( QPointF( xMultiLineOffset, yMultiLineOffset ) ); + context.painter()->translate( QPointF( xMultiLineOffset, yMultiLineOffset ) ); + if ( maskPainter ) + maskPainter->translate( QPointF( xMultiLineOffset, yMultiLineOffset ) ); + + Component subComponent; + subComponent.block = block; + subComponent.size = QSizeF( labelWidth, labelHeight ); + subComponent.offset = QPointF( 0.0, -ascentOffset ); + subComponent.rotation = -component.rotation * 180 / M_PI; + subComponent.rotationOffset = 0.0; + subComponent.extraWordSpacing = extraWordSpace * fontScale; + subComponent.extraLetterSpacing = extraLetterSpace * fontScale; + + // draw the mask below the text (for preview) + if ( format.mask().enabled() ) + { + QgsTextRenderer::drawMask( context, subComponent, format ); + } - Component subComponent; - subComponent.block = block; - subComponent.size = QSizeF( labelWidth, labelHeight ); - subComponent.offset = QPointF( 0.0, -ascentOffset ); - subComponent.rotation = -component.rotation * 180 / M_PI; - subComponent.rotationOffset = 0.0; + if ( drawType == QgsTextRenderer::Buffer ) + { + QgsTextRenderer::drawBuffer( context, subComponent, format ); + } + else + { + // store text's drawing in QPicture for drop shadow call + QPicture textPict; + QPainter textp; + textp.begin( &textPict ); + textp.setPen( Qt::NoPen ); + const QFont font = format.scaledFont( context, fontScale ); + textp.scale( 1 / fontScale, 1 / fontScale ); - // draw the mask below the text (for preview) - if ( format.mask().enabled() ) - { - QgsTextRenderer::drawMask( context, subComponent, format ); - } + double xOffset = 0; + for ( const QgsTextFragment &fragment : block ) + { + // draw text, QPainterPath method + QPainterPath path; + path.setFillRule( Qt::WindingFill ); + + QFont fragmentFont = font; + fragment.characterFormat().updateFontForFormat( fragmentFont, fontScale ); + + if ( extraWordSpace || extraLetterSpace ) + applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale ); + + path.addText( xOffset, 0, fragmentFont, fragment.text() ); + + QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color(); + textColor.setAlphaF( format.opacity() ); + textp.setBrush( textColor ); + textp.drawPath( path ); + + xOffset += fragment.horizontalAdvance( fragmentFont, true ); + } + textp.end(); + + if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowText ) + { + subComponent.picture = textPict; + subComponent.pictureBuffer = 0.0; // no pen width to deal with + subComponent.origin = QPointF( 0.0, 0.0 ); + + QgsTextRenderer::drawShadow( context, subComponent, format ); + } + + // paint the text + if ( context.useAdvancedEffects() ) + { + context.painter()->setCompositionMode( format.blendMode() ); + } + + // scale for any print output or image saving @ specific dpi + context.painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio ); - if ( drawType == QgsTextRenderer::Buffer ) + switch ( context.textRenderFormat() ) + { + case QgsRenderContext::TextFormatAlwaysOutlines: { - QgsTextRenderer::drawBuffer( context, subComponent, format ); + // draw outlined text + _fixQPictureDPI( context.painter() ); + context.painter()->drawPicture( 0, 0, textPict ); + break; } - else - { - // store text's drawing in QPicture for drop shadow call - QPicture textPict; - QPainter textp; - textp.begin( &textPict ); - textp.setPen( Qt::NoPen ); - const QFont font = format.scaledFont( context ); + case QgsRenderContext::TextFormatAlwaysText: + { double xOffset = 0; for ( const QgsTextFragment &fragment : block ) { - // draw text, QPainterPath method - QPainterPath path; - path.setFillRule( Qt::WindingFill ); - QFont fragmentFont = font; - fragment.characterFormat().updateFontForFormat( fragmentFont ); - QFontMetricsF fragmentMetrics = QFontMetricsF( fragmentFont ); + fragment.characterFormat().updateFontForFormat( fragmentFont, fontScale ); - path.addText( xOffset, 0, fragmentFont, fragment.text() ); + if ( extraWordSpace || extraLetterSpace ) + applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale ); QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color(); textColor.setAlphaF( format.opacity() ); - textp.setBrush( textColor ); - textp.drawPath( path ); - xOffset += fragment.horizontalAdvance( fragmentFont, true ); + context.painter()->setPen( textColor ); + context.painter()->setFont( fragmentFont ); + context.painter()->setRenderHint( QPainter::TextAntialiasing ); + + context.painter()->scale( 1 / fontScale, 1 / fontScale ); + context.painter()->drawText( xOffset, 0, fragment.text() ); + context.painter()->scale( fontScale, fontScale ); - // TODO: why are some font settings lost on drawPicture() when using drawText() inside QPicture? - // e.g. some capitalization options, but not others - //textp.setFont( tmpLyr.textFont ); - //textp.setPen( tmpLyr.textColor ); - //textp.drawText( 0, 0, component.text() ); + xOffset += fragment.horizontalAdvance( fragmentFont, true, fontScale ); } - textp.end(); + } + } + } + if ( maskPainter ) + maskPainter->restore(); + i++; + } +} - if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowText ) - { - subComponent.picture = textPict; - subComponent.pictureBuffer = 0.0; // no pen width to deal with - subComponent.origin = QPointF( 0.0, 0.0 ); +void QgsTextRenderer::drawTextInternalVertical( QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart drawType, QgsTextRenderer::DrawMode mode, const QgsTextRenderer::Component &component, const QgsTextDocument &document, double fontScale, const QFontMetricsF *fontMetrics, QgsTextRenderer::HAlignment hAlignment, QgsTextRenderer::VAlignment, double rotation ) +{ + QPainter *maskPainter = context.maskPainter( context.currentMaskId() ); + const QStringList textLines = document.toPlainText(); - QgsTextRenderer::drawShadow( context, subComponent, format ); - } + const QFont font = format.scaledFont( context, fontScale ); + double letterSpacing = font.letterSpacing() / fontScale; - // paint the text - if ( context.useAdvancedEffects() ) - { - context.painter()->setCompositionMode( format.blendMode() ); - } + double labelWidth = fontMetrics->maxWidth() / fontScale; // label width represents the width of one line of a multi-line label + double actualLabelWidest = labelWidth + ( textLines.size() - 1 ) * labelWidth * format.lineHeight(); + double labelWidest = 0.0; + switch ( mode ) + { + case Label: + case Point: + labelWidest = actualLabelWidest; + break; - // scale for any print output or image saving @ specific dpi - context.painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio ); + case Rect: + labelWidest = component.size.width(); + break; + } - switch ( context.textRenderFormat() ) - { - case QgsRenderContext::TextFormatAlwaysOutlines: - { - // draw outlined text - _fixQPictureDPI( context.painter() ); - context.painter()->drawPicture( 0, 0, textPict ); - break; - } + int maxLineLength = 0; + for ( const QString &line : qgis::as_const( textLines ) ) + { + maxLineLength = std::max( maxLineLength, line.length() ); + } + double actualLabelHeight = fontMetrics->ascent() / fontScale + ( fontMetrics->ascent() / fontScale + letterSpacing ) * ( maxLineLength - 1 ); + double ascentOffset = fontMetrics->ascent() / fontScale; - case QgsRenderContext::TextFormatAlwaysText: - { - double xOffset = 0; - for ( const QgsTextFragment &fragment : block ) - { - QFont fragmentFont = font; - fragment.characterFormat().updateFontForFormat( fragmentFont ); + int i = 0; - QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color(); - textColor.setAlphaF( format.opacity() ); + bool adjustForAlignment = hAlignment != AlignLeft && ( mode != Label || textLines.size() > 1 ); - context.painter()->setPen( textColor ); - context.painter()->setFont( fragmentFont ); - context.painter()->setRenderHint( QPainter::TextAntialiasing ); + for ( const QgsTextBlock &block : document ) + { + QgsScopedQPainterState painterState( context.painter() ); + context.setPainterFlagsUsingContext(); - context.painter()->drawText( xOffset, 0, fragment.text() ); + context.painter()->translate( component.origin ); + if ( !qgsDoubleNear( rotation, 0.0 ) ) + context.painter()->rotate( rotation ); - xOffset += fragment.horizontalAdvance( fragmentFont, true ); - } - } - } - } - if ( maskPainter ) - maskPainter->restore(); - i++; - } - break; + // apply to the mask painter the same transformations + if ( maskPainter ) + { + maskPainter->save(); + maskPainter->translate( component.origin ); + if ( !qgsDoubleNear( rotation, 0.0 ) ) + maskPainter->rotate( rotation ); } - case QgsTextFormat::VerticalOrientation: - case QgsTextFormat::RotationBasedOrientation: + // figure x offset of multiple lines + double xOffset = actualLabelWidest - labelWidth - ( i * labelWidth * format.lineHeight() ); + if ( adjustForAlignment ) { - const QFont font = format.scaledFont( context ); - double letterSpacing = font.letterSpacing(); - - double labelWidth = fontMetrics->maxWidth(); // label width represents the width of one line of a multi-line label - double actualLabelWidest = labelWidth + ( textLines.size() - 1 ) * labelWidth * format.lineHeight(); - double labelWidest = 0.0; - switch ( mode ) + double labelWidthDiff = 0; + switch ( hAlignment ) { - case Label: - case Point: - labelWidest = actualLabelWidest; + case AlignCenter: + labelWidthDiff = ( labelWidest - actualLabelWidest ) * 0.5; break; - case Rect: - labelWidest = component.size.width(); + case AlignRight: + labelWidthDiff = labelWidest - actualLabelWidest; break; - } - int maxLineLength = 0; - for ( const QString &line : qgis::as_const( textLines ) ) - { - maxLineLength = std::max( maxLineLength, line.length() ); + case AlignLeft: + case AlignJustify: + break; } - double actualLabelHeight = fontMetrics->ascent() + ( fontMetrics->ascent() + letterSpacing ) * ( maxLineLength - 1 ); - double ascentOffset = fontMetrics->ascent(); - - int i = 0; - - bool adjustForAlignment = alignment != AlignLeft && ( mode != Label || textLines.size() > 1 ); - for ( const QgsTextBlock &block : document ) + switch ( mode ) { - QgsScopedQPainterState painterState( context.painter() ); - context.setPainterFlagsUsingContext(); - - context.painter()->translate( component.origin ); - if ( !qgsDoubleNear( rotation, 0.0 ) ) - context.painter()->rotate( rotation ); + case Label: + case Rect: + xOffset += labelWidthDiff; + break; - // apply to the mask painter the same transformations - if ( maskPainter ) - { - maskPainter->save(); - maskPainter->translate( component.origin ); - if ( !qgsDoubleNear( rotation, 0.0 ) ) - maskPainter->rotate( rotation ); - } + case Point: + break; + } + } - // figure x offset of multiple lines - double xOffset = actualLabelWidest - labelWidth - ( i * labelWidth * format.lineHeight() ); - if ( adjustForAlignment ) + double yOffset = 0.0; + switch ( mode ) + { + case Label: + if ( format.orientation() == QgsTextFormat::RotationBasedOrientation ) { - double labelWidthDiff = labelWidest - actualLabelWidest; - if ( alignment == AlignCenter ) + if ( rotation >= -405 && rotation < -180 ) { - labelWidthDiff /= 2; + yOffset = ascentOffset; } - switch ( mode ) + else if ( rotation >= 0 && rotation < 45 ) { - case Label: - case Rect: - xOffset += labelWidthDiff; - break; - - case Point: - break; + xOffset -= actualLabelWidest; + yOffset = -actualLabelHeight + ascentOffset + fontMetrics->descent() / fontScale; } } - - double yOffset = 0.0; - switch ( mode ) + else { - case Label: - if ( format.orientation() == QgsTextFormat::RotationBasedOrientation ) - { - if ( rotation >= -405 && rotation < -180 ) - { - yOffset = ascentOffset; - } - else if ( rotation >= 0 && rotation < 45 ) - { - xOffset -= actualLabelWidest; - yOffset = -actualLabelHeight + ascentOffset + fontMetrics->descent(); - } - } - else - { - yOffset = -actualLabelHeight + ascentOffset; - } - break; + yOffset = -actualLabelHeight + ascentOffset; + } + break; - case Point: - yOffset = -actualLabelHeight + ascentOffset; - break; + case Point: + yOffset = -actualLabelHeight + ascentOffset; + break; - case Rect: - yOffset = ascentOffset; - break; - } + case Rect: + yOffset = ascentOffset; + break; + } - context.painter()->translate( QPointF( xOffset, yOffset ) ); + context.painter()->translate( QPointF( xOffset, yOffset ) ); - double fragmentYOffset = 0; - for ( const QgsTextFragment &fragment : block ) - { - // apply some character replacement to draw symbols in vertical presentation - const QString line = QgsStringUtils::substituteVerticalCharacters( fragment.text() ); + double fragmentYOffset = 0; + for ( const QgsTextFragment &fragment : block ) + { + // apply some character replacement to draw symbols in vertical presentation + const QString line = QgsStringUtils::substituteVerticalCharacters( fragment.text() ); - QFont fragmentFont( font ); - fragment.characterFormat().updateFontForFormat( fragmentFont ); + QFont fragmentFont( font ); + fragment.characterFormat().updateFontForFormat( fragmentFont, fontScale ); - QFontMetricsF fragmentMetrics( fragmentFont ); + QFontMetricsF fragmentMetrics( fragmentFont ); - double labelHeight = fragmentMetrics.ascent() + ( fragmentMetrics.ascent() + letterSpacing ) * ( line.length() - 1 ); + double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 ); - Component subComponent; - subComponent.block = QgsTextBlock( fragment ); - subComponent.size = QSizeF( labelWidth, labelHeight ); - subComponent.offset = QPointF( 0.0, fragmentYOffset ); - subComponent.rotation = -component.rotation * 180 / M_PI; - subComponent.rotationOffset = 0.0; + Component subComponent; + subComponent.block = QgsTextBlock( fragment ); + subComponent.size = QSizeF( labelWidth, labelHeight ); + subComponent.offset = QPointF( 0.0, fragmentYOffset ); + subComponent.rotation = -component.rotation * 180 / M_PI; + subComponent.rotationOffset = 0.0; - // draw the mask below the text (for preview) - if ( format.mask().enabled() ) - { - // WARNING: totally broken! (has been since mask was introduced) + // draw the mask below the text (for preview) + if ( format.mask().enabled() ) + { + // WARNING: totally broken! (has been since mask was introduced) #if 0 - QgsTextRenderer::drawMask( context, subComponent, format ); + QgsTextRenderer::drawMask( context, subComponent, format ); #endif - } + } - if ( drawType == QgsTextRenderer::Buffer ) - { - fragmentYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format ); - } - else - { - // draw text, QPainterPath method - QPainterPath path; - path.setFillRule( Qt::WindingFill ); - const QStringList parts = QgsPalLabeling::splitToGraphemes( fragment.text() ); - double partYOffset = 0.0; - for ( const auto &part : parts ) - { - double partXOffset = ( labelWidth - ( fragmentMetrics.width( part ) - letterSpacing ) ) / 2; - path.addText( partXOffset, partYOffset, fragmentFont, part ); - partYOffset += fragmentMetrics.ascent() + letterSpacing; - } + if ( drawType == QgsTextRenderer::Buffer ) + { + fragmentYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format ); + } + else + { + // draw text, QPainterPath method + QPainterPath path; + path.setFillRule( Qt::WindingFill ); + const QStringList parts = QgsPalLabeling::splitToGraphemes( fragment.text() ); + double partYOffset = 0.0; + for ( const auto &part : parts ) + { + double partXOffset = ( labelWidth - ( fragmentMetrics.width( part ) / fontScale - letterSpacing ) ) / 2; + path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part ); + partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing; + } - // store text's drawing in QPicture for drop shadow call - QPicture textPict; - QPainter textp; - textp.begin( &textPict ); - textp.setPen( Qt::NoPen ); - QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color(); - textColor.setAlphaF( format.opacity() ); - textp.setBrush( textColor ); - textp.drawPath( path ); - // TODO: why are some font settings lost on drawPicture() when using drawText() inside QPicture? - // e.g. some capitalization options, but not others - //textp.setFont( tmpLyr.textFont ); - //textp.setPen( tmpLyr.textColor ); - //textp.drawText( 0, 0, component.text() ); - textp.end(); - - if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowText ) - { - subComponent.picture = textPict; - subComponent.pictureBuffer = 0.0; // no pen width to deal with - subComponent.origin = QPointF( 0.0, fragmentYOffset ); - const double prevY = subComponent.offset.y(); - subComponent.offset = QPointF( 0, -labelHeight ); - subComponent.useOrigin = true; - QgsTextRenderer::drawShadow( context, subComponent, format ); - subComponent.useOrigin = false; - subComponent.offset = QPointF( 0, prevY ); - } + // store text's drawing in QPicture for drop shadow call + QPicture textPict; + QPainter textp; + textp.begin( &textPict ); + textp.setPen( Qt::NoPen ); + QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color(); + textColor.setAlphaF( format.opacity() ); + textp.setBrush( textColor ); + textp.scale( 1 / fontScale, 1 / fontScale ); + textp.drawPath( path ); + // TODO: why are some font settings lost on drawPicture() when using drawText() inside QPicture? + // e.g. some capitalization options, but not others + //textp.setFont( tmpLyr.textFont ); + //textp.setPen( tmpLyr.textColor ); + //textp.drawText( 0, 0, component.text() ); + textp.end(); + + if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowText ) + { + subComponent.picture = textPict; + subComponent.pictureBuffer = 0.0; // no pen width to deal with + subComponent.origin = QPointF( 0.0, fragmentYOffset ); + const double prevY = subComponent.offset.y(); + subComponent.offset = QPointF( 0, -labelHeight ); + subComponent.useOrigin = true; + QgsTextRenderer::drawShadow( context, subComponent, format ); + subComponent.useOrigin = false; + subComponent.offset = QPointF( 0, prevY ); + } - // paint the text - if ( context.useAdvancedEffects() ) - { - context.painter()->setCompositionMode( format.blendMode() ); - } + // paint the text + if ( context.useAdvancedEffects() ) + { + context.painter()->setCompositionMode( format.blendMode() ); + } + + // scale for any print output or image saving @ specific dpi + context.painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio ); - // scale for any print output or image saving @ specific dpi - context.painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio ); + switch ( context.textRenderFormat() ) + { + case QgsRenderContext::TextFormatAlwaysOutlines: + { + // draw outlined text + _fixQPictureDPI( context.painter() ); + context.painter()->drawPicture( 0, fragmentYOffset, textPict ); + fragmentYOffset += partYOffset; + break; + } + + case QgsRenderContext::TextFormatAlwaysText: + { + context.painter()->setFont( fragmentFont ); + context.painter()->setPen( textColor ); + context.painter()->setRenderHint( QPainter::TextAntialiasing ); - switch ( context.textRenderFormat() ) + double partYOffset = 0.0; + for ( const QString &part : parts ) { - case QgsRenderContext::TextFormatAlwaysOutlines: - { - // draw outlined text - _fixQPictureDPI( context.painter() ); - context.painter()->drawPicture( 0, fragmentYOffset, textPict ); - fragmentYOffset += partYOffset; - break; - } - - case QgsRenderContext::TextFormatAlwaysText: - { - context.painter()->setFont( fragmentFont ); - context.painter()->setPen( textColor ); - context.painter()->setRenderHint( QPainter::TextAntialiasing ); - - double partYOffset = 0.0; - for ( const QString &part : parts ) - { - double partXOffset = ( labelWidth - ( fragmentMetrics.width( part ) - letterSpacing ) ) / 2; - context.painter()->drawText( partXOffset, fragmentYOffset + partYOffset, part ); - partYOffset += fragmentMetrics.ascent() + letterSpacing; - } - fragmentYOffset += partYOffset; - } + double partXOffset = ( labelWidth - ( fragmentMetrics.width( part ) / fontScale - letterSpacing ) ) / 2; + context.painter()->scale( 1 / fontScale, 1 / fontScale ); + context.painter()->drawText( partXOffset * fontScale, ( fragmentYOffset + partYOffset ) * fontScale, part ); + context.painter()->scale( fontScale, fontScale ); + partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing; } + fragmentYOffset += partYOffset; } } - - if ( maskPainter ) - maskPainter->restore(); - i++; } - break; } + + if ( maskPainter ) + maskPainter->restore(); + i++; } } diff --git a/src/core/textrenderer/qgstextrenderer.h b/src/core/textrenderer/qgstextrenderer.h index 1f99a5056487..af367c2fb2e7 100644 --- a/src/core/textrenderer/qgstextrenderer.h +++ b/src/core/textrenderer/qgstextrenderer.h @@ -20,10 +20,10 @@ #include "qgis_core.h" #include "qgstextblock.h" #include "qgsrendercontext.h" +#include "qgstextformat.h" #include -class QgsTextFormat; class QgsTextDocument; /** @@ -60,8 +60,36 @@ class CORE_EXPORT QgsTextRenderer AlignLeft = 0, //!< Left align AlignCenter, //!< Center align AlignRight, //!< Right align + AlignJustify, //!< Justify align }; + /** + * Converts a Qt horizontal \a alignment flag to a QgsTextRenderer::HAlignment value. + * + * \see convertQtVAlignment() + * \since QGIS 3.16 + */ + static HAlignment convertQtHAlignment( Qt::Alignment alignment ); + + /** + * Vertical alignment + * \since QGIS 3.16 + */ + enum VAlignment + { + AlignTop = 0, //!< Align to top + AlignVCenter, //!< Center align + AlignBottom, //!< Align to bottom + }; + + /** + * Converts a Qt vertical \a alignment flag to a QgsTextRenderer::VAlignment value. + * + * \see convertQtHAlignment() + * \since QGIS 3.16 + */ + static VAlignment convertQtVAlignment( Qt::Alignment alignment ); + /** * Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling) * \param size size to convert @@ -86,10 +114,11 @@ class CORE_EXPORT QgsTextRenderer * formats like SVG to maintain text as text objects, but at the cost of degraded * rendering and may result in side effects like misaligned text buffers. This setting is deprecated and has no effect * as of QGIS 3.4.3 and the text format should be set using QgsRenderContext::setTextRenderFormat() instead. + * \param vAlignment vertical alignment (since QGIS 3.16) */ static void drawText( const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, - bool drawAsOutlines = true ); + bool drawAsOutlines = true, VAlignment vAlignment = AlignTop ); /** * Draws text at a point origin using the specified settings. @@ -156,9 +185,15 @@ class CORE_EXPORT QgsTextRenderer * Returns the font metrics for the given text \a format, when rendered * in the specified render \a context. The font metrics will take into account * all scaling required by the render context. + * + * The optional \a scaleFactor argument can specify a font size scaling factor. It is recommended to set this to + * QgsTextRenderer::FONT_WORKAROUND_SCALE and then manually scale painter devices or calculations + * based on the resultant font metrics. Failure to do so will result in poor quality text rendering + * at small font sizes. + * * \since QGIS 3.2 */ - static QFontMetricsF fontMetrics( QgsRenderContext &context, const QgsTextFormat &format ); + static QFontMetricsF fontMetrics( QgsRenderContext &context, const QgsTextFormat &format, double scaleFactor = 1.0 ); /** * Returns the width of a text based on a given format. @@ -181,6 +216,29 @@ class CORE_EXPORT QgsTextRenderer static double textHeight( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode = Point, QFontMetricsF *fontMetrics = nullptr ); + /** + * Returns the height of a character when rendered with the specified text \a format. + * + * \param context render context + * \param format text format + * \param character character to determine height of. If \a character is invalid, then the maximum character height will be returned. + * \param includeEffects if TRUE, then the size of formatting effects such as buffers and shadows will be considered in the + * returned height. If FALSE, then the returned size considers the character only. + * + * \since QGIS 3.16 + */ + static double textHeight( const QgsRenderContext &context, const QgsTextFormat &format, QChar character, bool includeEffects = false ); + + /** + * Scale factor for upscaling font sizes and downscaling destination painter devices. + * + * Using this scale factor and manually adjusting any font metric based calculations results in more stable + * font metrics and sizes for small font sizes. + * + * \since QGIS 3.16 + */ + static constexpr double FONT_WORKAROUND_SCALE = 10; + private: struct Component @@ -213,6 +271,11 @@ class CORE_EXPORT QgsTextRenderer double dpiRatio = 1.0; //! Horizontal alignment HAlignment hAlign = AlignLeft; + + //! Any additional word spacing to apply while rendering component + double extraWordSpacing = 0; + //! Any additional letter spacing to apply while rendering component + double extraLetterSpacing = 0; }; static double textWidth( const QgsRenderContext &context, const QgsTextFormat &format, const QgsTextDocument &document ); @@ -223,6 +286,7 @@ class CORE_EXPORT QgsTextRenderer * \param rect destination rectangle for text * \param rotation text rotation * \param alignment horizontal alignment + * \param vAlignment vertical alignment * \param document text document to draw * \param context render context * \param format text format @@ -232,7 +296,7 @@ class CORE_EXPORT QgsTextRenderer * \note Not available in Python bindings * \since QGIS 3.14 */ - static void drawPart( const QRectF &rect, double rotation, HAlignment alignment, const QgsTextDocument &document, + static void drawPart( const QRectF &rect, double rotation, HAlignment alignment, VAlignment vAlignment, const QgsTextDocument &document, QgsRenderContext &context, const QgsTextFormat &format, TextPart part ); @@ -283,14 +347,43 @@ class CORE_EXPORT QgsTextRenderer const QgsTextDocument &document, const QFontMetricsF *fontMetrics, HAlignment alignment, + VAlignment vAlignment, DrawMode mode = Rect ); + static QgsTextFormat::TextOrientation calculateRotationAndOrientationForComponent( const QgsTextFormat &format, const Component &component, double &rotation ); + + static void calculateExtraSpacingForLineJustification( double spaceToDistribute, const QgsTextBlock &block, double &extraWordSpace, double &extraLetterSpace ); + static void applyExtraSpacingForLineJustification( QFont &font, double extraWordSpace, double extraLetterSpace ); + + static void drawTextInternalHorizontal( QgsRenderContext &context, + const QgsTextFormat &format, + TextPart drawType, + DrawMode mode, + const Component &component, + const QgsTextDocument &document, + double fontScale, + const QFontMetricsF *fontMetrics, + HAlignment hAlignment, + VAlignment vAlignment, + double rotation ); + + static void drawTextInternalVertical( QgsRenderContext &context, + const QgsTextFormat &format, + TextPart drawType, + DrawMode mode, + const Component &component, + const QgsTextDocument &document, + double fontScale, + const QFontMetricsF *fontMetrics, + HAlignment hAlignment, + VAlignment vAlignment, + double rotation ); + friend class QgsVectorLayerLabelProvider; friend class QgsLabelPreview; static QgsTextFormat updateShadowPosition( const QgsTextFormat &format ); - }; diff --git a/src/core/textrenderer/qgstextrenderer_p.h b/src/core/textrenderer/qgstextrenderer_p.h index d5392d0fe14d..ac27e39ab002 100644 --- a/src/core/textrenderer/qgstextrenderer_p.h +++ b/src/core/textrenderer/qgstextrenderer_p.h @@ -258,6 +258,7 @@ class QgsTextSettingsPrivate : public QSharedData QgsTextSettingsPrivate( const QgsTextSettingsPrivate &other ) : QSharedData( other ) + , isValid( other.isValid ) , textFont( other.textFont ) , textNamedStyle( other.textNamedStyle ) , fontSizeUnits( other.fontSizeUnits ) @@ -274,6 +275,7 @@ class QgsTextSettingsPrivate : public QSharedData { } + bool isValid = false; QFont textFont; QString textNamedStyle; QgsUnitTypes::RenderUnit fontSizeUnits = QgsUnitTypes::RenderPoints; diff --git a/src/core/textrenderer/qgstextshadowsettings.cpp b/src/core/textrenderer/qgstextshadowsettings.cpp index ece9e91a5368..5235bfe45d2c 100644 --- a/src/core/textrenderer/qgstextshadowsettings.cpp +++ b/src/core/textrenderer/qgstextshadowsettings.cpp @@ -43,6 +43,33 @@ QgsTextShadowSettings::~QgsTextShadowSettings() //NOLINT } +bool QgsTextShadowSettings::operator==( const QgsTextShadowSettings &other ) const +{ + if ( d->enabled != other.enabled() + || d->shadowUnder != other.shadowPlacement() + || d->offsetAngle != other.offsetAngle() + || d->offsetDist != other.offsetDistance() + || d->offsetUnits != other.offsetUnit() + || d->offsetMapUnitScale != other.offsetMapUnitScale() + || d->offsetGlobal != other.offsetGlobal() + || d->radius != other.blurRadius() + || d->radiusUnits != other.blurRadiusUnit() + || d->radiusMapUnitScale != other.blurRadiusMapUnitScale() + || d->radiusAlphaOnly != other.blurAlphaOnly() + || d->scale != other.scale() + || d->color != other.color() + || d->opacity != other.opacity() + || d->blendMode != other.blendMode() ) + return false; + + return true; +} + +bool QgsTextShadowSettings::operator!=( const QgsTextShadowSettings &other ) const +{ + return !( *this == other ); +} + bool QgsTextShadowSettings::enabled() const { return d->enabled; diff --git a/src/core/textrenderer/qgstextshadowsettings.h b/src/core/textrenderer/qgstextshadowsettings.h index 0a0f41e00e8a..fcfcf8d6309f 100644 --- a/src/core/textrenderer/qgstextshadowsettings.h +++ b/src/core/textrenderer/qgstextshadowsettings.h @@ -61,6 +61,9 @@ class CORE_EXPORT QgsTextShadowSettings ~QgsTextShadowSettings(); + bool operator==( const QgsTextShadowSettings &other ) const; + bool operator!=( const QgsTextShadowSettings &other ) const; + /** * Returns whether the shadow is enabled. * \see setEnabled() diff --git a/src/core/vectortile/qgsvectortiledataitems.cpp b/src/core/vectortile/qgsvectortiledataitems.cpp index 41dcc786eb58..4bc453b593bb 100644 --- a/src/core/vectortile/qgsvectortiledataitems.cpp +++ b/src/core/vectortile/qgsvectortiledataitems.cpp @@ -20,7 +20,7 @@ ///@cond PRIVATE QgsVectorTileRootItem::QgsVectorTileRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "vectortile" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "vectortile" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconVectorTileLayer.svg" ); diff --git a/src/core/vectortile/qgsvectortiledataitems.h b/src/core/vectortile/qgsvectortiledataitems.h index 365738e5be1f..35d0cbc9b68d 100644 --- a/src/core/vectortile/qgsvectortiledataitems.h +++ b/src/core/vectortile/qgsvectortiledataitems.h @@ -22,7 +22,7 @@ #define SIP_NO_FILE //! Root item for XYZ tile layers -class CORE_EXPORT QgsVectorTileRootItem : public QgsDataCollectionItem +class CORE_EXPORT QgsVectorTileRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 53c3fbe066ff..4da6c23e17fc 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -393,6 +393,7 @@ SET(QGIS_GUI_SRCS qgsdetaileditemwidget.cpp qgsdial.cpp qgsdialog.cpp + qgsdoublevalidator.cpp qgsdockwidget.cpp qgsencodingfiledialog.cpp qgserrordialog.cpp @@ -492,6 +493,7 @@ SET(QGIS_GUI_SRCS qgsnewnamedialog.cpp qgsnewvectorlayerdialog.cpp qgsnewgeopackagelayerdialog.cpp + qgsnewvectortabledialog.cpp qgsopacitywidget.cpp qgsoptionsdialogbase.cpp qgsoptionsdialoghighlightwidget.cpp @@ -626,6 +628,7 @@ SET(QGIS_GUI_HDRS qgsdial.h qgsdialog.h qgsdockwidget.h + qgsdoublevalidator.h qgsencodingfiledialog.h qgserrordialog.h qgsexpressionbuilderdialog.h @@ -720,10 +723,12 @@ SET(QGIS_GUI_HDRS qgsnewauxiliaryfielddialog.h qgsnewauxiliarylayerdialog.h qgsnewgeopackagelayerdialog.h + qgsnewvectortabledialog.h qgsnewhttpconnection.h qgsnewmemorylayerdialog.h qgsnewnamedialog.h qgsnewvectorlayerdialog.h + qgsnewvectortabledialog.h qgsopacitywidget.h qgsoptionsdialogbase.h qgsoptionsdialoghighlightwidget.h @@ -1194,6 +1199,7 @@ SET(QGIS_GUI_UI_HDRS ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgenericprojectionselectorbase.h ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessagelogviewer.h ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessageviewer.h + ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsnewvectortabledialogbase.h ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsowssourceselectbase.h ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsarcgisservicesourceselectbase.h ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsprojectionselectorbase.h diff --git a/src/gui/attributeformconfig/qgsattributewidgetedit.cpp b/src/gui/attributeformconfig/qgsattributewidgetedit.cpp index 01fc32fd60d2..74932dcb4eec 100644 --- a/src/gui/attributeformconfig/qgsattributewidgetedit.cpp +++ b/src/gui/attributeformconfig/qgsattributewidgetedit.cpp @@ -29,21 +29,18 @@ QgsAttributeWidgetEdit::QgsAttributeWidgetEdit( QTreeWidgetItem *item, QWidget * // common configs mShowLabelCheckBox->setChecked( itemData.showLabel() ); - // hide specific configs - mRelationShowLinkCheckBox->hide(); - mRelationShowUnlinkCheckBox->hide(); - mRelationShowSaveChildEditsCheckBox->hide(); - switch ( itemData.type() ) { case QgsAttributesFormProperties::DnDTreeItemData::Relation: { - mRelationShowLinkCheckBox->show(); - mRelationShowUnlinkCheckBox->show(); - mRelationShowSaveChildEditsCheckBox->show(); - mRelationShowLinkCheckBox->setChecked( itemData.relationEditorConfiguration().showLinkButton ); - mRelationShowUnlinkCheckBox->setChecked( itemData.relationEditorConfiguration().showUnlinkButton ); - mRelationShowSaveChildEditsCheckBox->setChecked( itemData.relationEditorConfiguration().showSaveChildEditsButton ); + showRelationButtons( true ); + mRelationShowLinkCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::Link ) ); + mRelationShowUnlinkCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::Unlink ) ); + mRelationShowAddChildCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::AddChildFeature ) ); + mRelationShowDuplicateChildFeatureCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::DuplicateChildFeature ) ); + mRelationShowZoomToFeatureCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::ZoomToChildFeature ) ); + mRelationDeleteChildFeatureCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::DeleteChildFeature ) ); + mRelationShowSaveChildEditsCheckBox->setChecked( itemData.relationEditorConfiguration().buttons.testFlag( QgsAttributeEditorRelation::Button::SaveChildEdits ) ); } break; @@ -52,6 +49,7 @@ QgsAttributeWidgetEdit::QgsAttributeWidgetEdit( QTreeWidgetItem *item, QWidget * case QgsAttributesFormProperties::DnDTreeItemData::QmlWidget: case QgsAttributesFormProperties::DnDTreeItemData::HtmlWidget: case QgsAttributesFormProperties::DnDTreeItemData::WidgetType: + showRelationButtons( false ); break; } @@ -71,9 +69,15 @@ void QgsAttributeWidgetEdit::updateItemData() case QgsAttributesFormProperties::DnDTreeItemData::Relation: { QgsAttributesFormProperties::RelationEditorConfiguration relEdCfg; - relEdCfg.showLinkButton = mRelationShowLinkCheckBox->isChecked(); - relEdCfg.showUnlinkButton = mRelationShowUnlinkCheckBox->isChecked(); - relEdCfg.showSaveChildEditsButton = mRelationShowSaveChildEditsCheckBox->isChecked(); + QgsAttributeEditorRelation::Buttons buttons; + buttons.setFlag( QgsAttributeEditorRelation::Button::Link, mRelationShowLinkCheckBox->isChecked() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::Unlink, mRelationShowUnlinkCheckBox->isChecked() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::AddChildFeature, mRelationShowAddChildCheckBox->isChecked() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::DuplicateChildFeature, mRelationShowDuplicateChildFeatureCheckBox->isChecked() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::ZoomToChildFeature, mRelationShowZoomToFeatureCheckBox->isChecked() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::DeleteChildFeature, mRelationDeleteChildFeatureCheckBox->isChecked() ); + buttons.setFlag( QgsAttributeEditorRelation::Button::SaveChildEdits, mRelationShowSaveChildEditsCheckBox->isChecked() ); + relEdCfg.buttons = buttons; itemData.setRelationEditorConfiguration( relEdCfg ); } break; @@ -88,3 +92,10 @@ void QgsAttributeWidgetEdit::updateItemData() mTreeItem->setData( 0, QgsAttributesFormProperties::DnDTreeRole, itemData ); } + +void QgsAttributeWidgetEdit::showRelationButtons( bool show ) +{ + const QList buttons = mRelationButtonGroup->buttons(); + for ( QAbstractButton *button : buttons ) + button->setVisible( show ); +} diff --git a/src/gui/attributeformconfig/qgsattributewidgetedit.h b/src/gui/attributeformconfig/qgsattributewidgetedit.h index 56ad496f8aaf..0dbd6693d2a3 100644 --- a/src/gui/attributeformconfig/qgsattributewidgetedit.h +++ b/src/gui/attributeformconfig/qgsattributewidgetedit.h @@ -43,6 +43,8 @@ class GUI_EXPORT QgsAttributeWidgetEdit: public QgsCollapsibleGroupBox, private private: + void showRelationButtons( bool show ); + QTreeWidgetItem *mTreeItem; }; diff --git a/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp b/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp index d2df062ceb61..38a755e64171 100644 --- a/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp +++ b/src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp @@ -207,6 +207,9 @@ void QgsRelationReferenceSearchWidgetWrapper::initWidget( QWidget *editor ) } QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( QStringLiteral( "Relation" ) ).toString() ); + // if no relation is given from the config, fetch one if there is only one available + if ( !relation.isValid() && !layer()->referencingRelations( mFieldIdx ).isEmpty() && layer()->referencingRelations( mFieldIdx ).count() == 1 ) + relation = layer()->referencingRelations( mFieldIdx )[0]; mWidget->setRelation( relation, false ); mWidget->showIndeterminateState(); diff --git a/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp b/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp index 6dd2216d96a1..336887743edc 100644 --- a/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp +++ b/src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp @@ -101,20 +101,25 @@ void QgsRelationWidgetWrapper::widgetValueChanged( const QString &attribute, con bool QgsRelationWidgetWrapper::showUnlinkButton() const { + Q_NOWARN_DEPRECATED_PUSH return mWidget->showUnlinkButton(); + Q_NOWARN_DEPRECATED_POP } void QgsRelationWidgetWrapper::setShowUnlinkButton( bool showUnlinkButton ) { + Q_NOWARN_DEPRECATED_PUSH if ( mWidget ) mWidget->setShowUnlinkButton( showUnlinkButton ); + Q_NOWARN_DEPRECATED_POP } - void QgsRelationWidgetWrapper::setShowSaveChildEditsButton( bool showSaveChildEditsButton ) { + Q_NOWARN_DEPRECATED_PUSH if ( mWidget ) mWidget->setShowSaveChildEditsButton( showSaveChildEditsButton ); + Q_NOWARN_DEPRECATED_POP } bool QgsRelationWidgetWrapper::showLabel() const @@ -154,10 +159,12 @@ void QgsRelationWidgetWrapper::initWidget( QWidget *editor ) const_cast( myContext.vectorLayerTools() )->setForceSuppressFormPopup( true ); } + /* TODO: this seems to have no effect if ( config( QStringLiteral( "hide-save-child-edits" ), false ).toBool() ) { w->setShowSaveChildEditsButton( false ); } + */ w->setEditorContext( myContext ); @@ -189,16 +196,29 @@ bool QgsRelationWidgetWrapper::valid() const bool QgsRelationWidgetWrapper::showLinkButton() const { - return mWidget->showLinkButton(); + return visibleButtons().testFlag( QgsAttributeEditorRelation::Button::Link ); } void QgsRelationWidgetWrapper::setShowLinkButton( bool showLinkButton ) { + Q_NOWARN_DEPRECATED_PUSH if ( mWidget ) mWidget->setShowLinkButton( showLinkButton ); + Q_NOWARN_DEPRECATED_POP } bool QgsRelationWidgetWrapper::showSaveChildEditsButton() const { - return mWidget && mWidget->showSaveChildEditsButton(); + return visibleButtons().testFlag( QgsAttributeEditorRelation::Button::SaveChildEdits ); +} + +void QgsRelationWidgetWrapper::setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ) +{ + if ( mWidget ) + mWidget->setVisibleButtons( buttons ); +} + +QgsAttributeEditorRelation::Buttons QgsRelationWidgetWrapper::visibleButtons() const +{ + return mWidget->visibleButtons(); } diff --git a/src/gui/editorwidgets/qgsrelationwidgetwrapper.h b/src/gui/editorwidgets/qgsrelationwidgetwrapper.h index 43a45da37cc0..3a77ed3adb16 100644 --- a/src/gui/editorwidgets/qgsrelationwidgetwrapper.h +++ b/src/gui/editorwidgets/qgsrelationwidgetwrapper.h @@ -54,45 +54,57 @@ class GUI_EXPORT QgsRelationWidgetWrapper : public QgsWidgetWrapper /** * Determines if the "link feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showLinkButton() const; + Q_DECL_DEPRECATED bool showLinkButton() const SIP_DEPRECATED; /** * Determines if the "link feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowLinkButton( bool showLinkButton ); + Q_DECL_DEPRECATED void setShowLinkButton( bool showLinkButton ) SIP_DEPRECATED; /** - * Determines if the "save child layer edits" button should be shown - * + * Determines if the "unlink feature" button should be shown + * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use visibleButtons() instead + */ + Q_DECL_DEPRECATED bool showUnlinkButton() const SIP_DEPRECATED; + + /** + * Determines if the "unlink feature" button should be shown + * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead + */ + Q_DECL_DEPRECATED void setShowUnlinkButton( bool showUnlinkButton ) SIP_DEPRECATED; + + /** + * Determines if the "Save child layer edits" button should be shown * \since QGIS 3.14 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - bool showSaveChildEditsButton() const; + Q_DECL_DEPRECATED void setShowSaveChildEditsButton( bool showChildEdits ) SIP_DEPRECATED; /** - * Determines if the "save child layer edits" button should be shown - * + * Determines if the "Save child layer edits" button should be shown * \since QGIS 3.14 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - void setShowSaveChildEditsButton( bool showSaveChildEditsButton ); + Q_DECL_DEPRECATED bool showSaveChildEditsButton() const SIP_DEPRECATED; /** - * Determines if the "unlink feature" button should be shown - * - * \since QGIS 2.18 + * Defines the buttons which are shown + * \since QGIS 3.16 */ - bool showUnlinkButton() const; + void setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ); /** - * Determines if the "unlink feature" button should be shown - * - * \since QGIS 2.18 + * Returns the buttons which are shown + * \since QGIS 3.16 */ - void setShowUnlinkButton( bool showUnlinkButton ); + QgsAttributeEditorRelation::Buttons visibleButtons() const; /** * The relation for which this wrapper is created. diff --git a/src/gui/labeling/qgslabelinggui.cpp b/src/gui/labeling/qgslabelinggui.cpp index e7edc7ba56f2..80ee470ba5b8 100644 --- a/src/gui/labeling/qgslabelinggui.cpp +++ b/src/gui/labeling/qgslabelinggui.cpp @@ -192,6 +192,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, mFontMultiLineAlignComboBox->addItem( tr( "Left" ), QgsPalLayerSettings::MultiLeft ); mFontMultiLineAlignComboBox->addItem( tr( "Center" ), QgsPalLayerSettings::MultiCenter ); mFontMultiLineAlignComboBox->addItem( tr( "Right" ), QgsPalLayerSettings::MultiRight ); + mFontMultiLineAlignComboBox->addItem( tr( "Justify" ), QgsPalLayerSettings::MultiJustify ); // connections for groupboxes with separate activation checkboxes (that need to honor data defined setting) connect( mBufferDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi ); diff --git a/src/gui/layout/qgslayoutattributetablewidget.cpp b/src/gui/layout/qgslayoutattributetablewidget.cpp index 23a132127fc4..c68942f1d584 100644 --- a/src/gui/layout/qgslayoutattributetablewidget.cpp +++ b/src/gui/layout/qgslayoutattributetablewidget.cpp @@ -44,8 +44,6 @@ QgsLayoutAttributeTableWidget::QgsLayoutAttributeTableWidget( QgsLayoutFrame *fr connect( mGridStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutAttributeTableWidget::mGridStrokeWidthSpinBox_valueChanged ); connect( mGridColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mGridColorButton_colorChanged ); connect( mBackgroundColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mBackgroundColorButton_colorChanged ); - connect( mHeaderFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mHeaderFontColorButton_colorChanged ); - connect( mContentFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mContentFontColorButton_colorChanged ); connect( mDrawHorizontalGrid, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mDrawHorizontalGrid_toggled ); connect( mDrawVerticalGrid, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mDrawVerticalGrid_toggled ); connect( mShowGridGroupCheckBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutAttributeTableWidget::mShowGridGroupCheckBox_toggled ); @@ -72,8 +70,8 @@ QgsLayoutAttributeTableWidget::QgsLayoutAttributeTableWidget( QgsLayoutFrame *fr connect( mUseConditionalStylingCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutAttributeTableWidget::useConditionalStylingChanged ); setPanelTitle( tr( "Table Properties" ) ); - mContentFontToolButton->setMode( QgsFontButton::ModeQFont ); - mHeaderFontToolButton->setMode( QgsFontButton::ModeQFont ); + mContentFontToolButton->setMode( QgsFontButton::ModeTextRenderer ); + mHeaderFontToolButton->setMode( QgsFontButton::ModeTextRenderer ); blockAllSignals( true ); @@ -110,12 +108,6 @@ QgsLayoutAttributeTableWidget::QgsLayoutAttributeTableWidget( QgsLayoutFrame *fr mComposerMapComboBox->setItemType( QgsLayoutItemRegistry::LayoutMap ); connect( mComposerMapComboBox, &QgsLayoutItemComboBox::itemChanged, this, &QgsLayoutAttributeTableWidget::composerMapChanged ); - mHeaderFontColorButton->setColorDialogTitle( tr( "Select Header Font Color" ) ); - mHeaderFontColorButton->setAllowOpacity( true ); - mHeaderFontColorButton->setContext( QStringLiteral( "composer" ) ); - mContentFontColorButton->setColorDialogTitle( tr( "Select Content Font Color" ) ); - mContentFontColorButton->setAllowOpacity( true ); - mContentFontColorButton->setContext( QStringLiteral( "composer" ) ); mGridColorButton->setColorDialogTitle( tr( "Select Grid Color" ) ); mGridColorButton->setAllowOpacity( true ); mGridColorButton->setContext( QStringLiteral( "composer" ) ); @@ -300,20 +292,8 @@ void QgsLayoutAttributeTableWidget::headerFontChanged() if ( !mTable ) return; - mTable->beginCommand( tr( "Change Table Font" ) ); - mTable->setHeaderFont( mHeaderFontToolButton->currentFont() ); - mTable->endCommand(); -} - -void QgsLayoutAttributeTableWidget::mHeaderFontColorButton_colorChanged( const QColor &newColor ) -{ - if ( !mTable ) - { - return; - } - - mTable->beginCommand( tr( "Change Font Color" ), QgsLayoutMultiFrame::UndoTableHeaderFontColor ); - mTable->setHeaderFontColor( newColor ); + mTable->beginCommand( tr( "Change Table Text Format" ) ); + mTable->setHeaderTextFormat( mHeaderFontToolButton->textFormat() ); mTable->endCommand(); } @@ -324,20 +304,8 @@ void QgsLayoutAttributeTableWidget::contentFontChanged() return; } - mTable->beginCommand( tr( "Change Table Font" ) ); - mTable->setContentFont( mContentFontToolButton->currentFont() ); - mTable->endCommand(); -} - -void QgsLayoutAttributeTableWidget::mContentFontColorButton_colorChanged( const QColor &newColor ) -{ - if ( !mTable ) - { - return; - } - - mTable->beginCommand( tr( "Change Font Color" ), QgsLayoutMultiFrame::UndoTableContentFontColor ); - mTable->setContentFontColor( newColor ); + mTable->beginCommand( tr( "Change Table Text Format" ) ); + mTable->setContentTextFormat( mContentFontToolButton->textFormat() ); mTable->endCommand(); } @@ -458,10 +426,8 @@ void QgsLayoutAttributeTableWidget::updateGuiElements() } mBackgroundColorButton->setColor( mTable->backgroundColor() ); - mHeaderFontColorButton->setColor( mTable->headerFontColor() ); - mContentFontColorButton->setColor( mTable->contentFontColor() ); - mHeaderFontToolButton->setCurrentFont( mTable->headerFont() ); - mContentFontToolButton->setCurrentFont( mTable->contentFont() ); + mHeaderFontToolButton->setTextFormat( mTable->headerTextFormat() ); + mContentFontToolButton->setTextFormat( mTable->contentTextFormat() ); if ( mTable->displayOnlyVisibleFeatures() && mShowOnlyVisibleFeaturesCheckBox->isEnabled() ) { @@ -606,8 +572,6 @@ void QgsLayoutAttributeTableWidget::blockAllSignals( bool b ) mFeatureFilterCheckBox->blockSignals( b ); mHeaderHAlignmentComboBox->blockSignals( b ); mHeaderModeComboBox->blockSignals( b ); - mHeaderFontColorButton->blockSignals( b ); - mContentFontColorButton->blockSignals( b ); mResizeModeComboBox->blockSignals( b ); mRelationsComboBox->blockSignals( b ); mEmptyModeComboBox->blockSignals( b ); diff --git a/src/gui/layout/qgslayoutattributetablewidget.h b/src/gui/layout/qgslayoutattributetablewidget.h index c64fedc73111..e29b89f42d80 100644 --- a/src/gui/layout/qgslayoutattributetablewidget.h +++ b/src/gui/layout/qgslayoutattributetablewidget.h @@ -71,9 +71,7 @@ class GUI_EXPORT QgsLayoutAttributeTableWidget: public QgsLayoutItemBaseWidget, void mGridColorButton_colorChanged( const QColor &newColor ); void mBackgroundColorButton_colorChanged( const QColor &newColor ); void headerFontChanged(); - void mHeaderFontColorButton_colorChanged( const QColor &newColor ); void contentFontChanged(); - void mContentFontColorButton_colorChanged( const QColor &newColor ); void mDrawHorizontalGrid_toggled( bool state ); void mDrawVerticalGrid_toggled( bool state ); void mShowGridGroupCheckBox_toggled( bool state ); diff --git a/src/gui/layout/qgslayoutguiutils.cpp b/src/gui/layout/qgslayoutguiutils.cpp index a64911a9a57b..27e516577620 100644 --- a/src/gui/layout/qgslayoutguiutils.cpp +++ b/src/gui/layout/qgslayoutguiutils.cpp @@ -411,6 +411,21 @@ void QgsLayoutGuiUtils::registerGuiForKnownItemTypes( QgsMapCanvas *mapCanvas ) } } + //set default table fonts from settings + QgsSettings settings; + const QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString(); + if ( !defaultFontString.isEmpty() ) + { + QgsTextFormat format; + QFont f = format.font(); + f.setFamily( defaultFontString ); + format.setFont( f ); + tableMultiFrame->setContentTextFormat( format ); + f.setBold( true ); + format.setFont( f ); + tableMultiFrame->setHeaderTextFormat( format ); + } + layout->addMultiFrame( tableMultiFrame.release() ); std::unique_ptr< QgsLayoutFrame > frame = qgis::make_unique< QgsLayoutFrame >( layout, table ); QgsLayoutFrame *f = frame.get(); @@ -437,6 +452,21 @@ void QgsLayoutGuiUtils::registerGuiForKnownItemTypes( QgsMapCanvas *mapCanvas ) contents << ( QgsTableRow() << QgsTableCell() << QgsTableCell() ); table->setTableContents( contents ); + //set default table fonts from settings + QgsSettings settings; + const QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString(); + if ( !defaultFontString.isEmpty() ) + { + QgsTextFormat format; + QFont f = format.font(); + f.setFamily( defaultFontString ); + format.setFont( f ); + tableMultiFrame->setContentTextFormat( format ); + f.setBold( true ); + format.setFont( f ); + tableMultiFrame->setHeaderTextFormat( format ); + } + layout->addMultiFrame( tableMultiFrame.release() ); std::unique_ptr< QgsLayoutFrame > frame = qgis::make_unique< QgsLayoutFrame >( layout, table ); diff --git a/src/gui/layout/qgslayoutmanualtablewidget.cpp b/src/gui/layout/qgslayoutmanualtablewidget.cpp index cf51eaa1167b..4c42f817aad4 100644 --- a/src/gui/layout/qgslayoutmanualtablewidget.cpp +++ b/src/gui/layout/qgslayoutmanualtablewidget.cpp @@ -37,8 +37,6 @@ QgsLayoutManualTableWidget::QgsLayoutManualTableWidget( QgsLayoutFrame *frame ) connect( mGridStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutManualTableWidget::mGridStrokeWidthSpinBox_valueChanged ); connect( mGridColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutManualTableWidget::mGridColorButton_colorChanged ); connect( mBackgroundColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutManualTableWidget::mBackgroundColorButton_colorChanged ); - connect( mHeaderFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutManualTableWidget::mHeaderFontColorButton_colorChanged ); - connect( mContentFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutManualTableWidget::mContentFontColorButton_colorChanged ); connect( mDrawHorizontalGrid, &QCheckBox::toggled, this, &QgsLayoutManualTableWidget::mDrawHorizontalGrid_toggled ); connect( mDrawVerticalGrid, &QCheckBox::toggled, this, &QgsLayoutManualTableWidget::mDrawVerticalGrid_toggled ); connect( mShowGridGroupCheckBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutManualTableWidget::mShowGridGroupCheckBox_toggled ); @@ -53,8 +51,8 @@ QgsLayoutManualTableWidget::QgsLayoutManualTableWidget( QgsLayoutFrame *frame ) connect( mAdvancedCustomizationButton, &QPushButton::clicked, this, &QgsLayoutManualTableWidget::mAdvancedCustomizationButton_clicked ); setPanelTitle( tr( "Table Properties" ) ); - mContentFontToolButton->setMode( QgsFontButton::ModeQFont ); - mHeaderFontToolButton->setMode( QgsFontButton::ModeQFont ); + mContentFontToolButton->setMode( QgsFontButton::ModeTextRenderer ); + mHeaderFontToolButton->setMode( QgsFontButton::ModeTextRenderer ); blockAllSignals( true ); @@ -74,12 +72,6 @@ QgsLayoutManualTableWidget::QgsLayoutManualTableWidget( QgsLayoutFrame *frame ) mHeaderHAlignmentComboBox->addItem( tr( "Center" ), QgsLayoutTable::HeaderCenter ); mHeaderHAlignmentComboBox->addItem( tr( "Right" ), QgsLayoutTable::HeaderRight ); - mHeaderFontColorButton->setColorDialogTitle( tr( "Select Header Font Color" ) ); - mHeaderFontColorButton->setAllowOpacity( true ); - mHeaderFontColorButton->setContext( QStringLiteral( "composer" ) ); - mContentFontColorButton->setColorDialogTitle( tr( "Select Content Font Color" ) ); - mContentFontColorButton->setAllowOpacity( true ); - mContentFontColorButton->setContext( QStringLiteral( "composer" ) ); mGridColorButton->setColorDialogTitle( tr( "Select Grid Color" ) ); mGridColorButton->setAllowOpacity( true ); mGridColorButton->setContext( QStringLiteral( "composer" ) ); @@ -169,6 +161,7 @@ void QgsLayoutManualTableWidget::setTableContents() else { mEditorDialog = new QgsTableEditorDialog( this ); + mEditorDialog->registerExpressionContextGenerator( mTable ); connect( this, &QWidget::destroyed, mEditorDialog, &QMainWindow::close ); mEditorDialog->setIncludeTableHeader( mTable->includeTableHeader() ); @@ -269,31 +262,7 @@ void QgsLayoutManualTableWidget::contentFontChanged() } mTable->beginCommand( tr( "Change Table Font" ) ); - mTable->setContentFont( mContentFontToolButton->currentFont() ); - mTable->endCommand(); -} - -void QgsLayoutManualTableWidget::mContentFontColorButton_colorChanged( const QColor &newColor ) -{ - if ( !mTable ) - { - return; - } - - mTable->beginCommand( tr( "Change Font Color" ), QgsLayoutMultiFrame::UndoTableContentFontColor ); - mTable->setContentFontColor( newColor ); - mTable->endCommand(); -} - -void QgsLayoutManualTableWidget::mHeaderFontColorButton_colorChanged( const QColor &newColor ) -{ - if ( !mTable ) - { - return; - } - - mTable->beginCommand( tr( "Change Font Color" ), QgsLayoutMultiFrame::UndoTableHeaderFontColor ); - mTable->setHeaderFontColor( newColor ); + mTable->setContentTextFormat( mContentFontToolButton->textFormat() ); mTable->endCommand(); } @@ -399,7 +368,7 @@ void QgsLayoutManualTableWidget::headerFontChanged() return; mTable->beginCommand( tr( "Change Table Font" ) ); - mTable->setHeaderFont( mHeaderFontToolButton->currentFont() ); + mTable->setHeaderTextFormat( mHeaderFontToolButton->textFormat() ); mTable->endCommand(); } @@ -427,10 +396,8 @@ void QgsLayoutManualTableWidget::updateGuiElements() } mBackgroundColorButton->setColor( mTable->backgroundColor() ); - mHeaderFontColorButton->setColor( mTable->headerFontColor() ); - mContentFontColorButton->setColor( mTable->contentFontColor() ); - mHeaderFontToolButton->setCurrentFont( mTable->headerFont() ); - mContentFontToolButton->setCurrentFont( mTable->contentFont() ); + mHeaderFontToolButton->setTextFormat( mTable->headerTextFormat() ); + mContentFontToolButton->setTextFormat( mTable->contentTextFormat() ); mDrawEmptyCheckBox->setChecked( mTable->showEmptyRows() ); mWrapBehaviorComboBox->setCurrentIndex( mWrapBehaviorComboBox->findData( mTable->wrapBehavior() ) ); @@ -456,8 +423,6 @@ void QgsLayoutManualTableWidget::blockAllSignals( bool b ) mDrawHorizontalGrid->blockSignals( b ); mDrawVerticalGrid->blockSignals( b ); mShowGridGroupCheckBox->blockSignals( b ); - mContentFontColorButton->blockSignals( b ); - mHeaderFontColorButton->blockSignals( b ); mResizeModeComboBox->blockSignals( b ); mEmptyFrameCheckBox->blockSignals( b ); mHideEmptyBgCheckBox->blockSignals( b ); diff --git a/src/gui/layout/qgslayoutmanualtablewidget.h b/src/gui/layout/qgslayoutmanualtablewidget.h index 3ee8ff3b1553..44943496948f 100644 --- a/src/gui/layout/qgslayoutmanualtablewidget.h +++ b/src/gui/layout/qgslayoutmanualtablewidget.h @@ -68,8 +68,6 @@ class GUI_EXPORT QgsLayoutManualTableWidget: public QgsLayoutItemBaseWidget, pri void mBackgroundColorButton_colorChanged( const QColor &newColor ); void headerFontChanged(); void contentFontChanged(); - void mContentFontColorButton_colorChanged( const QColor &newColor ); - void mHeaderFontColorButton_colorChanged( const QColor &newColor ); void mDrawHorizontalGrid_toggled( bool state ); void mDrawVerticalGrid_toggled( bool state ); void mShowGridGroupCheckBox_toggled( bool state ); diff --git a/src/gui/layout/qgslayoutmapgridwidget.cpp b/src/gui/layout/qgslayoutmapgridwidget.cpp index 823186b1d2bf..f9c84e225578 100644 --- a/src/gui/layout/qgslayoutmapgridwidget.cpp +++ b/src/gui/layout/qgslayoutmapgridwidget.cpp @@ -91,7 +91,6 @@ QgsLayoutMapGridWidget::QgsLayoutMapGridWidget( QgsLayoutItemMapGrid *mapGrid, Q connect( mDistanceToMapFrameSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::mDistanceToMapFrameSpinBox_valueChanged ); connect( mMinWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::minIntervalChanged ); connect( mMaxWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutMapGridWidget::maxIntervalChanged ); - connect( mAnnotationFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutMapGridWidget::mAnnotationFontColorButton_colorChanged ); connect( mEnabledCheckBox, &QCheckBox::toggled, this, &QgsLayoutMapGridWidget::gridEnabledToggled ); setPanelTitle( tr( "Map Grid Properties" ) ); @@ -124,10 +123,6 @@ QgsLayoutMapGridWidget::QgsLayoutMapGridWidget( QgsLayoutItemMapGrid *mapGrid, Q mAnnotationFormatComboBox->addItem( tr( "Degree, Minute, Second Aligned" ), QgsLayoutItemMapGrid::DegreeMinuteSecondPadded ); mAnnotationFormatComboBox->addItem( tr( "Custom" ), QgsLayoutItemMapGrid::CustomFormat ); - mAnnotationFontColorButton->setColorDialogTitle( tr( "Select Font Color" ) ); - mAnnotationFontColorButton->setAllowOpacity( true ); - mAnnotationFontColorButton->setContext( QStringLiteral( "composer" ) ); - insertAnnotationDisplayEntries( mAnnotationDisplayLeftComboBox ); insertAnnotationDisplayEntries( mAnnotationDisplayRightComboBox ); insertAnnotationDisplayEntries( mAnnotationDisplayTopComboBox ); @@ -181,10 +176,12 @@ QgsLayoutMapGridWidget::QgsLayoutMapGridWidget( QgsLayoutItemMapGrid *mapGrid, Q updateGuiElements(); blockAllSignals( false ); - connect( mAnnotationFontButton, &QgsFontButton::changed, this, &QgsLayoutMapGridWidget::annotationFontChanged ); + connect( mAnnotationFontButton, &QgsFontButton::changed, this, &QgsLayoutMapGridWidget::annotationTextFormatChanged ); connect( mGridLineStyleButton, &QgsSymbolButton::changed, this, &QgsLayoutMapGridWidget::lineSymbolChanged ); connect( mGridMarkerStyleButton, &QgsSymbolButton::changed, this, &QgsLayoutMapGridWidget::markerSymbolChanged ); + connect( mAnnotationFontButton, &QgsFontButton::changed, this, &QgsLayoutMapGridWidget::annotationTextFormatChanged ); + mGridLineStyleButton->registerExpressionContextGenerator( mMapGrid ); mGridLineStyleButton->setLayer( coverageLayer() ); mGridMarkerStyleButton->registerExpressionContextGenerator( mMapGrid ); @@ -193,8 +190,10 @@ QgsLayoutMapGridWidget::QgsLayoutMapGridWidget( QgsLayoutItemMapGrid *mapGrid, Q { connect( &mMap->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mGridLineStyleButton, &QgsSymbolButton::setLayer ); connect( &mMap->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mGridMarkerStyleButton, &QgsSymbolButton::setLayer ); + connect( &mMap->layout()->reportContext(), &QgsLayoutReportContext::layerChanged, mAnnotationFontButton, &QgsFontButton::setLayer ); } - + mAnnotationFontButton->setLayer( coverageLayer() ); + mAnnotationFontButton->registerExpressionContextGenerator( mMapGrid ); } void QgsLayoutMapGridWidget::populateDataDefinedButtons() @@ -276,7 +275,6 @@ void QgsLayoutMapGridWidget::blockAllSignals( bool block ) mAnnotationDirectionComboBoxBottom->blockSignals( block ); mDistanceToMapFrameSpinBox->blockSignals( block ); mCoordinatePrecisionSpinBox->blockSignals( block ); - mAnnotationFontColorButton->blockSignals( block ); mAnnotationFontButton->blockSignals( block ); mMinWidthSpinBox->blockSignals( block ); mMaxWidthSpinBox->blockSignals( block ); @@ -453,6 +451,7 @@ void QgsLayoutMapGridWidget::setGridItems() mGridMarkerStyleButton->registerExpressionContextGenerator( mMapGrid ); mGridLineStyleButton->registerExpressionContextGenerator( mMapGrid ); + mAnnotationFontButton->registerExpressionContextGenerator( mMapGrid ); mEnabledCheckBox->setChecked( mMapGrid->enabled() ); mIntervalXSpinBox->setValue( mMapGrid->intervalX() ); @@ -575,8 +574,9 @@ void QgsLayoutMapGridWidget::setGridItems() initAnnotationDirectionBox( mAnnotationDirectionComboBoxTop, mMapGrid->annotationDirection( QgsLayoutItemMapGrid::Top ) ); initAnnotationDirectionBox( mAnnotationDirectionComboBoxBottom, mMapGrid->annotationDirection( QgsLayoutItemMapGrid::Bottom ) ); - mAnnotationFontColorButton->setColor( mMapGrid->annotationFontColor() ); - mAnnotationFontButton->setCurrentFont( mMapGrid->annotationFont() ); + mAnnotationFontButton->setDialogTitle( tr( "Grid Annotation Font" ) ); + mAnnotationFontButton->setMode( QgsFontButton::ModeTextRenderer ); + mAnnotationFontButton->setTextFormat( mMapGrid->annotationTextFormat() ); mAnnotationFormatComboBox->setCurrentIndex( mAnnotationFormatComboBox->findData( mMapGrid->annotationFormat() ) ); mAnnotationFormatButton->setEnabled( mMapGrid->annotationFormat() == QgsLayoutItemMapGrid::CustomFormat ); @@ -912,6 +912,20 @@ void QgsLayoutMapGridWidget::maxIntervalChanged( double interval ) mMap->update(); } +void QgsLayoutMapGridWidget::annotationTextFormatChanged() +{ + if ( !mMapGrid || !mMap ) + { + return; + } + + mMap->beginCommand( tr( "Change Annotation Font" ) ); + mMapGrid->setAnnotationTextFormat( mAnnotationFontButton->textFormat() ); + mMap->endCommand(); + mMap->updateBoundingRect(); + mMap->update(); +} + void QgsLayoutMapGridWidget::mGridBlendComboBox_currentIndexChanged( int index ) { Q_UNUSED( index ) @@ -1126,19 +1140,6 @@ void QgsLayoutMapGridWidget::mDistanceToMapFrameSpinBox_valueChanged( double d ) mMap->endCommand(); } -void QgsLayoutMapGridWidget::annotationFontChanged() -{ - if ( !mMapGrid || !mMap ) - { - return; - } - - mMap->beginCommand( tr( "Change Annotation Font" ) ); - mMapGrid->setAnnotationFont( mAnnotationFontButton->currentFont() ); - mMap->updateBoundingRect(); - mMap->update(); - mMap->endCommand(); -} void QgsLayoutMapGridWidget::lineSymbolChanged() { @@ -1180,19 +1181,6 @@ void QgsLayoutMapGridWidget::gridEnabledToggled( bool active ) mMap->update(); } -void QgsLayoutMapGridWidget::mAnnotationFontColorButton_colorChanged( const QColor &color ) -{ - if ( !mMapGrid || !mMap ) - { - return; - } - - mMap->beginCommand( tr( "Change Annotation Color" ), QgsLayoutItem::UndoMapGridAnnotationFontColor ); - mMapGrid->setAnnotationFontColor( color ); - mMap->update(); - mMap->endCommand(); -} - void QgsLayoutMapGridWidget::mAnnotationFormatComboBox_currentIndexChanged( int index ) { if ( !mMapGrid || !mMap ) diff --git a/src/gui/layout/qgslayoutmapgridwidget.h b/src/gui/layout/qgslayoutmapgridwidget.h index 5d438bce3849..c6d64bd53cb3 100644 --- a/src/gui/layout/qgslayoutmapgridwidget.h +++ b/src/gui/layout/qgslayoutmapgridwidget.h @@ -94,7 +94,6 @@ class GUI_EXPORT QgsLayoutMapGridWidget: public QgsLayoutItemBaseWidget, private void mAnnotationFormatComboBox_currentIndexChanged( int index ); void mCoordinatePrecisionSpinBox_valueChanged( int value ); void mDistanceToMapFrameSpinBox_valueChanged( double d ); - void mAnnotationFontColorButton_colorChanged( const QColor &color ); protected: @@ -109,13 +108,13 @@ class GUI_EXPORT QgsLayoutMapGridWidget: public QgsLayoutItemBaseWidget, private //! Sets the GUI elements to the values of mPicture void setGuiElementValues(); - void annotationFontChanged(); void lineSymbolChanged(); void markerSymbolChanged(); void gridEnabledToggled( bool active ); void intervalUnitChanged( int index ); void minIntervalChanged( double interval ); void maxIntervalChanged( double interval ); + void annotationTextFormatChanged(); private: QPointer< QgsLayoutItemMap > mMap; diff --git a/src/gui/processing/qgsprocessingaggregatewidgets.cpp b/src/gui/processing/qgsprocessingaggregatewidgets.cpp index a7d13f04b84d..729445b84612 100644 --- a/src/gui/processing/qgsprocessingaggregatewidgets.cpp +++ b/src/gui/processing/qgsprocessingaggregatewidgets.cpp @@ -34,7 +34,7 @@ QgsAggregateMappingModel::QgsAggregateMappingModel( const QgsFields &sourceFields, QObject *parent ) : QAbstractTableModel( parent ) - , mExpressionContextGenerator( new QgsFieldMappingModel::ExpressionContextGenerator( &sourceFields ) ) + , mExpressionContextGenerator( new QgsFieldMappingModel::ExpressionContextGenerator( sourceFields ) ) { setSourceFields( sourceFields ); } diff --git a/src/gui/processing/qgsprocessingwidgetwrapper.cpp b/src/gui/processing/qgsprocessingwidgetwrapper.cpp index d2476c2efbe8..d1b2b17a460e 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapper.cpp +++ b/src/gui/processing/qgsprocessingwidgetwrapper.cpp @@ -435,3 +435,44 @@ QgsExpressionContext QgsProcessingGuiUtils::createExpressionContext( QgsProcessi return c; } ///@endcond + +QgsProcessingHiddenWidgetWrapper::QgsProcessingHiddenWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QObject *parent ) + : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent ) +{ + +} + +void QgsProcessingHiddenWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & ) +{ + if ( mValue == value ) + return; + + mValue = value; + emit widgetValueHasChanged( this ); +} + +QVariant QgsProcessingHiddenWidgetWrapper::widgetValue() const +{ + return mValue; +} + +const QgsVectorLayer *QgsProcessingHiddenWidgetWrapper::linkedVectorLayer() const +{ + return mLayer; +} + +void QgsProcessingHiddenWidgetWrapper::setLinkedVectorLayer( const QgsVectorLayer *layer ) +{ + mLayer = layer; +} + +QWidget *QgsProcessingHiddenWidgetWrapper::createWidget() +{ + return nullptr; + +} + +QLabel *QgsProcessingHiddenWidgetWrapper::createLabel() +{ + return nullptr; +} diff --git a/src/gui/processing/qgsprocessingwidgetwrapper.h b/src/gui/processing/qgsprocessingwidgetwrapper.h index 5bd225b05959..4b54d181f433 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapper.h +++ b/src/gui/processing/qgsprocessingwidgetwrapper.h @@ -646,4 +646,49 @@ class GUI_EXPORT QgsProcessingParameterWidgetFactoryInterface }; +/** + * \class QgsProcessingHiddenWidgetWrapper + * + * An widget wrapper for hidden widgets. + * + * The hidden widget wrapper allows for creation of a widget wrapper which does not provide + * a graphical widget, yet still implements the QgsAbstractProcessingParameterWidgetWrapper + * interface. + * + * \ingroup gui + * \since QGIS 3.14 + */ +class GUI_EXPORT QgsProcessingHiddenWidgetWrapper: public QgsAbstractProcessingParameterWidgetWrapper +{ + public: + + /** + * Constructor for QgsProcessingHiddenWidgetWrapper, for the specified + * \a parameter definition and dialog \a type. + */ + QgsProcessingHiddenWidgetWrapper( const QgsProcessingParameterDefinition *parameter = nullptr, + QgsProcessingGui::WidgetType type = QgsProcessingGui::Standard, + QObject *parent SIP_TRANSFERTHIS = nullptr ); + + void setWidgetValue( const QVariant &value, QgsProcessingContext &context ) override; + QVariant widgetValue() const override; + + const QgsVectorLayer *linkedVectorLayer() const override; + + /** + * Sets the vector layer linked to the wrapper. + */ + void setLinkedVectorLayer( const QgsVectorLayer *layer ); + + protected: + QWidget *createWidget() override; + QLabel *createLabel() override; + + private: + + QVariant mValue; + QPointer < const QgsVectorLayer > mLayer; + +}; + #endif // QGSPROCESSINGWIDGETWRAPPER_H diff --git a/src/gui/providers/gdal/qgsgdalguiprovider.cpp b/src/gui/providers/gdal/qgsgdalguiprovider.cpp index e4b458a7baa7..4d53d09b86ca 100644 --- a/src/gui/providers/gdal/qgsgdalguiprovider.cpp +++ b/src/gui/providers/gdal/qgsgdalguiprovider.cpp @@ -45,7 +45,7 @@ QString QgsGdalItemGuiProvider::name() return QStringLiteral( "gdal_items" ); } -void QgsGdalItemGuiProvider::onDeleteLayer() +void QgsGdalItemGuiProvider::onDeleteLayer( QgsDataItemGuiContext context ) { QAction *s = qobject_cast( sender() ); QVariantMap data = s->data().toMap(); @@ -125,26 +125,26 @@ void QgsGdalItemGuiProvider::onDeleteLayer() if ( deleted ) { - QMessageBox::information( nullptr, title, tr( "Table deleted successfully." ) ); + notify( title, tr( "Table deleted successfully." ), context, Qgis::MessageLevel::Success ); if ( parent ) parent->refresh(); } else { - QMessageBox::warning( nullptr, title, errorMessage.isEmpty() ? - tr( "Could not delete table." ) : - tr( "Could not delete table, reason: %1." ).arg( errorMessage ) ); + notify( title, errorMessage.isEmpty() ? + tr( "Could not delete table." ) : + tr( "Could not delete table, reason: %1." ).arg( errorMessage ), context, Qgis::MessageLevel::Warning ); } } else { if ( !QFile::remove( path ) ) { - QMessageBox::warning( nullptr, title, tr( "Could not delete file." ) ); + notify( title, tr( "Could not delete file." ), context, Qgis::MessageLevel::Warning ); } else { - QMessageBox::information( nullptr, title, tr( "File deleted successfully." ) ); + notify( title, tr( "File deleted successfully." ), context, Qgis::MessageLevel::Success ); if ( parent ) parent->refresh(); } @@ -152,15 +152,14 @@ void QgsGdalItemGuiProvider::onDeleteLayer() } else { - QMessageBox::warning( nullptr, title, QObject::tr( "The layer “%1” cannot be deleted because it is in the current project as “%2”," - " remove it from the project and retry." ).arg( path, projectLayer->name() ) ); + notify( title, tr( "The layer “%1” cannot be deleted because it is in the current project as “%2”," + " remove it from the project and retry." ).arg( path, projectLayer->name() ), context, Qgis::MessageLevel::Warning ); } } void QgsGdalItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &selectedItems, QgsDataItemGuiContext context ) { Q_UNUSED( selectedItems ); - Q_UNUSED( context ); if ( QgsGdalLayerItem *layerItem = qobject_cast< QgsGdalLayerItem * >( item ) ) { @@ -175,7 +174,7 @@ void QgsGdalItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu data.insert( QStringLiteral( "path" ), isPostgresRaster ? layerItem->name() : layerItem->path() ); data.insert( QStringLiteral( "parentItem" ), QVariant::fromValue( QPointer< QgsDataItem >( layerItem->parent() ) ) ); actionDeleteLayer->setData( data ); - connect( actionDeleteLayer, &QAction::triggered, this, &QgsGdalItemGuiProvider::onDeleteLayer ); + connect( actionDeleteLayer, &QAction::triggered, this, [ = ] { onDeleteLayer( context ); } ); menu->addAction( actionDeleteLayer ); } } diff --git a/src/gui/providers/gdal/qgsgdalguiprovider.h b/src/gui/providers/gdal/qgsgdalguiprovider.h index e53bb212e8de..4273d235cc28 100644 --- a/src/gui/providers/gdal/qgsgdalguiprovider.h +++ b/src/gui/providers/gdal/qgsgdalguiprovider.h @@ -46,7 +46,7 @@ class QgsGdalItemGuiProvider : public QObject, public QgsDataItemGuiProvider const QList &selectedItems, QgsDataItemGuiContext context ) override; protected slots: - void onDeleteLayer(); + void onDeleteLayer( QgsDataItemGuiContext context ); }; class QgsGdalGuiProviderMetadata: public QgsProviderGuiMetadata diff --git a/src/gui/providers/ogr/qgsgeopackageitemguiprovider.cpp b/src/gui/providers/ogr/qgsgeopackageitemguiprovider.cpp index ab7844048f01..514a18b6285f 100644 --- a/src/gui/providers/ogr/qgsgeopackageitemguiprovider.cpp +++ b/src/gui/providers/ogr/qgsgeopackageitemguiprovider.cpp @@ -91,26 +91,6 @@ void QgsGeoPackageItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu menu->addAction( actionAddConnection ); } - // Add table to existing DB - QAction *actionAddTable = new QAction( tr( "Create a New Layer or Table…" ), collectionItem->parent() ); - QPointercollectionItemPtr { collectionItem }; - const QString itemPath = collectionItem->path().remove( QStringLiteral( "gpkg:/" ) ); - connect( actionAddTable, &QAction::triggered, actionAddTable, [ collectionItemPtr, itemPath ] - { - QgsNewGeoPackageLayerDialog dialog( nullptr ); - dialog.setDatabasePath( itemPath ); - dialog.setCrs( QgsProject::instance()->defaultCrsForNewLayers() ); - dialog.setOverwriteBehavior( QgsNewGeoPackageLayerDialog::AddNewLayer ); - dialog.lockDatabasePath(); - if ( dialog.exec() == QDialog::Accepted ) - { - if ( collectionItemPtr ) - collectionItemPtr->refreshConnections(); - } - } ); - - menu->addAction( actionAddTable ); - QAction *sep = new QAction( collectionItem->parent() ); sep->setSeparator( true ); menu->addAction( sep ); diff --git a/src/gui/providers/ogr/qgsogritemguiprovider.cpp b/src/gui/providers/ogr/qgsogritemguiprovider.cpp index fc698cec4763..cc37c2331d76 100644 --- a/src/gui/providers/ogr/qgsogritemguiprovider.cpp +++ b/src/gui/providers/ogr/qgsogritemguiprovider.cpp @@ -32,7 +32,7 @@ void QgsOgrItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &, - QgsDataItemGuiContext ) + QgsDataItemGuiContext context ) { if ( QgsOgrLayerItem *layerItem = qobject_cast< QgsOgrLayerItem * >( item ) ) { @@ -45,7 +45,7 @@ void QgsOgrItemGuiProvider::populateContextMenu( data.insert( QStringLiteral( "name" ), layerItem->name() ); data.insert( QStringLiteral( "parent" ), QVariant::fromValue( QPointer< QgsDataItem >( layerItem->parent() ) ) ); actionDeleteLayer->setData( data ); - connect( actionDeleteLayer, &QAction::triggered, this, &QgsOgrItemGuiProvider::onDeleteLayer ); + connect( actionDeleteLayer, &QAction::triggered, this, [ = ] { onDeleteLayer( context ); } ); menu->addAction( actionDeleteLayer ); } @@ -60,12 +60,12 @@ void QgsOgrItemGuiProvider::populateContextMenu( data.insert( QStringLiteral( "path" ), collectionItem->path() ); data.insert( QStringLiteral( "parent" ), QVariant::fromValue( QPointer< QgsDataItem >( collectionItem->parent() ) ) ); actionDeleteCollection->setData( data ); - connect( actionDeleteCollection, &QAction::triggered, this, &QgsOgrItemGuiProvider::deleteCollection ); + connect( actionDeleteCollection, &QAction::triggered, this, [ = ] { deleteCollection( context ); } ); menu->addAction( actionDeleteCollection ); } } -void QgsOgrItemGuiProvider::onDeleteLayer() +void QgsOgrItemGuiProvider::onDeleteLayer( QgsDataItemGuiContext context ) { QAction *s = qobject_cast( sender() ); QVariantMap data = s->data().toMap(); @@ -106,23 +106,23 @@ void QgsOgrItemGuiProvider::onDeleteLayer() bool res = QgsOgrProviderUtils::deleteLayer( uri, errCause ); if ( !res ) { - QMessageBox::warning( nullptr, title, errCause ); + notify( title, errCause, context, Qgis::MessageLevel::Critical ); } else { - QMessageBox::information( nullptr, title, isSubLayer ? tr( "Layer deleted successfully." ) : tr( "File deleted successfully." ) ); + notify( title, isSubLayer ? tr( "Layer deleted successfully." ) : tr( "File deleted successfully." ), context, Qgis::MessageLevel::Success ); if ( parent ) parent->refresh(); } } else { - QMessageBox::warning( nullptr, title, QObject::tr( "The layer '%1' cannot be deleted because it is in the current project as '%2'," - " remove it from the project and retry." ).arg( name, projectLayer->name() ) ); + notify( title, QObject::tr( "The layer '%1' cannot be deleted because it is in the current project as '%2'," + " remove it from the project and retry." ).arg( name, projectLayer->name() ), context, Qgis::MessageLevel::Warning ); } } -void QgsOgrItemGuiProvider::deleteCollection() +void QgsOgrItemGuiProvider::deleteCollection( QgsDataItemGuiContext context ) { QAction *s = qobject_cast( sender() ); QVariantMap data = s->data().toMap(); @@ -166,19 +166,19 @@ void QgsOgrItemGuiProvider::deleteCollection() } if ( !res ) { - QMessageBox::warning( nullptr, title, tr( "Could not delete %1." ).arg( type ) ); + notify( title, tr( "Could not delete %1." ).arg( type ), context, Qgis::MessageLevel::Warning ); } else { - QMessageBox::information( nullptr, title, tr( "%1 deleted successfully." ).arg( typeCaps ) ); + notify( title, tr( "%1 deleted successfully." ).arg( typeCaps ), context, Qgis::MessageLevel::Success ); if ( parent ) parent->refresh(); } } else { - QMessageBox::warning( nullptr, title, QObject::tr( "The %1 '%2' cannot be deleted because it is in the current project as '%3'," - " remove it from the project and retry." ).arg( type, path, projectLayer->name() ) ); + notify( title, tr( "The %1 '%2' cannot be deleted because it is in the current project as '%3'," + " remove it from the project and retry." ).arg( type, path, projectLayer->name() ), context, Qgis::MessageLevel::Warning ); } } ///@endcond diff --git a/src/gui/providers/ogr/qgsogritemguiprovider.h b/src/gui/providers/ogr/qgsogritemguiprovider.h index 14646af53d76..e0ce2d193dad 100644 --- a/src/gui/providers/ogr/qgsogritemguiprovider.h +++ b/src/gui/providers/ogr/qgsogritemguiprovider.h @@ -40,8 +40,9 @@ class QgsOgrItemGuiProvider : public QObject, public QgsDataItemGuiProvider QgsDataItemGuiContext context ) override; protected slots: - void onDeleteLayer(); - void deleteCollection(); + void onDeleteLayer( QgsDataItemGuiContext context ); + void deleteCollection( QgsDataItemGuiContext context ); + }; ///@endcond diff --git a/src/gui/qgsaddattrdialog.cpp b/src/gui/qgsaddattrdialog.cpp index 48bd22b4b0f1..5581682cfa1c 100644 --- a/src/gui/qgsaddattrdialog.cpp +++ b/src/gui/qgsaddattrdialog.cpp @@ -90,6 +90,7 @@ void QgsAddAttrDialog::setPrecisionMinMax() int minPrecType = mTypeBox->itemData( idx, Qt::UserRole + 4 ).toInt(); int maxPrecType = mTypeBox->itemData( idx, Qt::UserRole + 5 ).toInt(); bool precisionIsEnabled = minPrecType < maxPrecType; + mPrec->setEnabled( precisionIsEnabled ); mPrec->setVisible( precisionIsEnabled ); mPrecLabel->setVisible( precisionIsEnabled ); @@ -138,7 +139,7 @@ QgsField QgsAddAttrDialog::field() const ( QVariant::Type ) mTypeBox->currentData( Qt::UserRole ).toInt(), mTypeBox->currentData( Qt::UserRole + 1 ).toString(), mLength->value(), - mPrec->value(), + mPrec->isEnabled() ? mPrec->value() : 0, mCommentEdit->text(), static_cast( mTypeBox->currentData( Qt::UserRole ).toInt() ) == QVariant::Map ? QVariant::String : QVariant::Invalid ); diff --git a/src/gui/qgsalignmentcombobox.cpp b/src/gui/qgsalignmentcombobox.cpp index c9a0f14ab5aa..8e2d7ee8adb1 100644 --- a/src/gui/qgsalignmentcombobox.cpp +++ b/src/gui/qgsalignmentcombobox.cpp @@ -76,6 +76,13 @@ void QgsAlignmentComboBox::populate() if ( mAlignments & Qt::AlignJustify ) addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconAlignJustify.svg" ) ), tr( "Justify" ), Qt::AlignJustify ); + if ( mAlignments & Qt::AlignTop ) + addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconAlignTop.svg" ) ), tr( "Top" ), Qt::AlignTop ); + if ( mAlignments & Qt::AlignVCenter ) + addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconAlignVCenter.svg" ) ), tr( "Vertical Center" ), Qt::AlignVCenter ); + if ( mAlignments & Qt::AlignBottom ) + addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconAlignBottom.svg" ) ), tr( "Bottom" ), Qt::AlignBottom ); + const int index = findData( QVariant( prevAlign ) ); if ( index >= 0 ) setCurrentIndex( index ); diff --git a/src/gui/qgsattributedialog.cpp b/src/gui/qgsattributedialog.cpp index 0656fb83d033..5a9cd31fb08a 100644 --- a/src/gui/qgsattributedialog.cpp +++ b/src/gui/qgsattributedialog.cpp @@ -148,3 +148,8 @@ bool QgsAttributeDialog::event( QEvent *e ) return QDialog::event( e ); } + +void QgsAttributeDialog::setExtraContextScope( QgsExpressionContextScope *extraScope ) +{ + mAttributeForm->setExtraContextScope( extraScope ); +} diff --git a/src/gui/qgsattributedialog.h b/src/gui/qgsattributedialog.h index b622f69b816a..774f3702bc6c 100644 --- a/src/gui/qgsattributedialog.h +++ b/src/gui/qgsattributedialog.h @@ -95,6 +95,14 @@ class GUI_EXPORT QgsAttributeDialog : public QDialog */ bool event( QEvent *e ) override; + /** + * Sets \a extraScope as an additional expression context scope to be used + * for calculations in this form. + * + * \since QGIS 3.16 + */ + void setExtraContextScope( QgsExpressionContextScope *extraScope SIP_TRANSFER ); + public slots: void accept() override; void reject() override; diff --git a/src/gui/qgsattributeeditorcontext.h b/src/gui/qgsattributeeditorcontext.h index 46c2392e4b31..e1f86b1a3564 100644 --- a/src/gui/qgsattributeeditorcontext.h +++ b/src/gui/qgsattributeeditorcontext.h @@ -49,6 +49,7 @@ class GUI_EXPORT QgsAttributeEditorContext SingleEditMode, //!< Single edit mode, for editing a single feature AddFeatureMode, /*!< Add feature mode, for setting attributes for a new feature. In this mode the dialog will be editable even with an invalid feature and will add a new feature when the form is accepted. */ + FixAttributeMode, //!< Fix feature mode, for modifying the feature attributes without saving. The updated feature is available via `feature()` after `save()` MultiEditMode, //!< Multi edit mode, for editing fields of multiple features at once SearchMode, //!< Form values are used for searching/filtering the layer AggregateSearchMode, //!< Form is in aggregate search mode, show each widget in this mode \since QGIS 3.0 diff --git a/src/gui/qgsattributeform.cpp b/src/gui/qgsattributeform.cpp index f62aaa8bbf53..5b18839724a4 100644 --- a/src/gui/qgsattributeform.cpp +++ b/src/gui/qgsattributeform.cpp @@ -173,6 +173,10 @@ void QgsAttributeForm::setMode( QgsAttributeEditorContext::Mode mode ) w->setMode( QgsAttributeFormWidget::DefaultMode ); break; + case QgsAttributeEditorContext::FixAttributeMode: + w->setMode( QgsAttributeFormWidget::DefaultMode ); + break; + case QgsAttributeEditorContext::MultiEditMode: w->setMode( QgsAttributeFormWidget::MultiEditMode ); break; @@ -216,6 +220,11 @@ void QgsAttributeForm::setMode( QgsAttributeEditorContext::Mode mode ) mSearchButtonBox->setVisible( false ); break; + case QgsAttributeEditorContext::FixAttributeMode: + synchronizeEnabledState(); + mSearchButtonBox->setVisible( false ); + break; + case QgsAttributeEditorContext::MultiEditMode: resetMultiEdit( false ); synchronizeEnabledState(); @@ -278,6 +287,7 @@ void QgsAttributeForm::setFeature( const QgsFeature &feature ) case QgsAttributeEditorContext::SingleEditMode: case QgsAttributeEditorContext::IdentifyMode: case QgsAttributeEditorContext::AddFeatureMode: + case QgsAttributeEditorContext::FixAttributeMode: { resetValues(); @@ -320,7 +330,7 @@ bool QgsAttributeForm::saveEdits() // An add dialog should perform an action by default // and not only if attributes have "changed" - if ( mMode == QgsAttributeEditorContext::AddFeatureMode ) + if ( mMode == QgsAttributeEditorContext::AddFeatureMode || mMode == QgsAttributeEditorContext::FixAttributeMode ) doUpdate = true; QgsAttributes src = mFeature.attributes(); @@ -379,7 +389,11 @@ bool QgsAttributeForm::saveEdits() if ( doUpdate ) { - if ( mMode == QgsAttributeEditorContext::AddFeatureMode ) + if ( mMode == QgsAttributeEditorContext::FixAttributeMode ) + { + mFeature = updatedFeature; + } + else if ( mMode == QgsAttributeEditorContext::AddFeatureMode ) { mFeature.setValid( true ); mLayer->beginEditCommand( mEditCommandMessage ); @@ -516,7 +530,8 @@ bool QgsAttributeForm::updateDefaultValues( const int originIdx ) if ( mAlreadyUpdatedFields.contains( eww->fieldIdx() ) ) continue; - QString value = mLayer->defaultValue( eww->fieldIdx(), updatedFeature ).toString(); + QgsExpressionContext context = createExpressionContext( updatedFeature ); + QString value = mLayer->defaultValue( eww->fieldIdx(), updatedFeature, &context ).toString(); eww->setValue( value ); } } @@ -735,6 +750,7 @@ bool QgsAttributeForm::save() { case QgsAttributeEditorContext::SingleEditMode: case QgsAttributeEditorContext::IdentifyMode: + case QgsAttributeEditorContext::FixAttributeMode: case QgsAttributeEditorContext::MultiEditMode: if ( !mDirty ) return true; @@ -761,6 +777,7 @@ bool QgsAttributeForm::save() case QgsAttributeEditorContext::SingleEditMode: case QgsAttributeEditorContext::IdentifyMode: case QgsAttributeEditorContext::AddFeatureMode: + case QgsAttributeEditorContext::FixAttributeMode: case QgsAttributeEditorContext::SearchMode: case QgsAttributeEditorContext::AggregateSearchMode: success = saveEdits(); @@ -832,6 +849,17 @@ QString QgsAttributeForm::createFilterExpression() const return filter; } +QgsExpressionContext QgsAttributeForm::createExpressionContext( const QgsFeature &feature ) const +{ + QgsExpressionContext context; + context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) ); + context.appendScope( QgsExpressionContextUtils::formScope( feature, mContext.attributeFormModeString() ) ); + if ( mExtraContextScope ) + context.appendScope( new QgsExpressionContextScope( *mExtraContextScope.get() ) ); + context.setFeature( feature ); + return context; +} + void QgsAttributeForm::onAttributeChanged( const QVariant &value, const QVariantList &additionalFieldValues ) { @@ -848,6 +876,7 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value, const QVariant case QgsAttributeEditorContext::SingleEditMode: case QgsAttributeEditorContext::IdentifyMode: case QgsAttributeEditorContext::AddFeatureMode: + case QgsAttributeEditorContext::FixAttributeMode: { Q_NOWARN_DEPRECATED_PUSH emit attributeChanged( eww->field().name(), value ); @@ -950,10 +979,7 @@ void QgsAttributeForm::updateConstraints( QgsEditorWidgetWrapper *eww ) // sync OK button status synchronizeEnabledState(); - QgsExpressionContext context; - context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) ); - context.appendScope( QgsExpressionContextUtils::formScope( ft, mContext.attributeFormModeString() ) ); - context.setFeature( ft ); + QgsExpressionContext context = createExpressionContext( ft ); // Recheck visibility for all containers which are controlled by this value const QVector infos = mContainerInformationDependency.value( eww->field().name() ); @@ -966,10 +992,7 @@ void QgsAttributeForm::updateConstraints( QgsEditorWidgetWrapper *eww ) void QgsAttributeForm::updateContainersVisibility() { - QgsExpressionContext context; - context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) ); - context.appendScope( QgsExpressionContextUtils::formScope( mFeature, mContext.attributeFormModeString() ) ); - context.setFeature( mFeature ); + QgsExpressionContext context = createExpressionContext( mFeature ); const QVector infos = mContainerVisibilityInformation; @@ -1017,10 +1040,7 @@ void QgsAttributeForm::updateLabels() QgsFeature currentFeature; if ( currentFormFeature( currentFeature ) ) { - QgsExpressionContext context; - context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) ); - context.appendScope( QgsExpressionContextUtils::formScope( currentFeature, mContext.attributeFormModeString() ) ); - context.setFeature( currentFeature ); + QgsExpressionContext context = createExpressionContext( currentFeature ); for ( auto it = mLabelDataDefinedProperties.constBegin() ; it != mLabelDataDefinedProperties.constEnd(); ++it ) { @@ -1933,9 +1953,7 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt // This needs to be after QgsAttributeFormRelationEditorWidget creation, because the widget // does not exists yet until QgsAttributeFormRelationEditorWidget is created and the setters // below directly alter the widget and check for it. - rww->setShowLinkButton( relDef->showLinkButton() ); - rww->setShowUnlinkButton( relDef->showUnlinkButton() ); - rww->setShowSaveChildEditsButton( relDef->showSaveChildEditsButton() ); + rww->setVisibleButtons( relDef->visibleButtons() ); rww->setShowLabel( relDef->showLabel() ); mWidgets.append( rww ); @@ -2264,6 +2282,7 @@ void QgsAttributeForm::layerSelectionChanged() case QgsAttributeEditorContext::SingleEditMode: case QgsAttributeEditorContext::IdentifyMode: case QgsAttributeEditorContext::AddFeatureMode: + case QgsAttributeEditorContext::FixAttributeMode: case QgsAttributeEditorContext::SearchMode: case QgsAttributeEditorContext::AggregateSearchMode: break; @@ -2380,6 +2399,11 @@ QString QgsAttributeForm::aggregateFilter() const return filters.join( QStringLiteral( " AND " ) ); } +void QgsAttributeForm::setExtraContextScope( QgsExpressionContextScope *extraScope ) +{ + mExtraContextScope.reset( extraScope ); +} + int QgsAttributeForm::messageTimeout() { QgsSettings settings; diff --git a/src/gui/qgsattributeform.h b/src/gui/qgsattributeform.h index ece8b4fbfb1b..e6319573a8e0 100644 --- a/src/gui/qgsattributeform.h +++ b/src/gui/qgsattributeform.h @@ -183,6 +183,14 @@ class GUI_EXPORT QgsAttributeForm : public QWidget */ QString aggregateFilter() const; + /** + * Sets an additional expression context scope to be used + * for calculations in this form. + * + * \since QGIS 3.16 + */ + void setExtraContextScope( QgsExpressionContextScope *extraScope SIP_TRANSFER ); + signals: /** @@ -387,6 +395,8 @@ class GUI_EXPORT QgsAttributeForm : public QWidget QString createFilterExpression() const; + QgsExpressionContext createExpressionContext( const QgsFeature &feature ) const; + //! constraints management void updateAllConstraints(); void updateConstraints( QgsEditorWidgetWrapper *w ); @@ -407,6 +417,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget QgsMessageBarItem *mMultiEditMessageBarItem = nullptr; QList mWidgets; QgsAttributeEditorContext mContext; + std::unique_ptr mExtraContextScope; QDialogButtonBox *mButtonBox = nullptr; QWidget *mSearchButtonBox = nullptr; QList mInterfaces; diff --git a/src/gui/qgsdataitemguiprovider.cpp b/src/gui/qgsdataitemguiprovider.cpp index 0266b1e26b57..cb06846e14ce 100644 --- a/src/gui/qgsdataitemguiprovider.cpp +++ b/src/gui/qgsdataitemguiprovider.cpp @@ -14,7 +14,12 @@ ***************************************************************************/ #include "qgsdataitemguiprovider.h" - +#include "qgsdataitem.h" +#include "qgsproviderregistry.h" +#include "qgsprovidermetadata.h" +#include "qgsabstractdatabaseproviderconnection.h" +#include "qgsmessagebar.h" +#include // // QgsDataItemGuiContext // @@ -35,6 +40,7 @@ void QgsDataItemGuiContext::setMessageBar( QgsMessageBar *messageBar ) void QgsDataItemGuiProvider::populateContextMenu( QgsDataItem *, QMenu *, const QList &, QgsDataItemGuiContext ) { + } bool QgsDataItemGuiProvider::rename( QgsDataItem *, const QString &, QgsDataItemGuiContext ) @@ -66,3 +72,60 @@ QWidget *QgsDataItemGuiProvider::createParamWidget( QgsDataItem *, QgsDataItemGu { return nullptr; } + +void QgsDataItemGuiProvider::notify( const QString &title, const QString &message, QgsDataItemGuiContext context, Qgis::MessageLevel level ) +{ + switch ( level ) + { + case Qgis::MessageLevel::Info: + case Qgis::MessageLevel::None: + { + if ( context.messageBar() ) + { + context.messageBar()->pushInfo( title, message ); + } + else + { + QMessageBox::information( nullptr, title, message ); + } + break; + } + case Qgis::MessageLevel::Warning: + { + if ( context.messageBar() ) + { + context.messageBar()->pushWarning( title, message ); + } + else + { + QMessageBox::warning( nullptr, title, message ); + } + break; + } + case Qgis::MessageLevel::Critical: + { + if ( context.messageBar() ) + { + context.messageBar()->pushCritical( title, message ); + } + else + { + QMessageBox::critical( nullptr, title, message ); + } + break; + } + case Qgis::MessageLevel::Success: + { + if ( context.messageBar() ) + { + context.messageBar()->pushSuccess( title, message ); + } + else + { + // There is no "success" in message box, let's use information instead + QMessageBox::information( nullptr, title, message ); + } + break; + } + } +} diff --git a/src/gui/qgsdataitemguiprovider.h b/src/gui/qgsdataitemguiprovider.h index 507029f6cdfa..a875a2d51d31 100644 --- a/src/gui/qgsdataitemguiprovider.h +++ b/src/gui/qgsdataitemguiprovider.h @@ -18,6 +18,7 @@ #include "qgis_gui.h" #include "qgis_sip.h" +#include "qgis.h" #include #include #include @@ -174,6 +175,14 @@ class GUI_EXPORT QgsDataItemGuiProvider * \since QGIS 3.10 */ virtual QWidget *createParamWidget( QgsDataItem *item, QgsDataItemGuiContext context ) SIP_FACTORY; + + /** + * Notify the user showing a \a message with \a title and \a level + * If the context has a message bar the message will be shown in the message bar + * else a message dialog will be used. + * \since QGIS 3.16 + */ + static void notify( const QString &title, const QString &message, QgsDataItemGuiContext context, Qgis::MessageLevel level = Qgis::Info ); }; #endif // QGSDATAITEMGUIPROVIDER_H diff --git a/src/gui/qgsdoublevalidator.cpp b/src/gui/qgsdoublevalidator.cpp new file mode 100644 index 000000000000..3f15779b955e --- /dev/null +++ b/src/gui/qgsdoublevalidator.cpp @@ -0,0 +1,131 @@ +/*************************************************************************** + qgsdoublevalidator.cpp - description + ------------------- + begin : June 2020 + copyright : (C) 2020 by Sebastien Peillet + email : sebastien.peillet@oslandia.com + + adapted version of Qgslonglongvalidator + QgsFieldValidator + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include "qgis_gui.h" + +#include "qgsdoublevalidator.h" + +const QString PERMISSIVE_DOUBLE = R"(-?[\d]{0,1000}([\.%1][\d]{0,1000})?(e[+-]?[\d]{0,%2})?)"; + +QgsDoubleValidator::QgsDoubleValidator( QObject *parent ) + : QRegularExpressionValidator( parent ) + , mMinimum( std::numeric_limits::min() ) + , mMaximum( std::numeric_limits::max() ) +{ + // The regular expression accept double with point as decimal point but also the locale decimal point + QRegularExpression reg( PERMISSIVE_DOUBLE.arg( locale().decimalPoint() ).arg( 1000 ) ); + setRegularExpression( reg ); +} + +QgsDoubleValidator::QgsDoubleValidator( const QRegularExpression &expression, double bottom, double top, QObject *parent ) + : QRegularExpressionValidator( parent ) + , mMinimum( bottom ) + , mMaximum( top ) +{ + setRegularExpression( expression ); +} + +QgsDoubleValidator::QgsDoubleValidator( double bottom, double top, QObject *parent ) + : QRegularExpressionValidator( parent ) + , mMinimum( bottom ) + , mMaximum( top ) +{ + // The regular expression accept double with point as decimal point but also the locale decimal point + QRegularExpression reg( PERMISSIVE_DOUBLE.arg( locale().decimalPoint() ).arg( 1000 ) ); + setRegularExpression( reg ); +} + +QgsDoubleValidator::QgsDoubleValidator( double bottom, double top, int decimal, QObject *parent ) + : QRegularExpressionValidator( parent ) + , mMinimum( bottom ) + , mMaximum( top ) +{ + // The regular expression accept double with point as decimal point but also the locale decimal point + QRegularExpression reg( PERMISSIVE_DOUBLE.arg( locale().decimalPoint() ).arg( QString::number( decimal ) ) ); + setRegularExpression( reg ); +} + +QValidator::State QgsDoubleValidator::validate( QString &input, int & ) const +{ + if ( input.isEmpty() ) + return Intermediate; + + + bool ok = false; + const double entered = QgsDoubleValidator::toDouble( input, &ok ); + if ( ! ok ) + { + if ( regularExpression().match( input ).captured( 0 ) == input ) + return Intermediate; + else + return Invalid; + } + + if ( entered >= mMinimum && entered <= mMaximum && regularExpression().match( input ).captured( 0 ) == input ) + return Acceptable; + else + return Intermediate; +} + +QValidator::State QgsDoubleValidator::validate( QString &input ) const +{ + if ( input.isEmpty() ) + return Intermediate; + + + bool ok = false; + const double entered = QgsDoubleValidator::toDouble( input, &ok ); + if ( ! ok ) + { + if ( regularExpression().match( input ).captured( 0 ) == input ) + return Intermediate; + else + return Invalid; + } + + if ( entered >= mMinimum && entered <= mMaximum && regularExpression().match( input ).captured( 0 ) == input ) + return Acceptable; + else + return Intermediate; +} + +double QgsDoubleValidator::toDouble( const QString &input ) +{ + bool ok = false; + double value = QLocale().toDouble( input, &ok ); + if ( ! ok ) + { + value = QLocale( QLocale::C ).toDouble( input, &ok ); + } + return value; +} + +double QgsDoubleValidator::toDouble( const QString &input, bool *ok ) +{ + double value = QLocale().toDouble( input, ok ); + + if ( ! *ok ) + { + value = QLocale( QLocale::C ).toDouble( input, ok ); + } + return value ; +} diff --git a/src/gui/qgsdoublevalidator.h b/src/gui/qgsdoublevalidator.h new file mode 100644 index 000000000000..485b8e5ac1bb --- /dev/null +++ b/src/gui/qgsdoublevalidator.h @@ -0,0 +1,149 @@ +/*************************************************************************** + qgsdoublevalidator.h - description + ------------------- + begin : June 2020 + copyright : (C) 2020 by Sebastien Peillet + email : sebastien.peillet@oslandia.com + + adapted version of Qgslonglongvalidator + QgsFieldValidator + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSDOUBLEVALIDATOR_H +#define QGSDOUBLEVALIDATOR_H + +#include +#include +#include +#include "qgis_gui.h" +#include "qgis_sip.h" + +/** + * \ingroup gui + * + * QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator + * and QRegularExpressionValidator to allow user to enter double with both + * local and C interpretation as a fallback. + * + * \since QGIS 3.14 + */ +class GUI_EXPORT QgsDoubleValidator : public QRegularExpressionValidator +{ + Q_OBJECT + + public: + + /** + * Constructor for QgsDoubleValidator. + */ + explicit QgsDoubleValidator( QObject *parent ); + + /** + * Constructor for QgsDoubleValidator. + * + * \param bottom the minimal range limit accepted by the validator + * \param top the maximal range limit accepted by the validator + */ + QgsDoubleValidator( const QRegularExpression &expression, double bottom, double top, QObject *parent ); + + /** + * Constructor for QgsDoubleValidator. + * + * \param bottom the minimal range limit accepted by the validator + * \param top the maximal range limit accepted by the validator + */ + QgsDoubleValidator( double bottom, double top, QObject *parent ); + + /** + * Constructor for QgsDoubleValidator. + * + * \param bottom the minimal range limit accepted by the validator + * \param top the maximal range limit accepted by the validator + * \param decimal the number of decimal accepted by the validator + */ + QgsDoubleValidator( double bottom, double top, int decimal, QObject *parent ); + + + QValidator::State validate( QString &input, int & ) const override SIP_SKIP; + + /** + * Evaluates \a input string validity according to QRegularExpression + * and ability to be converted in double value. + */ + QValidator::State validate( QString &input ) const; + + /** + * Converts \a input string to double value. + * It used locale interpretation first + * and C locale interpretation as fallback + */ + static double toDouble( const QString &input, bool *ok ) SIP_SKIP; + + /** + * Converts \a input string to double value. + * It used locale interpretation first + * and C locale interpretation as fallback + */ + static double toDouble( const QString &input ); + + /** + * Set top range limit + * \see setTop + * \see setRange + */ + void setBottom( double bottom ) { mMinimum = bottom; } + + /** + * Set top range limit + * \see setBottom + * \see setRange + */ + void setTop( double top ) { mMaximum = top; } + + /** + * Set bottom and top range limits + * \see setBottom + * \see setTop + */ + virtual void setRange( double bottom, double top ) + { + mMinimum = bottom; + mMaximum = top; + } + + /** + * Returns top range limit + * \see setBottom + */ + double bottom() const { return mMinimum; } + + /** + * Returns top range limit + * \see setTop + */ + double top() const { return mMaximum; } + + private: + // Disables copy constructing + Q_DISABLE_COPY( QgsDoubleValidator ) + + /** + * Bottom range limit + */ + double mMinimum; + + /** + * Top range limit + */ + double mMaximum; +}; + +#endif // QGSDOUBLEVALIDATOR_H diff --git a/src/gui/qgsexpressionpreviewwidget.cpp b/src/gui/qgsexpressionpreviewwidget.cpp index 75a4acbda150..6c8d6943e568 100644 --- a/src/gui/qgsexpressionpreviewwidget.cpp +++ b/src/gui/qgsexpressionpreviewwidget.cpp @@ -55,10 +55,13 @@ void QgsExpressionPreviewWidget::setCurrentFeature( const QgsFeature &feature ) QgsFeature validFeature( feature ); validFeature.setValid( true ); mExpressionContext.setFeature( validFeature ); + mFeaturePickerWidget->setEnabled( false ); + mFeaturePickerWidget->setToolTip( tr( "No feature was found on this layer to evaluate the expression." ) ); } else { mExpressionContext.setFeature( feature ); + mFeaturePickerWidget->setEnabled( true ); } refreshPreview(); } diff --git a/src/gui/qgsfeaturepickerwidget.cpp b/src/gui/qgsfeaturepickerwidget.cpp index eb8a6c37e748..b87494f5b512 100644 --- a/src/gui/qgsfeaturepickerwidget.cpp +++ b/src/gui/qgsfeaturepickerwidget.cpp @@ -81,7 +81,6 @@ QgsFeaturePickerWidget::QgsFeaturePickerWidget( QWidget *parent ) mComboBox->setModel( mModel ); connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeaturePickerWidget::onCurrentTextChanged ); - } QgsVectorLayer *QgsFeaturePickerWidget::layer() const diff --git a/src/gui/qgsfieldmappingmodel.cpp b/src/gui/qgsfieldmappingmodel.cpp index 2ba69f1d2214..08784ecbe417 100644 --- a/src/gui/qgsfieldmappingmodel.cpp +++ b/src/gui/qgsfieldmappingmodel.cpp @@ -24,7 +24,7 @@ QgsFieldMappingModel::QgsFieldMappingModel( const QgsFields &sourceFields, QObject *parent ) : QAbstractTableModel( parent ) , mSourceFields( sourceFields ) - , mExpressionContextGenerator( new ExpressionContextGenerator( &mSourceFields ) ) + , mExpressionContextGenerator( new ExpressionContextGenerator( mSourceFields ) ) { setDestinationFields( destinationFields, expressions ); } @@ -494,7 +494,7 @@ bool QgsFieldMappingModel::moveDown( const QModelIndex &index ) return moveUpOrDown( index, false ); } -QgsFieldMappingModel::ExpressionContextGenerator::ExpressionContextGenerator( const QgsFields *sourceFields ) +QgsFieldMappingModel::ExpressionContextGenerator::ExpressionContextGenerator( const QgsFields &sourceFields ) : mSourceFields( sourceFields ) { } @@ -505,7 +505,7 @@ QgsExpressionContext QgsFieldMappingModel::ExpressionContextGenerator::createExp { QgsExpressionContext ctx = mBaseGenerator->createExpressionContext(); std::unique_ptr< QgsExpressionContextScope > fieldMappingScope = qgis::make_unique< QgsExpressionContextScope >( tr( "Field Mapping" ) ); - fieldMappingScope->setFields( *mSourceFields ); + fieldMappingScope->setFields( mSourceFields ); ctx.appendScope( fieldMappingScope.release() ); return ctx; } @@ -513,8 +513,8 @@ QgsExpressionContext QgsFieldMappingModel::ExpressionContextGenerator::createExp { QgsExpressionContext ctx; ctx.appendScope( QgsExpressionContextUtils::globalScope() ); - ctx.setFields( *mSourceFields ); - QgsFeature feature { *mSourceFields }; + ctx.setFields( mSourceFields ); + QgsFeature feature { mSourceFields }; feature.setValid( true ); ctx.setFeature( feature ); return ctx; diff --git a/src/gui/qgsfieldmappingmodel.h b/src/gui/qgsfieldmappingmodel.h index cff626313f23..82a05f3b3497 100644 --- a/src/gui/qgsfieldmappingmodel.h +++ b/src/gui/qgsfieldmappingmodel.h @@ -160,7 +160,7 @@ class GUI_EXPORT QgsFieldMappingModel: public QAbstractTableModel public: - ExpressionContextGenerator( const QgsFields *sourceFields ); + ExpressionContextGenerator( const QgsFields &sourceFields ); // QgsExpressionContextGenerator interface QgsExpressionContext createExpressionContext() const override; @@ -170,7 +170,7 @@ class GUI_EXPORT QgsFieldMappingModel: public QAbstractTableModel const QgsExpressionContextGenerator *mBaseGenerator = nullptr; - const QgsFields *mSourceFields; + const QgsFields mSourceFields; }; diff --git a/src/gui/qgsfontbutton.cpp b/src/gui/qgsfontbutton.cpp index 23aedb0148ca..702b27e9baa9 100644 --- a/src/gui/qgsfontbutton.cpp +++ b/src/gui/qgsfontbutton.cpp @@ -38,7 +38,7 @@ QgsFontButton::QgsFontButton( QWidget *parent, const QString &dialogTitle ) : QToolButton( parent ) , mDialogTitle( dialogTitle.isEmpty() ? tr( "Text Format" ) : dialogTitle ) - + , mNullFormatString( tr( "No Format" ) ) { setText( tr( "Font" ) ); @@ -159,11 +159,21 @@ void QgsFontButton::setTextFormat( const QgsTextFormat &format ) emit changed(); } +void QgsFontButton::setToNullFormat() +{ + mFormat = QgsTextFormat(); + updatePreview(); + emit changed(); +} + void QgsFontButton::setColor( const QColor &color ) { QColor opaque = color; opaque.setAlphaF( 1.0 ); + if ( mNullFormatAction ) + mNullFormatAction->setChecked( false ); + if ( mFormat.color() != opaque ) { mFormat.setColor( opaque ); @@ -521,6 +531,17 @@ void QgsFontButton::prepareMenu() //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless mMenu->clear(); + if ( mMode == ModeTextRenderer && mShowNoFormat ) + { + mNullFormatAction = new QAction( mNullFormatString, this ); + mMenu->addAction( mNullFormatAction ); + connect( mNullFormatAction, &QAction::triggered, this, &QgsFontButton::setToNullFormat ); + if ( !mFormat.isValid() ) + { + mNullFormatAction->setCheckable( true ); + mNullFormatAction->setChecked( true ); + } + } QWidgetAction *sizeAction = new QWidgetAction( mMenu ); QWidget *sizeWidget = new QWidget(); @@ -555,6 +576,8 @@ void QgsFontButton::prepareMenu() switch ( mMode ) { case ModeTextRenderer: + if ( mNullFormatAction ) + mNullFormatAction->setChecked( false ); mFormat.setSize( value ); break; case ModeQFont: @@ -672,6 +695,8 @@ void QgsFontButton::prepareMenu() double opacity = color.alphaF(); mFormat.setOpacity( opacity ); updatePreview(); + if ( mNullFormatAction ) + mNullFormatAction->setChecked( false ); emit changed(); } ); connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor & color ) { alphaRamp->setColor( color, false ); } @@ -796,6 +821,12 @@ void QgsFontButton::resizeEvent( QResizeEvent *event ) void QgsFontButton::updatePreview( const QColor &color, QgsTextFormat *format, QFont *font ) { + if ( mShowNoFormat && !mFormat.isValid() ) + { + setIcon( QPixmap() ); + return; + } + QgsTextFormat tempFormat; QFont tempFont; @@ -867,6 +898,7 @@ void QgsFontButton::updatePreview( const QColor &color, QgsTextFormat *format, Q context.setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 ); context.setUseAdvancedEffects( true ); + context.setFlag( QgsRenderContext::Antialiasing, true ); context.setPainter( &p ); // slightly inset text to account for buffer/background diff --git a/src/gui/qgsfontbutton.h b/src/gui/qgsfontbutton.h index 4e836f275372..79347bb39c0e 100644 --- a/src/gui/qgsfontbutton.h +++ b/src/gui/qgsfontbutton.h @@ -163,6 +163,45 @@ class GUI_EXPORT QgsFontButton : public QToolButton */ void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator ); + /** + * Sets whether the "null format" option should be shown in the button's drop-down menu. This option + * is only used for buttons set to the ModeTextRenderer mode(). + * + * If selected, the "null format" option sets the button's format to an invalid QgsTextFormat. This + * can be used to represent a "use default format" state for the button. + * + * By default this option is not shown. + * + * \see setNoFormatString() + * \see showNullFormat() + * \since QGIS 3.16 + */ + void setShowNullFormat( const bool show ) { mShowNoFormat = show; } + + /** + * Sets the \a string to use for the "null format" option in the button's drop-down menu. + * + * \note The "null format" option is only shown if showNullFormat() is TRUE. + * + * \see setShowNullFormat() + * \since QGIS 3.16 + */ + void setNoFormatString( const QString &string ) { mNullFormatString = string; } + + /** + * Returns whether the "null format" option will be shown in the button's drop-down menu. This option + * is only used for buttons set to the ModeTextRenderer mode(). + * + * If selected, the "null format" option sets the button's format to an invalid QgsTextFormat. This + * can be used to represent a "use default format" state for the button. + * + * By default this option is not shown. + * + * \see setShowNullFormat() + * \since QGIS 3.16 + */ + bool showNullFormat() const { return mShowNoFormat; } + public slots: /** @@ -172,6 +211,15 @@ class GUI_EXPORT QgsFontButton : public QToolButton */ void setTextFormat( const QgsTextFormat &format ); + /** + * Sets the text format to a null (invalid) QgsTextFormat. + * + * This is only used when mode() is ModeTextRenderer. + * + * \since QGIS 3.16 + */ + void setToNullFormat(); + /** * Sets the current text \a font to show in the widget. * This is only used when mode() is ModeQFont. @@ -278,6 +326,10 @@ class GUI_EXPORT QgsFontButton : public QToolButton QgsExpressionContextGenerator *mExpressionContextGenerator = nullptr; + bool mShowNoFormat = false; + QString mNullFormatString; + QPointer< QAction > mNullFormatAction; + /** * Attempts to parse \a mimeData as a text format. * \returns TRUE if mime data could be intrepreted as a format diff --git a/src/gui/qgsmapcanvas.cpp b/src/gui/qgsmapcanvas.cpp index f65ef53939fe..04e689c64fee 100644 --- a/src/gui/qgsmapcanvas.cpp +++ b/src/gui/qgsmapcanvas.cpp @@ -906,6 +906,8 @@ void QgsMapCanvas::showContextMenu( QgsMapMouseEvent *event ) if ( mMapTool ) mMapTool->populateContextMenu( mMenu ); + emit contextMenuAboutToShow( mMenu, event ); + mMenu->exec( event->globalPos() ); } diff --git a/src/gui/qgsmapcanvas.h b/src/gui/qgsmapcanvas.h index a870bf0e19ce..a868c0f02a6f 100644 --- a/src/gui/qgsmapcanvas.h +++ b/src/gui/qgsmapcanvas.h @@ -1034,11 +1034,21 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView /** * Emitted when the map canvas temporal range changes. - * - * \since QGIS 3.14 - */ + * + * \since QGIS 3.14 + */ void temporalRangeChanged(); + + /** + * Emitted before the map canvas context menu will be shown. + * Can be used to extend the context menu. + * + * \since QGIS 3.16 + */ + void contextMenuAboutToShow( QMenu *menu, QgsMapMouseEvent *event ); + + protected: bool event( QEvent *e ) override; diff --git a/src/gui/qgsmaptoolcapture.cpp b/src/gui/qgsmaptoolcapture.cpp index c9766d5f44ae..90ae22fd9901 100644 --- a/src/gui/qgsmaptoolcapture.cpp +++ b/src/gui/qgsmaptoolcapture.cpp @@ -318,7 +318,10 @@ bool QgsMapToolCapture::tracingAddVertex( const QgsPointXY &point ) if ( capabilities().testFlag( QgsMapToolCapture::Capability::SupportsCurves ) && vlayer->dataProvider()->capabilities().testFlag( QgsVectorDataProvider::Capability::CircularGeometries ) ) { QgsGeometry linear = QgsGeometry( mCaptureCurve.segmentize() ); - QgsGeometry curved = linear.convertToCurves(); + QgsGeometry curved = linear.convertToCurves( + settings.value( QStringLiteral( "/qgis/digitizing/convert_to_curve_angle_tolerance" ), 1e-6 ).toDouble(), + settings.value( QStringLiteral( "/qgis/digitizing/convert_to_curve_distance_tolerance" ), 1e-6 ).toDouble() + ); mCaptureCurve = *qgsgeometry_cast( curved.constGet() ); } } diff --git a/src/gui/qgsmaskingwidget.cpp b/src/gui/qgsmaskingwidget.cpp index 28620e9b1206..471e2acdd0c4 100644 --- a/src/gui/qgsmaskingwidget.cpp +++ b/src/gui/qgsmaskingwidget.cpp @@ -332,3 +332,8 @@ void QgsMaskingWidget::apply() layer->triggerRepaint(); } } + +bool QgsMaskingWidget::hasBeenPopulated() +{ + return !mMustPopulate; +} diff --git a/src/gui/qgsmaskingwidget.h b/src/gui/qgsmaskingwidget.h index 15eba6cf7248..e3ca7389a7d7 100644 --- a/src/gui/qgsmaskingwidget.h +++ b/src/gui/qgsmaskingwidget.h @@ -47,6 +47,9 @@ class GUI_EXPORT QgsMaskingWidget: public QgsPanelWidget, private Ui::QgsMasking //! Applies the changes void apply(); + //! Widget has been populated or not + bool hasBeenPopulated(); + signals: //! Emitted when a change is performed void widgetChanged(); diff --git a/src/gui/qgsmasksourceselectionwidget.cpp b/src/gui/qgsmasksourceselectionwidget.cpp index 8fc3d99241b0..25275fd67b63 100644 --- a/src/gui/qgsmasksourceselectionwidget.cpp +++ b/src/gui/qgsmasksourceselectionwidget.cpp @@ -67,8 +67,6 @@ QgsMaskSourceSelectionWidget::QgsMaskSourceSelectionWidget( QWidget *parent ) vbox->addWidget( mTree ); setLayout( vbox ); - - update(); } void QgsMaskSourceSelectionWidget::update() diff --git a/src/gui/qgsnewgeopackagelayerdialog.cpp b/src/gui/qgsnewgeopackagelayerdialog.cpp index e08371766a09..19968abc2a3f 100644 --- a/src/gui/qgsnewgeopackagelayerdialog.cpp +++ b/src/gui/qgsnewgeopackagelayerdialog.cpp @@ -51,6 +51,7 @@ QgsNewGeoPackageLayerDialog::QgsNewGeoPackageLayerDialog( QWidget *parent, Qt::W : QDialog( parent, fl ) { setupUi( this ); + setObjectName( QStringLiteral( "QgsNewGeoPackageLayerDialog" ) ); QgsGui::enableAutoGeometryRestore( this ); connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewGeoPackageLayerDialog::mAddAttributeButton_clicked ); diff --git a/src/gui/qgsnewmemorylayerdialog.cpp b/src/gui/qgsnewmemorylayerdialog.cpp index 4e69dfa52fda..64dbcee535c5 100644 --- a/src/gui/qgsnewmemorylayerdialog.cpp +++ b/src/gui/qgsnewmemorylayerdialog.cpp @@ -59,11 +59,15 @@ QgsNewMemoryLayerDialog::QgsNewMemoryLayerDialog( QWidget *parent, Qt::WindowFla mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconTableLayer.svg" ) ), tr( "No Geometry" ), QgsWkbTypes::NoGeometry ); mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Point ); - mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "LineString / CompoundCurve" ), QgsWkbTypes::LineString ); - mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon / CurvePolygon" ), QgsWkbTypes::Polygon ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "LineString" ), QgsWkbTypes::LineString ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "CompoundCurve" ), QgsWkbTypes::CompoundCurve ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon" ), QgsWkbTypes::Polygon ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "CurvePolygon" ), QgsWkbTypes::CurvePolygon ); mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "MultiPoint" ), QgsWkbTypes::MultiPoint ); - mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiLineString / MultiCurve" ), QgsWkbTypes::MultiLineString ); - mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiPolygon / MultiSurface" ), QgsWkbTypes::MultiPolygon ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiLineString" ), QgsWkbTypes::MultiLineString ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiCurve" ), QgsWkbTypes::MultiCurve ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiPolygon" ), QgsWkbTypes::MultiPolygon ); + mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiSurface" ), QgsWkbTypes::MultiSurface ); mGeometryTypeBox->setCurrentIndex( -1 ); mGeometryWithZCheckBox->setEnabled( false ); diff --git a/src/gui/qgsnewvectortabledialog.cpp b/src/gui/qgsnewvectortabledialog.cpp new file mode 100644 index 000000000000..d87818deed63 --- /dev/null +++ b/src/gui/qgsnewvectortabledialog.cpp @@ -0,0 +1,813 @@ +/*************************************************************************** + qgsnewvectortabledialog.cpp - QgsNewVectorTableDialog + + --------------------- + begin : 12.7.2020 + copyright : (C) 2020 by Alessandro Pasotti + email : elpaso at itopen dot it + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include "qgsnewvectortabledialog.h" +#include "qgsvectorlayer.h" +#include "qgslogger.h" +#include "qgsgui.h" +#include "qgsapplication.h" +#include +#include + +QgsNewVectorTableDialog::QgsNewVectorTableDialog( QgsAbstractDatabaseProviderConnection *conn, QWidget *parent ) + : QDialog( parent ) + , mConnection( conn ) +{ + + setupUi( this ); + + // This is a precondition for the dialog to work correctly + try + { + mFieldModel = new QgsNewVectorTableFieldModel( mConnection->nativeTypes(), this ); + } + catch ( QgsProviderConnectionException &ex ) + { + QMessageBox::critical( nullptr, tr( "Cannot Create New Tables" ), tr( "Error retrieving native types from the data provider: creation of new tables is not possible.\n" + "Error message: %1" ).arg( ex.what() ) ); + QTimer::singleShot( 0, [ = ] { reject(); } ); + return; + } + + Q_ASSERT( ! mFieldModel->nativeTypes().isEmpty() ); + + QgsGui::enableAutoGeometryRestore( this ); + setWindowTitle( tr( "New Table" ) ); + + auto updateTableNames = [ = ]( const QString &schema = QString( ) ) + { + mTableNames.clear(); + try + { + const auto constTables { conn->tables( schema ) }; + for ( const auto &tp : constTables ) + { + mTableNames.push_back( tp.tableName() ); + } + validate(); + } + catch ( QgsProviderConnectionException &ex ) + { + // This should never happen but it's not critical, we can safely continue. + QgsDebugMsg( QStringLiteral( "Error retrieving tables from connection: %1" ).arg( ex.what() ) ); + } + }; + + // Validate on data changed + connect( mFieldModel, &QgsNewVectorTableFieldModel::modelReset, this, [ = ]() + { + validate(); + } ); + + mTableName->setText( QStringLiteral( "new_table_name" ) ); + mFieldsTableView->setModel( mFieldModel ); + QgsNewVectorTableDialogFieldsDelegate *delegate { new QgsNewVectorTableDialogFieldsDelegate( mConnection->nativeTypes(), this )}; + mFieldsTableView->setItemDelegate( delegate ); + mFieldsTableView->setSelectionBehavior( QAbstractItemView::SelectionBehavior::SelectRows ); + mFieldsTableView->setSelectionMode( QAbstractItemView::SelectionMode::SingleSelection ); + mFieldsTableView->setVerticalHeader( nullptr ); + + // Cosmetics + mFieldsTableView->horizontalHeader()->setStretchLastSection( true ); + mFieldsTableView->setColumnWidth( QgsNewVectorTableFieldModel::ColumnHeaders::Type, 300 ); + + // Schema is not supported by all providers + if ( mConnection->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::Schemas ) ) + { + mSchemaCbo->addItems( mConnection->schemas() ); + connect( mSchemaCbo, qgis::overload::of( &QComboBox::currentIndexChanged ), this, [ = ]( const QString & schema ) + { + updateTableNames( schema ); + } ); + } + else + { + mSchemaCbo->hide(); + mSchemaLabel->hide(); + } + + if ( ! mConnection->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateSpatialIndex ) ) + { + mSpatialIndexChk->setChecked( false ); + mSpatialIndexChk->hide(); + mSpatialIndexLabel->hide(); + } + + // Initial load of table names + updateTableNames( mSchemaCbo->currentText() ); + + // Validators + connect( mTableName, &QLineEdit::textChanged, this, [ = ]( const QString & ) + { + validate(); + } ); + + connect( mGeomColumn, &QLineEdit::textChanged, this, [ = ]( const QString & ) + { + validate(); + } ); + + // Enable/disable geometry options and call validate + connect( mGeomTypeCbo, qgis::overload::of( &QComboBox::currentIndexChanged ), this, [ = ]( int index ) + { + const bool hasGeom { index != 0 }; + mGeomColumn->setEnabled( hasGeom ); + mGeomColumnLabel->setEnabled( hasGeom ); + mSpatialIndexChk->setEnabled( hasGeom ); + mSpatialIndexLabel->setEnabled( hasGeom ); + mCrs->setEnabled( hasGeom ); + mCrsLabel->setEnabled( hasGeom ); + mDimensionsLabel->setEnabled( hasGeom ); + mHasMChk->setEnabled( hasGeom ); + mHasZChk->setEnabled( hasGeom ); + validate(); + } ); + + // geometry types + const bool hasSinglePart { conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::SinglePart ) }; + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconTableLayer.svg" ) ), tr( "No Geometry" ), QgsWkbTypes::Type::NoGeometry ); + if ( hasSinglePart ) + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Type::Point ); + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPointLayer.svg" ) ), tr( "MultiPoint" ), QgsWkbTypes::Type::MultiPoint ); + if ( hasSinglePart ) + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "Line" ), QgsWkbTypes::Type::LineString ); + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "MultiLine" ), QgsWkbTypes::Type::MultiLineString ); + if ( hasSinglePart ) + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "Polygon" ), QgsWkbTypes::Type::Polygon ); + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "MultiPolygon" ), QgsWkbTypes::Type::MultiPolygon ); + + if ( conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::Curves ) ) + { + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "CompoundCurve" ), QgsWkbTypes::Type::CompoundCurve ); + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "CurvePolygon" ), QgsWkbTypes::Type::CurvePolygon ); + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "MultiCurve" ), QgsWkbTypes::Type::MultiCurve ); + mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "MultiSurface" ), QgsWkbTypes::Type::MultiSurface ); + } + + mGeomTypeCbo->setCurrentIndex( 0 ); + + const bool hasZ { conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::Z ) }; + const bool hasM { conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::M ) }; + if ( ! hasM ) + { + mHasMChk->setEnabled( false ); + mHasMChk->setChecked( false ); + } + if ( ! hasZ ) + { + mHasZChk->setEnabled( false ); + mHasZChk->setChecked( false ); + } + if ( ! hasM && ! hasM ) + { + mHasZChk->setVisible( false ); + mHasMChk->setVisible( false ); + mDimensionsLabel->setVisible( false ); + } + + connect( mFieldsTableView->selectionModel(), &QItemSelectionModel::selectionChanged, mFieldsTableView, [ = ]( const QItemSelection & selected, const QItemSelection & ) + { + if ( ! selected.isEmpty() ) + { + mCurrentRow = selected.indexes().first().row(); + } + updateButtons(); + } ); + + // Get a default type for new fields + const QVariant::Type defaultFieldType { mFieldModel->nativeTypes().first().mType }; + const QString defaultFieldTypeName { mFieldModel->nativeTypes().first().mTypeName }; + + // Actions + connect( mAddFieldBtn, &QPushButton::clicked, this, [ = ] + { + QgsFields fieldList { fields() }; + QgsField newField { QStringLiteral( "new_field_name" ), defaultFieldType, defaultFieldTypeName }; + fieldList.append( newField ); + setFields( fieldList ); + selectRow( fieldList.count() - 1 ); + } ); + + connect( mDeleteFieldBtn, &QPushButton::clicked, this, [ = ] + { + QgsFields fieldList { fields() }; + if ( fieldList.exists( mCurrentRow ) ) + { + fieldList.remove( mCurrentRow ); + setFields( fieldList ); + mCurrentRow = -1; + } + } ); + + connect( mFieldUpBtn, &QPushButton::clicked, this, [ = ] + { + if ( fields().exists( mCurrentRow ) && fields().exists( mCurrentRow - 1 ) ) + { + QgsFields fieldList; + for ( int i = 0; i < fields().count(); ++i ) + { + if ( i == mCurrentRow - 1 ) + { + fieldList.append( fields().at( mCurrentRow ) ); + fieldList.append( fields().at( mCurrentRow - 1 ) ); + } + else if ( i != mCurrentRow ) + { + fieldList.append( fields().at( i ) ); + } + } + setFields( fieldList ); + selectRow( mCurrentRow - 1 ); + } + } ); + + connect( mFieldDownBtn, &QPushButton::clicked, this, [ = ] + { + if ( fields().exists( mCurrentRow ) && fields().exists( mCurrentRow + 1 ) ) + { + QgsFields fieldList; + for ( int i = 0; i < fields().count(); ++i ) + { + if ( i == mCurrentRow ) + { + fieldList.append( fields().at( mCurrentRow + 1 ) ); + fieldList.append( fields().at( mCurrentRow ) ); + } + else if ( i != mCurrentRow + 1 ) + { + fieldList.append( fields().at( i ) ); + } + } + setFields( fieldList ); + selectRow( mCurrentRow + 1 ); + } + } ); + + updateButtons(); + validate(); +} + +void QgsNewVectorTableDialog::setSchemaName( const QString &name ) +{ + mSchemaCbo->setCurrentText( name ); +} + +void QgsNewVectorTableDialog::setTableName( const QString &name ) +{ + mTableName->setText( name ); +} + +void QgsNewVectorTableDialog::setGeometryType( QgsWkbTypes::Type type ) +{ + mGeomTypeCbo->setCurrentIndex( mGeomTypeCbo->findData( type ) ); +} + +void QgsNewVectorTableDialog::setCrs( const QgsCoordinateReferenceSystem &crs ) +{ + mCrs->setCrs( crs ); +} + +QgsCoordinateReferenceSystem QgsNewVectorTableDialog::crs() const +{ + return mCrs->crs( ); +} + +QString QgsNewVectorTableDialog::tableName() const +{ + return mTableName->text(); +} + +QString QgsNewVectorTableDialog::schemaName() const +{ + return mSchemaCbo->currentText(); +} + +QString QgsNewVectorTableDialog::geometryColumnName() const +{ + return mGeomColumn->text(); +} + +QgsFields QgsNewVectorTableDialog::fields() const +{ + return mFieldModel ? mFieldModel->fields() : QgsFields(); +} + +QgsWkbTypes::Type QgsNewVectorTableDialog::geometryType() const +{ + QgsWkbTypes::Type type { static_cast( mGeomTypeCbo->currentData( ).toInt() ) }; + if ( mHasMChk->isChecked() ) + { + type = QgsWkbTypes::addM( type ); + } + if ( mHasZChk->isChecked() ) + { + type = QgsWkbTypes::addZ( type ); + } + return type; +} + + +void QgsNewVectorTableDialog::setFields( const QgsFields &fields ) +{ + if ( mFieldModel ) + { + mFieldModel->setFields( fields ); + } +} + +bool QgsNewVectorTableDialog::createSpatialIndex() +{ + return mSpatialIndexChk->isChecked(); +} + +QStringList QgsNewVectorTableDialog::validationErrors() const +{ + return mValidationErrors; +} + +void QgsNewVectorTableDialog::updateButtons() +{ + mDeleteFieldBtn->setEnabled( mCurrentRow != -1 ); + mFieldUpBtn->setEnabled( mCurrentRow != -1 && mCurrentRow != 0 ); + mFieldDownBtn->setEnabled( mCurrentRow != -1 && mCurrentRow != fields().count() - 1 ); +} + +void QgsNewVectorTableDialog::selectRow( int row ) +{ + QModelIndex index { mFieldsTableView->model()->index( row, 0 ) }; + mFieldsTableView->setCurrentIndex( index ); + QItemSelectionModel::SelectionFlags flags { QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current }; + mFieldsTableView->selectionModel()->select( index, flags ); + mFieldsTableView->scrollTo( index ); +} + +void QgsNewVectorTableDialog::validate() +{ + mValidationErrors.clear(); + + const bool isSpatial { mGeomTypeCbo->currentIndex() > 0 }; + if ( mTableNames.contains( mTableName->text(), Qt::CaseSensitivity::CaseInsensitive ) ) + { + mValidationErrors.push_back( tr( "Table %1 already exists!" ).arg( mTableName->text() ) ); + } + // Check for field names and geom col name + if ( isSpatial && fields().names().contains( mGeomColumn->text(), Qt::CaseSensitivity::CaseInsensitive ) ) + { + mValidationErrors.push_back( tr( "Geometry column name %1 cannot be equal to an existing field name!" ).arg( mGeomColumn->text() ) ); + } + // No geometry and no fields? No party! + if ( ! isSpatial && fields().count() == 0 ) + { + mValidationErrors.push_back( tr( "The table has no geometry column and no fields!" ) ); + } + // Check if precision is <= length + const auto cFields { fields() }; + for ( const auto &f : cFields ) + { + if ( f.isNumeric() && f.length() >= 0 && f.precision() >= 0 && f.precision() > f.length() ) + { + mValidationErrors.push_back( tr( "Field %1: precision cannot be greater than length!" ).arg( f.name() ) ); + } + } + + const bool isValid { mValidationErrors.isEmpty() }; + if ( ! isValid ) + { + mValidationResults->setText( mValidationErrors.join( QStringLiteral( "
" ) ) ); + } + + mValidationFrame->setVisible( ! isValid ); + mButtonBox->button( QDialogButtonBox::StandardButton::Ok )->setEnabled( isValid ); +} + +void QgsNewVectorTableDialog::showEvent( QShowEvent *event ) +{ + QDialog::showEvent( event ); + mTableName->setFocus(); + mTableName->selectAll(); +} + + +/// @cond private + + +QgsNewVectorTableDialogFieldsDelegate::QgsNewVectorTableDialogFieldsDelegate( const QList &typeList, QObject *parent ) + : QStyledItemDelegate( parent ) + , mTypeList( typeList ) +{ + +} + +QWidget *QgsNewVectorTableDialogFieldsDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + switch ( index.column() ) + { + case QgsNewVectorTableFieldModel::ColumnHeaders::Type: + { + QComboBox *cbo = new QComboBox { parent }; + cbo->setEditable( false ); + cbo->setFrame( false ); + connect( cbo, qgis::overload::of( &QComboBox::currentIndexChanged ), this, &QgsNewVectorTableDialogFieldsDelegate::onFieldTypeChanged ); + for ( const auto &f : qgis::as_const( mTypeList ) ) + { + cbo->addItem( f.mTypeDesc, f.mTypeName ); + } + return cbo; + } + case QgsNewVectorTableFieldModel::ColumnHeaders::Precision: + { + QSpinBox *sp { new QSpinBox { parent } }; + const QgsNewVectorTableFieldModel *model { static_cast( index.model() )}; + if ( model ) + { + const QgsVectorDataProvider::NativeType nt { model->nativeType( index.row() ) }; + sp->setRange( nt.mMinPrec, std::min( nt.mMaxPrec, index.model()->data( index.model()->index( index.row(), index.column() - 1 ) ).toInt() ) ); + } + return sp; + } + case QgsNewVectorTableFieldModel::ColumnHeaders::Length: + { + QSpinBox *sp { new QSpinBox { parent } }; + const QgsNewVectorTableFieldModel *model { static_cast( index.model() )}; + if ( model ) + { + const QgsVectorDataProvider::NativeType nt { model->nativeType( index.row() ) }; + sp->setRange( std::max( nt.mMinLen, index.model()->data( index.model()->index( index.row(), index.column() + 1 ) ).toInt() ), nt.mMaxLen ); + } + return sp; + } + default: + { + return QStyledItemDelegate::createEditor( parent, option, index ); + } + } +} + +void QgsNewVectorTableDialogFieldsDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const +{ + const auto m { index.model() }; + switch ( index.column() ) + { + case QgsNewVectorTableFieldModel::ColumnHeaders::Type: + { + const QString txt = m->data( index, Qt::DisplayRole ).toString(); + QComboBox *cbo{ qobject_cast( editor ) }; + if ( cbo ) + { + cbo->setCurrentIndex( cbo->findText( txt ) ); + } + break; + } + case QgsNewVectorTableFieldModel::ColumnHeaders::Precision: + case QgsNewVectorTableFieldModel::ColumnHeaders::Length: + { + const int value = m->data( index, Qt::DisplayRole ).toInt(); + QSpinBox *sp{ qobject_cast( editor ) }; + if ( sp ) + { + sp->setValue( value ); + } + break; + } + default: + { + QStyledItemDelegate::setEditorData( editor, index ); + } + } +} + +void QgsNewVectorTableDialogFieldsDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const +{ + switch ( index.column() ) + { + case QgsNewVectorTableFieldModel::ColumnHeaders::Type: + { + QComboBox *cbo { qobject_cast( editor ) }; + if ( cbo ) + { + model->setData( index, cbo->currentData() ); + } + break; + } + default: + { + QStyledItemDelegate::setModelData( editor, model, index ); + } + } +} + +void QgsNewVectorTableDialogFieldsDelegate::onFieldTypeChanged( int index ) +{ + Q_UNUSED( index ) + QComboBox *cb = static_cast( sender() ); + if ( cb ) + { + emit commitData( cb ); + } +} + +QgsNewVectorTableFieldModel::QgsNewVectorTableFieldModel( const QList &typeList, QObject *parent ) + : QgsFieldModel( parent ) + , mNativeTypes( typeList ) +{ + +} + +int QgsNewVectorTableFieldModel::columnCount( const QModelIndex & ) const +{ + return 6; +} + +QVariant QgsNewVectorTableFieldModel::data( const QModelIndex &index, int role ) const +{ + if ( mFields.exists( index.row() ) ) + { + const QgsField field { mFields.at( index.row() ) }; + switch ( role ) + { + case Qt::ItemDataRole::DisplayRole: + { + switch ( static_cast( index.column() ) ) + { + case ColumnHeaders::Name: + { + return QgsFieldModel::data( index, role ); + } + case ColumnHeaders::Type: + { + return typeDesc( field.typeName() ); + } + case ColumnHeaders::ProviderType: + { + return field.typeName(); + } + case ColumnHeaders::Comment: + { + return field.comment(); + } + case ColumnHeaders::Precision: + { + return field.precision(); + } + case ColumnHeaders::Length: + { + return field.length(); + } + } + } + case Qt::ItemDataRole::TextAlignmentRole: + { + switch ( static_cast( index.column() ) ) + { + case ColumnHeaders::Precision: + case ColumnHeaders::Length: + { + return Qt::AlignmentFlag::AlignVCenter + Qt::AlignmentFlag::AlignHCenter; + } + default: + { + return QgsFieldModel::data( index, role ); + } + } + } + default: + { + if ( static_cast( index.column() ) == ColumnHeaders::Name ) + { + return QgsFieldModel::data( index, role ); + } + } + } + } + return QVariant(); +} + +QVariant QgsNewVectorTableFieldModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( orientation == Qt::Orientation::Horizontal ) + { + switch ( role ) + { + case Qt::ItemDataRole::DisplayRole: + { + switch ( static_cast( section ) ) + { + case ColumnHeaders::Name: + { + return tr( "Name" ); + } + case ColumnHeaders::Type: + { + return tr( "Type" ); + } + case ColumnHeaders::Comment: + { + return tr( "Comment" ); + } + case ColumnHeaders::ProviderType: + { + return tr( "Provider type" ); + } + case ColumnHeaders::Length: + { + return tr( "Length" ); + } + case ColumnHeaders::Precision: + { + return tr( "Precision" ); + } + default: + return QVariant(); + } + break; + } + case Qt::ItemDataRole::TextAlignmentRole: + { + switch ( static_cast( section ) ) + { + case ColumnHeaders::Name: + case ColumnHeaders::Comment: + case ColumnHeaders::Type: + case ColumnHeaders::ProviderType: + { + return Qt::AlignmentFlag::AlignVCenter + Qt::AlignmentFlag::AlignLeft; + } + default: + { + return Qt::AlignmentFlag::AlignVCenter + Qt::AlignmentFlag::AlignHCenter; + } + } + break; + } + default: + { + QgsFieldModel::headerData( section, orientation, role ); + } + } + } + return QVariant(); +} + +Qt::ItemFlags QgsNewVectorTableFieldModel::flags( const QModelIndex &index ) const +{ + switch ( static_cast( index.column() ) ) + { + case ColumnHeaders::Name: + case ColumnHeaders::Comment: + case ColumnHeaders::Type: + { + return QgsFieldModel::flags( index ) | Qt::ItemIsEditable; + } + case ColumnHeaders::Length: + { + if ( mFields.exists( index.row( ) ) ) + { + const QgsVectorDataProvider::NativeType nt { nativeType( mFields.at( index.row( ) ).typeName() ) }; + if ( nt.mMinLen < nt.mMaxLen ) + { + return QgsFieldModel::flags( index ) | Qt::ItemIsEditable; + } + } + break; + } + case ColumnHeaders::Precision: + { + if ( mFields.exists( index.row( ) ) ) + { + const QgsVectorDataProvider::NativeType nt { nativeType( mFields.at( index.row( ) ).typeName() ) }; + if ( nt.mMinPrec < nt.mMaxPrec ) + { + return QgsFieldModel::flags( index ) | Qt::ItemIsEditable; + } + } + break; + } + case ColumnHeaders::ProviderType: + { + return QgsFieldModel::flags( index ); + } + } + return QgsFieldModel::flags( index ); +} + +QList QgsNewVectorTableFieldModel::nativeTypes() const +{ + return mNativeTypes; +} + +QString QgsNewVectorTableFieldModel::typeDesc( const QString &typeName ) const +{ + for ( const auto &t : qgis::as_const( mNativeTypes ) ) + { + if ( t.mTypeName.compare( typeName, Qt::CaseSensitivity::CaseInsensitive ) == 0 ) + { + return t.mTypeDesc; + } + } + return typeName; +} + +QVariant::Type QgsNewVectorTableFieldModel::type( const QString &typeName ) const +{ + return nativeType( typeName ).mType; +} + +QgsVectorDataProvider::NativeType QgsNewVectorTableFieldModel::nativeType( const QString &typeName ) const +{ + for ( const auto &t : qgis::as_const( mNativeTypes ) ) + { + if ( t.mTypeName.compare( typeName, Qt::CaseSensitivity::CaseInsensitive ) == 0 ) + { + return t; + } + } + // This should never happen! + QgsDebugMsg( QStringLiteral( "Cannot get field native type for: %1" ).arg( typeName ) ); + return mNativeTypes.first(); +} + +QgsVectorDataProvider::NativeType QgsNewVectorTableFieldModel::nativeType( int row ) const +{ + if ( mFields.exists( row ) ) + { + return nativeType( mFields.at( row ).typeName() ); + } + // This should never happen! + QgsDebugMsg( QStringLiteral( "Cannot get field for row: %1" ).arg( row ) ); + return mNativeTypes.first(); +} + +bool QgsNewVectorTableFieldModel::setData( const QModelIndex &index, const QVariant &value, int role ) +{ + if ( role == Qt::ItemDataRole::EditRole && mFields.exists( index.row() ) && index.column() < 6 ) + { + const int fieldIdx { index.row() }; + QgsField field {mFields.at( fieldIdx )}; + switch ( static_cast( index.column() ) ) + { + case ColumnHeaders::Name: + { + field.setName( value.toString() ); + break; + } + case ColumnHeaders::Type: + { + field.setTypeName( value.toString() ); + const auto tp { nativeType( value.toString() ) }; + field.setType( tp.mType ); + field.setLength( std::max( std::min( field.length(), tp.mMaxLen ), tp.mMinLen ) ); + field.setPrecision( std::max( std::min( field.precision(), tp.mMaxPrec ), tp.mMinPrec ) ); + break; + } + case ColumnHeaders::Comment: + { + field.setComment( value.toString() ); + break; + } + case ColumnHeaders::ProviderType: + { + field.setTypeName( value.toString() ); + break; + } + case ColumnHeaders::Length: + { + field.setLength( value.toInt() ); + break; + } + case ColumnHeaders::Precision: + { + field.setPrecision( value.toInt() ); + break; + } + } + + QgsFields fields; + for ( int i = 0; i < mFields.count(); ++i ) + { + if ( i == fieldIdx ) + { + fields.append( field ); + } + else + { + fields.append( mFields.at( i ) ); + } + } + setFields( fields ); + } + return QgsFieldModel::setData( index, value, role ); +} + +/// @endcond diff --git a/src/gui/qgsnewvectortabledialog.h b/src/gui/qgsnewvectortabledialog.h new file mode 100644 index 000000000000..32b51e1afc2a --- /dev/null +++ b/src/gui/qgsnewvectortabledialog.h @@ -0,0 +1,210 @@ +/*************************************************************************** + qgsnewvectortabledialog.h - QgsNewVectorTableDialog + + --------------------- + begin : 12.7.2020 + copyright : (C) 2020 by Alessandro Pasotti + email : elpaso at itopen dot it + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef QGSNEWVECTORTABLEDIALOG_H +#define QGSNEWVECTORTABLEDIALOG_H + +#include + +#include "qgis_sip.h" +#include "qgis_gui.h" +#include "qgsfields.h" +#include "qgswkbtypes.h" +#include "qgsvectordataprovider.h" +#include "qgsfieldmodel.h" +#include "qgsabstractdatabaseproviderconnection.h" + +#include "ui_qgsnewvectortabledialogbase.h" + +class QgsNewVectorTableFieldModel; + +/** + * The QgsNewVectorTableDialog class is a provider-agnostic database vector + * and aspatial table designer dialog based on the connections API. + * + * It allows to design a new vector or aspatial database table by defining the schema + * (if supported by the provider) and table name, the list of QgsFields, + * the optional geometry type and SRID. + * + * The actual creation of the table is delegated to the connections API method + * QgsAbstractDatabaseProviderConnection::createVectorTable() + * + * \ingroup gui + * \since QGIS 3.16 + */ +class GUI_EXPORT QgsNewVectorTableDialog : public QDialog, private Ui_QgsNewVectorTableDialogBase +{ + public: + + /** + * QgsNewVectorTableDialog constructor + * \param connection DB connection, ownership is NOT transfered + * \param parent optional parent + */ + QgsNewVectorTableDialog( QgsAbstractDatabaseProviderConnection *conn, QWidget *parent SIP_TRANSFERTHIS = nullptr ); + + /** + * Sets the schema \a name + */ + void setSchemaName( const QString &name ); + + /** + * Sets the table \a name + */ + void setTableName( const QString &name ); + + /** + * Sets the geometry \a type + */ + void setGeometryType( QgsWkbTypes::Type type ); + + /** + * Sets the CRS to \a crs + */ + void setCrs( const QgsCoordinateReferenceSystem &crs ); + + /** + * Returns the CRS + */ + QgsCoordinateReferenceSystem crs() const; + + /** + * Returns the table name + */ + QString tableName() const; + + /** + * Returns the schema name + */ + QString schemaName() const; + + /** + * Returns the geometry column name + */ + QString geometryColumnName() const; + + /** + * Returns the fields + */ + QgsFields fields() const; + + /** + * Returns the geometry type + */ + QgsWkbTypes::Type geometryType() const; + + /** + * Sets the fields to \a fields + */ + void setFields( const QgsFields &fields ); + + /** + * Returns TRUE if spatialindex checkbox is cheched + * @return + */ + bool createSpatialIndex(); + + /** + * Returns the validation errors or an empty list if the dialog is valid + */ + QStringList validationErrors() const; + + private: + + QgsAbstractDatabaseProviderConnection *mConnection = nullptr; + QgsNewVectorTableFieldModel *mFieldModel = nullptr; + int mCurrentRow = -1; + // Used by validator + QStringList mTableNames; + QStringList mValidationErrors; + + void updateButtons(); + void selectRow( int row ); + void validate(); + + // QWidget interface + protected: + void showEvent( QShowEvent *event ) override; +}; + + + +/// @cond private + +#ifndef SIP_RUN +class QgsNewVectorTableDialogFieldsDelegate: public QStyledItemDelegate +{ + public: + + QgsNewVectorTableDialogFieldsDelegate( const QList< QgsVectorDataProvider::NativeType> &typeList, QObject *parent = nullptr ); + + // QAbstractItemDelegate interface + QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const override; + void setEditorData( QWidget *editor, const QModelIndex &index ) const override; + void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const override; + + public slots: + + void onFieldTypeChanged( int index ); + + private: + + const QList< QgsVectorDataProvider::NativeType> mTypeList; + +}; + + +class QgsNewVectorTableFieldModel: public QgsFieldModel +{ + + public: + + enum ColumnHeaders + { + Name, + Type, + ProviderType, + Length, + Precision, + Comment + }; + + QgsNewVectorTableFieldModel( const QList< QgsVectorDataProvider::NativeType> &nativeTypes, QObject *parent = nullptr ); + + // QAbstractItemModel interface + int columnCount( const QModelIndex & ) const override; + QVariant data( const QModelIndex &index, int role ) const override; + bool setData( const QModelIndex &index, const QVariant &value, int role ) override; + QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; + Qt::ItemFlags flags( const QModelIndex &index ) const override; + + QList nativeTypes() const; + QgsVectorDataProvider::NativeType nativeType( const QString &typeName ) const; + QgsVectorDataProvider::NativeType nativeType( int row ) const; + + private: + + const QList< QgsVectorDataProvider::NativeType> mNativeTypes; + QString typeDesc( const QString &typeName ) const; + QVariant::Type type( const QString &typeName ) const; + +}; + + +#endif + +/// @endcond + +#endif // QGSNEWVECTORTABLEDIALOG_H diff --git a/src/gui/qgsrelationeditorwidget.cpp b/src/gui/qgsrelationeditorwidget.cpp index b79eac1eb87e..76f673d4847c 100644 --- a/src/gui/qgsrelationeditorwidget.cpp +++ b/src/gui/qgsrelationeditorwidget.cpp @@ -872,6 +872,8 @@ void QgsRelationEditorWidget::toggleEditing( bool state ) if ( mNmRelation.isValid() ) mEditorContext.vectorLayerTools()->stopEditing( mNmRelation.referencedLayer() ); } + + updateButtons(); } void QgsRelationEditorWidget::saveEdits() @@ -952,6 +954,37 @@ bool QgsRelationEditorWidget::showSaveChildEditsButton() const return mSaveEditsButton->isVisible(); } +void QgsRelationEditorWidget::setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ) +{ + mLinkFeatureButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::Link ) ); + mUnlinkFeatureButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::Unlink ) ); + mSaveEditsButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::SaveChildEdits ) ); + mAddFeatureButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::AddChildFeature ) ); + mDuplicateFeatureButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::DuplicateChildFeature ) ); + mDeleteFeatureButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::DeleteChildFeature ) ); + mZoomToFeatureButton->setVisible( buttons.testFlag( QgsAttributeEditorRelation::Button::ZoomToChildFeature ) ); +} + +QgsAttributeEditorRelation::Buttons QgsRelationEditorWidget::visibleButtons() const +{ + QgsAttributeEditorRelation::Buttons buttons; + if ( mLinkFeatureButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::Link; + if ( mUnlinkFeatureButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::Unlink; + if ( mSaveEditsButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::SaveChildEdits; + if ( mAddFeatureButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::AddChildFeature; + if ( mDuplicateFeatureButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::DuplicateChildFeature; + if ( mDeleteFeatureButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::DeleteChildFeature; + if ( mZoomToFeatureButton->isVisible() ) + buttons |= QgsAttributeEditorRelation::Button::ZoomToChildFeature; + return buttons; +} + void QgsRelationEditorWidget::setShowUnlinkButton( bool showUnlinkButton ) { mUnlinkFeatureButton->setVisible( showUnlinkButton ); diff --git a/src/gui/qgsrelationeditorwidget.h b/src/gui/qgsrelationeditorwidget.h index 912153c78f8b..6e4ee697f61d 100644 --- a/src/gui/qgsrelationeditorwidget.h +++ b/src/gui/qgsrelationeditorwidget.h @@ -97,9 +97,11 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox Q_OBJECT Q_PROPERTY( QgsDualView::ViewMode viewMode READ viewMode WRITE setViewMode ) Q_PROPERTY( bool showLabel READ showLabel WRITE setShowLabel ) + Q_PROPERTY( QgsAttributeEditorRelation::Buttons visibleButtons READ visibleButtons WRITE setVisibleButtons ) public: + /** * \param parent parent widget */ @@ -167,45 +169,57 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox /** * Determines if the "link feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showLinkButton() const; + Q_DECL_DEPRECATED bool showLinkButton() const SIP_DEPRECATED; /** * Determines if the "link feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowLinkButton( bool showLinkButton ); + Q_DECL_DEPRECATED void setShowLinkButton( bool showLinkButton ) SIP_DEPRECATED; /** * Determines if the "unlink feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showUnlinkButton() const; + Q_DECL_DEPRECATED bool showUnlinkButton() const SIP_DEPRECATED; /** * Determines if the "unlink feature" button should be shown - * * \since QGIS 2.18 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowUnlinkButton( bool showUnlinkButton ); + Q_DECL_DEPRECATED void setShowUnlinkButton( bool showUnlinkButton ) SIP_DEPRECATED; /** * Determines if the "Save child layer edits" button should be shown - * * \since QGIS 3.14 + * \deprecated since QGIS 3.16 use setVisibleButtons() instead */ - void setShowSaveChildEditsButton( bool showChildEdits ); + Q_DECL_DEPRECATED void setShowSaveChildEditsButton( bool showChildEdits ) SIP_DEPRECATED; /** * Determines if the "Save child layer edits" button should be shown - * * \since QGIS 3.14 + * \deprecated since QGIS 3.16 use visibleButtons() instead */ - bool showSaveChildEditsButton() const; + Q_DECL_DEPRECATED bool showSaveChildEditsButton() const SIP_DEPRECATED; + + /** + * Defines the buttons which are shown + * \since QGIS 3.16 + */ + void setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons ); + + /** + * Returns the buttons which are shown + * \since QGIS 3.16 + */ + QgsAttributeEditorRelation::Buttons visibleButtons() const; /** * Returns the widget's current feature @@ -294,4 +308,5 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox void unlinkFeatures( const QgsFeatureIds &featureids ); }; + #endif // QGSRELATIONEDITOR_H diff --git a/src/gui/qgstextpreview.cpp b/src/gui/qgstextpreview.cpp index a2d152275ee2..b69336ce2dbb 100644 --- a/src/gui/qgstextpreview.cpp +++ b/src/gui/qgstextpreview.cpp @@ -30,6 +30,8 @@ QgsTextPreview::QgsTextPreview( QWidget *parent ) mContext.setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 ); mContext.setUseAdvancedEffects( true ); + mContext.setFlag( QgsRenderContext::Antialiasing, true ); + mContext.setIsGuiPreview( true ); } diff --git a/src/gui/raster/qgscolorrampshaderwidget.cpp b/src/gui/raster/qgscolorrampshaderwidget.cpp index 21195aa1bc83..ff3dae003204 100644 --- a/src/gui/raster/qgscolorrampshaderwidget.cpp +++ b/src/gui/raster/qgscolorrampshaderwidget.cpp @@ -142,7 +142,7 @@ QgsColorRampShader QgsColorRampShaderWidget::shader() const continue; } QgsColorRampShader::ColorRampItem newColorRampItem; - newColorRampItem.value = currentItem->text( ValueColumn ).toDouble(); + newColorRampItem.value = QLocale().toDouble( currentItem->text( ValueColumn ) ); newColorRampItem.color = currentItem->data( ColorColumn, Qt::EditRole ).value(); newColorRampItem.label = currentItem->text( LabelColumn ); colorRampItems.append( newColorRampItem ); @@ -181,7 +181,7 @@ void QgsColorRampShaderWidget::autoLabel() { label = "<= " + currentItem->text( ValueColumn ) + unit; } - else if ( currentItem->text( ValueColumn ).toDouble() == std::numeric_limits::infinity() ) + else if ( QLocale().toDouble( currentItem->text( ValueColumn ) ) == std::numeric_limits::infinity() ) { label = "> " + mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) + unit; } @@ -330,7 +330,7 @@ void QgsColorRampShaderWidget::classify() for ( ; it != colorRampItemList.end(); ++it ) { QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget ); - newItem->setText( ValueColumn, QString::number( it->value, 'g', 15 ) ); + newItem->setText( ValueColumn, QLocale().toString( it->value, 'g', 15 ) ); newItem->setData( ColorColumn, Qt::EditRole, it->color ); newItem->setText( LabelColumn, QString() ); // Labels will be populated in autoLabel() newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable ); @@ -386,7 +386,7 @@ void QgsColorRampShaderWidget::applyColorRamp() continue; } - double value = currentItem->text( ValueColumn ).toDouble(); + double value = QLocale().toDouble( currentItem->text( ValueColumn ) ); double position = ( value - mMin ) / ( mMax - mMin ); whileBlocking( static_cast( currentItem ) )->setData( ColorColumn, Qt::EditRole, ramp->color( position ) ); } @@ -406,7 +406,7 @@ void QgsColorRampShaderWidget::populateColormapTreeWidget( const QListsetText( ValueColumn, QString::number( it->value, 'g', 15 ) ); + newItem->setText( ValueColumn, QLocale().toString( it->value, 'g', 15 ) ); newItem->setData( ColorColumn, Qt::EditRole, it->color ); newItem->setText( LabelColumn, it->label ); newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable ); @@ -492,7 +492,7 @@ void QgsColorRampShaderWidget::mLoadFromFileButton_clicked() inputStringComponents = inputLine.split( ',' ); if ( inputStringComponents.size() == 6 ) { - QgsColorRampShader::ColorRampItem currentItem( inputStringComponents[0].toDouble(), + QgsColorRampShader::ColorRampItem currentItem( QLocale().toDouble( inputStringComponents[0] ), QColor::fromRgb( inputStringComponents[1].toInt(), inputStringComponents[2].toInt(), inputStringComponents[3].toInt(), inputStringComponents[4].toInt() ), inputStringComponents[5] ); @@ -570,7 +570,7 @@ void QgsColorRampShaderWidget::mExportToFileButton_clicked() continue; } color = currentItem->data( ColorColumn, Qt::EditRole ).value(); - outputStream << currentItem->text( ValueColumn ).toDouble() << ','; + outputStream << QLocale().toDouble( currentItem->text( ValueColumn ) ) << ','; outputStream << color.red() << ',' << color.green() << ',' << color.blue() << ',' << color.alpha() << ','; if ( currentItem->text( LabelColumn ).isEmpty() ) { @@ -737,9 +737,9 @@ void QgsColorRampShaderWidget::loadMinimumMaximumFromTree() return; } - double min = item->text( ValueColumn ).toDouble(); + double min = QLocale().toDouble( item->text( ValueColumn ) ); item = mColormapTreeWidget->topLevelItem( mColormapTreeWidget->topLevelItemCount() - 1 ); - double max = item->text( ValueColumn ).toDouble(); + double max = QLocale().toDouble( item->text( ValueColumn ) ); if ( !qgsDoubleNear( mMin, min ) || !qgsDoubleNear( mMax, max ) ) { diff --git a/src/gui/raster/qgsmultibandcolorrendererwidget.cpp b/src/gui/raster/qgsmultibandcolorrendererwidget.cpp index 80a9708313dc..cc09d701e4c7 100644 --- a/src/gui/raster/qgsmultibandcolorrendererwidget.cpp +++ b/src/gui/raster/qgsmultibandcolorrendererwidget.cpp @@ -20,6 +20,7 @@ #include "qgsrasterlayer.h" #include "qgsrasterdataprovider.h" #include "qgsrasterminmaxwidget.h" +#include "qgsdoublevalidator.h" QgsMultiBandColorRendererWidget::QgsMultiBandColorRendererWidget( QgsRasterLayer *layer, const QgsRectangle &extent ) : QgsRasterRendererWidget( layer, extent ) @@ -119,12 +120,12 @@ void QgsMultiBandColorRendererWidget::setMapCanvas( QgsMapCanvas *canvas ) void QgsMultiBandColorRendererWidget::createValidators() { - mRedMinLineEdit->setValidator( new QDoubleValidator( mRedMinLineEdit ) ); - mRedMaxLineEdit->setValidator( new QDoubleValidator( mRedMinLineEdit ) ); - mGreenMinLineEdit->setValidator( new QDoubleValidator( mGreenMinLineEdit ) ); - mGreenMaxLineEdit->setValidator( new QDoubleValidator( mGreenMinLineEdit ) ); - mBlueMinLineEdit->setValidator( new QDoubleValidator( mBlueMinLineEdit ) ); - mBlueMaxLineEdit->setValidator( new QDoubleValidator( mBlueMinLineEdit ) ); + mRedMinLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) ); + mRedMaxLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) ); + mGreenMinLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) ); + mGreenMaxLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) ); + mBlueMinLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) ); + mBlueMaxLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) ); } void QgsMultiBandColorRendererWidget::setCustomMinMaxValues( QgsMultiBandColorRenderer *r, @@ -150,8 +151,8 @@ void QgsMultiBandColorRendererWidget::setCustomMinMaxValues( QgsMultiBandColorRe QgsContrastEnhancement *blueEnhancement = nullptr; bool redMinOk, redMaxOk; - double redMin = mRedMinLineEdit->text().toDouble( &redMinOk ); - double redMax = mRedMaxLineEdit->text().toDouble( &redMaxOk ); + double redMin = QgsDoubleValidator::toDouble( mRedMinLineEdit->text(), &redMinOk ); + double redMax = QgsDoubleValidator::toDouble( mRedMaxLineEdit->text(), &redMaxOk ); if ( redMinOk && redMaxOk && redBand != -1 ) { redEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )( @@ -161,8 +162,8 @@ void QgsMultiBandColorRendererWidget::setCustomMinMaxValues( QgsMultiBandColorRe } bool greenMinOk, greenMaxOk; - double greenMin = mGreenMinLineEdit->text().toDouble( &greenMinOk ); - double greenMax = mGreenMaxLineEdit->text().toDouble( &greenMaxOk ); + double greenMin = QgsDoubleValidator::toDouble( mGreenMinLineEdit->text(), &greenMinOk ); + double greenMax = QgsDoubleValidator::toDouble( mGreenMaxLineEdit->text(), &greenMaxOk ); if ( greenMinOk && greenMaxOk && greenBand != -1 ) { greenEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )( @@ -172,8 +173,8 @@ void QgsMultiBandColorRendererWidget::setCustomMinMaxValues( QgsMultiBandColorRe } bool blueMinOk, blueMaxOk; - double blueMin = mBlueMinLineEdit->text().toDouble( &blueMinOk ); - double blueMax = mBlueMaxLineEdit->text().toDouble( &blueMaxOk ); + double blueMin = QgsDoubleValidator::toDouble( mBlueMinLineEdit->text(), &blueMinOk ); + double blueMax = QgsDoubleValidator::toDouble( mBlueMaxLineEdit->text(), &blueMaxOk ); if ( blueMinOk && blueMaxOk && blueBand != -1 ) { blueEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )( @@ -292,7 +293,7 @@ void QgsMultiBandColorRendererWidget::loadMinMax( int bandNo, double min, double } else { - myMinLineEdit->setText( QString::number( min ) ); + myMinLineEdit->setText( QLocale().toString( min ) ); } if ( std::isnan( max ) ) @@ -301,7 +302,7 @@ void QgsMultiBandColorRendererWidget::loadMinMax( int bandNo, double min, double } else { - myMaxLineEdit->setText( QString::number( max ) ); + myMaxLineEdit->setText( QLocale().toString( max ) ); } mDisableMinMaxWidgetRefresh = false; } @@ -320,8 +321,8 @@ void QgsMultiBandColorRendererWidget::setMinMaxValue( const QgsContrastEnhanceme return; } - minEdit->setText( QString::number( ce->minimumValue() ) ); - maxEdit->setText( QString::number( ce->maximumValue() ) ); + minEdit->setText( QLocale().toString( ce->minimumValue() ) ); + maxEdit->setText( QLocale().toString( ce->maximumValue() ) ); // QgsMultiBandColorRenderer is using individual contrast enhancements for each // band, but this widget GUI has one for all diff --git a/src/gui/raster/qgspalettedrendererwidget.cpp b/src/gui/raster/qgspalettedrendererwidget.cpp index e7f51d55a01e..39c99d92c031 100644 --- a/src/gui/raster/qgspalettedrendererwidget.cpp +++ b/src/gui/raster/qgspalettedrendererwidget.cpp @@ -727,7 +727,7 @@ bool QgsPalettedRendererModel::insertRows( int row, int count, const QModelIndex beginInsertRows( QModelIndex(), row, row + count - 1 ); for ( int i = row; i < row + count; ++i, ++nextValue ) { - mData.insert( i, QgsPalettedRasterRenderer::Class( nextValue, QColor( 200, 200, 200 ), QString::number( nextValue ) ) ); + mData.insert( i, QgsPalettedRasterRenderer::Class( nextValue, QColor( 200, 200, 200 ), QLocale().toString( nextValue ) ) ); } endInsertRows(); emit classesChanged(); diff --git a/src/gui/raster/qgsrasterhistogramwidget.cpp b/src/gui/raster/qgsrasterhistogramwidget.cpp index d1b1e5624972..2a394fb306e8 100644 --- a/src/gui/raster/qgsrasterhistogramwidget.cpp +++ b/src/gui/raster/qgsrasterhistogramwidget.cpp @@ -22,6 +22,7 @@ #include "qgsrasterhistogramwidget.h" #include "qgsrasterminmaxwidget.h" #include "qgsrasterdataprovider.h" +#include "qgsdoublevalidator.h" #include "qgssettings.h" #include @@ -104,8 +105,8 @@ QgsRasterHistogramWidget::QgsRasterHistogramWidget( QgsRasterLayer *lyr, QWidget } // histo min/max selectors - leHistoMin->setValidator( new QDoubleValidator( this ) ); - leHistoMax->setValidator( new QDoubleValidator( this ) ); + leHistoMin->setValidator( new QgsDoubleValidator( this ) ); + leHistoMax->setValidator( new QgsDoubleValidator( this ) ); // this might generate many refresh events! test.. // connect( leHistoMin, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateHistoMarkers() ) ); // connect( leHistoMax, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateHistoMarkers() ) ); diff --git a/src/gui/raster/qgsrasterlayerproperties.cpp b/src/gui/raster/qgsrasterlayerproperties.cpp index 68d5d2172c11..0e11969dacfa 100644 --- a/src/gui/raster/qgsrasterlayerproperties.cpp +++ b/src/gui/raster/qgsrasterlayerproperties.cpp @@ -60,6 +60,7 @@ #include "qgsprovidermetadata.h" #include "qgsproviderregistry.h" #include "qgsrasterlayertemporalproperties.h" +#include "qgsdoublevalidator.h" #include "qgsrasterlayertemporalpropertieswidget.h" #include "qgsprojecttimesettings.h" @@ -191,7 +192,7 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanv chkUseScaleDependentRendering->setChecked( lyr->hasScaleBasedVisibility() ); mScaleRangeWidget->setScaleRange( lyr->minimumScale(), lyr->maximumScale() ); - leNoDataValue->setValidator( new QDoubleValidator( -std::numeric_limits::max(), std::numeric_limits::max(), 1000, this ) ); + leNoDataValue->setValidator( new QgsDoubleValidator( -std::numeric_limits::max(), std::numeric_limits::max(), 1000, this ) ); // build GUI components QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) ); @@ -786,7 +787,8 @@ void QgsRasterLayerProperties::sync() // TODO: no data ranges if ( provider->sourceHasNoDataValue( 1 ) ) { - lblSrcNoDataValue->setText( QgsRasterBlock::printValue( provider->sourceNoDataValue( 1 ) ) ); + double v = QgsRasterBlock::printValue( provider->sourceNoDataValue( 1 ) ).toDouble(); + lblSrcNoDataValue->setText( QLocale().toString( v, 'g' ) ); } else { @@ -943,7 +945,7 @@ void QgsRasterLayerProperties::apply() if ( "" != leNoDataValue->text() ) { bool myDoubleOk = false; - double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk ); + double myNoDataValue = QgsDoubleValidator::toDouble( leNoDataValue->text(), &myDoubleOk ); if ( myDoubleOk ) { QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue ); @@ -1604,17 +1606,18 @@ void QgsRasterLayerProperties::setTransparencyCell( int row, int column, double { case Qgis::Float32: case Qgis::Float64: - lineEdit->setValidator( new QDoubleValidator( nullptr ) ); + lineEdit->setValidator( new QgsDoubleValidator( nullptr ) ); if ( !std::isnan( value ) ) { - valueString = QgsRasterBlock::printValue( value ); + double v = QgsRasterBlock::printValue( value ).toDouble(); + valueString = QLocale().toString( v, 'g' ) ; } break; default: lineEdit->setValidator( new QIntValidator( nullptr ) ); if ( !std::isnan( value ) ) { - valueString = QString::number( static_cast( value ) ); + valueString = QLocale().toString( static_cast( value ) ); } break; } @@ -1634,7 +1637,8 @@ void QgsRasterLayerProperties::setTransparencyCellValue( int row, int column, do { QLineEdit *lineEdit = dynamic_cast( tableTransparency->cellWidget( row, column ) ); if ( !lineEdit ) return; - lineEdit->setText( QgsRasterBlock::printValue( value ) ); + double v = QgsRasterBlock::printValue( value ).toDouble(); + lineEdit->setText( QLocale().toString( v, 'g' ) ); lineEdit->adjustSize(); adjustTransparencyCellWidth( row, column ); tableTransparency->resizeColumnsToContents(); diff --git a/src/gui/raster/qgsrastertransparencywidget.cpp b/src/gui/raster/qgsrastertransparencywidget.cpp index 929c783f3c81..a68d696416b2 100644 --- a/src/gui/raster/qgsrastertransparencywidget.cpp +++ b/src/gui/raster/qgsrastertransparencywidget.cpp @@ -13,7 +13,6 @@ * * ***************************************************************************/ #include -#include #include #include #include @@ -33,6 +32,7 @@ #include "qgsmapcanvas.h" #include "qgsrasteridentifyresult.h" #include "qgsmultibandcolorrenderer.h" +#include "qgsdoublevalidator.h" QgsRasterTransparencyWidget::QgsRasterTransparencyWidget( QgsRasterLayer *layer, QgsMapCanvas *canvas, QWidget *parent ) @@ -120,7 +120,8 @@ void QgsRasterTransparencyWidget::syncToLayer() QgsDebugMsg( QStringLiteral( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) ); if ( !noDataRangeList.isEmpty() ) { - leNoDataValue->setText( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ) ); + double v = QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ).toDouble(); + leNoDataValue->setText( QLocale().toString( v ) ); } else { @@ -395,7 +396,7 @@ void QgsRasterTransparencyWidget::apply() if ( "" != leNoDataValue->text() ) { bool myDoubleOk = false; - double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk ); + double myNoDataValue = QgsDoubleValidator::toDouble( leNoDataValue->text(), &myDoubleOk ); if ( myDoubleOk ) { QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue ); @@ -635,10 +636,11 @@ void QgsRasterTransparencyWidget::setTransparencyCell( int row, int column, doub { case Qgis::Float32: case Qgis::Float64: - lineEdit->setValidator( new QDoubleValidator( nullptr ) ); + lineEdit->setValidator( new QgsDoubleValidator( nullptr ) ); if ( !std::isnan( value ) ) { - valueString = QgsRasterBlock::printValue( value ); + double v = QgsRasterBlock::printValue( value ).toDouble(); + valueString = QLocale().toString( v ); } break; default: @@ -690,6 +692,6 @@ double QgsRasterTransparencyWidget::transparencyCellValue( int row, int column ) { return std::numeric_limits::quiet_NaN(); } - return lineEdit->text().toDouble(); + return QgsDoubleValidator::toDouble( lineEdit->text() ); } diff --git a/src/gui/raster/qgssinglebandgrayrendererwidget.cpp b/src/gui/raster/qgssinglebandgrayrendererwidget.cpp index f7a41feaf317..c299e8913887 100644 --- a/src/gui/raster/qgssinglebandgrayrendererwidget.cpp +++ b/src/gui/raster/qgssinglebandgrayrendererwidget.cpp @@ -20,6 +20,7 @@ #include "qgsrasterlayer.h" #include "qgsrasterdataprovider.h" #include "qgsrasterminmaxwidget.h" +#include "qgsdoublevalidator.h" QgsSingleBandGrayRendererWidget::QgsSingleBandGrayRendererWidget( QgsRasterLayer *layer, const QgsRectangle &extent ) : QgsRasterRendererWidget( layer, extent ) @@ -32,8 +33,8 @@ QgsSingleBandGrayRendererWidget::QgsSingleBandGrayRendererWidget( QgsRasterLayer mGradientComboBox->insertItem( 0, tr( "Black to white" ), QgsSingleBandGrayRenderer::BlackToWhite ); mGradientComboBox->insertItem( 1, tr( "White to black" ), QgsSingleBandGrayRenderer::WhiteToBlack ); - mMinLineEdit->setValidator( new QDoubleValidator( mMinLineEdit ) ); - mMaxLineEdit->setValidator( new QDoubleValidator( mMaxLineEdit ) ); + mMinLineEdit->setValidator( new QgsDoubleValidator( mMinLineEdit ) ); + mMaxLineEdit->setValidator( new QgsDoubleValidator( mMaxLineEdit ) ); if ( mRasterLayer ) { @@ -89,8 +90,8 @@ QgsRasterRenderer *QgsSingleBandGrayRendererWidget::renderer() QgsContrastEnhancement *e = new QgsContrastEnhancement( ( Qgis::DataType )( provider->dataType( band ) ) ); - e->setMinimumValue( mMinLineEdit->text().toDouble() ); - e->setMaximumValue( mMaxLineEdit->text().toDouble() ); + e->setMinimumValue( QgsDoubleValidator::toDouble( mMinLineEdit->text() ) ); + e->setMaximumValue( QgsDoubleValidator::toDouble( mMaxLineEdit->text() ) ); e->setContrastEnhancementAlgorithm( ( QgsContrastEnhancement::ContrastEnhancementAlgorithm )( mContrastEnhancementComboBox->currentData().toInt() ) ); QgsSingleBandGrayRenderer *renderer = new QgsSingleBandGrayRenderer( provider, band ); @@ -151,7 +152,7 @@ void QgsSingleBandGrayRendererWidget::loadMinMax( int bandNo, double min, double } else { - mMinLineEdit->setText( QString::number( min ) ); + mMinLineEdit->setText( QLocale().toString( min ) ); } if ( std::isnan( max ) ) @@ -160,7 +161,7 @@ void QgsSingleBandGrayRendererWidget::loadMinMax( int bandNo, double min, double } else { - mMaxLineEdit->setText( QString::number( max ) ); + mMaxLineEdit->setText( QLocale().toString( max ) ); } mDisableMinMaxWidgetRefresh = false; } @@ -188,8 +189,8 @@ void QgsSingleBandGrayRendererWidget::setFromRenderer( const QgsRasterRenderer * { //minmax mDisableMinMaxWidgetRefresh = true; - mMinLineEdit->setText( QString::number( ce->minimumValue() ) ); - mMaxLineEdit->setText( QString::number( ce->maximumValue() ) ); + mMinLineEdit->setText( QLocale().toString( ce->minimumValue() ) ); + mMaxLineEdit->setText( QLocale().toString( ce->maximumValue() ) ); mDisableMinMaxWidgetRefresh = false; //contrast enhancement algorithm mContrastEnhancementComboBox->setCurrentIndex( diff --git a/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp b/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp index df75b13c1469..88b3ce7e6535 100644 --- a/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp +++ b/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp @@ -21,6 +21,7 @@ #include "qgsrasterdataprovider.h" #include "qgsrastershader.h" #include "qgsrasterminmaxwidget.h" +#include "qgsdoublevalidator.h" #include "qgstreewidgetitem.h" #include "qgssettings.h" #include "qgsmapcanvas.h" @@ -67,8 +68,8 @@ QgsSingleBandPseudoColorRendererWidget::QgsSingleBandPseudoColorRendererWidget( } // Must be before adding items to mBandComboBox (signal) - mMinLineEdit->setValidator( new QDoubleValidator( mMinLineEdit ) ); - mMaxLineEdit->setValidator( new QDoubleValidator( mMaxLineEdit ) ); + mMinLineEdit->setValidator( new QgsDoubleValidator( mMinLineEdit ) ); + mMaxLineEdit->setValidator( new QgsDoubleValidator( mMaxLineEdit ) ); mMinMaxWidget = new QgsRasterMinMaxWidget( layer, this ); mMinMaxWidget->setExtent( extent ); @@ -192,7 +193,7 @@ void QgsSingleBandPseudoColorRendererWidget::loadMinMax( int bandNo, double min, } else { - whileBlocking( mMinLineEdit )->setText( QString::number( min ) ); + whileBlocking( mMinLineEdit )->setText( QLocale().toString( min ) ); } if ( std::isnan( max ) ) @@ -201,13 +202,13 @@ void QgsSingleBandPseudoColorRendererWidget::loadMinMax( int bandNo, double min, } else { - whileBlocking( mMaxLineEdit )->setText( QString::number( max ) ); + whileBlocking( mMaxLineEdit )->setText( QLocale().toString( max ) ); } // We compare old min and new min as text because QString::number keeps a fixed number of significant // digits (default 6) and so loaded min/max will always differ from current one, which triggers a // classification, and wipe out every user modification (see https://github.com/qgis/QGIS/issues/36172) - if ( mMinLineEdit->text() != QString::number( min ) || mMaxLineEdit->text() != QString::number( max ) ) + if ( mMinLineEdit->text() != QLocale().toString( min ) || mMaxLineEdit->text() != QLocale().toString( max ) ) { whileBlocking( mColorRampShaderWidget )->setRasterBand( bandNo ); whileBlocking( mColorRampShaderWidget )->setMinimumMaximumAndClassify( min, max ); @@ -217,8 +218,8 @@ void QgsSingleBandPseudoColorRendererWidget::loadMinMax( int bandNo, double min, void QgsSingleBandPseudoColorRendererWidget::loadMinMaxFromTree( double min, double max ) { - whileBlocking( mMinLineEdit )->setText( QString::number( min ) ); - whileBlocking( mMaxLineEdit )->setText( QString::number( max ) ); + whileBlocking( mMinLineEdit )->setText( QLocale().toString( min ) ); + whileBlocking( mMaxLineEdit )->setText( QLocale().toString( max ) ); minMaxModified(); } @@ -228,7 +229,7 @@ void QgsSingleBandPseudoColorRendererWidget::setLineEditValue( QLineEdit *lineEd QString s; if ( !std::isnan( value ) ) { - s = QString::number( value ); + s = QLocale().toString( value ); } lineEdit->setText( s ); } @@ -240,7 +241,7 @@ double QgsSingleBandPseudoColorRendererWidget::lineEditValue( const QLineEdit *l return std::numeric_limits::quiet_NaN(); } - return lineEdit->text().toDouble(); + return QgsDoubleValidator::toDouble( lineEdit->text() ); } void QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textEdited( const QString & ) diff --git a/src/gui/tableeditor/qgstableeditordialog.cpp b/src/gui/tableeditor/qgstableeditordialog.cpp index d0f26e8db553..e32e45a42dd6 100644 --- a/src/gui/tableeditor/qgstableeditordialog.cpp +++ b/src/gui/tableeditor/qgstableeditordialog.cpp @@ -64,7 +64,7 @@ QgsTableEditorDialog::QgsTableEditorDialog( QWidget *parent ) int minDockWidth( fontMetrics().boundingRect( QStringLiteral( "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ).width() ); - mPropertiesDock = new QgsDockWidget( tr( "Formatting" ), this ); + mPropertiesDock = new QgsDockWidget( tr( "Cell Contents" ), this ); mPropertiesDock->setObjectName( QStringLiteral( "FormattingDock" ) ); mPropertiesStack = new QgsPanelWidgetStack(); mPropertiesDock->setWidget( mPropertiesStack ); @@ -78,6 +78,16 @@ QgsTableEditorDialog::QgsTableEditorDialog( QWidget *parent ) connect( mFormattingWidget, &QgsTableEditorFormattingWidget::foregroundColorChanged, mTableWidget, &QgsTableEditorWidget::setSelectionForegroundColor ); connect( mFormattingWidget, &QgsTableEditorFormattingWidget::backgroundColorChanged, mTableWidget, &QgsTableEditorWidget::setSelectionBackgroundColor ); + + connect( mFormattingWidget, &QgsTableEditorFormattingWidget::horizontalAlignmentChanged, mTableWidget, &QgsTableEditorWidget::setSelectionHorizontalAlignment ); + connect( mFormattingWidget, &QgsTableEditorFormattingWidget::verticalAlignmentChanged, mTableWidget, &QgsTableEditorWidget::setSelectionVerticalAlignment ); + connect( mFormattingWidget, &QgsTableEditorFormattingWidget::cellPropertyChanged, mTableWidget, &QgsTableEditorWidget::setSelectionCellProperty ); + + connect( mFormattingWidget, &QgsTableEditorFormattingWidget::textFormatChanged, this, [ = ] + { + mTableWidget->setSelectionTextFormat( mFormattingWidget->textFormat() ); + } ); + connect( mFormattingWidget, &QgsTableEditorFormattingWidget::numberFormatChanged, this, [ = ] { mTableWidget->setSelectionNumericFormat( mFormattingWidget->numericFormat() ); @@ -92,6 +102,10 @@ QgsTableEditorDialog::QgsTableEditorDialog( QWidget *parent ) mFormattingWidget->setNumericFormat( mTableWidget->selectionNumericFormat(), mTableWidget->hasMixedSelectionNumericFormat() ); mFormattingWidget->setRowHeight( mTableWidget->selectionRowHeight() ); mFormattingWidget->setColumnWidth( mTableWidget->selectionColumnWidth() ); + mFormattingWidget->setTextFormat( mTableWidget->selectionTextFormat() ); + mFormattingWidget->setHorizontalAlignment( mTableWidget->selectionHorizontalAlignment() ); + mFormattingWidget->setVerticalAlignment( mTableWidget->selectionVerticalAlignment() ); + mFormattingWidget->setCellProperty( mTableWidget->selectionCellProperty() ); updateActionNamesFromSelection(); @@ -213,6 +227,11 @@ void QgsTableEditorDialog::setTableHeaders( const QVariantList &headers ) mTableWidget->setTableHeaders( headers ); } +void QgsTableEditorDialog::registerExpressionContextGenerator( QgsExpressionContextGenerator *generator ) +{ + mFormattingWidget->registerExpressionContextGenerator( generator ); +} + void QgsTableEditorDialog::updateActionNamesFromSelection() { const int rowCount = mTableWidget->rowsAssociatedWithSelection().size(); diff --git a/src/gui/tableeditor/qgstableeditordialog.h b/src/gui/tableeditor/qgstableeditordialog.h index 06486383f24e..a438d9200b33 100644 --- a/src/gui/tableeditor/qgstableeditordialog.h +++ b/src/gui/tableeditor/qgstableeditordialog.h @@ -25,6 +25,7 @@ class QgsMessageBar; class QgsDockWidget; class QgsPanelWidgetStack; class QgsTableEditorFormattingWidget; +class QgsExpressionContextGenerator; /** * \ingroup gui @@ -134,6 +135,13 @@ class GUI_EXPORT QgsTableEditorDialog : public QMainWindow, private Ui::QgsTable */ void setTableHeaders( const QVariantList &headers ); + /** + * Register an expression context generator class that will be used to retrieve + * an expression context for the editor when required. + * \since QGIS 3.16 + */ + void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator ); + signals: /** diff --git a/src/gui/tableeditor/qgstableeditorformattingwidget.cpp b/src/gui/tableeditor/qgstableeditorformattingwidget.cpp index 0effd17152ae..2123a0d7efcf 100644 --- a/src/gui/tableeditor/qgstableeditorformattingwidget.cpp +++ b/src/gui/tableeditor/qgstableeditorformattingwidget.cpp @@ -17,15 +17,19 @@ #include "qgsnumericformatselectorwidget.h" #include "qgsnumericformat.h" #include "qgis.h" +#include "qgsproperty.h" QgsTableEditorFormattingWidget::QgsTableEditorFormattingWidget( QWidget *parent ) : QgsPanelWidget( parent ) { setupUi( this ); - setPanelTitle( tr( "Formatting" ) ); + setPanelTitle( tr( "Cell Contents" ) ); mFormatNumbersCheckBox->setTristate( false ); + mFontButton->setShowNullFormat( true ); + mFontButton->setNoFormatString( tr( "Clear Formatting" ) ); + mTextColorButton->setAllowOpacity( true ); mTextColorButton->setColorDialogTitle( tr( "Text Color" ) ); mTextColorButton->setDefaultColor( QColor( 0, 0, 0 ) ); @@ -35,6 +39,9 @@ QgsTableEditorFormattingWidget::QgsTableEditorFormattingWidget( QWidget *parent mBackgroundColorButton->setDefaultColor( QColor( 255, 255, 255 ) ); mBackgroundColorButton->setShowNull( true ); + mHorizontalAlignComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight | Qt::AlignJustify ); + mVerticalAlignComboBox->setAvailableAlignments( Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom ); + mRowHeightSpinBox->setClearValue( 0, tr( "Automatic" ) ); mColumnWidthSpinBox->setClearValue( 0, tr( "Automatic" ) ); @@ -68,6 +75,12 @@ QgsTableEditorFormattingWidget::QgsTableEditorFormattingWidget( QWidget *parent emit numberFormatChanged(); } ); + connect( mFontButton, &QgsFontButton::changed, this, [ = ] + { + if ( !mBlockSignals ) + emit textFormatChanged(); + } ); + mCustomizeFormatButton->setEnabled( false ); connect( mCustomizeFormatButton, &QPushButton::clicked, this, [ = ] { @@ -104,6 +117,35 @@ QgsTableEditorFormattingWidget::QgsTableEditorFormattingWidget( QWidget *parent mBlockSignals--; } } ); + + connect( mHorizontalAlignComboBox, &QgsAlignmentComboBox::changed, this, [ = ] + { + if ( !mBlockSignals ) + { + emit horizontalAlignmentChanged( mHorizontalAlignComboBox->currentAlignment() ); + } + } ); + + connect( mVerticalAlignComboBox, &QgsAlignmentComboBox::changed, this, [ = ] + { + if ( !mBlockSignals ) + { + emit verticalAlignmentChanged( mVerticalAlignComboBox->currentAlignment() ); + } + } ); + + connect( mExpressionEdit, qgis::overload::of( &QgsFieldExpressionWidget::fieldChanged ), this, [ = ]( const QString & expression ) + { + if ( !mBlockSignals ) + { + emit cellPropertyChanged( expression.isEmpty() ? QgsProperty() : QgsProperty::fromExpression( expression ) ); + } + } ); + + mExpressionEdit->setAllowEmptyFieldName( true ); + + mExpressionEdit->registerExpressionContextGenerator( this ); + mFontButton->registerExpressionContextGenerator( this ); } QgsNumericFormat *QgsTableEditorFormattingWidget::numericFormat() @@ -114,6 +156,11 @@ QgsNumericFormat *QgsTableEditorFormattingWidget::numericFormat() return mNumericFormat->clone(); } +QgsTextFormat QgsTableEditorFormattingWidget::textFormat() const +{ + return mFontButton->textFormat(); +} + void QgsTableEditorFormattingWidget::setForegroundColor( const QColor &color ) { mBlockSignals++; @@ -137,6 +184,13 @@ void QgsTableEditorFormattingWidget::setNumericFormat( QgsNumericFormat *format, mBlockSignals--; } +void QgsTableEditorFormattingWidget::setTextFormat( const QgsTextFormat &format ) +{ + mBlockSignals++; + mFontButton->setTextFormat( format ); + mBlockSignals--; +} + void QgsTableEditorFormattingWidget::setRowHeight( double height ) { mBlockSignals++; @@ -159,4 +213,55 @@ void QgsTableEditorFormattingWidget::setColumnWidth( double width ) mBlockSignals--; } +void QgsTableEditorFormattingWidget::setHorizontalAlignment( Qt::Alignment alignment ) +{ + mBlockSignals++; + if ( alignment & Qt::AlignHorizontal_Mask && alignment & Qt::AlignVertical_Mask ) + mHorizontalAlignComboBox->setCurrentIndex( -1 ); + else + mHorizontalAlignComboBox->setCurrentAlignment( alignment ); + mBlockSignals--; +} + +void QgsTableEditorFormattingWidget::setVerticalAlignment( Qt::Alignment alignment ) +{ + mBlockSignals++; + if ( alignment & Qt::AlignHorizontal_Mask && alignment & Qt::AlignVertical_Mask ) + mVerticalAlignComboBox->setCurrentIndex( -1 ); + else + mVerticalAlignComboBox->setCurrentAlignment( alignment ); + mBlockSignals--; +} + +void QgsTableEditorFormattingWidget::setCellProperty( const QgsProperty &property ) +{ + mBlockSignals++; + if ( !property.isActive() ) + mExpressionEdit->setExpression( QString() ); + else + mExpressionEdit->setExpression( property.asExpression() ); + mBlockSignals--; +} + +void QgsTableEditorFormattingWidget::registerExpressionContextGenerator( QgsExpressionContextGenerator *generator ) +{ + mContextGenerator = generator; +} + +QgsExpressionContext QgsTableEditorFormattingWidget::createExpressionContext() const +{ + QgsExpressionContext context; + if ( mContextGenerator ) + context = mContextGenerator->createExpressionContext(); + + QgsExpressionContextScope *cellScope = new QgsExpressionContextScope(); + // TODO -- could set real row/column numbers here, in certain circumstances... + cellScope->setVariable( QStringLiteral( "row_number" ), 0 ); + cellScope->setVariable( QStringLiteral( "column_number" ), 0 ); + context.appendScope( cellScope ); + + context.setHighlightedVariables( QStringList() << QStringLiteral( "row_number" ) << QStringLiteral( "column_number" ) ); + return context; +} + QgsTableEditorFormattingWidget::~QgsTableEditorFormattingWidget() = default; diff --git a/src/gui/tableeditor/qgstableeditorformattingwidget.h b/src/gui/tableeditor/qgstableeditorformattingwidget.h index 1d83757a7307..cbe416c7cf8b 100644 --- a/src/gui/tableeditor/qgstableeditorformattingwidget.h +++ b/src/gui/tableeditor/qgstableeditorformattingwidget.h @@ -18,11 +18,13 @@ #include "qgis_gui.h" #include "ui_qgstableeditorformattingwidgetbase.h" #include "qgspanelwidget.h" +#include "qgsexpressioncontextgenerator.h" #include #define SIP_NO_FILE class QgsNumericFormat; +class QgsProperty; /** * \ingroup gui @@ -36,7 +38,7 @@ class QgsNumericFormat; * * \since QGIS 3.12 */ -class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, private Ui::QgsTableEditorFormattingWidgetBase +class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, public QgsExpressionContextGenerator, private Ui::QgsTableEditorFormattingWidgetBase { Q_OBJECT public: @@ -57,6 +59,14 @@ class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, private */ QgsNumericFormat *numericFormat() SIP_TRANSFERBACK; + /** + * Returns the current text format shown in the widget. + * + * \see setTextFormat() + * \since QGIS 3.16 + */ + QgsTextFormat textFormat() const; + /** * Sets the cell foreground \a color to show in the widget. * @@ -82,6 +92,14 @@ class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, private */ void setNumericFormat( QgsNumericFormat *format, bool isMixedFormat ); + /** + * Sets the text \a format to show in the widget. + * + * \see textFormat() + * \since QGIS 3.16 + */ + void setTextFormat( const QgsTextFormat &format ); + /** * Sets the row \a height to show in the widget, or 0 for automatic height. * @@ -98,6 +116,42 @@ class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, private */ void setColumnWidth( double width ); + /** + * Sets the horizontal \a alignment to show in the widget. + * + * \see horizontalAlignmentChanged() + * \see setVerticalAlignment() + * + * \since QGIS 3.16 + */ + void setHorizontalAlignment( Qt::Alignment alignment ); + + /** + * Sets the vertical \a alignment to show in the widget. + * + * \see verticalAlignmentChanged() + * \see setHorizontalAlignment() + * + * \since QGIS 3.16 + */ + void setVerticalAlignment( Qt::Alignment alignment ); + + /** + * Sets the cell content's \a property to show in the widget. + * + * \since QGIS 3.16 + */ + void setCellProperty( const QgsProperty &property ); + + /** + * Register an expression context generator class that will be used to retrieve + * an expression context for the widget when required. + * \since QGIS 3.16 + */ + void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator ); + + QgsExpressionContext createExpressionContext() const override; + signals: /** @@ -119,6 +173,13 @@ class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, private */ void numberFormatChanged(); + /** + * Emitted whenever the text format shown in the widget is changed. + * + * \since QGIS 3.16 + */ + void textFormatChanged(); + /** * Emitted whenever the row \a height shown in the widget is changed. */ @@ -129,10 +190,32 @@ class GUI_EXPORT QgsTableEditorFormattingWidget : public QgsPanelWidget, private */ void columnWidthChanged( double width ); + /** + * Emitted when the horizontal \a alignment shown in the widget is changed. + * + * \since QGIS 3.16 + */ + void horizontalAlignmentChanged( Qt::Alignment alignment ); + + /** + * Emitted when the vertical \a alignment shown in the widget is changed. + * + * \since QGIS 3.16 + */ + void verticalAlignmentChanged( Qt::Alignment alignment ); + + /** + * Emitted when the cell contents \a property shown in the widget is changed. + * + * \since QGIS 3.16 + */ + void cellPropertyChanged( const QgsProperty &property ); + private: std::unique_ptr< QgsNumericFormat > mNumericFormat; int mBlockSignals = 0; + QgsExpressionContextGenerator *mContextGenerator = nullptr; }; diff --git a/src/gui/tableeditor/qgstableeditorwidget.cpp b/src/gui/tableeditor/qgstableeditorwidget.cpp index 9678eddba277..d0a868e5d6a6 100644 --- a/src/gui/tableeditor/qgstableeditorwidget.cpp +++ b/src/gui/tableeditor/qgstableeditorwidget.cpp @@ -320,11 +320,19 @@ void QgsTableEditorWidget::setTableContents( const QgsTableContents &contents ) int colNumber = 0; for ( const QgsTableCell &col : row ) { - QTableWidgetItem *item = new QTableWidgetItem( col.content().toString() ); + QTableWidgetItem *item = new QTableWidgetItem( col.content().value< QgsProperty >().isActive() ? col.content().value< QgsProperty >().asExpression() : col.content().toString() ); item->setData( CellContent, col.content() ); // can't use EditRole, because Qt. (https://bugreports.qt.io/browse/QTBUG-11549) item->setData( Qt::BackgroundRole, col.backgroundColor().isValid() ? col.backgroundColor() : QColor( 255, 255, 255 ) ); item->setData( PresetBackgroundColorRole, col.backgroundColor().isValid() ? col.backgroundColor() : QVariant() ); item->setData( Qt::ForegroundRole, col.foregroundColor().isValid() ? col.foregroundColor() : QVariant() ); + item->setData( TextFormat, QVariant::fromValue( col.textFormat() ) ); + item->setData( HorizontalAlignment, static_cast< int >( col.horizontalAlignment() ) ); + item->setData( VerticalAlignment, static_cast< int >( col.verticalAlignment() ) ); + item->setData( CellProperty, QVariant::fromValue( col.content().value< QgsProperty >() ) ); + + if ( col.content().value< QgsProperty >().isActive() ) + item->setFlags( item->flags() & ( ~Qt::ItemIsEditable ) ); + if ( col.numericFormat() ) { mNumericFormats.insert( item, col.numericFormat()->clone() ); @@ -362,9 +370,12 @@ QgsTableContents QgsTableEditorWidget::tableContents() const QgsTableCell cell; if ( QTableWidgetItem *i = item( r, c ) ) { - cell.setContent( i->data( CellContent ) ); + cell.setContent( i->data( CellProperty ).value< QgsProperty >().isActive() ? i->data( CellProperty ) : i->data( CellContent ) ); cell.setBackgroundColor( i->data( PresetBackgroundColorRole ).value< QColor >() ); cell.setForegroundColor( i->data( Qt::ForegroundRole ).value< QColor >() ); + cell.setTextFormat( i->data( TextFormat ).value< QgsTextFormat >() ); + cell.setHorizontalAlignment( static_cast< Qt::Alignment >( i->data( HorizontalAlignment ).toInt() ) ); + cell.setVerticalAlignment( static_cast< Qt::Alignment >( i->data( VerticalAlignment ).toInt() ) ); if ( mNumericFormats.value( i ) ) { @@ -527,6 +538,99 @@ QColor QgsTableEditorWidget::selectionBackgroundColor() return c; } +Qt::Alignment QgsTableEditorWidget::selectionHorizontalAlignment() +{ + Qt::Alignment alignment = Qt::AlignLeft; + bool first = true; + const QModelIndexList selection = selectedIndexes(); + for ( const QModelIndex &index : selection ) + { + Qt::Alignment cellAlign = static_cast< Qt::Alignment >( model()->data( index, HorizontalAlignment ).toInt() ); + if ( first ) + { + alignment = cellAlign; + first = false; + } + else if ( cellAlign == alignment ) + continue; + else + { + return Qt::AlignLeft | Qt::AlignTop; + } + } + return alignment; +} + +Qt::Alignment QgsTableEditorWidget::selectionVerticalAlignment() +{ + Qt::Alignment alignment = Qt::AlignVCenter; + bool first = true; + const QModelIndexList selection = selectedIndexes(); + for ( const QModelIndex &index : selection ) + { + Qt::Alignment cellAlign = static_cast< Qt::Alignment >( model()->data( index, VerticalAlignment ).toInt() ); + if ( first ) + { + alignment = cellAlign; + first = false; + } + else if ( cellAlign == alignment ) + continue; + else + { + return Qt::AlignLeft | Qt::AlignTop; + } + } + return alignment; +} + +QgsProperty QgsTableEditorWidget::selectionCellProperty() +{ + QgsProperty property; + bool first = true; + const QModelIndexList selection = selectedIndexes(); + for ( const QModelIndex &index : selection ) + { + const QgsProperty cellProperty = model()->data( index, CellProperty ).value< QgsProperty >(); + if ( first ) + { + property = cellProperty; + first = false; + } + else if ( cellProperty == property ) + continue; + else + { + return QgsProperty(); + } + } + return property; +} + +QgsTextFormat QgsTableEditorWidget::selectionTextFormat() +{ + QgsTextFormat format; + bool first = true; + const QModelIndexList selection = selectedIndexes(); + for ( const QModelIndex &index : selection ) + { + if ( !model()->data( index, TextFormat ).isValid() ) + return QgsTextFormat(); + + QgsTextFormat cellFormat = model()->data( index, TextFormat ).value< QgsTextFormat >(); + if ( first ) + { + format = cellFormat; + first = false; + } + else if ( cellFormat == format ) + continue; + else + return QgsTextFormat(); + } + return format; +} + double QgsTableEditorWidget::selectionRowHeight() { double height = 0; @@ -908,6 +1012,147 @@ void QgsTableEditorWidget::setSelectionBackgroundColor( const QColor &color ) emit tableChanged(); } +void QgsTableEditorWidget::setSelectionHorizontalAlignment( Qt::Alignment alignment ) +{ + const QModelIndexList selection = selectedIndexes(); + bool changed = false; + mBlockSignals++; + for ( const QModelIndex &index : selection ) + { + if ( index.row() == 0 && mIncludeHeader ) + continue; + + if ( QTableWidgetItem *i = item( index.row(), index.column() ) ) + { + if ( static_cast< Qt::Alignment >( i->data( HorizontalAlignment ).toInt() ) != alignment ) + { + i->setData( HorizontalAlignment, static_cast< int >( alignment ) ); + changed = true; + } + } + else + { + QTableWidgetItem *newItem = new QTableWidgetItem(); + newItem->setData( HorizontalAlignment, static_cast< int >( alignment ) ); + setItem( index.row(), index.column(), newItem ); + changed = true; + } + } + mBlockSignals--; + if ( changed && !mBlockSignals ) + emit tableChanged(); +} + +void QgsTableEditorWidget::setSelectionVerticalAlignment( Qt::Alignment alignment ) +{ + const QModelIndexList selection = selectedIndexes(); + bool changed = false; + mBlockSignals++; + for ( const QModelIndex &index : selection ) + { + if ( index.row() == 0 && mIncludeHeader ) + continue; + + if ( QTableWidgetItem *i = item( index.row(), index.column() ) ) + { + if ( static_cast< Qt::Alignment >( i->data( HorizontalAlignment ).toInt() ) != alignment ) + { + i->setData( VerticalAlignment, static_cast< int >( alignment ) ); + changed = true; + } + } + else + { + QTableWidgetItem *newItem = new QTableWidgetItem(); + newItem->setData( VerticalAlignment, static_cast< int >( alignment ) ); + setItem( index.row(), index.column(), newItem ); + changed = true; + } + } + mBlockSignals--; + if ( changed && !mBlockSignals ) + emit tableChanged(); +} + +void QgsTableEditorWidget::setSelectionCellProperty( const QgsProperty &property ) +{ + const QModelIndexList selection = selectedIndexes(); + bool changed = false; + mBlockSignals++; + for ( const QModelIndex &index : selection ) + { + if ( index.row() == 0 && mIncludeHeader ) + continue; + + if ( QTableWidgetItem *i = item( index.row(), index.column() ) ) + { + if ( i->data( CellProperty ).value< QgsProperty >() != property ) + { + if ( property.isActive() ) + { + i->setData( CellProperty, QVariant::fromValue( property ) ); + i->setText( property.asExpression() ); + i->setFlags( i->flags() & ( ~Qt::ItemIsEditable ) ); + } + else + { + i->setData( CellProperty, QVariant() ); + i->setText( QString() ); + i->setFlags( i->flags() | Qt::ItemIsEditable ); + } + changed = true; + } + } + else + { + QTableWidgetItem *newItem = new QTableWidgetItem( property.asExpression() ); + if ( property.isActive() ) + { + newItem->setData( CellProperty, QVariant::fromValue( property ) ); + newItem->setFlags( newItem->flags() & ( ~Qt::ItemIsEditable ) ); + } + else + { + newItem->setData( CellProperty, QVariant() ); + newItem->setFlags( newItem->flags() | Qt::ItemIsEditable ); + } + setItem( index.row(), index.column(), newItem ); + changed = true; + } + } + mBlockSignals--; + if ( changed && !mBlockSignals ) + emit tableChanged(); +} + +void QgsTableEditorWidget::setSelectionTextFormat( const QgsTextFormat &format ) +{ + const QModelIndexList selection = selectedIndexes(); + bool changed = false; + mBlockSignals++; + for ( const QModelIndex &index : selection ) + { + if ( index.row() == 0 && mIncludeHeader ) + continue; + + if ( QTableWidgetItem *i = item( index.row(), index.column() ) ) + { + i->setData( TextFormat, QVariant::fromValue( format ) ); + changed = true; + } + else + { + QTableWidgetItem *newItem = new QTableWidgetItem(); + newItem->setData( TextFormat, QVariant::fromValue( format ) ); + setItem( index.row(), index.column(), newItem ); + changed = true; + } + } + mBlockSignals--; + if ( changed && !mBlockSignals ) + emit tableChanged(); +} + void QgsTableEditorWidget::setSelectionRowHeight( double height ) { bool changed = false; @@ -1185,7 +1430,7 @@ void QgsTableEditorDelegate::setModelData( QWidget *editor, QAbstractItemModel * if ( QgsTableEditorTextEdit *lineEdit = qobject_cast( editor ) ) { const QString text = lineEdit->toPlainText(); - if ( text != model->data( index, QgsTableEditorWidget::CellContent ).toString() ) + if ( text != model->data( index, QgsTableEditorWidget::CellContent ).toString() && !model->data( index, QgsTableEditorWidget::CellProperty ).value< QgsProperty >().isActive() ) { model->setData( index, text, QgsTableEditorWidget::CellContent ); model->setData( index, text, Qt::DisplayRole ); diff --git a/src/gui/tableeditor/qgstableeditorwidget.h b/src/gui/tableeditor/qgstableeditorwidget.h index 284dbdb04676..e0f0f4a5a938 100644 --- a/src/gui/tableeditor/qgstableeditorwidget.h +++ b/src/gui/tableeditor/qgstableeditorwidget.h @@ -20,6 +20,7 @@ #include "qgis_gui.h" #include "qgstablecell.h" +#include "qgsproperty.h" #include #include #include @@ -182,6 +183,45 @@ class GUI_EXPORT QgsTableEditorWidget : public QTableWidget */ QColor selectionBackgroundColor(); + /** + * Returns the horizontal alignment for the currently selected cells. + * + * If the returned value contains both horizontal and vertical alignment flags, then + * the selected cells have a mix of different horizontal alignments. + * + * \see selectionVerticalAlignment() + */ + Qt::Alignment selectionHorizontalAlignment(); + + /** + * Returns the horizontal alignment for the currently selected cells. + * + * If the returned value contains both horizontal and vertical alignment flags, then + * the selected cells have a mix of different vertical alignments. + * + * \see selectionVerticalAlignment() + */ + Qt::Alignment selectionVerticalAlignment(); + + /** + * Returns the QgsProperty used for the contents of the currently selected cells. + * + * If the returned value is a default constructed QgsProperty, then the selected + * cells have a mix of different properties. + * + * \since QGIS 3.16 + */ + QgsProperty selectionCellProperty(); + + /** + * Returns the text format for the currently selected cells. + * + * Returns an invalid QgsTextFormat if the selection has mixed text format. + * + * \since QGIS 3.16 + */ + QgsTextFormat selectionTextFormat(); + /** * Returns the height (in millimeters) of the rows associated with the current selection, * or 0 if an automatic row height is desired, or -1 if the selection has mixed row heights. @@ -335,6 +375,40 @@ class GUI_EXPORT QgsTableEditorWidget : public QTableWidget */ void setSelectionBackgroundColor( const QColor &color ); + /** + * Sets the horizontal alignment for the currently selected cells. + * + * \see selectionHorizontalAlignment() + * \see setSelectionVerticalAlignment() + * + * \since QGIS 3.16 + */ + void setSelectionHorizontalAlignment( Qt::Alignment alignment ); + + /** + * Sets the vertical alignment for the currently selected cells. + * + * \see selectionVerticalAlignment() + * \see setSelectionHorizontalAlignment() + * + * \since QGIS 3.16 + */ + void setSelectionVerticalAlignment( Qt::Alignment alignment ); + + /** + * Sets the cell contents QgsProperty for the currently selected cells. + * + * \since QGIS 3.16 + */ + void setSelectionCellProperty( const QgsProperty &property ); + + /** + * Sets the text \a format for the selected cells. + * + * \since QGIS 3.16 + */ + void setSelectionTextFormat( const QgsTextFormat &format ); + /** * Sets the row \a height (in millimeters) for the currently selected rows, or 0 for automatic row height. * @@ -390,7 +464,11 @@ class GUI_EXPORT QgsTableEditorWidget : public QTableWidget PresetBackgroundColorRole = Qt::UserRole + 1, RowHeight, ColumnWidth, - CellContent + CellContent, + TextFormat, + HorizontalAlignment, + VerticalAlignment, + CellProperty, }; void updateHeaders(); diff --git a/src/gui/vector/qgsattributesformproperties.cpp b/src/gui/vector/qgsattributesformproperties.cpp index cd1535e4ecdf..f459a59c5e75 100644 --- a/src/gui/vector/qgsattributesformproperties.cpp +++ b/src/gui/vector/qgsattributesformproperties.cpp @@ -482,9 +482,7 @@ QTreeWidgetItem *QgsAttributesFormProperties::loadAttributeEditorTreeItem( QgsAt DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Relation, relationEditor->relation().id(), relationEditor->relation().name() ); itemData.setShowLabel( widgetDef->showLabel() ); RelationEditorConfiguration relEdConfig; - relEdConfig.showLinkButton = relationEditor->showLinkButton(); - relEdConfig.showUnlinkButton = relationEditor->showUnlinkButton(); - relEdConfig.showSaveChildEditsButton = relationEditor->showSaveChildEditsButton( ); + relEdConfig.buttons = relationEditor->visibleButtons(); itemData.setRelationEditorConfiguration( relEdConfig ); newWidget = tree->addItem( parent, itemData ); break; @@ -713,9 +711,7 @@ QgsAttributeEditorElement *QgsAttributesFormProperties::createAttributeEditorWid { QgsRelation relation = QgsProject::instance()->relationManager()->relation( itemData.name() ); QgsAttributeEditorRelation *relDef = new QgsAttributeEditorRelation( relation, parent ); - relDef->setShowLinkButton( itemData.relationEditorConfiguration().showLinkButton ); - relDef->setShowUnlinkButton( itemData.relationEditorConfiguration().showUnlinkButton ); - relDef->setShowSaveChildEditsButton( itemData.relationEditorConfiguration().showSaveChildEditsButton ); + relDef->setVisibleButtons( itemData.relationEditorConfiguration().buttons ); widgetDef = relDef; break; } diff --git a/src/gui/vector/qgsattributesformproperties.h b/src/gui/vector/qgsattributesformproperties.h index 01c962d6f3f3..56281d834762 100644 --- a/src/gui/vector/qgsattributesformproperties.h +++ b/src/gui/vector/qgsattributesformproperties.h @@ -69,9 +69,7 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress struct RelationEditorConfiguration { - bool showLinkButton = true; - bool showUnlinkButton = true; - bool showSaveChildEditsButton = true; + QgsAttributeEditorRelation::Buttons buttons = QgsAttributeEditorRelation::Button::AllButtons; }; struct QmlElementEditorConfiguration diff --git a/src/gui/vector/qgsdiagramproperties.cpp b/src/gui/vector/qgsdiagramproperties.cpp index 864384ea0bd7..c41adf30ab60 100644 --- a/src/gui/vector/qgsdiagramproperties.cpp +++ b/src/gui/vector/qgsdiagramproperties.cpp @@ -298,6 +298,9 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare case QgsWkbTypes::PolygonGeometry: radOverCentroid->setChecked( true ); + mDiagramDistanceLabel->setEnabled( false ); + mDiagramDistanceSpinBox->setEnabled( false ); + mDistanceDDBtn->setEnabled( false ); break; case QgsWkbTypes::UnknownGeometry: diff --git a/src/gui/vector/qgsvectorlayerproperties.cpp b/src/gui/vector/qgsvectorlayerproperties.cpp index a895ea865a14..82b66498a8ca 100644 --- a/src/gui/vector/qgsvectorlayerproperties.cpp +++ b/src/gui/vector/qgsvectorlayerproperties.cpp @@ -388,7 +388,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties( dependencySources << layer; } - mLayersDependenciesTreeModel = new DependenciesLayerTreeModel( mLayer, this ); + mLayersDependenciesTreeModel = new QgsLayerTreeFilterProxyModel( this ); mLayersDependenciesTreeModel->setLayerTreeModel( new QgsLayerTreeModel( QgsProject::instance()->layerTreeRoot(), mLayersDependenciesTreeModel ) ); mLayersDependenciesTreeModel->setCheckedLayers( dependencySources ); connect( QgsProject::instance(), &QObject::destroyed, this, [ = ] {mLayersDependenciesTreeView->setModel( nullptr );} ); @@ -607,7 +607,7 @@ void QgsVectorLayerProperties::apply() mMetadataFilled = false; // save masking settings - if ( mMaskingWidget ) + if ( mMaskingWidget && mMaskingWidget->hasBeenPopulated() ) mMaskingWidget->apply(); // diff --git a/src/gui/vector/qgsvectorlayerproperties.h b/src/gui/vector/qgsvectorlayerproperties.h index 9bbcc3773992..8af2ce6d77af 100644 --- a/src/gui/vector/qgsvectorlayerproperties.h +++ b/src/gui/vector/qgsvectorlayerproperties.h @@ -160,19 +160,6 @@ class GUI_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private private: - class DependenciesLayerTreeModel : public QgsLayerTreeFilterProxyModel - { - public: - DependenciesLayerTreeModel( QgsVectorLayer *mainLayer, QObject *parent = nullptr ) - : QgsLayerTreeFilterProxyModel( parent ) - , mMainLayer( mainLayer ) - {} - - private: - QgsVectorLayer *mMainLayer = nullptr; - bool layerShown( QgsMapLayer *layer ) const override {return layer != mMainLayer;} - }; - enum PropertyType { Style = 0, @@ -241,7 +228,7 @@ class GUI_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private QgsExpressionContext createExpressionContext() const override; - DependenciesLayerTreeModel *mLayersDependenciesTreeModel; + QgsLayerTreeFilterProxyModel *mLayersDependenciesTreeModel; void showHelp(); diff --git a/src/plugins/geometry_checker/icons/geometrychecker.svg b/src/plugins/geometry_checker/icons/geometrychecker.svg index 2be5820e1921..0cd6b99e87a8 100644 --- a/src/plugins/geometry_checker/icons/geometrychecker.svg +++ b/src/plugins/geometry_checker/icons/geometrychecker.svg @@ -1,115 +1 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/gps_importer/create_gpx.svg b/src/plugins/gps_importer/create_gpx.svg index 032c6bed39fb..2ca612e1242e 100644 --- a/src/plugins/gps_importer/create_gpx.svg +++ b/src/plugins/gps_importer/create_gpx.svg @@ -1,378 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/gps_importer/gps_importer.svg b/src/plugins/gps_importer/gps_importer.svg index b15f85faf649..f41983459499 100644 --- a/src/plugins/gps_importer/gps_importer.svg +++ b/src/plugins/gps_importer/gps_importer.svg @@ -1,1001 +1 @@ - - - - - select add - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - select add - 2013-01-30 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - select add - - - GIS icons 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/gps_importer/import_gpx.svg b/src/plugins/gps_importer/import_gpx.svg index 8fed00df3f65..c9e6b987fe8c 100644 --- a/src/plugins/gps_importer/import_gpx.svg +++ b/src/plugins/gps_importer/import_gpx.svg @@ -1,345 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/db-connect.1.svg b/src/plugins/grass/modules/db-connect.1.svg index c7e432507ac9..80ecdd5ecb76 100644 --- a/src/plugins/grass/modules/db-connect.1.svg +++ b/src/plugins/grass/modules/db-connect.1.svg @@ -1,145 +1 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/db.connect.1.svg b/src/plugins/grass/modules/db.connect.1.svg index 055b036a3bb3..6298ff4093e8 100644 --- a/src/plugins/grass/modules/db.connect.1.svg +++ b/src/plugins/grass/modules/db.connect.1.svg @@ -1,101 +1 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/db.copy.1.svg b/src/plugins/grass/modules/db.copy.1.svg index cb0414cd6994..449adb286773 100644 --- a/src/plugins/grass/modules/db.copy.1.svg +++ b/src/plugins/grass/modules/db.copy.1.svg @@ -1,110 +1 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/db.execute.1.svg b/src/plugins/grass/modules/db.execute.1.svg index 5e3ca7ebaea4..46c14d395b37 100644 --- a/src/plugins/grass/modules/db.execute.1.svg +++ b/src/plugins/grass/modules/db.execute.1.svg @@ -1,109 +1 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/db.login.1.svg b/src/plugins/grass/modules/db.login.1.svg index 2b7f00e58b80..c43ee7337002 100644 --- a/src/plugins/grass/modules/db.login.1.svg +++ b/src/plugins/grass/modules/db.login.1.svg @@ -1,99 +1 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - *** - - - +*** \ No newline at end of file diff --git a/src/plugins/grass/modules/r.buffer.1.svg b/src/plugins/grass/modules/r.buffer.1.svg index 06f4f6d03f97..132a7f14597a 100644 --- a/src/plugins/grass/modules/r.buffer.1.svg +++ b/src/plugins/grass/modules/r.buffer.1.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/r.buffer.2.svg b/src/plugins/grass/modules/r.buffer.2.svg index 8709f4839493..491aca8c7ad0 100644 --- a/src/plugins/grass/modules/r.buffer.2.svg +++ b/src/plugins/grass/modules/r.buffer.2.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/r.to.vect.area.1.svg b/src/plugins/grass/modules/r.to.vect.area.1.svg index d156249b3bdb..73fccf437304 100644 --- a/src/plugins/grass/modules/r.to.vect.area.1.svg +++ b/src/plugins/grass/modules/r.to.vect.area.1.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/r.to.vect.area.2.svg b/src/plugins/grass/modules/r.to.vect.area.2.svg index e431afa8a4dd..f5da12a09803 100644 --- a/src/plugins/grass/modules/r.to.vect.area.2.svg +++ b/src/plugins/grass/modules/r.to.vect.area.2.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/r.to.vect.line.1.svg b/src/plugins/grass/modules/r.to.vect.line.1.svg index 3bcb264bc7bb..ef670d5961cd 100644 --- a/src/plugins/grass/modules/r.to.vect.line.1.svg +++ b/src/plugins/grass/modules/r.to.vect.line.1.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/r.to.vect.line.2.svg b/src/plugins/grass/modules/r.to.vect.line.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/r.to.vect.line.2.svg +++ b/src/plugins/grass/modules/r.to.vect.line.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/r.to.vect.point.1.svg b/src/plugins/grass/modules/r.to.vect.point.1.svg index 6d2dec6d3c1c..680ca79eb922 100644 --- a/src/plugins/grass/modules/r.to.vect.point.1.svg +++ b/src/plugins/grass/modules/r.to.vect.point.1.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/strds.svg b/src/plugins/grass/modules/strds.svg index f42c4c9336f0..140b2b51bc0d 100644 --- a/src/plugins/grass/modules/strds.svg +++ b/src/plugins/grass/modules/strds.svg @@ -1,549 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.aggregate.1.svg b/src/plugins/grass/modules/t.rast.aggregate.1.svg index 554871add978..b5dde8292328 100644 --- a/src/plugins/grass/modules/t.rast.aggregate.1.svg +++ b/src/plugins/grass/modules/t.rast.aggregate.1.svg @@ -1,555 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.aggregate.2.svg b/src/plugins/grass/modules/t.rast.aggregate.2.svg index 762ea0985175..e4174f5e661e 100644 --- a/src/plugins/grass/modules/t.rast.aggregate.2.svg +++ b/src/plugins/grass/modules/t.rast.aggregate.2.svg @@ -1,395 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.colors.1.svg b/src/plugins/grass/modules/t.rast.colors.1.svg index 3a10d81c9ce5..79c96cdc0605 100644 --- a/src/plugins/grass/modules/t.rast.colors.1.svg +++ b/src/plugins/grass/modules/t.rast.colors.1.svg @@ -1,598 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.import.1.svg b/src/plugins/grass/modules/t.rast.import.1.svg index 873a2a91bbcd..ad0697aab05a 100644 --- a/src/plugins/grass/modules/t.rast.import.1.svg +++ b/src/plugins/grass/modules/t.rast.import.1.svg @@ -1,907 +1 @@ - - - - - data-add - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - data-add - 2012-08-16 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - data-add - - - GIS icons 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.list.1.svg b/src/plugins/grass/modules/t.rast.list.1.svg index 9a8730fc01b5..30153aa29630 100644 --- a/src/plugins/grass/modules/t.rast.list.1.svg +++ b/src/plugins/grass/modules/t.rast.list.1.svg @@ -1,576 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - i - - - +i \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.mapcalc.1.svg b/src/plugins/grass/modules/t.rast.mapcalc.1.svg index f75fd36232d9..12481ed91aa2 100644 --- a/src/plugins/grass/modules/t.rast.mapcalc.1.svg +++ b/src/plugins/grass/modules/t.rast.mapcalc.1.svg @@ -1,648 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.to.rast3.1.svg b/src/plugins/grass/modules/t.rast.to.rast3.1.svg index 48a80565a704..140b2b51bc0d 100644 --- a/src/plugins/grass/modules/t.rast.to.rast3.1.svg +++ b/src/plugins/grass/modules/t.rast.to.rast3.1.svg @@ -1,551 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.to.rast3.2.svg b/src/plugins/grass/modules/t.rast.to.rast3.2.svg index 183147b1112b..4b5634d8c1f9 100644 --- a/src/plugins/grass/modules/t.rast.to.rast3.2.svg +++ b/src/plugins/grass/modules/t.rast.to.rast3.2.svg @@ -1,346 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast.univar.1.svg b/src/plugins/grass/modules/t.rast.univar.1.svg index c9026f8cad36..edd99d822b4e 100644 --- a/src/plugins/grass/modules/t.rast.univar.1.svg +++ b/src/plugins/grass/modules/t.rast.univar.1.svg @@ -1,566 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast3d.list.1.svg b/src/plugins/grass/modules/t.rast3d.list.1.svg index b5af5ce4fb9b..d5dd39002024 100644 --- a/src/plugins/grass/modules/t.rast3d.list.1.svg +++ b/src/plugins/grass/modules/t.rast3d.list.1.svg @@ -1,616 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - i - - - - - - - - +i \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast3d.mapcalc.1.svg b/src/plugins/grass/modules/t.rast3d.mapcalc.1.svg index c651ba53c1b7..7c9bbe6f00ce 100644 --- a/src/plugins/grass/modules/t.rast3d.mapcalc.1.svg +++ b/src/plugins/grass/modules/t.rast3d.mapcalc.1.svg @@ -1,674 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.rast3d.univar.1.svg b/src/plugins/grass/modules/t.rast3d.univar.1.svg index 3150f1281faa..718ee1bdb214 100644 --- a/src/plugins/grass/modules/t.rast3d.univar.1.svg +++ b/src/plugins/grass/modules/t.rast3d.univar.1.svg @@ -1,592 +1 @@ - - - - - GIS icon theme 0.2 - - - - - - - - - - - - - - - - - - - image/svg+xml - - GIS icon theme 0.2 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - GIS icons - - - GIS icons - http://robert.szczepanek.pl/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.vect.colors.1.svg b/src/plugins/grass/modules/t.vect.colors.1.svg index c8a2afad596d..5f79a9e8ecbc 100644 --- a/src/plugins/grass/modules/t.vect.colors.1.svg +++ b/src/plugins/grass/modules/t.vect.colors.1.svg @@ -1,580 +1 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.vect.import.1.svg b/src/plugins/grass/modules/t.vect.import.1.svg index bac8bbfc05b6..ad0697aab05a 100644 --- a/src/plugins/grass/modules/t.vect.import.1.svg +++ b/src/plugins/grass/modules/t.vect.import.1.svg @@ -1,904 +1 @@ - - - - - data-add - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - data-add - 2012-08-16 - - - Robert Szczepanek - - - - - Robert Szczepanek - - - - - data-add - - - GIS icons 0.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.vect.import.2.svg b/src/plugins/grass/modules/t.vect.import.2.svg index 743217339337..d0a69f1363e5 100644 --- a/src/plugins/grass/modules/t.vect.import.2.svg +++ b/src/plugins/grass/modules/t.vect.import.2.svg @@ -1,534 +1 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.vect.list.1.svg b/src/plugins/grass/modules/t.vect.list.1.svg index 4f342022fbd2..3c54d69c0cf3 100644 --- a/src/plugins/grass/modules/t.vect.list.1.svg +++ b/src/plugins/grass/modules/t.vect.list.1.svg @@ -1,570 +1 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - i - - - +i \ No newline at end of file diff --git a/src/plugins/grass/modules/t.vect.mapcalc.1.svg b/src/plugins/grass/modules/t.vect.mapcalc.1.svg index 4237b07e2186..08ac12d7bf18 100644 --- a/src/plugins/grass/modules/t.vect.mapcalc.1.svg +++ b/src/plugins/grass/modules/t.vect.mapcalc.1.svg @@ -1,630 +1 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/t.vect.univar.1.svg b/src/plugins/grass/modules/t.vect.univar.1.svg index 5003f80b3cd0..3b0b85b74203 100644 --- a/src/plugins/grass/modules/t.vect.univar.1.svg +++ b/src/plugins/grass/modules/t.vect.univar.1.svg @@ -1,556 +1 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.buffer.1.svg b/src/plugins/grass/modules/v.buffer.1.svg index 106e67b1ed8a..c8ef4bdddfbd 100644 --- a/src/plugins/grass/modules/v.buffer.1.svg +++ b/src/plugins/grass/modules/v.buffer.1.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.buffer.2.svg b/src/plugins/grass/modules/v.buffer.2.svg index ceeb28c404a2..aa2fcd63ebf8 100644 --- a/src/plugins/grass/modules/v.buffer.2.svg +++ b/src/plugins/grass/modules/v.buffer.2.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.delaunay.area.2.svg b/src/plugins/grass/modules/v.delaunay.area.2.svg index e370e898fe28..38ccceacbd83 100644 --- a/src/plugins/grass/modules/v.delaunay.area.2.svg +++ b/src/plugins/grass/modules/v.delaunay.area.2.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.delaunay.line.2.svg b/src/plugins/grass/modules/v.delaunay.line.2.svg index c12535db2b7f..cc94605520eb 100644 --- a/src/plugins/grass/modules/v.delaunay.line.2.svg +++ b/src/plugins/grass/modules/v.delaunay.line.2.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.extract.list.1.svg b/src/plugins/grass/modules/v.extract.list.1.svg index 7906ec8b178d..9f4011d06591 100644 --- a/src/plugins/grass/modules/v.extract.list.1.svg +++ b/src/plugins/grass/modules/v.extract.list.1.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.extract.list.2.svg b/src/plugins/grass/modules/v.extract.list.2.svg index b48a50448b42..1c98322daccc 100644 --- a/src/plugins/grass/modules/v.extract.list.2.svg +++ b/src/plugins/grass/modules/v.extract.list.2.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.extract.where.1.svg b/src/plugins/grass/modules/v.extract.where.1.svg index 7906ec8b178d..9f4011d06591 100644 --- a/src/plugins/grass/modules/v.extract.where.1.svg +++ b/src/plugins/grass/modules/v.extract.where.1.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.extract.where.2.svg b/src/plugins/grass/modules/v.extract.where.2.svg index b48a50448b42..1c98322daccc 100644 --- a/src/plugins/grass/modules/v.extract.where.2.svg +++ b/src/plugins/grass/modules/v.extract.where.2.svg @@ -1,32 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.generalize.1.svg b/src/plugins/grass/modules/v.generalize.1.svg index 7906ec8b178d..9f4011d06591 100644 --- a/src/plugins/grass/modules/v.generalize.1.svg +++ b/src/plugins/grass/modules/v.generalize.1.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.hull.2.svg b/src/plugins/grass/modules/v.hull.2.svg index 19e52ff3c418..3ea16907837f 100644 --- a/src/plugins/grass/modules/v.hull.2.svg +++ b/src/plugins/grass/modules/v.hull.2.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.dxf.1.svg b/src/plugins/grass/modules/v.in.dxf.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.dxf.1.svg +++ b/src/plugins/grass/modules/v.in.dxf.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.e00.1.svg b/src/plugins/grass/modules/v.in.e00.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.e00.1.svg +++ b/src/plugins/grass/modules/v.in.e00.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.geonames.1.svg b/src/plugins/grass/modules/v.in.geonames.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.geonames.1.svg +++ b/src/plugins/grass/modules/v.in.geonames.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.mapgen.1.svg b/src/plugins/grass/modules/v.in.mapgen.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.mapgen.1.svg +++ b/src/plugins/grass/modules/v.in.mapgen.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.ogr.1.svg b/src/plugins/grass/modules/v.in.ogr.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.ogr.1.svg +++ b/src/plugins/grass/modules/v.in.ogr.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.ogr.all.1.svg b/src/plugins/grass/modules/v.in.ogr.all.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.ogr.all.1.svg +++ b/src/plugins/grass/modules/v.in.ogr.all.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.ogr.all.loc.1.svg b/src/plugins/grass/modules/v.in.ogr.all.loc.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.ogr.all.loc.1.svg +++ b/src/plugins/grass/modules/v.in.ogr.all.loc.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.ogr.loc.1.svg b/src/plugins/grass/modules/v.in.ogr.loc.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.ogr.loc.1.svg +++ b/src/plugins/grass/modules/v.in.ogr.loc.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.ogr.qgis.1.svg b/src/plugins/grass/modules/v.in.ogr.qgis.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.ogr.qgis.1.svg +++ b/src/plugins/grass/modules/v.in.ogr.qgis.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.ogr.qgis.loc.1.svg b/src/plugins/grass/modules/v.in.ogr.qgis.loc.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.in.ogr.qgis.loc.1.svg +++ b/src/plugins/grass/modules/v.in.ogr.qgis.loc.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.in.region.1.svg b/src/plugins/grass/modules/v.in.region.1.svg index 675704b1fca7..eab40c731f4e 100644 --- a/src/plugins/grass/modules/v.in.region.1.svg +++ b/src/plugins/grass/modules/v.in.region.1.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.mkgrid.region.1.svg b/src/plugins/grass/modules/v.mkgrid.region.1.svg index 6f657fbf93e3..dfa2209d6610 100644 --- a/src/plugins/grass/modules/v.mkgrid.region.1.svg +++ b/src/plugins/grass/modules/v.mkgrid.region.1.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.1.svg b/src/plugins/grass/modules/v.net.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.1.svg +++ b/src/plugins/grass/modules/v.net.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.2.svg b/src/plugins/grass/modules/v.net.2.svg index b0279e00c49c..b5403c9bb0a8 100644 --- a/src/plugins/grass/modules/v.net.2.svg +++ b/src/plugins/grass/modules/v.net.2.svg @@ -1,57 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.alloc.1.svg b/src/plugins/grass/modules/v.net.alloc.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.alloc.1.svg +++ b/src/plugins/grass/modules/v.net.alloc.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.alloc.2.svg b/src/plugins/grass/modules/v.net.alloc.2.svg index b0279e00c49c..b5403c9bb0a8 100644 --- a/src/plugins/grass/modules/v.net.alloc.2.svg +++ b/src/plugins/grass/modules/v.net.alloc.2.svg @@ -1,57 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.iso.1.svg b/src/plugins/grass/modules/v.net.iso.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.iso.1.svg +++ b/src/plugins/grass/modules/v.net.iso.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.iso.2.svg b/src/plugins/grass/modules/v.net.iso.2.svg index a0dd391687cf..9cff408276fd 100644 --- a/src/plugins/grass/modules/v.net.iso.2.svg +++ b/src/plugins/grass/modules/v.net.iso.2.svg @@ -1,62 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.nodes.1.svg b/src/plugins/grass/modules/v.net.nodes.1.svg index 2a8a257e2fca..3b760fe8428a 100644 --- a/src/plugins/grass/modules/v.net.nodes.1.svg +++ b/src/plugins/grass/modules/v.net.nodes.1.svg @@ -1,29 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.nodes.2.svg b/src/plugins/grass/modules/v.net.nodes.2.svg index 50ce7f7b0ac1..824e6d498d2e 100644 --- a/src/plugins/grass/modules/v.net.nodes.2.svg +++ b/src/plugins/grass/modules/v.net.nodes.2.svg @@ -1,65 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.path.1.svg b/src/plugins/grass/modules/v.net.path.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.path.1.svg +++ b/src/plugins/grass/modules/v.net.path.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.path.2.svg b/src/plugins/grass/modules/v.net.path.2.svg index b0279e00c49c..b5403c9bb0a8 100644 --- a/src/plugins/grass/modules/v.net.path.2.svg +++ b/src/plugins/grass/modules/v.net.path.2.svg @@ -1,57 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.salesman.1.svg b/src/plugins/grass/modules/v.net.salesman.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.salesman.1.svg +++ b/src/plugins/grass/modules/v.net.salesman.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.salesman.2.svg b/src/plugins/grass/modules/v.net.salesman.2.svg index a13ae3dd4154..c8376ba6a753 100644 --- a/src/plugins/grass/modules/v.net.salesman.2.svg +++ b/src/plugins/grass/modules/v.net.salesman.2.svg @@ -1,36 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.steiner.1.svg b/src/plugins/grass/modules/v.net.steiner.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.steiner.1.svg +++ b/src/plugins/grass/modules/v.net.steiner.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.steiner.2.svg b/src/plugins/grass/modules/v.net.steiner.2.svg index 8748c4dcdace..b8aa4216d1d7 100644 --- a/src/plugins/grass/modules/v.net.steiner.2.svg +++ b/src/plugins/grass/modules/v.net.steiner.2.svg @@ -1,33 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.visibility.1.svg b/src/plugins/grass/modules/v.net.visibility.1.svg index 43911504d182..64869e335191 100644 --- a/src/plugins/grass/modules/v.net.visibility.1.svg +++ b/src/plugins/grass/modules/v.net.visibility.1.svg @@ -1,35 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.net.visibility.2.svg b/src/plugins/grass/modules/v.net.visibility.2.svg index b0279e00c49c..b5403c9bb0a8 100644 --- a/src/plugins/grass/modules/v.net.visibility.2.svg +++ b/src/plugins/grass/modules/v.net.visibility.2.svg @@ -1,57 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.dxf.2.svg b/src/plugins/grass/modules/v.out.dxf.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.dxf.2.svg +++ b/src/plugins/grass/modules/v.out.dxf.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.ogr.2.svg b/src/plugins/grass/modules/v.out.ogr.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.ogr.2.svg +++ b/src/plugins/grass/modules/v.out.ogr.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.ogr.gml.2.svg b/src/plugins/grass/modules/v.out.ogr.gml.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.ogr.gml.2.svg +++ b/src/plugins/grass/modules/v.out.ogr.gml.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.ogr.mapinfo.2.svg b/src/plugins/grass/modules/v.out.ogr.mapinfo.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.ogr.mapinfo.2.svg +++ b/src/plugins/grass/modules/v.out.ogr.mapinfo.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.ogr.shape.2.svg b/src/plugins/grass/modules/v.out.ogr.shape.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.ogr.shape.2.svg +++ b/src/plugins/grass/modules/v.out.ogr.shape.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.pov.2.svg b/src/plugins/grass/modules/v.out.pov.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.pov.2.svg +++ b/src/plugins/grass/modules/v.out.pov.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.svg.2.svg b/src/plugins/grass/modules/v.out.svg.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.svg.2.svg +++ b/src/plugins/grass/modules/v.out.svg.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.out.vtk.2.svg b/src/plugins/grass/modules/v.out.vtk.2.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.out.vtk.2.svg +++ b/src/plugins/grass/modules/v.out.vtk.2.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.and.1.svg b/src/plugins/grass/modules/v.overlay.and.1.svg index 0f940702ed15..987678f410ec 100644 --- a/src/plugins/grass/modules/v.overlay.and.1.svg +++ b/src/plugins/grass/modules/v.overlay.and.1.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.and.2.svg b/src/plugins/grass/modules/v.overlay.and.2.svg index f0261004ab64..7e5adf115437 100644 --- a/src/plugins/grass/modules/v.overlay.and.2.svg +++ b/src/plugins/grass/modules/v.overlay.and.2.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.and.3.svg b/src/plugins/grass/modules/v.overlay.and.3.svg index b7303195dee6..3f130234596d 100644 --- a/src/plugins/grass/modules/v.overlay.and.3.svg +++ b/src/plugins/grass/modules/v.overlay.and.3.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.not.1.svg b/src/plugins/grass/modules/v.overlay.not.1.svg index 0f940702ed15..987678f410ec 100644 --- a/src/plugins/grass/modules/v.overlay.not.1.svg +++ b/src/plugins/grass/modules/v.overlay.not.1.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.not.2.svg b/src/plugins/grass/modules/v.overlay.not.2.svg index f0261004ab64..7e5adf115437 100644 --- a/src/plugins/grass/modules/v.overlay.not.2.svg +++ b/src/plugins/grass/modules/v.overlay.not.2.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.not.3.svg b/src/plugins/grass/modules/v.overlay.not.3.svg index 7de257d0c43b..1e4de227d6df 100644 --- a/src/plugins/grass/modules/v.overlay.not.3.svg +++ b/src/plugins/grass/modules/v.overlay.not.3.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.or.1.svg b/src/plugins/grass/modules/v.overlay.or.1.svg index 0f940702ed15..987678f410ec 100644 --- a/src/plugins/grass/modules/v.overlay.or.1.svg +++ b/src/plugins/grass/modules/v.overlay.or.1.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.or.2.svg b/src/plugins/grass/modules/v.overlay.or.2.svg index f0261004ab64..7e5adf115437 100644 --- a/src/plugins/grass/modules/v.overlay.or.2.svg +++ b/src/plugins/grass/modules/v.overlay.or.2.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.or.3.svg b/src/plugins/grass/modules/v.overlay.or.3.svg index 9310ec3e49c6..06467f2af49d 100644 --- a/src/plugins/grass/modules/v.overlay.or.3.svg +++ b/src/plugins/grass/modules/v.overlay.or.3.svg @@ -1,18 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.xor.1.svg b/src/plugins/grass/modules/v.overlay.xor.1.svg index 0f940702ed15..987678f410ec 100644 --- a/src/plugins/grass/modules/v.overlay.xor.1.svg +++ b/src/plugins/grass/modules/v.overlay.xor.1.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.xor.2.svg b/src/plugins/grass/modules/v.overlay.xor.2.svg index f0261004ab64..7e5adf115437 100644 --- a/src/plugins/grass/modules/v.overlay.xor.2.svg +++ b/src/plugins/grass/modules/v.overlay.xor.2.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.overlay.xor.3.svg b/src/plugins/grass/modules/v.overlay.xor.3.svg index 29e3d3d038e9..d99eb27c4adc 100644 --- a/src/plugins/grass/modules/v.overlay.xor.3.svg +++ b/src/plugins/grass/modules/v.overlay.xor.3.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.select.overlap.1.svg b/src/plugins/grass/modules/v.select.overlap.1.svg index 9d2529ff0c8c..0a92850caa53 100644 --- a/src/plugins/grass/modules/v.select.overlap.1.svg +++ b/src/plugins/grass/modules/v.select.overlap.1.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.select.overlap.2.svg b/src/plugins/grass/modules/v.select.overlap.2.svg index c1bb282cfff3..15d21b207aa8 100644 --- a/src/plugins/grass/modules/v.select.overlap.2.svg +++ b/src/plugins/grass/modules/v.select.overlap.2.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.select.overlap.3.svg b/src/plugins/grass/modules/v.select.overlap.3.svg index 2108bfee9825..a0e36e9297a0 100644 --- a/src/plugins/grass/modules/v.select.overlap.3.svg +++ b/src/plugins/grass/modules/v.select.overlap.3.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.support.1.svg b/src/plugins/grass/modules/v.support.1.svg index 7906ec8b178d..9f4011d06591 100644 --- a/src/plugins/grass/modules/v.support.1.svg +++ b/src/plugins/grass/modules/v.support.1.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.to.rast.constant.1.svg b/src/plugins/grass/modules/v.to.rast.constant.1.svg index f36f76310eee..b9172140a27a 100644 --- a/src/plugins/grass/modules/v.to.rast.constant.1.svg +++ b/src/plugins/grass/modules/v.to.rast.constant.1.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.to.rast.constant.2.svg b/src/plugins/grass/modules/v.to.rast.constant.2.svg index 3bcb264bc7bb..ef670d5961cd 100644 --- a/src/plugins/grass/modules/v.to.rast.constant.2.svg +++ b/src/plugins/grass/modules/v.to.rast.constant.2.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.voronoi.area.2.svg b/src/plugins/grass/modules/v.voronoi.area.2.svg index f303cf1e5a5d..de99f8eefdf6 100644 --- a/src/plugins/grass/modules/v.voronoi.area.2.svg +++ b/src/plugins/grass/modules/v.voronoi.area.2.svg @@ -1,20 +1 @@ - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/modules/v.voronoi.line.2.svg b/src/plugins/grass/modules/v.voronoi.line.2.svg index 6cb31b49af04..0ec57427713c 100644 --- a/src/plugins/grass/modules/v.voronoi.line.2.svg +++ b/src/plugins/grass/modules/v.voronoi.line.2.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/themes/default/grass_arrow.svg b/src/plugins/grass/themes/default/grass_arrow.svg index c98c75f075be..752e3b6f2858 100644 --- a/src/plugins/grass/themes/default/grass_arrow.svg +++ b/src/plugins/grass/themes/default/grass_arrow.svg @@ -1,35 +1 @@ - - - - - - - - - image/svg+xml - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/grass/themes/default/grass_plus.svg b/src/plugins/grass/themes/default/grass_plus.svg index b3708251238e..75b89325cfde 100644 --- a/src/plugins/grass/themes/default/grass_plus.svg +++ b/src/plugins/grass/themes/default/grass_plus.svg @@ -1,35 +1 @@ - - - - - - - - - image/svg+xml - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/topology/mActionConfigure.svg b/src/plugins/topology/mActionConfigure.svg index 00d7eed4bc07..4478ec61aea0 100644 --- a/src/plugins/topology/mActionConfigure.svg +++ b/src/plugins/topology/mActionConfigure.svg @@ -1,626 +1 @@ - - - Configure icon - - - - - - - image/svg+xml - - Configure icon - - - slarosa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/topology/mActionTopologyChecker.svg b/src/plugins/topology/mActionTopologyChecker.svg index 3f7d68d1c30e..bb9c0c8ff7c3 100644 --- a/src/plugins/topology/mActionTopologyChecker.svg +++ b/src/plugins/topology/mActionTopologyChecker.svg @@ -1,563 +1 @@ - - - Topology Checker icon - - - - - - - image/svg+xml - - Topology Checker icon - - - slarosa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/topology/mActionValidateAll.svg b/src/plugins/topology/mActionValidateAll.svg index 953004adc82a..5d31ae9ecc12 100644 --- a/src/plugins/topology/mActionValidateAll.svg +++ b/src/plugins/topology/mActionValidateAll.svg @@ -1,414 +1 @@ - - - Validate Extent icon - - - - - - - image/svg+xml - - Validate Extent icon - - - slarosa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/plugins/topology/mActionValidateExtent.svg b/src/plugins/topology/mActionValidateExtent.svg index 9f44432660b4..d0ad4df471cb 100644 --- a/src/plugins/topology/mActionValidateExtent.svg +++ b/src/plugins/topology/mActionValidateExtent.svg @@ -1,421 +1 @@ - - - Validate Extent icon - - - - - - - image/svg+xml - - Validate Extent icon - - - slarosa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/process/CMakeLists.txt b/src/process/CMakeLists.txt index e0205acf6e12..e72041b5ffc7 100644 --- a/src/process/CMakeLists.txt +++ b/src/process/CMakeLists.txt @@ -15,7 +15,7 @@ ENDIF (UNIX AND NOT ANDROID) ######################################################## # Build -ADD_EXECUTABLE (qgis_process MACOSX_BUNDLE WIN32 ${QGIS_PROCESS_SRCS} ) +ADD_EXECUTABLE (qgis_process MACOSX_BUNDLE ${QGIS_PROCESS_SRCS}) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} diff --git a/src/process/qgsprocess.cpp b/src/process/qgsprocess.cpp index e9fc69fabf73..ca816050523f 100644 --- a/src/process/qgsprocess.cpp +++ b/src/process/qgsprocess.cpp @@ -27,7 +27,7 @@ #include "qgsprocessingparametertype.h" #include "processing/models/qgsprocessingmodelalgorithm.h" -#if defined(Q_OS_UNIX) and !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) #include "sigwatch.h" #endif @@ -102,10 +102,10 @@ void ConsoleFeedback::showTerminalProgress( double progress ) //! load Python support if possible -std::unique_ptr< QgsPythonUtils > loadPythonSupport() +std::unique_ptr< QgsPythonUtils > QgsProcessingExec::loadPythonSupport() { QString pythonlibName( QStringLiteral( "qgispython" ) ); -#if defined(Q_OS_UNIX) and !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) pythonlibName.prepend( QgsApplication::libraryPath() ); #endif #ifdef __MINGW32__ @@ -440,13 +440,17 @@ int QgsProcessingExec::execute( const QString &id, const QVariantMap ¶ms ) std::cout << it.key().toLocal8Bit().constData() << ":\t" << it.value().toString().toLocal8Bit().constData() << '\n'; } + QgsProcessingContext context; const QgsProcessingParameterDefinitions defs = alg->parameterDefinitions(); QList< const QgsProcessingParameterDefinition * > missingParams; for ( const QgsProcessingParameterDefinition *p : defs ) { - if ( !( p->flags() & QgsProcessingParameterDefinition::FlagOptional ) && !params.contains( p->name() ) ) + if ( !p->checkValueIsAcceptable( params.value( p->name() ), &context ) ) { - missingParams << p; + if ( !( p->flags() & QgsProcessingParameterDefinition::FlagOptional ) && !params.contains( p->name() ) ) + { + missingParams << p; + } } } @@ -461,10 +465,17 @@ int QgsProcessingExec::execute( const QString &id, const QVariantMap ¶ms ) return 1; } - QgsProcessingContext context; + QString message; + if ( !alg->checkParameterValues( params, context, &message ) ) + { + std::cerr << QStringLiteral( "ERROR:\tAn error was encountered while checking parameter values\n" ).toLocal8Bit().constData(); + std::cerr << QStringLiteral( "\t%1\n" ).arg( message ).toLocal8Bit().constData(); + return 1; + } + ConsoleFeedback feedback; -#if defined(Q_OS_UNIX) and !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) UnixSignalWatcher sigwatch; sigwatch.watchForSignal( SIGINT ); @@ -497,15 +508,15 @@ int QgsProcessingExec::execute( const QString &id, const QVariantMap ¶ms ) if ( it.key() == QLatin1String( "CHILD_INPUTS" ) || it.key() == QLatin1String( "CHILD_RESULTS" ) ) continue; - QVariant res = it.value(); - if ( res.type() == QVariant::List || res.type() == QVariant::StringList ) + QVariant result = it.value(); + if ( result.type() == QVariant::List || result.type() == QVariant::StringList ) { QStringList list; - for ( const QVariant &v : res.toList() ) + for ( const QVariant &v : result.toList() ) list << v.toString(); - res = list.join( ", " ); + result = list.join( ", " ); } - std::cout << it.key().toLocal8Bit().constData() << ":\t" << res.toString().toLocal8Bit().constData() << '\n'; + std::cout << it.key().toLocal8Bit().constData() << ":\t" << result.toString().toLocal8Bit().constData() << '\n'; } return 0; } diff --git a/src/process/qgsprocess.h b/src/process/qgsprocess.h index 69e49f189f06..77d595ba3cba 100644 --- a/src/process/qgsprocess.h +++ b/src/process/qgsprocess.h @@ -71,6 +71,7 @@ class QgsProcessingExec int execute( const QString &algId, const QVariantMap ¶meters ); std::unique_ptr< QgsPythonUtils > mPythonUtils; + std::unique_ptr loadPythonSupport(); }; #endif // QGSPROCESS_H diff --git a/src/providers/arcgisrest/qgsafsdataitems.cpp b/src/providers/arcgisrest/qgsafsdataitems.cpp index 5bd2fa4986e8..2fac6c0a1376 100644 --- a/src/providers/arcgisrest/qgsafsdataitems.cpp +++ b/src/providers/arcgisrest/qgsafsdataitems.cpp @@ -29,7 +29,7 @@ QgsAfsRootItem::QgsAfsRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "AFS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "AFS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconAfs.svg" ); diff --git a/src/providers/arcgisrest/qgsafsdataitems.h b/src/providers/arcgisrest/qgsafsdataitems.h index 19156f661c91..86fc66f33f01 100644 --- a/src/providers/arcgisrest/qgsafsdataitems.h +++ b/src/providers/arcgisrest/qgsafsdataitems.h @@ -21,7 +21,7 @@ #include "qgsdataitemprovider.h" -class QgsAfsRootItem : public QgsDataCollectionItem +class QgsAfsRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/arcgisrest/qgsamsdataitems.cpp b/src/providers/arcgisrest/qgsamsdataitems.cpp index a5bd36406c28..dcf324c0c2ef 100644 --- a/src/providers/arcgisrest/qgsamsdataitems.cpp +++ b/src/providers/arcgisrest/qgsamsdataitems.cpp @@ -27,7 +27,7 @@ #include QgsAmsRootItem::QgsAmsRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "AMS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "AMS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconAms.svg" ); diff --git a/src/providers/arcgisrest/qgsamsdataitems.h b/src/providers/arcgisrest/qgsamsdataitems.h index a950945232f6..aa57984a68bc 100644 --- a/src/providers/arcgisrest/qgsamsdataitems.h +++ b/src/providers/arcgisrest/qgsamsdataitems.h @@ -23,7 +23,7 @@ #include "qgsdataitemprovider.h" -class QgsAmsRootItem : public QgsDataCollectionItem +class QgsAmsRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/db2/qgsdb2dataitems.cpp b/src/providers/db2/qgsdb2dataitems.cpp index b0fd9e46dd22..07f630ac2b1c 100644 --- a/src/providers/db2/qgsdb2dataitems.cpp +++ b/src/providers/db2/qgsdb2dataitems.cpp @@ -334,7 +334,7 @@ bool QgsDb2ConnectionItem::handleDrop( const QMimeData *data, const QString &toS } QgsDb2RootItem::QgsDb2RootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "DB2" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "DB2" ) ) { mIconName = QStringLiteral( "mIconDb2.svg" ); populate(); diff --git a/src/providers/db2/qgsdb2dataitems.h b/src/providers/db2/qgsdb2dataitems.h index bfe82b96e9b5..bc689b4b62dc 100644 --- a/src/providers/db2/qgsdb2dataitems.h +++ b/src/providers/db2/qgsdb2dataitems.h @@ -30,7 +30,7 @@ class QgsDb2LayerItem; * \class QgsDb2RootItem * \brief Browser Panel DB2 root object. */ -class QgsDb2RootItem : public QgsDataCollectionItem +class QgsDb2RootItem : public QgsConnectionsRootItem { Q_OBJECT diff --git a/src/providers/geonode/qgsgeonodedataitems.cpp b/src/providers/geonode/qgsgeonodedataitems.cpp index 35ea8895fa8a..f8da694e70bd 100644 --- a/src/providers/geonode/qgsgeonodedataitems.cpp +++ b/src/providers/geonode/qgsgeonodedataitems.cpp @@ -186,7 +186,7 @@ void QgsGeoNodeServiceItem::replacePath( QgsDataItem *item, const QString &befor } QgsGeoNodeRootItem::QgsGeoNodeRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "GeoNode" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "GeoNode" ) ) { mCapabilities |= Fast; { diff --git a/src/providers/geonode/qgsgeonodedataitems.h b/src/providers/geonode/qgsgeonodedataitems.h index 42b541c5cf7d..6b6be83160dd 100644 --- a/src/providers/geonode/qgsgeonodedataitems.h +++ b/src/providers/geonode/qgsgeonodedataitems.h @@ -56,7 +56,7 @@ class QgsGeoNodeServiceItem : public QgsDataCollectionItem bool layerCollection() const override; }; -class QgsGeoNodeRootItem : public QgsDataCollectionItem +class QgsGeoNodeRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/mssql/qgsmssqlconnection.cpp b/src/providers/mssql/qgsmssqlconnection.cpp index 4f276d778219..e474e6a06584 100644 --- a/src/providers/mssql/qgsmssqlconnection.cpp +++ b/src/providers/mssql/qgsmssqlconnection.cpp @@ -423,6 +423,36 @@ QStringList QgsMssqlConnection::connectionList() return settings.childGroups(); } +QList QgsMssqlConnection::nativeTypes() +{ + return QList() + // integer types + << QgsVectorDataProvider::NativeType( QObject::tr( "8 Bytes integer" ), QStringLiteral( "bigint" ), QVariant::Int ) + << QgsVectorDataProvider::NativeType( QObject::tr( "4 Bytes integer" ), QStringLiteral( "int" ), QVariant::Int ) + << QgsVectorDataProvider::NativeType( QObject::tr( "2 Bytes integer" ), QStringLiteral( "smallint" ), QVariant::Int ) + << QgsVectorDataProvider::NativeType( QObject::tr( "1 Bytes integer" ), QStringLiteral( "tinyint" ), QVariant::Int ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Decimal number (numeric)" ), QStringLiteral( "numeric" ), QVariant::Double, 1, 20, 0, 20 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Decimal number (decimal)" ), QStringLiteral( "decimal" ), QVariant::Double, 1, 20, 0, 20 ) + + // floating point + << QgsVectorDataProvider::NativeType( QObject::tr( "Decimal number (real)" ), QStringLiteral( "real" ), QVariant::Double ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Decimal number (double)" ), QStringLiteral( "float" ), QVariant::Double ) + + // date/time types + << QgsVectorDataProvider::NativeType( QObject::tr( "Date" ), QStringLiteral( "date" ), QVariant::Date, -1, -1, -1, -1 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Time" ), QStringLiteral( "time" ), QVariant::Time, -1, -1, -1, -1 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Date & Time" ), QStringLiteral( "datetime" ), QVariant::DateTime, -1, -1, -1, -1 ) + + // string types + << QgsVectorDataProvider::NativeType( QObject::tr( "Text, fixed length (char)" ), QStringLiteral( "char" ), QVariant::String, 1, 255 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Text, limited variable length (varchar)" ), QStringLiteral( "varchar" ), QVariant::String, 1, 255 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Text, fixed length unicode (nchar)" ), QStringLiteral( "nchar" ), QVariant::String, 1, 255 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Text, limited variable length unicode (nvarchar)" ), QStringLiteral( "nvarchar" ), QVariant::String, 1, 255 ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Text, unlimited length (text)" ), QStringLiteral( "text" ), QVariant::String ) + << QgsVectorDataProvider::NativeType( QObject::tr( "Text, unlimited length unicode (ntext)" ), QStringLiteral( "text" ), QVariant::String ) + ; +} + QString QgsMssqlConnection::dbConnectionName( const QString &name ) { // Starting with Qt 5.11, sharing the same connection between threads is not allowed. diff --git a/src/providers/mssql/qgsmssqlconnection.h b/src/providers/mssql/qgsmssqlconnection.h index 16e71b9e5a0c..ab0bc6d35dff 100644 --- a/src/providers/mssql/qgsmssqlconnection.h +++ b/src/providers/mssql/qgsmssqlconnection.h @@ -22,6 +22,7 @@ #include #include "qgsdatasourceuri.h" +#include "qgsvectordataprovider.h" class QString; class QSqlDatabase; @@ -163,6 +164,12 @@ class QgsMssqlConnection */ static QStringList connectionList(); + /** + * Returns the list of native types + * \since QGIS 3.16 + */ + static QList nativeTypes(); + private: diff --git a/src/providers/mssql/qgsmssqldataitemguiprovider.cpp b/src/providers/mssql/qgsmssqldataitemguiprovider.cpp index 64ea68051334..ad2d1a7845ad 100644 --- a/src/providers/mssql/qgsmssqldataitemguiprovider.cpp +++ b/src/providers/mssql/qgsmssqldataitemguiprovider.cpp @@ -60,7 +60,7 @@ void QgsMssqlDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu connect( actionShowNoGeom, &QAction::toggled, connItem, &QgsMssqlConnectionItem::setAllowGeometrylessTables ); menu->addAction( actionShowNoGeom ); - QAction *actionCreateSchema = new QAction( tr( "Create Schema…" ), menu ); + QAction *actionCreateSchema = new QAction( tr( "New Schema…" ), menu ); connect( actionCreateSchema, &QAction::triggered, this, [connItem] { createSchema( connItem ); } ); menu->addAction( actionCreateSchema ); } @@ -83,7 +83,7 @@ void QgsMssqlDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu } } -bool QgsMssqlDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGuiContext ) +bool QgsMssqlDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGuiContext context ) { if ( QgsMssqlLayerItem *layerItem = qobject_cast< QgsMssqlLayerItem * >( item ) ) { @@ -105,11 +105,11 @@ bool QgsMssqlDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGu if ( !res ) { - QMessageBox::warning( nullptr, tr( "Delete %1" ).arg( typeName ), errCause ); + notify( tr( "Delete %1" ).arg( typeName ), errCause, context, Qgis::MessageLevel::Warning ); } else { - QMessageBox::information( nullptr, tr( "Delete %1" ).arg( typeName ), tr( "%1 deleted successfully." ).arg( typeName ) ); + notify( tr( "Delete %1" ).arg( typeName ), tr( "%1 deleted successfully." ).arg( typeName ), context, Qgis::MessageLevel::Success ); if ( connItem ) connItem->refresh(); } diff --git a/src/providers/mssql/qgsmssqldataitems.cpp b/src/providers/mssql/qgsmssqldataitems.cpp index 6ca90efd734d..8f9d65096d4a 100644 --- a/src/providers/mssql/qgsmssqldataitems.cpp +++ b/src/providers/mssql/qgsmssqldataitems.cpp @@ -481,7 +481,7 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name, { mCapabilities |= Delete; mUri = createUri(); - setState( Populated ); + setState( NotPopulated ); } @@ -520,7 +520,7 @@ QString QgsMssqlLayerItem::createUri() // --------------------------------------------------------------------------- QgsMssqlSchemaItem::QgsMssqlSchemaItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "MSSQL" ) ) + : QgsDatabaseSchemaItem( parent, name, path, QStringLiteral( "MSSQL" ) ) { mIconName = QStringLiteral( "mIconDbSchema.svg" ); //not fertile, since children are created by QgsMssqlConnectionItem @@ -592,14 +592,31 @@ QgsMssqlLayerItem *QgsMssqlSchemaItem::addLayer( const QgsMssqlLayerProperty &la if ( refresh ) addChildItem( layerItem, true ); else + { addChild( layerItem ); + layerItem->setParent( this ); + } return layerItem; } +void QgsMssqlSchemaItem::refresh() +{ + if ( parent() ) + parent()->refresh(); +} + + +QVector QgsMssqlLayerItem::createChildren() +{ + QVector children; + children.push_back( new QgsFieldsItem( this, uri() + QStringLiteral( "/columns/ " ), createUri(), providerKey(), mLayerProperty.schemaName, mLayerProperty.tableName ) ); + return children; +} + // --------------------------------------------------------------------------- QgsMssqlRootItem::QgsMssqlRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "MSSQL" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "MSSQL" ) ) { mIconName = QStringLiteral( "mIconMssql.svg" ); populate(); @@ -658,4 +675,3 @@ bool QgsMssqlSchemaItem::layerCollection() const { return true; } - diff --git a/src/providers/mssql/qgsmssqldataitems.h b/src/providers/mssql/qgsmssqldataitems.h index 9244ed6f03a8..a5979f88cae4 100644 --- a/src/providers/mssql/qgsmssqldataitems.h +++ b/src/providers/mssql/qgsmssqldataitems.h @@ -31,7 +31,7 @@ class QgsMssqlConnectionItem; class QgsMssqlSchemaItem; class QgsMssqlLayerItem; -class QgsMssqlRootItem : public QgsDataCollectionItem +class QgsMssqlRootItem : public QgsConnectionsRootItem { Q_OBJECT public: @@ -96,7 +96,7 @@ class QgsMssqlConnectionItem : public QgsDataCollectionItem void stop(); }; -class QgsMssqlSchemaItem : public QgsDataCollectionItem +class QgsMssqlSchemaItem : public QgsDatabaseSchemaItem { Q_OBJECT public: @@ -105,10 +105,9 @@ class QgsMssqlSchemaItem : public QgsDataCollectionItem QVector createChildren() override; QgsMssqlLayerItem *addLayer( const QgsMssqlLayerProperty &layerProperty, bool refresh ); - void refresh() override {} // do not refresh directly + void refresh() override; // do not refresh directly (call parent) void addLayers( QgsDataItem *newLayers ); - // QgsDataItem interface public: bool layerCollection() const override; }; @@ -128,11 +127,16 @@ class QgsMssqlLayerItem : public QgsLayerItem const QgsMssqlLayerProperty &layerInfo() const { return mLayerProperty; } + QVector createChildren() override; + private: QgsMssqlLayerProperty mLayerProperty; bool mDisableInvalidGeometryHandling = false; + }; + + //! Provider for GDAL root data item class QgsMssqlDataItemProvider : public QgsDataItemProvider { diff --git a/src/providers/mssql/qgsmssqlprovider.cpp b/src/providers/mssql/qgsmssqlprovider.cpp index 84b38628fc0e..5eedd056e0bd 100644 --- a/src/providers/mssql/qgsmssqlprovider.cpp +++ b/src/providers/mssql/qgsmssqlprovider.cpp @@ -149,32 +149,7 @@ QgsMssqlProvider::QgsMssqlProvider( const QString &uri, const ProviderOptions &o } //fill type names into sets - setNativeTypes( QList() - // integer types - << QgsVectorDataProvider::NativeType( tr( "8 Bytes integer" ), QStringLiteral( "bigint" ), QVariant::Int ) - << QgsVectorDataProvider::NativeType( tr( "4 Bytes integer" ), QStringLiteral( "int" ), QVariant::Int ) - << QgsVectorDataProvider::NativeType( tr( "2 Bytes integer" ), QStringLiteral( "smallint" ), QVariant::Int ) - << QgsVectorDataProvider::NativeType( tr( "1 Bytes integer" ), QStringLiteral( "tinyint" ), QVariant::Int ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (numeric)" ), QStringLiteral( "numeric" ), QVariant::Double, 1, 20, 0, 20 ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (decimal)" ), QStringLiteral( "decimal" ), QVariant::Double, 1, 20, 0, 20 ) - - // floating point - << QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), QStringLiteral( "real" ), QVariant::Double ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), QStringLiteral( "float" ), QVariant::Double ) - - // date/time types - << QgsVectorDataProvider::NativeType( tr( "Date" ), QStringLiteral( "date" ), QVariant::Date, -1, -1, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Time" ), QStringLiteral( "time" ), QVariant::Time, -1, -1, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), QStringLiteral( "datetime" ), QVariant::DateTime, -1, -1, -1, -1 ) - - // string types - << QgsVectorDataProvider::NativeType( tr( "Text, fixed length (char)" ), QStringLiteral( "char" ), QVariant::String, 1, 255 ) - << QgsVectorDataProvider::NativeType( tr( "Text, limited variable length (varchar)" ), QStringLiteral( "varchar" ), QVariant::String, 1, 255 ) - << QgsVectorDataProvider::NativeType( tr( "Text, fixed length unicode (nchar)" ), QStringLiteral( "nchar" ), QVariant::String, 1, 255 ) - << QgsVectorDataProvider::NativeType( tr( "Text, limited variable length unicode (nvarchar)" ), QStringLiteral( "nvarchar" ), QVariant::String, 1, 255 ) - << QgsVectorDataProvider::NativeType( tr( "Text, unlimited length (text)" ), QStringLiteral( "text" ), QVariant::String ) - << QgsVectorDataProvider::NativeType( tr( "Text, unlimited length unicode (ntext)" ), QStringLiteral( "text" ), QVariant::String ) - ); + setNativeTypes( QgsMssqlConnection::nativeTypes() ); } QgsMssqlProvider::~QgsMssqlProvider() @@ -1864,7 +1839,7 @@ QgsVectorLayerExporter::ExportError QgsMssqlProvider::createEmptyLayer( const QS { // found, get the field type QgsField fld = fields.at( i ); - if ( convertField( fld ) ) + if ( ( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) || convertField( fld ) ) { primaryKeyType = fld.typeName(); } @@ -2044,7 +2019,7 @@ QgsVectorLayerExporter::ExportError QgsMssqlProvider::createEmptyLayer( const QS continue; } - if ( !convertField( fld ) ) + if ( !( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) && !convertField( fld ) ) { if ( errorMessage ) *errorMessage = QObject::tr( "Unsupported type for field %1" ).arg( fld.name() ); diff --git a/src/providers/mssql/qgsmssqlproviderconnection.cpp b/src/providers/mssql/qgsmssqlproviderconnection.cpp index 57edbfc3142c..f9c62fb181ca 100644 --- a/src/providers/mssql/qgsmssqlproviderconnection.cpp +++ b/src/providers/mssql/qgsmssqlproviderconnection.cpp @@ -37,6 +37,7 @@ const QStringList QgsMssqlProviderConnection::EXTRA_CONNECTION_PARAMETERS QgsMssqlProviderConnection::QgsMssqlProviderConnection( const QString &name ) : QgsAbstractDatabaseProviderConnection( name ) { + mProviderKey = QStringLiteral( "mssql" ); // Remove the sql and table empty parts setUri( QgsMssqlConnection::connUri( name ).uri() ); setDefaultCapabilities(); @@ -45,6 +46,7 @@ QgsMssqlProviderConnection::QgsMssqlProviderConnection( const QString &name ) QgsMssqlProviderConnection::QgsMssqlProviderConnection( const QString &uri, const QVariantMap &configuration ): QgsAbstractDatabaseProviderConnection( QString(), configuration ) { + mProviderKey = QStringLiteral( "mssql" ); // Additional connection information const QgsDataSourceUri inputUri( uri ); QgsDataSourceUri currentUri { QgsDataSourceUri( uri ).connectionInfo( false ) }; @@ -81,7 +83,16 @@ void QgsMssqlProviderConnection::setDefaultCapabilities() Capability::Tables, Capability::Schemas, Capability::Spatial, - Capability::TableExists + Capability::TableExists, + Capability::DeleteField, + Capability::DeleteFieldCascade, + Capability::AddField + }; + mGeometryColumnCapabilities = + { + GeometryColumnCapability::Z, + GeometryColumnCapability::M, + GeometryColumnCapability::Curves }; } @@ -483,3 +494,8 @@ QIcon QgsMssqlProviderConnection::icon() const return QgsApplication::getThemeIcon( QStringLiteral( "mIconMssql.svg" ) ); } + +QList QgsMssqlProviderConnection::nativeTypes() const +{ + return QgsMssqlConnection::nativeTypes(); +} diff --git a/src/providers/mssql/qgsmssqlproviderconnection.h b/src/providers/mssql/qgsmssqlproviderconnection.h index ff1f18d3750d..2b8ca1723d80 100644 --- a/src/providers/mssql/qgsmssqlproviderconnection.h +++ b/src/providers/mssql/qgsmssqlproviderconnection.h @@ -48,6 +48,7 @@ class QgsMssqlProviderConnection : public QgsAbstractDatabaseProviderConnection void store( const QString &name ) const override; void remove( const QString &name ) const override; QIcon icon() const override; + QList nativeTypes() const override; private: @@ -57,6 +58,9 @@ class QgsMssqlProviderConnection : public QgsAbstractDatabaseProviderConnection void renameTablePrivate( const QString &schema, const QString &name, const QString &newName ) const; static const QStringList EXTRA_CONNECTION_PARAMETERS; + }; + + #endif // QGSMSSQLPROVIDERCONNECTION_H diff --git a/src/providers/oracle/qgsoracledataitems.cpp b/src/providers/oracle/qgsoracledataitems.cpp index 94c211828a36..f6077bdb6308 100644 --- a/src/providers/oracle/qgsoracledataitems.cpp +++ b/src/providers/oracle/qgsoracledataitems.cpp @@ -536,7 +536,7 @@ void QgsOracleOwnerItem::addLayer( const QgsOracleLayerProperty &layerProperty ) // --------------------------------------------------------------------------- QgsOracleRootItem::QgsOracleRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "ORACLE" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "ORACLE" ) ) { mIconName = QStringLiteral( "mIconOracle.svg" ); populate(); diff --git a/src/providers/oracle/qgsoracledataitems.h b/src/providers/oracle/qgsoracledataitems.h index 3ee1d5e2cad6..cb30947be035 100644 --- a/src/providers/oracle/qgsoracledataitems.h +++ b/src/providers/oracle/qgsoracledataitems.h @@ -34,7 +34,7 @@ class QgsOracleOwnerItem; class QgsOracleLayerItem; class QgsProxyProgressTask; -class QgsOracleRootItem : public QgsDataCollectionItem +class QgsOracleRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/oracle/qgsoracleprovider.cpp b/src/providers/oracle/qgsoracleprovider.cpp index 0339b73cc5ac..4bc0276ee286 100644 --- a/src/providers/oracle/qgsoracleprovider.cpp +++ b/src/providers/oracle/qgsoracleprovider.cpp @@ -2990,7 +2990,7 @@ QgsVectorLayerExporter::ExportError QgsOracleProvider::createEmptyLayer( if ( idx >= 0 ) { QgsField fld = fields.at( idx ); - if ( convertField( fld ) ) + if ( ( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) || convertField( fld ) ) { primaryKeyType = fld.typeName(); } @@ -3243,7 +3243,7 @@ QgsVectorLayerExporter::ExportError QgsOracleProvider::createEmptyLayer( continue; } - if ( !convertField( fld ) ) + if ( !( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) && ! convertField( fld ) ) { errorMessage = QObject::tr( "Unsupported type for field %1" ).arg( fld.name() ); diff --git a/src/providers/ows/qgsowsdataitems.cpp b/src/providers/ows/qgsowsdataitems.cpp index b1a3bff80365..4f9fb8cf45b1 100644 --- a/src/providers/ows/qgsowsdataitems.cpp +++ b/src/providers/ows/qgsowsdataitems.cpp @@ -141,7 +141,7 @@ bool QgsOWSConnectionItem::equal( const QgsDataItem *other ) QgsOWSRootItem::QgsOWSRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "OWS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "OWS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconOws.svg" ); diff --git a/src/providers/ows/qgsowsdataitems.h b/src/providers/ows/qgsowsdataitems.h index 3bcf02eeaa78..8d3836f8b375 100644 --- a/src/providers/ows/qgsowsdataitems.h +++ b/src/providers/ows/qgsowsdataitems.h @@ -32,7 +32,7 @@ class QgsOWSConnectionItem : public QgsDataCollectionItem void replacePath( QgsDataItem *item, QString before, QString after ); }; -class QgsOWSRootItem : public QgsDataCollectionItem +class QgsOWSRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/postgres/qgspostgresconn.cpp b/src/providers/postgres/qgspostgresconn.cpp index 4238f9e28df0..f993cb0b0426 100644 --- a/src/providers/postgres/qgspostgresconn.cpp +++ b/src/providers/postgres/qgspostgresconn.cpp @@ -1677,6 +1677,58 @@ QString QgsPostgresConn::fieldExpression( const QgsField &fld, QString expr ) } } +QList QgsPostgresConn::nativeTypes() +{ + QList types; + + types // integer types + << QgsVectorDataProvider::NativeType( tr( "Whole number (smallint - 16bit)" ), QStringLiteral( "int2" ), QVariant::Int, -1, -1, 0, 0 ) + << QgsVectorDataProvider::NativeType( tr( "Whole number (integer - 32bit)" ), QStringLiteral( "int4" ), QVariant::Int, -1, -1, 0, 0 ) + << QgsVectorDataProvider::NativeType( tr( "Whole number (integer - 64bit)" ), QStringLiteral( "int8" ), QVariant::LongLong, -1, -1, 0, 0 ) + << QgsVectorDataProvider::NativeType( tr( "Decimal number (numeric)" ), QStringLiteral( "numeric" ), QVariant::Double, 1, 20, 0, 20 ) + << QgsVectorDataProvider::NativeType( tr( "Decimal number (decimal)" ), QStringLiteral( "decimal" ), QVariant::Double, 1, 20, 0, 20 ) + + // floating point + << QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), QStringLiteral( "real" ), QVariant::Double, -1, -1, -1, -1 ) + << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), QStringLiteral( "double precision" ), QVariant::Double, -1, -1, -1, -1 ) + + // string types + << QgsVectorDataProvider::NativeType( tr( "Text, fixed length (char)" ), QStringLiteral( "char" ), QVariant::String, 1, 255, -1, -1 ) + << QgsVectorDataProvider::NativeType( tr( "Text, limited variable length (varchar)" ), QStringLiteral( "varchar" ), QVariant::String, 1, 255, -1, -1 ) + << QgsVectorDataProvider::NativeType( tr( "Text, unlimited length (text)" ), QStringLiteral( "text" ), QVariant::String, -1, -1, -1, -1 ) + << QgsVectorDataProvider::NativeType( tr( "Text, case-insensitive unlimited length (citext)" ), QStringLiteral( "citext" ), QVariant::String, -1, -1, -1, -1 ) + + // date type + << QgsVectorDataProvider::NativeType( tr( "Date" ), QStringLiteral( "date" ), QVariant::Date, -1, -1, -1, -1 ) + << QgsVectorDataProvider::NativeType( tr( "Time" ), QStringLiteral( "time" ), QVariant::Time, -1, -1, -1, -1 ) + << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), QStringLiteral( "timestamp without time zone" ), QVariant::DateTime, -1, -1, -1, -1 ) + + // complex types + << QgsVectorDataProvider::NativeType( tr( "Map (hstore)" ), QStringLiteral( "hstore" ), QVariant::Map, -1, -1, -1, -1, QVariant::String ) + << QgsVectorDataProvider::NativeType( tr( "Array of number (integer - 32bit)" ), QStringLiteral( "int4[]" ), QVariant::List, -1, -1, -1, -1, QVariant::Int ) + << QgsVectorDataProvider::NativeType( tr( "Array of number (integer - 64bit)" ), QStringLiteral( "int8[]" ), QVariant::List, -1, -1, -1, -1, QVariant::LongLong ) + << QgsVectorDataProvider::NativeType( tr( "Array of number (double)" ), QStringLiteral( "double precision[]" ), QVariant::List, -1, -1, -1, -1, QVariant::Double ) + << QgsVectorDataProvider::NativeType( tr( "Array of text" ), QStringLiteral( "text[]" ), QVariant::StringList, -1, -1, -1, -1, QVariant::String ) + + // boolean + << QgsVectorDataProvider::NativeType( tr( "Boolean" ), QStringLiteral( "bool" ), QVariant::Bool, -1, -1, -1, -1 ) + + // binary (bytea) + << QgsVectorDataProvider::NativeType( tr( "Binary object (bytea)" ), QStringLiteral( "bytea" ), QVariant::ByteArray, -1, -1, -1, -1 ) + ; + + if ( pgVersion() >= 90200 ) + { + types << QgsVectorDataProvider::NativeType( tr( "JSON (json)" ), QStringLiteral( "json" ), QVariant::Map, -1, -1, -1, -1, QVariant::String ); + + if ( pgVersion() >= 90400 ) + { + types << QgsVectorDataProvider::NativeType( tr( "JSON (jsonb)" ), QStringLiteral( "jsonb" ), QVariant::Map, -1, -1, -1, -1, QVariant::String ); + } + } + return types; +} + void QgsPostgresConn::deduceEndian() { QMutexLocker locker( &mLock ); diff --git a/src/providers/postgres/qgspostgresconn.h b/src/providers/postgres/qgspostgresconn.h index b15e54a05589..8ec6c0f89883 100644 --- a/src/providers/postgres/qgspostgresconn.h +++ b/src/providers/postgres/qgspostgresconn.h @@ -28,6 +28,7 @@ #include "qgsdatasourceuri.h" #include "qgswkbtypes.h" #include "qgsconfig.h" +#include "qgsvectordataprovider.h" extern "C" { @@ -345,6 +346,12 @@ class QgsPostgresConn : public QObject QString connInfo() const { return mConnInfo; } + /** + * Returns a list of supported native types for this connection. + * \since QGIS 3.16 + */ + QList nativeTypes(); + /** * Returns the underlying database. * diff --git a/src/providers/postgres/qgspostgresdataitemguiprovider.cpp b/src/providers/postgres/qgspostgresdataitemguiprovider.cpp index 547ff44377ef..5fdec319fd5c 100644 --- a/src/providers/postgres/qgspostgresdataitemguiprovider.cpp +++ b/src/providers/postgres/qgspostgresdataitemguiprovider.cpp @@ -52,9 +52,10 @@ void QgsPostgresDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe menu->addSeparator(); - QAction *actionCreateSchema = new QAction( tr( "Create Schema…" ), this ); + QAction *actionCreateSchema = new QAction( tr( "New Schema…" ), this ); connect( actionCreateSchema, &QAction::triggered, this, [connItem] { createSchema( connItem ); } ); menu->addAction( actionCreateSchema ); + } if ( QgsPGSchemaItem *schemaItem = qobject_cast< QgsPGSchemaItem * >( item ) ) @@ -100,7 +101,7 @@ void QgsPostgresDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe } -bool QgsPostgresDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGuiContext ) +bool QgsPostgresDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGuiContext context ) { if ( QgsPGLayerItem *layerItem = qobject_cast< QgsPGLayerItem * >( item ) ) { @@ -116,12 +117,12 @@ bool QgsPostgresDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataIte bool res = QgsPostgresUtils::deleteLayer( layerItem->uri(), errCause ); if ( !res ) { - QMessageBox::warning( nullptr, tr( "Delete %1" ).arg( typeName ), errCause ); + notify( tr( "Delete %1" ).arg( typeName ), errCause, context, Qgis::MessageLevel::Warning ); return false; } else { - QMessageBox::information( nullptr, tr( "Delete %1" ).arg( typeName ), tr( "%1 deleted successfully." ).arg( typeName ) ); + notify( tr( "Delete %1" ).arg( typeName ), tr( "%1 deleted successfully." ).arg( typeName ), context, Qgis::MessageLevel::Success ); if ( layerItem->parent() ) layerItem->parent()->refresh(); return true; @@ -225,7 +226,7 @@ void QgsPostgresDataItemGuiProvider::createSchema( QgsDataItem *item ) QgsPostgresConn *conn = QgsPostgresConn::connectDb( uri.connectionInfo( false ), false ); if ( !conn ) { - QMessageBox::warning( nullptr, tr( "Create Schema" ), tr( "Unable to create schema." ) ); + QMessageBox::warning( nullptr, tr( "New Schema" ), tr( "Unable to create schema." ) ); return; } @@ -235,7 +236,7 @@ void QgsPostgresDataItemGuiProvider::createSchema( QgsDataItem *item ) QgsPostgresResult result( conn->PQexec( sql ) ); if ( result.PQresultStatus() != PGRES_COMMAND_OK ) { - QMessageBox::warning( nullptr, tr( "Create Schema" ), tr( "Unable to create schema %1\n%2" ).arg( schemaName, + QMessageBox::warning( nullptr, tr( "New Schema" ), tr( "Unable to create schema %1\n%2" ).arg( schemaName, result.PQresultErrorMessage() ) ); conn->unref(); return; diff --git a/src/providers/postgres/qgspostgresdataitems.cpp b/src/providers/postgres/qgspostgresdataitems.cpp index f93934e58431..746bd605884a 100644 --- a/src/providers/postgres/qgspostgresdataitems.cpp +++ b/src/providers/postgres/qgspostgresdataitems.cpp @@ -314,9 +314,10 @@ QgsPGLayerItem::QgsPGLayerItem( QgsDataItem *parent, const QString &name, const : QgsLayerItem( parent, name, path, QString(), layerType, layerProperty.isRaster ? QStringLiteral( "postgresraster" ) : QStringLiteral( "postgres" ) ) , mLayerProperty( layerProperty ) { - mCapabilities |= Delete; + mCapabilities |= Delete | Fertile; mUri = createUri(); - setState( Populated ); + // No rasters for now + setState( layerProperty.isRaster ? Populated : NotPopulated ); Q_ASSERT( mLayerProperty.size() == 1 ); } @@ -367,7 +368,7 @@ QString QgsPGLayerItem::createUri() // --------------------------------------------------------------------------- QgsPGSchemaItem::QgsPGSchemaItem( QgsDataItem *parent, const QString &connectionName, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "PostGIS" ) ) + : QgsDatabaseSchemaItem( parent, name, path, QStringLiteral( "PostGIS" ) ) , mConnectionName( connectionName ) { mIconName = QStringLiteral( "mIconDbSchema.svg" ); @@ -523,10 +524,16 @@ QgsPGLayerItem *QgsPGSchemaItem::createLayer( QgsPostgresLayerProperty layerProp return layerItem; } +QVector QgsPGLayerItem::createChildren() +{ + QVector children; + children.push_back( new QgsFieldsItem( this, uri() + QStringLiteral( "/columns/ " ), createUri(), providerKey(), mLayerProperty.schemaName, mLayerProperty.tableName ) ); + return children; +} // --------------------------------------------------------------------------- QgsPGRootItem::QgsPGRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "PostGIS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "PostGIS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconPostgis.svg" ); diff --git a/src/providers/postgres/qgspostgresdataitems.h b/src/providers/postgres/qgspostgresdataitems.h index ff732efe7320..3fef8b635fdc 100644 --- a/src/providers/postgres/qgspostgresdataitems.h +++ b/src/providers/postgres/qgspostgresdataitems.h @@ -30,7 +30,7 @@ class QgsPGConnectionItem; class QgsPGSchemaItem; class QgsPGLayerItem; -class QgsPGRootItem : public QgsDataCollectionItem +class QgsPGRootItem : public QgsConnectionsRootItem { Q_OBJECT public: @@ -67,7 +67,7 @@ class QgsPGConnectionItem : public QgsDataCollectionItem }; -class QgsPGSchemaItem : public QgsDataCollectionItem +class QgsPGSchemaItem : public QgsDatabaseSchemaItem { Q_OBJECT public: @@ -100,10 +100,15 @@ class QgsPGLayerItem : public QgsLayerItem const QgsPostgresLayerProperty &layerInfo() const { return mLayerProperty; } + QVector createChildren() override; + private: QgsPostgresLayerProperty mLayerProperty; + }; + + //! Provider for Postgres data item class QgsPostgresDataItemProvider : public QgsDataItemProvider { diff --git a/src/providers/postgres/qgspostgresprovider.cpp b/src/providers/postgres/qgspostgresprovider.cpp index 2de5d21695c6..bc3f33aa4d97 100644 --- a/src/providers/postgres/qgspostgresprovider.cpp +++ b/src/providers/postgres/qgspostgresprovider.cpp @@ -222,55 +222,7 @@ QgsPostgresProvider::QgsPostgresProvider( QString const &uri, const ProviderOpti mConnectionRO->PQexecNR( QStringLiteral( "set client_min_messages to error" ) ); #endif - //fill type names into sets - QList nativeTypes; - - nativeTypes // integer types - << QgsVectorDataProvider::NativeType( tr( "Whole number (smallint - 16bit)" ), QStringLiteral( "int2" ), QVariant::Int, -1, -1, 0, 0 ) - << QgsVectorDataProvider::NativeType( tr( "Whole number (integer - 32bit)" ), QStringLiteral( "int4" ), QVariant::Int, -1, -1, 0, 0 ) - << QgsVectorDataProvider::NativeType( tr( "Whole number (integer - 64bit)" ), QStringLiteral( "int8" ), QVariant::LongLong, -1, -1, 0, 0 ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (numeric)" ), QStringLiteral( "numeric" ), QVariant::Double, 1, 20, 0, 20 ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (decimal)" ), QStringLiteral( "decimal" ), QVariant::Double, 1, 20, 0, 20 ) - - // floating point - << QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), QStringLiteral( "real" ), QVariant::Double, -1, -1, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), QStringLiteral( "double precision" ), QVariant::Double, -1, -1, -1, -1 ) - - // string types - << QgsVectorDataProvider::NativeType( tr( "Text, fixed length (char)" ), QStringLiteral( "char" ), QVariant::String, 1, 255, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Text, limited variable length (varchar)" ), QStringLiteral( "varchar" ), QVariant::String, 1, 255, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Text, unlimited length (text)" ), QStringLiteral( "text" ), QVariant::String, -1, -1, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Text, case-insensitive unlimited length (citext)" ), QStringLiteral( "citext" ), QVariant::String, -1, -1, -1, -1 ) - - // date type - << QgsVectorDataProvider::NativeType( tr( "Date" ), QStringLiteral( "date" ), QVariant::Date, -1, -1, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Time" ), QStringLiteral( "time" ), QVariant::Time, -1, -1, -1, -1 ) - << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), QStringLiteral( "timestamp without time zone" ), QVariant::DateTime, -1, -1, -1, -1 ) - - // complex types - << QgsVectorDataProvider::NativeType( tr( "Map (hstore)" ), QStringLiteral( "hstore" ), QVariant::Map, -1, -1, -1, -1, QVariant::String ) - << QgsVectorDataProvider::NativeType( tr( "Array of number (integer - 32bit)" ), QStringLiteral( "int4[]" ), QVariant::List, -1, -1, -1, -1, QVariant::Int ) - << QgsVectorDataProvider::NativeType( tr( "Array of number (integer - 64bit)" ), QStringLiteral( "int8[]" ), QVariant::List, -1, -1, -1, -1, QVariant::LongLong ) - << QgsVectorDataProvider::NativeType( tr( "Array of number (double)" ), QStringLiteral( "double precision[]" ), QVariant::List, -1, -1, -1, -1, QVariant::Double ) - << QgsVectorDataProvider::NativeType( tr( "Array of text" ), QStringLiteral( "text[]" ), QVariant::StringList, -1, -1, -1, -1, QVariant::String ) - - // boolean - << QgsVectorDataProvider::NativeType( tr( "Boolean" ), QStringLiteral( "bool" ), QVariant::Bool, -1, -1, -1, -1 ) - - // binary (bytea) - << QgsVectorDataProvider::NativeType( tr( "Binary object (bytea)" ), QStringLiteral( "bytea" ), QVariant::ByteArray, -1, -1, -1, -1 ) - ; - - if ( connectionRO()->pgVersion() >= 90200 ) - { - nativeTypes << QgsVectorDataProvider::NativeType( tr( "JSON (json)" ), QStringLiteral( "json" ), QVariant::Map, -1, -1, -1, -1, QVariant::String ); - - if ( connectionRO()->pgVersion() >= 90400 ) - { - nativeTypes << QgsVectorDataProvider::NativeType( tr( "JSON (jsonb)" ), QStringLiteral( "jsonb" ), QVariant::Map, -1, -1, -1, -1, QVariant::String ); - } - } - setNativeTypes( nativeTypes ); + setNativeTypes( mConnectionRO->nativeTypes() ); QString key; switch ( mPrimaryKeyType ) @@ -4495,7 +4447,7 @@ QgsVectorLayerExporter::ExportError QgsPostgresProvider::createEmptyLayer( const continue; } - if ( !convertField( fld, options ) ) + if ( !( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) && !convertField( fld, options ) ) { if ( errorMessage ) *errorMessage = QObject::tr( "Unsupported type for field %1" ).arg( fld.name() ); @@ -4517,7 +4469,7 @@ QgsVectorLayerExporter::ExportError QgsPostgresProvider::createEmptyLayer( const if ( !provider->addAttributes( flist ) ) { if ( errorMessage ) - *errorMessage = QObject::tr( "Creation of fields failed" ); + *errorMessage = QObject::tr( "Creation of fields failed:\n%1" ).arg( provider->errors().join( '\n' ) ); return QgsVectorLayerExporter::ErrAttributeCreationFailed; } diff --git a/src/providers/postgres/qgspostgresprovider.h b/src/providers/postgres/qgspostgresprovider.h index 47a4bbc1e3ee..a56cfc94aefc 100644 --- a/src/providers/postgres/qgspostgresprovider.h +++ b/src/providers/postgres/qgspostgresprovider.h @@ -241,7 +241,6 @@ class QgsPostgresProvider final: public QgsVectorDataProvider */ void setListening( bool isListening ) override; - private: Relkind relkind() const; diff --git a/src/providers/postgres/qgspostgresproviderconnection.cpp b/src/providers/postgres/qgspostgresproviderconnection.cpp index 9ab1267bf292..dea509b48e91 100644 --- a/src/providers/postgres/qgspostgresproviderconnection.cpp +++ b/src/providers/postgres/qgspostgresproviderconnection.cpp @@ -29,6 +29,7 @@ extern "C" QgsPostgresProviderConnection::QgsPostgresProviderConnection( const QString &name ) : QgsAbstractDatabaseProviderConnection( name ) { + mProviderKey = QStringLiteral( "postgres" ); // Remove the sql and table empty parts const QRegularExpression removePartsRe { R"raw(\s*sql=\s*|\s*table=""\s*)raw" }; setUri( QgsPostgresConn::connUri( name ).uri().replace( removePartsRe, QString() ) ); @@ -38,6 +39,7 @@ QgsPostgresProviderConnection::QgsPostgresProviderConnection( const QString &nam QgsPostgresProviderConnection::QgsPostgresProviderConnection( const QString &uri, const QVariantMap &configuration ): QgsAbstractDatabaseProviderConnection( QgsDataSourceUri( uri ).connectionInfo( false ), configuration ) { + mProviderKey = QStringLiteral( "postgres" ); setDefaultCapabilities(); } @@ -65,7 +67,17 @@ void QgsPostgresProviderConnection::setDefaultCapabilities() Capability::TableExists, Capability::CreateSpatialIndex, Capability::SpatialIndexExists, - Capability::DeleteSpatialIndex + Capability::DeleteSpatialIndex, + Capability::DeleteField, + Capability::DeleteFieldCascade, + Capability::AddField + }; + mGeometryColumnCapabilities = + { + GeometryColumnCapability::Z, + GeometryColumnCapability::M, + GeometryColumnCapability::SinglePart, + GeometryColumnCapability::Curves }; } @@ -328,17 +340,34 @@ void QgsPostgresProviderConnection::vacuum( const QString &schema, const QString void QgsPostgresProviderConnection::createSpatialIndex( const QString &schema, const QString &name, const QgsAbstractDatabaseProviderConnection::SpatialIndexOptions &options ) const { - if ( options.geometryColumnName.isEmpty() ) - throw QgsProviderConnectionException( QObject::tr( "Geometry column name not specified while creating spatial index" ) ); - checkCapability( Capability::CreateSpatialIndex ); - const QString indexName = QStringLiteral( "sidx_%1_%2" ).arg( name, options.geometryColumnName ); + QString geometryColumnName { options.geometryColumnName }; + if ( geometryColumnName.isEmpty() ) + { + // Can we guess it? + try + { + const auto tp { table( schema, name ) }; + geometryColumnName = tp.geometryColumn(); + } + catch ( QgsProviderConnectionException & ) + { + // pass + } + } + + if ( geometryColumnName.isEmpty() ) + { + throw QgsProviderConnectionException( QObject::tr( "Geometry column name not specified while creating spatial index" ) ); + } + + const QString indexName = QStringLiteral( "sidx_%1_%2" ).arg( name, geometryColumnName ); executeSql( QStringLiteral( "CREATE INDEX %1 ON %2.%3 USING GIST (%4);" ) .arg( indexName, QgsPostgresConn::quotedIdentifier( schema ), QgsPostgresConn::quotedIdentifier( name ), - QgsPostgresConn::quotedIdentifier( options.geometryColumnName ) ) ); + QgsPostgresConn::quotedIdentifier( geometryColumnName ) ) ); } bool QgsPostgresProviderConnection::spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const @@ -575,3 +604,19 @@ QIcon QgsPostgresProviderConnection::icon() const return QgsApplication::getThemeIcon( QStringLiteral( "mIconPostgis.svg" ) ); } + +QList QgsPostgresProviderConnection::nativeTypes() const +{ + QList types; + QgsPostgresConn *conn = QgsPostgresConnPool::instance()->acquireConnection( QgsDataSourceUri{ uri() }.connectionInfo( false ) ); + if ( conn ) + { + types = conn->nativeTypes(); + QgsPostgresConnPool::instance()->releaseConnection( conn ); + } + if ( types.isEmpty() ) + { + throw QgsProviderConnectionException( QObject::tr( "Error retrieving native types for connection %1" ).arg( uri() ) ); + } + return types; +} diff --git a/src/providers/postgres/qgspostgresproviderconnection.h b/src/providers/postgres/qgspostgresproviderconnection.h index 7edb458f6f10..6ead3fe05d94 100644 --- a/src/providers/postgres/qgspostgresproviderconnection.h +++ b/src/providers/postgres/qgspostgresproviderconnection.h @@ -56,6 +56,7 @@ class QgsPostgresProviderConnection : public QgsAbstractDatabaseProviderConnecti void store( const QString &name ) const override; void remove( const QString &name ) const override; QIcon icon() const override; + QList nativeTypes() const override; private: @@ -63,6 +64,10 @@ class QgsPostgresProviderConnection : public QgsAbstractDatabaseProviderConnecti void setDefaultCapabilities(); void dropTablePrivate( const QString &schema, const QString &name ) const; void renameTablePrivate( const QString &schema, const QString &name, const QString &newName ) const; + + }; + + #endif // QGSPOSTGRESPROVIDERCONNECTION_H diff --git a/src/providers/spatialite/qgsspatialiteconnection.cpp b/src/providers/spatialite/qgsspatialiteconnection.cpp index 98d4d3badbed..fb9e94257f03 100644 --- a/src/providers/spatialite/qgsspatialiteconnection.cpp +++ b/src/providers/spatialite/qgsspatialiteconnection.cpp @@ -26,6 +26,9 @@ #define strcasecmp(a,b) stricmp(a,b) #endif +const QString QgsSpatiaLiteConnection::SPATIALITE_ARRAY_PREFIX = QStringLiteral( "json" ); +const QString QgsSpatiaLiteConnection::SPATIALITE_ARRAY_SUFFIX = QStringLiteral( "list" ); + QStringList QgsSpatiaLiteConnection::connectionList() { QgsSettings settings; @@ -103,6 +106,21 @@ bool QgsSpatiaLiteConnection::updateStatistics() return ret; } +QList QgsSpatiaLiteConnection::nativeTypes() +{ + return QList() + << QgsVectorDataProvider::NativeType( tr( "Binary object (BLOB)" ), QStringLiteral( "BLOB" ), QVariant::ByteArray ) + << QgsVectorDataProvider::NativeType( tr( "Text" ), QStringLiteral( "TEXT" ), QVariant::String ) + << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), QStringLiteral( "FLOAT" ), QVariant::Double ) + << QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), QStringLiteral( "INTEGER" ), QVariant::LongLong ) + << QgsVectorDataProvider::NativeType( tr( "Date" ), QStringLiteral( "DATE" ), QVariant::Date ) + << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), QStringLiteral( "TIMESTAMP" ), QVariant::DateTime ) + + << QgsVectorDataProvider::NativeType( tr( "Array of text" ), SPATIALITE_ARRAY_PREFIX.toUpper() + "TEXT" + SPATIALITE_ARRAY_SUFFIX.toUpper(), QVariant::StringList, 0, 0, 0, 0, QVariant::String ) + << QgsVectorDataProvider::NativeType( tr( "Array of decimal numbers (double)" ), SPATIALITE_ARRAY_PREFIX.toUpper() + "REAL" + SPATIALITE_ARRAY_SUFFIX.toUpper(), QVariant::List, 0, 0, 0, 0, QVariant::Double ) + << QgsVectorDataProvider::NativeType( tr( "Array of whole numbers (integer)" ), SPATIALITE_ARRAY_PREFIX.toUpper() + "INTEGER" + SPATIALITE_ARRAY_SUFFIX.toUpper(), QVariant::List, 0, 0, 0, 0, QVariant::LongLong ); +} + int QgsSpatiaLiteConnection::checkHasMetadataTables( sqlite3 *handle ) { bool gcSpatiaLite = false; diff --git a/src/providers/spatialite/qgsspatialiteconnection.h b/src/providers/spatialite/qgsspatialiteconnection.h index 328b935c4099..6db33a17bd35 100644 --- a/src/providers/spatialite/qgsspatialiteconnection.h +++ b/src/providers/spatialite/qgsspatialiteconnection.h @@ -20,6 +20,7 @@ #include #include "qgsspatialiteutils.h" +#include "qgsvectordataprovider.h" extern "C" { @@ -80,6 +81,15 @@ class QgsSpatiaLiteConnection : public QObject //! Updates the Internal Statistics bool updateStatistics(); + /** + * Returns a list of supported nativeTypes for this connection. + * \since QGIS 3.16 + */ + static QList nativeTypes(); + + static const QString SPATIALITE_ARRAY_PREFIX; + static const QString SPATIALITE_ARRAY_SUFFIX; + protected: // SpatiaLite DB open / close sqlite3 *openSpatiaLiteDb( const QString &path ); diff --git a/src/providers/spatialite/qgsspatialitedataitemguiprovider.cpp b/src/providers/spatialite/qgsspatialitedataitemguiprovider.cpp index ae494054559c..7bdce67bdf55 100644 --- a/src/providers/spatialite/qgsspatialitedataitemguiprovider.cpp +++ b/src/providers/spatialite/qgsspatialitedataitemguiprovider.cpp @@ -48,7 +48,7 @@ void QgsSpatiaLiteDataItemGuiProvider::populateContextMenu( QgsDataItem *item, Q } } -bool QgsSpatiaLiteDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGuiContext ) +bool QgsSpatiaLiteDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGuiContext context ) { if ( QgsSLLayerItem *layerItem = qobject_cast< QgsSLLayerItem * >( item ) ) { @@ -61,13 +61,13 @@ bool QgsSpatiaLiteDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataI QString errCause; if ( !SpatiaLiteUtils::deleteLayer( uri.database(), uri.table(), errCause ) ) { - QMessageBox::warning( nullptr, tr( "Delete Layer" ), errCause ); - return false; + notify( tr( "Delete Layer" ), errCause, context, Qgis::MessageLevel::Warning ); } else { - QMessageBox::information( nullptr, tr( "Delete Layer" ), tr( "Layer deleted successfully." ) ); - layerItem->parent()->refresh(); + notify( tr( "Delete Layer" ), tr( "Layer deleted successfully." ), context, Qgis::MessageLevel::Success ); + if ( layerItem->parent() ) + layerItem->parent()->refresh(); return true; } } diff --git a/src/providers/spatialite/qgsspatialitedataitems.cpp b/src/providers/spatialite/qgsspatialitedataitems.cpp index 9c25918486c9..e19afc37a48d 100644 --- a/src/providers/spatialite/qgsspatialitedataitems.cpp +++ b/src/providers/spatialite/qgsspatialitedataitems.cpp @@ -64,7 +64,7 @@ QgsSLLayerItem::QgsSLLayerItem( QgsDataItem *parent, const QString &name, const : QgsLayerItem( parent, name, path, uri, layerType, QStringLiteral( "spatialite" ) ) { mCapabilities |= Delete; - setState( Populated ); // no children are expected + setState( NotPopulated ); } // ------ @@ -162,7 +162,7 @@ bool QgsSLConnectionItem::equal( const QgsDataItem *other ) // --------------------------------------------------------------------------- QgsSLRootItem::QgsSLRootItem( QgsDataItem *parent, const QString &name, const QString &path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "spatialite" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "spatialite" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconSpatialite.svg" ); @@ -300,3 +300,13 @@ bool QgsSLConnectionItem::layerCollection() const { return true; } + +QVector QgsSLLayerItem::createChildren() +{ + QVector children; + children.push_back( new QgsFieldsItem( this, + path() + QStringLiteral( "/columns/ " ), + uri(), + QStringLiteral( "spatialite" ), QString(), name() ) ); + return children; +} diff --git a/src/providers/spatialite/qgsspatialitedataitems.h b/src/providers/spatialite/qgsspatialitedataitems.h index cb75dfc1f47c..d5dfcbbf0d09 100644 --- a/src/providers/spatialite/qgsspatialitedataitems.h +++ b/src/providers/spatialite/qgsspatialitedataitems.h @@ -24,8 +24,12 @@ class QgsSLLayerItem : public QgsLayerItem public: QgsSLLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType ); + // QgsDataItem interface + QVector createChildren() override; }; + + class QgsSLConnectionItem : public QgsDataCollectionItem { Q_OBJECT @@ -45,7 +49,7 @@ class QgsSLConnectionItem : public QgsDataCollectionItem bool layerCollection() const override; }; -class QgsSLRootItem : public QgsDataCollectionItem +class QgsSLRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/spatialite/qgsspatialiteprovider.cpp b/src/providers/spatialite/qgsspatialiteprovider.cpp index e41073a3f2d2..dca0a34c8afd 100644 --- a/src/providers/spatialite/qgsspatialiteprovider.cpp +++ b/src/providers/spatialite/qgsspatialiteprovider.cpp @@ -50,8 +50,6 @@ using namespace nlohmann; const QString QgsSpatiaLiteProvider::SPATIALITE_KEY = QStringLiteral( "spatialite" ); const QString QgsSpatiaLiteProvider::SPATIALITE_DESCRIPTION = QStringLiteral( "SpatiaLite data provider" ); -static const QString SPATIALITE_ARRAY_PREFIX = QStringLiteral( "json" ); -static const QString SPATIALITE_ARRAY_SUFFIX = QStringLiteral( "list" ); QAtomicInt QgsSpatiaLiteProvider::sSavepointId = 0; bool QgsSpatiaLiteProvider::convertField( QgsField &field ) @@ -110,7 +108,7 @@ bool QgsSpatiaLiteProvider::convertField( QgsField &field ) subField.setType( field.subType() ); subField.setSubType( QVariant::Invalid ); if ( !convertField( subField ) ) return false; - fieldType = SPATIALITE_ARRAY_PREFIX + subField.typeName() + SPATIALITE_ARRAY_SUFFIX; + fieldType = QgsSpatiaLiteConnection::SPATIALITE_ARRAY_PREFIX + subField.typeName() + QgsSpatiaLiteConnection::SPATIALITE_ARRAY_SUFFIX; fieldSize = subField.length(); fieldPrec = subField.precision(); break; @@ -203,7 +201,7 @@ QgsSpatiaLiteProvider::createEmptyLayer( const QString &uri, { // found it, get the field type QgsField fld = fields.at( fldIdx ); - if ( convertField( fld ) ) + if ( ( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) || convertField( fld ) ) { primaryKeyType = fld.typeName(); } @@ -418,7 +416,7 @@ QgsSpatiaLiteProvider::createEmptyLayer( const QString &uri, continue; } - if ( !convertField( fld ) ) + if ( !( options && options->value( QStringLiteral( "skipConvertFields" ), false ).toBool() ) && !convertField( fld ) ) { QgsDebugMsg( "error creating field " + fld.name() + ": unsupported type" ); if ( errorMessage ) @@ -620,18 +618,7 @@ QgsSpatiaLiteProvider::QgsSpatiaLiteProvider( QString const &uri, const Provider spatialiteVersion(); //fill type names into sets - setNativeTypes( QList() - << QgsVectorDataProvider::NativeType( tr( "Binary object (BLOB)" ), QStringLiteral( "BLOB" ), QVariant::ByteArray ) - << QgsVectorDataProvider::NativeType( tr( "Text" ), QStringLiteral( "TEXT" ), QVariant::String ) - << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), QStringLiteral( "FLOAT" ), QVariant::Double ) - << QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), QStringLiteral( "INTEGER" ), QVariant::LongLong ) - << QgsVectorDataProvider::NativeType( tr( "Date" ), QStringLiteral( "DATE" ), QVariant::Date ) - << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), QStringLiteral( "TIMESTAMP" ), QVariant::DateTime ) - - << QgsVectorDataProvider::NativeType( tr( "Array of text" ), SPATIALITE_ARRAY_PREFIX.toUpper() + "TEXT" + SPATIALITE_ARRAY_SUFFIX.toUpper(), QVariant::StringList, 0, 0, 0, 0, QVariant::String ) - << QgsVectorDataProvider::NativeType( tr( "Array of decimal numbers (double)" ), SPATIALITE_ARRAY_PREFIX.toUpper() + "REAL" + SPATIALITE_ARRAY_SUFFIX.toUpper(), QVariant::List, 0, 0, 0, 0, QVariant::Double ) - << QgsVectorDataProvider::NativeType( tr( "Array of whole numbers (integer)" ), SPATIALITE_ARRAY_PREFIX.toUpper() + "INTEGER" + SPATIALITE_ARRAY_SUFFIX.toUpper(), QVariant::List, 0, 0, 0, 0, QVariant::LongLong ) - ); + setNativeTypes( QgsSpatiaLiteConnection::nativeTypes() ); // Update extent and feature count if ( ! mSubsetString.isEmpty() ) @@ -689,13 +676,13 @@ static TypeSubType getVariantType( const QString &type ) type == QLatin1String( "double precision" ) || type == QLatin1String( "float" ) ) return TypeSubType( QVariant::Double, QVariant::Invalid ); - else if ( type.startsWith( SPATIALITE_ARRAY_PREFIX ) && type.endsWith( SPATIALITE_ARRAY_SUFFIX ) ) + else if ( type.startsWith( QgsSpatiaLiteConnection::SPATIALITE_ARRAY_PREFIX ) && type.endsWith( QgsSpatiaLiteConnection::SPATIALITE_ARRAY_SUFFIX ) ) { // New versions of OGR convert list types (StringList, IntegerList, Integer64List and RealList) // to JSON when it stores a Spatialite table. It sets the column type as JSONSTRINGLIST, // JSONINTEGERLIST, JSONINTEGER64LIST or JSONREALLIST - TypeSubType subType = getVariantType( type.mid( SPATIALITE_ARRAY_PREFIX.length(), - type.length() - SPATIALITE_ARRAY_PREFIX.length() - SPATIALITE_ARRAY_SUFFIX.length() ) ); + TypeSubType subType = getVariantType( type.mid( QgsSpatiaLiteConnection::SPATIALITE_ARRAY_PREFIX.length(), + type.length() - QgsSpatiaLiteConnection::SPATIALITE_ARRAY_PREFIX.length() - QgsSpatiaLiteConnection::SPATIALITE_ARRAY_SUFFIX.length() ) ); return TypeSubType( subType.first == QVariant::String ? QVariant::StringList : QVariant::List, subType.first ); } else if ( type == QLatin1String( "jsonarray" ) ) diff --git a/src/providers/spatialite/qgsspatialiteproviderconnection.cpp b/src/providers/spatialite/qgsspatialiteproviderconnection.cpp index 260c14333d56..9118278cf149 100644 --- a/src/providers/spatialite/qgsspatialiteproviderconnection.cpp +++ b/src/providers/spatialite/qgsspatialiteproviderconnection.cpp @@ -25,6 +25,7 @@ QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString &name ) : QgsAbstractDatabaseProviderConnection( name ) { + mProviderKey = QStringLiteral( "spatialite" ); setDefaultCapabilities(); // TODO: QGIS 4: move into QgsSettings::Section::Providers group QgsSettings settings; @@ -39,6 +40,7 @@ QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString &uri, const QVariantMap &configuration ): QgsAbstractDatabaseProviderConnection( uri, configuration ) { + mProviderKey = QStringLiteral( "spatialite" ); const QRegularExpression removePartsRe { R"raw(\s*sql=\s*|\s*table=""\s*|\([^\)]+\))raw" }; // Cleanup the URI in case it contains other information other than the file path setUri( QString( uri ).replace( removePartsRe, QString() ) ); @@ -198,14 +200,36 @@ void QgsSpatiaLiteProviderConnection::vacuum( const QString &schema, const QStri void QgsSpatiaLiteProviderConnection::createSpatialIndex( const QString &schema, const QString &name, const QgsAbstractDatabaseProviderConnection::SpatialIndexOptions &options ) const { - Q_UNUSED( name ) - checkCapability( Capability::Vacuum ); + + checkCapability( Capability::CreateSpatialIndex ); + if ( ! schema.isEmpty() ) { QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by Spatialite, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info ); } + + QString geometryColumnName { options.geometryColumnName }; + if ( geometryColumnName.isEmpty() ) + { + // Can we guess it? + try + { + const auto tp { table( schema, name ) }; + geometryColumnName = tp.geometryColumn(); + } + catch ( QgsProviderConnectionException & ) + { + // pass + } + } + + if ( geometryColumnName.isEmpty() ) + { + throw QgsProviderConnectionException( QObject::tr( "Geometry column name not specified while creating spatial index" ) ); + } + executeSqlPrivate( QStringLiteral( "SELECT CreateSpatialIndex(%1, %2)" ).arg( QgsSqliteUtils::quotedString( name ), - QgsSqliteUtils::quotedString( ( options.geometryColumnName ) ) ) ); + QgsSqliteUtils::quotedString( ( geometryColumnName ) ) ) ); } bool QgsSpatiaLiteProviderConnection::spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const @@ -328,7 +352,7 @@ QList QgsSpatiaLiteProviderConne if ( ! errCause.isEmpty() ) { - throw QgsProviderConnectionException( QObject::tr( "Error listing tables from %1: %2" ).arg( pathFromUri() ).arg( errCause ) ); + throw QgsProviderConnectionException( QObject::tr( "Error listing tables from %1: %2" ).arg( pathFromUri(), errCause ) ); } // Filters if ( flags ) @@ -360,6 +384,14 @@ void QgsSpatiaLiteProviderConnection::setDefaultCapabilities() Capability::ExecuteSql, Capability::CreateSpatialIndex, Capability::SpatialIndexExists, + Capability::DeleteField, + Capability::AddField + }; + mGeometryColumnCapabilities = + { + GeometryColumnCapability::Z, + GeometryColumnCapability::M, + GeometryColumnCapability::SinglePart, }; } @@ -441,3 +473,27 @@ QString QgsSpatiaLiteProviderConnection::pathFromUri() const return dsUri.database(); } + +void QgsSpatiaLiteProviderConnection::deleteField( const QString &fieldName, const QString &, const QString &tableName, bool ) const +{ + QgsVectorLayer::LayerOptions options { false, false }; + options.skipCrsValidation = true; + std::unique_ptr vl { qgis::make_unique( QStringLiteral( "%1|layername=%2" ).arg( pathFromUri(), tableName ), QStringLiteral( "temp_layer" ), QStringLiteral( "ogr" ), options ) }; + if ( ! vl->isValid() ) + { + throw QgsProviderConnectionException( QObject::tr( "Could not create a valid layer for table '%1'" ).arg( tableName ) ); + } + if ( vl->fields().lookupField( fieldName ) == -1 ) + { + throw QgsProviderConnectionException( QObject::tr( "Could not delete field '%1' of table '%2': field does not exist" ).arg( fieldName, tableName ) ); + } + if ( ! vl->dataProvider()->deleteAttributes( {vl->fields().lookupField( fieldName )} ) ) + { + throw QgsProviderConnectionException( QObject::tr( "Unknown error deleting field '%1' of table '%2'" ).arg( fieldName, tableName ) ); + } +} + +QList QgsSpatiaLiteProviderConnection::nativeTypes() const +{ + return QgsSpatiaLiteConnection::nativeTypes(); +} diff --git a/src/providers/spatialite/qgsspatialiteproviderconnection.h b/src/providers/spatialite/qgsspatialiteproviderconnection.h index 5695ba1d959f..fc375a4f1267 100644 --- a/src/providers/spatialite/qgsspatialiteproviderconnection.h +++ b/src/providers/spatialite/qgsspatialiteproviderconnection.h @@ -45,6 +45,8 @@ class QgsSpatiaLiteProviderConnection : public QgsAbstractDatabaseProviderConnec QList tables( const QString &schema = QString(), const TableFlags &flags = nullptr ) const override; QIcon icon() const override; + void deleteField( const QString &fieldName, const QString &schema, const QString &tableName, bool force ) const override; + QList nativeTypes() const override; private: @@ -60,5 +62,9 @@ class QgsSpatiaLiteProviderConnection : public QgsAbstractDatabaseProviderConnec }; + + + + ///@endcond #endif // QGSSPATIALITEPROVIDERCONNECTION_H diff --git a/src/providers/wcs/qgswcsdataitems.cpp b/src/providers/wcs/qgswcsdataitems.cpp index a2bb711553dd..27f6b7511079 100644 --- a/src/providers/wcs/qgswcsdataitems.cpp +++ b/src/providers/wcs/qgswcsdataitems.cpp @@ -179,7 +179,7 @@ QString QgsWCSLayerItem::createUri() // --------------------------------------------------------------------------- QgsWCSRootItem::QgsWCSRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "WCS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "WCS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconWcs.svg" ); diff --git a/src/providers/wcs/qgswcsdataitems.h b/src/providers/wcs/qgswcsdataitems.h index 58fb20b526e4..27d667b3cac0 100644 --- a/src/providers/wcs/qgswcsdataitems.h +++ b/src/providers/wcs/qgswcsdataitems.h @@ -53,7 +53,7 @@ class QgsWCSLayerItem : public QgsLayerItem QgsWcsCoverageSummary mCoverageSummary; }; -class QgsWCSRootItem : public QgsDataCollectionItem +class QgsWCSRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/wfs/qgswfsdataitems.cpp b/src/providers/wfs/qgswfsdataitems.cpp index 23a8f7de2e3a..0d3826835829 100644 --- a/src/providers/wfs/qgswfsdataitems.cpp +++ b/src/providers/wfs/qgswfsdataitems.cpp @@ -228,7 +228,7 @@ QVector QgsWfsConnectionItem::createChildren() // QgsWfsRootItem::QgsWfsRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "WFS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "WFS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconWfs.svg" ); diff --git a/src/providers/wfs/qgswfsdataitems.h b/src/providers/wfs/qgswfsdataitems.h index be336eb6481f..a1d62db6b04b 100644 --- a/src/providers/wfs/qgswfsdataitems.h +++ b/src/providers/wfs/qgswfsdataitems.h @@ -21,7 +21,7 @@ #include "qgsdatasourceuri.h" #include "qgswfscapabilities.h" -class QgsWfsRootItem : public QgsDataCollectionItem +class QgsWfsRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/providers/wms/qgswmsdataitems.cpp b/src/providers/wms/qgswmsdataitems.cpp index 9bee1567d2a1..f5221b0c09ba 100644 --- a/src/providers/wms/qgswmsdataitems.cpp +++ b/src/providers/wms/qgswmsdataitems.cpp @@ -507,7 +507,7 @@ QString QgsWMTSLayerItem::createUri() // --------------------------------------------------------------------------- QgsWMSRootItem::QgsWMSRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "WMS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "WMS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconWms.svg" ); @@ -532,7 +532,7 @@ QVector QgsWMSRootItem::createChildren() // --------------------------------------------------------------------------- QgsWMTSRootItem::QgsWMTSRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "WMS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "WMS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconWms.svg" ); @@ -573,7 +573,7 @@ QgsDataItem *QgsWmsDataItemProvider::createDataItem( const QString &path, QgsDat QgsXyzTileRootItem::QgsXyzTileRootItem( QgsDataItem *parent, QString name, QString path ) - : QgsDataCollectionItem( parent, name, path, QStringLiteral( "WMS" ) ) + : QgsConnectionsRootItem( parent, name, path, QStringLiteral( "WMS" ) ) { mCapabilities |= Fast; mIconName = QStringLiteral( "mIconXyz.svg" ); diff --git a/src/providers/wms/qgswmsdataitems.h b/src/providers/wms/qgswmsdataitems.h index 2d1cbc977735..b281a8110571 100644 --- a/src/providers/wms/qgswmsdataitems.h +++ b/src/providers/wms/qgswmsdataitems.h @@ -147,7 +147,7 @@ class QgsWMTSLayerItem : public QgsLayerItem QString mId, mFormat, mStyle, mTileMatrixSet, mCrs, mTitle; }; -class QgsWMSRootItem : public QgsDataCollectionItem +class QgsWMSRootItem : public QgsConnectionsRootItem { Q_OBJECT public: @@ -160,7 +160,7 @@ class QgsWMSRootItem : public QgsDataCollectionItem public slots: }; -class QgsWMTSRootItem : public QgsDataCollectionItem +class QgsWMTSRootItem : public QgsConnectionsRootItem { Q_OBJECT public: @@ -185,7 +185,7 @@ class QgsWmsDataItemProvider : public QgsDataItemProvider //! Root item for XYZ tile layers -class QgsXyzTileRootItem : public QgsDataCollectionItem +class QgsXyzTileRootItem : public QgsConnectionsRootItem { Q_OBJECT public: diff --git a/src/quickgui/images/ic_back.svg b/src/quickgui/images/ic_back.svg index 72f5e6ddb2e6..419b98a5289f 100644 --- a/src/quickgui/images/ic_back.svg +++ b/src/quickgui/images/ic_back.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_broken_image_black.svg b/src/quickgui/images/ic_broken_image_black.svg index 4c7e52f7807f..368759f29c87 100644 --- a/src/quickgui/images/ic_broken_image_black.svg +++ b/src/quickgui/images/ic_broken_image_black.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_camera.svg b/src/quickgui/images/ic_camera.svg index dd124afc94e3..1b057fc659e9 100644 --- a/src/quickgui/images/ic_camera.svg +++ b/src/quickgui/images/ic_camera.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_camera_alt_border.svg b/src/quickgui/images/ic_camera_alt_border.svg index 7bd93c3322bb..0b2dc6af0c77 100644 --- a/src/quickgui/images/ic_camera_alt_border.svg +++ b/src/quickgui/images/ic_camera_alt_border.svg @@ -1,71 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/quickgui/images/ic_check_black.svg b/src/quickgui/images/ic_check_black.svg index 3fab25f262b0..0dd87bc62201 100644 --- a/src/quickgui/images/ic_check_black.svg +++ b/src/quickgui/images/ic_check_black.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_clear_black.svg b/src/quickgui/images/ic_clear_black.svg index ec8d116194f6..d9f926d15cd0 100644 --- a/src/quickgui/images/ic_clear_black.svg +++ b/src/quickgui/images/ic_clear_black.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_delete_forever_white.svg b/src/quickgui/images/ic_delete_forever_white.svg index ff2e74c8fd31..36708d74d1e2 100644 --- a/src/quickgui/images/ic_delete_forever_white.svg +++ b/src/quickgui/images/ic_delete_forever_white.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_gallery.svg b/src/quickgui/images/ic_gallery.svg index 122661c443e1..ebebc2433c63 100644 --- a/src/quickgui/images/ic_gallery.svg +++ b/src/quickgui/images/ic_gallery.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_navigation_black.svg b/src/quickgui/images/ic_navigation_black.svg index 20d6b393a80d..8f58252c35e5 100644 --- a/src/quickgui/images/ic_navigation_black.svg +++ b/src/quickgui/images/ic_navigation_black.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/quickgui/images/ic_photo_notavailable_white.svg b/src/quickgui/images/ic_photo_notavailable_white.svg index 89eaad55ec52..d3c03f6233b5 100644 --- a/src/quickgui/images/ic_photo_notavailable_white.svg +++ b/src/quickgui/images/ic_photo_notavailable_white.svg @@ -1,66 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/quickgui/images/ic_save_white.svg b/src/quickgui/images/ic_save_white.svg index 05684dfc3d75..b34cb2502be4 100644 --- a/src/quickgui/images/ic_save_white.svg +++ b/src/quickgui/images/ic_save_white.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/ui/3d/map3dconfigwidget.ui b/src/ui/3d/map3dconfigwidget.ui index 3e8c7e09c155..c11f621e9351 100644 --- a/src/ui/3d/map3dconfigwidget.ui +++ b/src/ui/3d/map3dconfigwidget.ui @@ -38,9 +38,9 @@ 0 - 0 - 555 - 675 + -49 + 541 + 724 @@ -56,100 +56,18 @@ 0 - - - - Qt::Vertical - - - - 20 - 0 - + + + + Show map tile info - + - - - - Terrain + + + + Show camera's view center - - - - - - - - Elevation - - - - - - - - - - Tile resolution - - - - - - - 1.000000000000000 - - - - - - - Type - - - - - - - px - - - 4096 - - - - - - - Vertical scale - - - - - - - Skirt height - - - - - - - map units - - - 1 - - - 10000.000000000000000 - - - 10.000000000000000 - - - - @@ -179,30 +97,11 @@ - - - - Camera + + + + Show labels - - - - - Field of View - - - - - - - ° - - - 180 - - - - @@ -229,11 +128,37 @@ - - + + - Show camera's view center + Show bounding boxes + + + + + + + Camera + + + + + Field of View + + + + + + + ° + + + 180 + + + + @@ -314,25 +239,100 @@ - - - - Show labels + + + + Qt::Vertical - - - - - - Show map tile info + + + 20 + 0 + - + - - - - Show bounding boxes + + + + Terrain + + + + + + + + Elevation + + + + + + + + + + Tile resolution + + + + + + + 1.000000000000000 + + + + + + + Type + + + + + + + px + + + 4096 + + + + + + + Vertical scale + + + + + + + Skirt height + + + + + + + map units + + + 1 + + + 10000.000000000000000 + + + 10.000000000000000 + + + + @@ -356,6 +356,13 @@ + + + + Show light sources + + + diff --git a/src/ui/3d/phongmaterialwidget.ui b/src/ui/3d/phongmaterialwidget.ui index e8cbab251039..12a137a83f17 100644 --- a/src/ui/3d/phongmaterialwidget.ui +++ b/src/ui/3d/phongmaterialwidget.ui @@ -6,14 +6,14 @@ 0 0 - 338 - 138 + 394 + 248 Form - + @@ -97,6 +97,65 @@ + + + + Use diffuse texture + + + false + + + + + + + + + + Texture scale + + + + + + + 0.010000000000000 + + + 100.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + Texture rotation + + + + + + + ° + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.500000000000000 + + + @@ -111,6 +170,12 @@
qgscolorbutton.h
1 + + QgsImageSourceLineEdit + QWidget +
qgsfilecontentsourcelineedit.h
+ 1 +
diff --git a/src/ui/3d/point3dsymbolwidget.ui b/src/ui/3d/point3dsymbolwidget.ui index 1eec51da6f4a..b8b435416ad0 100644 --- a/src/ui/3d/point3dsymbolwidget.ui +++ b/src/ui/3d/point3dsymbolwidget.ui @@ -238,14 +238,7 @@ - - - - - - - - + @@ -424,6 +417,12 @@ + + Qgs3DModelSourceLineEdit + QWidget +
qgs3dmodelsourcelineedit.h
+ 1 +
QgsPhongMaterialWidget QWidget @@ -456,7 +455,6 @@ spinSize spinLength lineEditModel - btnModel cbOverwriteMaterial spinBillboardHeight btnChangeSymbol diff --git a/src/ui/3d/polygon3dsymbolwidget.ui b/src/ui/3d/polygon3dsymbolwidget.ui index 78c100cc1c17..05e5319ab3c2 100644 --- a/src/ui/3d/polygon3dsymbolwidget.ui +++ b/src/ui/3d/polygon3dsymbolwidget.ui @@ -33,32 +33,6 @@
- - - - Invert normals (experimental) - - - - - - - - No culling - - - - - Front - - - - - Back - - - - @@ -66,33 +40,22 @@ - - - - 99999.000000000000000 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Shading - + + 0 + + + 0 + + + 0 + + 0 @@ -101,17 +64,17 @@ - - + + - Culling mode + - - + + - + Invert normals (experimental) @@ -134,7 +97,68 @@ - + + + + 99999.000000000000000 + + + + + + + Altitude binding + + + + + + + + No Culling + + + + + Front + + + + + Back + + + + + + + + + Vertex + + + + + Centroid + + + + + + + + + + + + + + + Altitude clamping + + + + Edges @@ -195,53 +219,72 @@
- + + + + Culling mode + + + + Add back faces - - + + - + Height - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Rendered facade + + + + + + + 0 + - Vertex + No Facades - Centroid + Walls + + + + + Roofs + + + + + Walls and Roofs - - - - - - Altitude binding - - - - - - - Height - - - - - - - Altitude clamping - diff --git a/src/ui/attributeformconfig/qgsattributewidgeteditgroupbox.ui b/src/ui/attributeformconfig/qgsattributewidgeteditgroupbox.ui index 23e10e251906..2ef163c3c730 100644 --- a/src/ui/attributeformconfig/qgsattributewidgeteditgroupbox.ui +++ b/src/ui/attributeformconfig/qgsattributewidgeteditgroupbox.ui @@ -6,8 +6,8 @@ 0 0 - 381 - 173 + 385 + 209 @@ -17,25 +17,54 @@ Widget Display - - + + - Show link button + Delete child feature + + mRelationButtonGroup + - - + + - Show label + Show unlink button + + mRelationButtonGroup + - - + + - Show unlink button + Add child feature + + + mRelationButtonGroup + + + + + + + Duplicate child feature + + + mRelationButtonGroup + + + + + + + Show link button + + mRelationButtonGroup + @@ -43,6 +72,26 @@ Show save child layer edits button + + mRelationButtonGroup + + + + + + + Show label + + + + + + + Zoom to child feature + + + mRelationButtonGroup + @@ -57,4 +106,11 @@ + + + + false + + + diff --git a/src/ui/layout/qgslayoutattributetablewidgetbase.ui b/src/ui/layout/qgslayoutattributetablewidgetbase.ui index 35294ac8a6a0..e5c457194e5a 100644 --- a/src/ui/layout/qgslayoutattributetablewidgetbase.ui +++ b/src/ui/layout/qgslayoutattributetablewidgetbase.ui @@ -54,9 +54,9 @@ 0 - 0 + -629 394 - 1487 + 1419 @@ -544,66 +544,13 @@ Table Heading - - - - - - - 120 - 0 - - - - - 120 - 16777215 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - + Alignment - - - - - 0 - 0 - - - - - - - - Color - - - @@ -624,6 +571,16 @@ + + + + + 0 + 0 + + + + @@ -640,49 +597,6 @@ - - - - Color - - - - - - - - - - 120 - 0 - - - - - 120 - 16777215 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -855,10 +769,8 @@ mDrawVerticalGrid groupBox_3 mHeaderFontToolButton - mHeaderFontColorButton mHeaderHAlignmentComboBox mContentFontToolButton - mContentFontColorButton frameGroupBox mResizeModeComboBox mAddFramePushButton diff --git a/src/ui/layout/qgslayoutmanualtablewidgetbase.ui b/src/ui/layout/qgslayoutmanualtablewidgetbase.ui index ace2a53039ec..8b9aeb55b3e7 100644 --- a/src/ui/layout/qgslayoutmanualtablewidgetbase.ui +++ b/src/ui/layout/qgslayoutmanualtablewidgetbase.ui @@ -56,7 +56,7 @@ 0 0 394 - 976 + 914 @@ -323,49 +323,6 @@ - - - - - - 120 - 0 - - - - - 120 - 16777215 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Alignment - - - - @@ -375,13 +332,6 @@ - - - - Color - - - @@ -402,6 +352,13 @@ + + + + Alignment + + + @@ -418,49 +375,6 @@ - - - - Color - - - - - - - - - - 120 - 0 - - - - - 120 - 16777215 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/src/ui/layout/qgslayoutmapgridwidgetbase.ui b/src/ui/layout/qgslayoutmapgridwidgetbase.ui index a6a2bae45cd1..08b5d45f3fdd 100644 --- a/src/ui/layout/qgslayoutmapgridwidgetbase.ui +++ b/src/ui/layout/qgslayoutmapgridwidgetbase.ui @@ -49,7 +49,7 @@ 0 0 409 - 1447 + 1416 @@ -686,68 +686,84 @@ false - - - - - Bottom - - - true - - - - - - - Format - - + + + - - - - Font color + + + + mm - - + + - Top + Left true - - + + - Left + Right true - - - - mm + + + + + + + + + + + + + :/images/themes/default/mIconExpression.svg:/images/themes/default/mIconExpression.svg + + + + + + + + + + 0 + 0 + + + + Font - - + + + + + - Coordinate precision + Bottom true + + + @@ -755,136 +771,83 @@ - - - - Right - - - true - - + + - + - Distance to map frame + Coordinate precision true - + - - - - false - - - - - - - - - - 120 - 0 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - Font - - - - - - - - - - - - - - + + - - + + - - + + + + Format + + - - + + + + Top + + + true + + - - + + - - + + - - - - - - - - - - - - - :/images/themes/default/mIconExpression.svg:/images/themes/default/mIconExpression.svg - - - - + + + + Distance to map frame + + + true + + + + + + + false + + + + + @@ -897,6 +860,12 @@ + + QgsCollapsibleGroupBoxBasic + QGroupBox +
qgscollapsiblegroupbox.h
+ 1 +
QgsScrollArea QScrollArea @@ -904,9 +873,9 @@ 1 - QgsCollapsibleGroupBoxBasic - QGroupBox -
qgscollapsiblegroupbox.h
+ QgsColorButton + QToolButton +
qgscolorbutton.h
1
@@ -914,53 +883,56 @@ QDoubleSpinBox
qgsdoublespinbox.h
+ + QgsFontButton + QToolButton +
qgsfontbutton.h
+
QgsSpinBox QSpinBox
qgsspinbox.h
- - QgsBlendModeComboBox - QComboBox -
qgsblendmodecombobox.h
-
- - QgsSymbolButton - QToolButton -
qgssymbolbutton.h
-
QgsPropertyOverrideButton QToolButton
qgspropertyoverridebutton.h
- QgsColorButton - QToolButton -
qgscolorbutton.h
- 1 + QgsBlendModeComboBox + QComboBox +
qgsblendmodecombobox.h
- QgsFontButton + QgsSymbolButton QToolButton -
qgsfontbutton.h
+
qgssymbolbutton.h
scrollArea mGridTypeComboBox mMapGridCRSButton + mMapGridUnitComboBox + mMinWidthSpinBox + mMaxWidthSpinBox mOffsetXSpinBox + mOffsetXDDBtn mOffsetYSpinBox + mOffsetYDDBtn mCrossWidthSpinBox + mCrossWidthDDBtn mGridLineStyleButton mGridMarkerStyleButton mGridBlendComboBox mGridFrameGroupBox mFrameStyleComboBox mFrameWidthSpinBox + mFrameSizeDDBtn mGridFrameMarginSpinBox + mFrameMarginDDBtn mGridFramePenSizeSpinBox + mFrameLineThicknessDDBtn mGridFramePenColorButton mGridFrameFill1ColorButton mGridFrameFill2ColorButton @@ -988,9 +960,15 @@ mAnnotationPositionBottomComboBox mAnnotationDirectionComboBoxBottom mAnnotationFontButton - mAnnotationFontColorButton mDistanceToMapFrameSpinBox + mLabelDistDDBtn mCoordinatePrecisionSpinBox + mEnabledCheckBox + mEnabledDDBtn + mIntervalXSpinBox + mIntervalYDDBtn + mIntervalYSpinBox + mIntervalXDDBtn diff --git a/src/ui/qgsdiagrampropertiesbase.ui b/src/ui/qgsdiagrampropertiesbase.ui index 74707b2f4fa5..944eea958ccc 100644 --- a/src/ui/qgsdiagrampropertiesbase.ui +++ b/src/ui/qgsdiagrampropertiesbase.ui @@ -853,14 +853,6 @@ labelrenderinggroup - - - 6 - - - 6 - - @@ -968,37 +960,6 @@ - - - - - - Discourage diagrams and labels from covering features - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -1034,8 +995,6 @@ -
- @@ -1167,7 +1126,7 @@ - + QFrame::NoFrame @@ -1474,7 +1433,7 @@ - + Qt::Vertical @@ -1487,7 +1446,7 @@ - + QFrame::NoFrame @@ -1558,7 +1517,7 @@ - + Priority @@ -1619,6 +1578,51 @@ + + + + Obstacles + + + labelplacementgroup + + + + 8 + + + 8 + + + + + Discourage diagrams and labels from covering features + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + @@ -2309,10 +2313,9 @@ mZIndexSpinBox mZOrderDDBtn mShowAllCheckBox - mScaleVisibilityGroupBox mShowDiagramDDBtn mAlwaysShowDDBtn - mIsObstacleDDBtn + mScaleVisibilityGroupBox scrollArea_5 mDiagramUnitComboBox mFixedSizeRadio @@ -2343,6 +2346,7 @@ mCoordYDDBtn mPrioritySlider mPriorityDDBtn + mIsObstacleDDBtn scrollArea_7 mOrientationUpButton mOrientationDownButton @@ -2354,29 +2358,6 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ui/qgsnewvectortabledialogbase.ui b/src/ui/qgsnewvectortabledialogbase.ui new file mode 100644 index 000000000000..7cf4a812d26f --- /dev/null +++ b/src/ui/qgsnewvectortabledialogbase.ui @@ -0,0 +1,416 @@ + + + QgsNewVectorTableDialogBase + + + Qt::WindowModal + + + + 0 + 0 + 936 + 562 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Create Table + + + true + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + Include values (M) + + + + + + + Geometry column name + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Include Z dimension + + + + + + + false + + + background-color: rgba(255,165,0,0.3); + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 1 + 0 + + + + false + + + background: transparent; + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + Validation results + + + 0 + + + + + + + background: transparent; + + + QFrame::Plain + + + 0 + + + + + + :/images/themes/default/mIconWarning.svg + + + 0 + + + + + + + + + + geom + + + + + + + + 2 + 0 + + + + + + + + + + + Dimensions + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + + + + + + + + Geometry type + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + CRS + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Create spatial index + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + true + + + + + + + + + + + + + + Add Field + + + + :/images/themes/default/mActionNewAttribute.svg:/images/themes/default/mActionNewAttribute.svg + + + + + + + Remove Field + + + + :/images/themes/default/mActionDeleteAttribute.svg:/images/themes/default/mActionDeleteAttribute.svg + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Up + + + + :/images/themes/default/mActionArrowUp.svg:/images/themes/default/mActionArrowUp.svg + + + + + + + Down + + + + :/images/themes/default/mActionArrowDown.svg:/images/themes/default/mActionArrowDown.svg + + + + + + + + + + 0 + 0 + + + + + 800 + 0 + + + + QAbstractItemView::AllEditTriggers + + + true + + + + + + + + + Schema + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Name + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + QgsProjectionSelectionWidget + QWidget +
qgsprojectionselectionwidget.h
+ 1 +
+
+ + mSchemaCbo + mTableName + mFieldsTableView + mAddFieldBtn + mDeleteFieldBtn + mFieldUpBtn + mFieldDownBtn + mButtonBox + + + + + + + mButtonBox + rejected() + QgsNewVectorTableDialogBase + reject() + + + 316 + 260 + + + 286 + 274 + + + + + mButtonBox + accepted() + QgsNewVectorTableDialogBase + accept() + + + 461 + 539 + + + 461 + 280 + + + + +
diff --git a/src/ui/qgstableeditorformattingwidgetbase.ui b/src/ui/qgstableeditorformattingwidgetbase.ui index 0f1eb61dd477..a07dffc3e81d 100644 --- a/src/ui/qgstableeditorformattingwidgetbase.ui +++ b/src/ui/qgstableeditorformattingwidgetbase.ui @@ -46,8 +46,28 @@ 464
- - + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Expression + + + + Qt::StrongFocus @@ -130,7 +150,7 @@
- + Qt::StrongFocus @@ -144,25 +164,65 @@ false - - + + Format as number - + Customize… + + + + + 0 + 0 + + + + Font + + + + + + + Horizontal alignment + + + + + + + Vertical alignment + + + + + + + + + + + + + Text format + + + - + Qt::StrongFocus @@ -214,18 +274,18 @@ - - - - Qt::Vertical + + + + + 0 + 0 + - - - 20 - 0 - + + Qt::StrongFocus - + @@ -234,6 +294,17 @@ + + QgsDoubleSpinBox + QDoubleSpinBox +
qgsdoublespinbox.h
+
+ + QgsColorButton + QToolButton +
qgscolorbutton.h
+ 1 +
QgsScrollArea QScrollArea @@ -241,20 +312,36 @@ 1 - QgsColorButton + QgsFontButton QToolButton -
qgscolorbutton.h
- 1 +
qgsfontbutton.h
- QgsDoubleSpinBox - QDoubleSpinBox -
qgsdoublespinbox.h
+ QgsAlignmentComboBox + QComboBox +
qgsalignmentcombobox.h
+
+ + QgsFieldExpressionWidget + QWidget +
qgsfieldexpressionwidget.h
+ 1
- scrollArea groupBox_6 + mTextColorButton + mBackgroundColorButton + groupBox_7 + mFontButton + mFormatNumbersCheckBox + mCustomizeFormatButton + mHorizontalAlignComboBox + mVerticalAlignComboBox + groupBox_8 + mRowHeightSpinBox + mColumnWidthSpinBox + scrollArea diff --git a/src/ui/qgstextformatwidgetbase.ui b/src/ui/qgstextformatwidgetbase.ui index 3c7fc36e3313..ee7563c60df3 100644 --- a/src/ui/qgstextformatwidgetbase.ui +++ b/src/ui/qgstextformatwidgetbase.ui @@ -5948,7 +5948,7 @@ font-style: italic; true - Discourage labels from covering features + Discourage labels and diagrams from covering features
diff --git a/tests/src/3d/testqgstessellator.cpp b/tests/src/3d/testqgstessellator.cpp index f91479aaaa3b..14d3fdc21fcc 100644 --- a/tests/src/3d/testqgstessellator.cpp +++ b/tests/src/3d/testqgstessellator.cpp @@ -406,7 +406,7 @@ void TestQgsTessellator::testCrash2DTriangle() // test tessellation of a 2D triangle - https://github.com/qgis/QGIS/issues/36024 QgsPolygon polygon; polygon.fromWkt( "Polygon((0 0, 42 0, 42 42, 0 0))" ); - QgsTessellator t( 0, 0, true ); + QgsTessellator t( 0, 0, true, false, false, true ); t.addPolygon( polygon, 0 ); // must not crash - that's all we test here } diff --git a/tests/src/app/testqgsmaptooladdfeatureline.cpp b/tests/src/app/testqgsmaptooladdfeatureline.cpp index d83459e7443a..868d623eb52d 100644 --- a/tests/src/app/testqgsmaptooladdfeatureline.cpp +++ b/tests/src/app/testqgsmaptooladdfeatureline.cpp @@ -67,6 +67,7 @@ class TestQgsMapToolAddFeatureLine : public QObject void testTracing(); void testTracingWithOffset(); void testTracingWithConvertToCurves(); + void testTracingWithConvertToCurvesCustomTolerance(); void testZ(); void testZMSnapping(); void testTopologicalEditingZ(); @@ -81,6 +82,7 @@ class TestQgsMapToolAddFeatureLine : public QObject QgsMapToolAddFeature *mCaptureTool = nullptr; QgsVectorLayer *mLayerLine = nullptr; QgsVectorLayer *mLayerLineCurved = nullptr; + QgsVectorLayer *mLayerLineCurvedOffset = nullptr; QgsVectorLayer *mLayerLineZ = nullptr; QgsVectorLayer *mLayerPointZM = nullptr; QgsVectorLayer *mLayerTopoZ = nullptr; @@ -131,7 +133,7 @@ void TestQgsMapToolAddFeatureLine::initTestCase() // just one added feature QCOMPARE( mLayerLine->undoStack()->index(), 1 ); - // make testing layers + // make testing layers for tracing curves mLayerLineCurved = new QgsVectorLayer( QStringLiteral( "LineString?crs=EPSG:27700" ), QStringLiteral( "curved layer line" ), QStringLiteral( "memory" ) ); QVERIFY( mLayerLineCurved->isValid() ); QgsProject::instance()->addMapLayers( QList() << mLayerLineCurved ); @@ -147,6 +149,22 @@ void TestQgsMapToolAddFeatureLine::initTestCase() // just one added feature QCOMPARE( mLayerLineCurved->undoStack()->index(), 1 ); + // make testing layers for tracing curves with offset + mLayerLineCurvedOffset = new QgsVectorLayer( QStringLiteral( "LineString?crs=EPSG:27700" ), QStringLiteral( "curved layer line" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayerLineCurvedOffset->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayerLineCurvedOffset ); + + QgsFeature curveF2; + curveF2.setGeometry( QgsGeometry::fromWkt( "CIRCULARSTRING(100000006 100000001, 100000006.5 100000001.5, 100000007 100000001)" ) ); + + mLayerLineCurvedOffset->startEditing(); + mLayerLineCurvedOffset->addFeature( curveF2 ); + mFidCurvedF1 = curveF2.id(); + QCOMPARE( mLayerLineCurvedOffset->featureCount(), ( long )1 ); + + // just one added feature + QCOMPARE( mLayerLineCurvedOffset->undoStack()->index(), 1 ); + // make testing layers mLayerLineZ = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); QVERIFY( mLayerLineZ->isValid() ); @@ -218,7 +236,7 @@ void TestQgsMapToolAddFeatureLine::initTestCase() mLayerSelfSnapLine->startEditing(); // add layers to canvas - mCanvas->setLayers( QList() << mLayerLine << mLayerLineCurved << mLayerLineZ << mLayerPointZM << mLayerTopoZ << mLayerLine2D << mLayerSelfSnapLine ); + mCanvas->setLayers( QList() << mLayerLine << mLayerLineCurved << mLayerLineCurvedOffset << mLayerLineZ << mLayerPointZM << mLayerTopoZ << mLayerLine2D << mLayerSelfSnapLine ); mCanvas->setSnappingUtils( new QgsMapCanvasSnappingUtils( mCanvas, this ) ); // create the tool @@ -440,6 +458,72 @@ void TestQgsMapToolAddFeatureLine::testTracingWithConvertToCurves() mEnableTracingAction->setChecked( false ); } + +void TestQgsMapToolAddFeatureLine::testTracingWithConvertToCurvesCustomTolerance() +{ + // Exactly the same as testTracingWithConvertToCurves but far from the origin + // At this distance, the arcs aren't correctly detected with the default tolerance + double offset = 100000000; // remember to change the feature geometry accordingly in initTestCase (sic) + + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/convert_to_curve_angle_tolerance" ), 1e-5 ); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/convert_to_curve_distance_tolerance" ), 1e-5 ); + + mCanvas->setExtent( QgsRectangle( offset + 0, offset + 0, offset + 8, offset + 8 ) ); + QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( offset + 0, offset + 0, offset + 8, offset + 8 ) ); + + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + + mCanvas->setCurrentLayer( mLayerLineCurvedOffset ); + + // enable snapping and tracing + mEnableTracingAction->setChecked( true ); + + QSet oldFids = utils.existingFeatureIds(); + + // tracing enabled - without converting to curves + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/convert_to_curve" ), false ); + + utils.mouseClick( offset + 6, offset + 1, Qt::LeftButton ); + utils.mouseClick( offset + 7, offset + 1, Qt::LeftButton ); + utils.mouseClick( offset + 7, offset + 1, Qt::RightButton ); + + QgsFeatureId newFid1 = utils.newFeatureId( oldFids ); + + const QgsAbstractGeometry *g = mLayerLineCurvedOffset->getFeature( newFid1 ).geometry().constGet(); + QCOMPARE( g->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( offset + 6, offset + 1 ) ); + QCOMPARE( g->vertexAt( QgsVertexId( 0, 0, g->vertexCount() - 1 ) ), QgsPoint( offset + 7, offset + 1 ) ); + QVERIFY( g->vertexCount() > 3 ); // a segmentized arc has (much) more than 3 points + + mLayerLineCurvedOffset->undoStack()->undo(); + + // we redo the same with convert to curves enabled + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/convert_to_curve" ), true ); + + // tracing enabled - without converting to curves + utils.mouseClick( offset + 6, offset + 1, Qt::LeftButton ); + utils.mouseClick( offset + 7, offset + 1, Qt::LeftButton ); + utils.mouseClick( offset + 7, offset + 1, Qt::RightButton ); + + QgsFeatureId newFid2 = utils.newFeatureId( oldFids ); + + g = mLayerLineCurvedOffset->getFeature( newFid2 ).geometry().constGet(); + QCOMPARE( g->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( offset + 6, offset + 1 ) ); + QCOMPARE( g->vertexAt( QgsVertexId( 0, 0, g->vertexCount() - 1 ) ), QgsPoint( offset + 7, offset + 1 ) ); + QVERIFY( g->vertexCount() == 3 ); // a true arc is composed of 3 vertices + + mLayerLineCurvedOffset->undoStack()->undo(); + + // no other unexpected changes happened + QCOMPARE( mLayerLineCurvedOffset->undoStack()->index(), 1 ); + + mEnableTracingAction->setChecked( false ); + + // restore the extent + mCanvas->setExtent( QgsRectangle( 0, 0, 8, 8 ) ); + QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 8, 8 ) ); + +} + void TestQgsMapToolAddFeatureLine::testZ() { TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); diff --git a/tests/src/core/testqgis.cpp b/tests/src/core/testqgis.cpp index d2eb924099cb..ed7901360596 100644 --- a/tests/src/core/testqgis.cpp +++ b/tests/src/core/testqgis.cpp @@ -22,6 +22,7 @@ //qgis includes... #include "qgis.h" #include "qgsmaplayermodel.h" +#include "qgsattributeeditorelement.h" /** * \ingroup UnitTests @@ -49,6 +50,8 @@ class TestQgis : public QObject void testQgsVariantEqual(); void testQgsEnumValueToKey(); void testQgsEnumKeyToValue(); + void testQgsFlagValueToKeys(); + void testQgsFlagKeysToValue(); void testQMapQVariantList(); private: @@ -411,6 +414,17 @@ void TestQgis::testQgsEnumKeyToValue() QCOMPARE( qgsEnumKeyToValue( QStringLiteral( "UnknownKey" ), QgsMapLayerModel::LayerIdRole ), QgsMapLayerModel::LayerIdRole ); } +void TestQgis::testQgsFlagValueToKeys() +{ + QgsAttributeEditorRelation::Buttons buttons = QgsAttributeEditorRelation::Button::Link | QgsAttributeEditorRelation::Button::AddChildFeature; + QCOMPARE( qgsFlagValueToKeys( buttons ), QStringLiteral( "Link|AddChildFeature" ) ); +} +void TestQgis::testQgsFlagKeysToValue() +{ + QCOMPARE( qgsFlagKeysToValue( QStringLiteral( "Link|AddChildFeature" ), QgsAttributeEditorRelation::Buttons( QgsAttributeEditorRelation::Button::AllButtons ) ), QgsAttributeEditorRelation::Button::Link | QgsAttributeEditorRelation::Button::AddChildFeature ); + QCOMPARE( qgsFlagKeysToValue( QStringLiteral( "UnknownKey" ), QgsAttributeEditorRelation::Buttons( QgsAttributeEditorRelation::Button::AllButtons ) ), QgsAttributeEditorRelation::Buttons( QgsAttributeEditorRelation::Button::AllButtons ) ); +} + void TestQgis::testQMapQVariantList() { QMap ids; diff --git a/tests/src/core/testqgsdiagram.cpp b/tests/src/core/testqgsdiagram.cpp index 5f9ad1178b22..972209b95a30 100644 --- a/tests/src/core/testqgsdiagram.cpp +++ b/tests/src/core/testqgsdiagram.cpp @@ -486,6 +486,62 @@ class TestQgsDiagram : public QObject } + void testStackedAxis() + { + QgsDiagramSettings ds; + QColor col1 = Qt::red; + QColor col2 = Qt::yellow; + col1.setAlphaF( 0.5 ); + col2.setAlphaF( 0.5 ); + ds.categoryColors = QList() << col1 << col2; + ds.categoryAttributes = QList() << QStringLiteral( "\"Pilots\"" ) << QStringLiteral( "\"Cabin Crew\"" ); + ds.minimumScale = -1; + ds.maximumScale = -1; + ds.minimumSize = 0; + ds.penColor = Qt::green; + ds.penWidth = .5; + ds.scaleByArea = true; + ds.sizeType = QgsUnitTypes::RenderMillimeters; + ds.size = QSizeF( 5, 5 ); + ds.rotationOffset = 0; + ds.setSpacing( 3 ); + ds.setShowAxis( true ); + + QgsStringMap props; + props.insert( QStringLiteral( "width" ), QStringLiteral( "2" ) ); + props.insert( QStringLiteral( "color" ), QStringLiteral( "#ff00ff" ) ); + ds.setAxisLineSymbol( QgsLineSymbol::createSimple( props ) ); + + QgsLinearlyInterpolatedDiagramRenderer *dr = new QgsLinearlyInterpolatedDiagramRenderer(); + dr->setLowerValue( 0.0 ); + dr->setLowerSize( QSizeF( 0.0, 0.0 ) ); + dr->setUpperValue( 10 ); + dr->setUpperSize( QSizeF( 40, 40 ) ); + dr->setClassificationField( QStringLiteral( "Staff" ) ); + dr->setDiagram( new QgsStackedBarDiagram() ); + dr->setDiagramSettings( ds ); + mPointsLayer->setDiagramRenderer( dr ); + + QgsDiagramLayerSettings dls = QgsDiagramLayerSettings(); + dls.setPlacement( QgsDiagramLayerSettings::OverPoint ); + dls.setShowAllDiagrams( true ); + mPointsLayer->setDiagramLayerSettings( dls ); + + QVERIFY( imageCheck( "stacked_axis_up" ) ); + + ds.diagramOrientation = QgsDiagramSettings::Down; + dr->setDiagramSettings( ds ); + QVERIFY( imageCheck( "stacked_axis_down" ) ); + + ds.diagramOrientation = QgsDiagramSettings::Left; + dr->setDiagramSettings( ds ); + QVERIFY( imageCheck( "stacked_axis_left" ) ); + + ds.diagramOrientation = QgsDiagramSettings::Right; + dr->setDiagramSettings( ds ); + QVERIFY( imageCheck( "stacked_axis_right" ) ); + } + void testPieDiagramExpression() { QgsDiagramSettings ds; diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index 18f2a02620bb..b33a159ad1fe 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -1240,6 +1240,12 @@ class TestQgsExpression: public QObject QTest::newRow( "m_min line M NaN" ) << "m_min(make_line(geom_from_wkt('PointZM (0 0 0 nan)'),geom_from_wkt('PointZM (1 1 1 2)')))" << false << QVariant( 2.0 ); QTest::newRow( "m_min point" ) << "m_min(make_point_m(0,0,1))" << false << QVariant( 1.0 ); QTest::newRow( "m_min line" ) << "m_min(make_line(make_point_m(0,0,1),make_point_m(-1,-1,2),make_point_m(-2,-2,0)))" << false << QVariant( 0.0 ); + QTest::newRow( "main angle polygon" ) << "round(main_angle( geom_from_wkt('POLYGON((0 0,2 9,9 2,0 0))')))" << false << QVariant( 77 ); + QTest::newRow( "main angle multi polygon" ) << "round(main_angle( geom_from_wkt('MULTIPOLYGON(((0 0,3 10,1 10,1 6,0 0)))')))" << false << QVariant( 17 ); + QTest::newRow( "main angle point" ) << "main_angle( geom_from_wkt('POINT (1.5 0.5)') )" << true << QVariant(); + QTest::newRow( "main angle line" ) << "round(main_angle( geom_from_wkt('LINESTRING (-1 2, 9 12)') ))" << false << QVariant( 45 ); + QTest::newRow( "main angle not geom" ) << "main_angle('g')" << true << QVariant(); + QTest::newRow( "main angle null" ) << "main_angle(NULL)" << false << QVariant(); // string functions QTest::newRow( "format_number" ) << "format_number(1999.567,2)" << false << QVariant( "1,999.57" ); diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp index 09860cb56d56..0d2d4bb2c41a 100644 --- a/tests/src/core/testqgsgeometry.cpp +++ b/tests/src/core/testqgsgeometry.cpp @@ -52,6 +52,7 @@ #include "qgscurvepolygon.h" #include "qgsproject.h" #include "qgslinesegment.h" +#include "qgsgeos.h" //qgs unit test utility class #include "qgsrenderchecker.h" @@ -85,6 +86,7 @@ class TestQgsGeometry : public QObject void vertexIterator(); void partIterator(); + void geos(); // geometry types void point(); //test QgsPointV2 @@ -522,6 +524,25 @@ void TestQgsGeometry::partIterator() // See test_qgsgeometry.py for geometry-type specific checks! } +void TestQgsGeometry::geos() +{ + // test GEOS conversion utils + + // empty parts should NOT be added to a GEOS collection -- it can cause crashes in GEOS + QgsMultiPolygon polyWithEmptyParts; + geos::unique_ptr asGeos( QgsGeos::asGeos( &polyWithEmptyParts ) ); + QgsGeometry res( QgsGeos::fromGeos( asGeos.get() ) ); + QCOMPARE( res.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) ); + polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString() ) ); + polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString( QVector< QgsPoint >() << QgsPoint( 0, 0 ) << QgsPoint( 0, 1 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) ) ) ); + polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString() ) ); + polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString( QVector< QgsPoint >() << QgsPoint( 10, 0 ) << QgsPoint( 10, 1 ) << QgsPoint( 11, 1 ) << QgsPoint( 10, 0 ) ) ) ); + asGeos = QgsGeos::asGeos( &polyWithEmptyParts ); + QCOMPARE( GEOSGetNumGeometries_r( QgsGeos::getGEOSHandler(), asGeos.get() ), 2 ); + res = QgsGeometry( QgsGeos::fromGeos( asGeos.get() ) ); + QCOMPARE( res.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((10 0, 10 1, 11 1, 10 0)))" ) ); +} + void TestQgsGeometry::point() { //test QgsPointV2 @@ -17098,6 +17119,12 @@ void TestQgsGeometry::smoothCheck() << QgsPointXY( 4.0, 3.8 ) << QgsPointXY( 3.8, 4.0 ) << QgsPointXY( 2.2, 4.0 ) << QgsPointXY( 2.0, 3.8 ) << QgsPointXY( 2, 2.2 ) << QgsPointXY( 2.2, 2 ) ) ); QVERIFY( QgsGeometry::compare( multipoly, expectedMultiPoly ) ); + + // curved geometry + wkt = QStringLiteral( "CurvePolygon (CompoundCurve (CircularString (-70.75639028391421448 42.11076979194393743, -70.75300889449444242 42.10738840252416537, -70.75639028391421448 42.10400701310439331, -70.75977167333398654 42.10738840252416537, -70.75639028391421448 42.11076979194393743))) 1" ); + geom = QgsGeometry::fromWkt( wkt ); + result = geom.smooth( 3 ); + QCOMPARE( result.wkbType(), QgsWkbTypes::Polygon ); } void TestQgsGeometry::unaryUnion() @@ -17696,6 +17723,93 @@ void TestQgsGeometry::splitGeometry() QCOMPARE( g2.splitGeometry( QgsPointSequence() << QgsPoint( 2749544.19, 1262914.79, 0 ) << QgsPoint( 2749557.64, 1262897.30, 0 ), newGeoms, false, testPoints ), QgsGeometry::Success ); QVERIFY( newGeoms.count() == 1 ); QCOMPARE( newGeoms[0].asWkt( 2 ), QStringLiteral( "LineStringZ (2749549.12 1262908.38 125.14, 2749557.82 1262920.06 200)" ) ); + + // Test split geometry with topological editing + QVector testPointsXY; + testPoints.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) ); + QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 1 ); + QCOMPARE( testPoints.count(), 2 ); + QgsGeometry::convertPointList( testPoints, testPointsXY ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + testPointsXY.clear(); + testPoints.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) ); + QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 2 ); + QCOMPARE( testPoints.count(), 2 ); + QgsGeometry::convertPointList( testPoints, testPointsXY ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + // Test split parts with topological editing + testPointsXY.clear(); + testPoints.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) ); + QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints, false ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 2 ); + QCOMPARE( testPoints.count(), 2 ); + QgsGeometry::convertPointList( testPoints, testPointsXY ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + testPointsXY.clear(); + testPoints.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) ); + QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints, false ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 3 ); + QCOMPARE( testPoints.count(), 2 ); + QgsGeometry::convertPointList( testPoints, testPointsXY ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + // Repeat previous tests with QVector instead of QgsPointSequence + // Those tests are for the deprecated QgsGeometry::splitGeometry() variant and should be removed in QGIS 4.0 + Q_NOWARN_DEPRECATED_PUSH + testPointsXY.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) ); + QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 1 ); + QCOMPARE( testPointsXY.count(), 2 ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + testPointsXY.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) ); + QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 2 ); + QCOMPARE( testPointsXY.count(), 2 ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + // Test split parts with topological editing + testPointsXY.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) ); + QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY, false ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 2 ); + QCOMPARE( testPointsXY.count(), 2 ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + + testPointsXY.clear(); + newGeoms.clear(); + g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) ); + QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY, false ), QgsGeometry::Success ); + QCOMPARE( newGeoms.count(), 3 ); + QCOMPARE( testPointsXY.count(), 2 ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) ); + QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) ); + Q_NOWARN_DEPRECATED_POP } void TestQgsGeometry::snappedToGrid() diff --git a/tests/src/core/testqgslayoutmanualtable.cpp b/tests/src/core/testqgslayoutmanualtable.cpp index 09dd1af2234b..16e2bf017c88 100644 --- a/tests/src/core/testqgslayoutmanualtable.cpp +++ b/tests/src/core/testqgslayoutmanualtable.cpp @@ -44,11 +44,15 @@ class TestQgsLayoutManualTable : public QObject void cleanup();// will be called after every testfunction. void setContents(); + void scopeForCell(); + void expressionContents(); void cellStyles(); void cellFormat(); void rowHeight(); void columnWidth(); void headers(); + void cellTextFormat(); + void cellTextAlignment(); private: QString mReport; @@ -63,6 +67,8 @@ void TestQgsLayoutManualTable::initTestCase() QgsApplication::initQgis(); mReport = QStringLiteral( "

Layout Manual Table Tests

\n" ); + + QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Bold" ) ); } void TestQgsLayoutManualTable::cleanupTestCase() @@ -266,6 +272,62 @@ void TestQgsLayoutManualTable::setContents() QCOMPARE( tableFromXml->columnWidths(), QList< double >() << 15.5 << 14.0 << 13.4 ); } +void TestQgsLayoutManualTable::scopeForCell() +{ + QVector expectedRows; + + QgsPrintLayout l( QgsProject::instance() ); + l.initializeDefaults(); + l.setName( QStringLiteral( "my layout" ) ); + QgsLayoutItemManualTable *table = new QgsLayoutItemManualTable( &l ); + + std::unique_ptr< QgsExpressionContextScope > scope( table->scopeForCell( 1, 2 ) ); + + // variable values for row/col should start at 1, not 0! + QCOMPARE( scope->variable( QStringLiteral( "row_number" ) ).toInt(), 2 ); + QCOMPARE( scope->variable( QStringLiteral( "column_number" ) ).toInt(), 3 ); +} + +void TestQgsLayoutManualTable::expressionContents() +{ + QVector expectedRows; + + QgsPrintLayout l( QgsProject::instance() ); + l.initializeDefaults(); + l.setName( QStringLiteral( "my layout" ) ); + QgsLayoutItemManualTable *table = new QgsLayoutItemManualTable( &l ); + + QStringList row; + + // 2 x 3 + row << QStringLiteral( "Jet" ) << QStringLiteral( "1,2" ) << QStringLiteral( "1,3" ); + expectedRows.append( row ); + row.clear(); + row << QStringLiteral( "my layout" ) << QStringLiteral( "Helicopter" ) << QStringLiteral( "Plane" ); + expectedRows.append( row ); + + table->setTableContents( + QgsTableContents() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "Jet" ) ) << QgsTableCell( QgsProperty::fromExpression( QStringLiteral( "@row_number || ',' || @column_number" ) ) ) << QgsTableCell( QgsProperty::fromExpression( QStringLiteral( "@row_number || ',' || @column_number" ) ) ) ) + << ( QgsTableRow() << QgsTableCell( QgsProperty::fromExpression( QStringLiteral( "@layout_name" ) ) ) << QgsTableCell( QStringLiteral( "Helicopter" ) ) << QgsTableCell( QStringLiteral( "Plane" ) ) ) ); + compareTable( table, expectedRows ); + + // save and restore + + //write to XML + QDomImplementation DomImplementation; + QDomDocumentType documentType = + DomImplementation.createDocumentType( + QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) ); + QDomDocument doc( documentType ); + QDomElement tableElement = doc.createElement( QStringLiteral( "table" ) ); + QVERIFY( table->writeXml( tableElement, doc, QgsReadWriteContext(), true ) ); + + //read from XML + QgsLayoutItemManualTable *tableFromXml = new QgsLayoutItemManualTable( &l ); + QVERIFY( tableFromXml->readXml( tableElement.firstChildElement(), doc, QgsReadWriteContext(), true ) ); + compareTable( tableFromXml, expectedRows ); +} + void TestQgsLayoutManualTable::cellStyles() { QgsLayout l( QgsProject::instance() ); @@ -336,7 +398,7 @@ void TestQgsLayoutManualTable::rowHeight() table->addFrame( frame1 ); table->setBackgroundColor( Qt::yellow ); - table->setContentFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); frame1->setFrameEnabled( false ); table->setShowGrid( true ); @@ -364,7 +426,7 @@ void TestQgsLayoutManualTable::columnWidth() table->addFrame( frame1 ); table->setBackgroundColor( Qt::yellow ); - table->setContentFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); frame1->setFrameEnabled( false ); table->setShowGrid( true ); @@ -392,14 +454,15 @@ void TestQgsLayoutManualTable::headers() table->addFrame( frame1 ); table->setBackgroundColor( Qt::yellow ); - table->setContentFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 16 ) ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + QgsTextFormat headerFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 16 ) ) ); + headerFormat.setColor( QColor( 255, 0, 255 ) ); + table->setHeaderTextFormat( headerFormat ); frame1->setFrameEnabled( false ); table->setShowGrid( true ); table->setHorizontalGrid( true ); table->setVerticalGrid( true ); - table->setHeaderFontColor( QColor( 255, 0, 255 ) ); table->setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "Jet" ) ) << QgsTableCell( QStringLiteral( "Helicopter" ) ) << QgsTableCell( QStringLiteral( "Plane" ) ) ) << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << QgsTableCell( QStringLiteral( "B" ) ) << QgsTableCell( QStringLiteral( "C" ) ) ) ); @@ -414,5 +477,97 @@ void TestQgsLayoutManualTable::headers() QVERIFY( result ); } +void TestQgsLayoutManualTable::cellTextFormat() +{ + QgsLayout l( QgsProject::instance() ); + l.initializeDefaults(); + QgsLayoutItemManualTable *table = new QgsLayoutItemManualTable( &l ); + QgsLayoutFrame *frame1 = new QgsLayoutFrame( &l, table ); + frame1->attemptSetSceneRect( QRectF( 5, 5, 100, 60 ) ); + frame1->setFrameEnabled( true ); + table->addFrame( frame1 ); + table->setBackgroundColor( Qt::yellow ); + + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + + frame1->setFrameEnabled( false ); + table->setShowGrid( true ); + table->setHorizontalGrid( true ); + table->setVerticalGrid( true ); + + QgsTableCell c1( QStringLiteral( "Jet" ) ); + QgsTextFormat f1 = table->contentTextFormat(); + f1.setSize( 20 ); + f1.buffer().setEnabled( true ); + f1.buffer().setColor( QColor( 100, 130, 150 ) ); + f1.buffer().setSize( 1 ); + c1.setTextFormat( f1 ); + + QgsTableCell c3( QStringLiteral( "Plane" ) ); + QgsTextFormat f2 = table->contentTextFormat(); + f2.setSize( 16 ); + f2.buffer().setEnabled( true ); + f2.buffer().setColor( QColor( 150, 110, 90 ) ); + f2.buffer().setSize( 1 ); + c3.setTextFormat( f2 ); + + QgsTableCell c5( QStringLiteral( "B" ) ); + QgsTextFormat f3 = table->contentTextFormat(); + f3.setSize( 36 ); + f3.buffer().setEnabled( true ); + f3.buffer().setColor( QColor( 200, 110, 90 ) ); + f3.buffer().setSize( 1 ); + c5.setTextFormat( f3 ); + + table->setTableContents( QgsTableContents() << ( QgsTableRow() << c1 << QgsTableCell( QStringLiteral( "Helicopter" ) ) << c3 ) + << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << c5 << QgsTableCell( QStringLiteral( "C" ) ) ) ); + + table->setColumnWidths( QList< double >() << 0 << 0.0 << 30.0 ); + QgsLayoutChecker checker( QStringLiteral( "manualtable_textformat" ), &l ); + checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); + bool result = checker.testLayout( mReport ); + QVERIFY( result ); +} + +void TestQgsLayoutManualTable::cellTextAlignment() +{ + QgsLayout l( QgsProject::instance() ); + l.initializeDefaults(); + QgsLayoutItemManualTable *table = new QgsLayoutItemManualTable( &l ); + QgsLayoutFrame *frame1 = new QgsLayoutFrame( &l, table ); + frame1->attemptSetSceneRect( QRectF( 5, 5, 100, 60 ) ); + frame1->setFrameEnabled( true ); + table->addFrame( frame1 ); + table->setBackgroundColor( Qt::yellow ); + + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + + frame1->setFrameEnabled( false ); + table->setShowGrid( true ); + table->setHorizontalGrid( true ); + table->setVerticalGrid( true ); + + QgsTableCell c1( QStringLiteral( "Jet" ) ); + c1.setHorizontalAlignment( Qt::AlignRight ); + c1.setVerticalAlignment( Qt::AlignBottom ); + + QgsTableCell c3( QStringLiteral( "Plane" ) ); + c3.setHorizontalAlignment( Qt::AlignCenter ); + c3.setVerticalAlignment( Qt::AlignTop ); + + QgsTableCell c5( QStringLiteral( "B" ) ); + c5.setHorizontalAlignment( Qt::AlignRight ); + c5.setVerticalAlignment( Qt::AlignTop ); + + table->setTableContents( QgsTableContents() << ( QgsTableRow() << c1 << QgsTableCell( QStringLiteral( "Helicopter\nHelicopter" ) ) << c3 ) + << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << c5 << QgsTableCell( QStringLiteral( "C" ) ) ) ); + + table->setColumnWidths( QList< double >() << 0 << 0.0 << 30.0 ); + QgsLayoutChecker checker( QStringLiteral( "manualtable_textalign" ), &l ); + checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); + bool result = checker.testLayout( mReport ); + QVERIFY( result ); +} + QGSTEST_MAIN( TestQgsLayoutManualTable ) #include "testqgslayoutmanualtable.moc" diff --git a/tests/src/core/testqgslayoutmap.cpp b/tests/src/core/testqgslayoutmap.cpp index aa7e3abbeb3f..0901fac23709 100644 --- a/tests/src/core/testqgslayoutmap.cpp +++ b/tests/src/core/testqgslayoutmap.cpp @@ -34,6 +34,7 @@ #include "qgspallabeling.h" #include "qgsvectorlayerlabeling.h" #include "qgstemporalrangeobject.h" +#include "qgsfontutils.h" #include #include "qgstest.h" @@ -86,6 +87,8 @@ void TestQgsLayoutMap::initTestCase() QgsApplication::init(); QgsApplication::initQgis(); + QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Bold" ) ); + //create maplayers from testdata and add to layer registry QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/landsat.tif" ); mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(), @@ -553,6 +556,7 @@ void TestQgsLayoutMap::rasterized() QgsLayoutItemMapGrid *grid = new QgsLayoutItemMapGrid( "test", map ); grid->setIntervalX( 10 ); grid->setIntervalY( 10 ); + grid->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); grid->setBlendMode( QPainter::CompositionMode_Darken ); grid->setAnnotationEnabled( true ); grid->setAnnotationDisplay( QgsLayoutItemMapGrid::ShowAll, QgsLayoutItemMapGrid::Left ); diff --git a/tests/src/core/testqgslayoutmapgrid.cpp b/tests/src/core/testqgslayoutmapgrid.cpp index b20e6d3583d5..31e03721e4a6 100644 --- a/tests/src/core/testqgslayoutmapgrid.cpp +++ b/tests/src/core/testqgslayoutmapgrid.cpp @@ -74,6 +74,8 @@ void TestQgsLayoutMapGrid::initTestCase() QgsApplication::init(); QgsApplication::initQgis(); + QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Bold" ) ); + mReport = QStringLiteral( "

Composer Map Grid Tests

\n" ); } @@ -110,7 +112,11 @@ void TestQgsLayoutMapGrid::grid() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 255, 0, 0 ) ); + format.setOpacity( 150.0 / 255.0 ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -130,10 +136,8 @@ void TestQgsLayoutMapGrid::grid() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->grid()->setAnnotationDirection( QgsLayoutItemMapGrid::Horizontal, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationDirection( QgsLayoutItemMapGrid::Horizontal, QgsLayoutItemMapGrid::Bottom ); - map->grid()->setAnnotationFontColor( QColor( 255, 0, 0, 150 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_Overlay ); map->updateBoundingRect(); - qWarning() << "grid annotation font: " << map->grid()->annotationFont().toString() << " exactMatch:" << map->grid()->annotationFont().exactMatch(); QgsLayoutChecker checker( QStringLiteral( "composermap_grid" ), &l ); checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); @@ -154,7 +158,7 @@ void TestQgsLayoutMapGrid::reprojected() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -197,7 +201,7 @@ void TestQgsLayoutMapGrid::crossGrid() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -235,7 +239,7 @@ void TestQgsLayoutMapGrid::markerGrid() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -272,7 +276,7 @@ void TestQgsLayoutMapGrid::frameOnly() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -313,7 +317,9 @@ void TestQgsLayoutMapGrid::zebraStyle() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 0, 0, 0, 0 ) ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -323,7 +329,6 @@ void TestQgsLayoutMapGrid::zebraStyle() l.addLayoutItem( map ); map->setExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) ); //zoom in - map->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::Zebra ); @@ -353,7 +358,9 @@ void TestQgsLayoutMapGrid::zebraStyleSides() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 0, 0, 0, 0 ) ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -363,7 +370,6 @@ void TestQgsLayoutMapGrid::zebraStyleSides() l.addLayoutItem( map ); map->setExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) ); - map->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::Zebra ); @@ -415,7 +421,9 @@ void TestQgsLayoutMapGrid::zebraStyleMargin() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 0, 0, 0, 0 ) ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -425,7 +433,6 @@ void TestQgsLayoutMapGrid::zebraStyleMargin() l.addLayoutItem( map ); map->setExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) ); //zoom in - map->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::Zebra ); @@ -456,7 +463,9 @@ void TestQgsLayoutMapGrid::zebraStyleNautical() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 0, 0, 0, 0 ) ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -466,7 +475,6 @@ void TestQgsLayoutMapGrid::zebraStyleNautical() l.addLayoutItem( map ); map->setExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) ); //zoom in - map->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::ZebraNautical ); @@ -497,7 +505,9 @@ void TestQgsLayoutMapGrid::frameDivisions() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 0, 0, 0, 0 ) ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -511,7 +521,6 @@ void TestQgsLayoutMapGrid::frameDivisions() map->setMapRotation( 45.0 ); //setup defaults - map->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::Zebra ); map->grid()->setFrameWidth( 10 ); @@ -561,7 +570,9 @@ void TestQgsLayoutMapGrid::annotationFilter() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + QgsTextFormat format = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + format.setColor( QColor( 0, 0, 0, 0 ) ); + map->grid()->setAnnotationTextFormat( format ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -575,12 +586,10 @@ void TestQgsLayoutMapGrid::annotationFilter() map->setMapRotation( 45.0 ); //setup defaults - map->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); map->grid()->setEnabled( true ); map->grid()->setAnnotationEnabled( true ); - map->grid()->setAnnotationFontColor( Qt::black ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Left ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Top ); @@ -622,7 +631,7 @@ void TestQgsLayoutMapGrid::interiorTicks() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -660,7 +669,7 @@ void TestQgsLayoutMapGrid::interiorTicksMargin() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -699,7 +708,7 @@ void TestQgsLayoutMapGrid::interiorTicksAnnotated() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -717,7 +726,6 @@ void TestQgsLayoutMapGrid::interiorTicksAnnotated() map->grid()->setEnabled( true ); map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->grid()->setAnnotationEnabled( true ); - map->grid()->setAnnotationFontColor( Qt::black ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Left ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Top ); @@ -755,7 +763,7 @@ void TestQgsLayoutMapGrid::exteriorTicks() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -793,7 +801,7 @@ void TestQgsLayoutMapGrid::exteriorTicksMargin() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -832,7 +840,7 @@ void TestQgsLayoutMapGrid::exteriorTicksAnnotated() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -850,7 +858,6 @@ void TestQgsLayoutMapGrid::exteriorTicksAnnotated() map->grid()->setEnabled( true ); map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->grid()->setAnnotationEnabled( true ); - map->grid()->setAnnotationFontColor( Qt::black ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Left ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Top ); @@ -888,7 +895,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicks() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -926,7 +933,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicksMargin() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -965,7 +972,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicksAnnotated() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -983,7 +990,6 @@ void TestQgsLayoutMapGrid::interiorExteriorTicksAnnotated() map->grid()->setEnabled( true ); map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->grid()->setAnnotationEnabled( true ); - map->grid()->setAnnotationFontColor( Qt::black ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Left ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Top ); @@ -1021,7 +1027,7 @@ void TestQgsLayoutMapGrid::lineBorder() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -1059,7 +1065,7 @@ void TestQgsLayoutMapGrid::lineBorderMargin() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -1098,7 +1104,7 @@ void TestQgsLayoutMapGrid::lineBorderNautical() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -1137,7 +1143,7 @@ void TestQgsLayoutMapGrid::lineBorderAnnotated() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -1155,7 +1161,6 @@ void TestQgsLayoutMapGrid::lineBorderAnnotated() map->grid()->setEnabled( true ); map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->grid()->setAnnotationEnabled( true ); - map->grid()->setAnnotationFontColor( Qt::black ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Left ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Top ); @@ -1193,7 +1198,7 @@ void TestQgsLayoutMapGrid::annotationFormats() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -1257,7 +1262,7 @@ void TestQgsLayoutMapGrid::descendingAnnotations() map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) ); map->setFrameEnabled( true ); map->setBackgroundColor( QColor( 150, 100, 100 ) ); - map->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() ); + map->grid()->setAnnotationTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); map->grid()->setAnnotationPrecision( 0 ); map->grid()->setIntervalX( 2000 ); map->grid()->setIntervalY( 2000 ); @@ -1272,7 +1277,6 @@ void TestQgsLayoutMapGrid::descendingAnnotations() map->grid()->setEnabled( true ); map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->grid()->setAnnotationEnabled( true ); - map->grid()->setAnnotationFontColor( Qt::black ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Left ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Right ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Top ); diff --git a/tests/src/core/testqgslayouttable.cpp b/tests/src/core/testqgslayouttable.cpp index 259d9a97e90d..e569c067873b 100644 --- a/tests/src/core/testqgslayouttable.cpp +++ b/tests/src/core/testqgslayouttable.cpp @@ -34,6 +34,8 @@ #include "qgslayoutmanager.h" #include "qgsprintlayout.h" #include "qgslayoutatlas.h" +#include "qgslayoututils.h" +#include "qgspallabeling.h" #include #include "qgstest.h" @@ -81,6 +83,8 @@ class TestQgsLayoutTable : public QObject void wrappedText(); void testBaseSort(); void testExpressionSort(); + void testScopeForCell(); + void testDataDefinedTextFormatForCell(); private: QgsVectorLayer *mVectorLayer = nullptr; @@ -103,6 +107,8 @@ void TestQgsLayoutTable::initTestCase() QgsProject::instance()->addMapLayer( mVectorLayer ); mReport = QStringLiteral( "

Layout Table Tests

\n" ); + + QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Bold" ) ); } void TestQgsLayoutTable::cleanupTestCase() @@ -134,8 +140,8 @@ void TestQgsLayoutTable::init() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); } @@ -437,8 +443,8 @@ void TestQgsLayoutTable::attributeTableRender() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 20 ); @@ -464,8 +470,8 @@ void TestQgsLayoutTable::manualColumnWidth() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 20 ); @@ -492,8 +498,8 @@ void TestQgsLayoutTable::attributeTableEmpty() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 20 ); @@ -534,8 +540,8 @@ void TestQgsLayoutTable::showEmptyRows() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 3 ); @@ -561,8 +567,8 @@ void TestQgsLayoutTable::attributeTableExtend() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); //test that adding and removing frames automatically does not result in a crash @@ -593,8 +599,8 @@ void TestQgsLayoutTable::attributeTableRepeat() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); //test that creating and removing new frames in repeat mode does not crash @@ -721,8 +727,8 @@ void TestQgsLayoutTable::attributeTableRelationSource() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points_relations.shp" ); @@ -898,8 +904,8 @@ void TestQgsLayoutTable::multiLineText() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); QgsVectorLayer *multiLineLayer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:string&field=col2:string&field=col3:string" ), QStringLiteral( "multiline" ), QStringLiteral( "memory" ) ); @@ -950,8 +956,8 @@ void TestQgsLayoutTable::horizontalGrid() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); QgsVectorLayer *multiLineLayer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:string&field=col2:string&field=col3:string" ), QStringLiteral( "multiline" ), QStringLiteral( "memory" ) ); @@ -1007,8 +1013,8 @@ void TestQgsLayoutTable::verticalGrid() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); QgsVectorLayer *multiLineLayer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:string&field=col2:string&field=col3:string" ), QStringLiteral( "multiline" ), QStringLiteral( "memory" ) ); @@ -1048,6 +1054,32 @@ void TestQgsLayoutTable::verticalGrid() delete multiLineLayer; } +void TestQgsLayoutTable::testDataDefinedTextFormatForCell() +{ + QgsLayout l( QgsProject::instance() ); + l.initializeDefaults(); + QgsLayoutItemAttributeTable *table = new QgsLayoutItemAttributeTable( &l ); + table->setVectorLayer( mVectorLayer ); + + l.addMultiFrame( table ); + QgsLayoutFrame *frame = new QgsLayoutFrame( &l, table ); + frame->attemptSetSceneRect( QRectF( 5, 5, 150, 30 ) ); + frame->setFrameEnabled( true ); + l.addLayoutItem( frame ); + table->addFrame( frame ); + + QgsTextFormat textFormat = QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ); + table->setHeaderTextFormat( textFormat ); + + textFormat.dataDefinedProperties().setProperty( QgsPalLayerSettings::Size, QgsProperty::fromExpression( QStringLiteral( "if(@column_number = 1,35,15)" ) ) ); + table->setContentTextFormat( textFormat ); + + QgsLayoutChecker checker( QStringLiteral( "composerattributetable_datadefinedtextformat" ), &l ); + checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); + bool result = checker.testLayout( mReport ); + QVERIFY( result ); +} + void TestQgsLayoutTable::align() { QgsLayout l( QgsProject::instance() ); @@ -1064,8 +1096,8 @@ void TestQgsLayoutTable::align() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); QgsVectorLayer *multiLineLayer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:string&field=col2:string&field=col3:string" ), QStringLiteral( "multiline" ), QStringLiteral( "memory" ) ); @@ -1115,8 +1147,8 @@ void TestQgsLayoutTable::wrapChar() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); std::unique_ptr< QgsVectorLayer > multiLineLayer = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Point?field=col1:string&field=col2:string&field=col3:string" ), QStringLiteral( "multiline" ), QStringLiteral( "memory" ) ); @@ -1156,8 +1188,8 @@ void TestQgsLayoutTable::autoWrap() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); std::unique_ptr< QgsVectorLayer > multiLineLayer = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Point?field=col1:string&field=col2:string&field=col3:string" ), QStringLiteral( "multiline" ), QStringLiteral( "memory" ) ); @@ -1210,8 +1242,8 @@ void TestQgsLayoutTable::cellStyles() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); QgsLayoutTableStyle original; @@ -1414,8 +1446,8 @@ void TestQgsLayoutTable::cellStylesRender() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 3 ); @@ -1460,8 +1492,8 @@ void TestQgsLayoutTable::conditionalFormatting() table->setVectorLayer( mVectorLayer ); table->setDisplayOnlyVisibleFeatures( false ); table->setMaximumNumberOfFeatures( 10 ); - table->setContentFont( QgsFontUtils::getStandardTestFont() ); - table->setHeaderFont( QgsFontUtils::getStandardTestFont() ); + table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); + table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 7 ); @@ -1579,7 +1611,8 @@ void TestQgsLayoutTable::wrappedText() QFont f; QString sourceText( "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua" ); - QString wrapText = t->wrappedText( sourceText, 101 /*columnWidth*/, f ); + QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( &l, nullptr ); + QString wrapText = t->wrappedText( context, sourceText, 101 /*columnWidth*/, QgsTextFormat::fromQFont( f ) ).join( '\n' ); //there should be no line break before the last word (bug #20546) QVERIFY( !wrapText.endsWith( "\naliqua" ) ); } @@ -1635,5 +1668,35 @@ void TestQgsLayoutTable::testExpressionSort() compareTable( table, expectedRows ); } +void TestQgsLayoutTable::testScopeForCell() +{ + QgsLayout l( QgsProject::instance() ); + l.initializeDefaults(); + QgsLayoutItemAttributeTable *table = new QgsLayoutItemAttributeTable( &l ); + table->setVectorLayer( mVectorLayer ); + table->refresh(); + + std::unique_ptr< QgsExpressionContextScope > scope( table->scopeForCell( 0, 0 ) ); + + // variable values for row/col should start at 1, not 0! + QCOMPARE( scope->variable( QStringLiteral( "row_number" ) ).toInt(), 1 ); + QCOMPARE( scope->variable( QStringLiteral( "column_number" ) ).toInt(), 1 ); + QCOMPARE( scope->feature().attribute( 0 ).toString(), QStringLiteral( "Jet" ) ); + scope.reset( table->scopeForCell( 0, 1 ) ); + QCOMPARE( scope->variable( QStringLiteral( "row_number" ) ).toInt(), 1 ); + QCOMPARE( scope->variable( QStringLiteral( "column_number" ) ).toInt(), 2 ); + QCOMPARE( scope->feature().attribute( 0 ).toString(), QStringLiteral( "Jet" ) ); + scope.reset( table->scopeForCell( 1, 2 ) ); + QCOMPARE( scope->variable( QStringLiteral( "row_number" ) ).toInt(), 2 ); + QCOMPARE( scope->variable( QStringLiteral( "column_number" ) ).toInt(), 3 ); + QCOMPARE( scope->feature().attribute( 0 ).toString(), QStringLiteral( "Biplane" ) ); + + // make sure fields are set + QgsExpressionContext context; + context.appendScope( scope.release() ); + QCOMPARE( context.fields().size(), 6 ); + QCOMPARE( context.fields().at( 0 ).name(), QStringLiteral( "Class" ) ); +} + QGSTEST_MAIN( TestQgsLayoutTable ) #include "testqgslayouttable.moc" diff --git a/tests/src/core/testqgsproperty.cpp b/tests/src/core/testqgsproperty.cpp index b8fa59a76069..bc519c166c1b 100644 --- a/tests/src/core/testqgsproperty.cpp +++ b/tests/src/core/testqgsproperty.cpp @@ -1375,6 +1375,10 @@ void TestQgsProperty::propertyCollection() QVERIFY( !collection.hasDynamicProperties() ); QVERIFY( !collection.hasActiveProperties() ); + QgsPropertyCollection collection2; + QVERIFY( collection == collection2 ); + QVERIFY( !( collection != collection2 ) ); + QgsProperty property = QgsProperty::fromValue( "value", true ); collection.setProperty( Property1, property ); QVERIFY( collection.hasProperty( Property1 ) ); @@ -1386,6 +1390,12 @@ void TestQgsProperty::propertyCollection() QVERIFY( collection.hasActiveProperties() ); QVERIFY( !collection.hasDynamicProperties() ); + QVERIFY( collection != collection2 ); + QVERIFY( !( collection == collection2 ) ); + collection2.setProperty( Property1, property ); + QVERIFY( collection == collection2 ); + QVERIFY( !( collection != collection2 ) ); + //preparation QVERIFY( collection.prepare( context ) ); @@ -1403,6 +1413,8 @@ void TestQgsProperty::propertyCollection() QCOMPARE( collection.property( Property1 ).value( context ), property2.value( context ) ); QVERIFY( collection.hasActiveProperties() ); QVERIFY( !collection.hasDynamicProperties() ); + QVERIFY( collection != collection2 ); + QVERIFY( !( collection == collection2 ) ); //implicit conversion collection.setProperty( Property3, 5 ); @@ -1432,6 +1444,13 @@ void TestQgsProperty::propertyCollection() collection.setProperty( Property4, QgsProperty::fromExpression( QStringLiteral( "\"field1\" + \"field2\"" ), true ) ); QCOMPARE( collection.count(), 4 ); + collection2 = collection; + QVERIFY( collection == collection2 ); + QVERIFY( !( collection != collection2 ) ); + collection2.setProperty( Property3, QgsProperty() ); + QVERIFY( collection != collection2 ); + QVERIFY( !( collection == collection2 ) ); + // test referenced fields QCOMPARE( collection.referencedFields( context ).count(), 2 ); QVERIFY( collection.referencedFields( context ).contains( "field1" ) ); @@ -1466,7 +1485,7 @@ void TestQgsProperty::propertyCollection() QVERIFY( restoredCollection.hasDynamicProperties() ); // copy constructor - QgsPropertyCollection collection2( collection ); + collection2 = QgsPropertyCollection( collection ); QCOMPARE( collection2.name(), QStringLiteral( "collection" ) ); QCOMPARE( collection2.count(), 4 ); QCOMPARE( collection2.property( Property1 ).propertyType(), QgsProperty::StaticProperty ); diff --git a/tests/src/gui/CMakeLists.txt b/tests/src/gui/CMakeLists.txt index 2054e7329d00..8c1abc00fb84 100644 --- a/tests/src/gui/CMakeLists.txt +++ b/tests/src/gui/CMakeLists.txt @@ -167,3 +167,4 @@ ADD_QGIS_TEST(tableeditorwidget testqgstableeditor.cpp) ADD_QGIS_TEST(newdatabasetablewidget testqgsnewdatabasetablewidget.cpp) ADD_QGIS_TEST(ogrproviderguitest testqgsogrprovidergui.cpp) ADD_QGIS_TEST(singlebandpseudocolorrendererwidget testqgssinglebandpseudocolorrendererwidget.cpp) +ADD_QGIS_TEST(doublevalidator testqgsdoublevalidator.cpp) diff --git a/tests/src/gui/testprocessinggui.cpp b/tests/src/gui/testprocessinggui.cpp index 78ee036e7dbd..e655c75246d4 100644 --- a/tests/src/gui/testprocessinggui.cpp +++ b/tests/src/gui/testprocessinggui.cpp @@ -189,6 +189,7 @@ class TestProcessingGui : public QObject void testWrapperGeneral(); void testWrapperDynamic(); void testModelerWrapper(); + void testHiddenWrapper(); void testBooleanWrapper(); void testStringWrapper(); void testFileWrapper(); @@ -784,6 +785,33 @@ void TestProcessingGui::testModelerWrapper() } +void TestProcessingGui::testHiddenWrapper() +{ + TestParamType param( QStringLiteral( "boolean" ), QStringLiteral( "bool" ) ); + + QgsProcessingHiddenWidgetWrapper wrapper( ¶m ); + QSignalSpy spy( &wrapper, &QgsProcessingHiddenWidgetWrapper::widgetValueHasChanged ); + + QgsProcessingContext context; + wrapper.setWidgetValue( 1, context ); + QCOMPARE( spy.count(), 1 ); + QCOMPARE( wrapper.widgetValue().toInt(), 1 ); + wrapper.setWidgetValue( 1, context ); + QCOMPARE( spy.count(), 1 ); + QCOMPARE( wrapper.widgetValue().toInt(), 1 ); + wrapper.setWidgetValue( 2, context ); + QCOMPARE( spy.count(), 2 ); + QCOMPARE( wrapper.widgetValue().toInt(), 2 ); + + QVERIFY( !wrapper.createWrappedWidget( context ) ); + QVERIFY( !wrapper.createWrappedLabel() ); + + std::unique_ptr< QgsVectorLayer > vl = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Polygon?crs=epsg:3111&field=pk:int" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ); + QVERIFY( !wrapper.linkedVectorLayer() ); + wrapper.setLinkedVectorLayer( vl.get() ); + QCOMPARE( wrapper.linkedVectorLayer(), vl.get() ); +} + void TestProcessingGui::testBooleanWrapper() { TestParamType param( QStringLiteral( "boolean" ), QStringLiteral( "bool" ) ); diff --git a/tests/src/gui/testqgsattributeform.cpp b/tests/src/gui/testqgsattributeform.cpp index 23eafc55efac..6d96505f596c 100644 --- a/tests/src/gui/testqgsattributeform.cpp +++ b/tests/src/gui/testqgsattributeform.cpp @@ -50,6 +50,7 @@ class TestQgsAttributeForm : public QObject void testConstraintsOnJoinedFields(); void testEditableJoin(); void testUpsertOnEdit(); + void testFixAttributeForm(); void testAttributeFormInterface(); void testDefaultValueUpdate(); void testDefaultValueUpdateRecursion(); @@ -878,6 +879,41 @@ void TestQgsAttributeForm::testUpsertOnEdit() delete layerC; } +void TestQgsAttributeForm::testFixAttributeForm() +{ + QString def = QStringLiteral( "Point?field=id:integer&field=col1:integer" ); + QgsVectorLayer *layer = new QgsVectorLayer( def, QStringLiteral( "layer" ), QStringLiteral( "memory" ) ); + + QVERIFY( layer ); + + QgsFeature f( layer->fields() ); + f.setAttribute( 0, 1 ); + f.setAttribute( 1, 681 ); + + QgsAttributeForm form( layer ); + + form.setMode( QgsAttributeEditorContext::FixAttributeMode ); + form.setFeature( f ); + + QgsEditorWidgetWrapper *ww = qobject_cast( form.mWidgets[1] ); + QCOMPARE( ww->field().name(), QString( "col1" ) ); + QCOMPARE( ww->value(), QVariant( 681 ) ); + + // now change the value + ww->setValue( QVariant( 630 ) ); + + // the value should be updated + QCOMPARE( ww->value(), QVariant( 630 ) ); + // the feature is not saved yet, so contains the old value + QCOMPARE( form.feature().attribute( QStringLiteral( "col1" ) ), QVariant( 681 ) ); + // now save the feature and enjoy its new value, but don't update the layer + QVERIFY( form.save() ); + QCOMPARE( form.feature().attribute( QStringLiteral( "col1" ) ), QVariant( 630 ) ); + QCOMPARE( ( int )layer->featureCount(), 0 ); + + delete layer; +} + void TestQgsAttributeForm::testAttributeFormInterface() { // Issue https://github.com/qgis/QGIS/issues/29667 diff --git a/tests/src/gui/testqgsdoublevalidator.cpp b/tests/src/gui/testqgsdoublevalidator.cpp new file mode 100644 index 000000000000..c5269fb6bb27 --- /dev/null +++ b/tests/src/gui/testqgsdoublevalidator.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + testqgsdoublespinbox.cpp + -------------------------------------- + Date : June 2020 + Copyright : (C) 2020 Sebastien Peillet + Email : sebastien dot peillet at oslandia dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include "qgstest.h" + +#include "qgsdoublevalidator.h" +#include + +class TestQgsDoubleValidator: public QObject +{ + Q_OBJECT + private slots: + void initTestCase(); // will be called before the first testfunction is executed. + void cleanupTestCase(); // will be called after the last testfunction was executed. + void init(); // will be called before each testfunction is executed. + void cleanup(); // will be called after every testfunction. + + void validate(); + void validate_data(); + void toDouble_data(); + void toDouble(); + + private: + +}; + +void TestQgsDoubleValidator::initTestCase() +{ + +} + +void TestQgsDoubleValidator::cleanupTestCase() +{ +} + +void TestQgsDoubleValidator::init() +{ +} + +void TestQgsDoubleValidator::cleanup() +{ +} + +void TestQgsDoubleValidator::validate_data() +{ + QTest::addColumn( "actualState" ); + QTest::addColumn( "expState" ); + + QTest::newRow( "C decimal" ) << QString( "4cd6" ) << int( QValidator::Acceptable ); + QTest::newRow( "locale decimal" ) << QString( "4ld6" ) << int( QValidator::Acceptable ); + QTest::newRow( "locale decimal" ) << QString( "4444ld6" ) << int( QValidator::Acceptable ); + + // QgsDoubleValidator doesn't expect group separator but it tolerates it, + // so the result will be QValidator::Intermediate and not QValidator::Acceptable + QTest::newRow( "locale group separator + locale decimal" ) << QString( "4lg444ld6" ) << int( QValidator::Intermediate ); + QTest::newRow( "locale group separator + c decimal" ) << QString( "4lg444cd6" ) << int( QValidator::Invalid ); + QTest::newRow( "c group separator + locale decimal" ) << QString( "4cg444ld6" ) << int( QValidator::Invalid ); + QTest::newRow( "c group separator + c decimal" ) << QString( "4cg444cd6" ) << int( QValidator::Intermediate ); + + QTest::newRow( "outside the range + local decimal" ) << QString( "3ld6" ) << int( QValidator::Intermediate ); + QTest::newRow( "outside the range + c decimal" ) << QString( "3cd6" ) << int( QValidator::Intermediate ); + QTest::newRow( "string" ) << QString( "string" ) << int( QValidator::Invalid ); + +} + +void TestQgsDoubleValidator::toDouble_data() +{ + QTest::addColumn( "actualValue" ); + QTest::addColumn( "expValue" ); + + QTest::newRow( "C decimal" ) << QString( "4cd6" ) << 4.6; + QTest::newRow( "locale decimal" ) << QString( "4ld6" ) << 4.6; + QTest::newRow( "locale decimal" ) << QString( "4444ld6" ) << 4444.6; + + // QgsDoubleValidator doesn't expect group separator but it tolerates it, + // so the result will be QValidator::Intermediate and not QValidator::Acceptable + QTest::newRow( "locale group separator + locale decimal" ) << QString( "4lg444ld6" ) << 4444.6; + QTest::newRow( "locale group separator + c decimal" ) << QString( "4lg444cd6" ) << 0.0; + QTest::newRow( "c group separator + locale decimal" ) << QString( "4cg444ld6" ) << 0.0; + QTest::newRow( "c group separator + c decimal" ) << QString( "4cg444cd6" ) << 4444.6; + + QTest::newRow( "outside the range + local decimal" ) << QString( "3ld6" ) << 3.6; + QTest::newRow( "outside the range + c decimal" ) << QString( "3cd6" ) << 3.6; + QTest::newRow( "string" ) << QString( "string" ) << 0.0; + +} + +void TestQgsDoubleValidator::validate() +{ + QLineEdit *lineEdit = new QLineEdit(); + QgsDoubleValidator *validator = new QgsDoubleValidator( 4, 10000, lineEdit ); + lineEdit->setValidator( validator ); + + QFETCH( QString, actualState ); + QFETCH( int, expState ); + QString value; + int expectedValue; + + QVectorlistLocale( {QLocale::English, QLocale::French, QLocale::German, QLocale::Italian} ); + QLocale loc; + for ( int i = 0; i < listLocale.count(); ++i ) + { + loc = listLocale.at( i ); + QLocale().setDefault( loc ); + validator->setLocale( loc ); + value = actualState; + value = value.replace( "ld", QLocale().decimalPoint() ) + .replace( "cd", QLocale( QLocale::C ).decimalPoint() ) + .replace( "lg", QLocale().groupSeparator() ) + .replace( "cg", QLocale( QLocale::C ).groupSeparator() ); + expectedValue = expState; + // if the local group separator / decimal point is equal to the C one, + // expected result will be different for double with test with mixed + // local/C characters. + // Example with lg as local group separator + // cg as C group separator + // ld as local decimal point + // cd as C decimal point + // for 4cg444ld6 double, if cg == lg then 4cg444ld6 == 4lg444ld6 + // and validator->validate(4lg444ld6) == 1 and not 0 + // for 4cg444ld6 double, if cd == ld then 4cg444ld6 == 4cg444cd6 + // and validator->validate(4cg444cd6) == 1 and not 0 + if ( ( QLocale( QLocale::C ).groupSeparator() == QLocale().groupSeparator() || + QLocale( QLocale::C ).decimalPoint() == QLocale().decimalPoint() ) + && value != "string" && expectedValue == 0 ) + expectedValue = 1; + QCOMPARE( int( validator->validate( value ) ), expectedValue ); + } +} + +void TestQgsDoubleValidator::toDouble() +{ + QFETCH( QString, actualValue ); + QFETCH( double, expValue ); + QString value; + double expectedValue; + + QVectorlistLocale( {QLocale::English, QLocale::French, QLocale::German, QLocale::Italian} ); + QLocale loc; + for ( int i = 0; i < listLocale.count(); ++i ) + { + loc = listLocale.at( i ); + QLocale().setDefault( loc ); + value = actualValue; + value = value.replace( "ld", QLocale().decimalPoint() ) + .replace( "cd", QLocale( QLocale::C ).decimalPoint() ) + .replace( "lg", QLocale().groupSeparator() ) + .replace( "cg", QLocale( QLocale::C ).groupSeparator() ); + expectedValue = expValue; + // if the local group separator / decimal point is equal to the C one, + // expected result will be different for double with test with mixed + // local/C characters. + // Example with lg as local group separator + // cg as C group separator + // ld as local decimal point + // cd as C group decimal point + // for 4cg444ld6 double, if cg == lg then 4cg444ld6 == 4lg444ld6 + // and QgsDoubleValidator::toDouble(4lg444ld6) == 4444.6 and not 0.0 + // for 4cg444ld6 double, if cd == ld then 4cg444ld6 == 4cg444cd6 + // and QgsDoubleValidator::toDouble(4cg444cd6) == 4444.6 and not 0.0 + if ( ( QLocale( QLocale::C ).groupSeparator() == QLocale().groupSeparator() || + QLocale( QLocale::C ).decimalPoint() == QLocale().decimalPoint() ) + && value != "string" && expectedValue == 0.0 ) + expectedValue = 4444.6; + + QCOMPARE( QgsDoubleValidator::toDouble( value ), expectedValue ); + } + +} + +QGSTEST_MAIN( TestQgsDoubleValidator ) +#include "testqgsdoublevalidator.moc" diff --git a/tests/src/gui/testqgsnewdatabasetablewidget.cpp b/tests/src/gui/testqgsnewdatabasetablewidget.cpp index 964a6c565e1b..fd74a610a458 100644 --- a/tests/src/gui/testqgsnewdatabasetablewidget.cpp +++ b/tests/src/gui/testqgsnewdatabasetablewidget.cpp @@ -138,6 +138,14 @@ void TestQgsNewDatabaseTableNameWidget::testWidgetSignalsPostgres() QVERIFY( ! w->isValid() ); + /* + QDialog d; + QVBoxLayout l; + l.addWidget( w.get() ); + d.setLayout( &l ); + d.exec(); + //*/ + QCOMPARE( providerSpy.count(), 1 ); QCOMPARE( uriSpy.count(), 0 ); QCOMPARE( tableSpy.count(), 0 ); diff --git a/tests/src/gui/testqgstableeditor.cpp b/tests/src/gui/testqgstableeditor.cpp index 4ee2220a5409..dbb8ba0e8f77 100644 --- a/tests/src/gui/testqgstableeditor.cpp +++ b/tests/src/gui/testqgstableeditor.cpp @@ -40,6 +40,9 @@ class TestQgsTableEditor: public QObject void clearSelected(); void foregroundColor(); void backgroundColor(); + void alignment(); + void properties(); + void textFormat(); void numericFormat(); void rowHeight(); void columnWidth(); @@ -78,9 +81,16 @@ void TestQgsTableEditor::testData() format->setNumberDecimalPlaces( 2 ); format->setPrefix( QStringLiteral( "$" ) ); c3.setNumericFormat( format.release() ); + c3.setHorizontalAlignment( Qt::AlignJustify ); + c3.setVerticalAlignment( Qt::AlignBottom ); QgsTableCell c2( 76 ); c2.setBackgroundColor( QColor( 255, 0, 0 ) ); c2.setForegroundColor( QColor( 0, 255, 0 ) ); + QgsTextFormat textFormat; + textFormat.setSize( 12.6 ); + c2.setTextFormat( textFormat ); + c2.setHorizontalAlignment( Qt::AlignRight ); + c2.setVerticalAlignment( Qt::AlignTop ); w.setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "Jet" ) ) << c2 << c3 ) ); QCOMPARE( spy.count(), 1 ); @@ -89,17 +99,25 @@ void TestQgsTableEditor::testData() QCOMPARE( w.tableContents().at( 0 ).at( 0 ).content().toString(), QStringLiteral( "Jet" ) ); QVERIFY( !w.tableContents().at( 0 ).at( 0 ).backgroundColor().isValid() ); QVERIFY( !w.tableContents().at( 0 ).at( 0 ).foregroundColor().isValid() ); + QVERIFY( !w.tableContents().at( 0 ).at( 0 ).textFormat().isValid() ); QVERIFY( !w.tableContents().at( 0 ).at( 0 ).numericFormat() ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).verticalAlignment(), Qt::AlignVCenter ); QCOMPARE( w.tableContents().at( 0 ).at( 1 ).content().toString(), QStringLiteral( "76" ) ); QCOMPARE( w.tableContents().at( 0 ).at( 1 ).backgroundColor(), QColor( 255, 0, 0 ) ); QCOMPARE( w.tableContents().at( 0 ).at( 1 ).foregroundColor(), QColor( 0, 255, 0 ) ); QVERIFY( !w.tableContents().at( 0 ).at( 1 ).numericFormat() ); + QVERIFY( w.tableContents().at( 0 ).at( 1 ).textFormat().isValid() ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).textFormat().size(), 12.6 ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).horizontalAlignment(), Qt::AlignRight ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).verticalAlignment(), Qt::AlignTop ); QCOMPARE( w.tableContents().at( 0 ).at( 2 ).content().toString(), QStringLiteral( "87" ) ); QVERIFY( !w.tableContents().at( 0 ).at( 2 ).backgroundColor().isValid() ); QVERIFY( !w.tableContents().at( 0 ).at( 2 ).foregroundColor().isValid() ); QVERIFY( w.tableContents().at( 0 ).at( 2 ).numericFormat() ); QCOMPARE( w.tableContents().at( 0 ).at( 2 ).numericFormat()->id(), QStringLiteral( "currency" ) ); - + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).horizontalAlignment(), Qt::AlignJustify ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).verticalAlignment(), Qt::AlignBottom ); } void TestQgsTableEditor::insertRowsBelow() @@ -839,6 +857,182 @@ void TestQgsTableEditor::backgroundColor() QVERIFY( !w.selectionBackgroundColor().isValid() ); } +void TestQgsTableEditor::alignment() +{ + QgsTableEditorWidget w; + QVERIFY( w.tableContents().isEmpty() ); + + QSignalSpy spy( &w, &QgsTableEditorWidget::tableChanged ); + QgsTableCell c3; + c3.setContent( 87 ); + std::unique_ptr< QgsCurrencyNumericFormat > format = qgis::make_unique< QgsCurrencyNumericFormat >(); + format->setNumberDecimalPlaces( 2 ); + format->setPrefix( QStringLiteral( "$" ) ); + c3.setNumericFormat( format.release() ); + QgsTableCell c2( 76 ); + c2.setHorizontalAlignment( Qt::AlignRight ); + c2.setVerticalAlignment( Qt::AlignBottom ); + w.setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "Jet" ) ) << c2 << c3 << QgsTableCell( QStringLiteral( "Jet3" ) ) ) ); + QCOMPARE( spy.count(), 1 ); + + QCOMPARE( w.tableContents().size(), 1 ); + QCOMPARE( w.tableContents().at( 0 ).size(), 4 ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).content().toString(), QStringLiteral( "Jet" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).verticalAlignment(), Qt::AlignVCenter ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).content().toString(), QStringLiteral( "76" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).horizontalAlignment(), Qt::AlignRight ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).verticalAlignment(), Qt::AlignBottom ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).content().toString(), QStringLiteral( "87" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).verticalAlignment(), Qt::AlignVCenter ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).content().toString(), QStringLiteral( "Jet3" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).verticalAlignment(), Qt::AlignVCenter ); + + w.selectionModel()->clearSelection(); + w.setSelectionVerticalAlignment( Qt::AlignTop ); + w.setSelectionHorizontalAlignment( Qt::AlignCenter ); + QCOMPARE( spy.count(), 1 ); + + w.selectionModel()->select( w.model()->index( 0, 0 ), QItemSelectionModel::ClearAndSelect ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).verticalAlignment(), Qt::AlignVCenter ); + w.selectionModel()->select( w.model()->index( 0, 1 ), QItemSelectionModel::Select ); + QCOMPARE( w.selectionHorizontalAlignment(), Qt::AlignLeft | Qt::AlignTop ); + QCOMPARE( w.selectionVerticalAlignment(), Qt::AlignLeft | Qt::AlignTop ); + w.selectionModel()->select( w.model()->index( 0, 1 ), QItemSelectionModel::ClearAndSelect ); + QCOMPARE( w.selectionHorizontalAlignment(), Qt::AlignRight ); + QCOMPARE( w.selectionVerticalAlignment(), Qt::AlignBottom ); + w.selectionModel()->select( w.model()->index( 0, 0 ), QItemSelectionModel::Select ); + QCOMPARE( w.selectionHorizontalAlignment(), Qt::AlignLeft | Qt::AlignTop ); + QCOMPARE( w.selectionVerticalAlignment(), Qt::AlignLeft | Qt::AlignTop ); + w.setSelectionHorizontalAlignment( Qt::AlignJustify ); + w.setSelectionVerticalAlignment( Qt::AlignTop ); + QCOMPARE( spy.count(), 3 ); + QCOMPARE( w.selectionHorizontalAlignment(), Qt::AlignJustify ); + QCOMPARE( w.selectionVerticalAlignment(), Qt::AlignTop ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).horizontalAlignment(), Qt::AlignJustify ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).verticalAlignment(), Qt::AlignTop ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).horizontalAlignment(), Qt::AlignJustify ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).verticalAlignment(), Qt::AlignTop ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).verticalAlignment(), Qt::AlignVCenter ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).horizontalAlignment(), Qt::AlignLeft ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).verticalAlignment(), Qt::AlignVCenter ); + w.selectionModel()->select( w.model()->index( 0, 3 ), QItemSelectionModel::Select ); + QCOMPARE( w.selectionHorizontalAlignment(), Qt::AlignLeft | Qt::AlignTop ); + QCOMPARE( w.selectionVerticalAlignment(), Qt::AlignLeft | Qt::AlignTop ); +} + +void TestQgsTableEditor::properties() +{ + QgsTableEditorWidget w; + QVERIFY( w.tableContents().isEmpty() ); + + QSignalSpy spy( &w, &QgsTableEditorWidget::tableChanged ); + QgsTableCell c3; + c3.setContent( 87 ); + std::unique_ptr< QgsCurrencyNumericFormat > format = qgis::make_unique< QgsCurrencyNumericFormat >(); + format->setNumberDecimalPlaces( 2 ); + format->setPrefix( QStringLiteral( "$" ) ); + c3.setNumericFormat( format.release() ); + QgsTableCell c2( QVariant::fromValue( QgsProperty::fromExpression( "1+2" ) ) ); + w.setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "Jet" ) ) << c2 << c3 << QgsTableCell( QStringLiteral( "Jet3" ) ) ) ); + QCOMPARE( spy.count(), 1 ); + + QCOMPARE( w.tableContents().size(), 1 ); + QCOMPARE( w.tableContents().at( 0 ).size(), 4 ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).content().toString(), QStringLiteral( "Jet" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 0 ).content().canConvert< QgsProperty >() ); + QVERIFY( w.tableContents().at( 0 ).at( 1 ).content().canConvert< QgsProperty >() ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).content().value< QgsProperty >().asExpression(), QStringLiteral( "1+2" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).content().toString(), QStringLiteral( "87" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 2 ).content().canConvert< QgsProperty >() ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).content().toString(), QStringLiteral( "Jet3" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 3 ).content().canConvert< QgsProperty >() ); + + w.selectionModel()->clearSelection(); + w.setSelectionCellProperty( QgsProperty::fromExpression( QStringLiteral( "2+3" ) ) ); + QCOMPARE( spy.count(), 1 ); + + w.selectionModel()->select( w.model()->index( 0, 0 ), QItemSelectionModel::ClearAndSelect ); + QVERIFY( !w.tableContents().at( 0 ).at( 0 ).content().canConvert< QgsProperty >() ); + w.selectionModel()->select( w.model()->index( 0, 1 ), QItemSelectionModel::Select ); + QVERIFY( !w.selectionCellProperty().isActive() ); + w.selectionModel()->select( w.model()->index( 0, 1 ), QItemSelectionModel::ClearAndSelect ); + QVERIFY( w.selectionCellProperty().isActive() ); + QCOMPARE( w.selectionCellProperty().asExpression(), QStringLiteral( "1+2" ) ); + w.selectionModel()->select( w.model()->index( 0, 0 ), QItemSelectionModel::Select ); + QVERIFY( !w.selectionCellProperty().isActive() ); + w.setSelectionCellProperty( QgsProperty::fromExpression( QStringLiteral( "3+4" ) ) ); + QCOMPARE( spy.count(), 2 ); + QVERIFY( w.selectionCellProperty().isActive() ); + QCOMPARE( w.selectionCellProperty().asExpression(), QStringLiteral( "3+4" ) ); + QVERIFY( w.tableContents().at( 0 ).at( 0 ).content().canConvert< QgsProperty >() ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).content().value< QgsProperty >().asExpression(), QStringLiteral( "3+4" ) ); + QVERIFY( w.tableContents().at( 0 ).at( 1 ).content().canConvert< QgsProperty >() ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).content().value< QgsProperty >().asExpression(), QStringLiteral( "3+4" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).content().toString(), QStringLiteral( "87" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 2 ).content().canConvert< QgsProperty >() ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).content().toString(), QStringLiteral( "Jet3" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 3 ).content().canConvert< QgsProperty >() ); + w.selectionModel()->select( w.model()->index( 0, 3 ), QItemSelectionModel::Select ); + QVERIFY( !w.selectionCellProperty().isActive() ); +} + +void TestQgsTableEditor::textFormat() +{ + QgsTableEditorWidget w; + QVERIFY( w.tableContents().isEmpty() ); + + QSignalSpy spy( &w, &QgsTableEditorWidget::tableChanged ); + QgsTableCell c3; + c3.setContent( 87 ); + QgsTextFormat format; + format.setSize( 12.6 ); + c3.setTextFormat( format ); + QgsTableCell c2( 76 ); + c2.setTextFormat( format ); + w.setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "Jet" ) ) << c2 << c3 << QgsTableCell( QStringLiteral( "Jet3" ) ) ) ); + QCOMPARE( spy.count(), 1 ); + + QCOMPARE( w.tableContents().size(), 1 ); + QCOMPARE( w.tableContents().at( 0 ).size(), 4 ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).content().toString(), QStringLiteral( "Jet" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 0 ).textFormat().isValid() ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).content().toString(), QStringLiteral( "76" ) ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).textFormat().size(), 12.6 ); + QVERIFY( w.tableContents().at( 0 ).at( 1 ).textFormat().isValid() ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).content().toString(), QStringLiteral( "87" ) ); + QVERIFY( w.tableContents().at( 0 ).at( 2 ).textFormat().isValid() ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).textFormat().size(), 12.6 ); + QCOMPARE( w.tableContents().at( 0 ).at( 3 ).content().toString(), QStringLiteral( "Jet3" ) ); + QVERIFY( !w.tableContents().at( 0 ).at( 3 ).textFormat().isValid() ); + + w.selectionModel()->clearSelection(); + format.setSize( 21 ); + w.setSelectionTextFormat( format ); + QCOMPARE( spy.count(), 1 ); + + w.selectionModel()->select( w.model()->index( 0, 0 ), QItemSelectionModel::ClearAndSelect ); + QVERIFY( w.selectionTextFormat().size() != 21.0 ); + w.selectionModel()->select( w.model()->index( 0, 1 ), QItemSelectionModel::Select ); + QVERIFY( w.selectionTextFormat().size() != 21.0 ); + w.selectionModel()->select( w.model()->index( 0, 1 ), QItemSelectionModel::ClearAndSelect ); + QCOMPARE( w.selectionTextFormat().size(), 12.6 ); + w.selectionModel()->select( w.model()->index( 0, 0 ), QItemSelectionModel::Select ); + QVERIFY( w.selectionTextFormat().size() != 21.0 ); + w.setSelectionTextFormat( format ); + QCOMPARE( spy.count(), 2 ); + QVERIFY( w.selectionTextFormat().isValid() ); + QCOMPARE( w.selectionTextFormat().size(), 21.0 ); + QCOMPARE( w.tableContents().at( 0 ).at( 0 ).textFormat().size(), 21.0 ); + QCOMPARE( w.tableContents().at( 0 ).at( 1 ).textFormat().size(), 21.0 ); + QCOMPARE( w.tableContents().at( 0 ).at( 2 ).textFormat().size(), 12.6 ); + QVERIFY( w.tableContents().at( 0 ).at( 3 ).textFormat().size() != 21 ); +} + void TestQgsTableEditor::numericFormat() { QgsTableEditorWidget w; diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index d07e0d60d800..dcf56bc0d7ca 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -175,6 +175,7 @@ ADD_PYTHON_TEST(PyQgsNullSymbolRenderer test_qgsnullsymbolrenderer.py) ADD_PYTHON_TEST(PyQgsNumericFormat test_qgsnumericformat.py) ADD_PYTHON_TEST(PyQgsNumericFormatGui test_qgsnumericformatgui.py) ADD_PYTHON_TEST(PyQgsNewGeoPackageLayerDialog test_qgsnewgeopackagelayerdialog.py) +ADD_PYTHON_TEST(PyQgsNewVectorTableDialog test_qgsnewvectortabledialog.py) ADD_PYTHON_TEST(PyQgsNoApplication test_qgsnoapplication.py) ADD_PYTHON_TEST(PyQgsObjectCustomProperties test_qgsobjectcustomproperties.py) ADD_PYTHON_TEST(PyQgsOgcUtils test_qgsogcutils.py) diff --git a/tests/src/python/test_provider_mssql.py b/tests/src/python/test_provider_mssql.py index f394f85bdfa0..b0853fbc48dc 100644 --- a/tests/src/python/test_provider_mssql.py +++ b/tests/src/python/test_provider_mssql.py @@ -23,12 +23,12 @@ QgsGeometry, QgsPointXY, QgsRectangle, + QgsProviderRegistry, NULL, QgsVectorLayerExporter, QgsCoordinateReferenceSystem) from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant -from qgis.PyQt.QtSql import QSqlDatabase, QSqlQuery from utilities import unitTestDataPath from qgis.testing import start_app, unittest from providertestbase import ProviderTestCase @@ -58,24 +58,14 @@ def setUpClass(cls): assert cls.poly_vl.isValid(), cls.poly_vl.dataProvider().error().message() cls.poly_provider = cls.poly_vl.dataProvider() - cls.conn = QSqlDatabase.addDatabase('QODBC') - cls.conn.setDatabaseName('testsqlserver') - if 'QGIS_MSSQLTEST_DB2' in os.environ: - print(os.environ['QGIS_MSSQLTEST_DB2']) - cls.conn.setDatabaseName(os.environ['QGIS_MSSQLTEST_DB2']) - elif 'QGIS_MSSQLTEST_DB' in os.environ: - print(os.environ['QGIS_MSSQLTEST_DB']) - cls.conn.setDatabaseName(os.environ['QGIS_MSSQLTEST_DB']) - else: - cls.conn.setUserName('SA') - cls.conn.setPassword('') - - assert cls.conn.open(), cls.conn.lastError().text() - # Triggers a segfault in the sql server odbc driver on Travis - TODO test with more recent Ubuntu base image if os.environ.get('TRAVIS', '') == 'true': del cls.getEditableLayer + # Use connections API + md = QgsProviderRegistry.instance().providerMetadata('mssql') + cls.conn_api = md.createConnection(cls.dbconn, {}) + @classmethod def tearDownClass(cls): """Run after all tests""" @@ -86,10 +76,8 @@ def setUp(self): self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.[{}]'.format(t)) def execSQLCommand(self, sql): - self.assertTrue(self.conn) - query = QSqlQuery(self.conn) - self.assertTrue(query.exec_(sql), sql + ': ' + query.lastError().text()) - query.finish() + self.assertTrue(self.conn_api) + self.conn_api.executeSql(sql) def getSource(self): # create temporary table for edit tests diff --git a/tests/src/python/test_qgsfontbutton.py b/tests/src/python/test_qgsfontbutton.py index 9e8cfed83c1e..71e80e9eeeec 100644 --- a/tests/src/python/test_qgsfontbutton.py +++ b/tests/src/python/test_qgsfontbutton.py @@ -103,6 +103,21 @@ def testSetColor(self): r = button.textFormat() self.assertEqual(r.color(), QColor(0, 255, 0)) + def testNull(self): + button = QgsFontButton() + self.assertFalse(button.showNullFormat()) + button.setShowNullFormat(True) + self.assertTrue(button.showNullFormat()) + + s = QgsTextFormat() + s.setFont(getTestFont()) + button.setTextFormat(s) + self.assertTrue(button.textFormat().isValid()) + button.setToNullFormat() + self.assertFalse(button.textFormat().isValid()) + button.setTextFormat(s) + self.assertTrue(button.textFormat().isValid()) + if __name__ == '__main__': unittest.main() diff --git a/tests/src/python/test_qgslayoutmapgrid.py b/tests/src/python/test_qgslayoutmapgrid.py index bb892abacb54..5b0a725e1215 100644 --- a/tests/src/python/test_qgslayoutmapgrid.py +++ b/tests/src/python/test_qgslayoutmapgrid.py @@ -12,7 +12,7 @@ import qgis # NOQA -from qgis.PyQt.QtCore import QRectF +from qgis.PyQt.QtCore import QRectF, QDir from qgis.PyQt.QtGui import QPainter, QColor from qgis.core import (QgsLayoutItemMap, @@ -22,7 +22,9 @@ QgsProperty, QgsLayoutObject, QgsFontUtils, - QgsProject) + QgsTextFormat, + QgsProject, + QgsCoordinateReferenceSystem) from qgis.testing import start_app, unittest from utilities import unitTestDataPath, getTestFont from qgslayoutchecker import QgsLayoutChecker @@ -33,10 +35,19 @@ class TestQgsLayoutMapGrid(unittest.TestCase): + def setUp(self): + self.report = "

Python QgsLayoutItemMap Tests

\n" + + def tearDown(self): + report_file_path = "%s/qgistest.html" % QDir.tempPath() + with open(report_file_path, 'a') as report_file: + report_file.write(self.report) + def testGrid(self): layout = QgsLayout(QgsProject.instance()) layout.initializeDefaults() map = QgsLayoutItemMap(layout) + map.setCrs(QgsCoordinateReferenceSystem('EPSG:32633')) map.attemptSetSceneRect(QRectF(20, 20, 200, 100)) map.setFrameEnabled(True) map.setBackgroundColor(QColor(150, 100, 100)) @@ -55,7 +66,10 @@ def testGrid(self): map.grid().setAnnotationEnabled(True) map.grid().setGridLineColor(QColor(0, 255, 0)) map.grid().setGridLineWidth(0.5) - map.grid().setAnnotationFont(getTestFont()) + format = QgsTextFormat.fromQFont(getTestFont('Bold')) + format.setColor(QColor(255, 0, 0)) + format.setOpacity(150 / 255) + map.grid().setAnnotationTextFormat(format) map.grid().setAnnotationPrecision(0) map.grid().setAnnotationDisplay(QgsLayoutItemMapGrid.HideAll, QgsLayoutItemMapGrid.Left) map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Right) @@ -63,13 +77,13 @@ def testGrid(self): map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Bottom) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Right) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Bottom) - map.grid().setAnnotationFontColor(QColor(255, 0, 0, 150)) map.grid().setBlendMode(QPainter.CompositionMode_Overlay) map.updateBoundingRect() checker = QgsLayoutChecker('composermap_grid', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() map.grid().setEnabled(False) map.grid().setAnnotationEnabled(False) @@ -100,6 +114,7 @@ def testCrossGrid(self): checker = QgsLayoutChecker('composermap_crossgrid', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() map.grid().setStyle(QgsLayoutItemMapGrid.Solid) map.grid().setEnabled(False) @@ -131,6 +146,7 @@ def testMarkerGrid(self): checker = QgsLayoutChecker('composermap_markergrid', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() map.grid().setStyle(QgsLayoutItemMapGrid.Solid) map.grid().setEnabled(False) @@ -162,6 +178,7 @@ def testFrameOnly(self): checker = QgsLayoutChecker('composermap_gridframeonly', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() map.grid().setStyle(QgsLayoutItemMapGrid.Solid) map.grid().setEnabled(False) @@ -186,7 +203,6 @@ def testZebraStyle(self): map.grid().setIntervalX(2000) map.grid().setIntervalY(2000) map.grid().setGridLineColor(QColor(0, 0, 0)) - map.grid().setAnnotationFontColor(QColor(0, 0, 0)) map.grid().setBlendMode(QPainter.CompositionMode_SourceOver) map.grid().setFrameStyle(QgsLayoutItemMapGrid.Zebra) map.grid().setFrameWidth(10) @@ -201,6 +217,7 @@ def testZebraStyle(self): checker = QgsLayoutChecker('composermap_zebrastyle', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout(0, 100) + self.report += checker.report() assert myTestResult, myMessage def testZebraStyleSides(self): @@ -218,7 +235,6 @@ def testZebraStyleSides(self): map.grid().setIntervalX(2000) map.grid().setIntervalY(2000) map.grid().setGridLineColor(QColor(0, 0, 0)) - map.grid().setAnnotationFontColor(QColor(0, 0, 0)) map.grid().setBlendMode(QPainter.CompositionMode_SourceOver) map.grid().setFrameStyle(QgsLayoutItemMapGrid.Zebra) map.grid().setFrameWidth(10) @@ -238,6 +254,7 @@ def testZebraStyleSides(self): checker = QgsLayoutChecker('composermap_zebrastyle_left', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout(0, 100) + self.report += checker.report() assert myTestResult, myMessage map.grid().setFrameSideFlag(QgsLayoutItemMapGrid.FrameTop, True) @@ -245,6 +262,7 @@ def testZebraStyleSides(self): checker = QgsLayoutChecker('composermap_zebrastyle_lefttop', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout(0, 100) + self.report += checker.report() assert myTestResult, myMessage map.grid().setFrameSideFlag(QgsLayoutItemMapGrid.FrameRight, True) @@ -252,6 +270,7 @@ def testZebraStyleSides(self): checker = QgsLayoutChecker('composermap_zebrastyle_lefttopright', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout(0, 100) + self.report += checker.report() assert myTestResult, myMessage map.grid().setFrameSideFlag(QgsLayoutItemMapGrid.FrameBottom, True) @@ -271,7 +290,6 @@ def testInteriorTicks(self): map.setExtent(myRectangle) map.grid().setIntervalX(2000) map.grid().setIntervalY(2000) - map.grid().setAnnotationFontColor(QColor(0, 0, 0)) map.grid().setBlendMode(QPainter.CompositionMode_SourceOver) map.grid().setFrameStyle(QgsLayoutItemMapGrid.InteriorTicks) map.grid().setFrameWidth(10) @@ -284,6 +302,7 @@ def testInteriorTicks(self): checker = QgsLayoutChecker('composermap_interiorticks', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout(0, 100) + self.report += checker.report() assert myTestResult, myMessage def testExpressionContext(self): @@ -321,7 +340,10 @@ def testDataDefinedEnabled(self): map.grid().setAnnotationEnabled(True) map.grid().setGridLineColor(QColor(0, 255, 0)) map.grid().setGridLineWidth(0.5) - map.grid().setAnnotationFont(getTestFont()) + format = QgsTextFormat.fromQFont(getTestFont('Bold')) + format.setColor(QColor(255, 0, 0)) + format.setOpacity(150 / 255) + map.grid().setAnnotationTextFormat(format) map.grid().setAnnotationPrecision(0) map.grid().setAnnotationDisplay(QgsLayoutItemMapGrid.HideAll, QgsLayoutItemMapGrid.Left) map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Right) @@ -329,7 +351,6 @@ def testDataDefinedEnabled(self): map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Bottom) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Right) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Bottom) - map.grid().setAnnotationFontColor(QColor(255, 0, 0, 150)) map.grid().setBlendMode(QPainter.CompositionMode_Overlay) map.updateBoundingRect() @@ -339,6 +360,7 @@ def testDataDefinedEnabled(self): checker = QgsLayoutChecker('composermap_grid', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) map.grid().dataDefinedProperties().setProperty(QgsLayoutObject.MapGridEnabled, QgsProperty.fromValue(False)) @@ -347,6 +369,7 @@ def testDataDefinedEnabled(self): checker = QgsLayoutChecker('composermap_datadefined_disabled', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) def testDataDefinedIntervalOffset(self): @@ -377,6 +400,7 @@ def testDataDefinedIntervalOffset(self): checker = QgsLayoutChecker('composermap_datadefined_intervaloffset', layout) checker.setControlPathPrefix("composer_mapgrid") + self.report += checker.report() myTestResult, myMessage = checker.testLayout() self.assertTrue(myTestResult, myMessage) @@ -415,6 +439,7 @@ def testDataDefinedFrameSize(self): 'composermap_datadefined_framesizemargin', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) def testDataDefinedCrossSize(self): @@ -446,6 +471,7 @@ def testDataDefinedCrossSize(self): checker = QgsLayoutChecker('composermap_datadefined_crosssize', layout) checker.setControlPathPrefix("composer_mapgrid") + self.report += checker.report() myTestResult, myMessage = checker.testLayout() self.assertTrue(myTestResult, myMessage) @@ -482,6 +508,7 @@ def testDataDefinedFrameThickness(self): checker = QgsLayoutChecker('composermap_datadefined_framethickness', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) def testDataDefinedAnnotationDistance(self): @@ -501,7 +528,12 @@ def testDataDefinedAnnotationDistance(self): map.grid().setAnnotationEnabled(True) map.grid().setGridLineColor(QColor(0, 255, 0)) map.grid().setGridLineWidth(0.5) - map.grid().setAnnotationFont(getTestFont('Bold', 20)) + + format = QgsTextFormat.fromQFont(getTestFont('Bold', 20)) + format.setColor(QColor(255, 0, 0)) + format.setOpacity(150 / 255) + map.grid().setAnnotationTextFormat(format) + map.grid().setAnnotationPrecision(0) map.grid().setAnnotationDisplay(QgsLayoutItemMapGrid.HideAll, QgsLayoutItemMapGrid.Left) map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Right) @@ -509,7 +541,6 @@ def testDataDefinedAnnotationDistance(self): map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Bottom) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Right) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Bottom) - map.grid().setAnnotationFontColor(QColor(255, 0, 0, 150)) map.grid().setBlendMode(QPainter.CompositionMode_Overlay) map.updateBoundingRect() @@ -519,6 +550,7 @@ def testDataDefinedAnnotationDistance(self): checker = QgsLayoutChecker('composermap_datadefined_annotationdistance', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) def testDynamicInterval(self): @@ -539,7 +571,12 @@ def testDynamicInterval(self): map.grid().setAnnotationEnabled(True) map.grid().setGridLineColor(QColor(0, 255, 0)) map.grid().setGridLineWidth(0.5) - map.grid().setAnnotationFont(getTestFont('Bold', 20)) + + format = QgsTextFormat.fromQFont(getTestFont('Bold', 20)) + format.setColor(QColor(255, 0, 0)) + format.setOpacity(150 / 255) + map.grid().setAnnotationTextFormat(format) + map.grid().setAnnotationPrecision(0) map.grid().setAnnotationDisplay(QgsLayoutItemMapGrid.HideAll, QgsLayoutItemMapGrid.Left) map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Right) @@ -547,7 +584,6 @@ def testDynamicInterval(self): map.grid().setAnnotationPosition(QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.Bottom) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Right) map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.Horizontal, QgsLayoutItemMapGrid.Bottom) - map.grid().setAnnotationFontColor(QColor(255, 0, 0, 150)) map.grid().setBlendMode(QPainter.CompositionMode_Overlay) map.updateBoundingRect() @@ -556,6 +592,7 @@ def testDynamicInterval(self): checker = QgsLayoutChecker('composermap_dynamic_5_10', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) map.setScale(map.scale() * 1.1) @@ -563,6 +600,7 @@ def testDynamicInterval(self): checker = QgsLayoutChecker('composermap_dynamic_5_10_2', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) map.setScale(map.scale() * 1.8) @@ -570,6 +608,7 @@ def testDynamicInterval(self): checker = QgsLayoutChecker('composermap_dynamic_5_10_3', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) map.grid().setMinimumIntervalWidth(10) @@ -579,6 +618,7 @@ def testDynamicInterval(self): checker = QgsLayoutChecker('composermap_dynamic_5_10_4', layout) checker.setControlPathPrefix("composer_mapgrid") myTestResult, myMessage = checker.testLayout() + self.report += checker.report() self.assertTrue(myTestResult, myMessage) diff --git a/tests/src/python/test_qgsnewvectortabledialog.py b/tests/src/python/test_qgsnewvectortabledialog.py new file mode 100644 index 000000000000..050c20fa43c4 --- /dev/null +++ b/tests/src/python/test_qgsnewvectortabledialog.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +"""QGIS Unit tests for QgsNewVectorTableDialog + +.. note:: This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +""" +__author__ = 'Alessandro Pasotti' +__date__ = '12/07/2020' +__copyright__ = 'Copyright 2020, The QGIS Project' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + + +import tempfile +import shutil + +from qgis.core import ( + QgsApplication, + QgsProviderRegistry, + QgsVectorLayer, + QgsWkbTypes, + QgsFields +) + +from qgis.gui import QgsNewVectorTableDialog +from qgis.testing import start_app, unittest +from qgis.PyQt.QtWidgets import ( + QDialogButtonBox, + QLineEdit, + QComboBox, + QCheckBox +) + +from utilities import unitTestDataPath + +TEST_DATA_DIR = unitTestDataPath() + + +class TestPyQgsNewVectorTableDialog(unittest.TestCase): + """Test QgsNewVectorTableDialog""" + + @classmethod + def setUpClass(cls): + """Run before all tests""" + start_app() + gpkg_original_path = '{}/qgis_server/test_project_wms_grouped_layers.gpkg'.format( + TEST_DATA_DIR) + cls.gpkg_path = tempfile.mktemp('.gpkg') + shutil.copy(gpkg_original_path, cls.gpkg_path) + vl = QgsVectorLayer('{}|layername=cdb_lines'.format( + cls.gpkg_path), 'test', 'ogr') + assert vl.isValid() + cls.uri = cls.gpkg_path + + def test_dialog(self): + + md = QgsProviderRegistry.instance().providerMetadata('ogr') + conn = md.createConnection(self.uri, {}) + dialog = QgsNewVectorTableDialog(conn) + dialog.setFields(conn.fields('', 'cdb_lines')) + dialog.setTableName('dont_lock_me_down_again') + + # dialog.exec_() + + geom_type_combo = dialog.findChildren(QComboBox, 'mGeomTypeCbo')[0] + geom_name_le = dialog.findChildren(QLineEdit, 'mGeomColumn')[0] + has_z_chk = dialog.findChildren(QCheckBox, 'mHasZChk')[0] + has_m_chk = dialog.findChildren(QCheckBox, 'mHasMChk')[0] + table_name = dialog.findChildren(QLineEdit, 'mTableName')[0] + buttons = dialog.findChildren(QDialogButtonBox, 'mButtonBox')[0] + ok_btn = buttons.button(QDialogButtonBox.Ok) + + # Default is no geometry, let's check if all geom options are disabled + self.assertFalse(geom_name_le.isEnabled()) + self.assertFalse(has_z_chk.isEnabled()) + self.assertFalse(has_m_chk.isEnabled()) + + # 2 is linestring + geom_type_combo.setCurrentIndex(3) + self.assertTrue(geom_name_le.isEnabled()) + self.assertTrue(has_z_chk.isEnabled()) + self.assertTrue(has_m_chk.isEnabled()) + + self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineString) + + # Set Z and check the type + has_z_chk.setChecked(True) + self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineStringZ) + has_z_chk.setChecked(False) + + # Set M and check the type + has_m_chk.setChecked(True) + self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineStringM) + + # Set both + has_z_chk.setChecked(True) + self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineStringZM) + + # Test validation (ok button enabled) + buttons = dialog.findChildren(QDialogButtonBox, 'mButtonBox')[0] + ok_btn = buttons.button(QDialogButtonBox.Ok) + self.assertTrue(ok_btn.isEnabled()) + + # Duplicate table name + table_name.setText('cdb_lines') + self.assertFalse(ok_btn.isEnabled()) + table_name.setText('cdb_lines2') + self.assertTrue(ok_btn.isEnabled()) + + # No fields (but geometry is ok) + dialog.setFields(QgsFields()) + self.assertTrue(ok_btn.isEnabled()) + + # Change to aspatial and check validity + geom_type_combo.setCurrentIndex(0) + self.assertFalse(ok_btn.isEnabled()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/src/python/test_qgsprocessexecutable.py b/tests/src/python/test_qgsprocessexecutable.py index 0ccef7c44a10..939dcce330f3 100644 --- a/tests/src/python/test_qgsprocessexecutable.py +++ b/tests/src/python/test_qgsprocessexecutable.py @@ -111,7 +111,7 @@ def testAlgorithmRunNoArgs(self): def testAlgorithmRun(self): output_file = self.TMP_DIR + '/polygon_centroid.shp' - rc, output, err = self.run_process(['run', 'native:centroids', '--INPUT={}'.format(TEST_DATA_DIR + '/polys.shp'), '--ALL_PARTS=false', '--OUTPUT={}'.format(output_file)]) + rc, output, err = self.run_process(['run', 'native:centroids', '--INPUT={}'.format(TEST_DATA_DIR + '/polys.shp'), '--OUTPUT={}'.format(output_file)]) if os.environ.get('TRAVIS', '') != 'true': # Travis DOES have errors, due to QStandardPaths: XDG_RUNTIME_DIR not set warnings raised by Qt self.assertFalse(err) diff --git a/tests/src/python/test_qgsproviderconnection_base.py b/tests/src/python/test_qgsproviderconnection_base.py index c7d202431328..26cfab276946 100644 --- a/tests/src/python/test_qgsproviderconnection_base.py +++ b/tests/src/python/test_qgsproviderconnection_base.py @@ -324,6 +324,24 @@ def _test_operations(self, md, conn): self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(4326)) self.assertEqual(ct.wkbType, QgsWkbTypes.LineString) + # Check fields + fields = conn.fields('myNewSchema', 'myNewTable') + for f in ['string_t', 'long_t', 'double_t', 'integer_t', 'date_t', 'datetime_t', 'time_t']: + self.assertTrue(f in fields.names()) + + if capabilities & QgsAbstractDatabaseProviderConnection.AddField: + field = QgsField('short_lived_field', QVariant.Int, 'integer') + conn.addField(field, 'myNewSchema', 'myNewTable') + fields = conn.fields('myNewSchema', 'myNewTable') + self.assertTrue('short_lived_field' in fields.names()) + + if capabilities & QgsAbstractDatabaseProviderConnection.DeleteField: + conn.deleteField('short_lived_field', 'myNewSchema', 'myNewTable') + # This fails on Travis for spatialite, for no particular reason + if self.providerKey == 'spatialite' and not os.environ.get('TRAVIS', False): + fields = conn.fields('myNewSchema', 'myNewTable') + self.assertFalse('short_lived_field' in fields.names()) + # Drop table conn.dropVectorTable(schema, 'myNewTable') conn.dropVectorTable(schema, 'myNewAspatialTable') @@ -383,3 +401,13 @@ def test_connections(self): self.assertEqual(len(changed_spy), 1) self._test_operations(md, conn) + + def test_native_types(self): + """Test native types retrieval""" + + md = QgsProviderRegistry.instance().providerMetadata(self.providerKey) + conn = md.createConnection(self.uri, {}) + native_types = conn.nativeTypes() + names = [nt.mTypeName.lower() for nt in native_types] + self.assertTrue('integer' in names or 'decimal' in names, names) + self.assertTrue('string' in names or 'text' in names, names) diff --git a/tests/src/python/test_qgsproviderconnection_mssql.py b/tests/src/python/test_qgsproviderconnection_mssql.py index 65b01d3d1f62..839ea08118bb 100644 --- a/tests/src/python/test_qgsproviderconnection_mssql.py +++ b/tests/src/python/test_qgsproviderconnection_mssql.py @@ -101,6 +101,14 @@ def test_table_uri(self): vl = QgsVectorLayer(conn.tableUri('qgis_test', 'someData'), 'my', 'mssql') self.assertTrue(vl.isValid()) + def test_gpkg_fields(self): + """Test fields""" + + md = QgsProviderRegistry.instance().providerMetadata('mssql') + conn = md.createConnection(self.uri, {}) + fields = conn.fields('qgis_test', 'someData') + self.assertEqual(fields.names(), ['pk', 'cnt', 'name', 'name2', 'num_char']) + if __name__ == '__main__': unittest.main() diff --git a/tests/src/python/test_qgsproviderconnection_ogr_gpkg.py b/tests/src/python/test_qgsproviderconnection_ogr_gpkg.py index a6da05887b2f..d6a8f8b24768 100644 --- a/tests/src/python/test_qgsproviderconnection_ogr_gpkg.py +++ b/tests/src/python/test_qgsproviderconnection_ogr_gpkg.py @@ -118,6 +118,14 @@ def test_gpkg_connections(self): self.assertFalse('myNewTable' in table_names) self.assertTrue('myNewAspatialTable' in table_names) + def test_gpkg_fields(self): + """Test fields""" + + md = QgsProviderRegistry.instance().providerMetadata('ogr') + conn = md.createConnection(self.uri, {}) + fields = conn.fields('', 'cdb_lines') + self.assertEqual(fields.names(), ['fid', 'id', 'typ', 'name', 'ortsrat', 'id_long']) + if __name__ == '__main__': unittest.main() diff --git a/tests/src/python/test_qgsproviderconnection_postgres.py b/tests/src/python/test_qgsproviderconnection_postgres.py index cf9c20be6891..376d24289a26 100644 --- a/tests/src/python/test_qgsproviderconnection_postgres.py +++ b/tests/src/python/test_qgsproviderconnection_postgres.py @@ -317,6 +317,14 @@ def test_foreign_table_server(self): conn.executeSql(foreign_table_definition) self.assertEquals(conn.tables('foreign_schema', QgsAbstractDatabaseProviderConnection.Foreign)[0].tableName(), 'someData') + def test_fields(self): + """Test fields""" + + md = QgsProviderRegistry.instance().providerMetadata('postgres') + conn = md.createConnection(self.uri, {}) + fields = conn.fields('qgis_test', 'someData') + self.assertEqual(fields.names(), ['pk', 'cnt', 'name', 'name2', 'num_char', 'dt', 'date', 'time', 'geom']) + if __name__ == '__main__': unittest.main() diff --git a/tests/src/python/test_qgsproviderconnection_spatialite.py b/tests/src/python/test_qgsproviderconnection_spatialite.py index fdc7fed52f7c..b85ec0234c44 100644 --- a/tests/src/python/test_qgsproviderconnection_spatialite.py +++ b/tests/src/python/test_qgsproviderconnection_spatialite.py @@ -110,6 +110,14 @@ def test_spatialite_connections(self): self.assertFalse('myNewTable' in table_names) self.assertTrue('myNewAspatialTable' in table_names) + def test_gpkg_fields(self): + """Test fields""" + + md = QgsProviderRegistry.instance().providerMetadata('spatialite') + conn = md.createConnection(self.uri, {}) + fields = conn.fields('', 'cdb_lines') + self.assertEqual(fields.names(), ['pk', 'geom', 'fid', 'id', 'typ', 'name', 'ortsrat', 'id_long']) + if __name__ == '__main__': unittest.main() diff --git a/tests/src/python/test_qgstablecell.py b/tests/src/python/test_qgstablecell.py index 2564eb909e38..b389e2bf7d16 100644 --- a/tests/src/python/test_qgstablecell.py +++ b/tests/src/python/test_qgstablecell.py @@ -13,7 +13,8 @@ import qgis # NOQA from qgis.core import (QgsTableCell, QgsBearingNumericFormat, - QgsReadWriteContext) + QgsReadWriteContext, + QgsTextFormat) from qgis.PyQt.QtGui import QColor @@ -35,6 +36,7 @@ def testCell(self): self.assertFalse(c.backgroundColor().isValid()) self.assertFalse(c.foregroundColor().isValid()) self.assertFalse(c.numericFormat()) + self.assertFalse(c.textFormat().isValid()) c.setBackgroundColor(QColor(255, 0, 0)) c.setForegroundColor(QColor(255, 0, 255)) @@ -43,6 +45,12 @@ def testCell(self): self.assertEqual(c.foregroundColor().name(), '#ff00ff') self.assertIsInstance(c.numericFormat(), QgsBearingNumericFormat) + format = QgsTextFormat() + format.setSize(16.8) + c.setTextFormat(format) + self.assertEqual(c.textFormat().size(), 16.8) + self.assertTrue(c.textFormat().isValid()) + def testProperties(self): c = QgsTableCell('test') @@ -55,12 +63,16 @@ def testProperties(self): self.assertFalse(c2.backgroundColor().isValid()) self.assertFalse(c2.foregroundColor().isValid()) self.assertFalse(c2.numericFormat()) + self.assertFalse(c2.textFormat().isValid()) c.setBackgroundColor(QColor(255, 0, 0)) c.setForegroundColor(QColor(255, 0, 255)) format = QgsBearingNumericFormat() format.setShowPlusSign(True) c.setNumericFormat(format) + text_format = QgsTextFormat() + text_format.setSize(16.8) + c.setTextFormat(text_format) props = c.properties(QgsReadWriteContext()) c3 = QgsTableCell() @@ -71,6 +83,8 @@ def testProperties(self): self.assertEqual(c3.foregroundColor().name(), '#ff00ff') self.assertIsInstance(c3.numericFormat(), QgsBearingNumericFormat) self.assertTrue(c3.numericFormat().showPlusSign()) + self.assertEqual(c3.textFormat().size(), 16.8) + self.assertTrue(c3.textFormat().isValid()) if __name__ == '__main__': diff --git a/tests/src/python/test_qgstextblock.py b/tests/src/python/test_qgstextblock.py index 91ffea2841ed..4dd73ce3b28f 100644 --- a/tests/src/python/test_qgstextblock.py +++ b/tests/src/python/test_qgstextblock.py @@ -35,6 +35,7 @@ def testConstructors(self): block = QgsTextBlock(fragment) self.assertEqual(len(block), 1) self.assertEqual(block[0].text(), fragment.text()) + self.assertEqual(block.toPlainText(), 'ludicrous gibs!') def testAppend(self): block = QgsTextBlock() @@ -50,6 +51,8 @@ def testAppend(self): self.assertEqual(block[0].text(), 'a') self.assertEqual(block[1].text(), 'b') + self.assertEqual(block.toPlainText(), 'ab') + def testAt(self): block = QgsTextBlock() block.append(QgsTextFragment('a')) diff --git a/tests/src/python/test_qgstextrenderer.py b/tests/src/python/test_qgstextrenderer.py index 2c59ab80f8bf..6c35b2da9f4e 100644 --- a/tests/src/python/test_qgstextrenderer.py +++ b/tests/src/python/test_qgstextrenderer.py @@ -52,14 +52,120 @@ def createEmptyLayer(): class PyQgsTextRenderer(unittest.TestCase): - def setUp(self): - self.report = "

Python QgsTextRenderer Tests

\n" + @classmethod + def setUpClass(cls): + cls.report = "

Python QgsTextRenderer Tests

\n" QgsFontUtils.loadStandardTestFonts(['Bold', 'Oblique']) - def tearDown(self): + @classmethod + def tearDownClass(cls): report_file_path = "%s/qgistest.html" % QDir.tempPath() with open(report_file_path, 'a') as report_file: - report_file.write(self.report) + report_file.write(cls.report) + + def testValid(self): + t = QgsTextFormat() + self.assertFalse(t.isValid()) + + tt = QgsTextFormat(t) + self.assertFalse(tt.isValid()) + + t.setValid() + self.assertTrue(t.isValid()) + tt = QgsTextFormat(t) + self.assertTrue(tt.isValid()) + + doc = QDomDocument() + elem = t.writeXml(doc, QgsReadWriteContext()) + parent = doc.createElement("settings") + parent.appendChild(elem) + t3 = QgsTextFormat() + t3.readXml(parent, QgsReadWriteContext()) + self.assertTrue(t3.isValid()) + + t = QgsTextFormat() + t.buffer().setEnabled(True) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.background().setEnabled(True) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.shadow().setEnabled(True) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.mask().setEnabled(True) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.font() + self.assertFalse(t.isValid()) + t.setFont(QFont()) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setNamedStyle('Bold') + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setSize(20) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setSizeUnit(QgsUnitTypes.RenderPixels) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setSizeMapUnitScale(QgsMapUnitScale(5, 10)) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setColor(QColor(255, 0, 0)) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setOpacity(0.2) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setBlendMode(QPainter.CompositionMode_Darken) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setLineHeight(20) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setOrientation(QgsTextFormat.VerticalOrientation) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setAllowHtmlFormatting(True) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.setPreviewBackgroundColor(QColor(255, 0, 0)) + self.assertTrue(t.isValid()) + + t = QgsTextFormat() + t.dataDefinedProperties().setProperty(QgsPalLayerSettings.Bold, QgsProperty.fromValue(True)) + self.assertTrue(t.isValid()) + + def testAlignmentConversion(self): + self.assertEqual(QgsTextRenderer.convertQtHAlignment(Qt.AlignLeft), QgsTextRenderer.AlignLeft) + self.assertEqual(QgsTextRenderer.convertQtHAlignment(Qt.AlignRight), QgsTextRenderer.AlignRight) + self.assertEqual(QgsTextRenderer.convertQtHAlignment(Qt.AlignHCenter), QgsTextRenderer.AlignCenter) + self.assertEqual(QgsTextRenderer.convertQtHAlignment(Qt.AlignJustify), QgsTextRenderer.AlignJustify) + # not supported, should fallback to left + self.assertEqual(QgsTextRenderer.convertQtHAlignment(Qt.AlignAbsolute), QgsTextRenderer.AlignLeft) + + self.assertEqual(QgsTextRenderer.convertQtVAlignment(Qt.AlignTop), QgsTextRenderer.AlignTop) + self.assertEqual(QgsTextRenderer.convertQtVAlignment(Qt.AlignBottom), QgsTextRenderer.AlignBottom) + self.assertEqual(QgsTextRenderer.convertQtVAlignment(Qt.AlignVCenter), QgsTextRenderer.AlignVCenter) + # note supported, should fallback to bottom + self.assertEqual(QgsTextRenderer.convertQtVAlignment(Qt.AlignBaseline), QgsTextRenderer.AlignBottom) def createBufferSettings(self): s = QgsTextBufferSettings() @@ -74,6 +180,46 @@ def createBufferSettings(self): s.setBlendMode(QPainter.CompositionMode_DestinationAtop) return s + def testBufferEquality(self): + s = self.createBufferSettings() + s2 = self.createBufferSettings() + self.assertEqual(s, s2) + + s.setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setSize(15) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setSizeUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setSizeMapUnitScale(QgsMapUnitScale(11, 12)) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setColor(QColor(255, 255, 0)) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setFillBufferInterior(False) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setOpacity(0.6) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setJoinStyle(Qt.MiterJoin) + self.assertNotEqual(s, s2) + s = self.createBufferSettings() + + s.setBlendMode(QPainter.CompositionMode_Darken) + self.assertNotEqual(s, s2) + def checkBufferSettings(self, s): """ test QgsTextBufferSettings """ self.assertTrue(s.enabled()) @@ -131,6 +277,39 @@ def createMaskSettings(self): QgsSymbolLayerReference("layerid2", QgsSymbolLayerId("symbol2", 2))]) return s + def testMaskEquality(self): + s = self.createMaskSettings() + s2 = self.createMaskSettings() + self.assertEqual(s, s2) + + s.setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createMaskSettings() + + s.setSize(15) + self.assertNotEqual(s, s2) + s = self.createMaskSettings() + + s.setSizeUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createMaskSettings() + + s.setSizeMapUnitScale(QgsMapUnitScale(11, 12)) + self.assertNotEqual(s, s2) + s = self.createMaskSettings() + + s.setOpacity(0.6) + self.assertNotEqual(s, s2) + s = self.createMaskSettings() + + s.setJoinStyle(Qt.MiterJoin) + self.assertNotEqual(s, s2) + s = self.createMaskSettings() + + s.setMaskedSymbolLayers([QgsSymbolLayerReference("layerid11", QgsSymbolLayerId("symbol", 1)), + QgsSymbolLayerReference("layerid21", QgsSymbolLayerId("symbol2", 2))]) + self.assertNotEqual(s, s2) + def checkMaskSettings(self, s): """ test QgsTextMaskSettings """ self.assertTrue(s.enabled()) @@ -201,6 +380,102 @@ def createBackgroundSettings(self): return s + def testBackgroundEquality(self): + s = self.createBackgroundSettings() + s2 = self.createBackgroundSettings() + self.assertEqual(s, s2) + + s.setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setType(QgsTextBackgroundSettings.ShapeRectangle) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setSvgFile('svg2.svg') + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setSizeType(QgsTextBackgroundSettings.SizeFixed) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setSize(QSizeF(1, 22)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setSizeUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setSizeMapUnitScale(QgsMapUnitScale(11, 22)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setRotationType(QgsTextBackgroundSettings.RotationSync) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setRotation(145) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setOffset(QPointF(31, 41)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setOffsetUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setOffsetMapUnitScale(QgsMapUnitScale(15, 16)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setRadii(QSizeF(111, 112)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setRadiiUnit(QgsUnitTypes.RenderPoints) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setRadiiMapUnitScale(QgsMapUnitScale(151, 161)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setFillColor(QColor(255, 255, 0)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setStrokeColor(QColor(0, 255, 255)) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setOpacity(0.6) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setJoinStyle(Qt.MiterJoin) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setBlendMode(QPainter.CompositionMode_Darken) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setStrokeWidth(17) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setStrokeWidthUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createBackgroundSettings() + + s.setStrokeWidthMapUnitScale(QgsMapUnitScale(QgsMapUnitScale(251, 261))) + self.assertNotEqual(s, s2) + def checkBackgroundSettings(self, s): """ test QgsTextBackgroundSettings """ self.assertTrue(s.enabled()) @@ -275,6 +550,70 @@ def createShadowSettings(self): s.setBlendMode(QPainter.CompositionMode_DestinationAtop) return s + def testShadowEquality(self): + s = self.createShadowSettings() + s2 = self.createShadowSettings() + self.assertEqual(s, s2) + + s.setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setShadowPlacement(QgsTextShadowSettings.ShadowText) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setOffsetAngle(145) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setOffsetDistance(175) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setOffsetUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setOffsetMapUnitScale(QgsMapUnitScale(15, 16)) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setOffsetGlobal(False) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setBlurRadius(21) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setBlurRadiusUnit(QgsUnitTypes.RenderPoints) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setBlurRadiusMapUnitScale(QgsMapUnitScale(115, 116)) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setBlurAlphaOnly(False) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setColor(QColor(255, 255, 0)) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setOpacity(0.6) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setScale(23) + self.assertNotEqual(s, s2) + s = self.createShadowSettings() + + s.setBlendMode(QPainter.CompositionMode_Darken) + self.assertNotEqual(s, s2) + def checkShadowSettings(self, s): """ test QgsTextShadowSettings """ self.assertTrue(s.enabled()) @@ -356,6 +695,96 @@ def createFormatSettings(self): s.dataDefinedProperties().setProperty(QgsPalLayerSettings.Bold, QgsProperty.fromExpression('1>2')) return s + def testFormatEquality(self): + s = self.createFormatSettings() + s2 = self.createFormatSettings() + self.assertEqual(s, s2) + + s.buffer().setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.buffer().setSize(12) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.mask().setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.mask().setSize(12) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.background().setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.background().setSvgFile('test2.svg') + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.shadow().setEnabled(False) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.shadow().setOffsetAngle(123) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + font = getTestFont() + font.setKerning(True) + s.setFont(font) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setNamedStyle('Bold') + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setSize(15) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setSizeUnit(QgsUnitTypes.RenderPixels) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setSizeMapUnitScale(QgsMapUnitScale(11, 12)) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setColor(QColor(255, 255, 0)) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setOpacity(0.6) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setBlendMode(QPainter.CompositionMode_Darken) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setLineHeight(15) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setPreviewBackgroundColor(QColor(100, 250, 200)) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setOrientation(QgsTextFormat.HorizontalOrientation) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.setAllowHtmlFormatting(False) + self.assertNotEqual(s, s2) + s = self.createFormatSettings() + + s.dataDefinedProperties().setProperty(QgsPalLayerSettings.Bold, QgsProperty.fromExpression('1>3')) + self.assertNotEqual(s, s2) + def checkTextFormat(self, s): """ test QgsTextFormat """ self.assertTrue(s.buffer().enabled()) @@ -896,7 +1325,7 @@ def testFontMetrics(self): self.assertAlmostEqual(metrics2.width(string), 104.15, 1) def imageCheck(self, name, reference_image, image): - self.report += "

Render {}

\n".format(name) + PyQgsTextRenderer.report += "

Render {}

\n".format(name) temp_dir = QDir.tempPath() + '/' file_name = temp_dir + name + ".png" image.save(file_name, "PNG") @@ -906,13 +1335,14 @@ def imageCheck(self, name, reference_image, image): checker.setRenderedImage(file_name) checker.setColorTolerance(2) result = checker.compareImages(name, 20) - self.report += checker.report() + PyQgsTextRenderer.report += checker.report() print(checker.report()) return result def checkRender(self, format, name, part=None, angle=0, alignment=QgsTextRenderer.AlignLeft, text=['test'], - rect=QRectF(100, 100, 50, 250)): + rect=QRectF(100, 100, 50, 250), + vAlignment=QgsTextRenderer.AlignTop): image = QImage(400, 400, QImage.Format_RGB32) @@ -923,6 +1353,7 @@ def checkRender(self, format, name, part=None, angle=0, alignment=QgsTextRendere context = QgsRenderContext.fromMapSettings(ms) context.setPainter(painter) context.setScaleFactor(96 / 25.4) # 96 DPI + context.setFlag(QgsRenderContext.ApplyScalingWorkaroundForTextRendering, True) painter.begin(image) painter.setRenderHint(QPainter.Antialiasing) @@ -947,7 +1378,7 @@ def checkRender(self, format, name, part=None, angle=0, alignment=QgsTextRendere alignment, text, context, - format) + format, vAlignment=vAlignment) painter.setFont(format.scaledFont(context)) painter.setPen(QPen(QColor(255, 0, 255, 200))) @@ -2123,6 +2554,61 @@ def testDrawTextRectRightAlign(self): assert self.checkRender(format, 'text_rect_right_aligned', text=['test'], alignment=QgsTextRenderer.AlignRight, rect=QRectF(100, 100, 200, 100)) + def testDrawTextRectMultilineJustifyAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + format.buffer().setEnabled(True) + format.buffer().setSize(4) + format.buffer().setSizeUnit(QgsUnitTypes.RenderMillimeters) + assert self.checkRender(format, 'text_rect_multiline_justify_aligned', text=['a t est', 'off', 'justification', 'align'], + alignment=QgsTextRenderer.AlignJustify, rect=QRectF(100, 100, 200, 100)) + + def testDrawTextRectJustifyAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + assert self.checkRender(format, 'text_rect_justify_aligned', text=['test'], + alignment=QgsTextRenderer.AlignJustify, rect=QRectF(100, 100, 200, 100)) + + def testDrawTextRectMultilineBottomAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + + assert self.checkRender(format, 'text_rect_multiline_bottom_aligned', text=['test', 'bottom', 'aligned'], + alignment=QgsTextRenderer.AlignLeft, rect=QRectF(100, 100, 200, 100), vAlignment=QgsTextRenderer.AlignBottom) + + def testDrawTextRectBottomAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + + assert self.checkRender(format, 'text_rect_bottom_aligned', text=['bottom aligned'], + alignment=QgsTextRenderer.AlignLeft, rect=QRectF(100, 100, 200, 100), vAlignment=QgsTextRenderer.AlignBottom) + + def testDrawTextRectMultilineVCenterAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + + assert self.checkRender(format, 'text_rect_multiline_vcenter_aligned', text=['test', 'center', 'aligned'], + alignment=QgsTextRenderer.AlignLeft, rect=QRectF(100, 100, 200, 100), vAlignment=QgsTextRenderer.AlignVCenter) + + def testDrawTextRectVCenterAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + + assert self.checkRender(format, 'text_rect_vcenter_aligned', text=['center aligned'], + alignment=QgsTextRenderer.AlignLeft, rect=QRectF(100, 100, 200, 100), vAlignment=QgsTextRenderer.AlignVCenter) + def testDrawTextRectMultilineCenterAlign(self): format = QgsTextFormat() format.setFont(getTestFont('bold')) @@ -2164,6 +2650,22 @@ def testDrawTextPointRightAlign(self): assert self.checkRenderPoint(format, 'text_point_right_aligned', text=['test'], alignment=QgsTextRenderer.AlignRight, point=QPointF(300, 200)) + def testDrawTextPointJustifyAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + assert self.checkRenderPoint(format, 'text_point_justify_aligned', text=['test'], + alignment=QgsTextRenderer.AlignJustify, point=QPointF(100, 200)) + + def testDrawTextPointMultilineJustifyAlign(self): + format = QgsTextFormat() + format.setFont(getTestFont('bold')) + format.setSize(30) + format.setSizeUnit(QgsUnitTypes.RenderPoints) + assert self.checkRenderPoint(format, 'text_point_justify_multiline_aligned', text=['a t est', 'off', 'justification', 'align'], + alignment=QgsTextRenderer.AlignJustify, point=QPointF(100, 200)) + def testDrawTextPointCenterAlign(self): format = QgsTextFormat() format.setFont(getTestFont('bold')) diff --git a/tests/src/python/test_qgsvectorfilewriter.py b/tests/src/python/test_qgsvectorfilewriter.py index 9958e64a5e52..7a3bcb8bd528 100644 --- a/tests/src/python/test_qgsvectorfilewriter.py +++ b/tests/src/python/test_qgsvectorfilewriter.py @@ -29,7 +29,10 @@ QgsCoordinateTransform, QgsMultiPolygon, QgsTriangle, - QgsPoint + QgsPoint, + QgsFields, + QgsCoordinateTransformContext, + QgsFeatureSink ) from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant, QDir, QByteArray import os @@ -1267,6 +1270,23 @@ def testWriteConversionErrors(self): f = next(created_layer.getFeatures(QgsFeatureRequest())) self.assertEqual(f['int'], 12345) + def test_regression_37386(self): + """Test issue GH #37386""" + + dest_file_name = os.path.join(str(QDir.tempPath()), 'writer_regression_37386.gpkg') + fields = QgsFields() + fields.append(QgsField("note", QVariant.Double)) + lyrname = "test1" + opts = QgsVectorFileWriter.SaveVectorOptions() + opts.driverName = "GPKG" + opts.layerName = lyrname + opts.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile + writer = QgsVectorFileWriter.create(dest_file_name, fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem.fromEpsgId(4326), QgsCoordinateTransformContext(), opts, QgsFeatureSink.SinkFlags(), None, lyrname) + self.assertEqual(writer.hasError(), QgsVectorFileWriter.NoError) + del writer + vl = QgsVectorLayer(dest_file_name) + self.assertTrue(vl.isValid()) + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill.png b/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill.png index 2445824e949e..6190037e4efc 100644 Binary files a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill.png and b/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill.png differ diff --git a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill_mask.png b/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill_mask.png deleted file mode 100644 index d13ed4a84812..000000000000 Binary files a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_line_fill/expected_adjacent_line_fill_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill.png b/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill.png index 49f233685d7b..55311f07b8bc 100644 Binary files a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill.png and b/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill.png differ diff --git a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill_mask.png b/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill_mask.png deleted file mode 100644 index 5a3a77840b9a..000000000000 Binary files a/tests/testdata/control_images/adjacent_tiles/expected_adjacent_marker_fill/expected_adjacent_marker_fill_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/default/expected_layoutmap_rasterized.png b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/default/expected_layoutmap_rasterized.png deleted file mode 100644 index 4730b65c0116..000000000000 Binary files a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/default/expected_layoutmap_rasterized.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/default/expected_layoutmap_rasterized_mask.png b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/default/expected_layoutmap_rasterized_mask.png deleted file mode 100644 index 6639e9ea144f..000000000000 Binary files a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/default/expected_layoutmap_rasterized_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/expected_layoutmap_rasterized.png b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/expected_layoutmap_rasterized.png new file mode 100644 index 000000000000..9e2b8d01395f Binary files /dev/null and b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/expected_layoutmap_rasterized.png differ diff --git a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/expected_layoutmap_rasterized_mask.png b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/expected_layoutmap_rasterized_mask.png new file mode 100644 index 000000000000..212da142617a Binary files /dev/null and b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/expected_layoutmap_rasterized_mask.png differ diff --git a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/fedora/expected_layoutmap_rasterized.png b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/fedora/expected_layoutmap_rasterized.png deleted file mode 100644 index eeb1f90be965..000000000000 Binary files a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/fedora/expected_layoutmap_rasterized.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/fedora/expected_layoutmap_rasterized_mask.png b/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/fedora/expected_layoutmap_rasterized_mask.png deleted file mode 100644 index 1e2ca443d14d..000000000000 Binary files a/tests/testdata/control_images/composer_map/expected_layoutmap_rasterized/fedora/expected_layoutmap_rasterized_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_datadefined_annotationdistance/expected_composermap_datadefined_annotationdistance.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_datadefined_annotationdistance/expected_composermap_datadefined_annotationdistance.png index 2f4d82edf741..be89ddce7ca5 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_datadefined_annotationdistance/expected_composermap_datadefined_annotationdistance.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_datadefined_annotationdistance/expected_composermap_datadefined_annotationdistance.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10/expected_composermap_dynamic_5_10_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10/expected_composermap_dynamic_5_10_mask.png new file mode 100644 index 000000000000..61ba4ae28aea Binary files /dev/null and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10/expected_composermap_dynamic_5_10_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_2/expected_composermap_dynamic_5_10_2_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_2/expected_composermap_dynamic_5_10_2_mask.png new file mode 100644 index 000000000000..39aa8fcedceb Binary files /dev/null and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_2/expected_composermap_dynamic_5_10_2_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_3/expected_composermap_dynamic_5_10_3_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_3/expected_composermap_dynamic_5_10_3_mask.png new file mode 100644 index 000000000000..89a08fd99493 Binary files /dev/null and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_3/expected_composermap_dynamic_5_10_3_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_4/expected_composermap_dynamic_5_10_4_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_4/expected_composermap_dynamic_5_10_4_mask.png new file mode 100644 index 000000000000..87800e6e8963 Binary files /dev/null and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_dynamic_5_10_4/expected_composermap_dynamic_5_10_4_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated.png index fd3b4334bc0a..f45f522fbe5f 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated_mask.png deleted file mode 100644 index 42e914eac991..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated/expected_composermap_exteriorticks_annotated_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2.png index 52ace9332ee0..fdd4f0e31627 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2_mask.png deleted file mode 100644 index 02c38b46b414..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_exteriorticks_annotated2/expected_composermap_exteriorticks_annotated2_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations.png index 2f422e71e1be..d2ad7913406b 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations_mask.png index 9152f90ede35..63e45296d7d8 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations_mask.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_filteredannotations/expected_composermap_filteredannotations_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/default/expected_composermap_grid.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/default/expected_composermap_grid.png deleted file mode 100644 index 94b74e31f70d..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/default/expected_composermap_grid.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/default/expected_composermap_grid_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/default/expected_composermap_grid_mask.png deleted file mode 100644 index 618fab481068..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/default/expected_composermap_grid_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/expected_composermap_grid.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/expected_composermap_grid.png new file mode 100644 index 000000000000..3e10cddfaffa Binary files /dev/null and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/expected_composermap_grid.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/expected_composermap_grid_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/expected_composermap_grid_mask.png new file mode 100644 index 000000000000..666bc62102ef Binary files /dev/null and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/expected_composermap_grid_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/fedora/expected_composermap_grid.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/fedora/expected_composermap_grid.png deleted file mode 100644 index 1669c18c2542..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/fedora/expected_composermap_grid.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/fedora/expected_composermap_grid_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/fedora/expected_composermap_grid_mask.png deleted file mode 100644 index ac406bfd9e32..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_grid/fedora/expected_composermap_grid_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated.png index 7930794c4390..e19572131d6e 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated_mask.png deleted file mode 100644 index 2f9e41890820..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated/expected_composermap_interiorexteriorticks_annotated_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2.png index 6346d5881029..ee6be31af5d0 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2_mask.png deleted file mode 100644 index cb1cab6b5d08..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorexteriorticks_annotated2/expected_composermap_interiorexteriorticks_annotated2_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated.png index 31ec2cd961fd..838fe05de3f7 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated_mask.png deleted file mode 100644 index 421376736b7c..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated/expected_composermap_interiorticks_annotated_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2.png index 307d85643180..78bf0fe241b6 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2_mask.png deleted file mode 100644 index a642b4130c38..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_interiorticks_annotated2/expected_composermap_interiorticks_annotated2_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated.png index e771cf5e7850..3d64013aecec 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated_mask.png deleted file mode 100644 index 949cd1c61cea..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated/expected_composermap_lineborder_annotated_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2.png index 8e878eab6218..4dcdcaf84274 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2_mask.png deleted file mode 100644 index b862ef442e51..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_lineborder_annotated2/expected_composermap_lineborder_annotated2_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations.png index 7c9d8fd87972..f9ab27d12380 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations_mask.png index 7cd58b99309d..63e45296d7d8 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations_mask.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_rotatedannotations/expected_composermap_rotatedannotations_mask.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside.png index a161dcc1a997..9908da5e583a 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside_mask.png deleted file mode 100644 index 1e5c913456f2..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_inside/expected_composermap_verticaldescending_inside_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside.png index 705f45a587a1..eebcad50a801 100644 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside.png and b/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside.png differ diff --git a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside_mask.png b/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside_mask.png deleted file mode 100644 index e8ea25da8545..000000000000 Binary files a/tests/testdata/control_images/composer_mapgrid/expected_composermap_verticaldescending_outside/expected_composermap_verticaldescending_outside_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_align/expected_composerattributetable_align.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_align/expected_composerattributetable_align.png index 339bd0151238..f788556e9a48 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_align/expected_composerattributetable_align.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_align/expected_composerattributetable_align.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/default/expected_composerattributetable_autowrap.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/default/expected_composerattributetable_autowrap.png deleted file mode 100644 index 299183fec3d0..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/default/expected_composerattributetable_autowrap.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/expected_composerattributetable_autowrap.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/expected_composerattributetable_autowrap.png new file mode 100644 index 000000000000..08957f47bf71 Binary files /dev/null and b/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/expected_composerattributetable_autowrap.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/fedora/expected_composerattributetable_autowrap.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/fedora/expected_composerattributetable_autowrap.png deleted file mode 100644 index 04921e767dd5..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_autowrap/fedora/expected_composerattributetable_autowrap.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle.png index a7c3863d0779..c0d88159e9c8 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle_mask.png deleted file mode 100644 index 5569e9987a11..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_cellstyle/expected_composerattributetable_cellstyle_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth.png index b1bc38a299f5..dd607b9d6b68 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth_mask.png deleted file mode 100644 index eb69bf95346e..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_columnwidth/expected_composerattributetable_columnwidth_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_conditionalstyles/expected_composerattributetable_conditionalstyles.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_conditionalstyles/expected_composerattributetable_conditionalstyles.png index 61a46b8e35e4..c188fbda136c 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_conditionalstyles/expected_composerattributetable_conditionalstyles.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_conditionalstyles/expected_composerattributetable_conditionalstyles.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_datadefinedtextformat/expected_composerattributetable_datadefinedtextformat.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_datadefinedtextformat/expected_composerattributetable_datadefinedtextformat.png new file mode 100644 index 000000000000..e8ca535e0f1c Binary files /dev/null and b/tests/testdata/control_images/composer_table/expected_composerattributetable_datadefinedtextformat/expected_composerattributetable_datadefinedtextformat.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty.png index dc1ae607921b..faa59c5a8603 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty_mask.png deleted file mode 100644 index b9ed72272947..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_drawempty/expected_composerattributetable_drawempty_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly.png index cdeddc60fe11..e39d4041dee8 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly_mask.png deleted file mode 100644 index 3500ed3ff181..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_headersonly/expected_composerattributetable_headersonly_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable.png index a7121ff50dec..7a27f99837c1 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable_mask.png deleted file mode 100644 index 4a5f82fbc5c5..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_hidetable/expected_composerattributetable_hidetable_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid.png index 70db426544ce..10ae470e0bc7 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid_mask.png deleted file mode 100644 index ecb302706ba6..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_horizontalgrid/expected_composerattributetable_horizontalgrid_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline.png index 455e5d26b169..30ec3042fbeb 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline_mask.png deleted file mode 100644 index e21705476445..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_multiline/expected_composerattributetable_multiline_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render.png index b2c32191f312..fde11b8cc71a 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render_mask.png deleted file mode 100644 index ad5fce3f79d1..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_render/expected_composerattributetable_render_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage.png index 239b8d194c86..2e3a3c7aac53 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage_mask.png deleted file mode 100644 index cb0ef5141c78..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_showmessage/expected_composerattributetable_showmessage_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid.png index eb6f35b430a7..3b2ee688b3fb 100644 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid.png and b/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid.png differ diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid_mask.png deleted file mode 100644 index d8c26a598dd1..000000000000 Binary files a/tests/testdata/control_images/composer_table/expected_composerattributetable_verticalgrid/expected_composerattributetable_verticalgrid_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0.png index e2aaec4996c9..0aceb2d8ce19 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0.png differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0_mask.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0_mask.png index 2d47aaf078c4..cc0e674e2db0 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0_mask.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0_mask.png differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateLegend_0/expected_importComposerTemplateLegend_0_mask.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateLegend_0/expected_importComposerTemplateLegend_0_mask.png index f87a0d390a7c..a49a132e7fa3 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateLegend_0/expected_importComposerTemplateLegend_0_mask.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateLegend_0/expected_importComposerTemplateLegend_0_mask.png differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateMap_0/expected_importComposerTemplateMap_0_mask.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateMap_0/expected_importComposerTemplateMap_0_mask.png index 587b58faf258..7c15870bf64e 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateMap_0/expected_importComposerTemplateMap_0_mask.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplateMap_0/expected_importComposerTemplateMap_0_mask.png differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_0/expected_importComposerTemplate_0_mask.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_0/expected_importComposerTemplate_0_mask.png index 5d06ed79246b..9a347cb08024 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_0/expected_importComposerTemplate_0_mask.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_0/expected_importComposerTemplate_0_mask.png differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1.png index 8273bf3e36ea..7bd890b12c71 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1.png differ diff --git a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1_mask.png b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1_mask.png index dd20342e7141..a89d1734d805 100644 Binary files a/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1_mask.png and b/tests/testdata/control_images/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1_mask.png differ diff --git a/tests/testdata/control_images/diagrams/expected_stacked_axis_down/expected_stacked_axis_down.png b/tests/testdata/control_images/diagrams/expected_stacked_axis_down/expected_stacked_axis_down.png new file mode 100644 index 000000000000..774472ed7f12 Binary files /dev/null and b/tests/testdata/control_images/diagrams/expected_stacked_axis_down/expected_stacked_axis_down.png differ diff --git a/tests/testdata/control_images/diagrams/expected_stacked_axis_left/expected_stacked_axis_left.png b/tests/testdata/control_images/diagrams/expected_stacked_axis_left/expected_stacked_axis_left.png new file mode 100644 index 000000000000..e3a8d82f0256 Binary files /dev/null and b/tests/testdata/control_images/diagrams/expected_stacked_axis_left/expected_stacked_axis_left.png differ diff --git a/tests/testdata/control_images/diagrams/expected_stacked_axis_right/expected_stacked_axis_right.png b/tests/testdata/control_images/diagrams/expected_stacked_axis_right/expected_stacked_axis_right.png new file mode 100644 index 000000000000..5e55e2a7b971 Binary files /dev/null and b/tests/testdata/control_images/diagrams/expected_stacked_axis_right/expected_stacked_axis_right.png differ diff --git a/tests/testdata/control_images/diagrams/expected_stacked_axis_up/expected_stacked_axis_up.png b/tests/testdata/control_images/diagrams/expected_stacked_axis_up/expected_stacked_axis_up.png new file mode 100644 index 000000000000..553369aa4694 Binary files /dev/null and b/tests/testdata/control_images/diagrams/expected_stacked_axis_up/expected_stacked_axis_up.png differ diff --git a/tests/testdata/control_images/expected_pal_canvas/sp_buffer/sp_buffer_mask.png b/tests/testdata/control_images/expected_pal_canvas/sp_buffer/sp_buffer_mask.png index 2adb5eb84c4a..b6ab34600c85 100644 Binary files a/tests/testdata/control_images/expected_pal_canvas/sp_buffer/sp_buffer_mask.png and b/tests/testdata/control_images/expected_pal_canvas/sp_buffer/sp_buffer_mask.png differ diff --git a/tests/testdata/control_images/expected_pal_composer/sp_img_buffer/sp_img_buffer_mask.png b/tests/testdata/control_images/expected_pal_composer/sp_img_buffer/sp_img_buffer_mask.png index ade7e27e3bb1..d524d6390c73 100644 Binary files a/tests/testdata/control_images/expected_pal_composer/sp_img_buffer/sp_img_buffer_mask.png and b/tests/testdata/control_images/expected_pal_composer/sp_img_buffer/sp_img_buffer_mask.png differ diff --git a/tests/testdata/control_images/expected_pal_composer/sp_pdf_buffer/sp_pdf_buffer_mask.png b/tests/testdata/control_images/expected_pal_composer/sp_pdf_buffer/sp_pdf_buffer_mask.png index 29171f076416..f5cf45ef3b90 100644 Binary files a/tests/testdata/control_images/expected_pal_composer/sp_pdf_buffer/sp_pdf_buffer_mask.png and b/tests/testdata/control_images/expected_pal_composer/sp_pdf_buffer/sp_pdf_buffer_mask.png differ diff --git a/tests/testdata/control_images/expected_pal_composer/sp_svg_buffer/sp_svg_buffer_mask.png b/tests/testdata/control_images/expected_pal_composer/sp_svg_buffer/sp_svg_buffer_mask.png index 0ec471969ec3..bee18e73b2b6 100644 Binary files a/tests/testdata/control_images/expected_pal_composer/sp_svg_buffer/sp_svg_buffer_mask.png and b/tests/testdata/control_images/expected_pal_composer/sp_svg_buffer/sp_svg_buffer_mask.png differ diff --git a/tests/testdata/control_images/labelingengine/expected_labeling_vertical_letter_line_spacing/expected_labeling_vertical_letter_line_spacing.png b/tests/testdata/control_images/labelingengine/expected_labeling_vertical_letter_line_spacing/expected_labeling_vertical_letter_line_spacing.png index 2990cec9987f..139d60012f7e 100644 Binary files a/tests/testdata/control_images/labelingengine/expected_labeling_vertical_letter_line_spacing/expected_labeling_vertical_letter_line_spacing.png and b/tests/testdata/control_images/labelingengine/expected_labeling_vertical_letter_line_spacing/expected_labeling_vertical_letter_line_spacing.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth.png index c1f85d0f9c6c..6cad30a5d08c 100644 Binary files a/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth.png and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth_mask.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth_mask.png index e9cf1764109b..5ae874754904 100644 Binary files a/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth_mask.png and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_columnwidth/expected_manualtable_columnwidth_mask.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers.png index 851840c41be5..7b2b2c0f3960 100644 Binary files a/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers.png and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers_mask.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers_mask.png index fc9d27f7c966..8e14937c7db4 100644 Binary files a/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers_mask.png and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_headers/expected_manualtable_headers_mask.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight.png index f9b8c33d9870..a298857ac036 100644 Binary files a/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight.png and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight_mask.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight_mask.png index 8f9fe0b84554..f5f1b91e15df 100644 Binary files a/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight_mask.png and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_rowheight/expected_manualtable_rowheight_mask.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_textalign/expected_manualtable_textalign.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textalign/expected_manualtable_textalign.png new file mode 100644 index 000000000000..02634f48b282 Binary files /dev/null and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textalign/expected_manualtable_textalign.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_textalign/expected_manualtable_textalign_mask.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textalign/expected_manualtable_textalign_mask.png new file mode 100644 index 000000000000..2194a987bf2e Binary files /dev/null and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textalign/expected_manualtable_textalign_mask.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_textformat/expected_manualtable_textformat.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textformat/expected_manualtable_textformat.png new file mode 100644 index 000000000000..dd606271e33c Binary files /dev/null and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textformat/expected_manualtable_textformat.png differ diff --git a/tests/testdata/control_images/layout_manual_table/expected_manualtable_textformat/expected_manualtable_textformat_mask.png b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textformat/expected_manualtable_textformat_mask.png new file mode 100644 index 000000000000..306e6f85a119 Binary files /dev/null and b/tests/testdata/control_images/layout_manual_table/expected_manualtable_textformat/expected_manualtable_textformat_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/label_mask/label_mask_mask.png b/tests/testdata/control_images/selective_masking/label_mask/label_mask_mask.png index 2233a6bded2e..cb1ad77d0dfa 100644 Binary files a/tests/testdata/control_images/selective_masking/label_mask/label_mask_mask.png and b/tests/testdata/control_images/selective_masking/label_mask/label_mask_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/label_mask_subsymbol/label_mask_subsymbol_mask.png b/tests/testdata/control_images/selective_masking/label_mask_subsymbol/label_mask_subsymbol_mask.png index 5bb7c9073f17..18b6e5190292 100644 Binary files a/tests/testdata/control_images/selective_masking/label_mask_subsymbol/label_mask_subsymbol_mask.png and b/tests/testdata/control_images/selective_masking/label_mask_subsymbol/label_mask_subsymbol_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/label_mask_symbol_levels/label_mask_symbol_levels_mask.png b/tests/testdata/control_images/selective_masking/label_mask_symbol_levels/label_mask_symbol_levels_mask.png index 0d579cc40812..7eacdd9a5361 100644 Binary files a/tests/testdata/control_images/selective_masking/label_mask_symbol_levels/label_mask_symbol_levels_mask.png and b/tests/testdata/control_images/selective_masking/label_mask_symbol_levels/label_mask_symbol_levels_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/label_mask_with_effect/label_mask_with_effect_mask.png b/tests/testdata/control_images/selective_masking/label_mask_with_effect/label_mask_with_effect_mask.png index bf4ba39581c1..87a0d48bce8c 100644 Binary files a/tests/testdata/control_images/selective_masking/label_mask_with_effect/label_mask_with_effect_mask.png and b/tests/testdata/control_images/selective_masking/label_mask_with_effect/label_mask_with_effect_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/layout_export/layout_export_mask.png b/tests/testdata/control_images/selective_masking/layout_export/layout_export_mask.png index e3b6229d665d..08c6316f687d 100644 Binary files a/tests/testdata/control_images/selective_masking/layout_export/layout_export_mask.png and b/tests/testdata/control_images/selective_masking/layout_export/layout_export_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/mask_with_effect/mask_with_effect_mask.png b/tests/testdata/control_images/selective_masking/mask_with_effect/mask_with_effect_mask.png index 4aba3ee374ce..39951a4be1d8 100644 Binary files a/tests/testdata/control_images/selective_masking/mask_with_effect/mask_with_effect_mask.png and b/tests/testdata/control_images/selective_masking/mask_with_effect/mask_with_effect_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/multiple_label_masks_different_sets/multiple_label_masks_different_sets_mask.png b/tests/testdata/control_images/selective_masking/multiple_label_masks_different_sets/multiple_label_masks_different_sets_mask.png index 36865ae397f8..7377cd93b7f1 100644 Binary files a/tests/testdata/control_images/selective_masking/multiple_label_masks_different_sets/multiple_label_masks_different_sets_mask.png and b/tests/testdata/control_images/selective_masking/multiple_label_masks_different_sets/multiple_label_masks_different_sets_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/multiple_label_masks_same_set/multiple_label_masks_same_set_mask.png b/tests/testdata/control_images/selective_masking/multiple_label_masks_same_set/multiple_label_masks_same_set_mask.png index ffade9842714..cc807c218123 100644 Binary files a/tests/testdata/control_images/selective_masking/multiple_label_masks_same_set/multiple_label_masks_same_set_mask.png and b/tests/testdata/control_images/selective_masking/multiple_label_masks_same_set/multiple_label_masks_same_set_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/multiple_masks_different_sl/multiple_masks_different_sl_mask.png b/tests/testdata/control_images/selective_masking/multiple_masks_different_sl/multiple_masks_different_sl_mask.png index 49a8c2615f9d..3e18510126d7 100644 Binary files a/tests/testdata/control_images/selective_masking/multiple_masks_different_sl/multiple_masks_different_sl_mask.png and b/tests/testdata/control_images/selective_masking/multiple_masks_different_sl/multiple_masks_different_sl_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/multiple_masks_different_sl2/multiple_masks_different_sl2_mask.png b/tests/testdata/control_images/selective_masking/multiple_masks_different_sl2/multiple_masks_different_sl2_mask.png index e9863145e838..f44e49a703e9 100644 Binary files a/tests/testdata/control_images/selective_masking/multiple_masks_different_sl2/multiple_masks_different_sl2_mask.png and b/tests/testdata/control_images/selective_masking/multiple_masks_different_sl2/multiple_masks_different_sl2_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/multiple_masks_same_sl/multiple_masks_same_sl_mask.png b/tests/testdata/control_images/selective_masking/multiple_masks_same_sl/multiple_masks_same_sl_mask.png index fe07537acb1c..af3c9326e8f1 100644 Binary files a/tests/testdata/control_images/selective_masking/multiple_masks_same_sl/multiple_masks_same_sl_mask.png and b/tests/testdata/control_images/selective_masking/multiple_masks_same_sl/multiple_masks_same_sl_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/rule_label_mask/rule_label_mask_mask.png b/tests/testdata/control_images/selective_masking/rule_label_mask/rule_label_mask_mask.png index 89e330501772..a56aa59f2808 100644 Binary files a/tests/testdata/control_images/selective_masking/rule_label_mask/rule_label_mask_mask.png and b/tests/testdata/control_images/selective_masking/rule_label_mask/rule_label_mask_mask.png differ diff --git a/tests/testdata/control_images/selective_masking/sl_mask/sl_mask_mask.png b/tests/testdata/control_images/selective_masking/sl_mask/sl_mask_mask.png index 966bb5fe9e64..6c8358698b12 100644 Binary files a/tests/testdata/control_images/selective_masking/sl_mask/sl_mask_mask.png and b/tests/testdata/control_images/selective_masking/sl_mask/sl_mask_mask.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol.png b/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol.png index 8dfbc9825b69..fa03df5f5d5b 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol.png and b/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol_mask.png b/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol_mask.png deleted file mode 100644 index a1ce30f22c15..000000000000 Binary files a/tests/testdata/control_images/symbol_linefill/expected_datadefined_subsymbol/expected_datadefined_subsymbol_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill.png index 9ecc7165d2aa..941e75fb4a69 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill.png and b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill_mask.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill_mask.png deleted file mode 100644 index 20d8342620de..000000000000 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill/expected_symbol_linefill_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_negoffset/expected_symbol_linefill_large_negoffset.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_negoffset/expected_symbol_linefill_large_negoffset.png index 2d83b53e2a24..9461e55b1367 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_negoffset/expected_symbol_linefill_large_negoffset.png and b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_negoffset/expected_symbol_linefill_large_negoffset.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_posoffset/expected_symbol_linefill_large_posoffset.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_posoffset/expected_symbol_linefill_large_posoffset.png index d3b7d509f116..cc72f168627b 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_posoffset/expected_symbol_linefill_large_posoffset.png and b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_large_posoffset/expected_symbol_linefill_large_posoffset.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negangle/expected_symbol_linefill_negangle.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negangle/expected_symbol_linefill_negangle.png index 8cbf7c20b6d5..fd0e39c8485f 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negangle/expected_symbol_linefill_negangle.png and b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negangle/expected_symbol_linefill_negangle.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negoffset/expected_symbol_linefill_negoffset.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negoffset/expected_symbol_linefill_negoffset.png index 30a721a4a9ea..dc20a6c5e8ca 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negoffset/expected_symbol_linefill_negoffset.png and b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_negoffset/expected_symbol_linefill_negoffset.png differ diff --git a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_posoffset/expected_symbol_linefill_posoffset.png b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_posoffset/expected_symbol_linefill_posoffset.png index be15b51f1344..534056d80576 100644 Binary files a/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_posoffset/expected_symbol_linefill_posoffset.png and b/tests/testdata/control_images/symbol_linefill/expected_symbol_linefill_posoffset/expected_symbol_linefill_posoffset.png differ diff --git a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill.png b/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill.png index 576766b60174..9e0ff13e0ea9 100644 Binary files a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill.png and b/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill.png differ diff --git a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill_mask.png b/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill_mask.png deleted file mode 100644 index 64d30c153b98..000000000000 Binary files a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill/expected_symbol_pointfill_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset.png b/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset.png index a62fd3610912..3decc56f042d 100644 Binary files a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset.png and b/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset.png differ diff --git a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset_mask.png b/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset_mask.png deleted file mode 100644 index 64d30c153b98..000000000000 Binary files a/tests/testdata/control_images/symbol_pointpatternfill/expected_symbol_pointfill_offset/expected_symbol_pointfill_offset_mask.png and /dev/null differ diff --git a/tests/testdata/control_images/text_renderer/background_ellipse_pixels/background_ellipse_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_ellipse_pixels/background_ellipse_pixels_mask.png index c65cd6220876..dfc7f6e2ab40 100644 Binary files a/tests/testdata/control_images/text_renderer/background_ellipse_pixels/background_ellipse_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_ellipse_pixels/background_ellipse_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_fillcolor/background_fillcolor_mask.png b/tests/testdata/control_images/text_renderer/background_fillcolor/background_fillcolor_mask.png index 38bb2e27ec43..13a44238cd20 100644 Binary files a/tests/testdata/control_images/text_renderer/background_fillcolor/background_fillcolor_mask.png and b/tests/testdata/control_images/text_renderer/background_fillcolor/background_fillcolor_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_marker_buffer_mapunits/background_marker_buffer_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_marker_buffer_mapunits/background_marker_buffer_mapunits_mask.png new file mode 100644 index 000000000000..060c536636b7 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/background_marker_buffer_mapunits/background_marker_buffer_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_marker_buffer_mm/background_marker_buffer_mm_mask.png b/tests/testdata/control_images/text_renderer/background_marker_buffer_mm/background_marker_buffer_mm_mask.png new file mode 100644 index 000000000000..6de30df9c615 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/background_marker_buffer_mm/background_marker_buffer_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_marker_buffer_pixels/background_marker_buffer_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_marker_buffer_pixels/background_marker_buffer_pixels_mask.png new file mode 100644 index 000000000000..827c15de2d1d Binary files /dev/null and b/tests/testdata/control_images/text_renderer/background_marker_buffer_pixels/background_marker_buffer_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_marker_fixed_mapunits/background_marker_fixed_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_marker_fixed_mapunits/background_marker_fixed_mapunits_mask.png new file mode 100644 index 000000000000..997ce4328dcc Binary files /dev/null and b/tests/testdata/control_images/text_renderer/background_marker_fixed_mapunits/background_marker_fixed_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_marker_fixed_mm/background_marker_fixed_mm_mask.png b/tests/testdata/control_images/text_renderer/background_marker_fixed_mm/background_marker_fixed_mm_mask.png new file mode 100644 index 000000000000..0f40b3c15e3f Binary files /dev/null and b/tests/testdata/control_images/text_renderer/background_marker_fixed_mm/background_marker_fixed_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_marker_fixed_pixels/background_marker_fixed_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_marker_fixed_pixels/background_marker_fixed_pixels_mask.png new file mode 100644 index 000000000000..9f090d2968a3 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/background_marker_fixed_pixels/background_marker_fixed_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_offset_mapunits/background_offset_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_offset_mapunits/background_offset_mapunits_mask.png index 8af0d3530ae7..70a6b1626e11 100644 Binary files a/tests/testdata/control_images/text_renderer/background_offset_mapunits/background_offset_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_offset_mapunits/background_offset_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_offset_mm/background_offset_mm_mask.png b/tests/testdata/control_images/text_renderer/background_offset_mm/background_offset_mm_mask.png index 1db4abf67e88..b159896883a7 100644 Binary files a/tests/testdata/control_images/text_renderer/background_offset_mm/background_offset_mm_mask.png and b/tests/testdata/control_images/text_renderer/background_offset_mm/background_offset_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_opacity/background_opacity_mask.png b/tests/testdata/control_images/text_renderer/background_opacity/background_opacity_mask.png index 38bb2e27ec43..9bf3426dd88e 100644 Binary files a/tests/testdata/control_images/text_renderer/background_opacity/background_opacity_mask.png and b/tests/testdata/control_images/text_renderer/background_opacity/background_opacity_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_outline/background_outline_mask.png b/tests/testdata/control_images/text_renderer/background_outline/background_outline_mask.png index fd48aab036e1..7cd81e2a3585 100644 Binary files a/tests/testdata/control_images/text_renderer/background_outline/background_outline_mask.png and b/tests/testdata/control_images/text_renderer/background_outline/background_outline_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_point_multiline_buffer_mapunits/background_point_multiline_buffer_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_point_multiline_buffer_mapunits/background_point_multiline_buffer_mapunits_mask.png index 828a5aa0c057..0a2c06c4f7ea 100644 Binary files a/tests/testdata/control_images/text_renderer/background_point_multiline_buffer_mapunits/background_point_multiline_buffer_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_point_multiline_buffer_mapunits/background_point_multiline_buffer_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_radii_mapunits/background_radii_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_radii_mapunits/background_radii_mapunits_mask.png index 1c4ede6765cd..0e6c1e0eaaba 100644 Binary files a/tests/testdata/control_images/text_renderer/background_radii_mapunits/background_radii_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_radii_mapunits/background_radii_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_radii_mm/background_radii_mm_mask.png b/tests/testdata/control_images/text_renderer/background_radii_mm/background_radii_mm_mask.png index 6ecca1f51cab..4de4939a3d53 100644 Binary files a/tests/testdata/control_images/text_renderer/background_radii_mm/background_radii_mm_mask.png and b/tests/testdata/control_images/text_renderer/background_radii_mm/background_radii_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_buffer_mapunits/background_rect_buffer_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_rect_buffer_mapunits/background_rect_buffer_mapunits_mask.png index 1997cd96a4b1..ffe66c9046d7 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_buffer_mapunits/background_rect_buffer_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_buffer_mapunits/background_rect_buffer_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_buffer_mm/background_rect_buffer_mm_mask.png b/tests/testdata/control_images/text_renderer/background_rect_buffer_mm/background_rect_buffer_mm_mask.png index cc9a47e76e32..1b5147a88933 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_buffer_mm/background_rect_buffer_mm_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_buffer_mm/background_rect_buffer_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_buffer_pixels/background_rect_buffer_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_rect_buffer_pixels/background_rect_buffer_pixels_mask.png index ec65a7a04566..7bedeec2c542 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_buffer_pixels/background_rect_buffer_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_buffer_pixels/background_rect_buffer_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_center_buffer_pixels/background_rect_center_buffer_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_rect_center_buffer_pixels/background_rect_center_buffer_pixels_mask.png index 86b0cce37031..baa15690dcff 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_center_buffer_pixels/background_rect_center_buffer_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_center_buffer_pixels/background_rect_center_buffer_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_mapunits/background_rect_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_rect_mapunits/background_rect_mapunits_mask.png index 73ed4b6a5230..a449b7b5d95d 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_mapunits/background_rect_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_mapunits/background_rect_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_mm/background_rect_mm_mask.png b/tests/testdata/control_images/text_renderer/background_rect_mm/background_rect_mm_mask.png index e4c3852a2512..425f9282f574 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_mm/background_rect_mm_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_mm/background_rect_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_multiline_buffer_mapunits/background_rect_multiline_buffer_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_rect_multiline_buffer_mapunits/background_rect_multiline_buffer_mapunits_mask.png index 763d71fc7618..bdd42a5606b3 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_multiline_buffer_mapunits/background_rect_multiline_buffer_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_multiline_buffer_mapunits/background_rect_multiline_buffer_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_multiline_mapunits/background_rect_multiline_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_rect_multiline_mapunits/background_rect_multiline_mapunits_mask.png index f3091b961cb0..959a6eb3021f 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_multiline_mapunits/background_rect_multiline_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_multiline_mapunits/background_rect_multiline_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_pixels/background_rect_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_rect_pixels/background_rect_pixels_mask.png index c9e45f2242a8..2f0b567cf615 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_pixels/background_rect_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_pixels/background_rect_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_right_buffer_pixels/background_rect_right_buffer_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_rect_right_buffer_pixels/background_rect_right_buffer_pixels_mask.png index 987b4556ea6c..3d885ce85821 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_right_buffer_pixels/background_rect_right_buffer_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_right_buffer_pixels/background_rect_right_buffer_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rect_right_mapunits/background_rect_right_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_rect_right_mapunits/background_rect_right_mapunits_mask.png index d910e0c6a47a..fb83b8cce126 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rect_right_mapunits/background_rect_right_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_rect_right_mapunits/background_rect_right_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_rotation_offset/background_rotation_offset_mask.png b/tests/testdata/control_images/text_renderer/background_rotation_offset/background_rotation_offset_mask.png index e2e33184d8db..170c73f7b0ad 100644 Binary files a/tests/testdata/control_images/text_renderer/background_rotation_offset/background_rotation_offset_mask.png and b/tests/testdata/control_images/text_renderer/background_rotation_offset/background_rotation_offset_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_svg_buffer_mapunits/background_svg_buffer_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_svg_buffer_mapunits/background_svg_buffer_mapunits_mask.png index 487d34b09f98..b79e7b9b2d45 100644 Binary files a/tests/testdata/control_images/text_renderer/background_svg_buffer_mapunits/background_svg_buffer_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_svg_buffer_mapunits/background_svg_buffer_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_svg_buffer_mm/background_svg_buffer_mm_mask.png b/tests/testdata/control_images/text_renderer/background_svg_buffer_mm/background_svg_buffer_mm_mask.png index 55b1376dd23b..487213c2267b 100644 Binary files a/tests/testdata/control_images/text_renderer/background_svg_buffer_mm/background_svg_buffer_mm_mask.png and b/tests/testdata/control_images/text_renderer/background_svg_buffer_mm/background_svg_buffer_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_svg_buffer_pixels/background_svg_buffer_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_svg_buffer_pixels/background_svg_buffer_pixels_mask.png index e2242a0ba571..815fc92c7812 100644 Binary files a/tests/testdata/control_images/text_renderer/background_svg_buffer_pixels/background_svg_buffer_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_svg_buffer_pixels/background_svg_buffer_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_svg_fixed_mapunits/background_svg_fixed_mapunits_mask.png b/tests/testdata/control_images/text_renderer/background_svg_fixed_mapunits/background_svg_fixed_mapunits_mask.png index 6e10d691a9e3..ff4e542c25d5 100644 Binary files a/tests/testdata/control_images/text_renderer/background_svg_fixed_mapunits/background_svg_fixed_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/background_svg_fixed_mapunits/background_svg_fixed_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_svg_fixed_mm/background_svg_fixed_mm_mask.png b/tests/testdata/control_images/text_renderer/background_svg_fixed_mm/background_svg_fixed_mm_mask.png index c38a9e90cf1d..08d1d50b1ee4 100644 Binary files a/tests/testdata/control_images/text_renderer/background_svg_fixed_mm/background_svg_fixed_mm_mask.png and b/tests/testdata/control_images/text_renderer/background_svg_fixed_mm/background_svg_fixed_mm_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/background_svg_fixed_pixels/background_svg_fixed_pixels_mask.png b/tests/testdata/control_images/text_renderer/background_svg_fixed_pixels/background_svg_fixed_pixels_mask.png index d053dbb1601a..6c4909d52e3b 100644 Binary files a/tests/testdata/control_images/text_renderer/background_svg_fixed_pixels/background_svg_fixed_pixels_mask.png and b/tests/testdata/control_images/text_renderer/background_svg_fixed_pixels/background_svg_fixed_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_color/shadow_color_mask.png b/tests/testdata/control_images/text_renderer/shadow_color/shadow_color_mask.png index 546d7af5a7e6..384ee880ddc4 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_color/shadow_color_mask.png and b/tests/testdata/control_images/text_renderer/shadow_color/shadow_color_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_enabled/shadow_enabled_mask.png b/tests/testdata/control_images/text_renderer/shadow_enabled/shadow_enabled_mask.png index da3f61d37edb..72dc783c0b58 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_enabled/shadow_enabled_mask.png and b/tests/testdata/control_images/text_renderer/shadow_enabled/shadow_enabled_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_offset_angle/shadow_offset_angle_mask.png b/tests/testdata/control_images/text_renderer/shadow_offset_angle/shadow_offset_angle_mask.png index 217fba1d1b5f..cef27577e32e 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_offset_angle/shadow_offset_angle_mask.png and b/tests/testdata/control_images/text_renderer/shadow_offset_angle/shadow_offset_angle_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_offset_mapunits/shadow_offset_mapunits_mask.png b/tests/testdata/control_images/text_renderer/shadow_offset_mapunits/shadow_offset_mapunits_mask.png index 4a79929cca50..c8148e47a57c 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_offset_mapunits/shadow_offset_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/shadow_offset_mapunits/shadow_offset_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_offset_pixels/shadow_offset_pixels_mask.png b/tests/testdata/control_images/text_renderer/shadow_offset_pixels/shadow_offset_pixels_mask.png index 059c2cc7bfb0..13f944ed2653 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_offset_pixels/shadow_offset_pixels_mask.png and b/tests/testdata/control_images/text_renderer/shadow_offset_pixels/shadow_offset_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_opacity/shadow_opacity_mask.png b/tests/testdata/control_images/text_renderer/shadow_opacity/shadow_opacity_mask.png index d8bff7d74f8e..8f30f5a656a1 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_opacity/shadow_opacity_mask.png and b/tests/testdata/control_images/text_renderer/shadow_opacity/shadow_opacity_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_placement_background/shadow_placement_background_mask.png b/tests/testdata/control_images/text_renderer/shadow_placement_background/shadow_placement_background_mask.png index 6414640b523e..0955d12b9781 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_placement_background/shadow_placement_background_mask.png and b/tests/testdata/control_images/text_renderer/shadow_placement_background/shadow_placement_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_placement_buffer/shadow_placement_buffer_mask.png b/tests/testdata/control_images/text_renderer/shadow_placement_buffer/shadow_placement_buffer_mask.png index d16d657c027a..77bd2fc40099 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_placement_buffer/shadow_placement_buffer_mask.png and b/tests/testdata/control_images/text_renderer/shadow_placement_buffer/shadow_placement_buffer_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_radius_mapunits/shadow_radius_mapunits_mask.png b/tests/testdata/control_images/text_renderer/shadow_radius_mapunits/shadow_radius_mapunits_mask.png index afa64385d9dd..8a6a9c574462 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_radius_mapunits/shadow_radius_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/shadow_radius_mapunits/shadow_radius_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_radius_pixels/shadow_radius_pixels_mask.png b/tests/testdata/control_images/text_renderer/shadow_radius_pixels/shadow_radius_pixels_mask.png index 4200848863c3..abe3832b182c 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_radius_pixels/shadow_radius_pixels_mask.png and b/tests/testdata/control_images/text_renderer/shadow_radius_pixels/shadow_radius_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/shadow_scale_150/shadow_scale_150_mask.png b/tests/testdata/control_images/text_renderer/shadow_scale_150/shadow_scale_150_mask.png index 41c86c38e424..e1c68e56a0b5 100644 Binary files a/tests/testdata/control_images/text_renderer/shadow_scale_150/shadow_scale_150_mask.png and b/tests/testdata/control_images/text_renderer/shadow_scale_150/shadow_scale_150_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_angled/text_angled_mask.png b/tests/testdata/control_images/text_renderer/text_angled/text_angled_mask.png index 2b64d9cbdc9a..386370e05d46 100644 Binary files a/tests/testdata/control_images/text_renderer/text_angled/text_angled_mask.png and b/tests/testdata/control_images/text_renderer/text_angled/text_angled_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_bold/text_bold_mask.png b/tests/testdata/control_images/text_renderer/text_bold/text_bold_mask.png index 1d406edec74c..d958db7eca0f 100644 Binary files a/tests/testdata/control_images/text_renderer/text_bold/text_bold_mask.png and b/tests/testdata/control_images/text_renderer/text_bold/text_bold_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_buffer_color/text_buffer_color_mask.png b/tests/testdata/control_images/text_renderer/text_buffer_color/text_buffer_color_mask.png index 6e8a5be8d4ee..df7470088066 100644 Binary files a/tests/testdata/control_images/text_renderer/text_buffer_color/text_buffer_color_mask.png and b/tests/testdata/control_images/text_renderer/text_buffer_color/text_buffer_color_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_buffer_pixels/text_buffer_pixels_mask.png b/tests/testdata/control_images/text_renderer/text_buffer_pixels/text_buffer_pixels_mask.png index 4a2fd100d4eb..09eae5416eb3 100644 Binary files a/tests/testdata/control_images/text_renderer/text_buffer_pixels/text_buffer_pixels_mask.png and b/tests/testdata/control_images/text_renderer/text_buffer_pixels/text_buffer_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_color/text_color_mask.png b/tests/testdata/control_images/text_renderer/text_color/text_color_mask.png index 0fabe2b76c5b..06470136cedb 100644 Binary files a/tests/testdata/control_images/text_renderer/text_color/text_color_mask.png and b/tests/testdata/control_images/text_renderer/text_color/text_color_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_dd_color_rect/text_dd_color_rect_mask.png b/tests/testdata/control_images/text_renderer/text_dd_color_rect/text_dd_color_rect_mask.png new file mode 100644 index 000000000000..2f3f146a08a3 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_dd_color_rect/text_dd_color_rect_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_line_height/text_line_height_mask.png b/tests/testdata/control_images/text_renderer/text_line_height/text_line_height_mask.png index 4fa9ad5f745b..1e578b63171b 100644 Binary files a/tests/testdata/control_images/text_renderer/text_line_height/text_line_height_mask.png and b/tests/testdata/control_images/text_renderer/text_line_height/text_line_height_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_mapunits/text_mapunits_mask.png b/tests/testdata/control_images/text_renderer/text_mapunits/text_mapunits_mask.png index a89d2c907864..dcd3f3c64dde 100644 Binary files a/tests/testdata/control_images/text_renderer/text_mapunits/text_mapunits_mask.png and b/tests/testdata/control_images/text_renderer/text_mapunits/text_mapunits_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_multiline/text_multiline_mask.png b/tests/testdata/control_images/text_renderer/text_multiline/text_multiline_mask.png index 36f93d83b2f1..6ecf21249182 100644 Binary files a/tests/testdata/control_images/text_renderer/text_multiline/text_multiline_mask.png and b/tests/testdata/control_images/text_renderer/text_multiline/text_multiline_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_opacity/text_opacity_mask.png b/tests/testdata/control_images/text_renderer/text_opacity/text_opacity_mask.png index d23c023c58f3..bd0e3f6fe4da 100644 Binary files a/tests/testdata/control_images/text_renderer/text_opacity/text_opacity_mask.png and b/tests/testdata/control_images/text_renderer/text_opacity/text_opacity_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_pixels/text_pixels_mask.png b/tests/testdata/control_images/text_renderer/text_pixels/text_pixels_mask.png index 757e796f32c7..0a7dfe0f3752 100644 Binary files a/tests/testdata/control_images/text_renderer/text_pixels/text_pixels_mask.png and b/tests/testdata/control_images/text_renderer/text_pixels/text_pixels_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_point_justify_aligned/text_point_justify_aligned.png b/tests/testdata/control_images/text_renderer/text_point_justify_aligned/text_point_justify_aligned.png new file mode 100644 index 000000000000..6bc7bb81d6bb Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_point_justify_aligned/text_point_justify_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_point_justify_multiline_aligned/text_point_justify_multiline_aligned.png b/tests/testdata/control_images/text_renderer/text_point_justify_multiline_aligned/text_point_justify_multiline_aligned.png new file mode 100644 index 000000000000..f36456233320 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_point_justify_multiline_aligned/text_point_justify_multiline_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_bottom_aligned/text_rect_bottom_aligned.png b/tests/testdata/control_images/text_renderer/text_rect_bottom_aligned/text_rect_bottom_aligned.png new file mode 100644 index 000000000000..9d7596de771e Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_bottom_aligned/text_rect_bottom_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_center_aligned/text_rect_center_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_center_aligned/text_rect_center_aligned_mask.png index 47a3f527ef37..f27e6bb48f25 100644 Binary files a/tests/testdata/control_images/text_renderer/text_rect_center_aligned/text_rect_center_aligned_mask.png and b/tests/testdata/control_images/text_renderer/text_rect_center_aligned/text_rect_center_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_justify_aligned/text_rect_justify_aligned.png b/tests/testdata/control_images/text_renderer/text_rect_justify_aligned/text_rect_justify_aligned.png new file mode 100644 index 000000000000..485a85830150 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_justify_aligned/text_rect_justify_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_bottom_aligned/text_rect_multiline_bottom_aligned.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_bottom_aligned/text_rect_multiline_bottom_aligned.png new file mode 100644 index 000000000000..50d5548726b1 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_multiline_bottom_aligned/text_rect_multiline_bottom_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_bottom_aligned/text_rect_multiline_bottom_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_bottom_aligned/text_rect_multiline_bottom_aligned_mask.png new file mode 100644 index 000000000000..34576601e4b7 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_multiline_bottom_aligned/text_rect_multiline_bottom_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_center_aligned/text_rect_multiline_center_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_center_aligned/text_rect_multiline_center_aligned_mask.png index c44eb20deddc..c9220562e1c6 100644 Binary files a/tests/testdata/control_images/text_renderer/text_rect_multiline_center_aligned/text_rect_multiline_center_aligned_mask.png and b/tests/testdata/control_images/text_renderer/text_rect_multiline_center_aligned/text_rect_multiline_center_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_justify_aligned/text_rect_multiline_justify_aligned.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_justify_aligned/text_rect_multiline_justify_aligned.png new file mode 100644 index 000000000000..6fa66d5e70c7 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_multiline_justify_aligned/text_rect_multiline_justify_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_justify_aligned/text_rect_multiline_justify_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_justify_aligned/text_rect_multiline_justify_aligned_mask.png new file mode 100644 index 000000000000..56af6a5bc345 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_multiline_justify_aligned/text_rect_multiline_justify_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_right_aligned/text_rect_multiline_right_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_right_aligned/text_rect_multiline_right_aligned_mask.png index f963afd81a4b..582b05d81009 100644 Binary files a/tests/testdata/control_images/text_renderer/text_rect_multiline_right_aligned/text_rect_multiline_right_aligned_mask.png and b/tests/testdata/control_images/text_renderer/text_rect_multiline_right_aligned/text_rect_multiline_right_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_vcenter_aligned/text_rect_multiline_vcenter_aligned.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_vcenter_aligned/text_rect_multiline_vcenter_aligned.png new file mode 100644 index 000000000000..c63e6ec93114 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_multiline_vcenter_aligned/text_rect_multiline_vcenter_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_multiline_vcenter_aligned/text_rect_multiline_vcenter_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_multiline_vcenter_aligned/text_rect_multiline_vcenter_aligned_mask.png new file mode 100644 index 000000000000..5865e496205e Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_multiline_vcenter_aligned/text_rect_multiline_vcenter_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_right_aligned/text_rect_right_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_rect_right_aligned/text_rect_right_aligned_mask.png index 0c76b5a75080..536b9aae60e7 100644 Binary files a/tests/testdata/control_images/text_renderer/text_rect_right_aligned/text_rect_right_aligned_mask.png and b/tests/testdata/control_images/text_renderer/text_rect_right_aligned/text_rect_right_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_rect_vcenter_aligned/text_rect_vcenter_aligned.png b/tests/testdata/control_images/text_renderer/text_rect_vcenter_aligned/text_rect_vcenter_aligned.png new file mode 100644 index 000000000000..e9c54acda7cf Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_rect_vcenter_aligned/text_rect_vcenter_aligned.png differ diff --git a/tests/testdata/control_images/text_renderer/text_vertical_rect_mode/text_vertical_rect_mode_mask.png b/tests/testdata/control_images/text_renderer/text_vertical_rect_mode/text_vertical_rect_mode_mask.png new file mode 100644 index 000000000000..c84944e3cec7 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_vertical_rect_mode/text_vertical_rect_mode_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_vertical_rect_mode_center_aligned/text_vertical_rect_mode_center_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_vertical_rect_mode_center_aligned/text_vertical_rect_mode_center_aligned_mask.png new file mode 100644 index 000000000000..e112e660d4f3 Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_vertical_rect_mode_center_aligned/text_vertical_rect_mode_center_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_vertical_rect_mode_right_aligned/text_vertical_rect_mode_right_aligned_mask.png b/tests/testdata/control_images/text_renderer/text_vertical_rect_mode_right_aligned/text_vertical_rect_mode_right_aligned_mask.png new file mode 100644 index 000000000000..8b56974af2be Binary files /dev/null and b/tests/testdata/control_images/text_renderer/text_vertical_rect_mode_right_aligned/text_vertical_rect_mode_right_aligned_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_background/text_with_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_background/text_with_background_mask.png index b05c9ab2c66b..20189f52de03 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_background/text_with_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_background/text_with_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_buffer/text_with_buffer_mask.png b/tests/testdata/control_images/text_renderer/text_with_buffer/text_with_buffer_mask.png index 4be3d9d471ca..e47bcd420cdd 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_buffer/text_with_buffer_mask.png and b/tests/testdata/control_images/text_renderer/text_with_buffer/text_with_buffer_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_buffer_and_background/text_with_buffer_and_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_buffer_and_background/text_with_buffer_and_background_mask.png index 8fa619df3f91..77cb561bdcd6 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_buffer_and_background/text_with_buffer_and_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_buffer_and_background/text_with_buffer_and_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_and_background/text_with_shadow_and_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_and_background/text_with_shadow_and_background_mask.png index 8aeb45625c7e..17a2d2616ddc 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_and_background/text_with_shadow_and_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_and_background/text_with_shadow_and_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_and_buffer/text_with_shadow_and_buffer_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_and_buffer/text_with_shadow_and_buffer_mask.png index a68683d03aea..08e5bd383649 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_and_buffer/text_with_shadow_and_buffer_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_and_buffer/text_with_shadow_and_buffer_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_below_buffer_and_background/text_with_shadow_below_buffer_and_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_below_buffer_and_background/text_with_shadow_below_buffer_and_background_mask.png index fdfee3a15b17..32dab3fadf9e 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_below_buffer_and_background/text_with_shadow_below_buffer_and_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_below_buffer_and_background/text_with_shadow_below_buffer_and_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_background/text_with_shadow_below_text_and_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_background/text_with_shadow_below_text_and_background_mask.png index 1f131a3a04f3..2f1fea216ee5 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_background/text_with_shadow_below_text_and_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_background/text_with_shadow_below_text_and_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_buffer/text_with_shadow_below_text_and_buffer_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_buffer/text_with_shadow_below_text_and_buffer_mask.png index 1776c42f4129..e0defa5f217c 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_buffer/text_with_shadow_below_text_and_buffer_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_and_buffer/text_with_shadow_below_text_and_buffer_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_buffer_and_background/text_with_shadow_below_text_buffer_and_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_buffer_and_background/text_with_shadow_below_text_buffer_and_background_mask.png index 31f7d57469f5..4f2621d947ca 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_buffer_and_background/text_with_shadow_below_text_buffer_and_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_below_text_buffer_and_background/text_with_shadow_below_text_buffer_and_background_mask.png differ diff --git a/tests/testdata/control_images/text_renderer/text_with_shadow_buffer_and_background/text_with_shadow_buffer_and_background_mask.png b/tests/testdata/control_images/text_renderer/text_with_shadow_buffer_and_background/text_with_shadow_buffer_and_background_mask.png index a24051c0b5e7..ed5cf5d71b81 100644 Binary files a/tests/testdata/control_images/text_renderer/text_with_shadow_buffer_and_background/text_with_shadow_buffer_and_background_mask.png and b/tests/testdata/control_images/text_renderer/text_with_shadow_buffer_and_background/text_with_shadow_buffer_and_background_mask.png differ diff --git a/tests/testdata/qgis_server/api/test_wfs3_api_project.json b/tests/testdata/qgis_server/api/test_wfs3_api_project.json index 0c814e433d51..d6d346fd4a5b 100644 --- a/tests/testdata/qgis_server/api/test_wfs3_api_project.json +++ b/tests/testdata/qgis_server/api/test_wfs3_api_project.json @@ -135,7 +135,7 @@ Content-Type: application/vnd.oai.openapi+json;version=3.0 }, "sortby": { "description": "Sort results by the specified field name", - "in": "path", + "in": "query", "name": "sortby", "required": false, "schema": { @@ -144,11 +144,11 @@ Content-Type: application/vnd.oai.openapi+json;version=3.0 }, "sortdesc": { "description": "Sort results in descending order, field name must be specified with 'sortby' parameter", - "in": "path", + "in": "query", "name": "sortdesc", "required": false, "schema": { - "type": "bool" + "type": "boolean" } } }, @@ -2077,4 +2077,4 @@ Content-Type: application/vnd.oai.openapi+json;version=3.0 "name": "Features" } ] -} \ No newline at end of file +}