A map theme is a list of layer names and visibility flags, so it is data. Two files hold it, because the two halves behave differently:
Value
A list of two data frames:
layers-template,theme,layer,visible,expanded,whykeep-template,theme,group,state
Details
| file | holds | portable? |
inst/lookups/rfp_qgs_themes.csv | layer rows | yes - template blank means any project |
inst/lookups/rfp_qgs_theme_keep.csv | group slots, by NAME | mostly - 41 of 57 rows portable |
No group path is stored (#329, #221). A theme's group state is derived
when it is applied, from where the layers it shows actually sit, so renaming,
moving or deleting a group cannot invalidate it. That is what a stored
group_path could not survive: it was recorded from the project group down,
so every one began bcfishpass Mobile / or bcrestoration Mobile / and
named no group in the other template - which is why the old group file was
scoped in its entirety, 322 rows of it.
Derivation reaches a group only through a layer the theme makes visible,
so a group holding none is invisible to it - the labelled empty slots a crew
drops layers into, Restoration above all (#216). Those are what the keep
file holds, by group name, because a name survives an ancestor rename.
Three words, and the third is subtractive:
| state | effect |
checked | tick this group and its ancestors, though no visible layer derives it |
expanded | expand it beyond the checked set |
collapsed | do not expand it though it is checked - the group only, never its ancestors |
The registry is still lossless, and that is asserted rather than claimed:
data-raw/qgs/themes_extract.R rebuilds all nine shipped presets from the
layer rows plus the keep rows and stops if any checked or expanded group set
differs.
Deriving is safe rather than merely smaller. Measured per preset, the derived
checked-group set contains nothing the stored one lacks - 0 across both
templates' 9 presets and across hornby_2026, sern_skeena_2023 and
sern_thompson_2026 - so it can never reveal a layer a theme meant to
hide. On a project already broken it differs by exactly the burial, which is
why re-applying the registry is also the repair.
A group name that matches several groups sets all of them and reports; a name a project has no group for resolves to nothing and is a no-op, which is what lets a row for a bcrestoration-only group ship portable.
A blank template on a layer row means the row applies to any project.
No shipped theme is scoped, and the one that was is worth knowing about:
High Detail - Crossings carried identical membership in both templates
with 27 of its 28 layers at opposite visibility, because bcrestoration's
copy shipped as a stub with everything switched off (#217). Repairing the
template made the two agree and themes_extract.R collapsed the scoped rows
on its own. The mechanism stays - a theme name is not a global key, and two
templates may legitimately disagree about one - but nothing uses it today.
Five of the eight themes are extracted from the shipped templates - the
union of what the two carry, which is 4 and 5 presets overlapping in 4.
Imagery is carried from hornby_2026, and Floodplain /
Floodplain - Habitat Lateral are derived from the seven field projects that
carry them (#302) - neither template has a Floodplain theme to extract. Those
two carry group rows for BOTH templates, because five of their source
projects are bcrestoration-rooted and two are bcfishpass-rooted. Imagery
and Land Tenure are the only two themes that do not, which is why they are
the two the group-state defect below was found on.
Regenerate both files with Rscript data-raw/qgs/themes_extract.R, which is
the only writer - data-raw/qgs/themes_extract-floodplain.R is sourced by it
rather than run, so two scripts cannot overwrite each other's rows. Never
hand-edited.
See also
Other qgs:
rfp_qgs_form_add(),
rfp_qgs_layer_rm(),
rfp_qgs_preview_set(),
rfp_qgs_raster_add(),
rfp_qgs_service_add(),
rfp_qgs_service_rm(),
rfp_qgs_services(),
rfp_qgs_style_export(),
rfp_qgs_style_set(),
rfp_qgs_subset_get(),
rfp_qgs_subset_set(),
rfp_qgs_theme_add(),
rfp_qgs_theme_names(),
rfp_qgs_theme_rm(),
rfp_qgs_theme_set(),
rfp_qgs_theme_unbury(),
rfp_qgs_themes(),
rfp_qgs_vector_add(),
rfp_qwc_config_create(),
rfp_raster_style_path(),
rfp_raster_styles()
Examples
reg <- rfp_qgs_theme_lookup()
unique(reg$layers$theme)
#> [1] "Floodplain" "Floodplain - Habitat Lateral"
#> [3] "High Detail - Crossings" "Imagery"
#> [5] "Land Tenure" "Low Detail - Bull Trout Model"
#> [7] "Low Detail - Salmon Model" "Low Detail - Steelhead Model"
reg$layers[reg$layers$theme == "Imagery", c("layer", "visible")]
#> layer visible
#> 82 Form FISS Site TRUE
#> 83 Form PSCIS TRUE
#> 84 Bing Aerial FALSE
#> 85 Esri Satellite TRUE
#> 86 ESRI World Topo FALSE
#> 87 Google Satellite FALSE
#> 88 Position track TRUE
#> 89 Provincial park TRUE
#> 90 Roads - DRA TRUE
#> 91 Streams - all TRUE
#> 92 Tracking TRUE
#> 93 Trail feature TRUE
#> 94 Trails TRUE
