Browse Source

OSMtools_IncludeGraphHopper
nilsnolde 2 years ago
parent
commit
a714c2866d

+ 229
- 0
Makefile View File

@@ -0,0 +1,229 @@
1
+#/***************************************************************************
2
+# ORStools
3
+#
4
+# falk
5
+#							 -------------------
6
+#		begin				: 2017-02-01
7
+#		git sha				: $Format:%H$
8
+#		copyright			: (C) 2017 by nils
9
+#		email				: nils
10
+# ***************************************************************************/
11
+#
12
+#/***************************************************************************
13
+# *																		 *
14
+# *   This program is free software; you can redistribute it and/or modify  *
15
+# *   it under the terms of the GNU General Public License as published by  *
16
+# *   the Free Software Foundation; either version 2 of the License, or	 *
17
+# *   (at your option) any later version.								   *
18
+# *																		 *
19
+# ***************************************************************************/
20
+
21
+#################################################
22
+# Edit the following to match your sources lists
23
+#################################################
24
+
25
+
26
+#Add iso code for any locales you want to support here (space separated)
27
+# default is no locales
28
+# LOCALES = af
29
+LOCALES =
30
+
31
+# If locales are enabled, set the name of the lrelease binary on your system. If
32
+# you have trouble compiling the translations, you may have to specify the full path to
33
+# lrelease
34
+#LRELEASE = lrelease
35
+#LRELEASE = lrelease-qt4
36
+
37
+
38
+# translation
39
+SOURCES = \
40
+	__init__.py \
41
+	ors_tools.py ors_tools_dialog.py
42
+
43
+PLUGINNAME = ORStools
44
+
45
+PY_FILES = \
46
+	__init__.py \
47
+	ors_tools.py ors_tools_dialog.py
48
+
49
+UI_FILES = ors_tools_dialog_base.ui
50
+
51
+EXTRAS = metadata.txt icon.png
52
+
53
+EXTRA_DIRS =
54
+
55
+COMPILED_RESOURCE_FILES = resources.py
56
+
57
+PEP8EXCLUDE=pydev,resources.py,conf.py,third_party,ui
58
+
59
+
60
+#################################################
61
+# Normally you would not need to edit below here
62
+#################################################
63
+
64
+HELP = help/build/html
65
+
66
+PLUGIN_UPLOAD = $(c)/plugin_upload.py
67
+
68
+RESOURCE_SRC=$(shell grep '^ *<file' resources.qrc | sed 's@</file>@@g;s/.*>//g' | tr '\n' ' ')
69
+
70
+QGISDIR=.qgis2
71
+
72
+default: compile
73
+
74
+compile: $(COMPILED_RESOURCE_FILES)
75
+
76
+%.py : %.qrc $(RESOURCES_SRC)
77
+	pyrcc4 -o $*.py  $<
78
+
79
+%.qm : %.ts
80
+	$(LRELEASE) $<
81
+
82
+test: compile transcompile
83
+	@echo
84
+	@echo "----------------------"
85
+	@echo "Regression Test Suite"
86
+	@echo "----------------------"
87
+
88
+	@# Preceding dash means that make will continue in case of errors
89
+	@-export PYTHONPATH=`pwd`:$(PYTHONPATH); \
90
+		export QGIS_DEBUG=0; \
91
+		export QGIS_LOG_FILE=/dev/null; \
92
+		nosetests -v --with-id --with-coverage --cover-package=. \
93
+		3>&1 1>&2 2>&3 3>&- || true
94
+	@echo "----------------------"
95
+	@echo "If you get a 'no module named qgis.core error, try sourcing"
96
+	@echo "the helper script we have provided first then run make test."
97
+	@echo "e.g. source run-env-linux.sh <path to qgis install>; make test"
98
+	@echo "----------------------"
99
+
100
+deploy: compile doc transcompile
101
+	@echo
102
+	@echo "------------------------------------------"
103
+	@echo "Deploying plugin to your .qgis2 directory."
104
+	@echo "------------------------------------------"
105
+	# The deploy  target only works on unix like operating system where
106
+	# the Python plugin directory is located at:
107
+	# $HOME/$(QGISDIR)/python/plugins
108
+	mkdir -p $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
109
+	cp -vf $(PY_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
110
+	cp -vf $(UI_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
111
+	cp -vf $(COMPILED_RESOURCE_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
112
+	cp -vf $(EXTRAS) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
113
+	cp -vfr i18n $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
114
+	cp -vfr $(HELP) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)/help
115
+	# Copy extra directories if any
116
+  # (temporarily removed)
117
+
118
+
119
+# The dclean target removes compiled python files from plugin directory
120
+# also deletes any .git entry
121
+dclean:
122
+	@echo
123
+	@echo "-----------------------------------"
124
+	@echo "Removing any compiled python files."
125
+	@echo "-----------------------------------"
126
+	find $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) -iname "*.pyc" -delete
127
+	find $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) -iname ".git" -prune -exec rm -Rf {} \;
128
+
129
+
130
+derase:
131
+	@echo
132
+	@echo "-------------------------"
133
+	@echo "Removing deployed plugin."
134
+	@echo "-------------------------"
135
+	rm -Rf $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
136
+
137
+zip: deploy dclean
138
+	@echo
139
+	@echo "---------------------------"
140
+	@echo "Creating plugin zip bundle."
141
+	@echo "---------------------------"
142
+	# The zip target deploys the plugin and creates a zip file with the deployed
143
+	# content. You can then upload the zip file on http://plugins.qgis.org
144
+	rm -f $(PLUGINNAME).zip
145
+	cd $(HOME)/$(QGISDIR)/python/plugins; zip -9r $(CURDIR)/$(PLUGINNAME).zip $(PLUGINNAME)
146
+
147
+package: compile
148
+	# Create a zip package of the plugin named $(PLUGINNAME).zip.
149
+	# This requires use of git (your plugin development directory must be a
150
+	# git repository).
151
+	# To use, pass a valid commit or tag as follows:
152
+	#   make package VERSION=Version_0.3.2
153
+	@echo
154
+	@echo "------------------------------------"
155
+	@echo "Exporting plugin to zip package.	"
156
+	@echo "------------------------------------"
157
+	rm -f $(PLUGINNAME).zip
158
+	git archive --prefix=$(PLUGINNAME)/ -o $(PLUGINNAME).zip $(VERSION)
159
+	echo "Created package: $(PLUGINNAME).zip"
160
+
161
+upload: zip
162
+	@echo
163
+	@echo "-------------------------------------"
164
+	@echo "Uploading plugin to QGIS Plugin repo."
165
+	@echo "-------------------------------------"
166
+	$(PLUGIN_UPLOAD) $(PLUGINNAME).zip
167
+
168
+transup:
169
+	@echo
170
+	@echo "------------------------------------------------"
171
+	@echo "Updating translation files with any new strings."
172
+	@echo "------------------------------------------------"
173
+	@chmod +x scripts/update-strings.sh
174
+	@scripts/update-strings.sh $(LOCALES)
175
+
176
+transcompile:
177
+	@echo
178
+	@echo "----------------------------------------"
179
+	@echo "Compiled translation files to .qm files."
180
+	@echo "----------------------------------------"
181
+	@chmod +x scripts/compile-strings.sh
182
+	@scripts/compile-strings.sh $(LRELEASE) $(LOCALES)
183
+
184
+transclean:
185
+	@echo
186
+	@echo "------------------------------------"
187
+	@echo "Removing compiled translation files."
188
+	@echo "------------------------------------"
189
+	rm -f i18n/*.qm
190
+
191
+clean:
192
+	@echo
193
+	@echo "------------------------------------"
194
+	@echo "Removing uic and rcc generated files"
195
+	@echo "------------------------------------"
196
+	rm $(COMPILED_UI_FILES) $(COMPILED_RESOURCE_FILES)
197
+
198
+doc:
199
+	@echo
200
+	@echo "------------------------------------"
201
+	@echo "Building documentation using sphinx."
202
+	@echo "------------------------------------"
203
+	cd help; make html
204
+
205
+pylint:
206
+	@echo
207
+	@echo "-----------------"
208
+	@echo "Pylint violations"
209
+	@echo "-----------------"
210
+	@pylint --reports=n --rcfile=pylintrc . || true
211
+	@echo
212
+	@echo "----------------------"
213
+	@echo "If you get a 'no module named qgis.core' error, try sourcing"
214
+	@echo "the helper script we have provided first then run make pylint."
215
+	@echo "e.g. source run-env-linux.sh <path to qgis install>; make pylint"
216
+	@echo "----------------------"
217
+
218
+
219
+# Run pep8 style checking
220
+#http://pypi.python.org/pypi/pep8
221
+pep8:
222
+	@echo
223
+	@echo "-----------"
224
+	@echo "PEP8 issues"
225
+	@echo "-----------"
226
+	@pep8 --repeat --ignore=E203,E121,E122,E123,E124,E125,E126,E127,E128 --exclude $(PEP8EXCLUDE) . || true
227
+	@echo "-----------"
228
+	@echo "Ignored in PEP8 check:"
229
+	@echo $(PEP8EXCLUDE)

+ 42
- 0
README.html View File

@@ -0,0 +1,42 @@
1
+<html>
2
+<body>
3
+<h3>Plugin Builder Results</h3>
4
+
5
+Congratulations! You just built a plugin for QGIS!<br/><br />
6
+
7
+<div id='help' style='font-size:.9em;'>
8
+Your plugin <b>ORStools</b> was created in:<br>
9
+&nbsp;&nbsp;<b>C:\Users\nnolde\Documents\Python_Scripts\QGIS_Plugins\ORStools</b>
10
+<p>
11
+Your QGIS plugin directory is located at:<br>
12
+&nbsp;&nbsp;<b>C:/Users/nnolde/.qgis2/python/plugins</b>
13
+<p>
14
+<h3>What's Next</h3>
15
+<ol>
16
+    <li>In your plugin directory, compile the resources file using pyrcc4 (simply run <b>make</b> if you have automake or use <b>pb_tool</b>)
17
+    <li>Test the generated sources using <b>make test</b> (or run tests from your IDE)
18
+    <li>Copy the entire directory containing your new plugin to the QGIS plugin directory (see Notes below)
19
+    <li>Test the plugin by enabling it in the QGIS plugin manager
20
+    <li>Customize it by editing the implementation file <b>ors_tools.py</b>
21
+    <li>Create your own custom icon, replacing the default <b>icon.png</b>
22
+    <li>Modify your user interface by opening <b>ors_tools_dialog_base.ui</b> in Qt Designer
23
+</ol>
24
+Notes:
25
+<ul>
26
+    <li>You can use the <b>Makefile</b> to compile and deploy when you
27
+        make changes. This requires GNU make (gmake). The Makefile is ready to use, however you 
28
+        will have to edit it to add addional Python source files, dialogs, and translations.
29
+    <li>You can also use <b>pb_tool</b> to compile and deploy your plugin. Tweak the <i>pb_tool.cfg</i> file included with your plugin as you add files. Install <b>pb_tool</b> using 
30
+        <i>pip</i> or <i>easy_install</i>. See <a href="http://loc8.cc/pb_tool">http://loc8.cc/pb_tool</a> for more information.
31
+</ul>
32
+</div>
33
+<div style='font-size:.9em;'>
34
+<p>
35
+For information on writing PyQGIS code, see <a href="http://loc8.cc/pyqgis_resources">http://loc8.cc/pyqgis_resources</a> for a list of resources.
36
+</p>
37
+</div>
38
+<p>
39
+&copy;2011-2016 GeoApt LLC - geoapt.com 
40
+</p>
41
+</body>
42
+</html>

+ 33
- 0
README.txt View File

@@ -0,0 +1,33 @@
1
+Plugin Builder Results
2
+
3
+Your plugin ORStools was created in:
4
+    C:\Users\nnolde\Documents\Python_Scripts\QGIS_Plugins\ORStools
5
+
6
+Your QGIS plugin directory is located at:
7
+    C:/Users/nnolde/.qgis2/python/plugins
8
+
9
+What's Next:
10
+
11
+  * Copy the entire directory containing your new plugin to the QGIS plugin
12
+    directory
13
+
14
+  * Compile the resources file using pyrcc4
15
+
16
+  * Run the tests (``make test``)
17
+
18
+  * Test the plugin by enabling it in the QGIS plugin manager
19
+
20
+  * Customize it by editing the implementation file: ``ors_tools.py``
21
+
22
+  * Create your own custom icon, replacing the default icon.png
23
+
24
+  * Modify your user interface by opening ORStools.ui in Qt Designer
25
+
26
+  * You can use the Makefile to compile your Ui and resource files when
27
+    you make changes. This requires GNU make (gmake)
28
+
29
+For more information, see the PyQGIS Developer Cookbook at:
30
+http://www.qgis.org/pyqgis-cookbook/index.html
31
+
32
+(C) 2011-2014 GeoApt LLC - geoapt.com
33
+Git revision : $Format:%H$

+ 35
- 0
__init__.py View File

@@ -0,0 +1,35 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+/***************************************************************************
4
+ ORStools
5
+                                 A QGIS plugin
6
+ falk
7
+                             -------------------
8
+        begin                : 2017-02-01
9
+        copyright            : (C) 2017 by nils
10
+        email                : nils
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 ORStools class from file ORStools.
29
+
30
+    :param iface: A QGIS interface instance.
31
+    :type iface: QgsInterface
32
+    """
33
+    #
34
+    from .ors_tools import ORStools
35
+    return ORStools(iface)

+ 1
- 0
apikey.txt View File

@@ -0,0 +1 @@
1
+ee0b8233adff52ce9fd6afc2a2859a28

+ 130
- 0
help/Makefile View File

@@ -0,0 +1,130 @@
1
+# Makefile for Sphinx documentation
2
+#
3
+
4
+# You can set these variables from the command line.
5
+SPHINXOPTS    =
6
+SPHINXBUILD   = sphinx-build
7
+PAPER         =
8
+BUILDDIR      = build
9
+
10
+# Internal variables.
11
+PAPEROPT_a4     = -D latex_paper_size=a4
12
+PAPEROPT_letter = -D latex_paper_size=letter
13
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
14
+
15
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
16
+
17
+help:
18
+	@echo "Please use \`make <target>' where <target> is one of"
19
+	@echo "  html       to make standalone HTML files"
20
+	@echo "  dirhtml    to make HTML files named index.html in directories"
21
+	@echo "  singlehtml to make a single large HTML file"
22
+	@echo "  pickle     to make pickle files"
23
+	@echo "  json       to make JSON files"
24
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
25
+	@echo "  qthelp     to make HTML files and a qthelp project"
26
+	@echo "  devhelp    to make HTML files and a Devhelp project"
27
+	@echo "  epub       to make an epub"
28
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
29
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
30
+	@echo "  text       to make text files"
31
+	@echo "  man        to make manual pages"
32
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
33
+	@echo "  linkcheck  to check all external links for integrity"
34
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
35
+
36
+clean:
37
+	-rm -rf $(BUILDDIR)/*
38
+
39
+html:
40
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
41
+	@echo
42
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
43
+
44
+dirhtml:
45
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
46
+	@echo
47
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
48
+
49
+singlehtml:
50
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
51
+	@echo
52
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
53
+
54
+pickle:
55
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
56
+	@echo
57
+	@echo "Build finished; now you can process the pickle files."
58
+
59
+json:
60
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
61
+	@echo
62
+	@echo "Build finished; now you can process the JSON files."
63
+
64
+htmlhelp:
65
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
66
+	@echo
67
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
68
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
69
+
70
+qthelp:
71
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
72
+	@echo
73
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
74
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
75
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/template_class.qhcp"
76
+	@echo "To view the help file:"
77
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/template_class.qhc"
78
+
79
+devhelp:
80
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
81
+	@echo
82
+	@echo "Build finished."
83
+	@echo "To view the help file:"
84
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/template_class"
85
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/template_class"
86
+	@echo "# devhelp"
87
+
88
+epub:
89
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
90
+	@echo
91
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
92
+
93
+latex:
94
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
95
+	@echo
96
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
97
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
98
+	      "(use \`make latexpdf' here to do that automatically)."
99
+
100
+latexpdf:
101
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
102
+	@echo "Running LaTeX files through pdflatex..."
103
+	make -C $(BUILDDIR)/latex all-pdf
104
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
105
+
106
+text:
107
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
108
+	@echo
109
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
110
+
111
+man:
112
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
113
+	@echo
114
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
115
+
116
+changes:
117
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
118
+	@echo
119
+	@echo "The overview file is in $(BUILDDIR)/changes."
120
+
121
+linkcheck:
122
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
123
+	@echo
124
+	@echo "Link check complete; look for any errors in the above output " \
125
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
126
+
127
+doctest:
128
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
129
+	@echo "Testing of doctests in the sources finished, look at the " \
130
+	      "results in $(BUILDDIR)/doctest/output.txt."

+ 155
- 0
help/make.bat View File

@@ -0,0 +1,155 @@
1
+@ECHO OFF
2
+
3
+REM Command file for Sphinx documentation
4
+
5
+if "%SPHINXBUILD%" == "" (
6
+	set SPHINXBUILD=sphinx-build
7
+)
8
+set BUILDDIR=build
9
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
10
+if NOT "%PAPER%" == "" (
11
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
12
+)
13
+
14
+if "%1" == "" goto help
15
+
16
+if "%1" == "help" (
17
+	:help
18
+	echo.Please use `make ^<target^>` where ^<target^> is one of
19
+	echo.  html       to make standalone HTML files
20
+	echo.  dirhtml    to make HTML files named index.html in directories
21
+	echo.  singlehtml to make a single large HTML file
22
+	echo.  pickle     to make pickle files
23
+	echo.  json       to make JSON files
24
+	echo.  htmlhelp   to make HTML files and a HTML help project
25
+	echo.  qthelp     to make HTML files and a qthelp project
26
+	echo.  devhelp    to make HTML files and a Devhelp project
27
+	echo.  epub       to make an epub
28
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
29
+	echo.  text       to make text files
30
+	echo.  man        to make manual pages
31
+	echo.  changes    to make an overview over all changed/added/deprecated items
32
+	echo.  linkcheck  to check all external links for integrity
33
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
34
+	goto end
35
+)
36
+
37
+if "%1" == "clean" (
38
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
39
+	del /q /s %BUILDDIR%\*
40
+	goto end
41
+)
42
+
43
+if "%1" == "html" (
44
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
45
+	echo.
46
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
47
+	goto end
48
+)
49
+
50
+if "%1" == "dirhtml" (
51
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
52
+	echo.
53
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
54
+	goto end
55
+)
56
+
57
+if "%1" == "singlehtml" (
58
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
59
+	echo.
60
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
61
+	goto end
62
+)
63
+
64
+if "%1" == "pickle" (
65
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
66
+	echo.
67
+	echo.Build finished; now you can process the pickle files.
68
+	goto end
69
+)
70
+
71
+if "%1" == "json" (
72
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
73
+	echo.
74
+	echo.Build finished; now you can process the JSON files.
75
+	goto end
76
+)
77
+
78
+if "%1" == "htmlhelp" (
79
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
80
+	echo.
81
+	echo.Build finished; now you can run HTML Help Workshop with the ^
82
+.hhp project file in %BUILDDIR%/htmlhelp.
83
+	goto end
84
+)
85
+
86
+if "%1" == "qthelp" (
87
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
88
+	echo.
89
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
90
+.qhcp project file in %BUILDDIR%/qthelp, like this:
91
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\template_class.qhcp
92
+	echo.To view the help file:
93
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\template_class.ghc
94
+	goto end
95
+)
96
+
97
+if "%1" == "devhelp" (
98
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
99
+	echo.
100
+	echo.Build finished.
101
+	goto end
102
+)
103
+
104
+if "%1" == "epub" (
105
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
106
+	echo.
107
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
108
+	goto end
109
+)
110
+
111
+if "%1" == "latex" (
112
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
113
+	echo.
114
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
115
+	goto end
116
+)
117
+
118
+if "%1" == "text" (
119
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
120
+	echo.
121
+	echo.Build finished. The text files are in %BUILDDIR%/text.
122
+	goto end
123
+)
124
+
125
+if "%1" == "man" (
126
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
127
+	echo.
128
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
129
+	goto end
130
+)
131
+
132
+if "%1" == "changes" (
133
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
134
+	echo.
135
+	echo.The overview file is in %BUILDDIR%/changes.
136
+	goto end
137
+)
138
+
139
+if "%1" == "linkcheck" (
140
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
141
+	echo.
142
+	echo.Link check complete; look for any errors in the above output ^
143
+or in %BUILDDIR%/linkcheck/output.txt.
144
+	goto end
145
+)
146
+
147
+if "%1" == "doctest" (
148
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
149
+	echo.
150
+	echo.Testing of doctests in the sources finished, look at the ^
151
+results in %BUILDDIR%/doctest/output.txt.
152
+	goto end
153
+)
154
+
155
+:end

+ 216
- 0
help/source/conf.py View File

@@ -0,0 +1,216 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# ORStools documentation build configuration file, created by
4
+# sphinx-quickstart on Sun Feb 12 17:11:03 2012.
5
+#
6
+# This file is execfile()d with the current directory set to its containing dir.
7
+#
8
+# Note that not all possible configuration values are present in this
9
+# autogenerated file.
10
+#
11
+# All configuration values have a default; values that are commented out
12
+# serve to show the default.
13
+
14
+import sys, os
15
+
16
+# If extensions (or modules to document with autodoc) are in another directory,
17
+# add these directories to sys.path here. If the directory is relative to the
18
+# documentation root, use os.path.abspath to make it absolute, like shown here.
19
+#sys.path.insert(0, os.path.abspath('.'))
20
+
21
+# -- General configuration -----------------------------------------------------
22
+
23
+# If your documentation needs a minimal Sphinx version, state it here.
24
+#needs_sphinx = '1.0'
25
+
26
+# Add any Sphinx extension module names here, as strings. They can be extensions
27
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28
+extensions = ['sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.viewcode']
29
+
30
+# Add any paths that contain templates here, relative to this directory.
31
+templates_path = ['_templates']
32
+
33
+# The suffix of source filenames.
34
+source_suffix = '.rst'
35
+
36
+# The encoding of source files.
37
+#source_encoding = 'utf-8-sig'
38
+
39
+# The master toctree document.
40
+master_doc = 'index'
41
+
42
+# General information about the project.
43
+project = u'ORStools'
44
+copyright = u'2013, nils'
45
+
46
+# The version info for the project you're documenting, acts as replacement for
47
+# |version| and |release|, also used in various other places throughout the
48
+# built documents.
49
+#
50
+# The short X.Y version.
51
+version = '0.1'
52
+# The full version, including alpha/beta/rc tags.
53
+release = '0.1'
54
+
55
+# The language for content autogenerated by Sphinx. Refer to documentation
56
+# for a list of supported languages.
57
+#language = None
58
+
59
+# There are two options for replacing |today|: either, you set today to some
60
+# non-false value, then it is used:
61
+#today = ''
62
+# Else, today_fmt is used as the format for a strftime call.
63
+#today_fmt = '%B %d, %Y'
64
+
65
+# List of patterns, relative to source directory, that match files and
66
+# directories to ignore when looking for source files.
67
+exclude_patterns = []
68
+
69
+# The reST default role (used for this markup: `text`) to use for all documents.
70
+#default_role = None
71
+
72
+# If true, '()' will be appended to :func: etc. cross-reference text.
73
+#add_function_parentheses = True
74
+
75
+# If true, the current module name will be prepended to all description
76
+# unit titles (such as .. function::).
77
+#add_TemplateModuleNames = True
78
+
79
+# If true, sectionauthor and moduleauthor directives will be shown in the
80
+# output. They are ignored by default.
81
+#show_authors = False
82
+
83
+# The name of the Pygments (syntax highlighting) style to use.
84
+pygments_style = 'sphinx'
85
+
86
+# A list of ignored prefixes for module index sorting.
87
+#modindex_common_prefix = []
88
+
89
+
90
+# -- Options for HTML output ---------------------------------------------------
91
+
92
+# The theme to use for HTML and HTML Help pages.  See the documentation for
93
+# a list of builtin themes.
94
+html_theme = 'default'
95
+
96
+# Theme options are theme-specific and customize the look and feel of a theme
97
+# further.  For a list of options available for each theme, see the
98
+# documentation.
99
+#html_theme_options = {}
100
+
101
+# Add any paths that contain custom themes here, relative to this directory.
102
+#html_theme_path = []
103
+
104
+# The name for this set of Sphinx documents.  If None, it defaults to
105
+# "<project> v<release> documentation".
106
+#html_title = None
107
+
108
+# A shorter title for the navigation bar.  Default is the same as html_title.
109
+#html_short_title = None
110
+
111
+# The name of an image file (relative to this directory) to place at the top
112
+# of the sidebar.
113
+#html_logo = None
114
+
115
+# The name of an image file (within the static path) to use as favicon of the
116
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
117
+# pixels large.
118
+#html_favicon = None
119
+
120
+# Add any paths that contain custom static files (such as style sheets) here,
121
+# relative to this directory. They are copied after the builtin static files,
122
+# so a file named "default.css" will overwrite the builtin "default.css".
123
+html_static_path = ['_static']
124
+
125
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126
+# using the given strftime format.
127
+#html_last_updated_fmt = '%b %d, %Y'
128
+
129
+# If true, SmartyPants will be used to convert quotes and dashes to
130
+# typographically correct entities.
131
+#html_use_smartypants = True
132
+
133
+# Custom sidebar templates, maps document names to template names.
134
+#html_sidebars = {}
135
+
136
+# Additional templates that should be rendered to pages, maps page names to
137
+# template names.
138
+#html_additional_pages = {}
139
+
140
+# If false, no module index is generated.
141
+#html_domain_indices = True
142
+
143
+# If false, no index is generated.
144
+#html_use_index = True
145
+
146
+# If true, the index is split into individual pages for each letter.
147
+#html_split_index = False
148
+
149
+# If true, links to the reST sources are added to the pages.
150
+#html_show_sourcelink = True
151
+
152
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153
+#html_show_sphinx = True
154
+
155
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156
+#html_show_copyright = True
157
+
158
+# If true, an OpenSearch description file will be output, and all pages will
159
+# contain a <link> tag referring to it.  The value of this option must be the
160
+# base URL from which the finished HTML is served.
161
+#html_use_opensearch = ''
162
+
163
+# This is the file name suffix for HTML files (e.g. ".xhtml").
164
+#html_file_suffix = None
165
+
166
+# Output file base name for HTML help builder.
167
+htmlhelp_basename = 'TemplateClassdoc'
168
+
169
+
170
+# -- Options for LaTeX output --------------------------------------------------
171
+
172
+# The paper size ('letter' or 'a4').
173
+#latex_paper_size = 'letter'
174
+
175
+# The font size ('10pt', '11pt' or '12pt').
176
+#latex_font_size = '10pt'
177
+
178
+# Grouping the document tree into LaTeX files. List of tuples
179
+# (source start file, target name, title, author, documentclass [howto/manual]).
180
+latex_documents = [
181
+  ('index', 'ORStools.tex', u'ORStools Documentation',
182
+   u'nils', 'manual'),
183
+]
184
+
185
+# The name of an image file (relative to this directory) to place at the top of
186
+# the title page.
187
+#latex_logo = None
188
+
189
+# For "manual" documents, if this is true, then toplevel headings are parts,
190
+# not chapters.
191
+#latex_use_parts = False
192
+
193
+# If true, show page references after internal links.
194
+#latex_show_pagerefs = False
195
+
196
+# If true, show URL addresses after external links.
197
+#latex_show_urls = False
198
+
199
+# Additional stuff for the LaTeX preamble.
200
+#latex_preamble = ''
201
+
202
+# Documents to append as an appendix to all manuals.
203
+#latex_appendices = []
204
+
205
+# If false, no module index is generated.
206
+#latex_domain_indices = True
207
+
208
+
209
+# -- Options for manual page output --------------------------------------------
210
+
211
+# One entry per manual page. List of tuples
212
+# (source start file, name, description, authors, manual section).
213
+man_pages = [
214
+    ('index', 'TemplateClass', u'ORStools Documentation',
215
+     [u'nils'], 1)
216
+]

+ 20
- 0
help/source/index.rst View File

@@ -0,0 +1,20 @@
1
+.. ORStools documentation master file, created by
2
+   sphinx-quickstart on Sun Feb 12 17:11:03 2012.
3
+   You can adapt this file completely to your liking, but it should at least
4
+   contain the root `toctree` directive.
5
+
6
+Welcome to ORStools's documentation!
7
+============================================
8
+
9
+Contents:
10
+
11
+.. toctree::
12
+   :maxdepth: 2
13
+
14
+Indices and tables
15
+==================
16
+
17
+* :ref:`genindex`
18
+* :ref:`modindex`
19
+* :ref:`search`
20
+

+ 11
- 0
i18n/af.ts View File

@@ -0,0 +1,11 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!DOCTYPE TS><TS version="2.0" language="af" sourcelanguage="en">
3
+<context>
4
+    <name>@default</name>
5
+    <message>
6
+        <location filename="test_translations.py" line="48"/>
7
+        <source>Good morning</source>
8
+        <translation>Goeie more</translation>
9
+    </message>
10
+</context>
11
+</TS>

BIN
icon.png View File


BIN
icon_locate.png View File


+ 39
- 0
metadata.txt View File

@@ -0,0 +1,39 @@
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=ORS Tools
11
+qgisMinimumVersion=2.0
12
+description=falk
13
+version=0.1
14
+author=nils
15
+email=nils
16
+
17
+about=sadf
18
+
19
+tracker=mimi
20
+repository=mimi
21
+# End of mandatory metadata
22
+
23
+# Recommended items:
24
+
25
+# Uncomment the following line and add your changelog:
26
+# changelog=
27
+
28
+# Tags are comma separated with spaces allowed
29
+tags=routing
30
+
31
+homepage=mimi
32
+category=Plugins
33
+icon=icon.png
34
+# experimental flag
35
+experimental=False
36
+
37
+# deprecated flag (applies to the whole plugin, not just a single version)
38
+deprecated=False
39
+

+ 249
- 0
ors_tools.py View File

@@ -0,0 +1,249 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+/***************************************************************************
4
+ ORStools
5
+                                 A QGIS plugin
6
+ falk
7
+                              -------------------
8
+        begin                : 2017-02-01
9
+        git sha              : $Format:%H$
10
+        copyright            : (C) 2017 by Nils Nolde
11
+        email                : nils.nolde@gmail.com
12
+ ***************************************************************************/
13
+ 
14
+ This plugin provides access to the various APIs from OpenRouteService 
15
+ (http://openrouteservice.readthedocs.io/en/1.0/api.html), developed and 
16
+ maintained by GIScience team at University of Heidelberg, Germany. By using 
17
+ this plugin you agree to the ORS terms of service
18
+ (http://openrouteservice.readthedocs.io/en/1.0/tos.html#terms-of-service).
19
+ 
20
+/***************************************************************************
21
+ *                                                                         *
22
+ *   This program is free software; you can redistribute it and/or modify  *
23
+ *   it under the terms of the GNU General Public License as published by  *
24
+ *   the Free Software Foundation; either version 2 of the License, or     *
25
+ *   (at your option) any later version.                                   *
26
+ *                                                                         *
27
+ ***************************************************************************/
28
+"""
29
+from PyQt4.QtCore import *
30
+from PyQt4.QtGui import *
31
+# Initialize Qt resources from file resources.py
32
+import resources_rc
33
+# Import the code for the dialog
34
+from ors_tools_dialog import ORStoolsDialog
35
+import os.path
36
+
37
+import ors_tools_access
38
+import ors_tools_routing
39
+
40
+from qgis.core import *
41
+import qgis.gui
42
+import qgis.utils
43
+
44
+import logging
45
+
46
+logging.basicConfig(format='%(levelname)s:%(message)s', level = logging.INFO)
47
+
48
+class ORStools:
49
+    """QGIS Plugin Implementation."""
50
+
51
+    def __init__(self, iface):
52
+        """Constructor.
53
+
54
+        :param iface: An interface instance that will be passed to this class
55
+            which provides the hook by which you can manipulate the QGIS
56
+            application at run time.
57
+        :type iface: QgsInterface
58
+        """
59
+        # Save reference to the QGIS interface
60
+        self.iface = iface
61
+        # initialize plugin directory
62
+        self.plugin_dir = os.path.dirname(__file__)
63
+        # initialize locale
64
+        locale = QSettings().value('locale/userLocale')[0:2]
65
+        locale_path = os.path.join(
66
+            self.plugin_dir,
67
+            'i18n',
68
+            'ORStools_{}.qm'.format(locale))
69
+
70
+        if os.path.exists(locale_path):
71
+            self.translator = QTranslator()
72
+            self.translator.load(locale_path)
73
+
74
+            if qVersion() > '4.3.3':
75
+                QCoreApplication.installTranslator(self.translator)
76
+
77
+        # Declare instance attributes
78
+        self.actions = []
79
+        self.menu = self.tr(u'&ORS Tools')
80
+        # TODO: We are going to let the user set this up in a future iteration
81
+        self.toolbar = self.iface.addToolBar(u'ORStools')
82
+        self.toolbar.setObjectName(u'ORStools')
83
+        
84
+        #custom __init__ declarations
85
+        self.dlg = ORStoolsDialog()
86
+        
87
+        self.canvas = qgis.utils.iface.mapCanvas()
88
+        self.script_dir = os.path.dirname(os.path.abspath(__file__))
89
+        
90
+    # noinspection PyMethodMayBeStatic
91
+    def tr(self, message):
92
+        """Get the translation for a string using Qt translation API.
93
+
94
+        We implement this ourselves since we do not inherit QObject.
95
+
96
+        :param message: String for translation.
97
+        :type message: str, QString
98
+
99
+        :returns: Translated version of message.
100
+        :rtype: QString
101
+        """
102
+        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
103
+        return QCoreApplication.translate('ORStools', message)
104
+
105
+
106
+    def add_action(
107
+        self,
108
+        icon_path,
109
+        text,
110
+        callback,
111
+        enabled_flag=True,
112
+        add_to_menu=True,
113
+        add_to_toolbar=True,
114
+        status_tip=None,
115
+        whats_this=None,
116
+        parent=None):
117
+        """Add a toolbar icon to the toolbar.
118
+
119
+        :param icon_path: Path to the icon for this action. Can be a resource
120
+            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
121
+        :type icon_path: str
122
+
123
+        :param text: Text that should be shown in menu items for this action.
124
+        :type text: str
125
+
126
+        :param callback: Function to be called when the action is triggered.
127
+        :type callback: function
128
+
129
+        :param enabled_flag: A flag indicating if the action should be enabled
130
+            by default. Defaults to True.
131
+        :type enabled_flag: bool
132
+
133
+        :param add_to_menu: Flag indicating whether the action should also
134
+            be added to the menu. Defaults to True.
135
+        :type add_to_menu: bool
136
+
137
+        :param add_to_toolbar: Flag indicating whether the action should also
138
+            be added to the toolbar. Defaults to True.
139
+        :type add_to_toolbar: bool
140
+
141
+        :param status_tip: Optional text to show in a popup when mouse pointer
142
+            hovers over the action.
143
+        :type status_tip: str
144
+
145
+        :param parent: Parent widget for the new action. Defaults None.
146
+        :type parent: QWidget
147
+
148
+        :param whats_this: Optional text to show in the status bar when the
149
+            mouse pointer hovers over the action.
150
+
151
+        :returns: The action that was created. Note that the action is also
152
+            added to self.actions list.
153
+        :rtype: QAction
154
+        """
155
+
156
+        # Create the dialog (after translation) and keep reference
157
+        
158
+
159
+        icon = QIcon(icon_path)
160
+        action = QAction(icon, text, parent)
161
+        action.triggered.connect(callback)
162
+        action.setEnabled(enabled_flag)
163
+
164
+        if status_tip is not None:
165
+            action.setStatusTip(status_tip)
166
+
167
+        if whats_this is not None:
168
+            action.setWhatsThis(whats_this)
169
+
170
+        if add_to_toolbar:
171
+            self.toolbar.addAction(action)
172
+
173
+        if add_to_menu:
174
+            self.iface.addPluginToMenu(
175
+                self.menu,
176
+                action)
177
+
178
+        self.actions.append(action)
179
+            
180
+        return action
181
+    
182
+    def initGui(self):
183
+        """Create the menu entries and toolbar icons inside the QGIS GUI."""
184
+
185
+        icon_path = ':/plugins/ORStools/icon.png'
186
+        self.add_action(
187
+            icon_path,
188
+            text=self.tr(u'Gimme'),
189
+            callback=self.run,
190
+            parent=self.iface.mainWindow())
191
+        
192
+        self.dlg.api_key.textChanged.connect(self.keyWriter)
193
+        
194
+        self.dlg.key_order.setText("<a href = 'mailto:openrouteservice@geog.uni-heidelberg.de?subject=ORS API key request'>Get Key!</a>") 
195
+        self.dlg.key_order.connect(self.dlg.key_order, SIGNAL("linkActivated(QString)"), self.OpenURL) 
196
+        self.dlg.header_2.linkActivated.connect(self.OpenURL)
197
+        self.dlg.header_3.linkActivated.connect(self.OpenURL)
198
+        
199
+        
200
+    def OpenURL(self, URL): 
201
+          QDesktopServices().openUrl(QUrl(URL))
202
+                
203
+    
204
+    def unload(self):        
205
+        self.dlg.close()
206
+        QApplication.restoreOverrideCursor()
207
+        
208
+        
209
+    def run(self):
210
+        """Run method that performs all the real work"""
211
+        
212
+        # Populate the api key lineEdit widget
213
+        with open(os.path.join(self.script_dir, "apikey.txt")) as key:
214
+            self.dlg.api_key.setText(key.read())
215
+        
216
+        # Initiate analysis classes
217
+        self.access_anal = ors_tools_access.accessAnalysis(self.dlg)
218
+        self.route_anal = ors_tools_routing.routing(self.dlg)
219
+        
220
+        self.dlg.setFixedSize(self.dlg.size())  
221
+        
222
+        self.dlg.show()
223
+        
224
+        # show the dialog
225
+        # Run the dialog event loop
226
+        result = self.dlg.exec_()
227
+        # See if OK was pressed
228
+        if result:
229
+            if self.dlg.tabWidget.currentIndex() == 0 and self.dlg.use_layer.isChecked():
230
+                self.access_anal.iterAnalysis()
231
+            
232
+            elif self.dlg.tabWidget.currentIndex() == 1:
233
+                self.route_anal.route()
234
+        else:
235
+            self.unload()
236
+                
237
+    def keyWriter(self):
238
+        with open(os.path.join(self.script_dir, "apikey.txt"), 'w') as key:
239
+            return key.write(self.dlg.api_key.text())
240
+        
241
+        
242
+def CheckCRS(self,crs):
243
+    check = True
244
+    if crs != "EPSG:4326":
245
+        msg = "CRS is {}. Must be EPSG:4326 (WGS84)".format(crs)
246
+        qgis.utils.iface.messageBar().pushMessage(msg, level = qgis.gui.QgsMessageBar.CRITICAL)
247
+        check = False
248
+    return check
249
+    

+ 317
- 0
ors_tools2.py View File

@@ -0,0 +1,317 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+/***************************************************************************
4
+ ORStools
5
+                                 A QGIS plugin
6
+ falk
7
+                              -------------------
8
+        begin                : 2017-02-01
9
+        git sha              : $Format:%H$
10
+        copyright            : (C) 2017 by nils
11
+        email                : nils
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 PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, QVariant, QObject, SIGNAL, QEvent, Qt, pyqtSignal
24
+from PyQt4.QtGui import QAction, QIcon, QMessageBox, QProgressBar, QComboBox, QDesktopServices
25
+from PyQt4 import QtCore, QtGui
26
+# Initialize Qt resources from file resources.py
27
+import resources_rc
28
+# Import the code for the dialog
29
+from ors_tools_dialog import ORStoolsDialog
30
+import os.path
31
+
32
+import ors_tools_pointtool
33
+import ors_tools_access
34
+
35
+from qgis.core import *
36
+import qgis.gui
37
+from qgis.gui import QgsMapTool
38
+import qgis.utils
39
+import processing
40
+
41
+from collections import OrderedDict
42
+from datetime import datetime
43
+import logging
44
+import numpy as np
45
+
46
+logging.basicConfig(format='%(levelname)s:%(message)s', level = logging.INFO)
47
+
48
+class ORStools:
49
+    """QGIS Plugin Implementation."""
50
+
51
+    def __init__(self, iface):
52
+        """Constructor.
53
+
54
+        :param iface: An interface instance that will be passed to this class
55
+            which provides the hook by which you can manipulate the QGIS
56
+            application at run time.
57
+        :type iface: QgsInterface
58
+        """
59
+        # Save reference to the QGIS interface
60
+        self.iface = iface
61
+        # initialize plugin directory
62
+        self.plugin_dir = os.path.dirname(__file__)
63
+        # initialize locale
64
+        locale = QSettings().value('locale/userLocale')[0:2]
65
+        locale_path = os.path.join(
66
+            self.plugin_dir,
67
+            'i18n',
68
+            'ORStools_{}.qm'.format(locale))
69
+
70
+        if os.path.exists(locale_path):
71
+            self.translator = QTranslator()
72
+            self.translator.load(locale_path)
73
+
74
+            if qVersion() > '4.3.3':
75
+                QCoreApplication.installTranslator(self.translator)
76
+
77
+        
78
+        # Declare instance attributes
79
+        self.actions = []
80
+        self.menu = self.tr(u'&ORS Tools')
81
+        # TODO: We are going to let the user set this up in a future iteration
82
+        self.toolbar = self.iface.addToolBar(u'ORStools')
83
+        self.toolbar.setObjectName(u'ORStools')
84
+        
85
+        #custom __init__ declarations
86
+        self.dlg = ORStoolsDialog()
87
+        
88
+        self.canvas = qgis.utils.iface.mapCanvas()
89
+        self.mapTool = None
90
+        self.script_dir = os.path.dirname(os.path.abspath(__file__))
91
+        
92
+    # noinspection PyMethodMayBeStatic
93
+    def tr(self, message):
94
+        """Get the translation for a string using Qt translation API.
95
+
96
+        We implement this ourselves since we do not inherit QObject.
97
+
98
+        :param message: String for translation.
99
+        :type message: str, QString
100
+
101
+        :returns: Translated version of message.
102
+        :rtype: QString
103
+        """
104
+        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
105
+        return QCoreApplication.translate('ORStools', message)
106
+
107
+
108
+    def add_action(
109
+        self,
110
+        icon_path,
111
+        text,
112
+        callback,
113
+        enabled_flag=True,
114
+        add_to_menu=True,
115
+        add_to_toolbar=True,
116
+        status_tip=None,
117
+        whats_this=None,
118
+        parent=None):
119
+        """Add a toolbar icon to the toolbar.
120
+
121
+        :param icon_path: Path to the icon for this action. Can be a resource
122
+            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
123
+        :type icon_path: str
124
+
125
+        :param text: Text that should be shown in menu items for this action.
126
+        :type text: str
127
+
128
+        :param callback: Function to be called when the action is triggered.
129
+        :type callback: function
130
+
131
+        :param enabled_flag: A flag indicating if the action should be enabled
132
+            by default. Defaults to True.
133
+        :type enabled_flag: bool
134
+
135
+        :param add_to_menu: Flag indicating whether the action should also
136
+            be added to the menu. Defaults to True.
137
+        :type add_to_menu: bool
138
+
139
+        :param add_to_toolbar: Flag indicating whether the action should also
140
+            be added to the toolbar. Defaults to True.
141
+        :type add_to_toolbar: bool
142
+
143
+        :param status_tip: Optional text to show in a popup when mouse pointer
144
+            hovers over the action.
145
+        :type status_tip: str
146
+
147
+        :param parent: Parent widget for the new action. Defaults None.
148
+        :type parent: QWidget
149
+
150
+        :param whats_this: Optional text to show in the status bar when the
151
+            mouse pointer hovers over the action.
152
+
153
+        :returns: The action that was created. Note that the action is also
154
+            added to self.actions list.
155
+        :rtype: QAction
156
+        """
157
+
158
+        # Create the dialog (after translation) and keep reference
159
+        
160
+
161
+        icon = QIcon(icon_path)
162
+        action = QAction(icon, text, parent)
163
+        action.triggered.connect(callback)
164
+        action.setEnabled(enabled_flag)
165
+
166
+        if status_tip is not None:
167
+            action.setStatusTip(status_tip)
168
+
169
+        if whats_this is not None:
170
+            action.setWhatsThis(whats_this)
171
+
172
+        if add_to_toolbar:
173
+            self.toolbar.addAction(action)
174
+
175
+        if add_to_menu:
176
+            self.iface.addPluginToMenu(
177
+                self.menu,
178
+                action)
179
+
180
+        self.actions.append(action)
181
+            
182
+        return action
183
+    
184
+    def initGui(self):
185
+        """Create the menu entries and toolbar icons inside the QGIS GUI."""
186
+
187
+        icon_path = ':/plugins/ORStools/icon.png'
188
+        self.add_action(
189
+            icon_path,
190
+            text=self.tr(u'Gimme'),
191
+            callback=self.run,
192
+            parent=self.iface.mainWindow())
193
+        
194
+        # Populate the api key lineEdit widget
195
+        with open(os.path.join(self.script_dir, "apikey.txt")) as key:
196
+            self.dlg.api_key.setText(key.read())
197
+        
198
+        # Set up all event connections
199
+        # Populate field ID dynamically when combobox selection changes
200
+        self.dlg.layer.currentIndexChanged.connect(self.popBox)
201
+        self.dlg.check_dissolve.stateChanged.connect(self.popBox)
202
+        self.dlg.access_map.clicked.connect(self.initMapTool)
203
+        self.dlg.api_key.textChanged.connect(self.keyWriter)
204
+        
205
+        self.dlg.key_order.setText("<a href = 'mailto:timothy.ellersiek@geog.uni-heidelberg.de?subject=ORS API key request'>Get Key!</a>") 
206
+        self.dlg.key_order.connect(self.dlg.key_order, SIGNAL("linkActivated(QString)"), self.OpenURL) 
207
+        
208
+        
209
+    def OpenURL(self, URL): 
210
+          QDesktopServices().openUrl(QtCore.QUrl(URL))
211
+                
212
+    
213
+    def unload(self):        
214
+        if self.mapTool != None:
215
+            self.mapTool.canvasClicked.disconnect()
216
+            self.canvas.unsetMapTool(self.mapTool) 
217
+        
218
+    
219
+    # Connect to PointTool and set as mapTool
220
+    def initMapTool(self):
221
+        self.mapTool = ors_tools_pointtool.PointTool(self.canvas)        
222
+        self.iface.mapCanvas().setMapTool(self.mapTool)     
223
+        self.mapTool.canvasClicked.connect(self.getCoords)
224
+        
225
+    
226
+    # Populate field ID
227
+    def popBox(self):
228
+        if self.dlg.check_dissolve.isChecked() == True:
229
+            self.dlg.id_field.setEnabled(True)
230
+            self.dlg.id_field.clear()
231
+            layer_list = [lyr for lyr in QgsMapLayerRegistry.instance().mapLayers().values() if lyr.name() == self.dlg.layer.currentText()]
232
+            if layer_list:
233
+                layer_selected = layer_list[0]
234
+                fields_selected = layer_selected.fields()
235
+                for field in fields_selected:
236
+                    self.dlg.id_field.addItem(field.name())
237
+        else:
238
+            self.dlg.id_field.setEnabled(False)
239
+        return
240
+        
241
+        
242
+    def getCoords(self, point):
243
+        self.access_anal.pointAnalysis(point)
244
+        
245
+        
246
+    def run(self):
247
+        """Run method that performs all the real work"""
248
+        self.dlg.show()
249
+        self.startUp()
250
+        self.dlg.setFixedSize(self.dlg.size())
251
+        self.iface.mapCanvas().setMapTool(self.mapTool)     
252
+        self.access_anal = ors_tools_access.accessAnalysis(self.dlg)
253
+        
254
+        # show the dialog
255
+        # Run the dialog event loop
256
+        result = self.dlg.exec_()
257
+        # See if OK was pressed
258
+        if result:
259
+            if self.dlg.tabWidget.currentIndex() == 0:
260
+                self.access_anal.iterAnalysis()
261
+        else:
262
+            self.unload()
263
+                
264
+        if self.mapTool != None:
265
+            self.canvas.unsetMapTool(self.mapTool)    
266
+            
267
+        
268
+    def startUp(self):
269
+    
270
+        # Accessibility init
271
+        self.dlg.mode.clear()
272
+        self.dlg.layer.clear()
273
+        self.dlg.method.clear()  
274
+        self.dlg.id_field.clear()
275
+        self.dlg.access_text.clear()
276
+        self.dlg.mode.addItem('Car')
277
+        self.dlg.mode.addItem('Bicycle')
278
+        self.dlg.mode.addItem('Pedestrian')      
279
+        self.dlg.method.addItem('RecursiveGrid')
280
+        self.dlg.method.addItem('TIN')        
281
+        
282
+        # Populate field ID from first layer
283
+        self.popBox()
284
+        
285
+        # Routing init
286
+        self.dlg.add_start.clear()
287
+        self.dlg.add_end.clear()
288
+        self.dlg.add_end.clear()
289
+        self.dlg.mode_travel.clear()
290
+        self.dlg.mode_routing.clear()
291
+        self.dlg.mode_travel.addItem('Car')
292
+        self.dlg.mode_travel.addItem('Bicycle')
293
+        self.dlg.mode_travel.addItem('Pedestrian')
294
+        self.dlg.mode_routing.addItem('Fastest')
295
+        self.dlg.mode_routing.addItem('Shortest')
296
+        
297
+        allLayers = qgis.utils.iface.legendInterface().layers()
298
+
299
+        for layer in allLayers:
300
+            layerType = layer.type()
301
+            if layerType == QgsMapLayer.VectorLayer and layer.wkbType() == QGis.WKBPoint:
302
+                self.dlg.layer.addItem(layer.name())
303
+
304
+                
305
+    def keyWriter(self):
306
+        with open(os.path.join(self.script_dir, "apikey.txt"), 'w') as key:
307
+            return key.write(self.dlg.api_key.text())
308
+        
309
+        
310
+def CheckCRS(self,crs):
311
+    check = True
312
+    if crs != "EPSG:4326":
313
+        msg = "CRS is {}. Must be EPSG:4326 (WGS84)".format(crs)
314
+        qgis.utils.iface.messageBar().pushMessage(msg, level = qgis.gui.QgsMessageBar.CRITICAL)
315
+        check = False
316
+    return check
317
+    

+ 307
- 0
ors_tools_access.py View File

@@ -0,0 +1,307 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+Created on Mon Feb 06 15:26:47 2017
4
+
5
+@author: nnolde
6
+"""
7
+from PyQt4.QtCore import *
8
+from PyQt4.QtGui import *
9
+
10
+from qgis.core import *
11
+from qgis.gui import * 
12
+import qgis.utils
13
+import processing
14
+
15
+import requests
16
+import xml.etree.ElementTree as ET
17
+import os.path
18
+
19
+import ors_tools       
20
+import ors_tools_geocode
21
+import ors_tools_pointtool
22
+        
23
+class accessAnalysis:
24
+    def __init__(self, dlg):
25
+        self.dlg = dlg
26
+        self.url = r"http://openls.geog.uni-heidelberg.de/analyse?"
27
+        self.ns = {'gml': 'http://www.opengis.net/gml',
28
+                  'aas': "http://www.geoinform.fh-mainz.de/aas",
29
+                  'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
30
+                  
31
+        self.mapTool = None
32
+
33
+        self.dlg.mode.clear()
34
+        self.dlg.layer.clear()
35
+        self.dlg.method.clear()  
36
+        self.dlg.mode.addItem('Car')
37
+        self.dlg.mode.addItem('Bicycle')
38
+        self.dlg.mode.addItem('Pedestrian')      
39
+        self.dlg.method.addItem('RecursiveGrid')
40
+        self.dlg.method.addItem('TIN') 
41
+        
42
+        for layer in qgis.utils.iface.legendInterface().layers():
43
+            layerType = layer.type()
44
+            if layerType == QgsMapLayer.VectorLayer and layer.wkbType() == QGis.WKBPoint:
45
+                self.dlg.layer.addItem(layer.name())
46
+                  
47
+        # GUI Init
48
+        self.popBox()
49
+        
50
+        # API parameters
51
+        self.api_key = self.dlg.api_key.text()
52
+        self.iso_max = self.dlg.iso_max.value()
53
+        self.iso_int = self.dlg.iso_int.value() * 60
54
+        self.iso_mode = self.dlg.mode.currentText()
55
+        self.iso_method = self.dlg.method.currentText()
56
+        self.iface = qgis.utils.iface
57
+        
58
+        self.script_dir = os.path.dirname(os.path.abspath(__file__))
59
+        
60
+        # Connect events to signals
61
+        self.dlg.iso_max.valueChanged.connect(self.valueChanged)
62
+        self.dlg.iso_int.valueChanged.connect(self.valueChanged)
63
+        self.dlg.mode.currentIndexChanged.connect(self.valueChanged)
64
+        self.dlg.method.currentIndexChanged.connect(self.valueChanged)
65
+        self.dlg.use_layer.stateChanged.connect(self.enableLayer)
66
+        self.dlg.api_key.textChanged.connect(self.keyWriter)
67
+        
68
+        # Populate field ID dynamically when combobox selection changes
69
+        self.dlg.layer.currentIndexChanged.connect(self.popBox)
70
+        self.dlg.check_dissolve.stateChanged.connect(self.popBox)
71
+        self.dlg.access_map.clicked.connect(self.initMapTool)
72
+    
73
+    
74
+    def enableLayer(self):
75
+        if self.dlg.use_layer.isChecked() == True:
76
+            self.dlg.frame_2.setEnabled(True)
77
+        else:
78
+            self.dlg.frame_2.setEnabled(False)
79
+            
80
+    
81
+    def valueChanged(self):
82
+        self.iso_max = self.dlg.iso_max.value()
83
+        self.iso_int = self.dlg.iso_int.value() * 60
84
+        self.iso_mode = self.dlg.mode.currentText()
85
+        self.iso_method = self.dlg.method.currentText()
86
+        
87
+    
88
+    def keyWriter(self):
89
+        with open(os.path.join(self.script_dir, "apikey.txt"), 'w') as key:
90
+            self.api_key = self.dlg.api_key.text()
91
+            return key.write(self.dlg.api_key.text())
92
+        
93
+        
94
+    # Populate field ID
95
+    def popBox(self):              
96
+        if self.dlg.check_dissolve.isChecked() == True:
97
+            self.dlg.id_field.setEnabled(True)
98
+            self.dlg.id_field.clear()
99
+            layer_list = [lyr for lyr in QgsMapLayerRegistry.instance().mapLayers().values() if lyr.name() == self.dlg.layer.currentText()]
100
+            if layer_list:
101
+                layer_selected = layer_list[0]
102
+                fields_selected = layer_selected.fields()
103
+                for field in fields_selected:
104
+                    self.dlg.id_field.addItem(field.name())
105
+        else:
106
+            self.dlg.id_field.setEnabled(False)
107
+        return
108
+    
109
+        
110
+    # Connect to PointTool and set as mapTool
111
+    def initMapTool(self):
112
+        sending_button = self.dlg.sender().objectName()
113
+        self.mapTool = ors_tools_pointtool.PointTool(qgis.utils.iface.mapCanvas(), sending_button)        
114
+        self.iface.mapCanvas().setMapTool(self.mapTool)     
115
+        self.mapTool.canvasClicked.connect(self.pointAnalysis)
116
+        
117
+        
118
+    def accRequest(self, point_in):
119
+        QApplication.setOverrideCursor(Qt.WaitCursor)
120
+        #geometry_in = QgsGeometry.fromPoint(point_in)
121
+        x, y = point_in.asPoint()
122
+        
123
+        #TODO: 'method' does not seem to be available over get()?! Ask GIScience team
124
+        req = "{}api_key={}&position={},{}&minutes={}&interval={}&routePreference={}".format(self.url, 
125
+                                                                self.api_key, 
126
+                                                                x, 
127
+                                                                y,
128
+                                                                self.iso_max,
129
+                                                                self.iso_int,
130
+                                                                self.iso_mode)
131
+        response = requests.get(req)
132
+        root = ET.fromstring(response.content)
133
+        access_path = root.find("aas:Response/"
134
+                                "aas:AccessibilityResponse/"
135
+                                "aas:AccessibilityGeometry",
136
+                                self.ns)
137
+        
138
+        QApplication.restoreOverrideCursor()
139
+        
140
+        isochrone_list = []
141
+        feat_list = []
142
+
143
+        for isochrone in access_path.findall("aas:Isochrone", self.ns):
144
+            feat_out = QgsFeature()
145
+            
146
+            coord_ext_list = []
147
+            coord_int_list = []
148
+            
149
+            # First find the exterior ring
150
+            for coords_ext in isochrone.findall("aas:IsochroneGeometry/"
151
+                                            "gml:Polygon/"
152
+                                            "gml:exterior/"
153
+                                            "gml:LinearRing/"
154
+                                            "gml:pos",
155
+                                            self.ns):
156
+                coords_ext_tuple = tuple([float(coord) for coord in coords_ext.text.split(" ")])
157
+                qgis_coords_ext = QgsPoint(coords_ext_tuple[0], coords_ext_tuple[1])
158
+                coord_ext_list.append(qgis_coords_ext)
159
+            
160
+            # Then find all interior rings
161
+            for ring_int in isochrone.findall("aas:IsochroneGeometry/"
162
+                                        "gml:Polygon/"
163
+                                        "gml:interior",
164
+                                        self.ns):
165
+                int_poly = []
166
+                for coords_int in ring_int.findall("gml:LinearRing/"
167
+                                        "gml:pos",
168
+                                        self.ns):
169
+                    coords_int_tuple = tuple([float(coord) for coord in coords_int.text.split(" ")])
170
+                    qgis_coords_int = QgsPoint(coords_int_tuple[0], coords_int_tuple[1])
171
+                    int_poly.append(qgis_coords_int)
172
+                coord_int_list.append(int_poly)
173
+                    
174
+            feat_out.setGeometry(QgsGeometry.fromPolygon([coord_ext_list] + coord_int_list))
175
+            feat_list.append(feat_out)
176
+            isochrone_list.append(float(isochrone.get("time"))/60)
177
+        
178
+        return feat_list, isochrone_list
179
+
180
+        
181
+    def pointAnalysis(self, point):
182
+        point_geometry = QgsGeometry.fromPoint(point)
183
+        feat_list, isochrone_list = self.accRequest(point_geometry)
184
+        
185
+        _point_geocode = ors_tools_geocode.Geocode(self.dlg, self.api_key)
186
+        loc_dict = _point_geocode.reverseGeocode(point_geometry)
187
+            
188
+        out_str = u"Long: {0:.3f}, Lat:{1:.3f}\n{2}\n{3}\n{4}".format(loc_dict.get('Lon', ""),
189
+                                                        loc_dict.get('Lat', ""),
190
+                                                        loc_dict.get('MUNICIPALI', "NA"),
191
+                                                        loc_dict.get('COUNTRYSUB', "NA"),
192
+                                                        loc_dict.get('COUNTRY', "NA")
193
+                                                        )
194
+        self.dlg.access_text.setText(out_str)
195
+        
196
+        layer_out = QgsVectorLayer("Polygon?crs=EPSG:4326", "AA_{0:.3f},{1:.3f}".format(loc_dict['Lon'], loc_dict['Lat']), "memory")
197
+        layer_out_point = QgsVectorLayer("Point?crs=EPSG:4326", "Point_{0:.3f},{1:.3f}".format(loc_dict['Lon'], loc_dict['Lat']), "memory")
198
+        
199
+        layer_out_prov = layer_out.dataProvider()
200
+        layer_out_prov.addAttributes([QgsField("AA_MINS", QVariant.Int)])
201
+        layer_out_prov.addAttributes([QgsField("AA_MODE", QVariant.String)])
202
+        layer_out.updateFields()
203
+        
204
+        layer_out_point_prov = layer_out_point.dataProvider()
205
+        layer_out_point_prov.addAttributes([QgsField("LAT", QVariant.String)])
206
+        layer_out_point_prov.addAttributes([QgsField("LONG", QVariant.String)])
207
+        layer_out_point_prov.addAttributes([QgsField("DIST_INPUT", QVariant.String)])
208
+        layer_out_point_prov.addAttributes([QgsField("BULIDINGNA", QVariant.String)])
209
+        layer_out_point_prov.addAttributes([QgsField("OFFICIALNA", QVariant.String)])
210
+        layer_out_point_prov.addAttributes([QgsField("NUMBER", QVariant.String)])
211
+        layer_out_point_prov.addAttributes([QgsField("POSTALCODE", QVariant.String)])
212
+        layer_out_point_prov.addAttributes([QgsField("MUNICIPALI", QVariant.String)])
213
+        layer_out_point_prov.addAttributes([QgsField("COUNTRYSUB", QVariant.String)])
214
+        layer_out_point_prov.addAttributes([QgsField("COUNTRY", QVariant.String)])
215
+        layer_out_point.updateFields()
216
+        
217
+        # Add clicked point feature to point feature class
218
+        point_out = QgsFeature()
219
+        point_out.setGeometry(point_geometry)
220
+        point_out.setAttributes([loc_dict.get("Lat", None),
221
+                                loc_dict.get("Lon", None),
222
+                                loc_dict.get("DIST_INPUT", None),
223
+                                loc_dict.get("BULIDINGNA", None),
224
+                                loc_dict.get("OFFICIALNA", None),
225
+                                loc_dict.get("NUMBER", None),
226
+                                loc_dict.get("POSTALCODE", None),
227
+                                loc_dict.get("MUNICIPALI", None),
228
+                                loc_dict.get("COUNTRYSUB", None),
229
+                                loc_dict.get('COUNTRY', None)
230
+                                ])
231
+        layer_out_point_prov.addFeatures([point_out])
232
+        
233
+        for ind, feat in enumerate(feat_list):
234
+            feat.setAttributes([isochrone_list[ind], self.iso_mode])
235
+            layer_out_prov.addFeatures([feat])
236
+
237
+        layer_out.updateExtents()
238
+        layer_out_point.updateExtents()
239
+        
240
+        QgsMapLayerRegistry.instance().addMapLayer(layer_out_point)
241
+        QgsMapLayerRegistry.instance().addMapLayer(layer_out)
242
+
243
+        fields_diss = ["AA_MINS"]
244
+        self.dissolveFields(layer_out, fields_diss)
245
+        
246
+        # Unset Map Tool
247
+        self.iface.mapCanvas().unsetMapTool(self.mapTool)
248
+        self.mapTool = None
249
+
250
+    def iterAnalysis(self):
251
+        allLayers = self.iface.legendInterface().layers()
252
+                
253
+        # Determine selected layer
254
+        for layer in allLayers:
255
+            if layer.name() == self.dlg.layer.currentText():
256
+                acc_input_lyr = layer
257
+                break
258
+        #TODO: Maybe reproject when other than WGS84?! Now it`s just closing the window
259
+        if ors_tools.CheckCRS(self, acc_input_lyr.crs().authid()) == False:
260
+            return
261
+        
262
+        # Define polygon .shp
263
+        layer_out = QgsVectorLayer("Polygon?crs=EPSG:4326", "{}_AA_{}".format(acc_input_lyr.name(),self.iso_mode), "memory")
264
+        layer_out_prov = layer_out.dataProvider()
265
+        for field in acc_input_lyr.fields():
266
+            layer_out_prov.addAttributes([field])
267
+        layer_out_prov.addAttributes([QgsField("AA_MINS", QVariant.Int)])
268
+        layer_out_prov.addAttributes([QgsField("AA_MODE", QVariant.String)])
269
+        layer_out.updateFields()
270
+        
271
+        features = acc_input_lyr.getFeatures()
272
+        
273
+        # Progress Bar
274
+        feature_count = acc_input_lyr.featureCount()
275
+        progressMessageBar = self.iface.messageBar().createMessage("Requesting analysis from ORS...")
276
+        progress = QProgressBar()
277
+        progress.setMaximum(feature_count)
278
+        progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
279
+        progressMessageBar.layout().addWidget(progress)
280
+        self.iface.messageBar().pushWidget(progressMessageBar, self.iface.messageBar().INFO)
281
+                
282
+        for i, feat_in in enumerate(features):
283
+            progress.setValue(i)
284
+            
285
+            feat_list, isochrone_list = self.accRequest(feat_in.geometry())
286
+            
287
+            for ind, feat in enumerate(feat_list):                
288
+                feat.setAttributes(feat_in.attributes() + [isochrone_list[ind], self.iso_mode])
289
+                layer_out_prov.addFeatures([feat])
290
+
291
+            layer_out.updateExtents()
292
+        
293
+        id_field = self.dlg.id_field.currentText()
294
+        fields_diss = ["AA_MINS", id_field]
295
+        
296
+        QgsMapLayerRegistry.instance().addMapLayer(layer_out)
297
+        self.dissolveFields(layer_out, fields_diss)
298
+    
299
+        
300
+    def dissolveFields(self, layer_out, fields_diss):        
301
+        # Dissolve output for interval 'AA_MINS' and id_layer, remove non-dissolved layer
302
+        
303
+        processing.runandload("qgis:dissolve", layer_out , False,
304
+                          fields_diss, "memory:dissolved")
305
+        layer_dissolved = QgsMapLayerRegistry.instance().mapLayersByName("Dissolved")[-1]
306
+        layer_dissolved.setLayerName(layer_out.name())
307
+        QgsMapLayerRegistry.instance().removeMapLayers([layer_out.id()])

+ 41
- 0
ors_tools_dialog.py View File

@@ -0,0 +1,41 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+/***************************************************************************
4
+ ORStoolsDialog
5
+                                 A QGIS plugin
6
+ falk
7
+                             -------------------
8
+        begin                : 2017-02-01
9
+        git sha              : $Format:%H$
10
+        copyright            : (C) 2017 by nils
11
+        email                : nils
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
+
24
+import os
25
+
26
+from PyQt4 import QtGui, uic
27
+
28
+FORM_CLASS, _ = uic.loadUiType(os.path.join(
29
+    os.path.dirname(__file__), 'ors_tools_dialog_base.ui'))
30
+
31
+
32
+class ORStoolsDialog(QtGui.QDialog, FORM_CLASS):
33
+    def __init__(self, parent=None):
34
+        """Constructor."""
35
+        super(ORStoolsDialog, self).__init__(parent)
36
+        # Set up the user interface from Designer.
37
+        # After setupUI you can access any designer object by doing
38
+        # self.<objectname>, and you can use autoconnect slots - see
39
+        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
40
+        # #widgets-and-dialogs-with-auto-connect
41
+        self.setupUi(self)

+ 1333
- 0
ors_tools_dialog_base.ui
File diff suppressed because it is too large
View File


+ 1010
- 0
ors_tools_dialog_base_v1.ui
File diff suppressed because it is too large
View File


+ 1010
- 0
ors_tools_dialog_base_v2.ui
File diff suppressed because it is too large
View File


+ 64
- 0
ors_tools_geocode.py View File

@@ -0,0 +1,64 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+Created on Tue Feb 07 00:34:21 2017
4
+
5
+@author: nnolde
6
+"""
7
+
8
+from PyQt4.QtCore import *
9
+from PyQt4.QtGui import *
10
+
11
+from qgis.core import *
12
+from qgis.gui import * 
13
+import qgis.utils
14
+
15
+import requests
16
+import xml.etree.ElementTree as ET
17
+
18
+class Geocode:
19
+    def __init__(self, dlg, api_key):
20
+        self.dlg = dlg
21
+        self.url = r"http://openls.geog.uni-heidelberg.de/geocode?"
22
+        self.ns = {'gml': 'http://www.opengis.net/gml',
23
+                  'xls': "http://www.opengis.net/xls",
24
+                  'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
25
+                  
26
+        # API parameters
27
+        self.api_key = api_key
28
+        
29
+        self.iface = qgis.utils.iface    
30
+        
31
+    def reverseGeocode(self, point_in):
32
+        x, y = point_in.asPoint()
33
+        req = "{}api_key={}&pos={} {}".format(self.url, 
34
+                                            self.api_key, 
35
+                                            x, 
36
+                                            y)
37
+        response = requests.get(req)
38
+        root = ET.fromstring(response.content)
39
+        access_path = root.find("xls:Response/"
40
+                                "xls:ReverseGeocodeResponse/"
41
+                                "xls:ReverseGeocodedLocation",
42
+                                self.ns)
43
+        
44
+        loc_place_dict = dict()
45
+        
46
+        pos = access_path.find("gml:Point/gml:pos", self.ns).text
47
+        x, y  = pos.split(" ")
48
+        loc_place_dict['Lon'] = float(x)
49
+        loc_place_dict['Lat'] = float(y)
50
+        loc_place_dict['DIST_INPUT'] = access_path.find("xls:SearchCentreDistance", self.ns).get('value')
51
+        loc_list = access_path.findall("xls:StreetAddress/xls:Building", self.ns)
52
+        for element in loc_list:
53
+            loc_place_dict[element.keys()[0][:10].upper()] = element.get(element.keys()[0], "")
54
+        loc_list = access_path.findall("xls:StreetAddress/xls:PostalCode", self.ns)
55
+        for element in loc_list:
56
+            loc_place_dict['POSTALCODE'] = element.text
57
+        loc_list = access_path.findall("xls:Address/xls:StreetAddress/xls:Street", self.ns)
58
+        for element in loc_list:
59
+            loc_place_dict[element.keys()[0][:10].upper()] = element.get(element.keys()[0], "")
60
+        loc_list = access_path.findall("xls:Address/xls:Place", self.ns)
61
+        for element in loc_list:
62
+            loc_place_dict[element.get('type')[:10].upper()] = unicode(element.text)
63
+                           
64
+        return loc_place_dict

+ 70
- 0
ors_tools_pointtool.py View File

@@ -0,0 +1,70 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+Created on Mon Feb 06 23:35:16 2017
4
+
5
+@author: nnolde
6
+"""
7
+from PyQt4.QtCore import *
8
+from PyQt4.QtGui import *
9
+
10
+from qgis.core import *
11
+from qgis.gui import *
12
+
13
+import os
14
+
15
+# Find cursor icon in plugin tree
16
+def resolve(name, basepath=None):
17
+    if not basepath:
18
+      basepath = os.path.dirname(os.path.realpath(__file__))
19
+    return os.path.join(basepath, name)
20
+    
21
+
22
+class PointTool(QgsMapTool):   
23
+    def __init__(self, canvas, button):
24
+        QgsMapTool.__init__(self, canvas)
25
+        self.canvas = canvas    
26
+        self.button = button
27
+        self.imgdir = resolve('icon_locate.png')
28
+        self.cursor = QCursor(QPixmap(self.imgdir).scaledToWidth(24), 12, 12)
29
+        
30
+        #QApplication.setOverrideCursor(QCursor(QPixmap('/icon_locate.png')))
31
+
32
+    def canvasPressEvent(self, event):
33
+        pass
34
+
35
+    def canvasMoveEvent(self, event):
36
+        pass
37
+    
38
+    canvasClicked = pyqtSignal(['QgsPoint', 'QString', 'Qt::MouseButton'])
39
+    def canvasReleaseEvent(self, event):
40
+        #Get the click and emit a transformed point
41
+        
42
+        crsSrc = self.canvas.mapRenderer().destinationCrs()
43
+        crsWGS = QgsCoordinateReferenceSystem(4326)
44
+    
45
+        point_oldcrs = self.toMapCoordinates(event.pos())
46
+        
47
+        xform = QgsCoordinateTransform(crsSrc, crsWGS)
48
+        point_newcrs = xform.transform(point_oldcrs)
49
+        
50
+        QApplication.restoreOverrideCursor()
51
+        
52
+        self.canvasClicked.emit(point_newcrs, self.button, event.button())
53
+        
54
+    def activate(self):
55
+        QApplication.setOverrideCursor(self.cursor)
56
+        #self.canvas.setCursor(self.cursor)
57
+        
58
+        print "WTFe"
59
+
60
+    def deactivate(self):
61
+        pass
62
+
63
+    def isZoomTool(self):
64
+        return False
65
+
66
+    def isTransient(self):
67
+        return False
68
+
69
+    def isEditTool(self):
70
+        return True

+ 334
- 0
ors_tools_routing.py View File

@@ -0,0 +1,334 @@
1
+# -*- coding: utf-8 -*-
2
+"""
3
+Created on Wed Feb 08 21:14:48 2017
4
+
5
+@author: nnolde
6
+"""
7
+
8
+from PyQt4.QtCore import *
9
+from PyQt4.QtGui import *
10
+
11
+from qgis.core import *
12
+from qgis.gui import * 
13
+import qgis.utils
14
+
15
+import requests
16
+import xml.etree.ElementTree as ET
17
+import os.path
18
+import re
19
+import itertools
20
+
21
+import ors_tools_pointtool
22
+
23
+class routing:
24
+    def __init__(self, dlg):
25
+        self.dlg = dlg
26
+        self.url = r"http://openls.geog.uni-heidelberg.de/route?"
27
+        self.ns = {'gml': 'http://www.opengis.net/gml',
28
+                  'xls': "http://www.opengis.net/xls",
29
+                  'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
30
+        
31
+        # GUI init
32
+        self.dlg.start_layer.clear()
33
+        self.dlg.end_layer.clear()
34
+        self.dlg.mode_travel.clear()
35
+        self.dlg.mode_routing.clear()
36
+        self.dlg.mode_travel.addItem('Car')
37
+        self.dlg.mode_travel.addItem('Bicycle')
38
+        self.dlg.mode_travel.addItem('Pedestrian')
39
+        self.dlg.mode_routing.addItem('Fastest')
40
+        self.dlg.mode_routing.addItem('Shortest')
41
+        
42
+        for layer in qgis.utils.iface.legendInterface().layers():
43
+            layerType = layer.type()
44
+            if layerType == QgsMapLayer.VectorLayer and layer.wkbType() == QGis.WKBPoint:
45
+                self.dlg.start_layer.addItem(layer.name())
46
+                self.dlg.end_layer.addItem(layer.name())
47
+                
48
+        self.layer_start = None
49
+        self.layer_end = None
50
+        
51
+        self.startPopBox()
52
+        self.endPopBox()
53
+                  
54
+        # API parameters
55
+        self.api_key = self.dlg.api_key.text()
56
+        self.mode_travel = self.dlg.mode_travel.currentText()
57
+        self.mode_routing = self.dlg.mode_routing.currentText()
58
+        self.speed_max = self.dlg.speed_max.value()
59
+        
60
+        self.iface = qgis.utils.iface
61
+        
62
+        self.script_dir = os.path.dirname(os.path.abspath(__file__))
63
+        
64
+        # Connect events to signals
65
+        self.dlg.start_radio_map.toggled.connect(self.startPopBox)
66
+        self.dlg.end_radio_map.toggled.connect(self.endPopBox)
67
+        self.dlg.start_layer.currentIndexChanged.connect(self.startPopBox)
68
+        self.dlg.end_layer.currentIndexChanged.connect(self.endPopBox)
69
+        self.dlg.mode_travel.currentIndexChanged.connect(self.valueChanged)
70
+        self.dlg.mode_routing.currentIndexChanged.connect(self.valueChanged)
71
+        self.dlg.speed_max.valueChanged.connect(self.valueChanged)
72
+        self.dlg.add_start_button.clicked.connect(self.initMapTool)
73
+        self.dlg.add_end_button.clicked.connect(self.initMapTool)
74
+        self.dlg.add_via_button.clicked.connect(self.initMapTool)
75
+        self.dlg.api_key.textChanged.connect(self.keyWriter)
76
+    
77
+    
78
+    def startPopBox(self):
79
+        if self.dlg.start_radio_layer.isChecked():
80
+            self.dlg.add_start_button.setEnabled(False)
81
+            self.dlg.start_layer.setEnabled(True)
82
+            self.dlg.start_layer_id.setEnabled(True)
83
+            self.dlg.start_layer_id.clear()
84
+            layer_list = [lyr for lyr in QgsMapLayerRegistry.instance().mapLayers().values() if lyr.name() == self.dlg.start_layer.currentText()]
85
+            if layer_list:
86
+                layer_selected = layer_list[0]
87
+                fields_selected = layer_selected.fields()
88
+                for field in fields_selected:
89
+                    self.dlg.start_layer_id.addItem(field.name())
90
+                
91
+            # Determine selected layer
92
+            for layer in qgis.utils.iface.legendInterface().layers():
93
+                if layer.name() == self.dlg.start_layer.currentText():
94
+                    self.layer_start = layer
95
+                    break
96
+        else:
97
+            self.dlg.start_layer_id.setEnabled(False)
98
+            self.dlg.start_layer.setEnabled(False)
99
+            self.dlg.add_start_button.setEnabled(True)
100
+            
101
+        if self.dlg.end_radio_layer.isChecked() and self.dlg.start_radio_layer.isChecked():
102
+            self.dlg.radio_one.setEnabled(True)
103
+            self.dlg.radio_many.setEnabled(True)
104
+        else:
105
+            self.dlg.radio_one.setEnabled(False)
106
+            self.dlg.radio_many.setEnabled(False)
107
+            
108
+        return
109
+    
110
+        
111
+    def endPopBox(self):
112
+        if self.dlg.end_radio_layer.isChecked():
113
+            self.dlg.add_end_button.setEnabled(False)
114
+            self.dlg.end_layer.setEnabled(True)
115
+            self.dlg.end_layer_id.setEnabled(True)
116
+            self.dlg.end_layer_id.clear()
117
+            layer_list = [lyr for lyr in QgsMapLayerRegistry.instance().mapLayers().values() if lyr.name() == self.dlg.end_layer.currentText()]
118
+            if layer_list:
119
+                layer_selected = layer_list[0]
120
+                fields_selected = layer_selected.fields()
121
+                for field in fields_selected:
122
+                    self.dlg.end_layer_id.addItem(field.name())
123
+                    
124
+            # Determine selected layer
125
+            for layer in qgis.utils.iface.legendInterface().layers():
126
+                if layer.name() == self.dlg.end_layer.currentText():
127
+                    self.layer_end = layer
128
+                    break            
129
+        else:
130
+            self.dlg.end_layer_id.setEnabled(False)
131
+            self.dlg.end_layer.setEnabled(False)
132
+            self.dlg.add_end_button.setEnabled(True)
133
+        
134
+        if self.dlg.end_radio_layer.isChecked() and self.dlg.start_radio_layer.isChecked():
135
+            self.dlg.radio_one.setEnabled(True)
136
+            self.dlg.radio_many.setEnabled(True)
137
+        else:
138
+            self.dlg.radio_one.setEnabled(False)
139
+            self.dlg.radio_many.setEnabled(False)
140
+            
141
+        return
142
+        
143
+    
144
+    # Event for GUI Signals
145
+    def valueChanged(self):
146
+        self.mode_travel = self.dlg.mode_travel.currentText()
147
+        self.mode_routing = self.dlg.mode_routing.currentText()
148
+        self.speed_max = self.dlg.speed_max.value()
149
+        
150
+    
151
+    # Event for API key change
152
+    def keyWriter(self):
153
+        with open(os.path.join(self.script_dir, "apikey.txt"), 'w') as key:
154
+            self.api_key = self.dlg.api_key.text()
155
+            return key.write(self.dlg.api_key.text())
156
+            
157
+    
158
+    # Connect to PointTool and set as mapTool
159
+    def initMapTool(self):
160
+        sending_button = self.dlg.sender().objectName() 
161
+        self.mapTool = ors_tools_pointtool.PointTool(qgis.utils.iface.mapCanvas(), sending_button)        
162
+        self.iface.mapCanvas().setMapTool(self.mapTool)     
163
+        self.mapTool.canvasClicked.connect(self.writeText)
164
+
165
+        
166
+    # Write map coordinates to text fields
167
+    def writeText(self, point, button):
168
+        x, y = point
169
+        
170
+        if button == self.dlg.add_start_button.objectName():
171
+            self.dlg.add_start.setText("{0:.5f},{1:.5f}".format(x, y))
172
+            
173
+        if button == self.dlg.add_end_button.objectName():
174
+            self.dlg.add_end.setText("{0:.5f},{1:.5f}".format(x, y))
175
+            
176
+        if button == self.dlg.add_via_button.objectName():
177
+            self.dlg.add_via.setText("{0:.5f},{1:.5f}\n".format(x, y))
178
+            
179
+        
180
+    def route(self):
181
+        
182
+#        if ors_tools.CheckCRS(self, self.layer_start.crs().authid()) == False:
183
+#            return
184
+#        if ors_tools.CheckCRS(self, self.layer_end.crs().authid()) == False:
185
+#            return
186
+        
187
+        # Create memory routing layer with fields
188
+        layer_out = QgsVectorLayer("LineString?crs=EPSG:4326", "Route", "memory")
189
+        layer_out_prov = layer_out.dataProvider()
190
+        layer_out_prov.addAttributes([QgsField("DISTANCE", QVariant.Double)])
191
+        layer_out_prov.addAttributes([QgsField("TIME_H", QVariant.Int)])
192
+        layer_out_prov.addAttributes([QgsField("TIME_MIN", QVariant.Int)])
193
+        layer_out_prov.addAttributes([QgsField("TIME_SEC", QVariant.Int)])
194
+        layer_out_prov.addAttributes([QgsField("MODE", QVariant.String)])
195
+        layer_out_prov.addAttributes([QgsField("PREF", QVariant.String)])
196
+        layer_out_prov.addAttributes([QgsField("SPEED_MAX", QVariant.String)])
197
+        layer_out_prov.addAttributes([QgsField("FROM_LAT", QVariant.Double)])
198
+        layer_out_prov.addAttributes([QgsField("FROM_LONG", QVariant.Double)])
199
+        layer_out_prov.addAttributes([QgsField("TO_LAT", QVariant.Double)])
200
+        layer_out_prov.addAttributes([QgsField("TO_LONG", QVariant.Double)])
201
+        layer_out_prov.addAttributes([QgsField("FROM_ID", QVariant.String)])
202
+        layer_out_prov.addAttributes([QgsField("TO_ID", QVariant.String)])
203
+        
204
+        layer_out.updateFields()
205
+        
206
+        start_features = []
207
+        end_features = []
208
+        start_ids = []
209
+        end_ids = []
210
+
211
+        # Create start features
212
+        if self.dlg.start_radio_layer.isChecked():
213
+            start_feat = self.layer_start.getFeatures()
214
+            field_id = self.layer_start.fieldNameIndex(self.dlg.start_layer_id.currentText())
215
+            for feat in start_feat:
216
+                x, y = feat.geometry().asPoint()
217
+                start_features.append(",".join([str(x), str(y)]))
218
+                start_ids.append(feat.attributes()[field_id])
219
+        else:
220
+            start_features.append(self.dlg.add_start.text())
221
+            start_ids.append(self.dlg.add_start.text())
222
+            
223
+        # Create end features
224
+        if self.dlg.end_radio_layer.isChecked():
225
+            end_feat = self.layer_end.getFeatures()
226
+            field_id = self.layer_end.fieldNameIndex(self.dlg.end_layer_id.currentText())
227
+            for feat in end_feat:
228
+                x, y = feat.geometry().asPoint()
229
+                end_features.append(",".join([str(x), str(y)]))
230
+                end_ids.append(feat.attributes()[field_id])
231
+        else:
232
+            end_features.append(self.dlg.add_end.text())
233
+            end_ids.append(self.dlg.add_end.text())
234
+            
235
+        # Rules for creating routing features
236
+        if len(start_features) == 1:
237
+            if len(end_features) == 1:
238
+                route_features = zip(start_features, end_features)
239
+                route_ids = zip(start_ids, end_ids)
240
+            else:
241
+                route_features = zip(itertools.cycle(start_features), end_features)
242
+                route_ids = zip(itertools.cycle(start_ids), end_ids)
243
+        else:
244
+            if len(end_features) == 1:
245
+                route_features = zip(start_features, itertools.cycle(end_features))
246
+                route_ids = zip(start_ids, itertools.cycle(end_ids))
247
+            else:
248
+                if self.dlg.radio_one.isChecked():
249
+                    route_features = zip(start_features, end_features)
250
+                    route_ids = zip(start_ids, end_ids)
251
+                else:
252
+                    route_features = list(itertools.product(start_features, end_features))
253
+                    route_ids = list(itertools.product(start_ids, end_ids))
254
+
255
+        # Read route details from GUI
256
+        route_via = " ".join(self.dlg.add_via.text().split("\n")[:-1])
257
+        
258
+        # Set up progress bar
259
+        route_count = len(route_features)
260
+        progressMessageBar = self.iface.messageBar().createMessage("Requesting routes from ORS...")
261
+        progress = QProgressBar()
262
+        progress.setMaximum(route_count)
263
+        progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
264
+        progressMessageBar.layout().addWidget(progress)
265
+        self.iface.messageBar().pushWidget(progressMessageBar, self.iface.messageBar().INFO)
266
+        
267
+        for i, route in enumerate(route_features):
268
+            # Skip route if start and end are identical
269
+            progress.setValue(i)
270
+            
271
+            if route[0] == route[1]:
272
+                continue
273
+            else:
274
+                # Create URL
275
+                req = "{}api_key={}&start={}&end={}&routepref={}&weighting={}&maxspeed={}&instructions=False".format(self.url, 
276
+                                                    self.api_key, 
277
+                                                    route[0],
278
+                                                    route[1],
279
+                                                    self.mode_travel,
280
+                                                    self.mode_routing,
281
+                                                    self.speed_max)
282
+                if route_via != "":
283
+                    req += "&via={}".format(route_via)
284
+                    
285
+                # Get response from API and read into element tree
286
+                response = requests.get(req)
287
+                root = ET.fromstring(response.content)
288
+                access_path = root.find("xls:Response/"
289
+                                        "xls:DetermineRouteResponse",
290
+                                        self.ns)
291
+                
292
+                feat_out = QgsFeature()
293
+                
294
+                # Read all coordinates
295
+                coords_list = []
296
+                for coords in access_path.findall("xls:RouteGeometry/gml:LineString/gml:pos", self.ns):
297
+                    coords_tuple = tuple([float(coord) for coord in coords.text.split(" ")])
298
+                    qgis_coords = QgsPoint(coords_tuple[0], coords_tuple[1])
299
+                    coords_list.append(qgis_coords)
300
+                
301
+                # Read total time
302
+                time_path = access_path.find("xls:RouteSummary/xls:TotalTime", self.ns)
303
+                time_list = list(reversed(re.split('H|M', time_path.text[2:-1]))) # Split with 3 characters into sec, mins, hours
304
+                while len(time_list) < 3:
305
+                    time_list.append('0')
306
+                secs, mins, hours = [int(x) for x in time_list]
307
+                                     
308
+                # Read total distance                             
309
+                distance = float(access_path.find("xls:RouteSummary/xls:TotalDistance", self.ns).get("value"))
310
+                
311
+                # Read X and Y
312
+                route_start_x, route_start_y = [float(coord) for coord in route[0].split(",")]
313
+                route_end_x, route_end_y = [float(coord) for coord in route[1].split(",")]
314
+                    
315
+                # Set feature geometry and attributes
316
+                feat_out.setGeometry(QgsGeometry.fromPolyline(coords_list))
317
+                feat_out.setAttributes([distance,
318
+                                        hours,
319
+                                        mins,
320
+                                        secs,
321
+                                        self.mode_travel,
322
+                                        self.mode_routing,
323
+                                        self.speed_max,
324
+                                        route_start_y,
325
+                                        route_start_x,
326
+                                        route_end_y,
327
+                                        route_end_x,
328
+                                        route_ids[i][0],
329
+                                        route_ids[i][1]]) 
330
+                
331
+                layer_out_prov.addFeatures([feat_out])
332
+        layer_out.updateExtents()
333
+
334
+        QgsMapLayerRegistry.instance().addMapLayer(layer_out)

+ 74
- 0
pb_tool.cfg View File

@@ -0,0 +1,74 @@
1
+#/***************************************************************************
2
+# ORStools
3
+#
4
+# Configuration file for plugin builder tool (pb_tool)
5
+#                            -------------------
6
+#       begin               : 2017-02-01
7
+#       copyright           : (C) 2017 by nils
8
+#       email               : nils
9
+# ***************************************************************************/
10
+#
11
+#/***************************************************************************
12
+# *                                                                         *
13
+# *   This program is free software; you can redistribute it and/or modify  *
14
+# *   it under the terms of the GNU General Public License as published by  *
15
+# *   the Free Software Foundation; either version 2 of the License, or     *
16
+# *   (at your option) any later version.                                   *
17
+# *                                                                         *
18
+# ***************************************************************************/
19
+# 
20
+# 
21
+# You can install pb_tool using:
22
+#  pip install http://geoapt.net/files/pb_tool.zip
23
+# 
24
+# Consider doing your development (and install of pb_tool) in a virtualenv.
25
+# 
26
+# For details on setting up and using pb_tool, see:
27
+#  http://spatialgalaxy.net/qgis-plugin-development-with-pb_tool
28
+#
29
+# Issues and pull requests here:
30
+# https://github.com/g-sherman/plugin_build_tool:
31
+# 
32
+# Sane defaults for your plugin generated by the Plugin Builder are
33
+# already set below.
34
+# 
35
+# As you add Python source files and UI files to your plugin, add
36
+# them to the appropriate [files] section below.
37
+
38
+[plugin]
39
+# Name of the plugin. This is the name of the directory that will
40
+# be created in .qgis2/python/plugins
41
+name: ORStools
42
+
43
+[files]
44
+# Python  files that should be deployed with the plugin
45
+python_files: __init__.py ors_tools.py ors_tools_dialog.py
46
+
47
+# The main dialog file that is loaded (not compiled)
48
+main_dialog: ors_tools_dialog_base.ui
49
+
50
+# Other ui files for dialogs you create (these will be compiled)
51
+compiled_ui_files: 
52
+
53
+# Resource file(s) that will be compiled
54
+resource_files: resources.qrc
55
+
56
+# Other files required for the plugin
57
+extras: metadata.txt icon.png
58
+
59
+# Other directories to be deployed with the plugin.
60
+# These must be subdirectories under the plugin directory
61
+extra_dirs:
62
+
63
+# ISO code(s) for any locales (translations), separated by spaces.
64
+# Corresponding .ts files must exist in the i18n directory
65
+locales:
66
+
67
+[help]
68
+# the built help directory that should be deployed with the plugin
69
+dir: help/build/html
70
+# the name of the directory to target in the deployed plugin 
71
+target: help
72
+
73
+
74
+

+ 107
- 0
plugin_upload.py View File

@@ -0,0 +1,107 @@
1
+#!/usr/bin/env python
2
+# coding=utf-8
3
+"""This script uploads a plugin package on the server.
4
+        Authors: A. Pasotti, V. Picavet
5
+        git sha              : $TemplateVCSFormat
6
+"""
7
+
8
+import sys
9
+import getpass
10
+import xmlrpclib
11
+from optparse import OptionParser
12
+
13
+# Configuration
14
+PROTOCOL = 'http'
15
+SERVER = 'plugins.qgis.org'
16
+PORT = '80'
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 = "%s://%s:%s@%s:%s%s" % (
28
+        PROTOCOL,
29
+        parameters.username,
30
+        parameters.password,
31
+        parameters.server,
32
+        parameters.port,
33
+        ENDPOINT)
34
+    print "Connecting to: %s" % hide_password(address)
35
+
36
+    server = xmlrpclib.ServerProxy(address, verbose=VERBOSE)
37
+
38
+    try:
39
+        plugin_id, version_id = server.plugin.upload(
40
+            xmlrpclib.Binary(open(arguments[0]).read()))
41
+        print "Plugin ID: %s" % plugin_id
42
+        print "Version ID: %s" % version_id
43
+    except xmlrpclib.ProtocolError, err:
44
+        print "A protocol error occurred"
45
+        print "URL: %s" % hide_password(err.url, 0)
46
+        print "HTTP/HTTPS headers: %s" % err.headers
47
+        print "Error code: %d" % err.errcode
48
+        print "Error message: %s" % err.errmsg
49
+    except xmlrpclib.Fault, err:
50
+        print "A fault occurred"
51
+        print "Fault code: %d" % err.faultCode
52
+        print "Fault string: %s" % err.faultString
53
+
54
+
55
+def hide_password(url, start=6):
56
+    """Returns the http url with password part replaced with '*'.
57
+
58
+    :param url: URL to upload the plugin to.
59
+    :type url: str
60
+
61
+    :param start: Position of start of password.
62
+    :type start: int
63
+    """
64
+    start_position = url.find(':', start) + 1
65
+    end_position = url.find('@')
66
+    return "%s%s%s" % (
67
+        url[:start_position],
68
+        '*' * (end_position - start_position),
69
+        url[end_position:])
70
+
71
+
72
+if __name__ == "__main__":
73
+    parser = OptionParser(usage="%prog [options] plugin.zip")
74
+    parser.add_option(
75
+        "-w", "--password", dest="password",
76
+        help="Password for plugin site", metavar="******")
77
+    parser.add_option(
78
+        "-u", "--username", dest="username",
79
+        help="Username of plugin site", metavar="user")
80
+    parser.add_option(
81
+        "-p", "--port", dest="port",
82
+        help="Server port to connect to", metavar="80")
83
+    parser.add_option(
84
+        "-s", "--server", dest="server",
85
+        help="Specify server name", metavar="plugins.qgis.org")
86
+    options, args = parser.parse_args()
87
+    if len(args) != 1:
88
+        print "Please specify zip file.\n"
89
+        parser.print_help()
90
+        sys.exit(1)
91
+    if not options.server:
92
+        options.server = SERVER
93
+    if not options.port:
94
+        options.port = PORT
95
+    if not options.username:
96
+        # interactive mode
97
+        username = getpass.getuser()
98
+        print "Please enter user name [%s] :" % username,
99
+        res = raw_input()
100
+        if res != "":
101
+            options.username = res
102
+        else:
103
+            options.username = username
104
+    if not options.password:
105
+        # interactive mode
106
+        options.password = getpass.getpass()
107
+    main(options, args)

+ 281
- 0
pylintrc View File

@@ -0,0 +1,281 @@
1
+[MASTER]
2
+
3
+# Specify a configuration file.
4
+#rcfile=
5
+
6
+# Python code to execute, usually for sys.path manipulation such as
7
+# pygtk.require().
8
+#init-hook=
9
+
10
+# Profiled execution.
11
+profile=no
12
+
13
+# Add files or directories to the blacklist. They should be base names, not
14
+# paths.
15
+ignore=CVS
16
+
17
+# Pickle collected data for later comparisons.
18
+persistent=yes
19
+
20
+# List of plugins (as comma separated values of python modules names) to load,
21
+# usually to register additional checkers.
22
+load-plugins=
23
+
24
+
25
+[MESSAGES CONTROL]
26
+
27
+# Enable the message, report, category or checker with the given id(s). You can
28
+# either give multiple identifier separated by comma (,) or put this option
29
+# multiple time. See also the "--disable" option for examples.
30
+#enable=
31
+
32
+# Disable the message, report, category or checker with the given id(s). You
33
+# can either give multiple identifiers separated by comma (,) or put this
34
+# option multiple times (only on the command line, not in the configuration
35
+# file where it should appear only once).You can also use "--disable=all" to
36
+# disable everything first and then reenable specific checks. For example, if
37
+# you want to run only the similarities checker, you can use "--disable=all
38
+# --enable=similarities". If you want to run only the classes checker, but have
39
+# no Warning level messages displayed, use"--disable=all --enable=classes
40
+# --disable=W"