diff --git a/crayfish/gui/plot_1d_widget.py b/crayfish/gui/plot_1d_widget.py index e0fecd7f..ff4c8ffc 100644 --- a/crayfish/gui/plot_1d_widget.py +++ b/crayfish/gui/plot_1d_widget.py @@ -46,7 +46,7 @@ from ..plot import timeseries_plot_data, cross_section_plot_data, colors, profile_1D_plot_data from .utils import time_to_string -from .plot_cf_layer_widget import CrayfishLayerWidget +from .plot_cf_layer_widget import CrayfishLayer1dWidget from .plot_1d_profile_widget import Profile1DPickerWidget from .plot_point_geometry_widget import PointGeometryPickerWidget from .plot_datasets_widget import DatasetsWidget @@ -123,7 +123,7 @@ def __init__(self, parent=None): self.layer = None - self.btn_layer = CrayfishLayerWidget(meshType=QgsMesh.Edge) + self.btn_layer = CrayfishLayer1dWidget() self.btn_layer.layer_changed.connect(self.on_layer_changed) self.btn_dataset_group = DatasetGroupsWidget() diff --git a/crayfish/gui/plot_3d_widget.py b/crayfish/gui/plot_3d_widget.py index 9cd25a62..ff93b160 100644 --- a/crayfish/gui/plot_3d_widget.py +++ b/crayfish/gui/plot_3d_widget.py @@ -47,7 +47,7 @@ from ..plot import colors, plot_3d_data from .utils import time_to_string -from .plot_cf_layer_widget import CrayfishLayerWidget +from .plot_cf_layer_widget import CrayfishLayer3dWidget from .plot_point_geometry_widget import PointGeometryPickerWidget from .plot_datasets_widget import DatasetsWidget from .plot_dataset_groups_widget import DatasetGroupsWidget @@ -59,7 +59,7 @@ def __init__(self, parent=None): self.layer = None - self.btn_layer = CrayfishLayerWidget() + self.btn_layer = CrayfishLayer3dWidget() self.btn_layer.layer_changed.connect(self.on_layer_changed) self.btn_dataset_group = DatasetGroupsWidget(datasetType=QgsMeshDatasetGroupMetadata.DataOnVolumes) diff --git a/crayfish/gui/plot_cf_layer_widget.py b/crayfish/gui/plot_cf_layer_widget.py index ab8c482c..08515b1d 100644 --- a/crayfish/gui/plot_cf_layer_widget.py +++ b/crayfish/gui/plot_cf_layer_widget.py @@ -29,15 +29,14 @@ from PyQt5.QtCore import * from qgis.core import QgsMapLayer, QgsProject, QgsMeshLayer, QgsMesh - +from .utils import * class CrayfishLayerMenu(QMenu): picked_layer = pyqtSignal(QgsMapLayer) - def __init__(self, parent=None, meshType=QgsMesh.Face): + def __init__(self, parent=None): QMenu.__init__(self, parent) - self.meshType = meshType QgsProject.instance().layersAdded.connect(self.layers_added) QgsProject.instance().layersWillBeRemoved.connect(self.layers_will_be_removed) @@ -46,7 +45,7 @@ def __init__(self, parent=None, meshType=QgsMesh.Face): def layers_added(self, lst): for layer in lst: - if not isinstance(layer, QgsMeshLayer) or not self.checkMeshType(layer): + if not self.layerFilter(layer): continue a = self.addAction(layer.name()) a.layer_id = layer.id() @@ -68,6 +67,9 @@ def checkMeshType(self,layer): or (containsEdge and self.meshType==QgsMesh.Edge)\ or (containsFace and self.meshType==QgsMesh.Face) + def layerFilter(self,layer): + raise NotImplementedError + class CrayfishLayerWidget(QToolButton): @@ -78,7 +80,7 @@ def __init__(self, parent=None, meshType=QgsMesh.Face): self.layer = None - self.menu_layers = CrayfishLayerMenu(meshType=meshType) + self.setupMenu() self.setPopupMode(QToolButton.InstantPopup) self.setMenu(self.menu_layers) @@ -99,3 +101,60 @@ def on_picked_layer(self, layer): def layers_will_be_removed(self, lst): if self.layer and self.layer.id() in lst: self.set_layer(None) + + def setupMenu(self): + raise NotImplementedError + + +class CrayfishLayer1dMenu(CrayfishLayerMenu): + + def __init__(self,parent=None): + CrayfishLayerMenu.__init__(self,parent) + + def layerFilter(self, layer): + return isLayer1d(layer) + + +class CrayfishLayer1dWidget(CrayfishLayerWidget): + + def __init__(self, parent=None): + CrayfishLayerWidget.__init__(self,parent) + + def setupMenu(self): + self.menu_layers = CrayfishLayer1dMenu() + + +class CrayfishLayer2dMenu(CrayfishLayerMenu): + + def __init__(self, parent=None): + CrayfishLayerMenu.__init__(self,parent) + + def layerFilter(self, layer): + return isLayer2d(layer) + + +class CrayfishLayer2dWidget(CrayfishLayerWidget): + + def __init__(self, parent=None): + CrayfishLayerWidget.__init__(self,parent) + + def setupMenu(self): + self.menu_layers = CrayfishLayer2dMenu() + + +class CrayfishLayer3dMenu(CrayfishLayerMenu): + + def __init__(self, parent=None): + CrayfishLayerMenu.__init__(self,parent) + + def layerFilter(self, layer): + return isLayer3d(layer) + + +class CrayfishLayer3dWidget(CrayfishLayerWidget): + + def __init__(self, parent=None): + CrayfishLayerWidget.__init__(self,parent) + + def setupMenu(self): + self.menu_layers = CrayfishLayer3dMenu() \ No newline at end of file diff --git a/crayfish/gui/plot_widget.py b/crayfish/gui/plot_widget.py index 55cd6e2b..c4573b1f 100644 --- a/crayfish/gui/plot_widget.py +++ b/crayfish/gui/plot_widget.py @@ -46,7 +46,7 @@ from ..plot import timeseries_plot_data, cross_section_plot_data, colors, integral_plot_data from .utils import time_to_string -from .plot_cf_layer_widget import CrayfishLayerWidget +from .plot_cf_layer_widget import CrayfishLayer2dWidget from .plot_line_geometry_widget import LineGeometryPickerWidget from .plot_point_geometry_widget import PointGeometryPickerWidget from .plot_datasets_widget import DatasetsWidget @@ -152,7 +152,7 @@ def __init__(self, parent=None): self.layer = None - self.btn_layer = CrayfishLayerWidget() + self.btn_layer = CrayfishLayer2dWidget() self.btn_layer.layer_changed.connect(self.on_layer_changed) self.btn_dataset_group = DatasetGroupsWidget() diff --git a/crayfish/gui/utils.py b/crayfish/gui/utils.py index 6f971525..d28ad2ec 100644 --- a/crayfish/gui/utils.py +++ b/crayfish/gui/utils.py @@ -145,3 +145,48 @@ def handle_ffmpeg(dialog): s.setValue("ffmpeg_path", ffmpeg_bin) return ffmpeg_bin + +def isLayer3d(layer): + if layer is None: + return False + + if layer.type()!=QgsMapLayerType.MeshLayer: + return + + dataProvider=layer.dataProvider() + if dataProvider is None: + return False + + datasetGroupCount=dataProvider.datasetGroupCount() + for i in range(datasetGroupCount): + meta=dataProvider.datasetGroupMetadata(i) + if meta.dataType()==QgsMeshDatasetGroupMetadata.DataOnVolumes: + return True + + return False + +def isLayer1d(layer): + if layer is None: + return False + + if layer.type()!=QgsMapLayerType.MeshLayer: + return + + dataProvider=layer.dataProvider() + if dataProvider.contains(QgsMesh.Edge): + return True + else: + return False + +def isLayer2d(layer): + if layer is None: + return False + + if layer.type()!=QgsMapLayerType.MeshLayer: + return + + dataProvider = layer.dataProvider() + if dataProvider.contains(QgsMesh.Face): + return True + else: + return False diff --git a/crayfish/plugin.py b/crayfish/plugin.py index ed073a9e..a2481def 100644 --- a/crayfish/plugin.py +++ b/crayfish/plugin.py @@ -31,7 +31,7 @@ from .gui.plot_widget import CrayfishPlotWidget from .gui.animation_dialog import CrayfishAnimationDialog from .gui.trace_animation_dialog import CrayfishTraceAnimationDialog -from .gui.utils import mesh_layer_active_dataset_group_with_maximum_timesteps +from .gui.utils import mesh_layer_active_dataset_group_with_maximum_timesteps, isLayer1d, isLayer2d, isLayer3d from .processing import CrayfishProcessingProvider from .resources import * @@ -44,6 +44,11 @@ def __init__(self, iface): self.plot_dock_1d_widget = None self.provider = CrayfishProcessingProvider() + QgsProject.instance().layersAdded.connect(self.layers_added) + QgsProject.instance().layersAdded.connect(self.updateActionEnabled) + QgsProject.instance().layersRemoved.connect(self.updateActionEnabled) + self.layers_added(QgsProject.instance().mapLayers().values()) + def initGui(self): # Add menu items self.mesh_menu = self.iface.mainWindow().findChild(QMenu, 'mMeshMenu') @@ -52,8 +57,8 @@ def initGui(self): self.action1DPlot = QAction(QIcon(":/plugins/crayfish/images/icon_plot_1d.svg"),"1D Plot", self.iface.mainWindow()) self.action1DPlot.triggered.connect(self.toggle_1d_plot) - self.actionPlot = QAction(QIcon(":/plugins/crayfish/images/icon_plot.svg"), "2D Plot", self.iface.mainWindow()) - self.actionPlot.triggered.connect(self.toggle_plot) + self.action2DPlot = QAction(QIcon(":/plugins/crayfish/images/icon_plot.svg"), "2D Plot", self.iface.mainWindow()) + self.action2DPlot.triggered.connect(self.toggle_plot) self.action3DPlot = QAction(QIcon(":/plugins/crayfish/images/icon_plot_3d.svg"), "3D Plot", self.iface.mainWindow()) self.action3DPlot.triggered.connect(self.toggle_3d_plot) @@ -65,15 +70,15 @@ def initGui(self): self.actionExportTraceAnimation.triggered.connect(self.exportParticleTraceAnimation) self.menu.addAction(self.action1DPlot) - self.menu.addAction(self.actionPlot) + self.menu.addAction(self.action2DPlot) self.menu.addAction(self.action3DPlot) self.menu.addAction(self.actionExportAnimation) self.menu.addAction(self.actionExportTraceAnimation) # Register actions for context menu - self.iface.addCustomActionForLayerType(self.action1DPlot, '', QgsMapLayer.MeshLayer, True) - self.iface.addCustomActionForLayerType(self.actionPlot, '', QgsMapLayer.MeshLayer, True) - self.iface.addCustomActionForLayerType(self.action3DPlot, '', QgsMapLayer.MeshLayer, True) + self.iface.addCustomActionForLayerType(self.action1DPlot, '', QgsMapLayer.MeshLayer, False) + self.iface.addCustomActionForLayerType(self.action2DPlot, '', QgsMapLayer.MeshLayer, False) + self.iface.addCustomActionForLayerType(self.action3DPlot, '', QgsMapLayer.MeshLayer, False) self.iface.addCustomActionForLayerType(self.actionExportAnimation, '', QgsMapLayer.MeshLayer, True) self.iface.addCustomActionForLayerType(self.actionExportTraceAnimation, '', QgsMapLayer.MeshLayer, True) @@ -81,7 +86,7 @@ def initGui(self): self.iface.layerTreeView().currentLayerChanged.connect(self.active_layer_changed) # Create widget - self.plot_dock_widget = QDockWidget("Crayfish Plot") + self.plot_dock_widget = QDockWidget("Crayfish 2D Plot") self.plot_dock_widget.setObjectName("CrayfishPlotDock") self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.plot_dock_widget) w = CrayfishPlotWidget(self.plot_dock_widget) @@ -90,6 +95,8 @@ def initGui(self): QgsApplication.processingRegistry().addProvider(self.provider) + self.updateActionEnabled() + def active_layer_changed(self, layer): # only change layer when there is none selected if self.plot_dock_widget.widget().layer: @@ -97,7 +104,15 @@ def active_layer_changed(self, layer): # only assign layer when active layer is a mesh layer if layer and layer.type() == QgsMapLayer.MeshLayer: - self.plot_dock_widget.widget().set_layer(layer) + dataProvider=layer.dataProvider() + if dataProvider.contains(QgsMesh.Face): + self.plot_dock_widget.widget().set_layer(layer) + + if self.plot_dock_1d_widget is not None and dataProvider.contains(QgsMesh.Edge): + self.plot_dock_1d_widget.widget().set_layer(layer) + + if self.plot_dock_3d_widget is not None and isLayer3d(layer): + self.plot_dock_3d_widget.widget().set_layer(layer) def toggle_plot(self): self.plot_dock_widget.setVisible(not self.plot_dock_widget.isVisible()) @@ -134,14 +149,14 @@ def toggle_1d_plot(self): def unload(self): # Remove menu item self.menu.removeAction(self.action1DPlot) - self.menu.removeAction(self.actionPlot) + self.menu.removeAction(self.action2DPlot) self.menu.removeAction(self.action3DPlot) self.menu.removeAction(self.actionExportAnimation) self.menu.removeAction(self.actionExportTraceAnimation) # Remove actions for context menu self.iface.removeCustomActionForLayerType(self.action1DPlot) - self.iface.removeCustomActionForLayerType(self.actionPlot) + self.iface.removeCustomActionForLayerType(self.action2DPlot) self.iface.removeCustomActionForLayerType(self.action3DPlot) self.iface.removeCustomActionForLayerType(self.actionExportAnimation) self.iface.removeCustomActionForLayerType(self.actionExportTraceAnimation) @@ -215,3 +230,33 @@ def exportParticleTraceAnimation(self): dlg = CrayfishTraceAnimationDialog(self.iface) dlg.exec_() + + def layers_added(self, lst): + + for layer in lst: + if isLayer1d(layer): + self.iface.addCustomActionForLayer(self.action1DPlot, layer) + if isLayer2d(layer): + self.iface.addCustomActionForLayer(self.action2DPlot, layer) + if isLayer3d(layer): + self.iface.addCustomActionForLayer(self.action3DPlot, layer) + + def updateActionEnabled(self): + layers = QgsProject.instance().mapLayers().values() + + enabled = len(layers)!=0 + self.actionExportAnimation.setEnabled(enabled) + self.actionExportTraceAnimation.setEnabled(enabled) + + self.action1DPlot.setEnabled(False) + self.action2DPlot.setEnabled(False) + self.action3DPlot.setEnabled(False) + + for layer in layers: + if isLayer1d(layer): + self.action1DPlot.setEnabled(True) + if isLayer2d(layer): + self.action2DPlot.setEnabled(True) + if isLayer3d(layer): + self.action3DPlot.setEnabled(True) +