Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QgsRasterLayerProperies does not call QgsMapLayerConfigWidget::apply #46832

Closed
2 tasks done
jakimowb opened this issue Jan 14, 2022 · 0 comments · Fixed by #46833
Closed
2 tasks done

QgsRasterLayerProperies does not call QgsMapLayerConfigWidget::apply #46832

jakimowb opened this issue Jan 14, 2022 · 0 comments · Fixed by #46833
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! PyQGIS Related to the PyQGIS API

Comments

@jakimowb
Copy link
Contributor

jakimowb commented Jan 14, 2022

What is the bug or the crash?

The vector/raster layer options shown in a QgsVectorLayerProperties/QgsRasterLayerProperties dialog can be enhanced with customized QgsMapLayerConfigWidgets.

After a user triggers the "Accept" or "Apply" button, the dialogs apply method is expected to call the custom widget's apply method as well. However, while this is implemented in QgsVectorLayerProperties (see code below), it is missing in QgsRasterLayerProperties:

void QgsVectorLayerProperties::apply(){
 ...
  // apply all plugin dialogs
  const auto constMLayerPropertiesPages = mLayerPropertiesPages;
  for ( QgsMapLayerConfigWidget *page : constMLayerPropertiesPages )
  {
    page->apply();
  }
 ...
}

Steps to reproduce the issue

This is a unit test to replicate the described behaviour.

import qgis  
import pathlib
import typing
from qgis.PyQt.QtWidgets import QWidget
from qgis.PyQt.QtGui import QIcon
from qgis.gui import QgsMapCanvas, QgsMapLayerConfigWidgetFactory, QgsMapLayerConfigWidget, QgsRasterLayerProperties
from qgis.core import QgsMapLayer, QgsProject, QgsRasterLayer
from utilities import unitTestDataPath
from qgis.testing import start_app, unittest

# Convenience instances in case you may need them
# not used in this test
start_app()


class TestQgsRasterLayerProperties(unittest.TestCase):

    def setUp(self):
        QgsProject.instance().removeAllMapLayers()

    def test_custom_widgets(self):
        class MyWidget(QgsMapLayerConfigWidget):
            """
            A custom QgsMapLayerConfigWidget
            """

            COUNT = 0

            def __init__(self, layer: QgsMapLayer, canvas: QgsMapCanvas, parent: QWidget = None):
                super().__init__(layer, canvas, parent=parent)

            def apply(self) -> None:
                MyWidget.COUNT += 1

        class MyFactory(QgsMapLayerConfigWidgetFactory):
            """
            A custom QgsMapLayerConfigWidgetFactory
            """

            COUNT = 0

            def __init__(self, title: str, icon: QIcon):
                super(MyFactory, self).__init__(title, icon)

            def supportsLayer(self, layer):
                return True

            def supportLayerPropertiesDialog(self):
                return True

            def createWidget(self,
                             layer: QgsMapLayer,
                             canvas: QgsMapCanvas,
                             dockWidget: bool = ..., parent:
                    typing.Optional[QWidget] = ...) -> QgsMapLayerConfigWidget:
                MyFactory.COUNT += 1
                w = MyWidget(layer, canvas, parent=parent)
                return w

        myFactory = MyFactory('Dummy Factory', QIcon())
        myCanvas = QgsMapCanvas()

        myPath = pathlib.Path(unitTestDataPath('raster')) / 'band1_float32_noct_epsg4326.tif'

        myRasterLayer = QgsRasterLayer(myPath.as_posix(), myPath.name)

        assert myRasterLayer.isValid(), f'Raster not loaded {myPath}'

        dialog = QgsRasterLayerProperties(myRasterLayer, myCanvas)

        dialog.addPropertiesPageFactory(myFactory)
        dialog.show()

        # this triggers the dialog's apply
        dialog.accept()
        self.assertEqual(MyFactory.COUNT, 1, msg=f'Custom QgsMapLayerConfigWidget::createWidget(...) not called')
        self.assertEqual(MyWidget.COUNT, 1, msg=f'Custom QgsMapLayerConfigWidget::apply() not called')

Versions

3.23.0-Master
code revision 18979e5

Supported QGIS version

  • I'm running a supported QGIS version according to the roadmap.

New profile

  • I tried with a new QGIS profile

Additional context

No response

@jakimowb jakimowb added the Bug Either a bug report, or a bug fix. Let's hope for the latter! label Jan 14, 2022
@gioman gioman added the PyQGIS Related to the PyQGIS API label Jan 14, 2022
jakimowb added a commit to jakimowb/QGIS that referenced this issue Jan 14, 2022
QgsRasterLayerProperties::apply now calls QgsMapLayerConfigWidget::apply
of added customized config widgets
nyalldawson pushed a commit that referenced this issue Jan 16, 2022
QgsRasterLayerProperties::apply now calls QgsMapLayerConfigWidget::apply
of added customized config widgets
qgis-bot pushed a commit that referenced this issue Jan 16, 2022
QgsRasterLayerProperties::apply now calls QgsMapLayerConfigWidget::apply
of added customized config widgets
nyalldawson pushed a commit that referenced this issue Jan 17, 2022
QgsRasterLayerProperties::apply now calls QgsMapLayerConfigWidget::apply
of added customized config widgets
manisandro pushed a commit to kadas-albireo/QGIS that referenced this issue Jan 24, 2022
QgsRasterLayerProperties::apply now calls QgsMapLayerConfigWidget::apply
of added customized config widgets
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! PyQGIS Related to the PyQGIS API
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants