├── COPYING ├── README.md ├── deploy.sh ├── deploy_resources_to_shared_drive.sh ├── make.sh ├── qgis-custom-0.9-2.tar.bz2 └── qgis-custom ├── apps ├── qgis-custom │ ├── WMTS_scales.xml │ ├── bin │ │ └── qgis-custom-ltr.reg │ ├── layout_checks.py │ ├── qgis-ltr-custom.bat.template │ ├── qgis_constrained_settings.py │ ├── qgis_constrained_settings.yml │ ├── qgis_global_settings.ini │ └── startup_project.qgs └── qgis-ltr │ └── python │ └── plugins │ ├── SpreadsheetLayers │ ├── CHANGELOG.md │ ├── README.rst │ ├── SpreadsheetLayersPlugin.py │ ├── __init__.py │ ├── help │ │ ├── .gitignore │ │ ├── locale │ │ │ └── fr │ │ │ │ └── LC_MESSAGES │ │ │ │ └── index.po │ │ ├── make.bat │ │ └── source │ │ │ ├── conf.py │ │ │ └── index.rst │ ├── i18n │ │ ├── .gitignore │ │ ├── SpreadsheetLayers_fr.ts │ │ └── SpreadsheetLayers_ru.ts │ ├── metadata.txt │ ├── plugin_upload.py │ ├── pylintrc │ ├── requirements.txt │ ├── resources │ │ ├── icon │ │ │ └── mActionAddSpreadsheetLayer.svg │ │ └── resources.qrc │ ├── ui │ │ ├── __init__.py │ │ ├── resources_rc.py │ │ └── ui_SpreadsheetLayersDialog.ui │ ├── util │ │ ├── __init__.py │ │ └── gdal_util.py │ └── widgets │ │ ├── SpreadsheetLayersDialog.py │ │ └── __init__.py │ ├── coordinator │ ├── __init__.py │ ├── coordinator.py │ ├── coordinator_dockwidget.py │ ├── coordinator_dockwidget_base.ui │ ├── funcs.py │ ├── help │ │ ├── help.css │ │ ├── images │ │ │ ├── capture.gif │ │ │ ├── screen_basics.png │ │ │ ├── screen_capture.png │ │ │ ├── screen_copy.png │ │ │ ├── screen_digitize.png │ │ │ ├── screen_labels.ai │ │ │ ├── screen_main.png │ │ │ └── screen_maptools.png │ │ └── index.html │ ├── i18n │ │ ├── coordinator_de.qm │ │ └── coordinator_fr.qm │ ├── metadata.txt │ ├── resources.py │ ├── resources.qrc │ └── test │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── data │ │ ├── europe.geojson │ │ ├── tenbytenraster.asc │ │ ├── tenbytenraster.keywords │ │ ├── tenbytenraster.lic │ │ ├── tenbytenraster.prj │ │ └── tenbytenraster.qml │ │ ├── qgis_interface.py │ │ ├── test_canvas.py │ │ ├── test_coordinator_dockwidget.py │ │ ├── test_init.py │ │ ├── test_integration.py │ │ ├── test_qgis_environment.py │ │ ├── test_resources.py │ │ ├── test_translations.py │ │ └── utilities.py │ ├── french_locator_filter │ ├── __about__.py │ ├── __init__.py │ ├── core │ │ ├── __init__.py │ │ └── locator_filter.py │ ├── gui │ │ ├── __init__.py │ │ ├── dlg_settings.py │ │ └── dlg_settings.ui │ ├── metadata.txt │ ├── plugin_main.py │ ├── resources.qrc │ ├── resources │ │ ├── help │ │ │ └── index.html │ │ ├── i18n │ │ │ ├── french_locator_filter_fr.qm │ │ │ ├── french_locator_filter_fr.ts │ │ │ └── plugin_translation.pro │ │ └── images │ │ │ └── icon.svg │ ├── resources_rc.py │ └── toolbelt │ │ ├── __init__.py │ │ ├── log_handler.py │ │ ├── network_manager.py │ │ ├── preferences.py │ │ └── translator.py │ ├── mask │ ├── Makefile │ ├── __init__.py │ ├── aeag_mask.png │ ├── aeag_mask.py │ ├── default_mask_style.qml │ ├── doc │ │ ├── en │ │ │ ├── about.html │ │ │ ├── legend_inmask.png │ │ │ └── tips.html │ │ └── fr │ │ │ ├── about.html │ │ │ ├── legend_inmask.png │ │ │ └── tips.html │ ├── htmldialog.py │ ├── i18n │ │ └── fr.qm │ ├── layerlist.py │ ├── maindialog.py │ ├── mask_filter.py │ ├── mask_parameters.py │ ├── metadata.txt │ ├── resources_rc.py │ ├── resources_rc.qrc │ ├── style_tools.py │ ├── ui_layer_list.py │ ├── ui_layer_list.ui │ ├── ui_plugin_mask.py │ └── ui_plugin_mask.ui │ ├── menu_from_project │ ├── __about__.py │ ├── __init__.py │ ├── doc │ │ ├── index-en.html │ │ └── index-fr.html │ ├── i18n │ │ ├── fr.qm │ │ └── fr.ts │ ├── logic │ │ ├── __init__.py │ │ ├── custom_datatypes.py │ │ ├── qgs_manager.py │ │ └── tools.py │ ├── menu_from_project.py │ ├── metadata.txt │ ├── plugin_translation.pro │ ├── resources │ │ ├── edit.svg │ │ ├── gear.svg │ │ ├── globe.svg │ │ └── menu_from_project.png │ └── ui │ │ ├── __init__.py │ │ ├── conf_dialog.ui │ │ └── menu_conf_dlg.py │ ├── qNote │ ├── README.rst │ ├── __init__.py │ ├── metadata.txt │ ├── qnote.py │ └── ui_qnote.ui │ └── redLayer │ ├── .gitattributes │ ├── .github │ ├── dependabot.yml │ └── workflows │ │ └── linter.yml │ ├── .gitignore │ ├── CHANGELOG.txt │ ├── README.md │ ├── __init__.py │ ├── i18n │ ├── redLayer.pro │ ├── redLayer_fr.qm │ └── redLayer_fr.ts │ ├── icons │ ├── canvas.svg │ ├── colorBlack.png │ ├── colorBlue.png │ ├── colorGreen.png │ ├── colorPalette.png │ ├── colorRed.png │ ├── colorYellow.png │ ├── erase.svg │ ├── inbox.svg │ ├── note.svg │ ├── outbox.svg │ ├── pen.svg │ ├── readme_menu.png │ ├── readme_menu_disabled.png │ ├── readme_screen.png │ ├── remove.svg │ ├── sketch.svg │ ├── toLayer.svg │ ├── width16.png │ ├── width2.png │ ├── width4.png │ └── width8.png │ ├── metadata.txt │ ├── note_class_dialog.py │ ├── redLayerModule.py │ ├── redLayerModule_dialog.py │ ├── redLayerModule_dialog_base.ui │ ├── setup.cfg │ ├── sketchLayerStyle.qml │ ├── tests │ ├── dev │ │ └── dev_qfile_dialog.py │ └── fixtures │ │ └── patatoid_around_south_america.sketch │ └── ui_note_dialog.ui ├── etc ├── postinstall │ └── qgis-custom.bat └── preremove │ └── qgis-custom.bat └── setup.hint /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # auteur : Régis Haubourg - GrenobleAlpesMetropole 5 | # Licence GPLV3 6 | # 26/05/2021 7 | 8 | # this script takes your locally built tar.bz2 package and push it to the local repository hosting your osgeo4W binaries 9 | 10 | echo "** Deploying osgeo4W custom package ** 11 | " 12 | 13 | cd qgis-custom 14 | 15 | SETUP_TEXT=$(cat setup.hint) 16 | 17 | PACKAGE_DIR="/x/OSGEO4W_DEPLOY_TEST/PAQUETS/http%3a%2f%2fwww.norbit.de%2fosgeo4w%2f" 18 | 19 | echo "-Target package directory : 20 | $PACKAGE_DIR 21 | " 22 | 23 | echo "-PAckage metadata : 24 | ------------ 25 | $SETUP_TEXT 26 | ------------" 27 | 28 | 29 | if [ ! -d "$PACKAGE_DIR" ] 30 | then 31 | echo "Target directory doesn't exists" 32 | # e xit 2 33 | fi 34 | 35 | 36 | VERSION=$(grep -i version setup.hint | awk '{printf $2}') 37 | 38 | echo "package version found: $VERSION" 39 | 40 | mkdir -p "$PACKAGE_DIR/x86_64/release/qgis/qgis-custom/" 41 | 42 | cd - 43 | 44 | cp -p qgis-custom-$VERSION.tar.bz2 $PACKAGE_DIR/x86_64/release/qgis/qgis-custom/ 45 | 46 | # md5 and size 47 | MD5=$(md5sum qgis-custom-$VERSION.tar.bz2 | awk -F'[ ]' '{print $1}') 48 | size=$(stat -c "%s" qgis-custom-$VERSION.tar.bz2) 49 | 50 | # adds metadata into setup.ini, from setup.hint template 51 | 52 | echo -e " 53 | - Modification du setup.ini cible" 54 | 55 | # deletes previous entry 56 | sed -i '/@ qgis-custom/,+8d;' $PACKAGE_DIR/x86_64/setup.ini 57 | 58 | # append to the end of the file 59 | 60 | echo "@ qgis-custom 61 | $SETUP_TEXT $size $MD5 62 | " >> $PACKAGE_DIR/x86_64/setup.ini 63 | 64 | echo -e "--------" 65 | 66 | echo -e "** Package deployed **" 67 | 68 | echo -e "--------" 69 | -------------------------------------------------------------------------------- /deploy_resources_to_shared_drive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # auteur : Régis Haubourg 5 | # Licence GPLV3 6 | # 26/05/2021 7 | 8 | 9 | echo "** Deployes some resources to a shared drive ** 10 | " 11 | S_DIR="/mnt/s/QGIS/custom" 12 | 13 | # Global settings et contraintes 14 | echo "copies global settings" 15 | cp qgis-custom/apps/qgis-custom/qgis_global_settings.ini $S_DIR/QGIS/ 16 | 17 | echo "Copies qgis_constrained_settings.yml" 18 | cp qgis-custom/apps/qgis-custom/qgis_constrained_settings.yml $S_DIR/QGIS/ 19 | 20 | 21 | # Startup project 22 | echo "Copies startup project" 23 | cp qgis-custom/apps/qgis-custom/startup_project.qgs $S_DIR/ 24 | 25 | 26 | echo -e "--------" 27 | 28 | echo -e "** End **" 29 | 30 | echo -e "--------" 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Building script of the custom package 5 | # gets version from setup.ini and build a osgeo4w tar.bz2 ready to be deployed 6 | 7 | cd qgis-custom 8 | # gets version 9 | VERSION=$(grep -i version setup.hint | awk '{printf $2}') 10 | 11 | # fix tar.bz2 name with real version replacing @@ marker with version 12 | 13 | sed -i "/install: x86_64/s/.*/install: x86_64\/release\/qgis\/qgis-custom\/qgis-custom-$VERSION.tar.bz2/" setup.hint 14 | 15 | # pushes version as a environment variable. Helps to diagnose which package version is installed quickly from QGIS settings 16 | sed -i "s/qgis-custom-VERSION=.*/qgis-custom-VERSION=$VERSION/" apps/qgis-custom/qgis-ltr-custom.bat.template 17 | 18 | # compression 19 | tar cvjSf ../qgis-custom-$VERSION.tar.bz2 . 20 | 21 | # restores @@ marker 22 | sed -i "s/qgis-custom-VERSION=.*/qgis-custom-VERSION=@@/" apps/qgis-custom/qgis-ltr-custom.bat.template 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /qgis-custom-0.9-2.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom-0.9-2.tar.bz2 -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/WMTS_scales.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/bin/qgis-custom-ltr.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_CLASSES_ROOT\QGIS Project] 4 | @="QGIS Project" 5 | 6 | [HKEY_CLASSES_ROOT\QGIS Project\DefaultIcon] 7 | @="@osgeo4w@\\apps\\qgis-ltr\\icons\\qgis-qgs.ico" 8 | 9 | [HKEY_CLASSES_ROOT\QGIS Project\Shell] 10 | 11 | [HKEY_CLASSES_ROOT\QGIS Project\Shell\open] 12 | @="" 13 | 14 | [HKEY_CLASSES_ROOT\QGIS Project\Shell\open\command] 15 | @="\"@osgeo4w@\\bin\\qgis-ltr-custom.bat\" \"%1\"" 16 | 17 | [HKEY_CLASSES_ROOT\.qgs] 18 | @="QGIS Project" 19 | 20 | [HKEY_CLASSES_ROOT\.qgz] 21 | @="QGIS Project" 22 | 23 | [HKEY_CLASSES_ROOT\QGIS Composer Template] 24 | @="QGIS Composer Template" 25 | 26 | [HKEY_CLASSES_ROOT\QGIS Composer Template\DefaultIcon] 27 | @="@osgeo4w@\\apps\\qgis-ltr\\icons\\qgis-qpt.ico" 28 | 29 | [HKEY_CLASSES_ROOT\.qpt] 30 | @="QGIS Composer Template" 31 | 32 | [HKEY_CLASSES_ROOT\QGIS Layer Settings] 33 | @="QGIS Layer Settings" 34 | 35 | [HKEY_CLASSES_ROOT\QGIS Layer Settings\DefaultIcon] 36 | @="@osgeo4w@\\apps\\qgis-ltr\\icons\\qgis-qml.ico" 37 | 38 | [HKEY_CLASSES_ROOT\.qml] 39 | @="QGIS Layer Settings" 40 | 41 | [HKEY_CLASSES_ROOT\QGIS Layer Definition] 42 | @="QGIS Layer Definition" 43 | 44 | [HKEY_CLASSES_ROOT\QGIS Layer Definition\DefaultIcon] 45 | @="@osgeo4w@\\apps\\qgis-ltr\\icons\\qgis-qlr.ico" 46 | 47 | [HKEY_CLASSES_ROOT\.qlr] 48 | @="QGIS Layer Definition" 49 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/layout_checks.py: -------------------------------------------------------------------------------- 1 | # Some scripts to provide layout pre-print checks - See https://north-road.com/2019/01/14/on-custom-layout-checks-in-qgis-3-6-and-how-they-can-do-your-work-for-you/ 2 | 3 | 4 | from qgis.core import check 5 | 6 | 7 | @check.register(type=QgsAbstractValidityCheck.TypeLayoutCheck) 8 | def layout_map_crs_choice_check(context, feedback): 9 | layout = context.layout 10 | for i in layout.items(): 11 | if isinstance(i, QgsLayoutItemMap): 12 | for l in i.layersToRender(): 13 | # check if layer source is blacklisted 14 | if "mt1.google.com" in l.source(): 15 | res = QgsValidityCheckResult() 16 | res.type = QgsValidityCheckResult.Critical 17 | res.title = "Blacklisted layer source" 18 | res.detailedDescription = 'This layout includes a Google Map layer ("{}"), which is in violation with their Terms of Service'.format( 19 | l.name() 20 | ) 21 | return [res] 22 | 23 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/qgis-ltr-custom.bat.template: -------------------------------------------------------------------------------- 1 | @echo off 2 | call "%~dp0\o4w_env.bat" 3 | call qt5_env.bat 4 | call py3_env.bat 5 | @echo off 6 | path %OSGEO4W_ROOT%\apps\qgis-ltr\bin;%PATH% 7 | set QGIS_PREFIX_PATH=%OSGEO4W_ROOT:\=/%/apps/qgis-ltr 8 | set GDAL_FILENAME_IS_UTF8=YES 9 | rem Set VSI cache to be used as buffer, see #6448 10 | set VSI_CACHE=TRUE 11 | set VSI_CACHE_SIZE=1000000 12 | set QT_PLUGIN_PATH=%OSGEO4W_ROOT%\apps\qgis-ltr\qtplugins;%OSGEO4W_ROOT%\apps\qt5\plugins 13 | 14 | rem config custom 15 | 16 | REM this "@@" pattern wil be replaced by make.sh with actual version 17 | 18 | set QGIS-CUSTOM-VERSION=@@ 19 | 20 | REM point a location for pg_service.conf 21 | set PGSERVICEFILE=\\some-server\sit$\QGIS\custom\.pg_service.conf 22 | 23 | REM centralized plugins on a server if needed 24 | REM set QGIS_PLUGINPATH=\\some-server\sit$\QGIS\custom\python\plugins 25 | 26 | REM location for default settings (if provided by this package) 27 | set QGIS_GLOBAL_SETTINGS_FILE=%OSGEO4W_ROOT%\apps\qgis-custom\qgis_global_settings.ini 28 | 29 | REM location for default settings (if centralized on a network path) 30 | REM set QGIS_GLOBAL_SETTINGS_FILE=\\some-server\sit$\QGIS\custom\QGIS\qgis_global_settings.ini 31 | 32 | REM starts QGIS with various options (profile name, startup code ) 33 | 34 | start "QGIS" /B "%OSGEO4W_ROOT%\bin\qgis-ltr-bin.exe" --profile custom --code %OSGEO4W_ROOT%\apps\qgis-custom\qgis_constrained_settings.py %* 35 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/qgis_constrained_settings.py: -------------------------------------------------------------------------------- 1 | # script that will run qsettings constraints when QGIS starts 2 | # config file : qgis_constrained_settings.yml 3 | # cf https://gitlab.com/Oslandia/qgis/qgis-constrained-settings 4 | 5 | import yaml 6 | import codecs 7 | import pathlib 8 | import collections 9 | import configparser 10 | import PyQt5.QtCore 11 | import qgis.core 12 | 13 | 14 | def main(): 15 | application = qgis.core.QgsApplication.instance() 16 | applicationSettings = qgis.core.QgsSettings( 17 | application.organizationName(), application.applicationName() 18 | ) 19 | globalSettingsPath = pathlib.Path(applicationSettings.globalSettingsPath()) 20 | globalSettingsDirPath = globalSettingsPath.parent 21 | qgisConstrainedSettingsPath = ( 22 | globalSettingsDirPath / "qgis_constrained_settings.yml" 23 | ) 24 | 25 | if not qgisConstrainedSettingsPath.is_file(): 26 | print("No file named {}".format(qgisConstrainedSettingsPath)) 27 | return 28 | 29 | print("Load constrained settings from {}".format(qgisConstrainedSettingsPath)) 30 | with open(str(qgisConstrainedSettingsPath)) as f: 31 | constrainedSettings = yaml.safe_load(f) 32 | 33 | userSettings = PyQt5.QtCore.QSettings() 34 | print("Process {}".format(userSettings.fileName())) 35 | 36 | propertiesToRemove = constrainedSettings.get("propertiesToRemove", {}) 37 | for group, properties in propertiesToRemove.items(): 38 | userSettings.beginGroup(group) 39 | if isinstance(properties, str): 40 | if properties == "*": 41 | userSettings.remove("") 42 | else: 43 | for prop in properties: 44 | userSettings.remove(prop) 45 | userSettings.endGroup() 46 | 47 | globalSettings = configparser.ConfigParser() 48 | with open(str(globalSettingsPath)) as f: 49 | globalSettings.read_file(f) 50 | 51 | propertiesToMerge = constrainedSettings.get("propertiesToMerge", {}) 52 | for group, properties in propertiesToMerge.items(): 53 | if not globalSettings.has_section(group): 54 | continue 55 | userSettings.beginGroup(group) 56 | for prop in properties: 57 | if not globalSettings.has_option(group, prop): 58 | continue 59 | userPropertyValues = userSettings.value(prop) 60 | if not userPropertyValues: 61 | continue 62 | if not isinstance(userPropertyValues, list): 63 | userPropertyValues = [userPropertyValues] 64 | globalPropertyValues = globalSettings.get(group, prop) 65 | globalPropertyValues = globalPropertyValues.split(",") 66 | # codecs.decode(v, "unicode_espace") is used to convert the raw string into a normal 67 | # string. This is required to avoid changing \\ sequences into \\\\ sequences 68 | globalPropertyValues = list( 69 | map( 70 | lambda v: codecs.decode(v.strip('" '), "unicode_escape"), 71 | globalPropertyValues, 72 | ) 73 | ) 74 | userPropertyValues = globalPropertyValues + userPropertyValues 75 | # remove duplicates 76 | userPropertyValues = list( 77 | collections.OrderedDict.fromkeys(userPropertyValues) 78 | ) 79 | userSettings.setValue(prop, userPropertyValues) 80 | userSettings.endGroup() 81 | 82 | propertyValuesToRemove = constrainedSettings.get("propertyValuesToRemove", {}) 83 | for group, properties in propertyValuesToRemove.items(): 84 | userSettings.beginGroup(group) 85 | for prop in properties: 86 | userPropertyValues = userSettings.value(prop) 87 | if not userPropertyValues: 88 | continue 89 | valuesToRemove = list(map(lambda v: v.rstrip("/\\ "), properties[prop])) 90 | userPropertyValues = [ 91 | v for v in userPropertyValues if v.rstrip("/\\ ") not in valuesToRemove 92 | ] 93 | userSettings.setValue(prop, userPropertyValues) 94 | userSettings.endGroup() 95 | 96 | 97 | if __name__ == "__main__": 98 | main() 99 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/qgis_constrained_settings.yml: -------------------------------------------------------------------------------- 1 | propertiesToRemove: 2 | qgis: 3 | - defaultProjectFileFormat 4 | proxy: 5 | - authcfg 6 | - proxyEnabled 7 | - proxyExcludeUrls 8 | - proxyHost 9 | - proxyPassword 10 | - proxyPort 11 | - proxyType 12 | - proxyUser 13 | - noProxyUrls 14 | PostgreSQL: 15 | - connections/selected 16 | - connections/bd_prod/service 17 | - connections/bd_prod/host 18 | - connections/bd_prod/port 19 | - connections/bd_prod/database 20 | - connections/bd_prod/username 21 | - connections/bd_prod/password 22 | - connections/bd_prod/sslmode 23 | - connections/bd_prod/saveUsername 24 | - connections/bd_prod/savePassword 25 | - connections/bd_prod/publicOnly 26 | - connections/bd_prod/dontResolveType 27 | - connections/bd_prod/geometryColumnsOnly 28 | - connections/bd_test/service 29 | - connections/bd_test/host 30 | - connections/bd_test/port 31 | - connections/bd_test/database 32 | - connections/bd_test/username 33 | - connections/bd_test/password 34 | - connections/bd_test/sslmode 35 | - connections/bd_test/saveUsername 36 | - connections/bd_test/savePassword 37 | - connections/bd_test/publicOnly 38 | - connections/bd_test/dontResolveType 39 | - connections/bd_test/geometryColumnsOnly 40 | PythonPlugins: 41 | - GdalTools 42 | - db_manager 43 | - processing 44 | - geometrycheckerplugin 45 | - SpreadsheetLayers 46 | - menu_from_project 47 | - redLayer 48 | - coordinator 49 | - french_locator_filter 50 | - mask 51 | - qNote 52 | menu_from_project: 53 | - is_setup_visible 54 | - optionTooltip 55 | - optionCreateGroup 56 | - optionLoadAll 57 | - projects/size 58 | - projects/1/file 59 | - projects/1/name 60 | - projects/1/location -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-custom/qgis_global_settings.ini: -------------------------------------------------------------------------------- 1 | [qgis] 2 | checkVersion=false 3 | defaultProjectFileFormat=Qgs 4 | dataSourceManagerNonModal=true 5 | parallel_rendering=true 6 | max_threads=3 7 | compileExpressions=true 8 | projOpenAtLaunch=0 9 | projOpenAtLaunchPath=//some-server/sit$/QGIS/custom/startup_project.qgs 10 | projectTemplateDir=//some-server/sit$/QGIS/custom/project_templates 11 | networkAndProxy\networkTimeout=30000 12 | networkAndProxy\userAgent=QGIS 13 | digitizing\default_snap_enabled=true 14 | # Default snapping tolerance (distance) 15 | digitizing\default_snapping_tolerance=12.0 16 | # Default snap to type 17 | # Vertex, VertexAndSegment, Segment 18 | digitizing\default_snap_type=Vertex 19 | # Default snapping unit 20 | # LayerUnits, Pixels, ProjectUnits 21 | digitizing\default_snapping_tolerance_unit=Pixels 22 | digitizing\snap_invisible_feature=false 23 | connections-xyz\OpenStreetMap\authcfg= 24 | connections-xyz\OpenStreetMap\password= 25 | connections-xyz\OpenStreetMap\referer= 26 | connections-xyz\OpenStreetMap\url=https://tile.openstreetmap.org/{z}/{x}/{y}.png 27 | connections-xyz\OpenStreetMap\username= 28 | connections-xyz\OpenStreetMap\zmax=19 29 | connections-xyz\OpenStreetMap\zmin=0 30 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\ignoreGetMapURI=false 31 | customEnvVarsUse=false 32 | iconSize=24 33 | connections-wms\CRAIG%20ortho%20membres\invertAxisOrientation=false 34 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\ignoreGetFeatureInfoURI=false 35 | customEnvVars=@Invalid() 36 | connections-wms\CRAIG%20ortho%20membres\ignoreReportedLayerExtents=false 37 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\ignoreAxisOrientation=false 38 | connections-wms\CRAIG%20ortho%20membres\ignoreGetMapURI=false 39 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\invertAxisOrientation=false 40 | connections-wms\CRAIG%20ortho%20membres\smoothPixmapTransform=false 41 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\referer= 42 | connections-wms\CRAIG%20ortho%20membres\dpiMode=7 43 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\smoothPixmapTransform=false 44 | connections-wms\CRAIG%20ortho%20membres\referer= 45 | connections-wms\%5BCRAIG%5D%20Mod%E8les%20Num%E9riques%20de%20Terrain%20%27tuil%E9%27%3A%20ombrage%2C%20couleur%2C%20courbes%20de%20niveau\dpiMode=7 46 | 47 | [proxy] 48 | proxyEnabled=true 49 | proxyType=DefaultProxy 50 | 51 | [PostgreSQL] 52 | connections\selected=bd_prod 53 | 54 | connections\bd_prod\allowGeometrylessTables=true 55 | connections\bd_prod\authcfg= 56 | connections\bd_prod\dontResolveType=false 57 | connections\bd_prod\estimatedMetadata=true 58 | connections\bd_prod\geometryColumnsOnly=false 59 | connections\bd_prod\projectsInDatabase=true 60 | connections\bd_prod\publicOnly=false 61 | connections\bd_prod\service=bd_prod 62 | connections\bd_prod\sslmode=SslPrefer 63 | 64 | connections\bd_test\allowGeometrylessTables=true 65 | connections\bd_test\authcfg= 66 | connections\bd_test\dontResolveType=false 67 | connections\bd_test\estimatedMetadata=true 68 | connections\bd_test\geometryColumnsOnly=false 69 | connections\bd_test\projectsInDatabase=true 70 | connections\bd_test\publicOnly=false 71 | connections\bd_test\service=bd_test 72 | connections\bd_test\sslmode=SslPrefer 73 | 74 | [PythonPlugins] 75 | GdalTools=true 76 | db_manager=true 77 | processing=true 78 | MetaSearch=false 79 | geometrycheckerplugin=true 80 | topolplugin=true 81 | SpreadsheetLayers=true 82 | menu_from_project=true 83 | redLayer=true 84 | coordinator=true 85 | french_locator_filter=true 86 | mask=true 87 | qNote=true 88 | 89 | [app] 90 | projections\defaultProjectCrs=EPSG:3945 91 | projections\newProjectCrsBehavior=UsePresetCrs 92 | projections\unknownCrsBehavior=PromptUserForCrs 93 | 94 | [Projections] 95 | layerDefaultCrs=EPSG:3945 96 | 97 | [svg] 98 | searchPathsForSVG=//some-server/sit$/QGIS/custom/svg 99 | 100 | [Map] 101 | searchRadiusMM=3 102 | 103 | [core] 104 | Layout\searchPathsForTemplates=//some-server/sit$/QGIS/custom/composer_templates 105 | 106 | [gui] 107 | LayoutDesigner\defaultFont=Calibri 108 | locator_filters\enabled_optionpages=false 109 | locator_filters\enabled_layouts=false 110 | locator_filters\enabled_actions=false 111 | locator_filters\default_edit_features=false 112 | locator_filters\default_optionpages=false 113 | locator_filters\default_layouts=false 114 | locator_filters\default_calculator=true 115 | locator_filters\default_features=true 116 | 117 | 118 | [variables] 119 | organisation=Grenoble Alpes M\xe9tropole 120 | 121 | 122 | [cache] 123 | size=@Variant(\0\0\0\x81\0\0\0\0\0\xea`\0) 124 | 125 | 126 | [menu_from_project] 127 | is_setup_visible=true 128 | optionTooltip=true 129 | optionCreateGroup=false 130 | optionLoadAll=true 131 | projects\size=1 132 | projects\1\file=//some-server/sit$/QGIS/custom/socle_data_central.qgs 133 | projects\1\name=Donn\xe9\x65s de r\xe9\x66\xe9rence 134 | projects\1\location=new 135 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | **Version 1.0.1** 4 | 5 | * Add sheet name in default layer name. 6 | * Handle non ascii characters in sheet names. 7 | * Dynamically load .ui files. 8 | * Handle non ascii characters in file paths. 9 | * Add sheet name in .vrt filename to support multiple worksheets. 10 | * Add russian translation file. 11 | 12 | **Version 1.0** 13 | 14 | * Add changelog file. 15 | * Add checkbox for end of file detection. 16 | * Force encoding to UTF-8 before adding layer to layer tree. 17 | * Fix column format selectors line position. 18 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/README.rst: -------------------------------------------------------------------------------- 1 | .. SpreadsheetLayers documentation master file, created by 2 | sphinx-quickstart on Thu Jan 15 15:15:55 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | QGIS-SpreadSheetLayers 7 | ====================== 8 | 9 | QGIS plugin to load layers from spreadsheet files (\*.ods, \*.xls, \*.xlsx) 10 | 11 | Description 12 | ----------- 13 | 14 | This plugin adds a *Add spreadsheet layer* entry in *Layer* / *Add new Layer* 15 | menu and a corresponding button in *Layers* toolbar. These two links open the 16 | same dialog to load a layer from a spreadsheet file with some options: 17 | 18 | * select file 19 | * layer name 20 | * sheet selection 21 | * header at first line 22 | * ignore some rows 23 | * load geometry from x and y fields 24 | 25 | When dialog is accepted, it creates a new GDAL VRT file in same folder as the 26 | source data file and layer name, expanded with a *.vrt* suffix, which is 27 | loaded into QGIS. 28 | 29 | When reusing the same file twice, the dialog loads its values from the 30 | existing *.vrt* file. 31 | 32 | Limitations 33 | ----------- 34 | 35 | Due to a GDAL/OGR lacks of functionalities: 36 | 37 | - use of header line on a per file basis ; 38 | - ignore lines at the beginning of file ; 39 | - correct end of .xls files detection. 40 | 41 | The plugin use an SQLITE select statement with offset and limit parameters 42 | to extract corresponding data from the source file. When one of this 43 | functionalities is in use, this could have some side effects. 44 | 45 | With GDAL <= 1.11.1, the plugin can't load geometry. With graceful 46 | degradation, geometry checkbox is then locked. To get the GDAL version in use, 47 | run this commands in QGIS python console: 48 | 49 | .. code:: 50 | 51 | import osgeo.gdal 52 | print osgeo.gdal.__version__ 53 | 54 | When opening a spreadsheet file, GDAL/OGR will try to detect the data type of 55 | columns (Date, Integer, Real, String, ...). This automatic detection occurs 56 | outside of plugin header and ignore lines functionalities, so when using this, 57 | GDAL/OGR should be unable to correctly detect data types. 58 | 59 | Configuration 60 | ------------- 61 | 62 | GDAL do not allow to define the presence of header line on a per layer basis, 63 | this choice is made through environment variables for each driver 64 | *OGR_ODS_HEADERS*, *OGR_XLS_HEADERS* and *OGR_XLSX_HEADERS*, 65 | with tree possible values *FORCE*, *DISABLE* and *AUTO*. 66 | For more details, consult the corresponding drivers documentation ie: 67 | http://www.gdal.org/drv_ods.html, http://www.gdal.org/drv_xls.html 68 | and http://www.gdal.org/drv_xlsx.html. 69 | 70 | You can change this values in QGIS settings: 71 | 72 | - open *Settings* / *Options* dialog; 73 | - select *System* tab, and go to *Environment* section; 74 | - check *Use custom variables*. 75 | - add a new line. Example: 76 | 77 | *Overwrite* | *OGR_ODS_HEADERS* | *FORCE* 78 | 79 | - restart QGIS to take this into consideration. 80 | 81 | Development install (linux) 82 | --------------------------- 83 | 84 | .. code:: 85 | 86 | git clone git@github.com:camptocamp/QGIS-SpreadSheetLayers.git SpreadsheetLayers 87 | ln -s SpreadsheetLayers ~/.qgis2/python/plugins/ 88 | cd SpreadsheetLayers 89 | make 90 | 91 | - run QGIS and activate SpreadsheetLayers plugin. 92 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/SpreadsheetLayersPlugin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /*************************************************************************** 4 | SpreadsheetLayersPlugin 5 | A QGIS plugin 6 | Load layers from MS Excel and OpenOffice spreadsheets 7 | ------------------- 8 | begin : 2014-10-30 9 | git sha : $Format:%H$ 10 | copyright : (C) 2014 by Camptocamp 11 | email : info@camptocamp.com 12 | ***************************************************************************/ 13 | 14 | /*************************************************************************** 15 | * * 16 | * This program is free software; you can redistribute it and/or modify * 17 | * it under the terms of the GNU General Public License as published by * 18 | * the Free Software Foundation; either version 2 of the License, or * 19 | * (at your option) any later version. * 20 | * * 21 | ***************************************************************************/ 22 | """ 23 | from __future__ import print_function 24 | import os.path 25 | from qgis.core import Qgis, QgsVectorLayer, QgsProject 26 | from qgis.PyQt import QtCore, QtGui, QtWidgets 27 | # Initialize Qt resources from file resources.py 28 | from .ui import resources_rc 29 | # Import the code for the dialog 30 | from .widgets.SpreadsheetLayersDialog import SpreadsheetLayersDialog 31 | 32 | 33 | class SpreadsheetLayersPlugin(QtCore.QObject): 34 | """QGIS Plugin Implementation.""" 35 | 36 | def __init__(self, iface): 37 | """Constructor. 38 | 39 | :param iface: An interface instance that will be passed to this class 40 | which provides the hook by which you can manipulate the QGIS 41 | application at run time. 42 | :type iface: QgsInterface 43 | """ 44 | super(SpreadsheetLayersPlugin, self).__init__() 45 | # Save reference to the QGIS interface 46 | self.iface = iface 47 | # initialize plugin directory 48 | self.plugin_dir = os.path.dirname(__file__) 49 | # initialize locale 50 | locale = QtCore.QSettings().value('locale/userLocale')[0:2] 51 | locale_path = os.path.join( 52 | self.plugin_dir, 53 | 'i18n', 54 | 'SpreadsheetLayers_{}.qm'.format(locale)) 55 | 56 | if os.path.exists(locale_path): 57 | self.translator = QtCore.QTranslator() 58 | self.translator.load(locale_path) 59 | 60 | if QtCore.qVersion() > '4.3.3': 61 | QtCore.QCoreApplication.installTranslator(self.translator) 62 | 63 | def initGui(self): 64 | self.action = QtWidgets.QAction( 65 | QtGui.QIcon(':/plugins/SpreadsheetLayers/icon/mActionAddSpreadsheetLayer.svg'), 66 | self.tr("Add spreadsheet layer"), 67 | self) 68 | self.action.triggered.connect(self.showDialog) 69 | if Qgis.QGIS_VERSION_INT > 20400: 70 | self.iface.addLayerMenu().addAction(self.action) 71 | else: 72 | menu = self.iface.layerMenu() 73 | for action in menu.actions(): 74 | if action.isSeparator(): 75 | break 76 | self.iface.layerMenu().insertAction(action, self.action) 77 | self.iface.layerToolBar().addAction(self.action) 78 | 79 | def unload(self): 80 | if hasattr(self, 'action'): 81 | if Qgis.QGIS_VERSION_INT > 20400: 82 | self.iface.addLayerMenu().removeAction(self.action) 83 | else: 84 | self.iface.layerMenu().removeAction(self.action) 85 | self.iface.layerToolBar().removeAction(self.action) 86 | 87 | def showDialog(self): 88 | dlg = SpreadsheetLayersDialog(self.iface.mainWindow()) 89 | dlg.show() 90 | if dlg.exec_(): 91 | layer = QgsVectorLayer(dlg.vrtPath(), dlg.layerName(), 'ogr') 92 | layer.setProviderEncoding('UTF-8') 93 | if not layer.isValid(): 94 | # fix_print_with_import 95 | print("Layer failed to load") 96 | else: 97 | QgsProject.instance().addMapLayer(layer) 98 | dlg.deleteLater() 99 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /*************************************************************************** 4 | SpreadsheetLayersPlugin 5 | A QGIS plugin 6 | Load layers from MS Excel and OpenOffice spreadsheets 7 | ------------------- 8 | begin : 2014-10-30 9 | copyright : (C) 2014 by Camptocamp 10 | email : info@camptocamp.com 11 | git sha : $Format:%H$ 12 | ***************************************************************************/ 13 | 14 | /*************************************************************************** 15 | * * 16 | * This program is free software; you can redistribute it and/or modify * 17 | * it under the terms of the GNU General Public License as published by * 18 | * the Free Software Foundation; either version 2 of the License, or * 19 | * (at your option) any later version. * 20 | * * 21 | ***************************************************************************/ 22 | This script initializes the plugin, making it known to QGIS. 23 | """ 24 | 25 | 26 | # noinspection PyPep8Naming 27 | def classFactory(iface): # pylint: disable=invalid-name 28 | """Load SpreadsheetLayersPlugin class from file SpreadsheetLayersPlugin. 29 | 30 | :param iface: A QGIS interface instance. 31 | :type iface: QgsInterface 32 | """ 33 | # 34 | from .SpreadsheetLayersPlugin import SpreadsheetLayersPlugin 35 | return SpreadsheetLayersPlugin(iface) 36 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/help/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .doctrees 3 | *.pot 4 | *.mo 5 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/help/source/index.rst: -------------------------------------------------------------------------------- 1 | .. SpreadsheetLayers documentation master file, created by 2 | sphinx-quickstart on Thu Jan 15 15:15:55 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | .. include:: ../../README.rst 7 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/i18n/.gitignore: -------------------------------------------------------------------------------- 1 | *.qm 2 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. Since 2 | # version 2.0 of QGIS this is the proper way to supply 3 | # information about a plugin. The old method of 4 | # embedding metadata in __init__.py will 5 | # is no longer supported since version 2.0. 6 | 7 | # This file should be included when you package your plugin. 8 | 9 | # Mandatory items: 10 | 11 | [general] 12 | name=Spreadsheet Layers 13 | qgisMinimumVersion=3.0 14 | description=Load layers from spreadsheet files (*.ods, *.xls, *.xlsx) 15 | about=This plugin adds a "Add spreadsheet layer" entry in "Layer" / "Add new Layer" menu and a corresponding button in the "Layers" toolbar. 16 | These two links open the same dialog to load a layer from a spreadsheet file (*.ods, *.xls, *.xlsx) with some options (use header at first line, ignore some rows and optionally load geometry from x and y fields). 17 | When this dialog is accepted, it creates a new GDAL VRT file in same folder as the source data file and layer name, expanded with a .vrt suffix which is loaded into QGIS using OGR VRT driver. 18 | When reusing the same file twice, the dialog loads its values from the existing .vrt file. 19 | No need to install additional dependencies. 20 | version=2.0.1 21 | author=Camptocamp 22 | email=info@camptocamp.com 23 | 24 | # End of mandatory metadata 25 | 26 | # Optional items: 27 | 28 | # Uncomment the following line and add your changelog: 29 | # changelog= 30 | 31 | # Tags are comma separated with spaces allowed 32 | tags=spreadsheet,ods,xls,xlsx,calc,excel 33 | 34 | homepage=https://github.com/camptocamp/QGIS-SpreadSheetLayers 35 | tracker=https://github.com/camptocamp/QGIS-SpreadSheetLayers/issues 36 | repository=https://github.com/camptocamp/QGIS-SpreadSheetLayers 37 | icon=resources/icon/mActionAddSpreadsheetLayer.svg 38 | # experimental flag 39 | experimental=False 40 | 41 | # deprecated flag (applies to the whole plugin, not just a single version) 42 | deprecated=False 43 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/plugin_upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """This script uploads a plugin package to the plugin repository. 3 | Authors: A. Pasotti, V. Picavet 4 | git sha : $TemplateVCSFormat 5 | """ 6 | 7 | import os 8 | import sys 9 | import getpass 10 | import xmlrpc.client 11 | from optparse import OptionParser 12 | 13 | # Configuration 14 | PROTOCOL = 'https' 15 | SERVER = 'plugins.qgis.org' 16 | PORT = '443' 17 | ENDPOINT = '/plugins/RPC2/' 18 | VERBOSE = False 19 | 20 | 21 | def main(parameters, arguments): 22 | """Main entry point. 23 | 24 | :param parameters: Command line parameters. 25 | :param arguments: Command line arguments. 26 | """ 27 | address = "{protocol}://{username}:{password}@{server}:{port}{endpoint}".format( 28 | protocol=PROTOCOL, 29 | username=parameters.username, 30 | password=parameters.password, 31 | server=parameters.server, 32 | port=parameters.port, 33 | endpoint=ENDPOINT) 34 | print("Connecting to: %s" % hide_password(address)) 35 | 36 | server = xmlrpc.client.ServerProxy(address, verbose=VERBOSE) 37 | 38 | try: 39 | with open(arguments[0], 'rb') as handle: 40 | plugin_id, version_id = server.plugin.upload( 41 | xmlrpc.client.Binary(handle.read())) 42 | print("Plugin ID: %s" % plugin_id) 43 | print("Version ID: %s" % version_id) 44 | except xmlrpc.client.ProtocolError as err: 45 | print("A protocol error occurred") 46 | print("URL: %s" % hide_password(err.url, 0)) 47 | print("HTTP/HTTPS headers: %s" % err.headers) 48 | print("Error code: %d" % err.errcode) 49 | print("Error message: %s" % err.errmsg) 50 | except xmlrpc.client.Fault as err: 51 | print("A fault occurred") 52 | print("Fault code: %d" % err.faultCode) 53 | print("Fault string: %s" % err.faultString) 54 | 55 | 56 | def hide_password(url, start=6): 57 | """Returns the http url with password part replaced with '*'. 58 | 59 | :param url: URL to upload the plugin to. 60 | :type url: str 61 | 62 | :param start: Position of start of password. 63 | :type start: int 64 | """ 65 | start_position = url.find(':', start) + 1 66 | end_position = url.find('@') 67 | return "%s%s%s" % ( 68 | url[:start_position], 69 | '*' * (end_position - start_position), 70 | url[end_position:]) 71 | 72 | 73 | if __name__ == "__main__": 74 | parser = OptionParser(usage="%prog [options] plugin.zip") 75 | parser.add_option( 76 | "-w", "--password", dest="password", 77 | help="Password for plugin site. " 78 | "You can use environment variable 'PLUGIN_UPLOAD_PASSWORD', " 79 | "or the password will be prompted on runtime.", metavar="******") 80 | parser.add_option( 81 | "-u", "--username", dest="username", 82 | help="Username of plugin site. " 83 | "You can use environment variable 'PLUGIN_UPLOAD_USERNAME', " 84 | "or the username will be prompted on runtime.", metavar="user") 85 | parser.add_option( 86 | "-p", "--port", dest="port", 87 | help="Server port to connect to", metavar="80") 88 | parser.add_option( 89 | "-s", "--server", dest="server", 90 | help="Specify server name", metavar="plugins.qgis.org") 91 | options, args = parser.parse_args() 92 | if len(args) != 1: 93 | print("Please specify zip file.\n") 94 | parser.print_help() 95 | sys.exit(1) 96 | if not options.server: 97 | options.server = SERVER 98 | if not options.port: 99 | options.port = PORT 100 | if not options.username: 101 | username = os.environ.get('PLUGIN_UPLOAD_USERNAME') 102 | if username: 103 | # environment variable 104 | options.username = username 105 | else: 106 | # interactive mode 107 | username = getpass.getuser() 108 | print("Please enter user name [%s] :" % username, end=' ') 109 | 110 | res = input() 111 | if res != "": 112 | options.username = res 113 | else: 114 | options.username = username 115 | if not options.password: 116 | password = os.environ.get('PLUGIN_UPLOAD_PASSWORD') 117 | if password: 118 | # environment variable 119 | options.password = password 120 | else: 121 | # interactive mode 122 | options.password = getpass.getpass() 123 | main(options, args) 124 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-intl 3 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/resources/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icon/mActionAddSpreadsheetLayer.svg 4 | 5 | 6 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/ui/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/util/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/util/gdal_util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import tempfile 5 | from osgeo import ogr 6 | 7 | def testGdal(): 8 | # Inspired from gdal test ogr_vrt_34 9 | # https://github.com/OSGeo/gdal/commit/82074ed5bd67d2efbfbcea50c5416856d9c5826d 10 | path = os.path.join(tempfile.gettempdir(), 'gdal_test.csv') 11 | f = open(path, 'wb') 12 | f.write('x,y\n'.encode('ascii')) 13 | f.write('2,49\n'.encode('ascii')) 14 | f.close() 15 | 16 | vrt_xml = """ 17 | 18 | 19 | """+path+""" 20 | SELECT * FROM gdal_test 21 | 22 | 23 | 24 | 25 | """ 26 | 27 | ds = ogr.Open( vrt_xml ) 28 | 29 | lyr = ds.GetLayer(0) 30 | lyr.SetIgnoredFields(['x', 'y']) 31 | f = lyr.GetNextFeature() 32 | result = True 33 | if f is None: 34 | result = False 35 | elif f.GetGeometryRef().ExportToWkt() != 'POINT (2 49)': 36 | result = False 37 | 38 | f = None 39 | lyr = None 40 | ds = None 41 | os.unlink(path) 42 | 43 | return result 44 | 45 | GDAL_COMPAT = testGdal() 46 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/SpreadsheetLayers/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /*************************************************************************** 4 | Coordinator 5 | A QGIS plugin 6 | Plugin to handle coordinate tasks better 7 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ 8 | ------------------- 9 | begin : 2019-05-04 10 | copyright : (C) 2019 by Jonas K�pper 11 | email : qgis@ag99.de 12 | git sha : $Format:%H$ 13 | ***************************************************************************/ 14 | 15 | /*************************************************************************** 16 | * * 17 | * This program is free software; you can redistribute it and/or modify * 18 | * it under the terms of the GNU General Public License as published by * 19 | * the Free Software Foundation; either version 2 of the License, or * 20 | * (at your option) any later version. * 21 | * * 22 | ***************************************************************************/ 23 | This script initializes the plugin, making it known to QGIS. 24 | """ 25 | from qgis.core import QgsMessageLog 26 | 27 | # noinspection PyPep8Naming 28 | def classFactory(iface): # pylint: disable=invalid-name 29 | """Load Coordinator class from file Coordinator. 30 | 31 | :param iface: A QGIS interface instance. 32 | :type iface: QgsInterface 33 | """ 34 | # 35 | from .coordinator import Coordinator 36 | #QgsMessageLog.logMessage("!!", "Coordinator") 37 | return Coordinator(iface) -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/funcs.py: -------------------------------------------------------------------------------- 1 | from math import floor 2 | 3 | from PyQt5.Qt import QLocale, QCoreApplication 4 | 5 | from qgis.core import QgsMessageLog 6 | 7 | def coordinatorDmsStringsToDecimal(deg, minute, sec): 8 | result = 0.0 9 | if(len(deg)>0): result += QLocale().toFloat(deg)[0] 10 | if(len(minute)>0): result += QLocale().toFloat(minute)[0]/60 11 | if(len(sec)>0): result += QLocale().toFloat(sec)[0]/3600 12 | return result 13 | 14 | def coordinatorDecimalToDms(deg): 15 | isNegative = deg < 0 16 | degree = int(floor(abs(deg))) 17 | deg2 = abs(deg)-degree 18 | minute = int(floor(deg2 * 60)) 19 | seconds = ( deg2 % (1/60) ) * 3600 20 | 21 | return (isNegative, degree, minute, seconds) 22 | 23 | 24 | def coordinatorLog(message): 25 | QgsMessageLog.logMessage(message, "Coordinator") 26 | 27 | class CoordinatorTranslator: 28 | # noinspection PyMethodMayBeStatic 29 | def tr(message, disambugation = None): 30 | """Get the translation for a string using Qt translation API. 31 | 32 | We implement this ourselves since we do not inherit QObject. 33 | 34 | :param message: String for translation. 35 | :type message: str, QString 36 | :param disambugation: an identifying string, for when the same sourceText is used in different roles within the same context 37 | :type disambugation: str, QString 38 | 39 | :returns: Translated version of message. 40 | :rtype: QString 41 | """ 42 | # noinspection PyTypeChecker,PyArgumentList,PyCallByClass 43 | return QCoreApplication.translate('CT', message, disambugation) 44 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/help.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Calibri, Arial, sans-serif 3 | } -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/capture.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/capture.gif -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_basics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_basics.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_capture.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_copy.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_digitize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_digitize.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_labels.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_labels.ai -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_main.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_maptools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/help/images/screen_maptools.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/i18n/coordinator_de.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/i18n/coordinator_de.qm -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/i18n/coordinator_fr.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/coordinator/i18n/coordinator_fr.qm -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/metadata.txt: -------------------------------------------------------------------------------- 1 | # This file should be included when you package your plugin.# Mandatory items: 2 | 3 | [general] 4 | name=Coordinator 5 | qgisMinimumVersion=3.4 6 | description=Capture, transform and use coordinates 7 | version=0.4 8 | author=Jonas Küpper 9 | email=qgis@geograffr.eu 10 | 11 | about=The purpose of this plugin is to make handling of coordinate IO easier and includes a transformation tool and supports creation of simple features. 12 | This plugin overlaps in different ways with the purpose of the plugins Coordinate Capture, Lat Lon Tools and the Advanced Digitize Panel. It however aims to integrate in a clean and simple interface multiple tasks these tools are sometimes used together. And yes...: Its almost as it's just another coordinate tool. :) 13 | The two main functions of this plugin are: 14 | (A) a simple and easy to use coordinate transformation tool with an integrated picker and 15 | (B) a quick to use coordinate digitizer with support for coordinates in an arbitrary CRS independent of project or layer CRS. 16 | Both of these functions are seamlessly integrated and are implemented as a single, unique operation. 17 | 18 | tracker=https://github.com/iona5/coordinator/issues 19 | repository=https://github.com/iona5/coordinator 20 | # End of mandatory metadata 21 | 22 | # Recommended items: 23 | 24 | # Uncomment the following line and add your changelog: 25 | changelog=0.4 26 | - fix capture with wrong coordinate system with Point geometry 27 | - ensure a valid CRS is selected when changing through QgsProjectionSelectionDialog (issue #5) 28 | 0.3.2 29 | - metadata fix 30 | 0.3.1 31 | - "add Feature"-button should be disabled when selecting non editing tool 32 | - pull request 16: use default values when capturing points (thanks @AlexanderFinkbeiner) 33 | 0.3 34 | - issue #2: make sure capture tool is deselected when user selects another tool 35 | - issue #12: negative coordinates in geodetic systems were not properly processed 36 | - digitize helper announced feature addition without actually knowing if it succeeded 37 | - various translation issus (including issues #7, #8) 38 | - internal bugfixes regarding stability and test regime 39 | 0.2 40 | - added french translation by SebastienPeillet 41 | - fix issue #3: switching to edit mode in QGIS compiled with Qt < 5.11 failed 42 | - fix issue #1: locked CRS does not change when CRS of selected layer changes 43 | - enhanced test suite 44 | - build improvements 45 | - help improvements 46 | - general cleanup 47 | 0.1 - Initial release 48 | 49 | # Tags are comma separated with spaces allowed 50 | tags=python,coordinate,coordinates,transformation,digitizing,clipboard,capture 51 | 52 | homepage=https://github.com/iona5/coordinator 53 | category=Plugins 54 | icon=icons/marker.svg 55 | # experimental flag 56 | experimental=True 57 | 58 | # deprecated flag (applies to the whole plugin, not just a single version) 59 | deprecated=False 60 | 61 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/help.svg 4 | icons/warning.svg 5 | icons/addToCanvas.svg 6 | icons/capture.svg 7 | icons/clear.svg 8 | icons/copy.svg 9 | icons/locked.svg 10 | icons/marker.svg 11 | icons/panMap.svg 12 | icons/unlocked.svg 13 | 14 | 15 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/__init__.py: -------------------------------------------------------------------------------- 1 | # import qgis libs so that ve set the correct sip api version 2 | import os, sys, qgis # pylint: disable=W0611 # NOQA 3 | from PyQt5.Qt import QLocale 4 | from qgis.testing import unittest 5 | from qgis.core import QgsProject, QgsVectorLayer 6 | 7 | def run_all(): 8 | loader = unittest.TestLoader() 9 | 10 | start_dir = os.path.dirname(__file__) 11 | suite = loader.discover(start_dir) 12 | 13 | runner = unittest.TextTestRunner(verbosity = 3, stream=sys.stdout) 14 | runner.run(suite) 15 | 16 | class CoordinatorTestCase(unittest.TestCase): 17 | 18 | def __init__(self, testCase): 19 | super(unittest.TestCase, self).__init__(testCase) 20 | self.project = None 21 | 22 | self._addedLayers = [] 23 | 24 | 25 | def setUp(self): 26 | self.project = QgsProject.instance() 27 | 28 | 29 | def tearDown(self): 30 | while len(self._addedLayers) > 0: 31 | layerName = self._addedLayers.pop() 32 | layers = self.project.mapLayersByName(layerName) 33 | self.project.removeMapLayers([layer.id() for layer in layers]) 34 | 35 | 36 | def addMapLayer(self, mapLayer): 37 | self.project.addMapLayer(mapLayer, True) 38 | self._addedLayers.append(mapLayer.name()) 39 | 40 | 41 | def addVectorLayerFile(self, vectorLayerFile, vectorLayerName): 42 | vectorLayer = QgsVectorLayer(vectorLayerFile, vectorLayerName, "ogr") 43 | self.addMapLayer(vectorLayer) 44 | return vectorLayer 45 | 46 | 47 | def addEuropeLayer(self): 48 | return self.addVectorLayerFile(os.path.join(os.path.dirname(__file__), "data/europe.geojson" ), "europe") 49 | 50 | 51 | def assertTextFieldCloseTo(self, expected, textField, tolerance = 1, msg = None): 52 | textFieldValue = QLocale().toFloat(textField.text())[0] 53 | 54 | result = ( (expected - tolerance) <= textFieldValue <= (expected + tolerance) ) 55 | 56 | if(not result): 57 | if msg == None: 58 | msg = "value '%f' of QTextField is not close to %f±%f)" % (textFieldValue, expected, tolerance) 59 | 60 | raise AssertionError(msg) 61 | 62 | 63 | def assertTextFieldBetween(self, lower, upper, textField, msg = None): 64 | textFieldValue = QLocale().toFloat(textField.text())[0] 65 | 66 | result = (lower < textFieldValue < upper) 67 | 68 | if msg == None: 69 | msg = "value '%f' of QTextField is not between %f and %f)" % (textFieldValue, lower, upper) 70 | 71 | self.assertTrue(result, msg) 72 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/__main__.py: -------------------------------------------------------------------------------- 1 | import unittest, sys, os 2 | 3 | from . import run_all 4 | 5 | if sys.platform == "win32" and 'QT_QPA_PLATFORM_PLUGIN_PATH' not in os.environ: 6 | if 'QT_PLUGIN_PATH' in os.environ: 7 | os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.environ['QT_PLUGIN_PATH'] 8 | else: 9 | if "OSGEO4W_ROOT" in os.environ: 10 | qtPluginPath = os.path.join(os.path.normpath(os.environ["OSGEO4W_ROOT"].strip()),'apps/qt5/plugins') 11 | os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = qtPluginPath 12 | else: 13 | print("Cannot set QT_QPA_PLATFORM") 14 | sys.exit(1) 15 | 16 | sys.path.append(os.path.join(os.path.dirname(__file__), "../..")) 17 | 18 | run_all() 19 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/data/tenbytenraster.asc: -------------------------------------------------------------------------------- 1 | NCOLS 10 2 | NROWS 10 3 | XLLCENTER 1535380.000000 4 | YLLCENTER 5083260.000000 5 | DX 10 6 | DY 10 7 | NODATA_VALUE -9999 8 | 0 1 2 3 4 5 6 7 8 9 9 | 0 1 2 3 4 5 6 7 8 9 10 | 0 1 2 3 4 5 6 7 8 9 11 | 0 1 2 3 4 5 6 7 8 9 12 | 0 1 2 3 4 5 6 7 8 9 13 | 0 1 2 3 4 5 6 7 8 9 14 | 0 1 2 3 4 5 6 7 8 9 15 | 0 1 2 3 4 5 6 7 8 9 16 | 0 1 2 3 4 5 6 7 8 9 17 | 0 1 2 3 4 5 6 7 8 9 18 | CRS 19 | NOTES 20 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/data/tenbytenraster.keywords: -------------------------------------------------------------------------------- 1 | title: Tenbytenraster 2 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/data/tenbytenraster.lic: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tim Sutton, Linfiniti Consulting CC 5 | 6 | 7 | 8 | tenbytenraster.asc 9 | 2700044251 10 | Yes 11 | Tim Sutton 12 | Tim Sutton (QGIS Source Tree) 13 | Tim Sutton 14 | This data is publicly available from QGIS Source Tree. The original 15 | file was created and contributed to QGIS by Tim Sutton. 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/data/tenbytenraster.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/data/tenbytenraster.qml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 0 26 | 27 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/test_init.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Tests QGIS plugin init.""" 3 | 4 | __author__ = 'Tim Sutton ' 5 | __revision__ = '$Format:%H$' 6 | __date__ = '17/10/2010' 7 | __license__ = "GPL" 8 | __copyright__ = 'Copyright 2012, Australia Indonesia Facility for ' 9 | __copyright__ += 'Disaster Reduction' 10 | 11 | import os 12 | import unittest 13 | import logging 14 | import configparser 15 | 16 | LOGGER = logging.getLogger('QGIS') 17 | 18 | 19 | class TestInit(unittest.TestCase): 20 | """Test that the plugin init is usable for QGIS. 21 | 22 | Based heavily on the validator class by Alessandro 23 | Passoti available here: 24 | 25 | http://github.com/qgis/qgis-django/blob/master/qgis-app/ 26 | plugins/validator.py 27 | 28 | """ 29 | 30 | def test_read_init(self): 31 | """Test that the plugin __init__ will validate on plugins.qgis.org.""" 32 | 33 | # You should update this list according to the latest in 34 | # https://github.com/qgis/qgis-django/blob/master/qgis-app/ 35 | # plugins/validator.py 36 | 37 | required_metadata = [ 38 | 'name', 39 | 'description', 40 | 'version', 41 | 'qgisMinimumVersion', 42 | 'email', 43 | 'author'] 44 | 45 | file_path = os.path.abspath(os.path.join( 46 | os.path.dirname(__file__), os.pardir, 47 | 'metadata.txt')) 48 | LOGGER.info(file_path) 49 | metadata = [] 50 | parser = configparser.ConfigParser() 51 | parser.optionxform = str 52 | parser.read(file_path) 53 | message = 'Cannot find a section named "general" in %s' % file_path 54 | assert parser.has_section('general'), message 55 | metadata.extend(parser.items('general')) 56 | 57 | for expectation in required_metadata: 58 | message = ('Cannot find metadata "%s" in metadata source (%s).' % ( 59 | expectation, file_path)) 60 | 61 | self.assertIn(expectation, dict(metadata), message) 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/test_qgis_environment.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Tests for QGIS functionality. 3 | 4 | 5 | .. note:: This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | """ 11 | __author__ = 'tim@linfiniti.com' 12 | __date__ = '20/01/2011' 13 | __copyright__ = ('Copyright 2012, Australia Indonesia Facility for ' 14 | 'Disaster Reduction') 15 | 16 | import os 17 | import unittest 18 | from qgis.core import ( 19 | QgsProviderRegistry, 20 | QgsCoordinateReferenceSystem, 21 | QgsRasterLayer) 22 | 23 | from coordinator.test.utilities import get_qgis_app 24 | QGIS_APP, IFACE, CANVAS = get_qgis_app() 25 | 26 | class QGISTest(unittest.TestCase): 27 | """Test the QGIS Environment""" 28 | 29 | def test_qgis_environment(self): 30 | """QGIS environment has the expected providers""" 31 | 32 | r = QgsProviderRegistry.instance() 33 | self.assertIn('gdal', r.providerList()) 34 | self.assertIn('ogr', r.providerList()) 35 | self.assertIn('postgres', r.providerList()) 36 | 37 | def test_projection(self): 38 | """Test that QGIS properly parses a wkt string. 39 | """ 40 | crs = QgsCoordinateReferenceSystem() 41 | wkt = ( 42 | 'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",' 43 | 'SPHEROID["WGS_1984",6378137.0,298.257223563]],' 44 | 'PRIMEM["Greenwich",0.0],UNIT["Degree",' 45 | '0.0174532925199433]]') 46 | 47 | self.assertTrue(crs.createFromWkt(wkt), "couldn't parse CRS") 48 | auth_id = crs.authid() 49 | expected_auth_id = 'EPSG:4326' 50 | self.assertEqual(auth_id, expected_auth_id) 51 | 52 | # now test for a loaded layer 53 | path = os.path.join(os.path.dirname(__file__), 'data/tenbytenraster.asc') 54 | title = 'TestRaster' 55 | layer = QgsRasterLayer(path, title) 56 | auth_id = layer.crs().authid() 57 | self.assertIn(auth_id, ("EPSG:4326", "OGC:CRS84") ) 58 | 59 | if __name__ == '__main__': 60 | unittest.main() 61 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/test_resources.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Resources test. 3 | 4 | .. note:: This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | """ 10 | 11 | __author__ = 'qgis@ag99.de' 12 | __date__ = '2019-05-04' 13 | __copyright__ = 'Copyright 2019, Jonas Küpper' 14 | 15 | import unittest 16 | 17 | from PyQt5.QtGui import QIcon 18 | 19 | 20 | 21 | class CoordinatorResourcesTest(unittest.TestCase): 22 | 23 | def setUp(self): 24 | """Runs before each test.""" 25 | pass 26 | 27 | def tearDown(self): 28 | """Runs after each test.""" 29 | pass 30 | 31 | def test_icon_png(self): 32 | path = ':/plugins/Coordinator/icon.png' 33 | icon = QIcon(path) 34 | self.assertFalse(icon.isNull()) 35 | 36 | if __name__ == "__main__": 37 | suite = unittest.makeSuite(CoordinatorResourcesTest) 38 | runner = unittest.TextTestRunner(verbosity=2) 39 | runner.run(suite) 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/test_translations.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Safe Translations Test. 3 | 4 | .. note:: This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | """ 10 | from coordinator.test.utilities import get_qgis_app 11 | 12 | __author__ = 'ismailsunni@yahoo.co.id' 13 | __date__ = '12/10/2011' 14 | __copyright__ = ('Copyright 2012, Australia Indonesia Facility for ' 15 | 'Disaster Reduction') 16 | import unittest 17 | import os 18 | 19 | from PyQt5.QtCore import QCoreApplication, QTranslator 20 | 21 | QGIS_APP, IFACE, CANVAS = get_qgis_app() 22 | 23 | 24 | class SafeTranslationsTest(unittest.TestCase): 25 | """Test translations work.""" 26 | 27 | translator = QTranslator() 28 | 29 | @classmethod 30 | def setUpClass(cls): 31 | super(SafeTranslationsTest, cls).setUpClass() 32 | parent_path = os.path.join(os.path.dirname(__file__), os.path.pardir) 33 | dir_path = os.path.abspath(parent_path) 34 | file_path = os.path.join(dir_path, 'i18n', 'coordinator_de.qm') 35 | SafeTranslationsTest.translator.load(file_path) 36 | 37 | 38 | def setUp(self): 39 | """Runs before each test.""" 40 | if 'LANG' in iter(os.environ.keys()): 41 | os.environ.__delitem__('LANG') 42 | 43 | 44 | def tearDown(self): 45 | """Runs after each test.""" 46 | if 'LANG' in iter(os.environ.keys()): 47 | os.environ.__delitem__('LANG') 48 | 49 | 50 | def test_qgis_translations(self): 51 | """Test that translations work.""" 52 | QCoreApplication.installTranslator(SafeTranslationsTest.translator) 53 | real_message = QCoreApplication.translate("CT", 'outside of map extent') 54 | self.assertEqual(real_message, 'außerhalb der Karte') 55 | 56 | 57 | if __name__ == "__main__": 58 | suite = unittest.makeSuite(SafeTranslationsTest) 59 | runner = unittest.TextTestRunner(verbosity=2) 60 | runner.run(suite) 61 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/coordinator/test/utilities.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Common functionality used by regression tests.""" 3 | 4 | import sys 5 | import logging 6 | from PyQt5.QtWidgets import QWidget 7 | from PyQt5.Qt import QMainWindow, QDialog, QWindow, QLocale 8 | from time import sleep 9 | from qgis.core import QgsCoordinateReferenceSystem 10 | from qgis.PyQt import sip 11 | 12 | 13 | LOGGER = logging.getLogger('QGIS') 14 | QGIS_APP = None # Static variable used to hold hand to running QGIS app 15 | CANVAS = None 16 | PARENT = None 17 | IFACE = None 18 | 19 | 20 | def get_qgis_app(): 21 | """ Start one QGIS application to test against. 22 | 23 | :returns: Handle to QGIS app, canvas, iface and parent. If there are any 24 | errors the tuple members will be returned as None. 25 | :rtype: (QgsApplication, CANVAS, IFACE, PARENT) 26 | 27 | If QGIS is already running the handle to that app will be returned. 28 | """ 29 | 30 | try: 31 | from PyQt5 import QtGui, QtCore 32 | from qgis.core import QgsApplication 33 | from qgis.gui import QgsMapCanvas 34 | import qgis.utils 35 | from .qgis_interface import QgisStubInterface 36 | except ImportError as error: 37 | print("Failed to import QGIS libs %s" % error) 38 | return None, None, None 39 | 40 | global QGIS_APP, IFACE, CANVAS, PARENT 41 | 42 | if CANVAS and sip.isdeleted(CANVAS): 43 | CANVAS = None 44 | IFACE = None 45 | 46 | if not IFACE or not CANVAS: 47 | if qgis.utils.iface: 48 | # we are probably running in the QGIS Applications Python console. 49 | # so we have all we need: 50 | IFACE = qgis.utils.iface 51 | CANVAS = IFACE.mapCanvas() 52 | QGIS_APP = QgsApplication.instance() 53 | PARENT = CANVAS.parentWidget() 54 | else: 55 | try: 56 | sysargsUtf8 = [sysarg.encode("utf-8") for sysarg in sys.argv] 57 | except AttributeError: 58 | sysargsUtf8 = [] 59 | QGIS_APP = QgsApplication(sysargsUtf8, True) 60 | QGIS_APP.initQgis() 61 | PARENT = QWidget() 62 | CANVAS = QgsMapCanvas(PARENT) 63 | CANVAS.resize(QtCore.QSize(400, 400)) 64 | CANVAS.setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:4326")) 65 | IFACE = QgisStubInterface(CANVAS) 66 | 67 | return QGIS_APP, IFACE, CANVAS 68 | 69 | 70 | DEC_POINT = QLocale().decimalPoint() 71 | GROUP_SEPARATOR = QLocale().groupSeparator() 72 | TRANSLATION = str.maketrans(".,", "%s%s" % (DEC_POINT, GROUP_SEPARATOR) ) 73 | 74 | def helperFormatCoordinates(coordinate): 75 | # if the locale does not use grouping, we need to remove the grouping 76 | # separator before translation: 77 | if QLocale.OmitGroupSeparator & QLocale().numberOptions(): 78 | coordinate = coordinate.replace(",", "") 79 | return coordinate.translate(TRANSLATION) 80 | 81 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/__about__.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | Metadata about the package to easily retrieve informations about it. 5 | See: https://packaging.python.org/guides/single-sourcing-package-version/ 6 | """ 7 | 8 | # ############################################################################ 9 | # ########## Libraries ############# 10 | # ################################## 11 | 12 | # standard library 13 | from configparser import ConfigParser 14 | from datetime import date 15 | from pathlib import Path 16 | 17 | # ############################################################################ 18 | # ########## Globals ############### 19 | # ################################## 20 | 21 | __all__ = [ 22 | "__author__", 23 | "__copyright__", 24 | "__email__", 25 | "__license__", 26 | "__summary__", 27 | "__title__", 28 | "__uri__", 29 | "__version__", 30 | ] 31 | 32 | DIR_PLUGIN_ROOT = Path(__file__).parent 33 | PLG_METADATA_FILE = DIR_PLUGIN_ROOT.resolve() / "metadata.txt" 34 | 35 | # ############################################################################ 36 | # ########## Functions ############# 37 | # ################################## 38 | 39 | 40 | def plugin_metadata_as_dict() -> dict: 41 | """Read plugin metadata.txt and returns it as a Python dict. 42 | 43 | Raises: 44 | IOError: if metadata.txt is not found 45 | 46 | Returns: 47 | dict: dict of dicts. 48 | """ 49 | config = ConfigParser() 50 | if PLG_METADATA_FILE.is_file(): 51 | config.read(PLG_METADATA_FILE.resolve(), encoding="UTF-8") 52 | return {s: dict(config.items(s)) for s in config.sections()} 53 | else: 54 | raise IOError("Plugin metadata.txt not found at: %s" % PLG_METADATA_FILE) 55 | 56 | 57 | # ############################################################################ 58 | # ########## Variables ############# 59 | # ################################## 60 | 61 | # store full metadata.txt as dict into a var 62 | __plugin_md__ = plugin_metadata_as_dict() 63 | 64 | __author__ = __plugin_md__.get("general").get("author") 65 | __copyright__ = "2014 - {0}, {1}".format(date.today().year, __author__) 66 | __email__ = __plugin_md__.get("general").get("email") 67 | __keywords__ = [ 68 | t.strip() for t in __plugin_md__.get("general").get("repository").split("tags") 69 | ] 70 | __license__ = "GPL-2.0" 71 | __summary__ = "{}\n{}".format( 72 | __plugin_md__.get("general").get("description"), 73 | __plugin_md__.get("general").get("about"), 74 | ) 75 | 76 | __title__ = __plugin_md__.get("general").get("name") 77 | __title_clean__ = "".join(e for e in __title__ if e.isalnum()) 78 | 79 | __uri_homepage__ = __plugin_md__.get("general").get("homepage") 80 | __uri_repository__ = __plugin_md__.get("general").get("repository") 81 | __uri_tracker__ = __plugin_md__.get("general").get("tracker") 82 | __uri__ = __uri_repository__ 83 | 84 | __version__ = __plugin_md__.get("general").get("version") 85 | __version_info__ = tuple( 86 | [ 87 | int(num) if num.isdigit() else num 88 | for num in __version__.replace("-", ".", 1).split(".") 89 | ] 90 | ) 91 | 92 | # ############################################################################# 93 | # ##### Main ####################### 94 | # ################################## 95 | if __name__ == "__main__": 96 | plugin_md = plugin_metadata_as_dict() 97 | assert isinstance(plugin_md, dict) 98 | assert plugin_md.get("general").get("name") == __title__ 99 | print("Plugin: " + __title__) 100 | print("Plugin (clean): " + __title_clean__) 101 | print("By: " + __author__) 102 | print("Version: " + __version__) 103 | print("Description: " + __summary__) 104 | print( 105 | "For: %s > QGIS > %s" 106 | % ( 107 | plugin_md.get("general").get("qgisminimumversion"), 108 | plugin_md.get("general").get("qgismaximumversion", "3.99"), 109 | ) 110 | ) 111 | print(__title_clean__) 112 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/__init__.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | 4 | def classFactory(iface): # pylint: disable=invalid-name 5 | """Load NominatimFilterPlugin class from file nominatimfilter. 6 | 7 | :param iface: A QGIS interface instance. 8 | :type iface: QgsInterface 9 | """ 10 | from .plugin_main import LocatorFilterPlugin 11 | 12 | return LocatorFilterPlugin(iface) 13 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/core/__init__.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | from .locator_filter import FrenchBanGeocoderLocatorFilter # noqa: F401 3 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/gui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/gui/__init__.py -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/gui/dlg_settings.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | Plugin settings dialog. 5 | """ 6 | 7 | # standard 8 | import logging 9 | from functools import partial 10 | from pathlib import Path 11 | 12 | # PyQGIS 13 | from qgis.gui import QgsOptionsPageWidget, QgsOptionsWidgetFactory 14 | from qgis.PyQt import uic 15 | from qgis.PyQt.Qt import QUrl 16 | from qgis.PyQt.QtCore import pyqtSignal 17 | from qgis.PyQt.QtGui import QDesktopServices, QIcon 18 | from qgis.PyQt.QtWidgets import QHBoxLayout, QWidget 19 | from qgis.utils import showPluginHelp 20 | 21 | # project 22 | from french_locator_filter.__about__ import ( 23 | DIR_PLUGIN_ROOT, 24 | __title__, 25 | __uri_tracker__, 26 | __version__, 27 | ) 28 | from french_locator_filter.toolbelt import PlgLogger, PlgOptionsManager 29 | 30 | # ############################################################################ 31 | # ########## Globals ############### 32 | # ################################## 33 | 34 | logger = logging.getLogger(__name__) 35 | FORM_CLASS, _ = uic.loadUiType( 36 | Path(__file__).parent / "{}.ui".format(Path(__file__).stem) 37 | ) 38 | 39 | # ############################################################################ 40 | # ########## Classes ############### 41 | # ################################## 42 | 43 | 44 | class DlgSettings(QWidget, FORM_CLASS): 45 | 46 | closingPlugin = pyqtSignal() 47 | 48 | def __init__(self, parent=None): 49 | """Constructor.""" 50 | super(DlgSettings, self).__init__(parent) 51 | self.setupUi(self) 52 | self.log = PlgLogger().log 53 | 54 | # header 55 | self.lbl_title.setText(f"{__title__} - Version {__version__}") 56 | 57 | # customization 58 | self.btn_help.setIcon(QIcon(":/images/themes/default/mActionHelpContents.svg")) 59 | self.btn_help.pressed.connect( 60 | partial(showPluginHelp, filename=f"{DIR_PLUGIN_ROOT}/resources/help/index") 61 | ) 62 | 63 | self.btn_report.setIcon( 64 | QIcon(":images/themes/default/console/iconSyntaxErrorConsole.svg") 65 | ) 66 | self.btn_report.pressed.connect( 67 | partial(QDesktopServices.openUrl, QUrl(__uri_tracker__)) 68 | ) 69 | 70 | # load previously saved settings 71 | self.plg_settings = PlgOptionsManager() 72 | self.load_settings() 73 | 74 | def closeEvent(self, event): 75 | """Map on plugin close. 76 | 77 | :param event: [description] 78 | :type event: [type] 79 | """ 80 | self.closingPlugin.emit() 81 | event.accept() 82 | 83 | def load_settings(self) -> dict: 84 | """Load options from QgsSettings into UI form.""" 85 | settings = self.plg_settings.get_plg_settings() 86 | 87 | # features 88 | self.lbl_url_path_value.setText(settings.request_url) 89 | self.lbl_url_query_value.setText(settings.request_url_query) 90 | self.lbl_http_content_type_value.setText(settings.http_content_type) 91 | self.lbl_http_user_agent_value.setText(settings.http_user_agent) 92 | self.sbx_min_search_length.setValue(settings.min_search_length) 93 | 94 | # misc 95 | self.opt_debug.setChecked(settings.debug_mode) 96 | self.lbl_version_saved_value.setText(settings.version) 97 | 98 | def save_settings(self): 99 | """Save options from UI form into QSettings.""" 100 | # save user settings 101 | self.plg_settings.set_value_from_key( 102 | "min_search_length", self.sbx_min_search_length.value() 103 | ) 104 | 105 | # save miscellaneous 106 | self.plg_settings.set_value_from_key("debug_mode", self.opt_debug.isChecked()) 107 | self.plg_settings.set_value_from_key("version", __version__) 108 | 109 | if __debug__: 110 | self.log( 111 | message="DEBUG - Settings successfully saved.", 112 | log_level=4, 113 | ) 114 | 115 | 116 | class PlgOptionsFactory(QgsOptionsWidgetFactory): 117 | def __init__(self): 118 | super().__init__() 119 | 120 | def icon(self): 121 | return QIcon(str(DIR_PLUGIN_ROOT / "resources/images/icon.svg")) 122 | 123 | def createWidget(self, parent): 124 | return ConfigOptionsPage(parent) 125 | 126 | def title(self): 127 | return __title__ 128 | 129 | 130 | class ConfigOptionsPage(QgsOptionsPageWidget): 131 | def __init__(self, parent): 132 | super().__init__(parent) 133 | self.dlg_settings = DlgSettings(self) 134 | layout = QHBoxLayout() 135 | layout.setContentsMargins(0, 0, 0, 0) 136 | self.dlg_settings.setLayout(layout) 137 | self.setLayout(layout) 138 | self.setObjectName("mOptionsPage{}".format(__title__)) 139 | 140 | def apply(self): 141 | """Called to permanently apply the settings shown in the options page (e.g. \ 142 | save them to QgsSettings objects). This is usually called when the options \ 143 | dialog is accepted.""" 144 | self.dlg_settings.save_settings() 145 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/metadata.txt: -------------------------------------------------------------------------------- 1 | [general] 2 | name=French Locator Filter 3 | about=The French geo.api is an open Geocoder service provided by French Government. 4 | A Locator Filter implements the fetching of data from internal or external sources. 5 | This plugin is forked from the work of Richard Duivenvoorde. Kudos Richard 6 | Read more: http://www.qgis.nl/2018/05/16/english-coding-a-qgslocator-plugin 7 | about[fr]=L'API du gouvernement français est un service de geocodage gratuit et ouvert base sur la base adresse nationale. Ce plugin ajoute un filtre de recherche sur ce service dans la barre de recherche universelle. 8 | 9 | category=Filter 10 | 11 | description=This is a plugin which adds a Locator Filter (Geocoder) based on the french API geo.api.gouv.fr/adresse to QGIS 12 | description[fr]=Extension activant la recherche d'adresse dans la barre de recherche universelle, basee sur l'API geo.api.gouv.fr/adresse 13 | Financement par les services de la gendarmerie Nationale. 14 | Ce plugin est basé sur le travail de Richard Duivenvoorde (merci Richard !). 15 | En savoir plus sur ce plugin http://www.qgis.nl/2018/05/16/english-coding-a-qgslocator-plugin 16 | 17 | icon=resources/images/icon.svg 18 | 19 | tags=geocoder, locator, filter, addok, France, french 20 | tags[fr]=geocodeur, recherche, adresse, France, ADDOK, Etalab, BAN, BANO 21 | 22 | # credits and contact 23 | author=Régis Haubourg (Oslandia), Richard Duivenvoorde, Zuidt, Julien Moura (Oslandia) 24 | email=qgis@oslandia.com 25 | homepage=https://oslandia.gitlab.io/qgis/french_locator_filter/ 26 | repository=https://gitlab.com/Oslandia/qgis/french_locator_filter/ 27 | tracker=https://gitlab.com/Oslandia/qgis/french_locator_filter/-/issues 28 | 29 | # status 30 | deprecated=False 31 | experimental=True 32 | qgisMinimumVersion=3.16 33 | qgisMaximumVersion=3.99 34 | 35 | # versioning 36 | version=1.0.0-beta1 37 | changelog= 38 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/plugin_main.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | Main plugin module. 5 | """ 6 | 7 | # standard library 8 | from string import Template 9 | 10 | # PyQGIS 11 | from qgis.gui import QgisInterface 12 | from qgis.PyQt.QtCore import QCoreApplication 13 | 14 | # project 15 | from french_locator_filter.__about__ import __title__, __version__ 16 | from french_locator_filter.core import FrenchBanGeocoderLocatorFilter 17 | from french_locator_filter.gui.dlg_settings import PlgOptionsFactory 18 | from french_locator_filter.toolbelt import PlgLogger, PlgTranslator 19 | 20 | # ############################################################################ 21 | # ########## Classes ############### 22 | # ################################## 23 | 24 | 25 | class LocatorFilterPlugin: 26 | def __init__(self, iface: QgisInterface): 27 | """Constructor. 28 | 29 | :param iface: An interface instance that will be passed to this class which \ 30 | provides the hook by which you can manipulate the QGIS application at run time. 31 | :type iface: QgsInterface 32 | """ 33 | self.iface = iface 34 | self.log = PlgLogger().log 35 | 36 | # translation 37 | plg_translation_mngr = PlgTranslator( 38 | tpl_filename=Template("french_locator_filter_$locale.qm") 39 | ) 40 | translator = plg_translation_mngr.get_translator() 41 | if translator: 42 | QCoreApplication.installTranslator(translator) 43 | self.tr = plg_translation_mngr.tr 44 | 45 | # install locator filter 46 | self.filter = FrenchBanGeocoderLocatorFilter(self.iface) 47 | self.iface.registerLocatorFilter(self.filter) 48 | 49 | if __debug__: 50 | self.log( 51 | message=( 52 | "DEBUG - French (BAN Geocoder) Locator Filter" 53 | f" ({__title__} {__version__}) installed." 54 | ), 55 | log_level=4, 56 | ) 57 | 58 | def initGui(self): 59 | """Set up plugin UI elements.""" 60 | # settings page within the QGIS preferences menu 61 | self.options_factory = PlgOptionsFactory() 62 | self.iface.registerOptionsWidgetFactory(self.options_factory) 63 | 64 | def unload(self): 65 | """Cleans up when plugin is disabled/uninstalled.""" 66 | # -- Clean up preferences panel in QGIS settings 67 | self.iface.unregisterOptionsWidgetFactory(self.options_factory) 68 | 69 | # remove filter from locator 70 | self.iface.deregisterLocatorFilter(self.filter) 71 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | resources/images/icon.svg 4 | 5 | 6 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/resources/help/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Redirecting... 7 | 8 | 9 | 10 | 11 | 12 |

Redirection to the online documentation...

13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/resources/i18n/french_locator_filter_fr.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/resources/i18n/french_locator_filter_fr.qm -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/resources/i18n/french_locator_filter_fr.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FrenchBanGeocoderLocatorFilter 6 | 7 | 8 | French Adress geocoder 9 | Géocodeur API BAN 10 | 11 | 12 | 13 | dlg_settings 14 | 15 | 16 | Settings 17 | Paramètres 18 | 19 | 20 | 21 | Features 22 | Fonctionnalités 23 | 24 | 25 | 26 | HTTP user-agent: 27 | HTTP user-agent : 28 | 29 | 30 | 31 | Request URL: 32 | Base de l'URL de requête : 33 | 34 | 35 | 36 | Request parameters: 37 | Paramètres de la requête : 38 | 39 | 40 | 41 | Miscellaneous 42 | Divers 43 | 44 | 45 | 46 | Enable debug mode. 47 | Activer le mode debug. 48 | 49 | 50 | 51 | Debug mode (degraded performances) 52 | Activer le mode debug (performances dégradées) 53 | 54 | 55 | 56 | Version used to save settings: 57 | Paramaètres sauvegardés avec la version : 58 | 59 | 60 | 61 | Report an issue 62 | Signaler une anomalie 63 | 64 | 65 | 66 | Help 67 | Aide en ligne 68 | 69 | 70 | 71 | Minimal search length 72 | Nombre minimal de caractères avant de déclencher la requête à l'API 73 | 74 | 75 | 76 | characters 77 | caractères 78 | 79 | 80 | 81 | Minimal search length: 82 | Longueur minimale de la recherche : 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/resources/i18n/plugin_translation.pro: -------------------------------------------------------------------------------- 1 | FORMS = ../../gui/dlg_settings.ui 2 | 3 | SOURCES= ../../plugin_main.py \ 4 | ../../core/locator_filter.py \ 5 | ../../toolbelt/log_handler.py \ 6 | ../../toolbelt/network_manager.py \ 7 | ../../toolbelt/preferences.py 8 | 9 | TRANSLATIONS = french_locator_filter_fr.ts 10 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/toolbelt/__init__.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | from .log_handler import PlgLogger # noqa: F401 3 | from .network_manager import NetworkRequestsManager # noqa: F401 4 | from .preferences import PlgOptionsManager # noqa: F401 5 | from .translator import PlgTranslator # noqa: F401 6 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/toolbelt/log_handler.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | # standard library 4 | import logging 5 | 6 | # PyQGIS 7 | from qgis.core import QgsMessageLog 8 | from qgis.utils import iface 9 | 10 | # project package 11 | from french_locator_filter.__about__ import __title__ 12 | 13 | # ############################################################################ 14 | # ########## Classes ############### 15 | # ################################## 16 | 17 | 18 | class PlgLogger(logging.Handler): 19 | """Python logging handler supercharged with QGIS useful methods.""" 20 | 21 | @staticmethod 22 | def log( 23 | message: str, 24 | application: str = __title__, 25 | log_level: int = 0, 26 | push: bool = False, 27 | ): 28 | """Send messages to QGIS messages windows and to the user as a message bar. \ 29 | Plugin name is used as title. 30 | 31 | :param message: message to display 32 | :type message: str 33 | :param application: name of the application sending the message. \ 34 | Defaults to __about__.__title__ 35 | :type application: str, optional 36 | :param log_level: message level. Possible values: 0 (info), 1 (warning), \ 37 | 2 (critical), 3 (success), 4 (none - grey). Defaults to 0 (info) 38 | :type log_level: int, optional 39 | :param push: also display the message in the QGIS message bar in addition to \ 40 | the log, defaults to False 41 | :type push: bool, optional 42 | 43 | :Example: 44 | 45 | .. code-block:: python 46 | 47 | log(message="Plugin loaded - INFO", log_level=0, push=1) 48 | log(message="Plugin loaded - WARNING", log_level=1, push=1) 49 | log(message="Plugin loaded - ERROR", log_level=2, push=1) 50 | log(message="Plugin loaded - SUCCESS", log_level=3, push=1) 51 | log(message="Plugin loaded - TEST", log_level=4, push=1) 52 | """ 53 | # ensure message is a string 54 | if not isinstance(message, str): 55 | try: 56 | message = str(message) 57 | except Exception as err: 58 | err_msg = "Log message must be a string, not: {}. Trace: {}".format( 59 | type(message), err 60 | ) 61 | logging.error(err_msg) 62 | message = err_msg 63 | 64 | # send it to QGIS messages panel 65 | QgsMessageLog.logMessage( 66 | message=message, tag=application, notifyUser=push, level=log_level 67 | ) 68 | 69 | # optionally, display message on QGIS Message bar (above the map canvas) 70 | if push: 71 | iface.messageBar().pushMessage( 72 | title=application, 73 | text=message, 74 | level=log_level, 75 | duration=(log_level + 1) * 3, 76 | ) 77 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/toolbelt/preferences.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | Plugin settings. 5 | """ 6 | 7 | # standard 8 | import logging 9 | from typing import NamedTuple 10 | 11 | # PyQGIS 12 | from qgis.core import QgsSettings 13 | 14 | # package 15 | from french_locator_filter.__about__ import __title__, __version__ 16 | 17 | from .log_handler import PlgLogger 18 | 19 | # ############################################################################ 20 | # ########## Globals ############### 21 | # ################################## 22 | 23 | logger = logging.getLogger(__name__) 24 | plg_logger = PlgLogger() 25 | 26 | # ############################################################################ 27 | # ########## Classes ############### 28 | # ################################## 29 | 30 | 31 | class PlgSettingsStructure(NamedTuple): 32 | """Plugin settings structure and defaults values.""" 33 | 34 | # misc 35 | debug_mode: bool = False 36 | version: str = __version__ 37 | 38 | # network 39 | http_content_type: str = "application/json" 40 | http_user_agent: str = f"{__title__}/{__version__}" 41 | min_search_length: int = 2 42 | request_url: str = "https://api-adresse.data.gouv.fr/search/" 43 | request_url_query: str = "limit=10&autocomplete=1" 44 | 45 | 46 | class PlgOptionsManager: 47 | @staticmethod 48 | def get_plg_settings() -> PlgSettingsStructure: 49 | """Load and return plugin settings as a dictionary. \ 50 | Useful to get user preferences across plugin logic. 51 | 52 | :return: plugin settings 53 | :rtype: PlgSettingsStructure 54 | """ 55 | settings = QgsSettings() 56 | settings.beginGroup(__title__) 57 | 58 | options = PlgSettingsStructure( 59 | # misc 60 | debug_mode=settings.value(key="debug_mode", defaultValue=False, type=bool), 61 | version=settings.value(key="version", defaultValue=__version__, type=str), 62 | # network 63 | http_content_type=settings.value( 64 | key="http_content_type", 65 | defaultValue="application/json", 66 | type=str, 67 | ), 68 | http_user_agent=settings.value( 69 | key="http_user_agent", 70 | defaultValue=f"{__title__}/{__version__}", 71 | type=str, 72 | ), 73 | min_search_length=settings.value( 74 | key="min_search_length", 75 | defaultValue=2, 76 | type=int, 77 | ), 78 | request_url=settings.value( 79 | key="request_url", 80 | defaultValue="https://api-adresse.data.gouv.fr/search/", 81 | type=str, 82 | ), 83 | request_url_query=settings.value( 84 | key="request_url_query", 85 | defaultValue="limit=10&autocomplete=1", 86 | type=str, 87 | ), 88 | ) 89 | 90 | settings.endGroup() 91 | 92 | return options 93 | 94 | @staticmethod 95 | def get_value_from_key(key: str, default=None, exp_type=None): 96 | """Load and return plugin settings as a dictionary. \ 97 | Useful to get user preferences across plugin logic. 98 | 99 | :return: plugin settings value matching key 100 | """ 101 | if not hasattr(PlgSettingsStructure, key): 102 | logger.error( 103 | "Bad settings key. Must be one of: {}".format( 104 | ",".join(PlgSettingsStructure._fields) 105 | ) 106 | ) 107 | return None 108 | 109 | settings = QgsSettings() 110 | settings.beginGroup(__title__) 111 | 112 | try: 113 | out_value = settings.value(key=key, defaultValue=default, type=exp_type) 114 | except Exception as err: 115 | logger.error(err) 116 | plg_logger.log(err) 117 | out_value = None 118 | 119 | settings.endGroup() 120 | 121 | return out_value 122 | 123 | @staticmethod 124 | def set_value_from_key(key: str, value): 125 | """Load and return plugin settings as a dictionary. \ 126 | Useful to get user preferences across plugin logic. 127 | 128 | :return: plugin settings value matching key 129 | """ 130 | if not hasattr(PlgSettingsStructure, key): 131 | logger.error( 132 | "Bad settings key. Must be one of: {}".format( 133 | ",".join(PlgSettingsStructure._fields) 134 | ) 135 | ) 136 | return False 137 | 138 | settings = QgsSettings() 139 | settings.beginGroup(__title__) 140 | 141 | try: 142 | settings.setValue(key, value) 143 | out_value = True 144 | except Exception as err: 145 | logger.error(err) 146 | plg_logger.log(err) 147 | out_value = False 148 | 149 | settings.endGroup() 150 | 151 | return out_value 152 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/french_locator_filter/toolbelt/translator.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | # standard library 4 | import logging 5 | from functools import lru_cache 6 | from inspect import currentframe 7 | from pathlib import Path 8 | from string import Template 9 | 10 | # PyQGIS 11 | from qgis.core import QgsSettings 12 | from qgis.PyQt.QtCore import QLocale, QTranslator 13 | from qgis.PyQt.QtWidgets import QApplication 14 | 15 | # project package 16 | from french_locator_filter.__about__ import DIR_PLUGIN_ROOT, __email__, __title__ 17 | from french_locator_filter.toolbelt import PlgLogger 18 | 19 | # ############################################################################ 20 | # ########## Globals ############### 21 | # ################################## 22 | 23 | logger = logging.getLogger(__name__) 24 | 25 | 26 | # ############################################################################ 27 | # ########## Classes ############### 28 | # ################################## 29 | 30 | 31 | class PlgTranslator: 32 | """Helper module to manage plugin translations. 33 | 34 | :param qm_search_start_path: folder where to search fro QM files. \ 35 | Defaults to DIR_PLUGIN_ROOT 36 | :type qm_search_start_path: Path, optional 37 | :param tpl_filename: pattern of translations filenames. \ 38 | Defaults to Template(f"{__title__.lower()}_.qm") 39 | :type tpl_filename: str, optional 40 | """ 41 | 42 | AVAILABLE_TRANSLATIONS: tuple = None 43 | 44 | def __init__( 45 | self, 46 | qm_search_start_path: Path = DIR_PLUGIN_ROOT, 47 | tpl_filename: str = Template(f"{__title__.lower()}_$locale.qm"), 48 | ): 49 | """Initialize method.""" 50 | 51 | self.log = PlgLogger().log 52 | 53 | # list .qm files 54 | qm_files = tuple(qm_search_start_path.glob("**/*.qm")) 55 | self.AVAILABLE_TRANSLATIONS = tuple(q.name for q in qm_files) 56 | 57 | # get locale and identify the compiled translation file (*.qm) to use 58 | locale = QgsSettings().value("locale/userLocale", QLocale().name())[0:2] 59 | locale_filename = tpl_filename.substitute(locale=locale) 60 | 61 | self.qm_filepath = None 62 | for qm in qm_files: 63 | if qm.name == locale_filename: 64 | self.qm_filepath = qm 65 | break 66 | 67 | if not self.qm_filepath: 68 | info_msg = self.tr( 69 | "Your selected locale ({}) is not available. " 70 | "Please consider to contribute with your own translation :). " 71 | "Contact the plugin maintener(s): {}".format(locale, __email__) 72 | ) 73 | self.log(message=str(info_msg), log_level=1, push=0) 74 | logger.info(info_msg) 75 | 76 | def get_translator(self) -> QTranslator: 77 | """Load translation file into QTranslator. 78 | 79 | :return: translator instance 80 | :rtype: QTranslator 81 | """ 82 | if self.AVAILABLE_TRANSLATIONS is None: 83 | warn_msg = self.tr( 84 | text="No translation found among plugin files and folders.", 85 | context="PlgTranslator", 86 | ) 87 | logger.warning(warn_msg) 88 | self.log(message=warn_msg, log_level=1) 89 | return None 90 | 91 | if not self.qm_filepath: 92 | return None 93 | 94 | # load translation 95 | self.translator = QTranslator() 96 | self.translator.load(str(self.qm_filepath.resolve())) 97 | return self.translator 98 | 99 | @lru_cache(maxsize=128) 100 | def tr(self, text: str, context: str = None) -> str: 101 | """Translate a text using the installed translator. 102 | 103 | :param text: text to translate, defaults to None. 104 | :type text: str 105 | :param context: where the text is located. In Python code, it's the class name. \ 106 | If None, it tries to automatically retrieve class name. Defaults to None. 107 | :type context: str, optional 108 | 109 | :return: translated text. 110 | :rtype: str 111 | """ 112 | if not context: 113 | frame = currentframe().f_back 114 | if "self" in frame.f_locals: 115 | context = type(frame.f_locals["self"]).__name__ 116 | 117 | return QApplication.translate(context, text) 118 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/Makefile: -------------------------------------------------------------------------------- 1 | #/*************************************************************************** 2 | # ------------------- 3 | # begin : 2014-02-20 4 | # copyright : (C) 2014 by Oslandia 5 | # email : hugo.mercier@oslandia.com 6 | # ***************************************************************************/ 7 | # 8 | #/*************************************************************************** 9 | # * * 10 | # * This program is free software; you can redistribute it and/or modify * 11 | # * it under the terms of the GNU General Public License as published by * 12 | # * the Free Software Foundation; either version 2 of the License, or * 13 | # * (at your option) any later version. * 14 | # * * 15 | # ***************************************************************************/ 16 | 17 | QGISDIR=.qgis2 18 | 19 | # Makefile for a PyQGIS plugin 20 | 21 | # global 22 | 23 | PLUGINNAME = mask 24 | 25 | # 26 | SOURCES = aeag_mask.py maindialog.py __init__.py layerlist.py mask_filter.py mask_parameters.py style_tools.py htmldialog.py 27 | TRANSLATIONS = mask_fr.ts 28 | 29 | EXTRAS = aeag_mask.png metadata.txt default_mask_style.qml 30 | UI_FILES = ui_plugin_mask.py ui_layer_list.py 31 | 32 | RESOURCE_FILES = resources_rc.py 33 | 34 | default: compile 35 | 36 | compile: $(UI_FILES) $(RESOURCE_FILES) 37 | 38 | %_rc.py : %.qrc 39 | pyrcc4 -o $*_rc.py $< 40 | 41 | %.py : %.ui 42 | pyuic4 -o $@ $< 43 | 44 | %.qm : %.ts 45 | lrelease-qt4 $< 46 | 47 | # The deploy target only works on unix like operating system where 48 | # the Python plugin directory is located at: 49 | # $HOME/$(QGISDIR)/python/plugins 50 | deploy: compile transcompile 51 | mkdir -p $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 52 | mkdir -p $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)/db 53 | cp -vf $(SOURCES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 54 | cp -vf $(UI_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 55 | cp -vf $(RESOURCE_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 56 | cp -vf $(EXTRAS) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 57 | cp -vf *.ts *.qm $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 58 | cp -vfr doc/ $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 59 | 60 | # The dclean target removes compiled python files from plugin directory 61 | # also delets any .svn entry 62 | dclean: 63 | find $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) -iname "*.pyc" -delete 64 | find $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) -iname ".svn" -prune -exec rm -Rf {} \; 65 | 66 | # The derase deletes deployed plugin 67 | derase: 68 | rm -Rf $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) 69 | 70 | # The zip target deploys the plugin and creates a zip file with the deployed 71 | # content. You can then upload the zip file on http://plugins.qgis.org 72 | zip: deploy dclean 73 | rm -f $(PLUGINNAME).zip 74 | cd $(HOME)/$(QGISDIR)/python/plugins; zip -9r $(CURDIR)/$(PLUGINNAME).zip $(PLUGINNAME) 75 | 76 | # Create a zip package of the plugin named $(PLUGINNAME).zip. 77 | # This requires use of git (your plugin development directory must be a 78 | # git repository). 79 | # To use, pass a valid commit or tag as follows: 80 | # make package VERSION=Version_0.3.2 81 | package: compile 82 | rm -f $(PLUGINNAME).zip 83 | git archive --prefix=$(PLUGINNAME)/ -o $(PLUGINNAME).zip $(VERSION) 84 | echo "Created package: $(PLUGINNAME).zip" 85 | 86 | upload: zip 87 | $(PLUGIN_UPLOAD) $(PLUGINNAME).zip 88 | 89 | # transup 90 | # update .ts translation files 91 | transup: 92 | pylupdate4 $(SOURCES) $(UI_FILES:.py=.ui) -ts $(TRANSLATIONS) 93 | 94 | # transcompile 95 | # compile translation files into .qm binary format 96 | transcompile: $(TRANSLATIONS:.ts=.qm) 97 | 98 | # transclean 99 | # deletes all .qm files 100 | transclean: 101 | rm -f *.qm 102 | 103 | clean: 104 | rm $(UI_FILES) $(RESOURCE_FILES) 105 | 106 | # build documentation with sphinx 107 | #doc: 108 | # cd help; make html 109 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | /*************************************************************************** 3 | Name : Mask plugin 4 | Description : Help to create mask 5 | Date : 08/Feb/12 6 | copyright : (C) 2011 by AEAG 7 | email : xavier.culos@eau-adour-garonne.fr 8 | ***************************************************************************/ 9 | 10 | /*************************************************************************** 11 | * * 12 | * This program is free software; you can redistribute it and/or modify * 13 | * it under the terms of the GNU General Public License as published by * 14 | * the Free Software Foundation; either version 2 of the License, or * 15 | * (at your option) any later version. * 16 | * * 17 | ***************************************************************************/ 18 | This script initializes the plugin, making it known to QGIS. 19 | """ 20 | def classFactory(iface): 21 | # load aeag_mask class from file aeag_mask 22 | from .aeag_mask import aeag_mask 23 | return aeag_mask(iface) 24 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/aeag_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/mask/aeag_mask.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/default_mask_style.qml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 0 39 | 0 40 | 2 41 | 42 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/en/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | About 4 | 5 | 6 | That tool is designed to help users to quickly generate cartographic masking layer to enlight an area of interest.

7 | Current features are: 17 | 18 |

Mask plugin was developped by Xavier Culos (AEAG) and contributed by Hugo Mercier (Oslandia) on funding by Agence de l'eau Adour Garonne.
19 | Please notify any issue or enhancement request here

20 | 21 |

Tips

22 | 23 | 24 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/en/legend_inmask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/en/legend_inmask.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/en/tips.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tips 4 | 5 | 6 |

How to filter out legend elements based on the mask ?

7 |

One may want to use the mask to highlight some part of a map. In which case, one may want to hide 8 | elements of the legend (in a composition) that are not displayed inside the polygon of the mask.

9 |

The in_mask function can be used for that purpose. Starting with QGIS 2.14, a new option 10 | has been added to the legend filter tool, allowing to specify an expression. A symbol will be part of 11 | the legend only if at least one of its features make the boolean expression evaluated to true.

12 |

That can especially be used to filter out features that are not visible inside the mask by using 13 | the function in_mask(SRID). The first argument must be the EPSG code of the target CRS of the evaluated features. 14 | For example in_mask(2154) for a French Lambert 93.

15 |

Use in_mask(0) if all layers (mask and labels) are in the same projection.

16 | 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/fr/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | À propos 5 | 6 | 7 | Cet outil a été développé pour aider les utilisateurs à générer rapidement des couches de masque pour mettre en évidence une zone d'intérêt.

8 | Les fonctionnalités actuelles sont : 18 | 19 |

Le plugin Mask a été développé par Xavier Culos (AEAG) avec des contributions de Hugo Mercier (Oslandia) sur financements de l'Agence de l'eau Adour Garonne.
20 | Merci de notifier tout problème ou demande d'évolution ici

21 | 22 |

Astuces

23 | 24 | 25 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/fr/legend_inmask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/fr/legend_inmask.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/doc/fr/tips.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Astuces 5 | 6 | 7 |

Comment éliminer les élements de légende en dehors du masque ?

8 |

On peut vouloir utiliser le masque pour mettre en évidence une zone d'une carte. Auquel cas, on peut vouloir cacher 9 | les éléments de légende qui ne sont pas affichés à l'intérieur du polygon de masque.

10 |

La fonction in_mask peut être utilisée dans ce but. À partir de QGIS 2.14, une nouvelle option 11 | a été ajoutée aux outils de filtre de légende, permettant de spécifier une expression. Un symbole fera partie de 12 | la légende seulement si au moins une de ses entités fait que l'expression booléenne est évaluée à vrai.

13 |

Ceci peut en particulier être utilisé pour éliminer de la légende les entités qui ne sont pas dans le masque en utilisant 14 | la fonction in_mask(SRID). Le premier argument doit être le code EPSG du système de coordonnées de l'entité sur laquelle l'expression est évaluée. 15 | Par exemple in_mask(2154) pour du Lambert 93.

16 |

Utilisez in_mask(0) si l'ensemble de vos données (masque et étiquettes) sont codées dans une même projection.

17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/htmldialog.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import (QSettings, QUrl, Qt) 2 | from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QTextBrowser, QDialogButtonBox) 3 | 4 | import os 5 | 6 | 7 | class HtmlDialog(QDialog): 8 | 9 | def __init__(self, parent, url): 10 | QDialog.__init__(self, parent) 11 | 12 | self.resize(800, 600) 13 | 14 | l = QVBoxLayout() 15 | 16 | self.te = QTextBrowser(self) 17 | self.te.sourceChanged.connect(self.onSourceChanged) 18 | self.te.setOpenExternalLinks(True) 19 | if not url.startswith('http'): 20 | pwd = os.path.dirname(__file__) 21 | locale = QSettings().value("locale/userLocale")[0:2] 22 | file = "{}/doc/{}/{}".format(pwd, locale, url) 23 | if not os.path.isfile(file): 24 | file = "{}/doc/en/{}".format(pwd, url) 25 | self.te.setSource(QUrl.fromLocalFile(file)) 26 | else: 27 | self.te.setSource(QUrl(url)) 28 | 29 | btn = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal, self) 30 | btn.clicked.connect(self.close) 31 | 32 | l.addWidget(self.te) 33 | l.addWidget(btn) 34 | 35 | self.setLayout(l) 36 | 37 | def onSourceChanged(self, url): 38 | self.setWindowTitle(self.te.documentTitle()) 39 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/i18n/fr.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/mask/i18n/fr.qm -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/layerlist.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import (Qt) 2 | from PyQt5.QtWidgets import (QWidget, QTableWidgetItem, QDialog, QCheckBox, 3 | QDialogButtonBox, QVBoxLayout) 4 | from qgis.core import (QgsProject, QgsVectorLayer) 5 | 6 | from .ui_layer_list import Ui_LayerListWidget 7 | 8 | from . import mask_filter 9 | 10 | 11 | class LayerListWidget(QWidget): 12 | def __init__(self, parent): 13 | QWidget.__init__(self, parent) 14 | 15 | self.ui = Ui_LayerListWidget() 16 | self.ui.setupUi(self) 17 | 18 | self.ui.selectAllBtn.clicked.connect(self.on_selectall) 19 | self.ui.unselectAllBtn.clicked.connect(self.on_unselectall) 20 | 21 | # list of limited layers (list of layer id) 22 | self.limited = [] 23 | 24 | def get_limited_layers(self): 25 | return self.limited 26 | 27 | def on_selectall(self): 28 | "Select all layers for label filtering" 29 | ll = self.ui.layerTable 30 | for i in range(ll.rowCount()): 31 | ll.cellWidget(i, 0).setChecked(True) 32 | 33 | def on_unselectall(self): 34 | "Unselect all layers for label filtering" 35 | ll = self.ui.layerTable 36 | for i in range(ll.rowCount()): 37 | ll.cellWidget(i, 0).setChecked(False) 38 | 39 | def update_from_layers(self, is_new=False): 40 | layers = QgsProject.instance().mapLayers() 41 | n = 0 42 | for name, layer in layers.items(): 43 | 44 | if layer.name() == 'Mask': 45 | continue 46 | # skip non vector layers 47 | if not isinstance(layer, QgsVectorLayer): 48 | continue 49 | 50 | # skip layers without labels 51 | if layer.labeling() is None: 52 | continue 53 | 54 | do_limit = False 55 | did_limit = layer.id() in self.limited 56 | do_limit = mask_filter.has_mask_filter(layer) 57 | 58 | if do_limit and not did_limit: 59 | self.limited.append(layer.id()) 60 | if not do_limit and did_limit: 61 | self.limited.remove(layer.id()) 62 | 63 | self.ui.layerTable.insertRow(n) 64 | name_item = QTableWidgetItem() 65 | name_item.setData(Qt.DisplayRole, layer.name()) 66 | self.ui.layerTable.setItem(n, 1, name_item) 67 | w = QCheckBox(self.ui.layerTable) 68 | w.setEnabled(layer.labeling() is not None) 69 | w.setChecked(do_limit or is_new) 70 | self.ui.layerTable.setCellWidget(n, 0, w) 71 | item = QTableWidgetItem() 72 | item.setData(Qt.UserRole, layer) 73 | self.ui.layerTable.setItem(n, 0, item) 74 | n += 1 75 | 76 | self.ui.selectAllBtn.setEnabled(n != 0) 77 | self.ui.unselectAllBtn.setEnabled(n != 0) 78 | 79 | def update_labeling_from_list(self): 80 | ll = self.ui.layerTable 81 | 82 | for i in range(ll.rowCount()): 83 | do_limit = ll.cellWidget(i, 0).isChecked() 84 | layer = ll.item(i, 0).data(Qt.UserRole) 85 | did_limit = layer.id() in self.limited 86 | 87 | if not did_limit and do_limit: 88 | # add spatial filtering 89 | mask_filter.add_mask_filter(layer) 90 | self.limited.append(layer.id()) 91 | 92 | if did_limit and not do_limit: 93 | mask_filter.remove_mask_filter(layer) 94 | self.limited.remove(layer.id()) 95 | 96 | 97 | class LayerListDialog(QDialog): 98 | def __init__(self, parent): 99 | QDialog.__init__(self, parent) 100 | 101 | # add a button box 102 | self.layout = QVBoxLayout() 103 | 104 | self.layer_list = LayerListWidget(self) 105 | self.button_box = QDialogButtonBox(self) 106 | self.button_box.setOrientation(Qt.Horizontal) 107 | self.button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) 108 | self.button_box.accepted.connect(self.accept) 109 | self.button_box.rejected.connect(self.reject) 110 | 111 | self.layout.addWidget(self.layer_list) 112 | self.layout.addWidget(self.button_box) 113 | 114 | self.setLayout(self.layout) 115 | 116 | def set_labeling_model(self, model): 117 | self.layer_list.set_model(model) 118 | 119 | def exec_(self): 120 | self.layer_list.update_from_layers() 121 | return QDialog.exec_(self) 122 | 123 | def accept(self): 124 | # update layers 125 | self.layer_list.update_labeling_from_list() 126 | QDialog.accept(self) 127 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/mask_filter.py: -------------------------------------------------------------------------------- 1 | from qgis.core import (QgsVectorLayer, QgsPalLayerSettings, QgsProperty, QgsMessageLog, 2 | QgsVectorLayerSimpleLabeling) 3 | 4 | SPATIAL_FILTER = "in_mask" 5 | 6 | 7 | def has_mask_filter(layer): 8 | if not isinstance(layer, QgsVectorLayer): 9 | return False 10 | 11 | # check if a layer has already a mask filter enabled 12 | if layer.labeling() is None: 13 | return False 14 | 15 | settings = layer.labeling().settings() 16 | show_expr = settings.dataDefinedProperties().property(QgsPalLayerSettings.Show) 17 | if show_expr is None: 18 | return False 19 | 20 | return show_expr.expressionString().startswith(SPATIAL_FILTER) 21 | 22 | 23 | def remove_mask_filter(layer): 24 | if not isinstance(layer, QgsVectorLayer): 25 | return False 26 | 27 | # check if a layer has already a mask filter enabled 28 | if layer.labeling() is None: 29 | return False 30 | 31 | settings = layer.labeling().settings() 32 | 33 | try: 34 | if settings.dataDefinedProperties().hasProperty(QgsPalLayerSettings.Show) and \ 35 | settings.dataDefinedProperties().property(QgsPalLayerSettings.Show).expressionString().startswith(SPATIAL_FILTER): 36 | # new settings 37 | settings = QgsPalLayerSettings(layer.labeling().settings()) 38 | settings.dataDefinedProperties().setProperty(QgsPalLayerSettings.Show, True) 39 | if isinstance(layer.labeling(), QgsVectorLayerSimpleLabeling): 40 | layer.setLabeling(QgsVectorLayerSimpleLabeling(settings)) 41 | except Exception as e: 42 | for m in e.args: 43 | QgsMessageLog.logMessage(m, 'Extensions') 44 | 45 | 46 | def add_mask_filter(layer): 47 | if not isinstance(layer, QgsVectorLayer): 48 | return False 49 | 50 | # check if a layer has already a mask filter enabled 51 | if layer.labeling() is None: 52 | return False 53 | 54 | try: 55 | expr = "%s(%d)" % (SPATIAL_FILTER, layer.crs().postgisSrid()) 56 | prop = QgsProperty() 57 | prop.setExpressionString(expr) 58 | 59 | # new settings 60 | settings = QgsPalLayerSettings(layer.labeling().settings()) 61 | settings.dataDefinedProperties().setProperty(QgsPalLayerSettings.Show, prop) 62 | if isinstance(layer.labeling(), QgsVectorLayerSimpleLabeling): 63 | layer.setLabeling(QgsVectorLayerSimpleLabeling(settings)) 64 | 65 | except Exception as e: 66 | for m in e.args: 67 | QgsMessageLog.logMessage(m, 'Extensions') 68 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/metadata.txt: -------------------------------------------------------------------------------- 1 | # Mandatory items: 2 | 3 | [general] 4 | name=Mask 5 | qgisMinimumVersion=3.4 6 | qgisMaximumVersion=3.98 7 | 8 | description=Help to create mask, filter labels in it 9 | description[fr]=Aide à la création de masque, filtrage d'étiquette 10 | version=1.9.4 11 | # end of mandatory metadata 12 | 13 | # Optional items: 14 | about=This plugin allows user to quickly transform a polygon selection into a map masking layer or a region of interest, following symbology choice. The plugin allows also to spatially filter labeling of other layer, so that labels will only appear in the Region of Interest. 15 | about[fr]=Cette extension permet de générer un masque à partir d'une sélection de polygones. Le plugin permet également de filtrer l'étiquetage uniquement pour les objets à l'intérieur de ce masque. 16 | # Uncomment the following line and add your changelog entries: 17 | changelog= 18 | 1.9.4 : fix #78 : Python error atlas + mask, fix #79 locale.Error 19 | 1.9.3 : fix #77 : The absence of 'locale' probably behind the bug. 20 | 1.9.2 : fix #76 : Updating the existing mask doesn't update extents, and mask little less blue by default 21 | 1.9.1 : fix #75 : Locale symbol for decimal value, https://github.com/aeag/mask/issues/75 22 | 1.9.0 : Minimum fixes allowing a nominal work with the atlas. Fix #68 23 | 1.8.4 : fix #72, issues/21214 24 | 1.8.3 : a partially functional version (Atlas does not work anymore) 25 | 1.8.2 : adaptation to API changes (QgsCoordinateTransform) 26 | 1.8.1 : do not affect Rule based labeling 27 | 1.8 : Some API changes (QgsExpression, QgsPalLayerSettings) 28 | 1.7 : Migration to QGis 3 29 | 1.6 : master developpement version (not released) 30 | 1.5.1 : enables plugin only for qgis <=2.8 . See https://github.com/aeag/mask/issues/51 31 | 1.5 : fixes number of issues with Atlas, UI improvements. 32 | 1.4 : zooms to mask and clears selection on the fly. Some fixes due to mask_plugin renamed to mask 33 | 1.3 : enhance spatial operator for exact labeling filter. Was "contains", now is "contains" or "overlaps" 34 | 1.2 : bugfixe release : 35 | - Crash after removal of the mask layer 36 | - Unfreeze mapcanvas when atlas previewx is ON 37 | - Disable label filtering if mask layer has no object 38 | 1.1 : bugfixe release 39 | 1.0 : Can be used with atlas, 2.4 compatible 40 | 0.9 : Can be used with atlas, 2.4 compatible - test version 41 | 0.5 : QGis 2.0 Compatible 42 | 0.4 : Python console callable 43 | --fr-- 44 | 1.4 : Zoom sur le masque et nettoyage de la sélection à la volée. Corrections mineures liées au renommage des répertoire de mask_plugin en mask 45 | 1.3 : Amélioration de l'opérateur spatial exact de filtre des étiquettes. Avant:"contains", après: "contains" OU "overlaps" 46 | 1.2 : correction de bugs : 47 | - Crash après la suppression d'un couche de masque 48 | - Ne gèle plus l'affichage si la prévisualisation d'Atlas est activée 49 | - Désactive le filtrage d'étiquette si la couche de masque est vide 50 | 1.1 : bugfixe release 51 | 1.0 : Ajoute la capacité à masquer les cartes du générateur d'Atlas 52 | 0.9 : Can be used with atlas, 2.4 compatible - test version 53 | 0.5 : Version QGis 2.0 54 | 0.4 : ajoute une classe permettant d'appeler le plugin depuis la console python ou un autre plugin. 55 | 56 | # tags are comma separated with spaces allowed 57 | tags=mask, ROI, filter labels, étiquettes, masque, zone d'intérêt 58 | 59 | homepage=https://github.com/aeag/mask 60 | tracker=https://github.com/aeag/mask/issues 61 | repository=https://github.com/aeag/mask 62 | icon=aeag_mask.png 63 | # experimental flag 64 | experimental=False 65 | 66 | # deprecated flag (applies to the whole plugin, not just a single version 67 | deprecated=False 68 | 69 | # Author contact information 70 | author=Hugo Mercier (Oslandia) - Xavier Culos (Agence de l'eau Adour Garonne) - Régis Haubourg (Oslandia) 71 | email=geocatalogue@eau-adour-garonne.fr 72 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/resources_rc.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | aeag_mask.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/style_tools.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from PyQt5.QtCore import QSettings 4 | from PyQt5.QtXml import QDomDocument, QDomImplementation 5 | from qgis.core import QgsReadWriteContext 6 | 7 | from .mask_parameters import MaskParameters 8 | 9 | 10 | def set_layer_symbology(layer, symbology): 11 | if symbology is not None: 12 | doc = QDomDocument("qgis") 13 | doc.setContent(symbology) 14 | errorMsg = '' 15 | ctx = QgsReadWriteContext() 16 | layer.readSymbology(doc.firstChildElement("qgis"), errorMsg, ctx) 17 | 18 | 19 | def get_layer_symbology(layer): 20 | doc = QDomDocument(QDomImplementation().createDocumentType("qgis", 21 | "http://mrcc.com/qgis.dtd", 22 | "SYSTEM")) 23 | rootNode = doc.createElement("qgis") 24 | doc.appendChild(rootNode) 25 | errorMsg = '' 26 | ctx = QgsReadWriteContext() 27 | layer.writeSymbology(rootNode, doc, errorMsg, ctx) 28 | return doc.toByteArray() 29 | 30 | 31 | def set_default_layer_symbology(layer): 32 | settings = QSettings() 33 | 34 | parameters = MaskParameters() 35 | defaults = settings.value("mask/defaults", None) 36 | if defaults is not None: 37 | parameters.unserialize(defaults) 38 | set_layer_symbology(layer, parameters.style) 39 | else: 40 | default_style = os.path.join(os.path.dirname(__file__), "default_mask_style.qml") 41 | layer.loadNamedStyle(default_style) 42 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/ui_layer_list.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'W:\GitHub\mask\mask\ui_layer_list.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.6 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_LayerListWidget(object): 12 | def setupUi(self, LayerListWidget): 13 | LayerListWidget.setObjectName("LayerListWidget") 14 | LayerListWidget.resize(768, 438) 15 | self.verticalLayout = QtWidgets.QVBoxLayout(LayerListWidget) 16 | self.verticalLayout.setObjectName("verticalLayout") 17 | self.formLayout = QtWidgets.QFormLayout() 18 | self.formLayout.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow) 19 | self.formLayout.setObjectName("formLayout") 20 | self.label = QtWidgets.QLabel(LayerListWidget) 21 | self.label.setObjectName("label") 22 | self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label) 23 | self.polygonOperatorCombo = QtWidgets.QComboBox(LayerListWidget) 24 | self.polygonOperatorCombo.setObjectName("polygonOperatorCombo") 25 | self.polygonOperatorCombo.addItem("") 26 | self.polygonOperatorCombo.addItem("") 27 | self.polygonOperatorCombo.addItem("") 28 | self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.polygonOperatorCombo) 29 | self.label_2 = QtWidgets.QLabel(LayerListWidget) 30 | self.label_2.setObjectName("label_2") 31 | self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_2) 32 | self.lineOperatorCombo = QtWidgets.QComboBox(LayerListWidget) 33 | self.lineOperatorCombo.setObjectName("lineOperatorCombo") 34 | self.lineOperatorCombo.addItem("") 35 | self.lineOperatorCombo.addItem("") 36 | self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineOperatorCombo) 37 | self.verticalLayout.addLayout(self.formLayout) 38 | self.layerTable = QtWidgets.QTableWidget(LayerListWidget) 39 | self.layerTable.setObjectName("layerTable") 40 | self.layerTable.setColumnCount(2) 41 | self.layerTable.setRowCount(0) 42 | item = QtWidgets.QTableWidgetItem() 43 | self.layerTable.setHorizontalHeaderItem(0, item) 44 | item = QtWidgets.QTableWidgetItem() 45 | self.layerTable.setHorizontalHeaderItem(1, item) 46 | self.layerTable.horizontalHeader().setStretchLastSection(True) 47 | self.verticalLayout.addWidget(self.layerTable) 48 | self.horizontalLayout = QtWidgets.QHBoxLayout() 49 | self.horizontalLayout.setObjectName("horizontalLayout") 50 | self.selectAllBtn = QtWidgets.QPushButton(LayerListWidget) 51 | self.selectAllBtn.setObjectName("selectAllBtn") 52 | self.horizontalLayout.addWidget(self.selectAllBtn) 53 | self.unselectAllBtn = QtWidgets.QPushButton(LayerListWidget) 54 | self.unselectAllBtn.setObjectName("unselectAllBtn") 55 | self.horizontalLayout.addWidget(self.unselectAllBtn) 56 | self.verticalLayout.addLayout(self.horizontalLayout) 57 | 58 | self.retranslateUi(LayerListWidget) 59 | self.polygonOperatorCombo.setCurrentIndex(0) 60 | self.lineOperatorCombo.setCurrentIndex(0) 61 | QtCore.QMetaObject.connectSlotsByName(LayerListWidget) 62 | 63 | def retranslateUi(self, LayerListWidget): 64 | _translate = QtCore.QCoreApplication.translate 65 | LayerListWidget.setWindowTitle(_translate("LayerListWidget", "Form")) 66 | self.label.setText(_translate("LayerListWidget", "Function used for labeling filtering on polygons")) 67 | self.polygonOperatorCombo.setItemText(0, _translate("LayerListWidget", "Exact (slow and will disable simplification)")) 68 | self.polygonOperatorCombo.setItemText(1, _translate("LayerListWidget", "The mask geometry contains the centroid")) 69 | self.polygonOperatorCombo.setItemText(2, _translate("LayerListWidget", "The mask geometry contains a point on the polygon surface")) 70 | self.label_2.setText(_translate("LayerListWidget", "Function used for labeling filtering on lines")) 71 | self.lineOperatorCombo.setItemText(0, _translate("LayerListWidget", "The mask geometry intersects the line")) 72 | self.lineOperatorCombo.setItemText(1, _translate("LayerListWidget", "The mask geometry contains the line")) 73 | item = self.layerTable.horizontalHeaderItem(0) 74 | item.setText(_translate("LayerListWidget", "Limit")) 75 | item = self.layerTable.horizontalHeaderItem(1) 76 | item.setText(_translate("LayerListWidget", "Layer")) 77 | self.selectAllBtn.setText(_translate("LayerListWidget", "Select all")) 78 | self.unselectAllBtn.setText(_translate("LayerListWidget", "Unselect all")) 79 | 80 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/mask/ui_layer_list.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LayerListWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 768 10 | 438 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | QFormLayout::AllNonFixedFieldsGrow 21 | 22 | 23 | 24 | 25 | Function used for labeling filtering on polygons 26 | 27 | 28 | 29 | 30 | 31 | 32 | 0 33 | 34 | 35 | 36 | Exact (slow and will disable simplification) 37 | 38 | 39 | 40 | 41 | The mask geometry contains the centroid 42 | 43 | 44 | 45 | 46 | The mask geometry contains a point on the polygon surface 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Function used for labeling filtering on lines 55 | 56 | 57 | 58 | 59 | 60 | 61 | 0 62 | 63 | 64 | 65 | The mask geometry intersects the line 66 | 67 | 68 | 69 | 70 | The mask geometry contains the line 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | true 81 | 82 | 83 | 84 | Limit 85 | 86 | 87 | 88 | 89 | Layer 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Select all 100 | 101 | 102 | 103 | 104 | 105 | 106 | Unselect all 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/__about__.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | Metadata about the package to easily retrieve informations about it. 5 | See: https://packaging.python.org/guides/single-sourcing-package-version/ 6 | """ 7 | 8 | from configparser import ConfigParser 9 | from datetime import date 10 | from pathlib import Path 11 | 12 | __all__ = [ 13 | "__author__", 14 | "__copyright__", 15 | "__email__", 16 | "__license__", 17 | "__summary__", 18 | "__title__", 19 | "__uri__", 20 | "__version__", 21 | ] 22 | 23 | # -- GLOBALS -------------------------------------------------------------------- 24 | 25 | DIR_PLUGIN_ROOT = Path(__file__).parent 26 | PLG_METADATA_FILE = DIR_PLUGIN_ROOT / "metadata.txt" 27 | 28 | 29 | # -- FUNCTIONS -------------------------------------------------------------------- 30 | 31 | 32 | def plugin_metadata_as_dict() -> dict: 33 | """Read plugin metadata.txt and returns it as a Python dict. 34 | 35 | Raises: 36 | IOError: if metadata.txt is not found 37 | 38 | Returns: 39 | dict: dict of dicts. 40 | """ 41 | config = ConfigParser() 42 | if PLG_METADATA_FILE.is_file(): 43 | config.read(PLG_METADATA_FILE, encoding="UTF-8") 44 | return {s: dict(config.items(s)) for s in config.sections()} 45 | else: 46 | raise IOError("Plugin metadata.txt not found at: %s" % PLG_METADATA_FILE) 47 | 48 | 49 | # -- VARIABLES -------------------------------------------------------------------- 50 | 51 | # store full metadata.txt as dict into a var 52 | __plugin_md__ = plugin_metadata_as_dict() 53 | 54 | __author__ = __plugin_md__.get("general").get("author") 55 | __copyright__ = "2014 - {0}, {1}".format(date.today().year, __author__) 56 | __email__ = __plugin_md__.get("general").get("email") 57 | __keywords__ = __plugin_md__.get("general").get("repository").split("tags") 58 | __license__ = "GPL-2.0" 59 | __summary__ = "{}\n{}".format( 60 | __plugin_md__.get("general").get("description"), 61 | __plugin_md__.get("general").get("about"), 62 | ) 63 | 64 | __title__ = __plugin_md__.get("general").get("name") 65 | __title_clean__ = "".join(e for e in __title__ if e.isalnum()) 66 | 67 | __uri_homepage__ = __plugin_md__.get("general").get("homepage") 68 | __uri_repository__ = __plugin_md__.get("general").get("repository") 69 | __uri_tracker__ = __plugin_md__.get("general").get("tracker") 70 | __uri__ = __uri_repository__ 71 | 72 | __version__ = __plugin_md__.get("general").get("version") 73 | __version_info__ = tuple( 74 | [ 75 | int(num) if num.isdigit() else num 76 | for num in __version__.replace("-", ".", 1).split(".") 77 | ] 78 | ) 79 | 80 | # ############################################################################# 81 | # ##### Main ####################### 82 | # ################################## 83 | if __name__ == "__main__": 84 | plugin_md = plugin_metadata_as_dict() 85 | assert isinstance(plugin_md, dict) 86 | assert plugin_md.get("general").get("name") == __title__ 87 | print("Plugin: " + __title__) 88 | print("Plugin (clean): " + __title_clean__) 89 | print("By: " + __author__) 90 | print("Version: " + __version__) 91 | print("Description: " + __summary__) 92 | print( 93 | "For: %s > QGIS > %s" 94 | % ( 95 | plugin_md.get("general").get("qgisminimumversion"), 96 | plugin_md.get("general").get("qgismaximumversion"), 97 | ) 98 | ) 99 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | /*************************************************************************** 3 | Name : menu_from_project plugin 4 | Description : Build layers shortcut menu based on QGIS project 5 | Date : 10/11/2011 6 | copyright : (C) 2011 by Agence de l'Eau Adour Garonne 7 | email : xavier.culos@eau-adour-garonne.fr 8 | ***************************************************************************/ 9 | 10 | /*************************************************************************** 11 | * * 12 | * This program is free software; you can redistribute it and/or modify * 13 | * it under the terms of the GNU General Public License as published by * 14 | * the Free Software Foundation; either version 2 of the License, or * 15 | * (at your option) any later version. * 16 | * * 17 | ***************************************************************************/ 18 | This script initializes the plugin, making it known to QGIS. 19 | """ 20 | 21 | 22 | def classFactory(iface): 23 | # load menu_from_project class from file menu_from_project 24 | from .menu_from_project import MenuFromProject 25 | 26 | return MenuFromProject(iface) 27 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/doc/index-en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Menu Layer from Project - Redirecting... 7 | 8 | 9 | 10 | 11 | 12 |

Redirection to the online documentation...

13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/doc/index-fr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Menu Layer from Project - Redirecting... 7 | 8 | 9 | 10 | 11 | 12 |

Redirection en cours vers la documentation en ligne...

13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/i18n/fr.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/i18n/fr.qm -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/logic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/logic/__init__.py -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/logic/custom_datatypes.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | # Standard library 4 | from collections import namedtuple 5 | 6 | # Constants 7 | REGISTERED_PROJECT = namedtuple( 8 | "RegisteredProject", ["name", "type_storage", "type_menu_location", "uri"] 9 | ) 10 | 11 | TABLE_COLUMNS_ORDER = namedtuple( 12 | "ColumnsIndex", ["edit", "name", "type_menu_location", "type_storage", "uri"] 13 | ) 14 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/logic/tools.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | # Standard library 4 | import logging 5 | from functools import lru_cache 6 | 7 | # PyQGIS 8 | from qgis.core import QgsApplication, QgsLayerItem 9 | 10 | # project 11 | from menu_from_project.__about__ import DIR_PLUGIN_ROOT 12 | 13 | # ############################################################################ 14 | # ########## Globals ############### 15 | # ################################## 16 | 17 | logger = logging.getLogger(__name__) 18 | 19 | # ############################################################################ 20 | # ########## Classes ############### 21 | # ################################## 22 | 23 | 24 | @lru_cache() 25 | def guess_type_from_uri(qgs_uri: str) -> str: 26 | """Return project storage type based on the QGS URI. 27 | 28 | :param qgs_uri: QGS project URI (filepath, url or connection string) 29 | :type qgs_uri: str 30 | 31 | :return: storage type: "database", "file" or "http" 32 | :rtype: str 33 | """ 34 | if qgs_uri.startswith("postgresql"): 35 | return "database" 36 | elif qgs_uri.startswith("http"): 37 | return "http" 38 | else: 39 | return "file" 40 | 41 | 42 | @lru_cache() 43 | def icon_per_storage_type(type_storage: str) -> str: 44 | """Returns the icon for a storage type, 45 | 46 | :param type_storage: [description] 47 | :type type_storage: str 48 | 49 | :return: icon path 50 | :rtype: str 51 | """ 52 | if type_storage == "file": 53 | return QgsApplication.iconPath("mIconFile.svg") 54 | elif type_storage == "database": 55 | return QgsApplication.iconPath("mIconPostgis.svg") 56 | elif type_storage == "http": 57 | return str(DIR_PLUGIN_ROOT / "resources/globe.svg") 58 | else: 59 | return QgsApplication.iconPath("mIconFile.svg") 60 | 61 | 62 | @lru_cache() 63 | def icon_per_geometry_type(geometry_type: str): 64 | """Return the icon for a geometry type. 65 | 66 | If not found, it will return the default icon. 67 | 68 | :param geometry_type: The geometry as a string. 69 | :type geometry_type: basestring 70 | 71 | :return: The icon. 72 | :rtype: QIcon 73 | """ 74 | geometry_type = geometry_type.lower() 75 | if geometry_type == "raster": 76 | return QgsLayerItem.iconRaster() 77 | elif geometry_type == "mesh": 78 | return QgsLayerItem.iconMesh() 79 | elif geometry_type == "point": 80 | return QgsLayerItem.iconPoint() 81 | elif geometry_type == "line": 82 | return QgsLayerItem.iconLine() 83 | elif geometry_type == "polygon": 84 | return QgsLayerItem.iconPolygon() 85 | elif geometry_type == "no geometry": 86 | return QgsLayerItem.iconTable() 87 | else: 88 | return QgsLayerItem.iconDefault() 89 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. Beginning 2 | # with version 1.8 this is the preferred way to supply information about a 3 | # plugin. The current method of embedding metadata in __init__.py will 4 | # be supported until version 2.0 5 | 6 | # This file should be included when you package your plugin. 7 | 8 | # Mandatory items: 9 | 10 | 11 | [general] 12 | name=Layers menu from project 13 | qgisMinimumVersion=3.10 14 | qgisMaximumVersion=3.98 15 | description=Build layers shortcuts menus based on QGIS projects 16 | about=Allow easy opening of layers maintaining their style. 17 | 18 | version=2.0.0 19 | 20 | # end of mandatory metadata 21 | 22 | # Optional items: 23 | 24 | # Uncomment the following line and add your changelog entries: 25 | changelog= 26 | 2.0.0 : Allow pointing to http/https online qgs-qgz project file (#28) 27 | thanks to Julien Moura (https://github.com/Guts) 28 | Support of Joined layers 29 | 1.1.0 : It is now possible to merge two projects (#27). 30 | 1.0.6 : Build menus on initializationCompleted, otherwise tooltips are imperfect 31 | 1.0.5 : fix #25 32 | 1.0.4 : Add support for "trusted project" option, thanks to https://github.com/Djedouas 33 | 1.0.3 : fix #20 - Layer doesn't appear when sourced from "Integrate layers and group" 34 | 1.0.2 : Load all styles from DB if the plugin DB-Style-Manager is setup 35 | 1.0.1 : Bugfix #18. Relative paths mode 36 | 1.0.0 : Display geometry type icon, new location possible : "add layer" menu, code cleaning 37 | thanks to Etienne Trimaille (https://github.com/Gustry) 38 | Fix load-all failure 39 | 0.9.0 : Allow a project stored in database, thanks to Etienne Trimaille (https://github.com/Gustry) 40 | allow qgz projects 41 | 0.8.3 : When create group option is checked, the original layer visibility is preserved. 42 | thanks to Eric LAZZARETTI 43 | 0.8.2 : Code cleaning 44 | 0.8.1 : QGIS 2.99 compatible, Python 3, QT5 45 | 0.8.0 : Migration for QGIS3 46 | 0.7.6 : Better documentation 47 | 0.7.5 : Tooltip refinement 48 | 0.7.4 : Some python cleaning 49 | 0.7.3 : New layer id without special characters 50 | 0.7.2 : Some optimizations 51 | 0.7.1 : QGIS 2.4 compatible. Deprecated functions are deleted 52 | 0.7 : Works with "relative path" projects, and embedded layers 53 | 0.6 : QGIS 2.2 compatible 54 | 0.5 : QGIS 2.0 compatible 55 | 0.4.1 : Load all layers item, create group option (dev version 1.9) 56 | 57 | # tags are comma separated with spaces allowed 58 | tags=menu layer project 59 | 60 | homepage=https://github.com/xcaeag/MenuFromProject-Qgis-Plugin 61 | tracker=https://github.com/xcaeag/MenuFromProject-Qgis-Plugin/issues 62 | repository=https://github.com/xcaeag/MenuFromProject-Qgis-Plugin 63 | icon=resources/menu_from_project.png 64 | 65 | # experimental flag 66 | experimental=False 67 | 68 | # deprecated flag (applies to the whole plugin, not just a single version 69 | deprecated=False 70 | 71 | # Author contact information 72 | author=Xavier Culos (Agence de l'eau Adour Garonne), Etienne Trimaille, Julien M. (Oslandia) 73 | email=xavier.culos@eau-adour-garonne.fr 74 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/plugin_translation.pro: -------------------------------------------------------------------------------- 1 | SOURCES = menu_from_project.py \ 2 | logic/custom_datatypes.py \ 3 | logic/qgs_manager.py \ 4 | logic/tools.py \ 5 | ui/menu_conf_dlg.py 6 | 7 | FORMS = ui/conf_dialog.ui 8 | 9 | TRANSLATIONS = i18n/fr.ts 10 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/resources/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/resources/menu_from_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/resources/menu_from_project.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/menu_from_project/ui/__init__.py -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/qNote/README.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | qNote plugin for Quantum GIS 3 | ============================ 4 | 5 | **qNote is plugin for saving notes in QGIS project files.** 6 | 7 | This plugin is created by Piotr Pociask 8 | 9 | * project repository: https://github.com/p0cisk/qNote 10 | * bug tracker: https://github.com/p0cisk/qNote/issues 11 | 12 | Quick instruction 13 | +++++++++++++++++ 14 | 15 | Just write some information in text field and save project. 16 | When you reopen it informations automaticly loads to text field. 17 | 18 | Installation 19 | ++++++++++++ 20 | 21 | Use plugin installer in Quantum GIS or download zipped file from repository https://github.com/p0cisk/qNote/zipball/master 22 | and unpack files into your ~/.qgis/python/plugins folder. 23 | 24 | License 25 | +++++++ 26 | 27 | This program is free software; you can redistribute it and/or modify 28 | it under the terms of the GNU General Public License as published by 29 | the Free Software Foundation; either version 2 of the License, or 30 | (at your option) any later version. -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/qNote/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /*************************************************************************** 4 | qNote 5 | A QGIS plugin 6 | Save notes in QGIS projects 7 | ------------------- 8 | begin : 2012-03-31 9 | copyright : (C) 2012 by Piotr Pociask 10 | email : opengis84 (at) gmail (dot) com 11 | ***************************************************************************/ 12 | 13 | /*************************************************************************** 14 | * * 15 | * This program is free software; you can redistribute it and/or modify * 16 | * it under the terms of the GNU General Public License as published by * 17 | * the Free Software Foundation; either version 2 of the License, or * 18 | * (at your option) any later version. * 19 | * * 20 | ***************************************************************************/ 21 | This script initializes the plugin, making it known to QGIS. 22 | """ 23 | from __future__ import absolute_import 24 | def name(): 25 | return "qNote" 26 | def author(): 27 | return "GIS Support, Piotr Pociask" 28 | def email(): 29 | return "piotr.pociask@gis-support.pl" 30 | def description(): 31 | return "Save notes in QGIS projects" 32 | def version(): 33 | return "Version 1.0" 34 | def icon(): 35 | return "icon.png" 36 | def qgisMinimumVersion(): 37 | return "1.0" 38 | def qgisMaximumVersion(): 39 | return "2.99" 40 | def classFactory(iface): 41 | # load qNote class from file qNote 42 | from .qnote import qNote 43 | return qNote(iface) 44 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/qNote/metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. Beginning 2 | # with version 1.8 this is the preferred way to supply information about a 3 | # plugin. The current method of embedding metadata in __init__.py will 4 | # be supported until version 2.0 5 | 6 | # This file should be included when you package your plugin. 7 | 8 | # Mandatory items: 9 | 10 | 11 | [general] 12 | name=qNote 13 | qgisMinimumVersion=3.0 14 | qgisMaximumVersion=3.99 15 | description=Save notes in QGIS projects 16 | version=2.0 17 | about=qNote is plugin for saving text notes in QGIS project files 18 | 19 | # end of mandatory metadata 20 | 21 | # Optional items: 22 | 23 | # Uncomment the following line and add your changelog entries: 24 | changelog=2.0 25 | - port to QGIS 3 26 | 27 | 1.0 28 | - qNote is not marked as experimental from now 29 | - set qgisMaximumVersion to allow downloading in QGIS 2.0 30 | 31 | 0.1 32 | - first release 33 | 34 | # tags are comma separated with spaces allowed 35 | tags= 36 | 37 | homepage=http://www.gis-support.pl/qnote-notatki-w-qgis/ 38 | tracker=https://github.com/p0cisk/qNote/issues 39 | repository=https://github.com/p0cisk/qNote 40 | icon=icon.png 41 | # experimental flag 42 | experimental=False 43 | 44 | # deprecated flag (applies to the whole plugin, not just a single version 45 | deprecated=False 46 | 47 | # Author contact information 48 | author=GIS Support, Piotr Pociask 49 | email=piotr.pociask@gis-support.pl 50 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/qNote/qnote.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /*************************************************************************** 4 | qNote 5 | A QGIS plugin 6 | Save notes in QGIS projects 7 | ------------------- 8 | begin : 2012-03-31 9 | copyright : (C) 2012 by Piotr Pociask 10 | email : opengis84 (at) gmail (dot) com 11 | ***************************************************************************/ 12 | 13 | /*************************************************************************** 14 | * * 15 | * This program is free software; you can redistribute it and/or modify * 16 | * it under the terms of the GNU General Public License as published by * 17 | * the Free Software Foundation; either version 2 of the License, or * 18 | * (at your option) any later version. * 19 | * * 20 | ***************************************************************************/ 21 | """ 22 | # Import the PyQt and QGIS libraries 23 | from builtins import object 24 | from qgis.PyQt.QtCore import QFileInfo, QSettings, QCoreApplication, QObject, Qt 25 | from qgis.core import QgsApplication, QgsProject 26 | 27 | from qgis.PyQt import uic 28 | from os import path 29 | 30 | class qNote(object): 31 | 32 | def __init__(self, iface): 33 | # Save reference to the QGIS interface 34 | self.iface = iface 35 | 36 | def initGui(self): 37 | proj = QgsProject.instance() 38 | proj.readProject.connect(self.loadData) 39 | proj.writeProject.connect(self.saveData) 40 | self.iface.newProjectCreated .connect(self.clearEdit) 41 | 42 | pluginPath = path.dirname(path.abspath(__file__)) 43 | self.dock = uic.loadUi(path.join(pluginPath, "ui_qnote.ui")) 44 | self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.dock) 45 | self.loadData() 46 | 47 | def unload(self): 48 | self.iface.removeDockWidget(self.dock) 49 | 50 | def run(self): 51 | self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.dock) 52 | self.loadData() 53 | 54 | def saveData(self): 55 | proj = QgsProject.instance() 56 | text = self.dock.edit.toPlainText() 57 | if text: 58 | proj.writeEntry('qnote', 'data', text) 59 | else: 60 | proj.removeEntry('qnote', 'data') 61 | 62 | def loadData(self): 63 | proj = QgsProject.instance() 64 | text = proj.readEntry('qnote', 'data', '')[0] 65 | self.dock.edit.setText( text ) 66 | 67 | def clearEdit(self): 68 | self.dock.edit.setText('') -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/qNote/ui_qnote.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | qNote 4 | 5 | 6 | 7 | 0 8 | 0 9 | 634 10 | 167 11 | 12 | 13 | 14 | qNote 15 | 16 | 17 | 18 | 19 | 20 | 21 | QTextEdit::NoWrap 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: Linter 🐍 2 | 3 | env: 4 | PROJECT_FOLDER: "." 5 | PYTHON_VERSION: 3.7 6 | 7 | on: 8 | push: 9 | branches: [ master ] 10 | paths: 11 | - '**.py' 12 | pull_request: 13 | branches: [ master ] 14 | paths: 15 | - '**.py' 16 | 17 | jobs: 18 | flake8_py3: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@master 24 | 25 | - name: Setup Python 26 | uses: actions/setup-python@v2 27 | with: 28 | python-version: ${{ env.PYTHON_VERSION }} 29 | 30 | - uses: actions/cache@v2.1.4 31 | with: 32 | path: ~/.cache/pip 33 | key: ${{ runner.os }}-pip-${{ hashFiles('requirements/*.txt') }} 34 | restore-keys: | 35 | ${{ runner.os }}-pip- 36 | 37 | - name: Install project requirements 38 | run: | 39 | python -m pip install -U pip setuptools wheel 40 | python -m pip install -U flake8 41 | 42 | - name: Lint with flake8 43 | run: | 44 | # stop the build if there are Python syntax errors or undefined names 45 | flake8 ${{ env.PROJECT_FOLDER }} --count --select=E9,F63,F7,F82 --show-source --statistics 46 | # exit-zero treats all errors as warnings. 47 | flake8 ${{ env.PROJECT_FOLDER }} --count --exit-zero --statistics 48 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | Makefile 3 | *.log 4 | help/ 5 | # i18n/ 6 | scripts/ 7 | test/ 8 | .idea/ 9 | .DS_Store 10 | versions/ 11 | .venv 12 | .vscode 13 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | R1.0 2 | First QGIS2 release 3 | 4 | R1.1 5 | Toolbar disabled when project is not saved. issue fixed 6 | 7 | R1.2 8 | throws error opening new project issue fixed 9 | 10 | R1.3 11 | Line tool added 12 | 13 | R1.3.1 14 | self.gestures exception fixed 15 | 16 | R1.4 17 | Open and save sketches to file feature 18 | 19 | R1.4.1 20 | load issue fixed 21 | 22 | R1.4.2 23 | erase existing annotations on load issue fix and save project as issues fixed 24 | 25 | R1.4.3 26 | erase all action does not erase annotations issue fixed 27 | 28 | R2.0.0 29 | QGIS3 migration 30 | 31 | R2.0.1 32 | ModuleNotFoundError issue fixed 33 | 34 | R2.0.2 35 | French Translations added (courtesy of @SebastienPeillet) 36 | 37 | R2.0.3 38 | Fix for .sketch file issue (courtesy of Regis Hauburg @haubourg) 39 | 40 | R2.0.4 41 | Fix for QgsAnnotation API break (courtesy of @Fighterisr) 42 | 43 | R2.1.0 44 | Code and Pep8 cleanup, exceptions logging and external sketch file handling issues fixed ( courtesy of @Guts for Oslandia ) 45 | 46 | R2.2.0 47 | Save issue fix and CRS Trasformation support -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/README.md: -------------------------------------------------------------------------------- 1 | # Red Layer plugin 2 | 3 | A QGIS3 plugin for raw sketching and drawing on map canvas. It is intended for quick annotations and field use. Sketches can be drawn in different colors and widths over the map canvas, without mixing with existing layers but can be converted in memory layer if needed. The sketches are stored in the project directory in a separate .sketch txt file that can be shared with other users. 4 | 5 | On plugin install or with new unsaved project the toolbar is disabled: 6 | 7 | ![](icons/readme_menu_disabled.png) 8 | 9 | When the project is saved the toolbar gets enabled 10 | 11 | ![](icons/readme_menu.png) 12 | 13 | and is possible to sketch on the screen 14 | 15 | ![](icons/readme_screen.png) 16 | 17 | 18 | 19 | Tutorial on [Youtube](https://youtu.be/zLt9LB-_8rs) 20 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/__init__.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | /*************************************************************************** 5 | redLayer 6 | A QGIS plugin 7 | fast georeferenced annotation 8 | ------------------- 9 | begin : 2015-03-10 10 | copyright : (C) 2015 by Enrico Ferreguti 11 | email : enricofer@gmail.com 12 | git sha : $Format:%H$ 13 | ***************************************************************************/ 14 | 15 | /*************************************************************************** 16 | * * 17 | * This program is free software; you can redistribute it and/or modify * 18 | * it under the terms of the GNU General Public License as published by * 19 | * the Free Software Foundation; either version 2 of the License, or * 20 | * (at your option) any later version. * 21 | * * 22 | ***************************************************************************/ 23 | This script initializes the plugin, making it known to QGIS. 24 | """ 25 | 26 | 27 | # noinspection PyPep8Naming 28 | def classFactory(iface): # pylint: disable=invalid-name 29 | """Load redLayer class from file redLayer. 30 | 31 | :param iface: A QGIS interface instance. 32 | :type iface: QgsInterface 33 | """ 34 | # 35 | from .redLayerModule import redLayer 36 | return redLayer(iface) 37 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/i18n/redLayer.pro: -------------------------------------------------------------------------------- 1 | FORMS = ../redLayerModule_dialog_base.ui \ 2 | ../ui_note_dialog.ui 3 | 4 | SOURCES= ../redLayerModule.py \ 5 | ../redLayerModule_dialog.py \ 6 | ../note_class_dialog.py 7 | 8 | TRANSLATIONS = redLayer_fr.ts 9 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/i18n/redLayer_fr.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/i18n/redLayer_fr.qm -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/i18n/redLayer_fr.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | noteDialog 6 | 7 | 8 | Sketch Note 9 | Sketch Note 10 | 11 | 12 | 13 | Note 14 | Note 15 | 16 | 17 | 18 | redLayer 19 | 20 | 21 | &Red Layer 22 | &Red Layer 23 | 24 | 25 | 26 | Sketch on map 27 | Trait à main levée sur carte 28 | 29 | 30 | 31 | Draw line on map 32 | Trait droit sur carte 33 | 34 | 35 | 36 | Color and width canvas 37 | Palette et épaisseur de trait 38 | 39 | 40 | 41 | Erase sketches 42 | Gomme 43 | 44 | 45 | 46 | Remove all sketches 47 | Retirer tous les traits 48 | 49 | 50 | 51 | Add text annotations to sketches 52 | Ajouter une annotation 53 | 54 | 55 | 56 | Convert annotations to Memory Layer 57 | Convertir les annotations en couche temporaire 58 | 59 | 60 | 61 | Save sketches to file 62 | Sauvegarder les esquisses dans un fichier 63 | 64 | 65 | 66 | Load sketches from file 67 | Charger les esquisses depuis un fichier 68 | 69 | 70 | 71 | color palette 72 | palette de couleurs 73 | 74 | 75 | 76 | Remove sketches failed. 77 | 78 | 79 | 80 | 81 | Erase sketch failed. 82 | 83 | 84 | 85 | 86 | Remove unsaved action failed. 87 | 88 | 89 | 90 | 91 | Remove current sketches failed. 92 | 93 | 94 | 95 | 96 | Error connecting to project signals. 97 | 98 | 99 | 100 | 101 | Remove all annotations failed. 102 | 103 | 104 | 105 | 106 | Adding sketch to memory layer failed. 107 | 108 | 109 | 110 | 111 | redLayerDialogBase 112 | 113 | 114 | Red Layer 115 | Red Layer 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/canvas.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorBlack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorBlack.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorBlue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorBlue.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorGreen.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorPalette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorPalette.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorRed.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/colorYellow.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/erase.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/note.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 58 | 59 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/pen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/readme_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/readme_menu.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/readme_menu_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/readme_menu_disabled.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/readme_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/readme_screen.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/remove.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 58 | 59 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/sketch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/toLayer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width16.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width2.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width4.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haubourg/custom-osgeo4w-qgis/3c26b187b6b94562327338a610ca467697ba21c7/qgis-custom/apps/qgis-ltr/python/plugins/redLayer/icons/width8.png -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. Since 2 | # version 2.0 of QGIS this is the proper way to supply 3 | # information about a plugin. The old method of 4 | # embedding metadata in __init__.py will 5 | # is no longer supported since version 2.0. 6 | 7 | # This file should be included when you package your plugin.# Mandatory items: 8 | 9 | [general] 10 | name=Red Layer 11 | qgisMinimumVersion=2.99 12 | qgisMaximumVersion=3.99 13 | description=quick georeferenced sketches and annotations 14 | version=2.2 15 | author=Enrico Ferreguti 16 | email=enricofer@gmail.com 17 | about=A qgis plugin for sketching and drawing on map canvas. It is intended for quick annotations and field use. Sketches can be drawn in different colors and widths and can be converted in memory layer if needed. The sketches are stored in the project directory in a separate .sketch txt file that can be shared with other users. 18 | 19 | # End of mandatory metadata 20 | 21 | # Recommended items: 22 | 23 | # Uncomment the following line and add your changelog: 24 | changelog=R2.2.0 Save issue fix and CRS Trasformation support 25 | 26 | # Tags are comma separated with spaces allowed 27 | tags=annotations, sketch, draw, pen, 28 | 29 | homepage=http://geogear.wordpress.com 30 | tracker=https://github.com/enricofer/redLayer/issues 31 | repository=https://github.com/enricofer/redLayer 32 | category=Plugins 33 | icon=icons/sketch.svg 34 | # experimental flag 35 | experimental=False 36 | 37 | # deprecated flag (applies to the whole plugin, not just a single version) 38 | deprecated=False 39 | 40 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/note_class_dialog.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | /*************************************************************************** 5 | idtVen - class idtVen_albero 6 | A QGIS plugin 7 | compilazione assistita metadati regione veneto 8 | ------------------- 9 | begin : 2014-12-04 10 | git sha : $Format:%H$ 11 | copyright : (C) 2014 by Enrico Ferreguti 12 | email : enricofer@gmail.com 13 | ***************************************************************************/ 14 | 15 | /*************************************************************************** 16 | * * 17 | * This program is free software; you can redistribute it and/or modify * 18 | * it under the terms of the GNU General Public License as published by * 19 | * the Free Software Foundation; either version 2 of the License, or * 20 | * (at your option) any later version. * 21 | * * 22 | ***************************************************************************/ 23 | """ 24 | 25 | # standard library 26 | import logging 27 | import os 28 | 29 | # PyQGIS 30 | from qgis.core import QgsPointXY, QgsTextAnnotation 31 | from qgis.gui import QgsMapCanvasAnnotationItem 32 | from qgis.PyQt import uic 33 | from qgis.PyQt.QtGui import QTextDocument 34 | from qgis.PyQt.QtWidgets import QDialog 35 | 36 | # create the dialog for zoom to point 37 | FORM_CLASS, _ = uic.loadUiType(os.path.join( 38 | os.path.dirname(__file__), 'ui_note_dialog.ui')) 39 | 40 | # ############################################################################ 41 | # ########## Globals ############### 42 | # ################################## 43 | 44 | logger = logging.getLogger(__name__) 45 | 46 | 47 | # ############################################################################ 48 | # ########## Classes ############### 49 | # ################################## 50 | 51 | class sketchNoteDialog(QDialog, FORM_CLASS): 52 | def __init__(self, iface, parent=None): 53 | super(sketchNoteDialog, self).__init__(parent) 54 | self.setupUi(self) 55 | self.hide() 56 | self.buttonBox.accepted.connect(self.mkNote) 57 | self.buttonBox.rejected.connect(self.cancel) 58 | self.note = None 59 | self.iface = iface 60 | 61 | def setPoint(self, segment): 62 | self.point = self.midPoint(segment) 63 | 64 | def getNote(self): 65 | return self.note 66 | 67 | def getAnnotation(self): 68 | try: 69 | return self.textItem 70 | except Exception as err: 71 | logger.error(err) 72 | return None 73 | 74 | def cancel(self): 75 | self.note = "" 76 | 77 | def mkNote(self): 78 | self.textItem = self.mkAnnotation(self.noteText.toPlainText()) 79 | self.note = self.noteText.toPlainText() 80 | self.noteText.clear() 81 | 82 | def mkAnnotation(self, doc): 83 | if self.point: 84 | TD = QTextDocument(doc) 85 | item = QgsTextAnnotation() 86 | item.setMapPosition(self.point) 87 | item.setFrameSize(TD.size()) 88 | item.setDocument(TD) 89 | i = QgsMapCanvasAnnotationItem(item, self.iface.mapCanvas()) 90 | return i 91 | else: 92 | return 93 | 94 | def midPoint(self, s): 95 | x = (s.vertexAt(0).x() + s.vertexAt(1).x())/2 96 | y = (s.vertexAt(0).y() + s.vertexAt(1).y())/2 97 | return QgsPointXY(x, y) 98 | 99 | @staticmethod 100 | def newPoint(iface, segment, txt=None): 101 | dialog = sketchNoteDialog(iface) 102 | 103 | dialog.setPoint(segment) 104 | if not txt: 105 | result = dialog.exec_() 106 | dialog.show() 107 | if QDialog.Accepted: 108 | return dialog.getAnnotation() 109 | else: 110 | return None 111 | else: 112 | return dialog.mkAnnotation(txt) 113 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/redLayerModule_dialog.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | /*************************************************************************** 5 | redLayerDialog 6 | A QGIS plugin 7 | fast georeferenced annotation 8 | ------------------- 9 | begin : 2015-03-10 10 | git sha : $Format:%H$ 11 | copyright : (C) 2015 by Enrico Ferreguti 12 | email : enricofer@gmail.com 13 | ***************************************************************************/ 14 | 15 | /*************************************************************************** 16 | * * 17 | * This program is free software; you can redistribute it and/or modify * 18 | * it under the terms of the GNU General Public License as published by * 19 | * the Free Software Foundation; either version 2 of the License, or * 20 | * (at your option) any later version. * 21 | * * 22 | ***************************************************************************/ 23 | """ 24 | 25 | # standard library 26 | import os 27 | 28 | # PyQGIS 29 | from qgis.PyQt import uic 30 | from qgis.PyQt.QtWidgets import QDialog 31 | 32 | FORM_CLASS, _ = uic.loadUiType(os.path.join( 33 | os.path.dirname(__file__), 'redLayerModule_dialog_base.ui')) 34 | 35 | 36 | class redLayerDialog(QDialog, FORM_CLASS): 37 | def __init__(self, parent=None): 38 | """Constructor.""" 39 | super(redLayerDialog, self).__init__(parent) 40 | # Set up the user interface from Designer. 41 | # After setupUI you can access any designer object by doing 42 | # self., and you can use autoconnect slots - see 43 | # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html 44 | # #widgets-and-dialogs-with-auto-connect 45 | self.setupUi(self) 46 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/redLayerModule_dialog_base.ui: -------------------------------------------------------------------------------- 1 | 2 | redLayerDialogBase 3 | 4 | 5 | 6 | 0 7 | 0 8 | 400 9 | 300 10 | 11 | 12 | 13 | Red Layer 14 | 15 | 16 | 17 | 18 | 30 19 | 240 20 | 341 21 | 32 22 | 23 | 24 | 25 | Qt::Horizontal 26 | 27 | 28 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 29 | 30 | 31 | 32 | 33 | 34 | 35 | button_box 36 | accepted() 37 | redLayerDialogBase 38 | accept() 39 | 40 | 41 | 248 42 | 254 43 | 44 | 45 | 157 46 | 274 47 | 48 | 49 | 50 | 51 | button_box 52 | rejected() 53 | redLayerDialogBase 54 | reject() 55 | 56 | 57 | 316 58 | 260 59 | 60 | 61 | 286 62 | 274 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/setup.cfg: -------------------------------------------------------------------------------- 1 | # -- Packaging -------------------------------------- 2 | [metadata] 3 | description-file = README.md 4 | 5 | # -- Code quality ------------------------------------ 6 | [flake8] 7 | count = True 8 | exclude = 9 | # No need to traverse our git directory 10 | .git, 11 | # There's no value in checking cache directories 12 | __pycache__, 13 | # The conf file is mostly autogenerated, ignore it 14 | docs/conf.py, help/source/conf.py, 15 | # The old directory contains Flake8 2.0 16 | old, 17 | # This contains our built documentation 18 | build, 19 | # This contains builds of flake8 that we don't want to check 20 | dist, 21 | # This contains local virtual environments 22 | .venv*, 23 | # do not watch on tests 24 | tests, 25 | # do not consider external packages 26 | */external/*, ext_libs/* 27 | ignore = E121,E123,E126,E203,E226,E24,E704,W503,W504 28 | max-complexity = 15 29 | max-doc-length = 130 30 | max-line-length = 100 31 | output-file = dev_flake8_report.txt 32 | statistics = True 33 | tee = True 34 | 35 | [isort] 36 | multi_line_output = 3 37 | include_trailing_comma = True 38 | force_grid_wrap = 0 39 | use_parentheses = True 40 | ensure_newline_before_comments = True 41 | line_length = 88 42 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/tests/dev/dev_qfile_dialog.py: -------------------------------------------------------------------------------- 1 | #! python3 # noqa: E265 2 | 3 | """ 4 | Development script to try QFileDialog abilities and scenarii. 5 | """ 6 | 7 | from pathlib import Path 8 | from sys import exit 9 | 10 | from qgis.PyQt.QtWidgets import QFileDialog 11 | 12 | # HERE = Path(__file__).parent 13 | HERE = "/home/jmo/Git/Oslandia/Projects/Gendarmerie/redLayer/" 14 | 15 | options = QFileDialog.Options() 16 | options |= QFileDialog.DontUseNativeDialog 17 | sketch_filepath, sketch_suffix_filter = QFileDialog().getSaveFileName( 18 | parent=None, 19 | caption="Save RedLayer sketches", 20 | directory=HERE, 21 | filter="All Files (*);;Annotations (*.sketch)", 22 | initialFilter="Annotations (*.sketch)", 23 | options=options, 24 | ) 25 | 26 | if sketch_filepath: 27 | out_sketch_path = Path(sketch_filepath) 28 | if out_sketch_path.suffix != ".sketch": 29 | out_sketch_path = Path(str(out_sketch_path) + ".sketch") 30 | print("Saving sketches to {}".format(out_sketch_path.resolve())) 31 | else: 32 | exit("No file selected") 33 | 34 | if sketch_suffix_filter: 35 | print(sketch_suffix_filter) 36 | 37 | with out_sketch_path.open(mode="w", encoding="UTF8") as f: 38 | f.write("toto") 39 | -------------------------------------------------------------------------------- /qgis-custom/apps/qgis-ltr/python/plugins/redLayer/ui_note_dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | noteDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 180 10 | 131 11 | 12 | 13 | 14 | Sketch Note 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Note 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Qt::Horizontal 33 | 34 | 35 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | buttonBox 47 | accepted() 48 | noteDialog 49 | accept() 50 | 51 | 52 | 248 53 | 254 54 | 55 | 56 | 157 57 | 274 58 | 59 | 60 | 61 | 62 | buttonBox 63 | rejected() 64 | noteDialog 65 | reject() 66 | 67 | 68 | 316 69 | 260 70 | 71 | 72 | 286 73 | 274 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /qgis-custom/etc/postinstall/qgis-custom.bat: -------------------------------------------------------------------------------- 1 | @REM install QGIS custom launcher 2 | @echo on 3 | echo "Starting postinstall qgis-custom .bat" 4 | 5 | set OSGEO4W_ROOT=%OSGEO4W_ROOT:\=\\% 6 | 7 | @REM backup native QGIS bat files and shortcuts 8 | 9 | move /Y "%OSGEO4W_ROOT%\bin\qgis-ltr.bat" "%OSGEO4W_ROOT%\bin\qgis-ltr-natif.bat" 10 | 11 | move /Y "%AppData%\Microsoft\Windows\Start Menu\Programs\QGIS3.lnk" "%OSGEO4W_ROOT%\apps\qgis-custom\qgis-ltr-backup\startmenu_links\ 12 | move /Y "%OSGEO4W_STARTMENU%\*" "%OSGEO4W_ROOT%\apps\qgis-custom\qgis-ltr-backup\startmenu_links\ 13 | 14 | @REM delete of backup link (may remain from previous install) 15 | del "%OSGEO4W_ROOT%\apps\qgis-custom\qgis-ltr-backup\QGIS CUSTOM (LTR).lnk" 16 | 17 | 18 | @rem copy launcher and make a shortcut in start menu 19 | move /Y "%OSGEO4W_ROOT%\apps\qgis-custom\qgis-ltr-custom.bat.template" "%OSGEO4W_ROOT%\bin\qgis-ltr-custom.bat" 20 | 21 | nircmd shortcut "%OSGEO4W_ROOT%\bin\nircmd.exe" "%OSGEO4W_STARTMENU%" "QGIS custom (LTR)" "exec hide ~q%OSGEO4W_ROOT%\bin\qgis-ltr-custom.bat~q" "%OSGEO4W_ROOT%\apps\qgis-ltr\icons\qgis.ico" 22 | 23 | @REM file associations 24 | 25 | textreplace -std -t "%OSGEO4W_ROOT%\apps\qgis-custom\bin\qgis-custom-ltr.reg" 26 | nircmd elevate "%WINDIR%\regedit" /s "%OSGEO4W_ROOT%\apps\qgis-custom\bin\qgis-custom-ltr.reg" 27 | 28 | echo "End of qgis-custom postinstall" 29 | 30 | @echo off 31 | exit /b 0 32 | .lnk -------------------------------------------------------------------------------- /qgis-custom/etc/preremove/qgis-custom.bat: -------------------------------------------------------------------------------- 1 | @REM puts back QGIS native launchers and file associations 2 | 3 | echo "running .bat preremove qgis-custom " 4 | 5 | 6 | @REM deletes .bat et and custom shortcuts 7 | 8 | del "%OSGEO4W_ROOT%\bin\qgis-ltr-custom.bat" 9 | del "%OSGEO4W_STARTMENU%\QGIS custom (LTR).lnk" 10 | 11 | @REM del "%OSGEO4W_ROOT%\bin\qgis-ltr-custom-bin.vars" 12 | @REM del "%OSGEO4W_ROOT%\bin\qgis-ltr-custom-bin.env" 13 | 14 | @REM cleans python compiled files (should be adapted to Python3 cache) 15 | del /s /q "%OSGEO4W_ROOT%\apps\qgis-custom\python\*.pyc" 16 | 17 | @REM deletes custom shortcut backup (may remain) 18 | del "%OSGEO4W_ROOT%\apps\qgis-custom\qgis-ltr-backup\QGIS CUSTOM (LTR).lnk" 19 | 20 | @REM delete old reg key association 21 | 22 | del "%OSGEO4W_ROOT%\apps\qgis-custom\bin\qgis-custom-ltr.reg" 23 | 24 | @REM restore native shortcuts 25 | 26 | move /Y "%OSGEO4W_ROOT%\bin\qgis-ltr-natif.bat" "%OSGEO4W_ROOT%\bin\qgis-ltr.bat" 27 | 28 | move /Y "%OSGEO4W_ROOT%\apps\qgis-custom\qgis-ltr-backup\startmenu_links\*.lnk" "%OSGEO4W_STARTMENU%\" 29 | 30 | 31 | @REM replays file associations for qgs / qgz with QGIS native 32 | 33 | 34 | set OSGEO4W_ROOT=%OSGEO4W_ROOT:\=\\% 35 | textreplace -std -t "%OSGEO4W_ROOT%\apps\qgis-ltr\bin\qgis.reg" 36 | nircmd elevate "%WINDIR%\regedit" /s "%OSGEO4W_ROOT%\apps\qgis-ltr\bin\qgis.reg" -------------------------------------------------------------------------------- /qgis-custom/setup.hint: -------------------------------------------------------------------------------- 1 | sdesc: "QGIS LTR configuration package" 2 | ldesc: "QGIS LTR custom configuration package" 3 | maintainer: RHaubourg 4 | category: Desktop 5 | requires: qgis-ltr 6 | version: 0.9-2 7 | install: x86_64/release/qgis/qgis-custom/qgis-custom-0.9-2.tar.bz2 8 | --------------------------------------------------------------------------------