diff --git a/eotimeseriesviewer/docks.py b/eotimeseriesviewer/docks.py index 2eb6a1bd7eeddeade239e5b467ca762d7f2f5e61..39377bb4724d9cf84a91ebf9c78fd869a8c4b259 100644 --- a/eotimeseriesviewer/docks.py +++ b/eotimeseriesviewer/docks.py @@ -10,7 +10,7 @@ from eotimeseriesviewer.labeling import LabelWidget, gotoNextFeature, gotoPrevio class SpectralLibraryDockWidget(SpectralLibraryPanel): def __init__(self, speclib: SpectralLibrary, *args, **kwds): - super().__init__(*args, **kwds) + super().__init__(*args, speclib=speclib, **kwds) assert isinstance(self.SLW, SpectralLibraryWidget) self.mActionNextFeature = QAction('Next Feature', parent=self) self.mActionNextFeature.setIcon(QIcon(':/images/themes/default/mActionAtlasNext.svg')) @@ -31,7 +31,7 @@ class SpectralLibraryDockWidget(SpectralLibraryPanel): self.SLW.mToolbar: QToolBar self.SLW.mToolbar.insertActions(self.SLW.mActionToggleEditing, - [self.mActionPreviousFeature, self.mActionNextFeature]) + [self.mActionPreviousFeature, self.mActionNextFeature]) self.SLW.mToolbar.insertSeparator(self.SLW.mActionToggleEditing) def setVectorLayerTools(self, tools: QgsVectorLayerTools): diff --git a/eotimeseriesviewer/externals/qps/__init__.py b/eotimeseriesviewer/externals/qps/__init__.py index 2667579da0d75c8da976ec67f3c033c6db964869..c1fbe1fffcae5c3a9fed78dfe10ff15b3a61a30d 100644 --- a/eotimeseriesviewer/externals/qps/__init__.py +++ b/eotimeseriesviewer/externals/qps/__init__.py @@ -24,19 +24,24 @@ *************************************************************************** """ -import sys, importlib, site, os, pathlib, typing +import pathlib +import sys +import typing + from qgis.core import QgsApplication -from qgis.gui import QgisInterface, QgsMapLayerConfigWidgetFactory +from qgis.gui import QgsMapLayerConfigWidgetFactory + __version__ = '1.0' -DIR_UI_FILES = pathlib.Path(__file__).parent / 'ui' +DIR_QPS = pathlib.Path(__file__).parent +DIR_UI_FILES = DIR_QPS / 'ui' DIR_ICONS = DIR_UI_FILES / 'icons' -QPS_RESOURCE_FILE = pathlib.Path(__file__).parent / 'qpsresources_rc.py' - +QPS_RESOURCE_FILE = DIR_QPS / 'qpsresources_rc.py' MAPLAYER_CONFIGWIDGET_FACTORIES = list() -def registerMapLayerConfigWidgetFactory(factory:QgsMapLayerConfigWidgetFactory): + +def registerMapLayerConfigWidgetFactory(factory: QgsMapLayerConfigWidgetFactory): """ Register a new tab in the map layer properties dialog. :param factory: QgsMapLayerConfigWidgetFactory @@ -48,7 +53,8 @@ def registerMapLayerConfigWidgetFactory(factory:QgsMapLayerConfigWidgetFactory): if factory not in MAPLAYER_CONFIGWIDGET_FACTORIES: MAPLAYER_CONFIGWIDGET_FACTORIES.append(factory) -def unregisterMapLayerConfigWidgetFactory(factory:QgsMapLayerConfigWidgetFactory): + +def unregisterMapLayerConfigWidgetFactory(factory: QgsMapLayerConfigWidgetFactory): """ Unregister a previously registered tab in the map layer properties dialog. :param factory: @@ -60,6 +66,7 @@ def unregisterMapLayerConfigWidgetFactory(factory:QgsMapLayerConfigWidgetFactory while factory in MAPLAYER_CONFIGWIDGET_FACTORIES: MAPLAYER_CONFIGWIDGET_FACTORIES.remove(factory) + def mapLayerConfigWidgetFactories() -> typing.List[QgsMapLayerConfigWidgetFactory]: """ Returns registered QgsMapLayerConfigWidgetFactories @@ -68,6 +75,7 @@ def mapLayerConfigWidgetFactories() -> typing.List[QgsMapLayerConfigWidgetFactor """ return MAPLAYER_CONFIGWIDGET_FACTORIES[:] + def registerEditorWidgets(): """ Call this function to register QgsEditorwidgetFactories to the QgsEditorWidgetRegistry @@ -112,12 +120,13 @@ def registerMapLayerConfigWidgetFactories(): registerMapLayerConfigWidgetFactory(RasterBandConfigWidgetFactory()) registerMapLayerConfigWidgetFactory(GDALMetadataConfigWidgetFactory()) + def initResources(): from .testing import initResourceFile initResourceFile(QPS_RESOURCE_FILE) + def initAll(): initResources() registerEditorWidgets() registerMapLayerConfigWidgetFactories() - diff --git a/eotimeseriesviewer/externals/qps/resources.py b/eotimeseriesviewer/externals/qps/resources.py index 914aded28d11f2854e9a170451627f0dd038d8ee..4a10b3424b5ced417bb367cb131abc89a633dbb5 100644 --- a/eotimeseriesviewer/externals/qps/resources.py +++ b/eotimeseriesviewer/externals/qps/resources.py @@ -25,14 +25,21 @@ *************************************************************************** """ -import sys, os, pathlib, typing, re +import os +import pathlib +import re +import sys +import typing +import site + +from qgis.PyQt.QtCore import * from qgis.PyQt.QtGui import * +from qgis.PyQt.QtSvg import QGraphicsSvgItem from qgis.PyQt.QtWidgets import * -from qgis.PyQt.QtCore import * from qgis.PyQt.QtXml import * -from qgis.PyQt.QtSvg import QGraphicsSvgItem from .utils import file_search, findUpwardPath + REGEX_FILEXTENSION_IMAGE = re.compile(r'\.([^.]+)$') @@ -45,7 +52,8 @@ def getDOMAttributes(elem): values[str(attr.nodeName())] = attr.nodeValue() return values -def compileResourceFiles(dirRoot:str, targetDir:str=None, suffix:str= '_rc.py'): + +def compileResourceFiles(dirRoot: str, targetDir: str = None, suffix: str = '_rc.py'): """ Searches for *.ui files and compiles the *.qrc files they use. :param dirRoot: str, root directory, in which to search for *.qrc files or a list of *.ui file paths. @@ -125,7 +133,8 @@ def compileResourceFiles(dirRoot:str, targetDir:str=None, suffix:str= '_rc.py'): for qrcFile in qrc_files_skipped: print(qrcFile.as_posix()) -def compileResourceFile(pathQrc, targetDir=None, suffix:str='_rc.py', compressLevel=7, compressThreshold=100): + +def compileResourceFile(pathQrc, targetDir=None, suffix: str = '_rc.py', compressLevel=7, compressThreshold=100): """ Compiles a *.qrc file :param pathQrc: @@ -145,7 +154,6 @@ def compileResourceFile(pathQrc, targetDir=None, suffix:str='_rc.py', compressLe assert isinstance(targetDir, pathlib.Path) targetDir = targetDir.resolve() - cwd = pathlib.Path(pathQrc).parent pathPy = targetDir / (os.path.splitext(pathQrc.name)[0] + suffix) @@ -155,7 +163,7 @@ def compileResourceFile(pathQrc, targetDir=None, suffix:str='_rc.py', compressLe cmd = 'pyrcc5 -compress {} -o {} {}'.format(compressLevel, pathPy, pathQrc) cmd2 = 'pyrcc5 -no-compress -o {} {}'.format(pathPy.as_posix(), pathQrc.name) - #print(cmd) + # print(cmd) import PyQt5.pyrcc_main @@ -179,7 +187,7 @@ def compileResourceFile(pathQrc, targetDir=None, suffix:str='_rc.py', compressLe os.chdir(last_cwd) -def compileQGISResourceFiles(qgis_repo:str, target:str=None): +def compileQGISResourceFiles(qgis_repo: str, target: str = None): """ Searches for *.qrc files in the QGIS repository and compile them to <target> @@ -202,7 +210,8 @@ def compileQGISResourceFiles(qgis_repo:str, target:str=None): qgis_repo = pathlib.Path(qgis_repo) assert isinstance(qgis_repo, pathlib.Path) assert qgis_repo.is_dir() - assert (qgis_repo / 'images' /'images.qrc').is_file(), '{} is not the QGIS repository root'.format(qgis_repo.as_posix()) + assert (qgis_repo / 'images' / 'images.qrc').is_file(), '{} is not the QGIS repository root'.format( + qgis_repo.as_posix()) if target is None: DIR_REPO = findUpwardPath(__file__, '.git') @@ -260,9 +269,9 @@ def initResourceFile(path): try: __import__(name) # spec = importlib.util.spec_from_file_location(name, path) - #rcModule = importlib.util.module_from_spec(spec) - #spec.loader.exec_module(rcModule) - #rcModule.qInitResources() + # rcModule = importlib.util.module_from_spec(spec) + # spec.loader.exec_module(rcModule) + # rcModule.qInitResources() except Exception as ex: print(ex, file=sys.stderr) @@ -270,6 +279,7 @@ def initResourceFile(path): if add_path: sys.path.remove(path.parent.as_posix()) + def findQGISResourceFiles(): """ Tries to find a folder 'qgisresources'. @@ -310,6 +320,7 @@ def scanResources(path=':') -> str: elif D.fileInfo().isFile(): yield D.filePath() + def printResources(): print('Available resources:') res = sorted(list(scanResources())) @@ -317,7 +328,6 @@ def printResources(): print(r) - class ResourceTableModel(QAbstractTableModel): def __init__(self, *args, **kwds): @@ -381,14 +391,11 @@ class ResourceTableModel(QAbstractTableModel): class ResourceTableView(QTableView): def __init__(self, *args, **kwds): - super().__init__(*args ,**kwds) - + super().__init__(*args, **kwds) def contextMenuEvent(self, event: QContextMenuEvent) -> None: - idx = self.indexAt(event.pos()) if isinstance(idx, QModelIndex) and idx.isValid(): - uri = idx.data(Qt.UserRole) m = QMenu() a = m.addAction('Copy Name') @@ -420,7 +427,7 @@ class ResourceBrowser(QWidget): self.btnReload: QToolButton self.preview: QLabel - self.graphicsView:QGraphicsView + self.graphicsView: QGraphicsView self.graphicsScene = QGraphicsScene() self.graphicsView.setScene(self.graphicsScene) @@ -460,8 +467,6 @@ class ResourceBrowser(QWidget): self.resourceProxyModel.setFilterRegExp(None) self.info.setText(expr.errorString()) - - def onSelectionChanged(self, selected, deselected): selectedIdx = selected.indexes() @@ -474,7 +479,7 @@ class ResourceBrowser(QWidget): uri = idx1.data(Qt.UserRole) self.updatePreview(uri) - def updatePreview(self, uri:str): + def updatePreview(self, uri: str): hasImage = False hasText = False @@ -510,13 +515,10 @@ class ResourceBrowser(QWidget): self.tabWidget.setTabEnabled(self.tabWidget.indexOf(self.pageImage), hasImage) self.tabWidget.setTabEnabled(self.tabWidget.indexOf(self.pageText), hasText) - - def useFilterRegex(self) -> bool: return self.optionUseRegex.isChecked() - def showResources() -> ResourceBrowser: """ A simple way to list available Qt resources @@ -530,4 +532,5 @@ def showResources() -> ResourceBrowser: browser.show() if needQApp: QApplication.instance().exec_() - return browser \ No newline at end of file + return browser + diff --git a/eotimeseriesviewer/main.py b/eotimeseriesviewer/main.py index 7ae4e186a8576b99e45c8085abe46f1ba7092c7d..2e69ed4266531f7736fa6f52a3ace102544b220b 100644 --- a/eotimeseriesviewer/main.py +++ b/eotimeseriesviewer/main.py @@ -1662,6 +1662,7 @@ class EOTimeSeriesViewer(QgisInterface, QObject): for field in SPECTRA_PROFILE_FIELDS: speclib.addAttribute(field) assert speclib.commitChanges() + QgsProject.instance().addMapLayer(speclib) self.showAttributeTable(speclib) self.addMapLayers(speclib) diff --git a/eotimeseriesviewer/mapvisualization.py b/eotimeseriesviewer/mapvisualization.py index 33e60f18fa715131a7836606b07a131f8ad61a87..e51587086654ae7a7d3d2187b9b24db25f130fef 100644 --- a/eotimeseriesviewer/mapvisualization.py +++ b/eotimeseriesviewer/mapvisualization.py @@ -626,16 +626,28 @@ class MapView(QFrame): assert isinstance(sensor, SensorInstrument) if sensor not in self.sensors(): sensor.sigNameChanged.connect(self.sigCanvasAppearanceChanged) + masterLayer: SensorProxyLayer = sensor.proxyRasterLayer() assert isinstance(masterLayer.renderer(), QgsRasterRenderer) + self.mSensorLayerList.append((sensor, masterLayer)) masterLayer.styleChanged.connect(lambda *args, v=self, l=masterLayer: self.onMasterStyleChanged(l)) + masterLayer.nameChanged.connect(self.onMasterLyrNameChanged) layerTreeLayer: QgsLayerTreeLayer = self.mLayerTreeSensorNode.addLayer(masterLayer) layerTreeLayer.setCustomProperty(KEY_LOCKED_LAYER, True) layerTreeLayer.setCustomProperty(KEY_SENSOR_LAYER, True) + dummyLayers = self.mDummyCanvas.layers() + [masterLayer] + self.mDummyCanvas.setLayers(dummyLayers) + self.mLayerStyleInitialized[sensor] = False + def onMasterLyrNameChanged(self, *args): + lyr = self.sender() + newname = lyr.name() + ltn = self.mLayerTreeSensorNode.findLayer(lyr) + #print(ltn.name()) + def onMasterStyleChanged(self, masterLayer: SensorProxyLayer): sensor: SensorInstrument = masterLayer.sensor() @@ -694,7 +706,7 @@ class MapView(QFrame): self.mLayerTreeSensorNode.removeLayer(t[1]) self.mSensorLayerList.remove(t) - def hasSensor(self, sensor) -> bool: + def hasSensor(self, sensor: SensorInstrument) -> bool: """ :param sensor: :return: @@ -777,9 +789,10 @@ class MapViewLayerTreeViewMenuProvider(QgsLayerTreeViewMenuProvider): model = self.layerTreeModel() ltree = self.layerTree() - view = self.layerTreeView() + view: QgsLayerTreeView = self.layerTreeView() currentGroup = view.currentGroupNode() currentLayer = view.currentLayer() + currentIndex = view.currentIndex() currentCanvas = self.mapView().currentMapCanvas() isSensorGroup = isinstance(currentGroup, QgsLayerTreeGroup) and currentGroup.customProperty( @@ -799,6 +812,10 @@ class MapViewLayerTreeViewMenuProvider(QgsLayerTreeViewMenuProvider): menu = QMenu(view) assert isinstance(mw, MapWidget) if isinstance(currentLayer, QgsMapLayer): + a = menu.addAction('Rename') + a.triggered.connect(lambda *args, cidx=currentIndex: view.edit(cidx)) + menu.addSeparator() + # zoom to layer menu.addAction(eotsv.actionZoomToLayer()) @@ -856,8 +873,8 @@ class MapViewLayerTreeViewMenuProvider(QgsLayerTreeViewMenuProvider): menu.addAction(eotsv.actionCopyLayerStyle()) # Properties - menu.addAction(eotsv.actionLayerProperties()) menu.addSeparator() + menu.addAction(eotsv.actionLayerProperties()) menu.addSeparator() return menu diff --git a/eotimeseriesviewer/timeseries.py b/eotimeseriesviewer/timeseries.py index b3d1136b05faa85f9384494d36d30e7a00d88168..1c52c45997a1872cb2e4576947b396ca89777048 100644 --- a/eotimeseriesviewer/timeseries.py +++ b/eotimeseriesviewer/timeseries.py @@ -299,7 +299,7 @@ class SensorInstrument(QObject): :return: QgsRasterLayer """ lyr = SensorProxyLayer(self.mMockupDS.GetFileList()[0], name=self.name(), sensor=self) - lyr.nameChanged.connect(lambda l=lyr: self.setName(l.name())) + lyr.nameChanged.connect(lambda *args, l=lyr: self.setName(l.name())) lyr.setCustomProperty('eotsv/sensorid', self.id()) self.sigNameChanged.connect(lyr.setName) return lyr