A client-side web editor for QLC+ (Q Light Controller Plus) projects. Load two
.qxwworkspaces, compare them, copy items between projects with full conflict handling, perform bulk renames, remap fixtures and save the result β all in a single HTML page, with no server and no upload.
- What is it
- Features
- Installation and launch
- Privacy and security
- π User manual
- Common workflows
- Technologies used
- Known limitations
- Contributing
- License
QLC+ Project Editor is a tool aimed at people working with QLC+, the open-source software for DMX lighting control, who often need to:
- merge parts of one project into another (e.g. moving scenes/chasers from one show into a new production)
- batch rename fixtures, scenes and chasers after duplicating a setup
- remap fixtures when the DMX patch has changed
- compare two workspaces to understand what changed
These tasks, when performed by hand inside QLC+ or in a text editor on the raw XML, are slow and error-prone. This tool makes them fast, safe and visual.
- π Dual loading β Project A and Project B side by side, drag-and-drop or click-to-pick
- π Bidirectional copy of Fixtures, Scenes, Chasers, Audio, Collections, EFX, RGB Matrix, Shows, Videos and Virtual Console widgets
β οΈ Automatic conflict detection β exact duplicates (same name, same content) or name-only matches- π οΈ Three conflict resolution strategies β Copy as New / Overwrite / Skip
- π Recursive dependency copy β when copying a Chaser, Collection or Show you can pick which referenced functions to copy along with it
- π― Configurable insertion point in the destination project (visual selection)
- βοΈ Bulk Rename with five strategies: Find/Replace, Prefix, Suffix, Number, Trim
- β Remap Fixtures β reassign fixture IDs across all of Project A's functions in one go
- π Side-by-side XML editor powered by CodeMirror, with syntax highlighting and folding
- π₯οΈ VC Preview β visual preview of the Virtual Console with zoom and edit mode (drag widgets to reposition)
- πΎ Export the modified project as a native QLC+
.qxwfile
The tool is a single self-contained HTML file. There is nothing to install, no Node, no server.
- Download
qlc_merge.htmlfrom this repository - Open it in any modern browser (Chrome, Firefox, Edge, Safari) β double-click works
- Fork this repository
- Go to Settings β Pages and enable GitHub Pages on the
mainbranch - Open the URL provided by GitHub and use the tool online
Since it's a single static file, you can serve it from any static host (Netlify, Vercel, Cloudflare Pages, internal serverβ¦). No build step required.
π Your files never leave your computer.
XML parsing, modification and saving all happen entirely in the browser through the FileReader API and local blobs. There are no network requests sending your data to any backend server.
The only resources loaded from the network are static libraries served by public CDNs:
- CodeMirror for the XML editor
- Material Design Lite for some UI components
- Google Fonts (Syne, JetBrains Mono)
β οΈ The page contains a Google Analytics tag (gtag.js) for aggregate usage statistics. If you want a fully offline / no-tracking version, remove the<script async src="https://www.googletagmanager.com/...">block fromqlc_merge.html(around line 18). Nothing else will stop working.
The two cards at the top, Project A (blue) and Project B (red), accept QLC+ .qxw or .xml files:
- Click β Load to open the file picker, or
- Drag a file directly onto the card
When a project is loaded, the card shows the filename, the status pill turns green, and the tab counters fill in. If the XML is malformed, an error toast appears without affecting the app's state.
The two colors (A blue, B red) follow you throughout the entire interface, so you always know which project an item belongs to.
Below the loading cards is the 11-tab bar, each tab carrying a badge with the count of items in the project:
| Tab | What it contains |
|---|---|
| Fixtures | Patched DMX fixtures (universe, address, channels) |
| Scenes | Static scenes |
| Chasers | Sequences of scenes |
| Audio | Linked audio tracks |
| Collections | Groupings of functions |
| EFX | Automated effects (movement, colorβ¦) |
| RGB Matrix | Effects on RGB matrices |
| Shows | Full show timelines |
| Videos | Video tracks |
| Virtual Console | Virtual console widgets (button, slider, frameβ¦) |
| VC Preview | Visual preview of the Virtual Console |
Within each tab, two columns display the items from Project A (left) and Project B (right). The search bar filters in real time.
For each item you have actions like: copy to the other project (arrows β / β), rename, view/edit XML inline.
Click the copy arrow (β or β) next to an item. The copy modal opens and asks for:
- Insertion point β a tree view of the destination project where you choose where to place the new item (at the end, after X, inside Yβ¦)
- Referenced functions (only for Chasers, Collections, Shows) β the list of functions the item references. You decide on a per-item basis which ones to bring along
- Conflict resolution (if applicable) β see the next section
Click Copy Here β to confirm. The copy deep-clones the XML, reassigns IDs to avoid collisions and updates cross-references.
When the app detects that the item you're about to copy would conflict with something already in the destination project, it shows a badge:
- π§ β Duplicato (
exact) β same name and same content. You almost certainly don't want a second copy - π¨ β Nome (
warn) β same name but different content. A decision is needed
The copy modal exposes three strategies:
| Resolution | What it does |
|---|---|
| Copy as New | Adds a copy with a new ID. If the name is identical, an automatic suffix is appended (e.g. Scene 1 (2)) |
| Sovrascrivi esistente (Overwrite) | Replaces the existing item in the destination, keeping its ID. All references remain valid |
| Salta (Skip) | Don't copy the item |
The conflict map is recomputed on every project change, so the badges are always up to date.
Click the βοΈ icon next to an item's name β the Rename Object modal opens. As you type the new name, an impact analysis appears showing where the old name was referenced, so you know in advance what will change in the project.
Enter to apply, Esc to cancel.
In every main tab (Fixtures, Scenes, Chasers, Audioβ¦) there's a β Bulk Rename button. Click it β you enter bulk mode:
- Pick the target project (A or B) with the corresponding buttons
- Pick the strategy:
- Trova/Sost. (Find/Replace) β replaces a substring across all names (e.g. find
Washreplace withSpot) - Prefisso (Prefix) β prepends text (e.g.
[OLD]) - Suffisso (Suffix) β appends text (e.g.
v2) - Numera (Number) β appends a sequential number
- Trim β removes characters/substrings
- Trova/Sost. (Find/Replace) β replaces a substring across all names (e.g. find
- Fill in the strategy's input fields: a live preview updates the names as you type
- Tick only the items you want the operation applied to (or use β Tutti / β Nessuno β All / None)
- Click β Applica (Apply) to confirm, β Esci (Exit) to bail out without changes
The operation modifies the names in the XML and automatically updates all cross-references.
The β Remap Fixtures button at the top right (green) becomes active when both projects are loaded. It opens a modal listing the fixtures of Project A and, next to each, a select with all the fixtures of Project B.
Classic use case: you've patched a new show in QLC+ using fixtures of different brands/models, but you want to reuse scenes from an old show. For each old fixture, pick which new fixture should take its place, click Apply Remap and all of Project A's scenes/chasers/efx will be updated to point at the new fixtures.
The collapsible β¨/β© XML Source Viewer & Diff section shows the serialized XML of both projects side by side in CodeMirror editors with syntax highlighting and folding. Useful for:
- inspecting the source of a single item (the inline βοΈ badge next to items)
- hand-editing the XML when you need an operation not covered by the UI
- spotting structural differences between A and B at a glance
Editing the editor re-parses the project automatically and refreshes the entire app.
The VC Preview tab shows a graphical preview of the Virtual Console with widgets in their actual positions:
- Zoom +/-, Fit, 1:1 to adjust the view
- βοΈ Edit to enter edit mode: drag widgets to reposition them directly on the preview, and the changes get written back to the XML
Click β Save on the card of the modified project. The browser will download a .qxw file ready to be imported into QLC+.
π‘ Best practice: always save with a different name from the original (e.g.
myfile_merged.qxw) until you're sure of the result. The tool never overwrites anything automatically β you choose the name at download time.
- Load the old show as Project A and the new setup (with patched fixtures) as Project B
- Open β Remap Fixtures and map A's fixtures onto B's
- In the Scenes/Chasers tabs β pick what you want to bring over and copy it to B (β)
- Save Project B under a new name
- Load the project as Project A and again as Project B (or load the same file on both sides)
- Go to the Scenes tab β β Bulk Rename β strategy Prefisso or Suffisso β apply only to the selected scenes
- Save
- Load the project on both sides (A and B)
- On one side, copy to the other side only what you want to keep
- Save the "clean" side
- Vanilla JavaScript β no framework
- CodeMirror 5.65 β XML editor with folding and syntax highlighting
- Material Design Lite 1.3 β some components
- Native DOMParser / XMLSerializer for parsing/serializing the QLC+ XML
- Google Fonts β Syne (UI) and JetBrains Mono (XML editor)
The entire application lives in a single qlc_merge.html file β roughly 4,100 lines of HTML, CSS and embedded JavaScript.
- Supported browsers: modern evergreens (Chrome 90+, Firefox 90+, Edge 90+, Safari 14+). IE is not supported
.qxwfiles are loaded entirely into memory: very large projects (tens of MB of XML) may slow down the CodeMirror editor- Conflict detection is O(nΒ²) in item counts: efficient up to a few thousand items per project, beyond that some optimization may be needed
- The UI strings are a mixed IT/EN legacy (some buttons read in Italian, e.g.
Applica,Salta,Sovrascrivi esistente). Full internationalization is on the roadmap - Undo/redo is limited to what the XML editor offers β there is no global undo stack across copy/rename operations
Pull requests are welcome! For significant changes, please open an Issue first to discuss the approach.
Since this is a single HTML file, the development workflow is straightforward:
- Open
qlc_merge.htmlin your favorite editor - Edit HTML/CSS/JS directly (the file is organized into sections marked with
// =====comments) - Reload in the browser to test
- The JS code has explanatory comments on the global state object
Sand the main functions
- Full internationalization (separate language files)
- A "visual diff" mode highlighting differences between A and B item by item
- A fully offline build (remove CDN dependencies)
- Automated tests on the XML parser/transformer code
QLC+ is a trademark of its respective owner. This tool is not officially affiliated with the QLC+ project but is intended to complement it.