Solid Hardware Without Device File Archaeology
I left an import dialog open, pulled the card reader, and clicked Import. The dialog still had a pointer to a Solid::StorageAccess interface from the device it had displayed. The hardware was gone; my object graph had not heard the news.
Hotplug makes lifetime the main problem, not discovery. A device can disappear between filling a menu and handling its action. A mount can vanish while a job is queued. Keeping /dev/sdb1 does not fix that, and keeping a frontend interface pointer around is worse because it looks usable right up to the point that it is not.
The dialog now stores the device’s unique device identifier, not a borrowed interface object. When the user starts an import, it asks Solid for the device again, checks that it is still valid, obtains the storage interface for that operation, and then checks the current accessibility state. No lookup, no import.
I also listen for deviceRemoved(QString). If the identifier matches the open dialog, the UI disables Import and says the device was removed. Any queued work receives the same cancellation instead of continuing with a path that happened to exist a moment ago.
There is a small race even with the fresh lookup: unplugging is allowed to win after the check. The operation still needs to handle mount or I/O failure. The lookup keeps stale application objects out of the way; it cannot promise that a human will leave the cable alone.
deviceAdded gets less special treatment now. It gives me an identifier to inspect, and I query capabilities when I need them. The removal signal is the one that tears down assumptions.
This fixed a second oddity too: unplugging and reinserting the same reader could produce a new frontend object while the dialog held the old one. Keying the UI by identifier and reacquiring the device made that boring, which is exactly what hotplug code should be.