4

Is there a way to programmatically access a layer's visibility presets defined in the layer tree view widget (methods, properties, etc.)?

To avoid misunderstandings the part I want to access is the one highlighted in blue in the following screen capture (ex. preset "Test-01" ...)

enter image description here

  • 1
    The question is not very clear, could you elaborate a bit more on what you intend to do? Perhaps through an example? – Germán Carrillo Jul 8 '15 at 14:34
  • 1
    I think that the class you are looking for is this one github.com/qgis/QGIS/blob/master/src/app/qgsvisibilitypresets.h but i'm using qgis 2.4 and i think that presets are not in my system to make tests. I think that you can get it wiht iface.layerMenu() – Francisco Puga Jul 9 '15 at 7:48
  • That seems to be THE answer Francisco but i don't find any trace of this class in the API documentation and i don't see how i should call it so far ... I'm using QGIS 2.6 – snaileater Jul 9 '15 at 9:13
  • Can anybody tell me if the class QgsVisibilityPresets really exists ? i don't clearly understand the online documentation ... – snaileater Jul 14 '15 at 12:43
  • 1
    @snaileater The link provided by Francisco refers to a class in the app folder of the QGIS source code, which is not exposed to Python bindings. Classes in the core or gui folder are offered in PyQGIS, but not QgsVisibilityPresets. – Germán Carrillo Jul 14 '15 at 14:11
2

You can access the visibilityPresetCollection through the project instance:

QgsProject.instance().visibilityPresetCollection()

http://qgis.org/api/classQgsVisibilityPresetCollection.html

1
def visibility_presets():
  """Return the names of the visibility presets in a list."""
  # List order should be the same as in GUI.
  project = qgis.core.QgsProject.instance()
  pr_coll = project.visibilityPresetCollection()
  return pr_coll.presets()

def active_visibility_preset():
  """Return the name of the active visibility preset or
  None if no active visibility preset."""
  # Note that this function should match all layers
  # first by visibility then by stylename.
  project = qgis.core.QgsProject.instance()
  pr_coll = project.visibilityPresetCollection()
  legend = qgis.utils.iface.legendInterface()
  visible_layers_ids = {l.id() for l in legend.layers()
      if legend.isLayerVisible(l)}
  for preset_name in pr_coll.presets():
    pr_state = pr_coll.presetState(preset_name)
    pr_visible_layer_ids = set(pr_state.mVisibleLayerIDs)
    if pr_visible_layer_ids != visible_layers_ids:
      continue
    pr_style_by_layer_id = pr_state.mPerLayerCurrentStyle
    #// alternatively //
    #pr_visible_layer_ids = pr_coll.presetVisibleLayers(
    #    preset_name)
    for layer in legend.layers():
      id_ = layer.id()
    #// alternatively //
    #lreg = qgis.core.QgsMapLayerRegistry.instance()
    #maplayers = lreg.mapLayers()
    #for id_, layer in maplayers.items():
      stylemanager = layer.styleManager()
      curr_style = stylemanager.currentStyle()
      if curr_style != pr_style_by_layer_id.get(id_, u''):
        break
    else:  # finished without break
      return preset_name

def activate_visibility_preset(preset_name):
  """Activates a visibility preset by its name.
  Return a boolean indicating success."""
  # Note that it iterates over all layers and turn them on or
  # off then activate their named stlye according to the preset.
  project = qgis.core.QgsProject.instance()
  pr_coll = project.visibilityPresetCollection()
  if preset_name not in pr_coll.presets():
    return False
  pr_state = pr_coll.presetState(preset_name)
  pr_visible_layer_ids = pr_state.mVisibleLayerIDs
  pr_style_by_layer_id = pr_state.mPerLayerCurrentStyle
  legend = qgis.utils.iface.legendInterface()
  for layer in legend.layers():
    id_ = layer.id()
    visible = legend.isLayerVisible(layer)
    pr_visible = (id_ in pr_visible_layer_ids)
    # turn the unvisible off and set style while hidden
    if not pr_visible and visible:
      legend.setLayerVisible(layer, False)
    pr_layer_style_name = pr_style_by_layer_id.get(id_, u'')
    stylemanager = layer.styleManager()
    curr_style = stylemanager.currentStyle()
    # set style only if differs assuming some overhead in it
    if pr_layer_style_name != curr_style:
      stylemanager.setCurrentStyle(pr_layer_style_name)
    # now after style is matched, turn off if hidden but should
    # be visible
    if pr_visible and not visible:
      legend.setLayerVisible(layer, True)
  return True

Usage:

>>> visibility_presets()
[u'Test-01']
>>> activate_visibility_preset(u'Test-01')
True
>>> active_visibility_preset()
u'Test-01'

Tested on QGIS 2.18.6. If you know how to improve it, please share it!

Code on GitHub Gist (if you upvote here I would appreciate a star there too)

1

If you are using QGIS 3.0 freshly released, instead of

QgsProject.instance().visibilityPresetCollection()

you now have to use the following:

QgsProject.instance().mapThemeCollection()

as stated in QGIS 3.0 API Backwards Incompatible Changes

Then, you can get themes names with:

QgsProject.instance().mapThemeCollection().mapThemes()
0

If you have your layer for example as:

layer = iface.activeLayer()

You should get legend:

legend = iface.legendInterface()

Then you can check layers visibility (it returns bool):

legend.isLayerVisible(layer)

Or toggle visibility:

# off
legend.setLayerVisible(layer, False)
# on
legend.setLayerVisible(layer, True)
  • yeah thanks i knew these one but u describe a per layer access, my question is about the whole visibility preset (which is a set of "checked" layers) ... how can we access the members of the set, the name of the set, how can we activate a set and/or switch to another ? ... – snaileater Jul 8 '15 at 9:33
  • To be more precise (maybe...) is there a Qgis Class related to these layers visibility presets (i hope i use the right english name, sorry...) ? – snaileater Jul 8 '15 at 9:42
  • If you want to get set of visible layers you have to use for loop on all layers and add them to list or something like that. There isn't any class related to all visible or invisible layers. Maybe layers group, but it isn't related with visibility. – dmh126 Jul 8 '15 at 9:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.