
Selection, Modelled: Why GTK4 Puts Selection in the Model, Not the View
This is the fifth entry in A Field Guide to GTK Widgets — a series about which widget to reach for, when, and what bites you when you do. The previous post got rows behaving correctly under recycling. This one is about which of them is selected. The complete, runnable code lives in the companion repo. Where we left off Two posts ago I wrapped the list store in a NoSelection and moved on, with a note that GtkListView won’t accept a bare GListModel and that NoSelection is how you say “no selection, and I mean it.” True enough as far as it went, but it was a placeholder. Time to take the wrapper seriously. ...

Your First Factory: GtkListView and the Bind/Unbind Rhythm
This is the fourth entry in A Field Guide to GTK Widgets — a series about which widget to reach for, when, and what bites you when you do. The previous post got a list on screen with a factory it deliberately didn’t explain. This one explains it. The complete, runnable code lives in the companion repo. Where we left off The list-mindset post got a GtkListView on screen with just enough factory code to prove the model-driven approach worked, and it said so directly: setup builds a row’s widgets once, bind fills them in, and GTK recycles rows as you scroll — the same widgets get re-bound to different items instead of new rows being built for each one. That recycling is the entire reason GtkListView scrolls well through ten thousand rows without breaking a sweat, and it’s also the thing that breaks people’s mental model the first time they hit it, because nothing in the API shouts about it. You write bind once, it looks like a constructor, and it isn’t one. ...

Moments: The Photo App I Built to Win an Argument
A phone call with a mate turned into a wager: could AI actually build a real application from scratch? Five months, 898 commits and 40,000 lines of Rust later, here’s the verdict — and the app. It started with a phone call Like most of my questionable decisions, this one started on the phone with a mate, talking about technology the way we always do. The conversation drifted, as every technical conversation eventually does now, into AI. And we ended up circling the same question everyone circles: is this stuff actually capable of building real software, or is it just very confident autocomplete? ...

Building GNOME Apps with Rust, Part 6: Fetching Feeds
This is Part 6 of a series taking a GNOME app from an empty directory to GNOME Circle. Part 5 wired the sidebar to a real Feed GObject and a feed-selected signal — selecting a row updates the content pane and prints a line to the terminal. This is the post where that line stops being a placeholder and becomes a real network fetch. The click that still does nothing real Select This Week in GNOME, then select Hacker News. The placeholder swaps in the new name and URL — everything the app knows about that feed, and none of what’s actually in it. Every Feed in the sidebar has a uri pointing at a real RSS or Atom document on the actual internet, and nothing in the codebase has ever asked one of them what’s there. ...

Stop Thinking in Rows: GListModel and the Modern List Mindset
This is the third entry in A Field Guide to GTK Widgets — a series about which widget to reach for, when, and what bites you when you do. We’re jumping straight to lists, ahead of layout and navigation, because it’s the material the reference documents worst. Each post stands on its own, and the complete, runnable code for this one lives in the companion repo. The list you’d build without thinking Say you’re showing a handful of tasks. The obvious way to do it doesn’t require reading any documentation at all: ...

Two YubiKeys, One Prompt Too Many
I carry two YubiKeys. One lives on my keyring, one lives in a drawer, and both are enrolled everywhere that matters. A hardware token with no backup is a single point of failure you have chosen on purpose. For months I had a small irritation I never bothered to chase. Some days git push asked for my PIN, I typed it, and it worked. Other days it asked for my PIN, failed, and then asked again, and the second one worked. Same command, same repo, same laptop. The variable turned out to be which of the two keys happened to be in the USB port. ...

Excavating Legacy ETL: The AI Never Asserts a Fact It Could Look Up
Every platform modernisation programme has the same first act, and it is never the interesting one. Before anyone gets to write a line of dbt, somebody has to work out what the current thing actually does. In the SAP BusinessObjects Data Services case — BODS, if you’ve had the pleasure — that means inheriting a few hundred dataflows whose authors left the organisation years ago. The logic lives in exported XML. The business rationale lived in the heads of people who are now at other companies. Nobody can tell you which flows are duplicates, which ones nothing reads any more, or what any given one is for. There is a spreadsheet somewhere claiming to be an inventory. It is wrong in ways nobody can enumerate. ...

The Application Shell: GtkApplicationWindow vs AdwApplicationWindow
This is the first proper entry in A Field Guide to GTK Widgets — a series about which widget to reach for, when, and what bites you when you do. We start where every app starts: the window. Each post stands on its own, and the complete, runnable code for this one lives in the companion repo. Two windows, and the one you should reach for You sit down to write a GNOME app. The very first widget you need is the window, and the toolkit immediately hands you a choice it doesn’t explain: GtkApplicationWindow, from GTK itself, or AdwApplicationWindow, from Libadwaita. The reference describes both accurately and tells you nothing about which one you want. ...

A Field Guide to GTK Widgets
This is the opening post of a series that works through GTK4 and Libadwaita together, one practical interface decision at a time. The posts are grouped around the things you actually build — a window, a list, a settings page — rather than the library a widget happens to ship in. Each post stands alone; together they’re meant to be the field guide the reference documentation isn’t. The problem with the reference The GTK4 documentation is genuinely good. Every widget has a page. Every property, signal, and method is listed. The class hierarchies are accurate and the prose is precise. If you already know which widget you need, the reference will tell you everything about it. ...

Building GNOME Apps with Rust, Part 5: State and Signals
This is Part 5 of a series taking a GNOME app from an empty directory to GNOME Circle. Part 4 replaced our XML templates with Blueprint and grew the window into the real Gazette layout — a sidebar, a content pane, and three typed widget handles waiting for behaviour. This is the post where they get some. If the GObject machinery in here feels unfamiliar — mod imp, properties, signals — Part 2 is the reference. This is where those patterns stop being theoretical. ...