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

Plugin layer registry #12452

Closed
qgib opened this issue Jan 25, 2010 · 6 comments
Closed

Plugin layer registry #12452

qgib opened this issue Jan 25, 2010 · 6 comments

Comments

@qgib
Copy link
Contributor

qgib commented Jan 25, 2010

Author Name: Mathias Walker (Mathias Walker)
Original Redmine Issue: 2392

Redmine category:python_plugins
Assignee: Martin Dobias


This patch adds a plugin layer registry to support plugin specific maplayers.

Plugins can register a function that creates the specific subclass of QgsMapLayer. This allows to instantiate the corresponding plugin layer when reading the project file.

Workflow

see sample plugin for details

  • create subclass of @QgsMapLayer@
    *** implement @isEditable()@, @draw()@ and @writeXml()@

  • create subclass of @QgsPluginLayerCreator@
    *** implement @Createlayer()@ e.g. as callback to a plugin function

  • init plugin
    *** register PluginLayerCreator using @QgsPluginLayerRegistry.instance().addCreator()@

  • add layer
    *** create PluginMapLayer instance of layer type @QgsMapLayer.PluginLayer@
    *** add layer using @QgsMapLayerRegistry.instance().addMapLayer()@

  • save project
    *** calls @PluginMapLayer.writeXml()@
    *** save plugin id string as attribute @"type"@

  • load project
    *** @QgsPluginLayerRegistry@ calls @Createlayer()@ for all registered @QgsPluginLayerCreators@
    *** plugin creates and adds a new PluginMapLayer instance if the attribute @"type"@ matches their id string

  • unload plugin
    *** unregister PluginLayerCreator using @QgsPluginLayerRegistry.instance().removeCreator()@


@qgib
Copy link
Contributor Author

qgib commented Jan 25, 2010

Author Name: luca76 - (luca76 -)


+1

very interesting patch!

@qgib
Copy link
Contributor Author

qgib commented Jan 25, 2010

Author Name: Marco Hugentobler (@mhugent)


Martin, do you have time to review this patch?

@qgib
Copy link
Contributor Author

qgib commented Jan 26, 2010

Author Name: Giovanni Manghi (@gioman)


applied in 8f32f25 (SVN r12835)


  • resolution was changed from to fixed
  • status_id was changed from Open to Closed

@qgib
Copy link
Contributor Author

qgib commented Jan 26, 2010

Author Name: Martin Dobias (@wonder-sk)


Applied in 8f32f25 (SVN r12835) with several modifications:

  • plugin layers are subclassed from [[QgsPluginLayer]] and not directly from [[QgsMapLayer]] for convenience
  • each plugin layer type has its unique name used in [[QgsPluginLayerRegistry]] - instead of dynamically assigned IDs
  • layer creator has been enhanced to return the unique layer type name and to be able to open layer's properties dialog (and renamed to [[QgsPluginLayerType]] as it's not just a creator)
  • simplified creation of plugin layers: for the unique type name the registry returns instance of the layer
  • when the plugin layer type is removed from registry, layer of that type are removed automatically

I've modified also the sample plugin to reflect my changes.

Sample plugin from the example:

LAYER_TYPE = "sample"

class [[SamplePluginLayer]](QgsPluginLayer):
  def +init+(self, width=None):
    [[QgsPluginLayer]].+init+(self, LAYER_TYPE, "Sample plugin layer")

    self.width = width if width is not None else 256
    self.setValid(True)

  def draw(self, rendererContext):
    painter = rendererContext.painter()
    painter.setPen(Qt.red)
    painter.drawRect(32, 32, self.width, 128)
    return True

  def readXml(self, node):
    self.width = node.toElement().attribute("width", "256").toInt()r0
    return True

  def writeXml(self, node, doc):
    element = node.toElement()
    # write plugin layer type to project (essential to be read from project)
    element.setAttribute("type", "plugin")
    element.setAttribute("name", LAYER_TYPE)
    # custom properties
    element.setAttribute("width", str(self.width))
    return True

Definition of the layer's type with auxiliary methods:

class [[SamplePluginLayerType]](QgsPluginLayerType):
  def +init+(self):
    [[QgsPluginLayerType]].+init+(self, LAYER_TYPE)

  def createLayer(self):
    return [[SamplePluginLayer]]()

  def showLayerProperties(self, layer):
    res = QInputDialog.getInt(None, "Sample plugin", "Set width of the rectangle", layer.width, 1, 1000)
    if resr1: # dialog was not cancelled
      layer.width = resr0
      # trigger repaint
      layer.setCacheImage(None)
      layer.emit(SIGNAL("repaintRequested()"))

    # indicate that we have shown the properties dialog
    return True

Registration:

    [[QgsPluginLayerRegistry]].instance().addPluginLayerType( [[SamplePluginLayerType]]() )

Creation of the layer:

layer = [[SamplePluginLayer]]()
1. -or-
[[QgsPluginLayerRegistry]].instance().pluginLayerType(LAYER_TYPE).createLayer()

Finalization:

    [[QgsPluginLayerRegistry]].instance().removePluginLayerType(LAYER_TYPE)

@wonder-sk
Copy link
Member

@bnegruimajing feel free to open a new issue if something is not working correctly and attach your testing code and more details (qgis version etc)

@bnegruimajing
Copy link

bnegruimajing commented Jun 19, 2019

@wonder-sk please disregard my remark. while building the sample for the bug report, I realized that the "# write plugin layer type to project (essential to be read from project)" comment in SamplePluginLayer.writeXml is not just sample code but actually quite important. I was expecting the QgsPluginLayer base class to take care of the necessary attributes to identify a plugin layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants