Commit eeb4a86c authored by Benjamin Jakimow's avatar Benjamin Jakimow
Browse files

pulled qps updates

parent 08540515
import sys, importlib, site, os
import sys, importlib, site, os, pathlib, typing
from qgis.core import QgsApplication
from qgis.gui import QgisInterface
__version__ = '0.2'
from qgis.gui import QgisInterface, QgsMapLayerConfigWidgetFactory
__version__ = '0.3'
def initResources():
DIR_UI_FILES = pathlib.Path(__file__).parent / 'ui'
DIR_ICONS = DIR_UI_FILES / 'icons'
QPS_RESOURCE_FILE = pathlib.Path(__file__).parent / 'qpsresources_rc.py'
MAPLAYER_CONFIGWIDGET_FACTORIES = list()
def registerMapLayerConfigWidgetFactory(factory:QgsMapLayerConfigWidgetFactory):
"""
Initializes compiled Qt resources
Register a new tab in the map layer properties dialog.
:param factory: QgsMapLayerConfigWidgetFactory
:type factory:
:return:
:rtype:
"""
try:
from .qpsresources import qInitResources
qInitResources()
except Exception as ex:
print(ex, file=sys.stderr)
print('It might be required to compile the qps/resources.py first', file=sys.stderr)
# make required modules available in case they are not part of the core-python installation
# if importlib.util.find_spec('pyqtgraph') is None:
# path = os.path.join(os.path.dirname(__file__), *['externals', 'ext-pyqtgraph'])
# site.addsitedir(path)
"""
try:
import pyqtgraph
except:
print('PyQtGraph is not installed. Use qps.externals.pyqtgraph instead.')
import qps.externals.pyqtgraph
sys.modules['pyqtgraph'] = qps.externals.pyqtgraph
"""
assert isinstance(factory, QgsMapLayerConfigWidgetFactory)
if factory not in MAPLAYER_CONFIGWIDGET_FACTORIES:
MAPLAYER_CONFIGWIDGET_FACTORIES.append(factory)
def unregisterMapLayerConfigWidgetFactory(factory:QgsMapLayerConfigWidgetFactory):
"""
Unregister a previously registered tab in the map layer properties dialog.
:param factory:
:type factory:
:return:
:rtype:
"""
assert isinstance(factory, QgsMapLayerConfigWidgetFactory)
while factory in MAPLAYER_CONFIGWIDGET_FACTORIES:
MAPLAYER_CONFIGWIDGET_FACTORIES.remove(factory)
def mapLayerConfigWidgetFactories()->typing.List[QgsMapLayerConfigWidgetFactory]:
"""
Returns registered QgsMapLayerConfigWidgetFactories
:return: list of QgsMapLayerConfigWidgetFactories
:rtype:
"""
return MAPLAYER_CONFIGWIDGET_FACTORIES[:]
def registerEditorWidgets():
"""
......@@ -36,10 +50,10 @@ def registerEditorWidgets():
assert isinstance(QgsApplication.instance(), QgsApplication), 'QgsApplication has not been instantiated'
try:
from .speclib.spectrallibraries import registerSpectralProfileEditorWidget
from .speclib.gui import registerSpectralProfileEditorWidget
registerSpectralProfileEditorWidget()
except Exception as ex:
print('Failed to call qps.speclib.spectrallibraries.registerSpectralProfileEditorWidget()', file=sys.stderr)
print('Failed to call qps.speclib.core.registerSpectralProfileEditorWidget()', file=sys.stderr)
print(ex, file=sys.stderr)
try:
......@@ -65,8 +79,19 @@ def registerEditorWidgets():
print(ex, file=sys.stderr)
def registerMapLayerConfigWidgetFactories():
from .layerconfigwidgets.rasterbands import RasterBandConfigWidgetFactory
from .layerconfigwidgets.gdalmetadata import GDALMetadataConfigWidgetFactory
def initAll():
registerMapLayerConfigWidgetFactory(RasterBandConfigWidgetFactory())
registerMapLayerConfigWidgetFactory(GDALMetadataConfigWidgetFactory())
def initResources():
from .testing import initResourceFile
initResourceFile(QPS_RESOURCE_FILE)
def initAll():
initResources()
registerEditorWidgets()
\ No newline at end of file
registerEditorWidgets()
registerMapLayerConfigWidgetFactories()
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>352</width>
<width>408</width>
<height>297</height>
</rect>
</property>
......@@ -114,6 +114,9 @@
<iconset resource="../../../../QGIS/images/images.qrc">
<normaloff>:/images/themes/default/mActionEditCopy.svg</normaloff>:/images/themes/default/mActionEditCopy.svg</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
......@@ -219,6 +222,31 @@
<string>Save classes</string>
</property>
</action>
<action name="actionLoadFromRasterFile">
<property name="text">
<string>Load from raster file</string>
</property>
</action>
<action name="actionLoadFromMapLayer">
<property name="text">
<string>Load from Map Layer</string>
</property>
</action>
<action name="actionLoadfromTextFile">
<property name="text">
<string>Load from Text File</string>
</property>
</action>
<action name="actionCopyToVectorLayer">
<property name="text">
<string>Copy to Vector Layer</string>
</property>
</action>
<action name="actionCopyToRasterLayer">
<property name="text">
<string>Copy to Raster Layer</string>
</property>
</action>
</widget>
<resources>
<include location="../qpsresources.qrc"/>
......
......@@ -12,6 +12,7 @@ from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
import numpy as np
from .. import DIR_UI_FILES
from ..utils import *
class CrosshairStyle(object):
......@@ -156,11 +157,27 @@ class CrosshairMapCanvasItem(QgsMapCanvasItem):
:param qgsRasterLayer:
:return:
"""
if qgsRasterLayer == self.mRasterGridLayer:
return
if isinstance(self.mRasterGridLayer, QgsRasterLayer):
self.mRasterGridLayer.willBeDeleted.disconnect(self.onLayerWillBeDeleted)
if isinstance(qgsRasterLayer, QgsRasterLayer):
self.mRasterGridLayer = qgsRasterLayer
self.mRasterGridLayer.willBeDeleted.connect(self.onLayerWillBeDeleted)
else:
self.mRasterGridLayer = None
def onLayerWillBeDeleted(self):
"""
Removes the reference to the map layer
:return:
:rtype:
"""
self.mRasterGridLayer = None
def rasterGridLayer(self)->QgsRasterLayer:
"""
Returns the raster grid layer
......@@ -393,15 +410,15 @@ def nicePredecessor(l):
return 0.0
class CrosshairWidget(QWidget, loadUI('crosshairwidget.ui')):
class CrosshairWidget(QWidget):
"""
A widget to configurate a CrossHair
A widget to configure a CrossHair
"""
sigCrosshairStyleChanged = pyqtSignal(CrosshairStyle)
def __init__(self, title='<#>', parent=None):
super(CrosshairWidget, self).__init__(parent)
self.setupUi(self)
loadUi(pathlib.Path(__file__).parent / 'crosshairwidget.ui', self)
self.mapCanvas.setExtent(QgsRectangle(0, 0, 1, 1)) #
......
......@@ -25,6 +25,7 @@ from qgis.gui import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from . import DIR_UI_FILES
from .utils import *
from .models import *
from .classification.classificationscheme import ClassInfo, ClassificationScheme
......@@ -284,21 +285,16 @@ class ComboBoxOptionModel(QAbstractListModel):
return value
class CursorLocationInfoDock(QDockWidget,
loadUI('cursorlocationinfodock.ui')):
class CursorLocationInfoDock(QDockWidget):
sigLocationRequest = pyqtSignal()
sigCursorLocationInfoAdded = pyqtSignal()
def __init__(self, parent=None):
def __init__(self, *args, **kwds):
"""Constructor."""
QWidget.__init__(self, parent)
# super(CursorLocationValueWidget, self).__init__(parent)
# Set up the user interface from Designer.
# After setupUI you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots - see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)
super().__init__(*args, **kwds)
path_ui = DIR_UI_FILES / 'cursorlocationinfodock.ui'
loadUi(path_ui, self)
self.mMaxPoints = 1
self.mLocationHistory = []
......
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.10.2-A Coruña" styleCategories="AllStyleCategories" maxScale="0" hasScaleBasedVisibilityFlag="0" minScale="1e+08">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
</flags>
<customproperties>
<property key="WMSBackgroundLayer" value="false"/>
<property key="WMSPublishDataSourceUrl" value="false"/>
<property key="embeddedWidgets/count" value="0"/>
<property key="identify/format" value="Value"/>
</customproperties>
<pipe>
<rasterrenderer alphaBand="-1" redBand="1" greenBand="2" blueBand="3" type="multibandcolor" opacity="1">
<rasterTransparency/>
<minMaxOrigin>
<limits>CumulativeCut</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<redContrastEnhancement>
<minValue>271</minValue>
<maxValue>646</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</redContrastEnhancement>
<greenContrastEnhancement>
<minValue>279</minValue>
<maxValue>649</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</greenContrastEnhancement>
<blueContrastEnhancement>
<minValue>273</minValue>
<maxValue>647</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</blueContrastEnhancement>
</rasterrenderer>
<brightnesscontrast contrast="0" brightness="0"/>
<huesaturation saturation="0" colorizeBlue="128" grayscaleMode="0" colorizeRed="255" colorizeOn="0" colorizeStrength="100" colorizeGreen="128"/>
<rasterresampler maxOversampling="2"/>
</pipe>
<blendMode>0</blendMode>
</qgis>
<PAMDataset>
<Metadata domain="IMAGE_STRUCTURE">
<MDI key="INTERLEAVE">BAND</MDI>
</Metadata>
<Metadata>
<MDI key="wavelength">{ 0.460000, 0.465000, 0.470000, 0.475000, 0.479000, 0.484000, 0.489000, 0.494000, 0.499000, 0.503000, 0.508000, 0.513000, 0.518000, 0.523000, 0.528000, 0.533000, 0.538000, 0.543000, 0.549000, 0.554000, 0.559000, 0.565000, 0.570000, 0.575000, 0.581000, 0.587000, 0.592000, 0.598000, 0.604000, 0.610000, 0.616000, 0.622000, 0.628000, 0.634000, 0.640000, 0.646000, 0.653000, 0.659000, 0.665000, 0.672000, 0.679000, 0.685000, 0.692000, 0.699000, 0.706000, 0.713000, 0.720000, 0.727000, 0.734000, 0.741000, 0.749000, 0.756000, 0.763000, 0.771000, 0.778000, 0.786000, 0.793000, 0.801000, 0.809000, 0.817000, 0.824000, 0.832000, 0.840000, 0.848000, 0.856000, 0.864000, 0.872000, 0.880000, 0.888000, 0.896000, 0.915000, 0.924000, 0.934000, 0.944000, 0.955000, 0.965000, 0.975000, 0.986000, 0.997000, 1.007000, 1.018000, 1.029000, 1.040000, 1.051000, 1.063000, 1.074000, 1.086000, 1.097000, 1.109000, 1.120000, 1.132000, 1.144000, 1.155000, 1.167000, 1.179000, 1.191000, 1.203000, 1.215000, 1.227000, 1.239000, 1.251000, 1.263000, 1.275000, 1.287000, 1.299000, 1.311000, 1.323000, 1.522000, 1.534000, 1.545000, 1.557000, 1.568000, 1.579000, 1.590000, 1.601000, 1.612000, 1.624000, 1.634000, 1.645000, 1.656000, 1.667000, 1.678000, 1.689000, 1.699000, 1.710000, 1.721000, 1.731000, 1.742000, 1.752000, 1.763000, 1.773000, 1.783000, 2.044000, 2.053000, 2.062000, 2.071000, 2.080000, 2.089000, 2.098000, 2.107000, 2.115000, 2.124000, 2.133000, 2.141000, 2.150000, 2.159000, 2.167000, 2.176000, 2.184000, 2.193000, 2.201000, 2.210000, 2.218000, 2.226000, 2.234000, 2.243000, 2.251000, 2.259000, 2.267000, 2.275000, 2.283000, 2.292000, 2.300000, 2.308000, 2.315000, 2.323000, 2.331000, 2.339000, 2.347000, 2.355000, 2.363000, 2.370000, 2.378000, 2.386000, 2.393000, 2.401000, 2.409000}</MDI>
<MDI key="wavelength_units">Micrometers</MDI>
</Metadata>
<PAMRasterBand band="1">
<Histograms>
<HistItem>
<HistMin>257.0357142857143</HistMin>
<HistMax>677.9642857142857</HistMax>
<BucketCount>70</BucketCount>
<IncludeOutOfRange>0</IncludeOutOfRange>
<Approximate>0</Approximate>
<HistCounts>1|0|1|0|1|0|1|0|0|0|0|0|0|0|1|2|1|1|0|1|2|0|2|1|1|0|1|4|1|4|0|1|1|1|1|0|2|0|2|3|2|5|2|2|1|1|2|2|1|2|3|1|0|1|0|0|1|0|1|0|2|0|1|1|0|1|0|0|0|1</HistCounts>
</HistItem>
</Histograms>
<Metadata>
<MDI key="STATISTICS_MAXIMUM">675</MDI>
<MDI key="STATISTICS_MEAN">477.87142857143</MDI>
<MDI key="STATISTICS_MINIMUM">260</MDI>
<MDI key="STATISTICS_STDDEV">92.61131085326</MDI>
<MDI key="STATISTICS_VALID_PERCENT">100</MDI>
</Metadata>
</PAMRasterBand>
<PAMRasterBand band="2">
<Histograms>
<HistItem>
<HistMin>259.0714285714286</HistMin>
<HistMax>674.9285714285714</HistMax>
<BucketCount>70</BucketCount>
<IncludeOutOfRange>0</IncludeOutOfRange>
<Approximate>0</Approximate>
<HistCounts>1|0|0|1|0|0|1|1|0|0|0|0|0|0|0|0|2|1|2|3|0|1|1|1|0|2|1|0|3|1|2|2|1|1|1|2|1|1|2|1|7|3|0|0|2|2|0|1|2|1|3|2|0|1|1|0|1|1|2|0|0|1|0|1|0|1|1|0|0|1</HistCounts>
</HistItem>
</Histograms>
<Metadata>
<MDI key="STATISTICS_MAXIMUM">672</MDI>
<MDI key="STATISTICS_MEAN">480.44285714286</MDI>
<MDI key="STATISTICS_MINIMUM">262</MDI>
<MDI key="STATISTICS_STDDEV">92.22931602638</MDI>
<MDI key="STATISTICS_VALID_PERCENT">100</MDI>
</Metadata>
</PAMRasterBand>
<PAMRasterBand band="3">
<Histograms>
<HistItem>
<HistMin>270.1714285714286</HistMin>
<HistMax>671.8285714285714</HistMax>
<BucketCount>70</BucketCount>
<IncludeOutOfRange>0</IncludeOutOfRange>
<Approximate>0</Approximate>
<HistCounts>2|0|1|1|0|0|0|0|0|0|0|0|0|0|0|0|4|2|1|1|1|1|1|1|0|2|2|0|3|1|1|1|2|0|1|0|4|0|1|2|4|0|4|3|1|2|2|2|0|2|0|0|3|3|0|0|0|0|1|1|0|1|0|0|2|1|1|0|0|1</HistCounts>
</HistItem>
</Histograms>
<Metadata>
<MDI key="STATISTICS_MAXIMUM">669</MDI>
<MDI key="STATISTICS_MEAN">482.81428571429</MDI>
<MDI key="STATISTICS_MINIMUM">273</MDI>
<MDI key="STATISTICS_STDDEV">93.115641291145</MDI>
<MDI key="STATISTICS_VALID_PERCENT">100</MDI>
</Metadata>
</PAMRasterBand>
</PAMDataset>
# -*- coding: utf-8 -*-
import weakref
from ..Qt import QtCore, QtGui
from ..python2_3 import sortList, cmp
from ..Point import Point
from .. import functions as fn
from .. import ptime as ptime
......@@ -183,12 +183,14 @@ class GraphicsScene(QtGui.QGraphicsScene):
if int(ev.buttons() & btn) == 0:
continue
if int(btn) not in self.dragButtons: ## see if we've dragged far enough yet
cev = [e for e in self.clickEvents if int(e.button()) == int(btn)][0]
dist = Point(ev.scenePos() - cev.scenePos()).length()
if dist == 0 or (dist < self._moveDistance and now - cev.time() < self.minDragTime):
continue
init = init or (len(self.dragButtons) == 0) ## If this is the first button to be dragged, then init=True
self.dragButtons.append(int(btn))
cev = [e for e in self.clickEvents if int(e.button()) == int(btn)]
if cev:
cev = cev[0]
dist = Point(ev.scenePos() - cev.scenePos()).length()
if dist == 0 or (dist < self._moveDistance and now - cev.time() < self.minDragTime):
continue
init = init or (len(self.dragButtons) == 0) ## If this is the first button to be dragged, then init=True
self.dragButtons.append(int(btn))
## If we have dragged buttons, deliver a drag event
if len(self.dragButtons) > 0:
......@@ -208,10 +210,11 @@ class GraphicsScene(QtGui.QGraphicsScene):
self.dragButtons.remove(ev.button())
else:
cev = [e for e in self.clickEvents if int(e.button()) == int(ev.button())]
if self.sendClickEvent(cev[0]):
#print "sent click event"
ev.accept()
self.clickEvents.remove(cev[0])
if cev:
if self.sendClickEvent(cev[0]):
#print "sent click event"
ev.accept()
self.clickEvents.remove(cev[0])
if int(ev.buttons()) == 0:
self.dragItem = None
......@@ -263,7 +266,8 @@ class GraphicsScene(QtGui.QGraphicsScene):
for item in prevItems:
event.currentItem = item
try:
item.hoverEvent(event)
if item.scene() is self:
item.hoverEvent(event)
except:
debug.printExc("Error sending hover exit event:")
finally:
......@@ -288,7 +292,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
else:
acceptedItem = None
if acceptedItem is not None:
if acceptedItem is not None and acceptedItem.scene() is self:
#print "Drag -> pre-selected item:", acceptedItem
self.dragItem = acceptedItem
event.currentItem = self.dragItem
......@@ -435,6 +439,8 @@ class GraphicsScene(QtGui.QGraphicsScene):
for item in items:
if hoverable and not hasattr(item, 'hoverEvent'):
continue
if item.scene() is not self:
continue
shape = item.shape() # Note: default shape() returns boundingRect()
if shape is None:
continue
......@@ -448,7 +454,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
return 0
return item.zValue() + absZValue(item.parentItem())
sortList(items2, lambda a,b: cmp(absZValue(b), absZValue(a)))
items2.sort(key=absZValue, reverse=True)
return items2
......@@ -557,6 +563,3 @@ class GraphicsScene(QtGui.QGraphicsScene):
@staticmethod
def translateGraphicsItems(items):
return list(map(GraphicsScene.translateGraphicsItem, items))
......@@ -23,6 +23,8 @@ class ExportDialog(QtGui.QWidget):
self.currentExporter = None
self.scene = scene
self.exporterParameters = {}
self.selectBox = QtGui.QGraphicsRectItem()
self.selectBox.setPen(fn.mkPen('y', width=3, style=QtCore.Qt.DashLine))
self.selectBox.hide()
......@@ -121,7 +123,18 @@ class ExportDialog(QtGui.QWidget):
return
expClass = self.exporterClasses[str(item.text())]
exp = expClass(item=self.ui.itemTree.currentItem().gitem)
params = exp.parameters()
if prev:
oldtext = str(prev.text())
self.exporterParameters[oldtext] = self.currentExporter.parameters()
newtext = str(item.text())
if newtext in self.exporterParameters.keys():
params = self.exporterParameters[newtext]
exp.params = params
else:
params = exp.parameters()
self.exporterParameters[newtext] = params
if params is None:
self.ui.paramTree.clear()
else:
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>241</width>
<height>367</height>
</rect>
</property>
<property name="windowTitle">
<string>Export</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>Item to export:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QTreeWidget" name="itemTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Export format</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QListWidget" name="formatList"/>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="exportBtn">
<property name="text">
<string>Export</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="closeBtn">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="ParameterTree" name="paramTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Export options</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="copyBtn">
<property name="text">
<string>Copy</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ParameterTree</class>
<extends>QTreeWidget</extends>
<header>..parametertree</header>
</customwidget>
</customwidgets>
<resources/>
<co