Icon style guide¶
geoserver_manager/resources/icons/catalog.json is the single inventory of
the plugin’s icons. Reuse an existing ID when the meaning matches. The SVGs
live beside it. Qt’s own checkboxes, message symbols and window controls are
outside this registry. The brand mark keeps its original
proportions.
Drawing rules¶
Use a 24 × 24 canvas, 1.2-unit strokes, round caps and round joins. The dialog shows icons at 20 px, which gives a one-pixel stroke.
Keep path centres mostly within 2 to 22. Leave about two units between unrelated strokes. Use one recognisable object and one action marker.
Keep brushes broad at the tip, and chain links large enough to balance folders and databases. Simplify crowded geometry and keep the strokes thin.
Use an up arrow for sending to GeoServer and a down arrow for bringing content back. Keep the style-transfer pair’s upright brush identical, and reverse only its separate, full-height arrow on the right.
Use a plus for adding, a minus for stopping caching, and a bin for deleting a resource. The cache eraser has a flat contact edge and a short baseline.
Use plain paths and shapes, with no backgrounds, fonts, raster images, gradients or shadows. Use
fill="none"except for small meaningful dots.
Use these exact lowercase colour tokens. The shared renderer replaces them with the widget’s palette and the light or dark accents; the selected and disabled states become monochrome. The shape must carry the meaning without colour.
Token |
Role |
|---|---|
|
Neutral outline |
|
Server, connection or transfer accent |
|
Layer, map or styling accent |
|
Destructive action |
Start from a related SVG. This is the shared structure:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g fill="none" stroke="#172f36" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round">
<!-- Add the object's geometry and one action marker here. -->
</g>
</svg>
Register and use¶
Add a stable, meaningful ID to catalog.json with label, category,
purpose, status: "custom" and asset: "icons/<id>.svg". If the artwork
is pending, omit asset and register the fallback at once:
"new-feature": {
"label": "New feature",
"category": "Utilities",
"purpose": "Describe what the action does.",
"status": "needs-custom",
"fallback": "mActionHelpContents.svg",
"notes": "Describe the custom symbol still needed."
}
When the artwork is ready, replace fallback and notes with the SVG’s
asset and set status to custom. Use the ID in TABS, _row_actions or
icon("new-feature", button.palette()) from gui/icons.py. Do not call
QIcon, getThemeIcon or iconPath elsewhere. A menu-only action uses
for_menu=True for the highlighted colours; a shared toolbar action leaves it
off. Give an icon-only control a tooltip and an accessible name. A row button
shows a 20 px icon inside a target of at least 30 px. Use the shared
row-action builder for the spacing, the keyboard focus, the selection colours
and the labelled secondary actions. Do not make a destructive action a quick
button.
Review¶
python scripts/build_icon_catalog.py --check # validate, write nothing
python scripts/build_icon_catalog.py # optional local gallery
Open build/icon-catalog.html to compare the 16, 20 and 24 px previews in
the light, dark, selected and disabled states. Git ignores the file, and you
can delete it at any time. Also inspect the real QGIS control at normal and
2× scaling. The unit tests check the registration, the fallbacks, missing
SVGs and the stroke consistency; no generated file needs to be committed.
When a visible icon changes, update the usage guide, the changelog and the
screenshot of the real dialog.