Re-record the manual for 0.17.0, with albums and the new preset sheet

Every scene is recorded again on the 0.17.0 build, because the header
(Export to Exports), the sidebar (Albums) and the develop column had
all moved. The launch pictures showed the typed folder field, and the
export settings "Export to"; the presets picture predated the sections.

New scenes: presets_film scrolls the sheet down through the shipped
sections and applies Ilford HP5 Plus, a look that changes the film and
nothing else; albums exports four New York frames to an album, selects
it to show the originals behind its files, and opens a new album's
sheet before deleting what it made. record.sh now points the profile's
old export folder at DR_HOME/Exports, which the app turns into the
album "Exports" on first open - the one way to have an album without
the portal's dialogue, which Xvfb cannot show. The launch scene signs
out of a remembered folder instead of typing one, so it shows
"Open folder" beside the folder used last.

Not recorded: the server browser's New folder, which needs a Nextcloud
server, and the download screen, which a folder library never reaches
(the original is a local read, over before the first poll). The manual
says so where it describes each. film_reach and duplicates passed;
inference was pinned to the CPU.
This commit is contained in:
2026-09-26 15:15:51 -04:00
parent 9f95d23ff4
commit 7428f6f845
40 changed files with 300 additions and 101 deletions
+37 -11
View File
@@ -17,16 +17,19 @@ DarkRoom opens on a library: a folder on this machine, a folder a sync
client keeps, or a Nextcloud account. A folder needs no password and uploads client keeps, or a Nextcloud account. A folder needs no password and uploads
nothing. `Choose folder…` opens your desktop's own folder dialogue, which can nothing. `Choose folder…` opens your desktop's own folder dialogue, which can
make a new folder too; the folder used last stays on the screen with make a new folder too; the folder used last stays on the screen with
`Open folder` beside it. On a Nextcloud account the library folder is chosen `Open folder` beside it, and `Choose another…` in place of `Choose folder…`.
in a browser of the server, whose `New folder` makes one there. On a Nextcloud account the library folder is chosen in a browser of the
server, whose `New folder` makes one there. (The browser is not pictured:
these recordings have no server behind them. Nor is the folder dialogue,
which is your desktop's rather than DarkRoom's.)
![The launch screen: a server field, a folder field, and which formats to scan for](media/launch.png) ![The launch screen: a Nextcloud server or an app password, or the folder used last with Open folder beside it](media/launch.png)
Once a folder is named, it is the library — you are not asked for it again, Once a folder is named, it is the library — you are not asked for it again,
and `Open library` opens it whole. `Subfolder…` narrows the scan to part of and `Open library` opens it whole. `Subfolder…` narrows the scan to part of
it. The formats ticked are what the scan looks for; RAW is on and JPEG off it. The formats ticked are what the scan looks for; RAW is on and JPEG off
by default, because a RAW editor's sensible default is the file the camera by default, because a RAW editor's sensible default is the file the camera
wrote first. wrote first. `Change library`, at the foot of the sidebar, comes back here.
![A folder chosen: the library, whether to scan a subfolder, and the formats](media/launch-folder.png) ![A folder chosen: the library, whether to scan a subfolder, and the formats](media/launch-folder.png)
@@ -188,6 +191,15 @@ and the left arrow or `A` the one before; held down, they go on past the
stretch the roll has loaded, through everything the grid would show. The stretch the roll has loaded, through everything the grid would show. The
edit on screen is saved on the way, so stepping along a shoot loses nothing. edit on screen is saved on the way, so stepping along a shoot loses nothing.
On a Nextcloud library a photograph may not be on this device yet. Its
thumbnail from the grid stands in at once; if the original has to come down,
the thumbnail dims under *Not on this device yet*, with how far the download
has got — `Downloading — 12.4 of 38.0 MB` — and a bar, and the photograph
opens when it lands. Step on before then and the one you step to is the one
that opens: a download that arrives late is kept for later and never takes
the place of the photograph whose name is showing. (Not pictured: a folder
library, which these recordings use, never has a photograph to wait for.)
### White balance from the photograph ### White balance from the photograph
Press `pick` in the White Balance group, then click something neutral — Press `pick` in the White Balance group, then click something neutral —
@@ -262,7 +274,8 @@ black-and-white stocks at its end.
Every change is a step; `Undo` and the History panel walk them. `Snapshot` Every change is a step; `Undo` and the History panel walk them. `Snapshot`
keeps the current state under a name. `Presets…` saves the settings to keeps the current state under a name. `Presets…` saves the settings to
apply elsewhere, and imports `.xmp` from other applications. apply elsewhere, and imports Lightroom presets — `Folder…` for a folder of
them, `.xmp file…` for one.
The sheet lists your own presets first, then the ones DarkRoom ships — The sheet lists your own presets first, then the ones DarkRoom ships —
Essentials, and colour, cinema and black-and-white film, one measured stock Essentials, and colour, cinema and black-and-white film, one measured stock
@@ -270,9 +283,12 @@ each. A shipped preset is a look: it changes what it names and leaves the
photograph's own corrections alone, as an imported Lightroom preset does. photograph's own corrections alone, as an imported Lightroom preset does.
Saving under a shipped preset's name makes your version the one that name Saving under a shipped preset's name makes your version the one that name
applies, marked *changed*; `Revert` brings the shipped one back, and renaming applies, marked *changed*; `Revert` brings the shipped one back, and renaming
yours makes it one of your own. yours makes it one of your own. A film preset carries its stock: choosing one
sets the `Film` chooser and leaves the rest of the edit where it was.
![The presets sheet](media/presets.png) ![The presets sheet: a name for the current edit, the shipped Essentials, importing, and what an apply carries](media/presets.png)
![Scrolling down the shipped presets to the black-and-white films, applying Ilford HP5 Plus, then holding Before](media/presets-film.gif)
### Copying settings ### Copying settings
@@ -314,16 +330,26 @@ in a browser that can make a folder as well as open one. Not inside the
library — a JPEG exported there would come back from the next scan as a library — a JPEG exported there would come back from the next scan as a
photograph of its own, and the browser says so rather than letting you. photograph of its own, and the browser says so rather than letting you.
![A new album named, before its folder is chosen](media/album-sheet.png)
The folder holds only the exported files. The album remembers which The folder holds only the exported files. The album remembers which
photograph each came from, so selecting it in the sidebar shows the photograph each came from, so selecting it in the sidebar shows the
originals behind its JPEGs — edit one and export it again. Albums reach your originals behind its JPEGs — edit one and export it again. Albums reach your
other devices as collections do; a folder on this device does not, so an other devices as collections do; a folder on this device does not, so an
album made on the desktop asks the tablet for a folder of its own. Deleting album made on the desktop asks the tablet for a folder of its own.
an album leaves its files where they are. Right-click an album, double-click it or press the arrow on its row to
rename it, give it another folder or delete it; deleting an album leaves
its files where they are.
An export with no album chosen is refused, and the header says so. ![Four New York frames exported to an album, then the album chosen in the sidebar](media/albums.gif)
![Export defaults in Settings](media/settings-export.png) ![The album chosen: the four photographs behind its files](media/albums.png)
An export with no album chosen is refused, and the header says so. With one
chosen, the buttons name it: `Export to Exports` in develop, `Export 4 to
Exports` on the selection bar.
![Export defaults in Settings, ending with the album exports go to](media/settings-export.png)
## Settings ## Settings
+31 -11
View File
@@ -150,14 +150,17 @@ is only about what you see.</p>
client keeps, or a Nextcloud account. A folder needs no password and uploads client keeps, or a Nextcloud account. A folder needs no password and uploads
nothing. <code>Choose folder…</code> opens your desktop's own folder dialogue, which can nothing. <code>Choose folder…</code> opens your desktop's own folder dialogue, which can
make a new folder too; the folder used last stays on the screen with make a new folder too; the folder used last stays on the screen with
<code>Open folder</code> beside it. On a Nextcloud account the library folder is chosen <code>Open folder</code> beside it, and <code>Choose another…</code> in place of <code>Choose folder…</code>.
in a browser of the server, whose <code>New folder</code> makes one there.</p> On a Nextcloud account the library folder is chosen in a browser of the
<figure><img loading="lazy" src="media/launch.png" alt="The launch screen: a server field, a folder field, and which formats to scan for"><figcaption>The launch screen: a server field, a folder field, and which formats to scan for</figcaption></figure> server, whose <code>New folder</code> makes one there. (The browser is not pictured:
these recordings have no server behind them. Nor is the folder dialogue,
which is your desktop's rather than DarkRoom's.)</p>
<figure><img loading="lazy" src="media/launch.png" alt="The launch screen: a Nextcloud server or an app password, or the folder used last with Open folder beside it"><figcaption>The launch screen: a Nextcloud server or an app password, or the folder used last with Open folder beside it</figcaption></figure>
<p>Once a folder is named, it is the library — you are not asked for it again, <p>Once a folder is named, it is the library — you are not asked for it again,
and <code>Open library</code> opens it whole. <code>Subfolder…</code> narrows the scan to part of and <code>Open library</code> opens it whole. <code>Subfolder…</code> narrows the scan to part of
it. The formats ticked are what the scan looks for; RAW is on and JPEG off it. The formats ticked are what the scan looks for; RAW is on and JPEG off
by default, because a RAW editor's sensible default is the file the camera by default, because a RAW editor's sensible default is the file the camera
wrote first.</p> wrote first. <code>Change library</code>, at the foot of the sidebar, comes back here.</p>
<figure><img loading="lazy" src="media/launch-folder.png" alt="A folder chosen: the library, whether to scan a subfolder, and the formats"><figcaption>A folder chosen: the library, whether to scan a subfolder, and the formats</figcaption></figure> <figure><img loading="lazy" src="media/launch-folder.png" alt="A folder chosen: the library, whether to scan a subfolder, and the formats"><figcaption>A folder chosen: the library, whether to scan a subfolder, and the formats</figcaption></figure>
<h2 id="the-library">The library</h2> <h2 id="the-library">The library</h2>
<figure><img loading="lazy" src="media/library.png" alt="The grid: collections on the left, the timeline beside it, the roll of thumbnails, and the filter bar above"><figcaption>The grid: collections on the left, the timeline beside it, the roll of thumbnails, and the filter bar above</figcaption></figure> <figure><img loading="lazy" src="media/library.png" alt="The grid: collections on the left, the timeline beside it, the roll of thumbnails, and the filter bar above"><figcaption>The grid: collections on the left, the timeline beside it, the roll of thumbnails, and the filter bar above</figcaption></figure>
@@ -271,6 +274,14 @@ showing; click one to open it. The right arrow, <code>D</code> or space opens th
and the left arrow or <code>A</code> the one before; held down, they go on past the and the left arrow or <code>A</code> the one before; held down, they go on past the
stretch the roll has loaded, through everything the grid would show. The stretch the roll has loaded, through everything the grid would show. The
edit on screen is saved on the way, so stepping along a shoot loses nothing.</p> edit on screen is saved on the way, so stepping along a shoot loses nothing.</p>
<p>On a Nextcloud library a photograph may not be on this device yet. Its
thumbnail from the grid stands in at once; if the original has to come down,
the thumbnail dims under <em>Not on this device yet</em>, with how far the download
has got — <code>Downloading — 12.4 of 38.0 MB</code> — and a bar, and the photograph
opens when it lands. Step on before then and the one you step to is the one
that opens: a download that arrives late is kept for later and never takes
the place of the photograph whose name is showing. (Not pictured: a folder
library, which these recordings use, never has a photograph to wait for.)</p>
<h3 id="white-balance-from-the-photograph">White balance from the photograph</h3> <h3 id="white-balance-from-the-photograph">White balance from the photograph</h3>
<p>Press <code>pick</code> in the White Balance group, then click something neutral — <p>Press <code>pick</code> in the White Balance group, then click something neutral —
a white wall, a grey card, the air conditioner here. The picker sets the a white wall, a grey card, the air conditioner here. The picker sets the
@@ -320,15 +331,18 @@ black-and-white stocks at its end.</p>
<h3 id="history-snapshots-presets">History, snapshots, presets</h3> <h3 id="history-snapshots-presets">History, snapshots, presets</h3>
<p>Every change is a step; <code>Undo</code> and the History panel walk them. <code>Snapshot</code> <p>Every change is a step; <code>Undo</code> and the History panel walk them. <code>Snapshot</code>
keeps the current state under a name. <code>Presets…</code> saves the settings to keeps the current state under a name. <code>Presets…</code> saves the settings to
apply elsewhere, and imports <code>.xmp</code> from other applications.</p> apply elsewhere, and imports Lightroom presets — <code>Folder…</code> for a folder of
them, <code>.xmp file…</code> for one.</p>
<p>The sheet lists your own presets first, then the ones DarkRoom ships — <p>The sheet lists your own presets first, then the ones DarkRoom ships —
Essentials, and colour, cinema and black-and-white film, one measured stock Essentials, and colour, cinema and black-and-white film, one measured stock
each. A shipped preset is a look: it changes what it names and leaves the each. A shipped preset is a look: it changes what it names and leaves the
photograph's own corrections alone, as an imported Lightroom preset does. photograph's own corrections alone, as an imported Lightroom preset does.
Saving under a shipped preset's name makes your version the one that name Saving under a shipped preset's name makes your version the one that name
applies, marked <em>changed</em>; <code>Revert</code> brings the shipped one back, and renaming applies, marked <em>changed</em>; <code>Revert</code> brings the shipped one back, and renaming
yours makes it one of your own.</p> yours makes it one of your own. A film preset carries its stock: choosing one
<figure><img loading="lazy" src="media/presets.png" alt="The presets sheet"><figcaption>The presets sheet</figcaption></figure> sets the <code>Film</code> chooser and leaves the rest of the edit where it was.</p>
<figure><img loading="lazy" src="media/presets.png" alt="The presets sheet: a name for the current edit, the shipped Essentials, importing, and what an apply carries"><figcaption>The presets sheet: a name for the current edit, the shipped Essentials, importing, and what an apply carries</figcaption></figure>
<figure><img loading="lazy" src="media/presets-film.gif" alt="Scrolling down the shipped presets to the black-and-white films, applying Ilford HP5 Plus, then holding Before"><figcaption>Scrolling down the shipped presets to the black-and-white films, applying Ilford HP5 Plus, then holding Before</figcaption></figure>
<h3 id="copying-settings">Copying settings</h3> <h3 id="copying-settings">Copying settings</h3>
<p><code>Copy</code> in the top bar, or Ctrl+C, takes this photograph's settings; <code>Paste</code>, <p><code>Copy</code> in the top bar, or Ctrl+C, takes this photograph's settings; <code>Paste</code>,
or Ctrl+V, puts them on another, and says what it would paste — how many or Ctrl+V, puts them on another, and says what it would paste — how many
@@ -359,14 +373,20 @@ folder dialogue (on the tablet, Android's folder picker), or on the server,
in a browser that can make a folder as well as open one. Not inside the in a browser that can make a folder as well as open one. Not inside the
library — a JPEG exported there would come back from the next scan as a library — a JPEG exported there would come back from the next scan as a
photograph of its own, and the browser says so rather than letting you.</p> photograph of its own, and the browser says so rather than letting you.</p>
<figure><img loading="lazy" src="media/album-sheet.png" alt="A new album named, before its folder is chosen"><figcaption>A new album named, before its folder is chosen</figcaption></figure>
<p>The folder holds only the exported files. The album remembers which <p>The folder holds only the exported files. The album remembers which
photograph each came from, so selecting it in the sidebar shows the photograph each came from, so selecting it in the sidebar shows the
originals behind its JPEGs — edit one and export it again. Albums reach your originals behind its JPEGs — edit one and export it again. Albums reach your
other devices as collections do; a folder on this device does not, so an other devices as collections do; a folder on this device does not, so an
album made on the desktop asks the tablet for a folder of its own. Deleting album made on the desktop asks the tablet for a folder of its own.
an album leaves its files where they are.</p> Right-click an album, double-click it or press the arrow on its row to
<p>An export with no album chosen is refused, and the header says so.</p> rename it, give it another folder or delete it; deleting an album leaves
<figure><img loading="lazy" src="media/settings-export.png" alt="Export defaults in Settings"><figcaption>Export defaults in Settings</figcaption></figure> its files where they are.</p>
<figure><img loading="lazy" src="media/albums.gif" alt="Four New York frames exported to an album, then the album chosen in the sidebar"><figcaption>Four New York frames exported to an album, then the album chosen in the sidebar</figcaption></figure>
<figure><img loading="lazy" src="media/albums.png" alt="The album chosen: the four photographs behind its files"><figcaption>The album chosen: the four photographs behind its files</figcaption></figure>
<p>An export with no album chosen is refused, and the header says so. With one
chosen, the buttons name it: <code>Export to Exports</code> in develop, <code>Export 4 to Exports</code> on the selection bar.</p>
<figure><img loading="lazy" src="media/settings-export.png" alt="Export defaults in Settings, ending with the album exports go to"><figcaption>Export defaults in Settings, ending with the album exports go to</figcaption></figure>
<h2 id="settings">Settings</h2> <h2 id="settings">Settings</h2>
<figure><img loading="lazy" src="media/settings.png" alt="The settings page: background activity, indexing, storage, display"><figcaption>The settings page: background activity, indexing, storage, display</figcaption></figure> <figure><img loading="lazy" src="media/settings.png" alt="The settings page: background activity, indexing, storage, display"><figcaption>The settings page: background activity, indexing, storage, display</figcaption></figure>
<p>Background activity with progress, thumbnail and face indexing, how many <p>Background activity with progress, thumbnail and face indexing, how many
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8 -2
View File
@@ -20,7 +20,7 @@
# the merged DNG), so DR_LIBRARY_SNAPSHOT, if set, is copied over it first. # the merged DNG), so DR_LIBRARY_SNAPSHOT, if set, is copied over it first.
# #
# Environment: DR_HOME (/var/tmp/dr-manual), DR_DISPLAY (:7), DR_BIN, # Environment: DR_HOME (/var/tmp/dr-manual), DR_DISPLAY (:7), DR_BIN,
# DR_LIBRARY_SNAPSHOT, DR_EXPORT_DIR (LIBRARY/../export), DR_INFERENCE # DR_LIBRARY_SNAPSHOT, DR_EXPORT_DIR (DR_HOME/Exports), DR_INFERENCE
# (`cpu`, the default, pins inference to the CPU so a recording does not # (`cpu`, the default, pins inference to the CPU so a recording does not
# fight a training run for the GPU; `probe` lets the app choose), CARGO # fight a training run for the GPU; `probe` lets the app choose), CARGO
# (cargo; a wrapper taking cargo's arguments works too). # (cargo; a wrapper taking cargo's arguments works too).
@@ -109,7 +109,13 @@ cat > "$profile/config/darkroom/sessions.json" <<JSON
"login": "", "user_id": "", "root": "", "root_chosen": true, "login": "", "user_id": "", "root": "", "root_chosen": true,
"formats": [], "last_scan": null } ] } "formats": [], "last_scan": null } ] }
JSON JSON
export_dir="${DR_EXPORT_DIR:-$(dirname "$library")/export}" # An export folder set before albums becomes the album "Exports" on first
# open (albums_ui::adopt_old_destination), which is how the albums scene has
# an album without the portal's dialogue. In the throwaway profile's folder,
# outside the library, and the scene deletes what it exported.
export DR_EXPORT_DIR="${DR_EXPORT_DIR:-$DR_HOME/Exports}"
export_dir="$DR_EXPORT_DIR"
mkdir -p "$export_dir"
cat > "$profile/config/darkroom/settings.json" <<JSON cat > "$profile/config/darkroom/settings.json" <<JSON
{ "export": { "destination": "$export_dir" } } { "export": { "destination": "$export_dir" } }
JSON JSON
+148 -13
View File
@@ -390,24 +390,40 @@ def reset_adjust():
sources=COMMON + ['ui/dr-ui/ui/launch.slint', 'ui/dr-ui/src/launch_ui.rs', sources=COMMON + ['ui/dr-ui/ui/launch.slint', 'ui/dr-ui/src/launch_ui.rs',
'ui/dr-ui/src/launch.rs']) 'ui/dr-ui/src/launch.rs'])
def launch(): def launch():
"""The launch screen belongs to a profile with no library, so this one """The launch screen belongs to a profile that has not opened a library,
is its own: the app is restarted on an empty profile beside the real so this one is its own: the app is restarted on a profile beside the
one, shown the demo folder, and put back.""" real one that knows the demo folder, taken back to the launch screen by
empty = f'{dr.HOME}/launch-xdg' `Change library`, and signed out of the folder — which leaves it on the
subprocess.run(['rm', '-rf', empty], check=True) screen with `Open folder` beside it, as someone returning sees it. The
os.makedirs(f'{empty}/config/darkroom', exist_ok=True) folder is never chosen with `Choose another…`: that is the desktop
portal's dialogue, not the app's to draw, and it does not open on a
private X server."""
other = f'{dr.HOME}/launch-xdg'
subprocess.run(['rm', '-rf', other], check=True)
os.makedirs(f'{other}/config/darkroom', exist_ok=True)
with open(f'{other}/config/darkroom/sessions.json', 'w') as f:
# The formats a first open saves — the RAWs, not JPEG — rather than
# none, which would scan (and tick) everything.
f.write('{ "version": 0, "sessions": [ { "backend": "folder", "server": "%s",'
' "login": "", "user_id": "", "root": "", "root_chosen": true,'
' "formats": ["cr2", "cr3", "nef", "arw", "raf", "rw2", "orf", "dng"],'
' "last_scan": null } ] }'
% (DEMO_LIBRARY or '/var/tmp/dr-demo/library'))
dr.stop() dr.stop()
dr.launch([], xdg=empty) dr.launch([], xdg=other)
dr.wait_ready() dr.wait_ready()
dr.wait_for('Open folder@Button', 30) dr.wait_for('id:grid-scroll', 60)
pause(1) pause(3)
shot('launch') dr.click_on('Change library@Button')
dr.click_on('Library folder@TextInput')
type_text(DEMO_LIBRARY or '/var/tmp/dr-demo/library')
dr.click_on('Open folder@Button')
dr.wait_for('Open library@Button', 30) dr.wait_for('Open library@Button', 30)
dr.move(10, 10)
pause(1) pause(1)
shot('launch-folder') shot('launch-folder')
dr.click_on('Sign out@Button')
dr.wait_for('Open folder@Button', 30)
dr.move(10, 10)
pause(1)
shot('launch')
dr.stop() dr.stop()
dr.launch([]) dr.launch([])
dr.wait_ready() dr.wait_ready()
@@ -1084,6 +1100,39 @@ def presets():
pause(1.0) pause(1.0)
@scene(media=['presets-film.gif'],
sources=DEVELOP_SRC + ['ui/dr-ui/ui/presets.slint', 'ui/dr-ui/src/presets.rs',
'core/dr-pipeline/presets/*.drpl', 'core/dr-pipeline/src/bundled.rs'])
def presets_film():
"""The sheet scrolled from Essentials down through the shipped film
sections, and a black-and-white stock applied from the last of them —
a look, so the sheet closes on the photograph with its film changed and
nothing else — then Before held."""
at_develop()
rec('presets-film')
pause(0.4)
dr.click_on('Presets…@Button')
dr.wait_for('CARRIES@Text', 5)
pause(1.5)
x, y = dr.centre('Crisp detail@Button')
for _ in range(80): # a notch at a time, so the film shows the sections pass
if dr.present(f'{PRESET_BW}@Button'):
break
wheel(1, x, y)
pause(0.3)
pause(1.0)
dr.click_on(f'{PRESET_BW}@Button')
dr.wait_gone('CARRIES@Text', 5)
pause(4)
hold_before(1.4)
pause(0.8)
cut()
undo_all()
PRESET_BW = 'Ilford HP5 Plus' # a shipped look in the black-and-white film section
# --- panorama --------------------------------------------------------------- # --- panorama ---------------------------------------------------------------
def wait_for_new(folder, suffix, since, timeout): def wait_for_new(folder, suffix, since, timeout):
"""Until a file ending in `suffix` newer than `since` appears in """Until a file ending in `suffix` newer than `since` appears in
@@ -1183,6 +1232,92 @@ def settings():
pause(1.5) pause(1.5)
# --- albums -----------------------------------------------------------------
ALBUM = 'Exports' # made by the app from the export folder record.sh sets
def album_row(name):
"""The sidebar row for album `name`: its label is the name and where its
files go, "Exports, On this device · …"."""
for e in dr.ask(f'labels {name}, '):
if e['role'] == 'Button' and e['label'].startswith(f'{name}, '):
return int(e['x'] + e['w'] / 2), int(e['y'] + e['h'] / 2)
raise dr.NotFound(f'no album row for {name}')
def export_button():
"""The selection bar's export button, whose label names the count and
the album: "Export 5 to Exports"."""
for e in dr.ask('labels Export '):
if e['role'] == 'Button' and e['label'].startswith('Export ') and ' to ' in e['label']:
return int(e['x'] + e['w'] / 2), int(e['y'] + e['h'] / 2)
raise dr.NotFound('no export button naming an album')
@scene(media=['albums.gif', 'albums.png', 'album-sheet.png'],
sources=LIBRARY_SRC + ['ui/dr-ui/ui/albums.slint', 'ui/dr-ui/src/albums_ui.rs',
'ui/dr-ui/ui/export.slint', 'ui/dr-ui/src/export.rs'])
def albums():
"""The New York frames exported to the album the profile's old export
folder became, then the album chosen in the sidebar: the grid shows the
originals behind its files. Then the sheet `+` opens, with a name typed
and no folder yet — its `Choose folder…` is the desktop portal's
dialogue, which does not open on a private X server. The files exported
are deleted again, and the album with them."""
folder = os.environ.get('DR_EXPORT_DIR', '')
before = set(os.listdir(folder)) if os.path.isdir(folder) else set()
try:
at_library()
grid_top()
album_row(ALBUM)
rec('albums-a')
pause(0.5)
start_selecting()
dr.click(*cell(NY_FIRST))
pause(0.3)
with_key('shift', dr.click, *cell(NY_LAST))
pause(1.0)
dr.click(*export_button())
pause(3)
cut()
try: # a short batch can be over before this looks
dr.wait_for('Cancel export@Button', 5)
except Exception:
pass
dr.wait_gone('Cancel export@Button', 300)
pause(1)
stop_selecting()
rec('albums-b')
pause(0.5)
dr.click(*album_row(ALBUM))
pause(2.5)
cut()
join('albums', ['albums-a', 'albums-b'])
dr.move(*album_row(ALBUM))
pause(1)
shot('albums')
dr.click_on('New album@Button')
dr.wait_for('Make album@Button', 5)
pause(0.6)
type_text('Prints')
pause(1)
shot('album-sheet')
dr.click_on('Cancel@Button#-1')
pause(0.8)
dr.click_on(f'Edit {ALBUM}@Button')
dr.wait_for('Delete…@Button', 5)
dr.click_on('Delete…@Button')
dr.wait_for('Delete album@Button', 5)
dr.click_on('Delete album@Button')
pause(1)
dr.click_on('All photographs@Text')
pause(1.2)
finally:
if folder and os.path.isdir(folder):
for f in set(os.listdir(folder)) - before:
os.remove(os.path.join(folder, f))
# --- duplicate originals --------------------------------------------------- # --- duplicate originals ---------------------------------------------------
DUPLICATED = [NY_FIRST, '_MG_8394'] # copied into a `bck` folder beside their own DUPLICATED = [NY_FIRST, '_MG_8394'] # copied into a `bck` folder beside their own