Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,6 @@ img.intro-screenshot {
.body-container .olist,
.body-container .ulist,
.body-container .exampleblock,
.body-container .imageblock,
.body-container .listingblock,
.body-container .literalblock,
.body-container .sidebarblock,
Expand All @@ -339,6 +338,11 @@ img.intro-screenshot {
margin-bottom: 1rem;
}

.body-container .imageblock {
/* was 1rem, but it looks ugly to have that space after images */
margin-bottom: 0rem;
}

.body-container .dlist .dlist,
.body-container .dlist .olist,
.body-container .dlist .ulist,
Expand Down Expand Up @@ -658,6 +662,10 @@ img.intro-screenshot {
vertical-align: middle;
}

.body-container .highlight pre {
padding: 0.5rem;
}

/* Open Collective logo from https://css.gg/open-collective (license: MIT) */

.gg-open-collective,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
311 changes: 311 additions & 0 deletions content/blog/2025-09-12_preview_of_next_gen_ui/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
---
date: 2025-09-12
title: Preview of LibrePCB 2.0's Next-Gen UI
author: U. Bruhin
preview: new-window.png
---

I've made a lot of progress with the completely new user interface for
LibrePCB 2.0 and am very excited to share some insights how it will look,
and how it makes LibrePCB better in many ways.

The Original Problem
--------------------

First, let's quickly look back how everything began. Since the early days of
LibrePCB around 2013, we are using Qt as the UI toolkit and the concept was
to implement every editor as a separate window (schematic editor, board editor,
library editor etc.):

[.imageblock]
{{< imglink "old windows" "old-windows.png" >}}

But with more features added over time, the UI got more and more cluttered.
Also the paradigm of separate windows is often cumbersome to work with -- e.g.
having just one library and one project opened required to constantly switch
between four(!) windows. Even a dual-monitor setup was not enough to work
efficiently with LibrePCB. So it was clear we need a completely new
organization of windows and editors. Generally we could have done that with Qt,
but its traditional approach makes is really hard to pursue more modern
UI paradigms, not to mention the effort and the error-proneness it involves.
In the past I have struggled many times with Qt to create nice UI elements,
thus I didn't feel confident to build up a completely new UI with Qt again.

Slint: A Declarative UI Language
--------------------------------

In the blog post
link:{{< relref "blog/2024-10-17_roadmap_2.0/index.adoc" >}}[NGI0 Grant for LibrePCB 2.0]
I listed a few possible solutions how to build a more modern user interface. The
most promising option was https://slint.dev/[Slint], a relatively new UI
toolkit (open-source & written in Rust) which uses a custom, declarative
language to describe the UI. With the declarative approach, relations and
behavior can be easily specified right in the UI description:

{{< highlight qml >}}
Window {
Button {
x: parent.width - self.width - 5px; // place 5px from the right border
y: 5px; // place 5px from the top border
text: @tr("Open Project");
}
}
{{< /highlight >}}

It may sound trivial to place a button at the top right corner of its parent,
but with the procedural approach of Qt this is often not trivially doable. In
many cases, it requires to implement event handlers in C++ which update the
widgets position whenever the parent object's size or the widgets's own size
has changed. Writing such code is time-consuming and error-prone, while the
declarative approach of Slint is quick, easy and safe -- not just for
this trivial example, but also in more complex cases. For a large project like
LibrePCB, which consists of hundrets of UI elements, the declarative approach
is really a game-changer for us developers! _(Side note: As of today, LibrePCB
contains 23.746 lines of Slint code!)_

An Incremental Migration
------------------------

Unfortunately, even with several months of full-time work, LibrePCB is too
large to be migrated to Slint by 100% at once -- to avoid delaying the next
release too much, we need to do the migration in steps. All the main windows &
editors first, and the remaining dialogs and wizards in later releases. Also
our whole business logic depends on Qt (it is much more than just a UI
framework), thus our dependency on Qt will remain for a long time.

So the question is, can we mix Qt with Slint? In the end, LibrePCB only works
if the main thread is running Qt's event loop. But Slint only works when the
main thread is running _their_ event loop. So at first glance it seems we
have a very bad conflict here :-/

In fact, Slint supports
https://docs.slint.dev/latest/docs/slint/guide/backends-and-renderers/backends_and_renderers/[different backends]
for interaction with the underlying system, e.g. for input events handling
and window drawing. These are (interestingly) Qt,
https://docs.rs/winit/latest/winit/[winit] and LinuxKMS. Winit comes with the
ability of GPU-accelerated rendering, which would be interesting for
performance reasons. But unfortunately right now we can't use winit because
of the event loop conflict.

Luckily Slint's Qt backend avoids that problem since Slint will run Qt's
event loop for us. So the event loop will process the events for both, the
Slint UI and the LibrePCB backend. This works because Slint and LibrePCB
are compiled and linked against the same Qt library. It also allows us to
mix the new Slint window with legacy Qt dialogs & wizards, so we can do
a step-by-step migration.

One Window For Everything
-------------------------

Enough background information for now, let's have a look at the new UI of
LibrePCB 2.0. The most important thing is that all the individual windows
mentioned above have been replaced by a single, multifunctional window.
Within that window, any kind of "document" (e.g. a footprint, a schematic or
a board) is opened as a tab. The toolbars of the new window now depend on
which tab is currently active, because for example the footprint editor
supports other features than the schematic editor. This is how the new window
currently looks like:

[.imageblock.rounded-window.window-border]
{{< imglink "new window" "new-window.png" >}}

By the way, in this new window you can even have multiple projects (and
libraries) opened at the same time! All the opened projects and libraries are
listed in the documents panel, and the contained entities can be opened as
individual tabs.

Sidebar & Panel
~~~~~~~~~~~~~~~

A lot of functionality is accessible through the new sidebar. Depending on
context, there are different kinds of panels available. For example if you're
working on a schematic, there is a panel which displays ERC messages. But if
you're working on a board, that panel will display DRC messages.

[.imageblock]
{{< imglink "side panels" "side-panels.png" >}}

The sidebar also shows you status information about various parts of the
application. For example you see if there are ERC warnings or outdated
workspace libraries without even opening the corresponding panel:

[.imageblock]
{{< imglink "side buttons" "side-buttons.png" >}}

Working Area
~~~~~~~~~~~~

The most important part of our UI is of course the working area where you
draw schematics or layout traces etc. This area has been improved in many ways.
Not only that _everything_ is now a tab (remember that schematics were not
tabs in the old UI), you can now even split the window into multiple sections
and open tabs side-by-side. For example if you're working on a single-monitor
setup, it is now easy to work on the board while still having the schematics
in sight:

[.imageblock.rounded-window.window-border]
{{< imglink "split section" "split-section.png" >}}

Tabs and sections can be easily arranged by drag&drop -- *see it in action
in link:/blog/2025-09-12_preview_of_next_gen_ui/drag-n-drop.gif[this video]*.

In addition, the working area has been maximized and decluttered to have as
much of the screen size available for the graphics view as possible. For
example, tool buttons are now overlays inside the editors rather than
traditional toolbars spanning the whole window height or width even if
only a third of them is filled with buttons. There is no such wasted space
anymore in the new UI.

Statusbar & Notifications
~~~~~~~~~~~~~~~~~~~~~~~~~

We already had a status bar in the old UI, but it was purely visual and not
interactive. Instead of just _displaying_ the grid interval, the new UI
allows you to _modify_ the grid interval and the grid style right in the status
bar -- no dedicated dialog window is required anymore. Also the state of
placement locks is displayed and can be toggled right in the status bar.
Last but not least, there is a completely new notification system which
displays messages and ongoing operations in an expandable/collapsible popup
in the bottom right corner:

[.imageblock]
{{< imglink "statusbar" "statusbar.png" >}}

Multi-Monitor Ready
~~~~~~~~~~~~~~~~~~~

If you are working on a multi-monitor setup and now worry that a single window
is worse than the multiple windows we had before -- of course this use-case
is covered as well. Although the new window replaces all the old windows,
I have implemented the ability to open _multiple instances_ of that window
at the same time. So you decide whether to display schematic and board
side-by-side by splitting a single window, or by opening schematic and
board in entirely separate windows -- everything is possible with the new
concept!

Simplified Library Management
-----------------------------

The old library manager was not that bad, but it was more complicated than
necessary due to its "operation-based" workflow of manually triggering the
installation or uninstallation of libraries, with those operations even
spread across multiple list views and pages.

The new library manager is much simpler (but as functional as before)
by following a "state-based" paradigm now. Instead of triggering the
installation or uninstallation of individual libraries, you now just check
the libraries you like to use (or uncheck those you don't want anymore) and
a single _apply_ operation performs all the necessary installations or
removals at once. Beside the improved user experience, this also fixes some
issues of the old concept (e.g. limitations of the automatic dependency
management).

[.imageblock.rounded-window.window-border]
{{< imglink "library manager" "library-manager.gif" >}}

Configurable 3D View
--------------------

The old 3D view was just a pure read-only display with no configuration
options at all. But for a detailed review of the design, sometimes it is
necessary to hide specific things -- e.g. the devices or the solder paste.
This is now possible by changing the transparency of those objects:

[.imageblock.rounded-window.window-border]
{{< imglink "3d view" "3d-view.gif" >}}


Built-In Hints, Tips & Guides
-----------------------------

In my vision, an EDA tool should support engineers/makers as well as
possible (in a non-disruptive way) to help them creating PCB designs without
errors as quick as possible. The new UI has therefore various new tips & hints
implemented which show up in certain situations. Many of them are especially
useful for LibrePCB beginners to ensure a smooth first-use experience, but
some are useful for everyone to minimize errors or wasted time.

As an example, the built-in PCB ordering feature now displays the state of
the electrical- & design-rule checks as a friendly reminder to review & fix
any issues before ordering a (possibly faulty) PCB. The order panel contains
direct hyperlinks to the ERC & DRC panels, and even allows to run the DRC
right from the order panel. And as an additional psychological effect, the
order button is only highlighted if there are no issues, though it is always
clickable. 🤓

[.imageblock.rounded-window.window-border]
{{< imglink "order pcb" "order-pcb.gif" >}}

What's Next?
------------

Even though the new UI is the biggest change in the history of LibrePCB,
this is just the beginning of a new user experience. There is still a lot
of room for improvements which we will take care of after the LibrePCB 2.0
release. Just a few examples:

* Object property editors (incl. multi-object editing) in side panel to get
rid of modal dialogs
* Replace remaining modal dialogs & wizards by integrating them as tabs
or lightweight popups
* Reflect typical workflows by the UI, for higher productivity and intuitivity
* Productivity improvements, e.g. drag&drop, more keyboard shortcuts,
hints, links to docs, ...
* Theme improvements / cleanup / polishing, maybe some day support
customizable themes

All the completed tasks and the planned tasks, together with more details
and previews of the new UI, are summarized in
https://github.com/LibrePCB/LibrePCB/issues/1494[this issue]. Of course there
are also a lot of new non-UI features beeing developed for LibrePCB 2.0 and
beyond, those are tracked in separate issues. This blog post just focused on
the UI things due to its huge relevance in this moment.

Give it a Try!
~~~~~~~~~~~~~~

If you like to try out the new UI already, we have nightly builds available
*https://download.librepcb.org/nightly_builds/new-ui-with-file-format-1_0/[here]*.
In contrast to the current `master` branch, these builds still use the stable
file format 1.0 so no changes will be made to your library- and project files.
But of course there might still be some bugs -- if you experience any issues
or annoyances, or have any other feedback, please
link:{{< relref "help/help/index.adoc" >}}[let us know]!

++++
<div class="text-center my-3">
<a class="btn btn-primary mx-1 my-1" role="button" href="https://download.librepcb.org/nightly_builds/new-ui-with-file-format-1_0" >
<i class="fa-solid fa-download"></i>
Get Nightly Builds
</a>
<a class="btn btn-warning mx-1 my-1" role="button" href="{{< relref "help/help/index.adoc" >}}" >
<i class="fa-solid fa-message"></i>
Give Feedback
</a>
<a class="btn btn-danger mx-1 my-1" role="button" href="{{< relref "donate/index.adoc" >}}" >
<i class="fa-solid fa-heart"></i>
Support My Work
</a>
</div>
++++

Btw, if you are curious about the timeline of the LibrePCB 2.0 release:
There are still some new features to be implemented (mostly non-UI things now)
and it is hard to say when they are finished. But roughly I'd estimate it
should be ready in around 2-3 months. If you like to support my work on
the LibrePCB project, any link:{{< relref "donate/index.adoc" >}}[donations]
are highly appreciated and help me to keep the development ongoing. icon:heart[]

---

Credits
-------

[.right.ms-3]
{{< imglink "NGI0" "nlnet-ngi0.png" "https://nlnet.nl/project/LibrePCB2.0/" 130 >}}

A majority of these updates were part of the
link:{{< relref "blog/2024-10-17_roadmap_2.0/index.adoc" >}}[NGI0 Commons grant]
we receive from link:https://nlnet.nl[NLnet], thanks a lot for their support!
Also a special thanks to the Slint developers who helped me with support,
feature development and bugfixes during this migration.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.