Skip to content

Commit

Permalink
Merge branch 'qgis:master' into feature/metasearch
Browse files Browse the repository at this point in the history
  • Loading branch information
frida-161 committed Dec 1, 2021
2 parents f5d6800 + dfde275 commit dd12a94
Show file tree
Hide file tree
Showing 42 changed files with 420 additions and 145 deletions.
19 changes: 18 additions & 1 deletion .ci/ogc/nginx.conf
Expand Up @@ -13,7 +13,7 @@ server {
try_files $uri $uri/ =404;
}

location /qgisserver {
location /qgisserver_wms130 {
fastcgi_pass qgis-server:5555;
add_header Access-Control-Allow-Origin *;
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,X-Requested-With';
Expand All @@ -29,4 +29,21 @@ server {
fastcgi_param SERVER_NAME $server_addr;
fastcgi_param QGIS_PROJECT_FILE /data/teamengine_wms_130.qgs;
}

location /qgisserver_ogcapif {
fastcgi_pass qgis-server:5555;
add_header Access-Control-Allow-Origin *;
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,X-Requested-With';
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param SERVER_PORT 80;
fastcgi_param SERVER_NAME $server_addr;
fastcgi_param QGIS_PROJECT_FILE /data/QGIS-Training-Data/exercise_data/qgis-server-tutorial-data/world.qgs;
}
}
3 changes: 2 additions & 1 deletion .docker/qgis_resources/test_runner/qgis_startup.py
Expand Up @@ -6,11 +6,12 @@
~/.qgis3/python/startup.py
"""
from qgis.core import Qgis
from qgis import utils
import traceback


def _showException(type, value, tb, msg, messagebar=False):
def _showException(type, value, tb, msg, messagebar=False, level=Qgis.Warning):
print(msg)
logmessage = ''
for s in traceback.format_exception(type, value, tb):
Expand Down
13 changes: 9 additions & 4 deletions .github/workflows/ogc.yml
Expand Up @@ -85,16 +85,21 @@ jobs:
run: |
sudo apt-get update && sudo apt-get install python3-virtualenv virtualenv git
git clone https://github.com/pblottiere/pyogctest
cd pyogctest && git checkout 1.0.4 && cd -
cd pyogctest && git checkout 1.1.0 && cd -
virtualenv -p /usr/bin/python3 venv && source venv/bin/activate && pip install -e pyogctest/
- name: Extract WMS 1.3.0 dataset
- name: Run WMS 1.3.0 OGC tests
run: |
source venv/bin/activate && ./pyogctest/pyogctest.py -s wms130 -e
docker-compose -f .ci/ogc/docker-compose.yml up -d
source venv/bin/activate && ./pyogctest/pyogctest.py -n ogc_qgis -s wms130 -v -u http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' qgis_server_nginx)/qgisserver_wms130
env:
DOCKER_IMAGE: ${{ steps.docker-build.outputs.FULL_IMAGE_NAME }}

- name: Run WMS 1.3.0 OGC tests
- name: Run OGC API Features 1.0 tests
run: |
cd data && git clone https://github.com/qgis/QGIS-Training-Data && cd -
docker-compose -f .ci/ogc/docker-compose.yml up -d
source venv/bin/activate && ./pyogctest/pyogctest.py -n ogc_qgis -s wms130 -v -u http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' qgis_server_nginx)/qgisserver
source venv/bin/activate && ./pyogctest/pyogctest.py -n ogc_qgis -s ogcapif -v -u http://$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' qgis_server_nginx)/qgisserver_ogcapif
env:
DOCKER_IMAGE: ${{ steps.docker-build.outputs.FULL_IMAGE_NAME }}
2 changes: 1 addition & 1 deletion python/plugins/MetaSearch/CMakeLists.txt
@@ -1,4 +1,4 @@
file(GLOB PY_FILES __init__.py link_types.py plugin.py util.py)
file(GLOB PY_FILES __init__.py link_types.py plugin.py search_backend.py util.py)
PLUGIN_INSTALL(MetaSearch . ${PY_FILES} metadata.txt LICENSE.txt)

foreach(dir ui dialogs images resources resources/templates)
Expand Down
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>XMLDialog</class>
<widget class="QDialog" name="XMLDialog">
<class>APIRequestResponseDialog</class>
<widget class="QDialog" name="APIRequestResponseDialog">
<property name="geometry">
<rect>
<x>0</x>
Expand All @@ -11,28 +11,28 @@
</rect>
</property>
<property name="windowTitle">
<string>XML Request / Response</string>
<string>API Request / Response</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblXMLRequest">
<widget class="QLabel" name="lblAPIRequest">
<property name="text">
<string>Request</string>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="txtbrXMLRequest"/>
<widget class="QTextBrowser" name="txtbrAPIRequest"/>
</item>
<item>
<widget class="QLabel" name="lblXMLResponse">
<widget class="QLabel" name="lblAPIResponse">
<property name="text">
<string>Response</string>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="txtbrXMLResponse">
<widget class="QTextBrowser" name="txtbrAPIResponse">
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
Expand All @@ -58,7 +58,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>XMLDialog</receiver>
<receiver>APIRequestResponseDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
Expand All @@ -74,7 +74,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>XMLDialog</receiver>
<receiver>APIRequestResponseDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
Expand Down
131 changes: 127 additions & 4 deletions python/plugins/processing/ProcessingPlugin.py
Expand Up @@ -29,28 +29,35 @@
from qgis.core import (QgsApplication,
QgsProcessingUtils,
QgsProcessingModelAlgorithm,
QgsProcessingAlgorithm,
QgsDataItemProvider,
QgsDataProvider,
QgsDataItem,
QgsMapLayerType,
QgsMimeDataUtils)
from qgis.gui import (QgsOptionsWidgetFactory,
QgsCustomDropHandler)
from qgis.PyQt.QtCore import Qt, QCoreApplication, QDir, QFileInfo
from qgis.PyQt.QtWidgets import QMenu, QAction
from qgis.PyQt.QtCore import QObject, Qt, QItemSelectionModel, QCoreApplication, QDir, QFileInfo, pyqtSlot
from qgis.PyQt.QtWidgets import QWidget, QMenu, QAction
from qgis.PyQt.QtGui import QIcon, QKeySequence
from qgis.utils import iface

from processing.core.Processing import Processing
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.ProcessingToolbox import ProcessingToolbox
from processing.gui.HistoryDialog import HistoryDialog
from processing.gui.ConfigDialog import ConfigOptionsPage
from processing.gui.ResultsDock import ResultsDock
from processing.gui.MessageDialog import MessageDialog
from processing.gui.MessageBarProgress import MessageBarProgress
from processing.gui.AlgorithmLocatorFilter import (AlgorithmLocatorFilter,
InPlaceAlgorithmLocatorFilter)
from processing.gui.Postprocessing import handleAlgorithmResults
from processing.gui.AlgorithmExecutor import execute, execute_in_place
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.BatchAlgorithmDialog import BatchAlgorithmDialog
from processing.modeler.ModelerDialog import ModelerDialog
from processing.tools.system import tempHelpFolder
from processing.tools import dataobjects
from processing.gui.menus import removeMenus, initializeMenus, createMenus, createButtons, removeButtons
from processing.core.ProcessingResults import resultsList

Expand Down Expand Up @@ -158,9 +165,10 @@ def createDataItem(self, path, parentItem):
return None


class ProcessingPlugin:
class ProcessingPlugin(QObject):

def __init__(self, iface):
super().__init__()
self.iface = iface
self.options_factory = None
self.drop_handler = None
Expand Down Expand Up @@ -195,6 +203,8 @@ def initGui(self):
self.toolbox.hide()
self.toolbox.visibilityChanged.connect(self.toolboxVisibilityChanged)

self.toolbox.executeWithGui.connect(self.executeAlgorithm)

self.resultsDock = ResultsDock()
self.iface.addDockWidget(Qt.RightDockWidgetArea, self.resultsDock)
self.resultsDock.hide()
Expand Down Expand Up @@ -282,6 +292,111 @@ def initGui(self):
self.iface.actionToggleEditing().triggered.connect(partial(self.sync_in_place_button_state, None))
self.sync_in_place_button_state()

# Sync project models
self.projectModelsMenu = None
self.projectMenuAction = None
self.projectMenuSeparator = None

self.projectProvider = QgsApplication.instance().processingRegistry().providerById("project")
self.projectProvider.algorithmsLoaded.connect(self.updateProjectModelMenu)

def updateProjectModelMenu(self):
"""Add projects models to menu"""

if self.projectMenuAction is None:
self.projectModelsMenu = QMenu(self.tr("Models"))
self.projectMenuAction = self.iface.projectMenu().insertMenu(self.iface.projectMenu().children()[-1], self.projectModelsMenu)
self.projectMenuAction.setParent(self.projectModelsMenu)
self.iface.projectMenu().insertSeparator(self.projectMenuAction)

self.projectModelsMenu.clear()

for model in self.projectProvider.algorithms():
modelSubMenu = self.projectModelsMenu.addMenu(model.name())
modelSubMenu.setParent(self.projectModelsMenu)
action = QAction(self.tr("Execute…"), modelSubMenu)
action.triggered.connect(partial(self.executeAlgorithm, model.id(), self.projectModelsMenu, self.toolbox.in_place_mode))
modelSubMenu.addAction(action)
if model.flags() & QgsProcessingAlgorithm.FlagSupportsBatch:
action = QAction(self.tr("Execute as Batch Process…"), modelSubMenu)
modelSubMenu.addAction(action)
action.triggered.connect(partial(self.executeAlgorithm, model.id(), self.projectModelsMenu, self.toolbox.in_place_mode, True))

@pyqtSlot(str, QWidget, bool, bool)
def executeAlgorithm(self, alg_id, parent, in_place=False, as_batch=False):
"""Executes a project model with GUI interaction if needed.
:param alg_id: algorithm id
:type alg_id: string
:param parent: parent widget
:type parent: QWidget
:param in_place: in place flag, defaults to False
:type in_place: bool, optional
:param as_batch: execute as batch flag, defaults to False
:type as_batch: bool, optional
"""

config = {}
if in_place:
config['IN_PLACE'] = True

alg = QgsApplication.instance().processingRegistry().createAlgorithmById(alg_id, config)

if alg is not None:

ok, message = alg.canExecute()
if not ok:
dlg = MessageDialog()
dlg.setTitle(self.tr('Error executing algorithm'))
dlg.setMessage(
self.tr('<h3>This algorithm cannot '
'be run :-( </h3>\n{0}').format(message))
dlg.exec_()
return

if as_batch:
dlg = BatchAlgorithmDialog(alg, iface.mainWindow())
dlg.setAttribute(Qt.WA_DeleteOnClose)
dlg.show()
dlg.exec_()
else:
in_place_input_parameter_name = 'INPUT'
if hasattr(alg, 'inputParameterName'):
in_place_input_parameter_name = alg.inputParameterName()

if in_place and not [d for d in alg.parameterDefinitions() if d.name() not in (in_place_input_parameter_name, 'OUTPUT')]:
parameters = {}
feedback = MessageBarProgress(algname=alg.displayName())
ok, results = execute_in_place(alg, parameters, feedback=feedback)
if ok:
iface.messageBar().pushSuccess('', self.tr('{algname} completed. %n feature(s) processed.', n=results['__count']).format(algname=alg.displayName()))
feedback.close()
# MessageBarProgress handles errors
return

if alg.countVisibleParameters() > 0:
dlg = alg.createCustomParametersWidget(parent)

if not dlg:
dlg = AlgorithmDialog(alg, in_place, iface.mainWindow())
canvas = iface.mapCanvas()
prevMapTool = canvas.mapTool()
dlg.show()
dlg.exec_()
if canvas.mapTool() != prevMapTool:
try:
canvas.mapTool().reset()
except Exception:
pass
canvas.setMapTool(prevMapTool)
else:
feedback = MessageBarProgress(algname=alg.displayName())
context = dataobjects.createContext(feedback)
parameters = {}
ret, results = execute(alg, parameters, context, feedback)
handleAlgorithmResults(alg, context, feedback)
feedback.close()

def sync_in_place_button_state(self, layer=None):
"""Synchronise the button state with layer state"""

Expand Down Expand Up @@ -328,6 +443,14 @@ def unload(self):

removeButtons()
removeMenus()

if self.projectMenuAction is not None:
self.iface.projectMenu().removeAction(self.projectMenuAction)
self.projectMenuAction = None
if self.projectMenuSeparator is not None:
self.iface.projectMenu().removeAction(self.projectMenuSeparator)
self.projectMenuSeparator = None

Processing.deinitialize()

def openToolbox(self, show):
Expand Down
1 change: 1 addition & 0 deletions python/plugins/processing/gui/AlgorithmExecutor.py
Expand Up @@ -24,6 +24,7 @@
import sys
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (Qgis,
QgsApplication,
QgsFeatureSink,
QgsProcessingFeedback,
QgsProcessingUtils,
Expand Down

0 comments on commit dd12a94

Please sign in to comment.