Skip to content

Legacy Importer Internals

Bobby Comet edited this page Aug 1, 2026 · 4 revisions

Legacy Importer Internals & Conversion Rules

Project → Import Legacy Theme… builds a Studio project graph from a theme folder. Conversion is semantic, not a pixel-perfect clone. This page documents how that mapping works.

Source of truth in code: conkystudio/importer/legacy_parser.py (UI entry: main_window._import_legacy_theme). Related behaviour also lives in visuals.py / sources_external.py / lua_gen.py / builder.py for Custom Lua inputs and Custom Script inline bodies.


Pipeline overview

theme folder (dialog lists files + hidden; Accept = folder, or parent of a selected file)
  ├── conf / conkyrc → Canvas + palette (colorN / font) + lua_load paths
  ├── TEXT section → cursor layout + text / bar / line / exec nodes
  ├── *.lua (lua_load) → Custom Lua visual node(s) + path rewrites
  └── scripts / images → Custom Script sources (path + optional script_body), asset lists, warnings
        ↓
   Project (nodes + edges + warnings)
        ↓
   _layout_import_graph + _collapse_warnings
        ↓
   Studio canvas load → Build & Install (Manager root) → user polish

Import produces a graph; Build writes start.sh / conf / Lua the same way as native projects.


UI entry (_import_legacy_theme)

  1. Folder dialog — non-native Qt dialog, files and hidden entries visible (ShowDirsOnly = false, QDir filters include Hidden). Selecting a file uses its parent directory as the theme root.
  2. import_legacy_theme(theme_dir) — parse + graph.
  3. load_project — open in Studio.
  4. builder.build_project into a sanitized name under the install root (spaces/parens from "name (imported)" are normalized).
  5. Failures are caught in stages (dialog / parse / canvas / build) with traceback dialogs instead of aborting the process.

Conf block → Canvas (+ palette)

Parsed from the Lua-style conky.config = { ... } (and classic settings where present):

Conf concept Studio target
minimum_width / height (and related; Lua locals like WIDTH resolved when possible) Canvas width / height
alignment, gap_x, gap_y Canvas placement
update_interval Influences FPS / timing defaults where mapped
default_color, color0color9 / colourN Import palette used by ${color…} in TEXT
font / default_font Default cursor font family / size for TEXT
lua_load Resolved relative to the theme dir; may be one path or a list
own_window_* Not always 1:1; Build applies session-aware window types later

lua_load resolution: relative paths, HOME concatenations, and sibling .lua files under the theme are collected. Multiple loads can become multiple Custom Lua nodes.


TEXT section → cursor + nodes

TEXT is walked line by line with a virtual cursor (x, y, font, colour) — the same mental model as Conky’s ${goto} / ${voffset} layout, not a full typesetting engine.

Cursor colour/font start from the conf palette and default font, not hard-coded white/Sans.

Layout directives

Directive Behaviour
${goto N} Set cursor x to N
${offset N} Add N to x
${voffset N} Add N to y
${alignc} / ${alignc N} Centre-ish x using canvas width (+ optional offset)
${alignr} / ${alignr N} Right-side x (canvas width − offset)
${font …} Update cursor font family / size
${color…} / ${colour…} Update cursor colour from palette index, #hex, or default
${hr} / ${stippled_hr} visual.hline at cursor; advances y slightly
blank lines Advance y by font size + spacing

Literal runs of text become visual.text nodes at the current cursor with the active font/colour. Placeholders like {{VALUE:id}} may be turned into String Format logic + a text visual when mixed with surrounding text.

Conditionals

${if_running…}, ${if_match…}, ${endif} are stripped. Content is kept; branching is not reconstructed. A warning is recorded when any conditional was removed.

Native variables → sources (deduplicated)

Identical type + props share one source node (get_or_create_source), so a TEXT-heavy theme does not spawn dozens of CPU boxes. Unknown registered types fall back to a Custom Script placeholder + warning instead of crashing the canvas.

Directive (examples) Studio source / visual
${cpu} / ${cpu N} source.cpu_percent (core mapped when possible)
${mem} / ${memperc} source.ram_percent
${fs_used_perc PATH} source.disk_percent
${fs_bar … PATH} Disk source + visual.bar
${battery} / ${battery_percent} source.battery_percent
${downspeed} / ${downspeedf} source.net_down
${upspeed} / ${upspeedf} source.net_up
${uptime} / ${uptime_short} source.uptime
${nodename} source.hostname
${kernel} source.kernel
${processes} source.process_count
${time FORMAT} source.datetime
${cpubar} / ${membar} Matching source + visual.bar
${cpugraph} / ${memgraph} Matching source + visual.history_graph

Unknown or exotic directives (${top}, swap bars, etc.) are counted and appear in one summary warning (or a short placeholder text node), not one warning per occurrence.


${execi} / ${exec} / friends

Form Import rule
${execi INTERVAL CMD} Interval + command extracted
${execpi} / ${texeci} Same family as execi
${exec CMD} Treated as rare/once-style; Custom Script with a long interval + warning
${execbar … CMD} Source (family/native/custom) + visual.bar

Classification of CMD (_classify_known_script):

  1. Native — known patterns → get_or_create_source for a built-in type.
  2. Family — known script families (weather, playerctl, …) → family source with poll_mode: execi and interval.
  3. ElseCustom Script: script_path set; small file contents copied into script_body (Inline script) so Properties can edit without an external editor.

TEXT may embed a {{VALUE:id}} placeholder so a following text visual can be wired. Unknown scripts are never dropped silently.


${image}

Flag / args Result
path, -p x,y, -s W×H Position/size parsed when present
-n (no cache) Often mapped to Album Art-style node + warning with original path
normal image visual.image_icon if a matching file is found under the theme tree
missing file Node still created with empty/partial path + warning to re-attach

Important: Image/media import is best-effort. Pure-Lua themes typically keep drawing images inside Custom Lua; Build copies listed asset_paths into assets/ and images/. Separate Image nodes are not auto-created for that case (Custom Lua has no bindable image inputs — use Input 1–6 for numeric/text data only).


Cairo / Lua → Custom Lua

Scope boundary (by design): the importer does not decompile Cairo into Arc/Bar/Star nodes.

Input Output
Bodies from lua_load One or more visual.custom_lua nodes
Surface create/destroy boilerplate Stripped or rewritten toward Studio’s shared cr / W / H
Asset / cache paths inside Lua Rewritten toward THEME_DIR / ASSETS_DIR / CACHE_DIR when basenames match
Scripts only referenced from Lua Discovered and turned into Custom Script nodes when possible
Click regions in Lua Clickable markers / commands when patterns are recognized

Post-import data flow (Custom Lua)

Each Custom Lua node has bindable Input 1–6. Codegen injects:

local in1 = (SRC[''] or 0)
--
local in6 =

before the user’s Cairo body. Wire CPU / sensors / Math / Custom Script outputs into those sockets and read in1in6 (use tonumber(in1) when needed) instead of dead conky_parse or host-specific cache paths.

Heavy hand-written themes remain mostly Custom Lua after import — editable, and now able to follow the same source → logic → visual pattern as native nodes.


Scripts & caches (Custom Script)

  • Shell scripts in the theme tree are listed; paths are recorded on Custom Script nodes.
  • script_body (Inline script) is preloaded for files under a size limit so the Properties panel can edit them like Custom Lua code.
  • At Build, non-empty Inline script wins over Script path; body is written under scripts/ (shebang added if missing).
  • Cache directory assumptions in scripts can be patched toward Studio’s .runtime-cache layout.
  • Unwired companion scripts (e.g. sensors.sh for pure-Lua HUDs) still become Custom Script nodes, often daemon mode so Build’s start.sh keeps them running — even when Custom Lua still reads the cache file directly until you rewire Input 1–6.

Post-pass: layout & warnings

Step Rule
_layout_import_graph Sources in a left column; logic beside them; visuals near draw x/y or cx/cy
_collapse_warnings Drop noisy “unrecognised” spam; dedupe identical lines; cap list length
Ignored TEXT directives One summary line listing ${name}×count

Edge-case overrides & honesty limits

Situation Rule
Unknown ${…} var Counted in summary warning; optional placeholder text for top*
Nested complex TEXT Approximate positions
Pure Cairo art Custom Lua only (+ optional Input 1–6 rewiring)
Absolute paths to another machine Survive as strings; break until edited or replaced by wired inputs / Inline script
Pixel parity Target ~70–90% structural usefulness, then polish in Studio

Approximations appear in ImportResult.warnings — read them after import.


After import

  1. Fix Canvas size/alignment.
  2. Wire Custom Lua Input 1–6 and/or edit Custom Script Inline script.
  3. Re-attach missing images if you need first-class Image nodes.
  4. Wire or replace text placeholders.
  5. Live Preview (same pipeline as native).
  6. Build & Install so start.sh is Studio-standard (Import already attempts this once).

See also Legacy Import (user-facing summary).

Clone this wiki locally