Add search, and lay the window out in three resizable columns #10

Merged
GrumpyStraw merged 1 commit from search into main 2026-10-11 14:40:06 +02:00
Owner

Three columns and one top bar

The Kirigami page stack is replaced by a SplitView with three columns:

  • Left: the playlists. Clicking one opens it in the middle. Songs dropped on a playlist are added to it.
  • Middle: All Music, or the playlist in the current tab. All Music is a fixed first tab, and the middle shows it whenever no playlist is open. Its first row has the column's title and, in a playlist, Add songs and Remove songs.
  • Right: Now Playing.

One bar runs across the top (src/qml/TopBar.qml). The playlists button at the left end and the Now Playing button at the right end show or hide the column on their side. Next to the playlists button, the search button shows or hides the search fields. Refresh, Settings and the menu sit on the right.

  • The side columns can be resized by dragging the line between columns, and the middle takes the rest. Hiding one side leaves the other where it is.
  • The window's minimum width follows the columns shown, so the middle column never gets narrower than its minimum.
  • The widths, which columns are shown and whether the search is shown are saved with the rest of the layout.

Removed: the Hide sidebar button, the All Music button, the Now Playing button in the player bar, and Play and Shuffle in the middle column. Play and Shuffle stay on each playlist in the left column. LibraryPage.qml and ColumnTitle.qml are gone. The playlist and queue pages are now plain views (PlaylistView.qml, QueueView.qml).

All Music and the playlist now share the middle column, so the old drag from All Music into the open playlist cannot happen anymore. Songs can be dropped on a playlist's tab or on the playlist in the left column instead (SongDropArea.qml). Files dragged from the file manager still drop into the open playlist at the line under the pointer.

The search button or Ctrl+F shows a field above the playlists, which filters by name, and one above the middle column, which filters what it shows. Hiding them clears both searches.

  • Plain words match the file name, every text tag in the file and the length as it shows (3:07). Each word must match somewhere, in any order, ignoring case and accents.
  • Fields search one tag: title:, artist: (or author:, which also looks at the album artist), albumartist:, album:, genre:, composer:, comment:, year:/date:, length: and file:. A value can have spaces and runs to the next field: lifehouse album:you give what you get.
  • Comparisons: lengths and years compare with <, <=, > and >=: length:>2:00, year:<2000. A length without a colon is in minutes.
  • While typing: a field with no value yet, or a length or year that cannot be read, is ignored, so the list does not empty out mid-word.

How it works:

  • src/songsearch.cpp reads the tags with libavformat, the same opener as the cover code (src/audiofile.cpp). It skips encoder, ReplayGain, MusicBrainz and lyrics tags. Tag names are unified across formats, for example album_artist and ALBUMARTIST. Results are cached per file until it changes on disk.
  • SongModel scans the folder as before, then reads the tags on a thread pool thread. Until that finishes, All Music searches file names only. TrackModel reads through the same cache, so a playlist search is usually instant.
  • SearchFilterModel is a QSortFilterProxyModel between each list and its model. While a search filters a playlist, reordering is off, removing maps back to the playlist row, and dropped songs go at the end.

Add to playlist menu

src/qml/PlaylistMenu.qml shows a set number of playlists at a time: 15 by default, from 3 to 100 in Settings. With more playlists, arrows above and below scroll through them, on hover, click or mouse wheel, and a search field at the top narrows the list. Enter adds the song to the first playlist left. The arrows and the field are not MenuItems, so clicking them leaves the menu open.

Docs

README.md has new Window layout, Editing playlists and Search sections. CHANGELOG.md lists the changes under Unreleased. ROADMAP.md ticks Search and the button rearrangement, and adds "Create and delete playlists" under Later.

Checked

  • Builds without warnings and qmllint is clean in org.kde.Sdk//6.11. The three test suites pass. The new tst_songsearch covers folding, query parsing, fields, comparisons, and reading tags from tagged MP3, FLAC and Opus files.
  • Screenshots in a nested KWin with a test library: the layout with each column hidden, the titles, searches by word, field, length and year, and the cropped menu with a search typed in.
  • Tested in a local Flatpak build.
## Three columns and one top bar The Kirigami page stack is replaced by a `SplitView` with three columns: - **Left:** the playlists. Clicking one opens it in the middle. Songs dropped on a playlist are added to it. - **Middle:** All Music, or the playlist in the current tab. All Music is a fixed first tab, and the middle shows it whenever no playlist is open. Its first row has the column's title and, in a playlist, **Add songs** and **Remove songs**. - **Right:** Now Playing. One bar runs across the top (`src/qml/TopBar.qml`). The playlists button at the left end and the Now Playing button at the right end show or hide the column on their side. Next to the playlists button, the search button shows or hides the search fields. Refresh, Settings and the menu sit on the right. - The side columns can be resized by dragging the line between columns, and the middle takes the rest. Hiding one side leaves the other where it is. - The window's minimum width follows the columns shown, so the middle column never gets narrower than its minimum. - The widths, which columns are shown and whether the search is shown are saved with the rest of the layout. Removed: the Hide sidebar button, the All Music button, the Now Playing button in the player bar, and Play and Shuffle in the middle column. Play and Shuffle stay on each playlist in the left column. `LibraryPage.qml` and `ColumnTitle.qml` are gone. The playlist and queue pages are now plain views (`PlaylistView.qml`, `QueueView.qml`). All Music and the playlist now share the middle column, so the old drag from All Music into the open playlist cannot happen anymore. Songs can be dropped on a playlist's tab or on the playlist in the left column instead (`SongDropArea.qml`). Files dragged from the file manager still drop into the open playlist at the line under the pointer. ## Search The search button or Ctrl+F shows a field above the playlists, which filters by name, and one above the middle column, which filters what it shows. Hiding them clears both searches. - **Plain words** match the file name, every text tag in the file and the length as it shows (`3:07`). Each word must match somewhere, in any order, ignoring case and accents. - **Fields** search one tag: `title:`, `artist:` (or `author:`, which also looks at the album artist), `albumartist:`, `album:`, `genre:`, `composer:`, `comment:`, `year:`/`date:`, `length:` and `file:`. A value can have spaces and runs to the next field: `lifehouse album:you give what you get`. - **Comparisons:** lengths and years compare with `<`, `<=`, `>` and `>=`: `length:>2:00`, `year:<2000`. A length without a colon is in minutes. - **While typing:** a field with no value yet, or a length or year that cannot be read, is ignored, so the list does not empty out mid-word. How it works: - `src/songsearch.cpp` reads the tags with libavformat, the same opener as the cover code (`src/audiofile.cpp`). It skips encoder, ReplayGain, MusicBrainz and lyrics tags. Tag names are unified across formats, for example `album_artist` and `ALBUMARTIST`. Results are cached per file until it changes on disk. - `SongModel` scans the folder as before, then reads the tags on a thread pool thread. Until that finishes, All Music searches file names only. `TrackModel` reads through the same cache, so a playlist search is usually instant. - `SearchFilterModel` is a `QSortFilterProxyModel` between each list and its model. While a search filters a playlist, reordering is off, removing maps back to the playlist row, and dropped songs go at the end. ## Add to playlist menu `src/qml/PlaylistMenu.qml` shows a set number of playlists at a time: 15 by default, from 3 to 100 in Settings. With more playlists, arrows above and below scroll through them, on hover, click or mouse wheel, and a search field at the top narrows the list. Enter adds the song to the first playlist left. The arrows and the field are not `MenuItem`s, so clicking them leaves the menu open. ## Docs `README.md` has new Window layout, Editing playlists and Search sections. `CHANGELOG.md` lists the changes under Unreleased. `ROADMAP.md` ticks Search and the button rearrangement, and adds "Create and delete playlists" under Later. ## Checked - Builds without warnings and `qmllint` is clean in `org.kde.Sdk//6.11`. The three test suites pass. The new `tst_songsearch` covers folding, query parsing, fields, comparisons, and reading tags from tagged MP3, FLAC and Opus files. - Screenshots in a nested KWin with a test library: the layout with each column hidden, the titles, searches by word, field, length and year, and the cropped menu with a search typed in. - Tested in a local Flatpak build.
Add search, and lay the window out in three resizable columns
All checks were successful
build / build (pull_request) Successful in 2m25s
build / release (pull_request) Has been skipped
951c3b68b4
The window has one bar across the top and three columns: the playlists, All Music or the
open playlist, and Now Playing. The side columns can be hidden from the top bar and
resized, and the middle one takes the rest.

Search filters the playlists by name, and the songs in All Music or the open playlist by
file name, tags and length. A search can name a tag, as in album:you give what you get,
and compare lengths and years, as in length:>2:00 or year:<2000. The tags are read with
libavformat on a background thread after the folder scan.

The Add to playlist menu shows a set number of playlists at a time, 15 by default, with
scroll arrows and a search field. Songs can be dropped on a playlist's tab or on the
playlist in the left column.
GrumpyStraw scheduled this pull request to auto merge when all checks succeed 2026-10-11 14:38:33 +02:00
GrumpyStraw deleted branch search 2026-10-11 14:40:06 +02:00
Sign in to join this conversation.
No description provided.