Compare commits
61 Commits
6a51ee32b5
...
67fed77ba1
Author | SHA1 | Date |
---|---|---|
Jonas Kvinge | 67fed77ba1 | |
Jonas Kvinge | dff3ae7410 | |
Jonas Kvinge | 76614bcde0 | |
Jonas Kvinge | 2953f9eefc | |
Jonas Kvinge | 4a24605361 | |
Jonas Kvinge | decabe8d47 | |
Jonas Kvinge | 51adcf0f1e | |
Jonas Kvinge | 2a6a07fef6 | |
Jonas Kvinge | 315cf63118 | |
Wedone | e28d362aad | |
Jonas Kvinge | e0d9b8f715 | |
Jonas Kvinge | eff6b75c43 | |
Robert Gingras | e8be0adf37 | |
Robert Gingras | 9f4a82bb62 | |
Robert Gingras | 8d7e14f21d | |
Robert Gingras | d03d3622aa | |
Robert Gingras | 821c32992d | |
Robert Gingras | b52cf9f3cd | |
Robert Gingras | ab8e687f96 | |
Robert Gingras | 90703703aa | |
Jonas Kvinge | 176984afe0 | |
Jonas Kvinge | 542efa17ff | |
Jonas Kvinge | 6a2c2dbba1 | |
Jonas Kvinge | 426de61525 | |
Jonas Kvinge | 24c8d06d41 | |
Jonas Kvinge | 227f5e5176 | |
Jonas Kvinge | 92e39a3e21 | |
Jonas Kvinge | fb2300e2fa | |
Jonas Kvinge | 78becae5e9 | |
Jonas Kvinge | d10eb4370e | |
Jonas Kvinge | 9c92ef941f | |
Jonas Kvinge | 7aefe3d71b | |
Jonas Kvinge | 398db964b8 | |
Jonas Kvinge | 579349b104 | |
Jonas Kvinge | 5f9a83871d | |
Jonas Kvinge | da0c5e67c5 | |
Jonas Kvinge | a0cfde18c3 | |
Jonas Kvinge | 0ad4889936 | |
Jonas Kvinge | 36e809d530 | |
Jonas Kvinge | 78096658e2 | |
Jonas Kvinge | 3edd218e3a | |
Jonas Kvinge | 569bf6335b | |
Jonas Kvinge | 7b8919d706 | |
Jonas Kvinge | 147fd87d8c | |
Jonas Kvinge | ac0926d40b | |
Jonas Kvinge | 105d472f5d | |
Jonas Kvinge | c1a49da385 | |
Jonas Kvinge | c3f596e64e | |
Jonas Kvinge | adfda84c41 | |
Jonas Kvinge | 345cc118a3 | |
Jonas Kvinge | df070ac0cf | |
Jonas Kvinge | 7b88be2635 | |
Kientz Arnaud | c30a39d29a | |
Jonas Kvinge | 36db41a1f0 | |
Jonas Kvinge | 8b249dc06a | |
Jonas Kvinge | 0c6872b352 | |
Jonas Kvinge | 58944993b8 | |
Olivier HUMBERT | 3cfffa5fbb | |
Jonas Kvinge | 4873b8b413 | |
Jonas Kvinge | 0b85f5192c | |
Jonas Kvinge | 3e9a1776a1 |
|
@ -15,11 +15,14 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
opensuse_version: [ 'tumbleweed', 'leap:15.6' ]
|
||||
opensuse_version: [ 'tumbleweed', 'leap:15.5', 'leap:15.6' ]
|
||||
qt_version: [ '5', '6' ]
|
||||
container:
|
||||
image: opensuse/${{matrix.opensuse_version}}
|
||||
steps:
|
||||
- name: Add devel tools building repo
|
||||
if: matrix.opensuse_version != 'tumbleweed'
|
||||
run: zypper -n ar -c -f -n 'devel-tools-building' https://download.opensuse.org/repositories/devel:tools:building/$(echo "${{matrix.opensuse_version}}" | cut -d ':' -f 2)/ devel-tools-building
|
||||
- name: Add tagparser repo
|
||||
if: matrix.opensuse_version == 'tumbleweed'
|
||||
run: zypper -n ar -c -f -n 'repo-tagparser' https://download.opensuse.org/repositories/home:/mkittler/openSUSE_Tumbleweed/ repo-tagparser
|
||||
|
@ -182,7 +185,7 @@ jobs:
|
|||
run: dnf -y upgrade
|
||||
- name: Install dependencies
|
||||
run: >
|
||||
dnf -y --skip-broken install
|
||||
dnf -y install
|
||||
@development-tools
|
||||
redhat-lsb-core
|
||||
which
|
||||
|
@ -260,8 +263,7 @@ jobs:
|
|||
|
||||
build-openmandriva:
|
||||
name: Build OpenMandriva
|
||||
if: false
|
||||
#if: github.repository != 'strawberrymusicplayer/strawberry-private'
|
||||
if: github.repository != 'strawberrymusicplayer/strawberry-private' && false
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -360,7 +362,7 @@ jobs:
|
|||
|
||||
build-mageia:
|
||||
name: Build Mageia
|
||||
if: github.repository != 'strawberrymusicplayer/strawberry-private' && false
|
||||
if: github.repository != 'strawberrymusicplayer/strawberry-private'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -369,8 +371,14 @@ jobs:
|
|||
container:
|
||||
image: mageia:${{matrix.mageia_version}}
|
||||
steps:
|
||||
- name: Set media
|
||||
run: |
|
||||
urpmi.removemedia "Core Release"
|
||||
urpmi.removemedia "Core Updates"
|
||||
urpmi.addmedia "Core Release" "https://mirrors.kernel.org/mageia/distrib/${{matrix.mageia_version}}/x86_64/media/core/release/"
|
||||
urpmi.addmedia "Core Updates" "https://mirrors.kernel.org/mageia/distrib/${{matrix.mageia_version}}/x86_64/media/core/updates/"
|
||||
- name: Update repositories
|
||||
run: urpmi.update --auto -a
|
||||
run: urpmi.update -a
|
||||
- name: Upgrade packages
|
||||
run: urpmi --auto --auto-update
|
||||
- name: Install dependencies
|
||||
|
@ -404,16 +412,19 @@ jobs:
|
|||
lib64fftw-devel
|
||||
lib64dbus-devel
|
||||
lib64appstream-devel
|
||||
lib64qt6core-devel
|
||||
lib64qt6gui-devel
|
||||
lib64qt6widgets-devel
|
||||
lib64qt6network-devel
|
||||
lib64qt6concurrent-devel
|
||||
lib64qt6sql-devel
|
||||
lib64qt6dbus-devel
|
||||
lib64qt6help-devel
|
||||
lib64qt6test-devel
|
||||
protobuf-compiler
|
||||
desktop-file-utils
|
||||
appstream-util
|
||||
hicolor-icon-theme
|
||||
- name: Install Qt 5
|
||||
if: matrix.mageia_version == '8'
|
||||
run: urpmi --auto --force urpmi-debuginfo-install lib64qt5core-devel lib64qt5gui-devel lib64qt5widgets-devel lib64qt5network-devel lib64qt5concurrent-devel lib64qt5sql-devel lib64qt5dbus-devel lib64qt5help-devel lib64qt5test-devel lib64qt5x11extras-devel
|
||||
- name: Install Qt 6
|
||||
if: matrix.mageia_version == 'cauldron'
|
||||
run: urpmi --auto --force urpmi-debuginfo-install lib64qt6core-devel lib64qt6gui-devel lib64qt6widgets-devel lib64qt6network-devel lib64qt6concurrent-devel lib64qt6sql-devel lib64qt6dbus-devel lib64qt6help-devel lib64qt6test-devel
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
|
@ -974,7 +985,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [ 'i686', 'x86_64' ]
|
||||
arch: [ 'x86_64' ]
|
||||
buildtype: [ 'debug', 'release' ]
|
||||
container:
|
||||
image: jonaski/strawberry-mxe-${{matrix.arch}}-${{matrix.buildtype}}
|
||||
|
@ -1145,8 +1156,8 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [ 'x86', 'x86_64' ]
|
||||
buildtype: [ 'debug', 'release' ]
|
||||
arch: [ 'x86_64' ]
|
||||
buildtype: [ 'release' ]
|
||||
steps:
|
||||
|
||||
- name: Set prefix path
|
||||
|
@ -1427,7 +1438,7 @@ jobs:
|
|||
|
||||
upload:
|
||||
name: Upload
|
||||
if: github.repository == 'strawberrymusicplayer/strawberry' && (github.event_name == 'release' || (github.event_name == 'push' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')))
|
||||
if: (success() || failure()) && github.repository == 'strawberrymusicplayer/strawberry' && (github.event_name == 'release' || (github.event_name == 'push' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')))
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-opensuse
|
||||
|
@ -1476,11 +1487,12 @@ jobs:
|
|||
|
||||
attach:
|
||||
name: Attach to release
|
||||
if: github.event_name == 'release'
|
||||
if: (success() || failure()) && github.event_name == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-opensuse
|
||||
- build-fedora
|
||||
- build-mageia
|
||||
- build-debian
|
||||
- build-ubuntu
|
||||
- build-windows-mingw
|
||||
|
|
|
@ -439,6 +439,7 @@ option(INSTALL_TRANSLATIONS "Install translations" OFF)
|
|||
|
||||
optional_component(SUBSONIC ON "Streaming: Subsonic")
|
||||
optional_component(TIDAL ON "Streaming: Tidal")
|
||||
optional_component(SPOTIFY ON "Streaming: Spotify" DEPENDS "gstreamer" GSTREAMER_FOUND)
|
||||
optional_component(QOBUZ ON "Streaming: Qobuz")
|
||||
|
||||
optional_component(MOODBAR ON "Moodbar"
|
||||
|
@ -508,6 +509,8 @@ add_definitions(
|
|||
-DQT_NO_CAST_TO_ASCII
|
||||
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
||||
-DQT_NO_FOREACH
|
||||
-DQT_ASCII_CAST_WARNINGS
|
||||
-DQT_NO_CAST_FROM_ASCII
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
:strawberry: Strawberry Music Player [![Build Status](https://github.com/strawberrymusicplayer/strawberry/workflows/build/badge.svg)](https://github.com/strawberrymusicplayer/strawberry/actions)
|
||||
:strawberry: Strawberry Music Player [![Build Status](https://github.com/strawberrymusicplayer/strawberry/workflows/Build/badge.svg)](https://github.com/strawberrymusicplayer/strawberry/actions)
|
||||
=======================
|
||||
[![Sponsor](https://img.shields.io/badge/-Sponsor-green?logo=github)](https://github.com/sponsors/jonaski)
|
||||
[![Patreon](https://img.shields.io/badge/patreon-donate-green.svg)](https://patreon.com/jonaskvinge)
|
||||
|
|
|
@ -42,5 +42,6 @@
|
|||
<file>pictures/star-off.png</file>
|
||||
<file>mood/sample.mood</file>
|
||||
<file>text/ghosts.txt</file>
|
||||
<file>pictures/sidebar-background.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
<file>icons/128x128/love.png</file>
|
||||
<file>icons/128x128/subsonic.png</file>
|
||||
<file>icons/128x128/tidal.png</file>
|
||||
<file>icons/128x128/spotify.png</file>
|
||||
<file>icons/128x128/qobuz.png</file>
|
||||
<file>icons/128x128/multimedia-player-ipod-standard-black.png</file>
|
||||
<file>icons/128x128/radio.png</file>
|
||||
|
@ -189,6 +190,7 @@
|
|||
<file>icons/64x64/love.png</file>
|
||||
<file>icons/64x64/subsonic.png</file>
|
||||
<file>icons/64x64/tidal.png</file>
|
||||
<file>icons/64x64/spotify.png</file>
|
||||
<file>icons/64x64/qobuz.png</file>
|
||||
<file>icons/64x64/multimedia-player-ipod-standard-black.png</file>
|
||||
<file>icons/64x64/radio.png</file>
|
||||
|
@ -291,6 +293,7 @@
|
|||
<file>icons/48x48/love.png</file>
|
||||
<file>icons/48x48/subsonic.png</file>
|
||||
<file>icons/48x48/tidal.png</file>
|
||||
<file>icons/48x48/spotify.png</file>
|
||||
<file>icons/48x48/qobuz.png</file>
|
||||
<file>icons/48x48/multimedia-player-ipod-standard-black.png</file>
|
||||
<file>icons/48x48/radio.png</file>
|
||||
|
@ -393,6 +396,7 @@
|
|||
<file>icons/32x32/love.png</file>
|
||||
<file>icons/32x32/subsonic.png</file>
|
||||
<file>icons/32x32/tidal.png</file>
|
||||
<file>icons/32x32/spotify.png</file>
|
||||
<file>icons/32x32/qobuz.png</file>
|
||||
<file>icons/32x32/multimedia-player-ipod-standard-black.png</file>
|
||||
<file>icons/32x32/radio.png</file>
|
||||
|
@ -495,6 +499,7 @@
|
|||
<file>icons/22x22/love.png</file>
|
||||
<file>icons/22x22/subsonic.png</file>
|
||||
<file>icons/22x22/tidal.png</file>
|
||||
<file>icons/22x22/spotify.png</file>
|
||||
<file>icons/22x22/qobuz.png</file>
|
||||
<file>icons/22x22/multimedia-player-ipod-standard-black.png</file>
|
||||
<file>icons/22x22/radio.png</file>
|
||||
|
|
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 7.3 KiB |
|
@ -0,0 +1,289 @@
|
|||
CREATE TABLE IF NOT EXISTS spotify_artists_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
fingerprint TEXT,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
lastseen INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_embedded INTEGER DEFAULT 0,
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
art_unset INTEGER DEFAULT 0,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT,
|
||||
|
||||
rating INTEGER DEFAULT -1,
|
||||
|
||||
acoustid_id TEXT,
|
||||
acoustid_fingerprint TEXT,
|
||||
|
||||
musicbrainz_album_artist_id TEXT,
|
||||
musicbrainz_artist_id TEXT,
|
||||
musicbrainz_original_artist_id TEXT,
|
||||
musicbrainz_album_id TEXT,
|
||||
musicbrainz_original_album_id TEXT,
|
||||
musicbrainz_recording_id TEXT,
|
||||
musicbrainz_track_id TEXT,
|
||||
musicbrainz_disc_id TEXT,
|
||||
musicbrainz_release_group_id TEXT,
|
||||
musicbrainz_work_id TEXT,
|
||||
|
||||
ebur128_integrated_loudness_lufs REAL,
|
||||
ebur128_loudness_range_lu REAL
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS spotify_albums_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
fingerprint TEXT,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
lastseen INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_embedded INTEGER DEFAULT 0,
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
art_unset INTEGER DEFAULT 0,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT,
|
||||
|
||||
rating INTEGER DEFAULT -1,
|
||||
|
||||
acoustid_id TEXT,
|
||||
acoustid_fingerprint TEXT,
|
||||
|
||||
musicbrainz_album_artist_id TEXT,
|
||||
musicbrainz_artist_id TEXT,
|
||||
musicbrainz_original_artist_id TEXT,
|
||||
musicbrainz_album_id TEXT,
|
||||
musicbrainz_original_album_id TEXT,
|
||||
musicbrainz_recording_id TEXT,
|
||||
musicbrainz_track_id TEXT,
|
||||
musicbrainz_disc_id TEXT,
|
||||
musicbrainz_release_group_id TEXT,
|
||||
musicbrainz_work_id TEXT,
|
||||
|
||||
ebur128_integrated_loudness_lufs REAL,
|
||||
ebur128_loudness_range_lu REAL
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS spotify_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
fingerprint TEXT,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
lastseen INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_embedded INTEGER DEFAULT 0,
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
art_unset INTEGER DEFAULT 0,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT,
|
||||
|
||||
rating INTEGER DEFAULT -1,
|
||||
|
||||
acoustid_id TEXT,
|
||||
acoustid_fingerprint TEXT,
|
||||
|
||||
musicbrainz_album_artist_id TEXT,
|
||||
musicbrainz_artist_id TEXT,
|
||||
musicbrainz_original_artist_id TEXT,
|
||||
musicbrainz_album_id TEXT,
|
||||
musicbrainz_original_album_id TEXT,
|
||||
musicbrainz_recording_id TEXT,
|
||||
musicbrainz_track_id TEXT,
|
||||
musicbrainz_disc_id TEXT,
|
||||
musicbrainz_release_group_id TEXT,
|
||||
musicbrainz_work_id TEXT,
|
||||
|
||||
ebur128_integrated_loudness_lufs REAL,
|
||||
ebur128_loudness_range_lu REAL
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS spotify_artists_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 1"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS spotify_albums_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 1"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS spotify_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 1"
|
||||
|
||||
);
|
||||
|
||||
UPDATE schema_version SET version=19;
|
|
@ -422,6 +422,192 @@ CREATE TABLE IF NOT EXISTS tidal_songs (
|
|||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS spotify_artists_songs (
|
||||
|
||||
title TEXT DEFAULT '',
|
||||
album TEXT DEFAULT '',
|
||||
artist TEXT DEFAULT '',
|
||||
albumartist TEXT DEFAULT '',
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||
genre TEXT DEFAULT '',
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT DEFAULT '',
|
||||
performer TEXT DEFAULT '',
|
||||
grouping TEXT DEFAULT '',
|
||||
comment TEXT DEFAULT '',
|
||||
lyrics TEXT DEFAULT '',
|
||||
|
||||
artist_id TEXT DEFAULT '',
|
||||
album_id TEXT DEFAULT '',
|
||||
song_id TEXT DEFAULT '',
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL DEFAULT '',
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
fingerprint TEXT DEFAULT '',
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
lastseen INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT DEFAULT '',
|
||||
art_manual TEXT DEFAULT '',
|
||||
|
||||
effective_albumartist TEXT DEFAULT '',
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT DEFAULT '',
|
||||
|
||||
rating INTEGER DEFAULT -1
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS spotify_albums_songs (
|
||||
|
||||
title TEXT DEFAULT '',
|
||||
album TEXT DEFAULT '',
|
||||
artist TEXT DEFAULT '',
|
||||
albumartist TEXT DEFAULT '',
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||
genre TEXT DEFAULT '',
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT DEFAULT '',
|
||||
performer TEXT DEFAULT '',
|
||||
grouping TEXT DEFAULT '',
|
||||
comment TEXT DEFAULT '',
|
||||
lyrics TEXT DEFAULT '',
|
||||
|
||||
artist_id TEXT DEFAULT '',
|
||||
album_id TEXT DEFAULT '',
|
||||
song_id TEXT DEFAULT '',
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL DEFAULT '',
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
fingerprint TEXT DEFAULT '',
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
lastseen INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT DEFAULT '',
|
||||
art_manual TEXT DEFAULT '',
|
||||
|
||||
effective_albumartist TEXT DEFAULT '',
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT DEFAULT '',
|
||||
|
||||
rating INTEGER DEFAULT -1
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS spotify_songs (
|
||||
|
||||
title TEXT DEFAULT '',
|
||||
album TEXT DEFAULT '',
|
||||
artist TEXT DEFAULT '',
|
||||
albumartist TEXT DEFAULT '',
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||
genre TEXT DEFAULT '',
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT DEFAULT '',
|
||||
performer TEXT DEFAULT '',
|
||||
grouping TEXT DEFAULT '',
|
||||
comment TEXT DEFAULT '',
|
||||
lyrics TEXT DEFAULT '',
|
||||
|
||||
artist_id TEXT DEFAULT '',
|
||||
album_id TEXT DEFAULT '',
|
||||
song_id TEXT DEFAULT '',
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL DEFAULT '',
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
fingerprint TEXT DEFAULT '',
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
lastseen INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT DEFAULT '',
|
||||
art_manual TEXT DEFAULT '',
|
||||
|
||||
effective_albumartist TEXT DEFAULT '',
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT DEFAULT '',
|
||||
|
||||
rating INTEGER DEFAULT -1
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qobuz_artists_songs (
|
||||
|
||||
title TEXT,
|
||||
|
@ -872,6 +1058,51 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
|
|||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS spotify_artists_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 1"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS spotify_albums_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 1"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS spotify_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 1"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS qobuz_artists_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
|
|
|
@ -3,8 +3,10 @@ Version=1.0
|
|||
Type=Application
|
||||
Name=Strawberry
|
||||
GenericName=Strawberry Music Player
|
||||
GenericName[fr]=Lecteur de musique Strawberry
|
||||
GenericName[ru]=Музыкальный проигрыватель Strawberry
|
||||
Comment=Plays music
|
||||
Comment[fr]=Joue de la musique
|
||||
Comment[ru]=Прослушивание музыки
|
||||
Exec=strawberry %U
|
||||
TryExec=strawberry
|
||||
|
|
|
@ -109,7 +109,11 @@
|
|||
|
||||
Unicode True
|
||||
|
||||
!ifdef debug
|
||||
SetCompressor lzma
|
||||
!else
|
||||
SetCompressor /SOLID lzma
|
||||
!endif
|
||||
|
||||
!include "MUI2.nsh"
|
||||
!include "FileAssociation.nsh"
|
||||
|
@ -497,7 +501,7 @@ Section "Strawberry" Strawberry
|
|||
|
||||
; Common files
|
||||
|
||||
File "icudt74.dll"
|
||||
File "icudt75.dll"
|
||||
File "libfftw3-3.dll"
|
||||
!ifdef debug
|
||||
File "libprotobufd.dll"
|
||||
|
@ -505,8 +509,8 @@ Section "Strawberry" Strawberry
|
|||
File "libprotobuf.dll"
|
||||
!endif
|
||||
!ifdef msvc && debug
|
||||
File "icuin74d.dll"
|
||||
File "icuuc74d.dll"
|
||||
File "icuin75d.dll"
|
||||
File "icuuc75d.dll"
|
||||
File "Qt6Concurrentd.dll"
|
||||
File "Qt6Cored.dll"
|
||||
File "Qt6Guid.dll"
|
||||
|
@ -514,8 +518,8 @@ Section "Strawberry" Strawberry
|
|||
File "Qt6Sqld.dll"
|
||||
File "Qt6Widgetsd.dll"
|
||||
!else
|
||||
File "icuin74.dll"
|
||||
File "icuuc74.dll"
|
||||
File "icuin75.dll"
|
||||
File "icuuc75.dll"
|
||||
File "Qt6Concurrent.dll"
|
||||
File "Qt6Core.dll"
|
||||
File "Qt6Gui.dll"
|
||||
|
@ -1065,7 +1069,7 @@ Section "Uninstall"
|
|||
|
||||
; Common files
|
||||
|
||||
Delete "$INSTDIR\icudt74.dll"
|
||||
Delete "$INSTDIR\icudt75.dll"
|
||||
Delete "$INSTDIR\libfftw3-3.dll"
|
||||
!ifdef debug
|
||||
Delete "$INSTDIR\libprotobufd.dll"
|
||||
|
@ -1073,8 +1077,8 @@ Section "Uninstall"
|
|||
Delete "$INSTDIR\libprotobuf.dll"
|
||||
!endif
|
||||
!ifdef msvc && debug
|
||||
Delete "$INSTDIR\icuin74d.dll"
|
||||
Delete "$INSTDIR\icuuc74d.dll"
|
||||
Delete "$INSTDIR\icuin75d.dll"
|
||||
Delete "$INSTDIR\icuuc75d.dll"
|
||||
Delete "$INSTDIR\Qt6Concurrentd.dll"
|
||||
Delete "$INSTDIR\Qt6Cored.dll"
|
||||
Delete "$INSTDIR\Qt6Guid.dll"
|
||||
|
@ -1082,8 +1086,8 @@ Section "Uninstall"
|
|||
Delete "$INSTDIR\Qt6Sqld.dll"
|
||||
Delete "$INSTDIR\Qt6Widgetsd.dll"
|
||||
!else
|
||||
Delete "$INSTDIR\icuin74.dll"
|
||||
Delete "$INSTDIR\icuuc74.dll"
|
||||
Delete "$INSTDIR\icuin75.dll"
|
||||
Delete "$INSTDIR\icuuc75.dll"
|
||||
Delete "$INSTDIR\Qt6Concurrent.dll"
|
||||
Delete "$INSTDIR\Qt6Core.dll"
|
||||
Delete "$INSTDIR\Qt6Gui.dll"
|
||||
|
|
|
@ -67,8 +67,8 @@ static QIODevice *sNullDevice = nullptr;
|
|||
|
||||
const char *kDefaultLogLevels = "*:3";
|
||||
|
||||
static const char *kMessageHandlerMagic = "__logging_message__";
|
||||
static const size_t kMessageHandlerMagicLength = strlen(kMessageHandlerMagic);
|
||||
static constexpr char kMessageHandlerMagic[] = "__logging_message__";
|
||||
static const size_t kMessageHandlerMagicLen = strlen(kMessageHandlerMagic);
|
||||
static QtMessageHandler sOriginalMessageHandler = nullptr;
|
||||
|
||||
template<class T>
|
||||
|
@ -135,9 +135,9 @@ class LoggedDebug : public DebugBase<LoggedDebug> {
|
|||
|
||||
static void MessageHandler(QtMsgType type, const QMessageLogContext&, const QString &message) {
|
||||
|
||||
if (message.startsWith(kMessageHandlerMagic)) {
|
||||
if (message.startsWith(QLatin1String(kMessageHandlerMagic))) {
|
||||
QByteArray message_data = message.toUtf8();
|
||||
fprintf(type == QtCriticalMsg || type == QtFatalMsg ? stderr : stdout, "%s\n", message_data.constData() + kMessageHandlerMagicLength);
|
||||
fprintf(type == QtCriticalMsg || type == QtFatalMsg ? stderr : stdout, "%s\n", message_data.constData() + kMessageHandlerMagicLen);
|
||||
fflush(type == QtCriticalMsg || type == QtFatalMsg ? stderr : stdout);
|
||||
return;
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ static void MessageHandler(QtMsgType type, const QMessageLogContext&, const QStr
|
|||
break;
|
||||
}
|
||||
|
||||
for (const QString &line : message.split('\n')) {
|
||||
BufferedDebug d = CreateLogger<BufferedDebug>(level, "unknown", -1, nullptr);
|
||||
for (const QString &line : message.split(QLatin1Char('\n'))) {
|
||||
BufferedDebug d = CreateLogger<BufferedDebug>(level, QStringLiteral("unknown"), -1, nullptr);
|
||||
d << line.toLocal8Bit().constData();
|
||||
if (d.buf_) {
|
||||
d.buf_->close();
|
||||
|
@ -193,8 +193,8 @@ void SetLevels(const QString &levels) {
|
|||
|
||||
if (!sClassLevels) return;
|
||||
|
||||
for (const QString &item : levels.split(',')) {
|
||||
const QStringList class_level = item.split(':');
|
||||
for (const QString &item : levels.split(QLatin1Char(','))) {
|
||||
const QStringList class_level = item.split(QLatin1Char(':'));
|
||||
|
||||
QString class_name;
|
||||
bool ok = false;
|
||||
|
@ -212,7 +212,7 @@ void SetLevels(const QString &levels) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (class_name.isEmpty() || class_name == "*") {
|
||||
if (class_name.isEmpty() || class_name == QStringLiteral("*")) {
|
||||
sDefaultLevel = static_cast<Level>(level);
|
||||
}
|
||||
else {
|
||||
|
@ -225,10 +225,10 @@ void SetLevels(const QString &levels) {
|
|||
static QString ParsePrettyFunction(const char *pretty_function) {
|
||||
|
||||
// Get the class name out of the function name.
|
||||
QString class_name = pretty_function;
|
||||
const qint64 paren = class_name.indexOf('(');
|
||||
QString class_name = QLatin1String(pretty_function);
|
||||
const qint64 paren = class_name.indexOf(QLatin1Char('('));
|
||||
if (paren != -1) {
|
||||
const qint64 colons = class_name.lastIndexOf("::", paren);
|
||||
const qint64 colons = class_name.lastIndexOf(QLatin1String("::"), paren);
|
||||
if (colons != -1) {
|
||||
class_name = class_name.left(colons);
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ static QString ParsePrettyFunction(const char *pretty_function) {
|
|||
}
|
||||
}
|
||||
|
||||
const qint64 space = class_name.lastIndexOf(' ');
|
||||
const qint64 space = class_name.lastIndexOf(QLatin1Char(' '));
|
||||
if (space != -1) {
|
||||
class_name = class_name.mid(space + 1);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ static T CreateLogger(Level level, const QString &class_name, int line, const ch
|
|||
case Level_Fatal: level_name = " FATAL "; break;
|
||||
}
|
||||
|
||||
QString filter_category = (category != nullptr) ? category : class_name;
|
||||
QString filter_category = (category != nullptr) ? QLatin1String(category) : class_name;
|
||||
// Check the settings to see if we're meant to show or hide this message.
|
||||
Level threshold_level = sDefaultLevel;
|
||||
if (sClassLevels && sClassLevels->contains(filter_category)) {
|
||||
|
@ -272,10 +272,10 @@ static T CreateLogger(Level level, const QString &class_name, int line, const ch
|
|||
|
||||
QString function_line = class_name;
|
||||
if (line != -1) {
|
||||
function_line += ":" + QString::number(line);
|
||||
function_line += QStringLiteral(":") + QString::number(line);
|
||||
}
|
||||
if (category) {
|
||||
function_line += "(" + QString(category) + ")";
|
||||
function_line += QStringLiteral("(") + QLatin1String(category) + QStringLiteral(")");
|
||||
}
|
||||
|
||||
QtMsgType type = QtDebugMsg;
|
||||
|
@ -284,7 +284,7 @@ static T CreateLogger(Level level, const QString &class_name, int line, const ch
|
|||
}
|
||||
|
||||
T ret(type);
|
||||
ret.nospace() << QDateTime::currentDateTime().toString("hh:mm:ss.zzz").toLatin1().constData() << level_name << function_line.leftJustified(32).toLatin1().constData();
|
||||
ret.nospace() << QDateTime::currentDateTime().toString(QStringLiteral("hh:mm:ss.zzz")).toLatin1().constData() << level_name << function_line.leftJustified(32).toLatin1().constData();
|
||||
|
||||
return ret.space();
|
||||
|
||||
|
@ -310,7 +310,7 @@ QString CXXDemangle(const QString &mangled_function) {
|
|||
QString LinuxDemangle(const QString &symbol);
|
||||
QString LinuxDemangle(const QString &symbol) {
|
||||
|
||||
QRegularExpression regex("\\(([^+]+)");
|
||||
QRegularExpression regex(QStringLiteral("\\(([^+]+)"));
|
||||
QRegularExpressionMatch match = regex.match(symbol);
|
||||
if (!match.hasMatch()) {
|
||||
return symbol;
|
||||
|
@ -326,9 +326,9 @@ QString DarwinDemangle(const QString &symbol);
|
|||
QString DarwinDemangle(const QString &symbol) {
|
||||
|
||||
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
QStringList split = symbol.split(' ', Qt::SkipEmptyParts);
|
||||
QStringList split = symbol.split(QLatin1Char(' '), Qt::SkipEmptyParts);
|
||||
# else
|
||||
QStringList split = symbol.split(' ', QString::SkipEmptyParts);
|
||||
QStringList split = symbol.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
# endif
|
||||
QString mangled_function = split[3];
|
||||
return CXXDemangle(mangled_function);
|
||||
|
@ -392,7 +392,7 @@ namespace {
|
|||
|
||||
template<typename T>
|
||||
QString print_duration(T duration, const std::string &unit) {
|
||||
return QString("%1%2").arg(duration.count()).arg(unit.c_str());
|
||||
return QStringLiteral("%1%2").arg(duration.count()).arg(QString::fromStdString(unit));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
|
@ -171,7 +172,7 @@ WorkerPool<HandlerType>::WorkerPool(QObject *parent)
|
|||
local_server_name_ = qApp->applicationName().toLower();
|
||||
|
||||
if (local_server_name_.isEmpty()) {
|
||||
local_server_name_ = "workerpool";
|
||||
local_server_name_ = QStringLiteral("workerpool");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -243,15 +244,15 @@ void WorkerPool<HandlerType>::DoStart() {
|
|||
QStringList search_path;
|
||||
search_path << QCoreApplication::applicationDirPath();
|
||||
#if defined(Q_OS_UNIX)
|
||||
search_path << "/usr/libexec";
|
||||
search_path << "/usr/local/libexec";
|
||||
search_path << QStringLiteral("/usr/libexec");
|
||||
search_path << QStringLiteral("/usr/local/libexec");
|
||||
#endif
|
||||
#if defined(Q_OS_MACOS)
|
||||
search_path << QDir::cleanPath(QCoreApplication::applicationDirPath() + "/../PlugIns");
|
||||
search_path << QDir::cleanPath(QCoreApplication::applicationDirPath() + QStringLiteral("/../PlugIns"));
|
||||
#endif
|
||||
|
||||
for (const QString &path_prefix : search_path) {
|
||||
const QString executable_path = path_prefix + "/" + executable_name_;
|
||||
for (const QString &path_prefix : std::as_const(search_path)) {
|
||||
const QString executable_path = path_prefix + QLatin1Char('/') + executable_name_;
|
||||
if (QFile::exists(executable_path)) {
|
||||
executable_path_ = executable_path;
|
||||
qLog(Debug) << "Using worker" << executable_name_ << "from" << path_prefix;
|
||||
|
@ -294,7 +295,7 @@ void WorkerPool<HandlerType>::StartOneWorker(Worker *worker) {
|
|||
// Create a server, find an unused name and start listening
|
||||
forever {
|
||||
const quint32 unique_number = QRandomGenerator::global()->bounded(static_cast<quint32>(quint64(this) & 0xFFFFFFFF));
|
||||
const QString name = QString("%1_%2").arg(local_server_name_).arg(unique_number);
|
||||
const QString name = QStringLiteral("%1_%2").arg(local_server_name_).arg(unique_number);
|
||||
|
||||
if (worker->local_server_->listen(name)) {
|
||||
break;
|
||||
|
|
|
@ -74,7 +74,7 @@ TagReaderBase::Cover TagReaderBase::LoadCoverFromRequest(const spb::tagreader::S
|
|||
}
|
||||
QString cover_mime_type;
|
||||
if (request.has_cover_mime_type()) {
|
||||
cover_mime_type = QByteArray(request.cover_mime_type().data(), static_cast<qint64>(request.cover_mime_type().size()));
|
||||
cover_mime_type = QString::fromStdString(request.cover_mime_type());
|
||||
}
|
||||
|
||||
return LoadCoverFromRequest(song_filename, cover_filename, cover_data, cover_mime_type);
|
||||
|
@ -94,7 +94,7 @@ TagReaderBase::Cover TagReaderBase::LoadCoverFromRequest(const spb::tagreader::S
|
|||
}
|
||||
QString cover_mime_type;
|
||||
if (request.has_cover_mime_type()) {
|
||||
cover_mime_type = QByteArray(request.cover_mime_type().data(), static_cast<qint64>(request.cover_mime_type().size()));
|
||||
cover_mime_type = QString::fromStdString(request.cover_mime_type());
|
||||
}
|
||||
|
||||
return LoadCoverFromRequest(song_filename, cover_filename, cover_data, cover_mime_type);
|
||||
|
@ -118,24 +118,28 @@ TagReaderBase::Cover TagReaderBase::LoadCoverFromRequest(const QString &song_fil
|
|||
if (cover_mime_type.isEmpty()) {
|
||||
cover_mime_type = QMimeDatabase().mimeTypeForData(cover_data).name();
|
||||
}
|
||||
if (cover_mime_type == "image/jpeg") {
|
||||
if (cover_mime_type == QStringLiteral("image/jpeg")) {
|
||||
qLog(Debug) << "Using cover from JPEG data for" << song_filename;
|
||||
return Cover(cover_data, cover_mime_type);
|
||||
}
|
||||
if (cover_mime_type == "image/png") {
|
||||
if (cover_mime_type == QStringLiteral("image/png")) {
|
||||
qLog(Debug) << "Using cover from PNG data for" << song_filename;
|
||||
return Cover(cover_data, cover_mime_type);
|
||||
}
|
||||
// Convert image to JPEG.
|
||||
qLog(Debug) << "Converting cover to JPEG data for" << song_filename;
|
||||
QImage cover_image(cover_data);
|
||||
QImage cover_image;
|
||||
if (!cover_image.loadFromData(cover_data)) {
|
||||
qLog(Error) << "Failed to load image from cover data for" << song_filename;
|
||||
return Cover();
|
||||
}
|
||||
cover_data.clear();
|
||||
QBuffer buffer(&cover_data);
|
||||
if (buffer.open(QIODevice::WriteOnly)) {
|
||||
cover_image.save(&buffer, "JPEG");
|
||||
buffer.close();
|
||||
}
|
||||
return Cover(cover_data, "image/jpeg");
|
||||
return Cover(cover_data, QStringLiteral("image/jpeg"));
|
||||
}
|
||||
|
||||
return Cover();
|
||||
|
|
|
@ -36,16 +36,16 @@
|
|||
#include "tagreadertaglib.h"
|
||||
|
||||
bool GME::IsSupportedFormat(const QFileInfo &file_info) {
|
||||
return file_info.exists() && (file_info.completeSuffix().endsWith("spc", Qt::CaseInsensitive) || file_info.completeSuffix().endsWith("vgm"), Qt::CaseInsensitive);
|
||||
return file_info.exists() && (file_info.completeSuffix().endsWith(QLatin1String("spc"), Qt::CaseInsensitive) || file_info.completeSuffix().endsWith(QLatin1String("vgm")), Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool GME::ReadFile(const QFileInfo &file_info, spb::tagreader::SongMetadata *song_info) {
|
||||
|
||||
if (file_info.completeSuffix().endsWith("spc"), Qt::CaseInsensitive) {
|
||||
if (file_info.completeSuffix().endsWith(QLatin1String("spc")), Qt::CaseInsensitive) {
|
||||
SPC::Read(file_info, song_info);
|
||||
return true;
|
||||
}
|
||||
if (file_info.completeSuffix().endsWith("vgm", Qt::CaseInsensitive)) {
|
||||
if (file_info.completeSuffix().endsWith(QLatin1String("vgm"), Qt::CaseInsensitive)) {
|
||||
VGM::Read(file_info, song_info);
|
||||
return true;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ void GME::SPC::Read(const QFileInfo &file_info, spb::tagreader::SongMetadata *so
|
|||
qLog(Debug) << "Reading tags from SPC file" << file_info.fileName();
|
||||
|
||||
// Check for header -- more reliable than file name alone.
|
||||
if (!file.read(33).startsWith(QString("SNES-SPC700").toLatin1())) return;
|
||||
if (!file.read(33).startsWith(QStringLiteral("SNES-SPC700").toLatin1())) return;
|
||||
|
||||
// First order of business -- get any tag values that exist within the core file information.
|
||||
// These only allow for a certain number of bytes per field,
|
||||
|
@ -125,7 +125,7 @@ void GME::SPC::Read(const QFileInfo &file_info, spb::tagreader::SongMetadata *so
|
|||
// Check for XID6 data -- this is infrequently used, but being able to fill in data from this is ideal before trying to rely on APETAG values.
|
||||
// XID6 format follows EA's binary file format standard named "IFF"
|
||||
file.seek(XID6_OFFSET);
|
||||
if (has_id6 && file.read(4) == QString("xid6").toLatin1()) {
|
||||
if (has_id6 && file.read(4) == QStringLiteral("xid6").toLatin1()) {
|
||||
QByteArray xid6_head_data = file.read(4);
|
||||
if (xid6_head_data.size() >= 4) {
|
||||
qint64 xid6_size = xid6_head_data[0] | (xid6_head_data[1] << 8) | (xid6_head_data[2] << 16) | xid6_head_data[3];
|
||||
|
@ -195,7 +195,7 @@ void GME::VGM::Read(const QFileInfo &file_info, spb::tagreader::SongMetadata *so
|
|||
|
||||
qLog(Debug) << "Reading tags from VGM file" << file_info.fileName();
|
||||
|
||||
if (!file.read(4).startsWith(QString("Vgm ").toLatin1())) return;
|
||||
if (!file.read(4).startsWith(QStringLiteral("Vgm ").toLatin1())) return;
|
||||
|
||||
file.seek(GD3_TAG_PTR);
|
||||
QByteArray gd3_head = file.read(4);
|
||||
|
@ -226,7 +226,7 @@ void GME::VGM::Read(const QFileInfo &file_info, spb::tagreader::SongMetadata *so
|
|||
#else
|
||||
fileTagStream.setCodec("UTF-16");
|
||||
#endif
|
||||
QStringList strings = fileTagStream.readLine(0).split(QChar('\0'));
|
||||
QStringList strings = fileTagStream.readLine(0).split(QLatin1Char('\0'));
|
||||
if (strings.count() < 10) return;
|
||||
|
||||
// VGM standard dictates string tag data exist in specific order.
|
||||
|
|
|
@ -248,7 +248,7 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
|||
song->set_ctime(song->mtime());
|
||||
}
|
||||
|
||||
song->set_lastseen(QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||
song->set_lastseen(QDateTime::currentSecsSinceEpoch());
|
||||
|
||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||
if (fileref->isNull()) {
|
||||
|
@ -328,137 +328,8 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
|||
}
|
||||
|
||||
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
|
||||
if (file_mpeg->ID3v2Tag()) {
|
||||
const TagLib::ID3v2::FrameListMap &map = file_mpeg->ID3v2Tag()->frameListMap();
|
||||
|
||||
if (map.contains("TPOS")) disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
|
||||
if (map.contains("TCOM")) TStringToStdString(map["TCOM"].front()->toString(), song->mutable_composer());
|
||||
|
||||
// content group
|
||||
if (map.contains("TIT1")) TStringToStdString(map["TIT1"].front()->toString(), song->mutable_grouping());
|
||||
|
||||
// original artist/performer
|
||||
if (map.contains("TOPE")) TStringToStdString(map["TOPE"].front()->toString(), song->mutable_performer());
|
||||
|
||||
// Skip TPE1 (which is the artist) here because we already fetched it
|
||||
|
||||
// non-standard: Apple, Microsoft
|
||||
if (map.contains("TPE2")) TStringToStdString(map["TPE2"].front()->toString(), song->mutable_albumartist());
|
||||
|
||||
if (map.contains("TCMP")) compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
|
||||
|
||||
if (map.contains("TDOR")) {
|
||||
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
|
||||
}
|
||||
else if (map.contains("TORY")) {
|
||||
song->set_originalyear(map["TORY"].front()->toString().substr(0, 4).toInt());
|
||||
}
|
||||
|
||||
if (map.contains("USLT")) {
|
||||
TStringToStdString(map["USLT"].front()->toString(), song->mutable_lyrics());
|
||||
}
|
||||
else if (map.contains("SYLT")) {
|
||||
TStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
||||
}
|
||||
|
||||
if (map.contains("APIC")) song->set_art_embedded(true);
|
||||
|
||||
// Find a suitable comment tag. For now we ignore iTunNORM comments.
|
||||
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
||||
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
|
||||
|
||||
if (frame && TStringToQString(frame->description()) != "iTunNORM") {
|
||||
TStringToStdString(frame->text(), song->mutable_comment());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_playcount = TagLib::ID3v2::UserTextIdentificationFrame::find(file_mpeg->ID3v2Tag(), "FMPS_Playcount")) {
|
||||
TagLib::StringList frame_field_list = frame_fmps_playcount->fieldList();
|
||||
if (frame_field_list.size() > 1) {
|
||||
int playcount = TStringToQString(frame_field_list[1]).toInt();
|
||||
if (song->playcount() <= 0 && playcount > 0) {
|
||||
song->set_playcount(playcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_rating = TagLib::ID3v2::UserTextIdentificationFrame::find(file_mpeg->ID3v2Tag(), "FMPS_Rating")) {
|
||||
TagLib::StringList frame_field_list = frame_fmps_rating->fieldList();
|
||||
if (frame_field_list.size() > 1) {
|
||||
float rating = TStringToQString(frame_field_list[1]).toFloat();
|
||||
if (song->rating() <= 0 && rating > 0 && rating <= 1.0) {
|
||||
song->set_rating(rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.contains("POPM")) {
|
||||
const TagLib::ID3v2::PopularimeterFrame *frame = dynamic_cast<const TagLib::ID3v2::PopularimeterFrame*>(map["POPM"].front());
|
||||
if (frame) {
|
||||
if (song->playcount() <= 0 && frame->counter() > 0) {
|
||||
song->set_playcount(frame->counter());
|
||||
}
|
||||
if (song->rating() <= 0 && frame->rating() > 0) {
|
||||
song->set_rating(ConvertPOPMRating(frame->rating()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.contains("UFID")) {
|
||||
for (uint i = 0; i < map["UFID"].size(); ++i) {
|
||||
if (TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(map["UFID"][i])) {
|
||||
const TagLib::PropertyMap property_map = frame->asProperties();
|
||||
if (property_map.contains(kID3v2_MusicBrainz_RecordingID)) {
|
||||
TStringToStdString(property_map[kID3v2_MusicBrainz_RecordingID].toString(), song->mutable_musicbrainz_recording_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.contains("TXXX")) {
|
||||
for (uint i = 0; i < map["TXXX"].size(); ++i) {
|
||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>(map["TXXX"][i])) {
|
||||
const TagLib::StringList frame_field_list = frame->fieldList();
|
||||
if (frame_field_list.size() != 2) continue;
|
||||
if (frame->description() == kID3v2_AcoustID_ID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_AcoustID_Fingerprint) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_fingerprint());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_AlbumArtistID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_artist_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_ArtistID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_artist_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_OriginalArtistID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_artist_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_AlbumID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_OriginalAlbumID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_album_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_TrackID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_track_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_DiscID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_disc_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_ReleaseGroupID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_release_group_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_WorkID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_work_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file_mpeg->hasID3v2Tag()) {
|
||||
ParseID3v2Tag(file_mpeg->ID3v2Tag(), &disc, &compilation, song);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -658,12 +529,18 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
|||
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
||||
}
|
||||
|
||||
else if (TagLib::RIFF::WAV::File *file_wav = dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) {
|
||||
if (file_wav->hasID3v2Tag()) {
|
||||
ParseID3v2Tag(file_wav->ID3v2Tag(), &disc, &compilation, song);
|
||||
}
|
||||
}
|
||||
|
||||
else if (tag) {
|
||||
TStringToStdString(tag->comment(), song->mutable_comment());
|
||||
}
|
||||
|
||||
if (!disc.isEmpty()) {
|
||||
const qint64 i = disc.indexOf('/');
|
||||
const qint64 i = disc.indexOf(QLatin1Char('/'));
|
||||
if (i != -1) {
|
||||
// disc.right( i ).toInt() is total number of discs, we don't use this at the moment
|
||||
song->set_disc(disc.left(i).toInt());
|
||||
|
@ -677,7 +554,7 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
|||
// well, it wasn't set, but if the artist is VA assume it's a compilation
|
||||
const QString albumartist = QString::fromUtf8(song->albumartist().data(), static_cast<qint64>(song->albumartist().size()));
|
||||
const QString artist = QString::fromUtf8(song->artist().data(), static_cast<qint64>(song->artist().size()));
|
||||
if (artist.compare("various artists") == 0 || albumartist.compare("various artists") == 0) {
|
||||
if (artist.compare(QLatin1String("various artists")) == 0 || albumartist.compare(QLatin1String("various artists")) == 0) {
|
||||
song->set_compilation(true);
|
||||
}
|
||||
}
|
||||
|
@ -710,6 +587,139 @@ void TagReaderTagLib::TStringToStdString(const TagLib::String &tag, std::string
|
|||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
||||
|
||||
TagLib::ID3v2::FrameListMap map = tag->frameListMap();
|
||||
|
||||
if (map.contains("TPOS")) *disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
|
||||
if (map.contains("TCOM")) TStringToStdString(map["TCOM"].front()->toString(), song->mutable_composer());
|
||||
|
||||
// content group
|
||||
if (map.contains("TIT1")) TStringToStdString(map["TIT1"].front()->toString(), song->mutable_grouping());
|
||||
|
||||
// original artist/performer
|
||||
if (map.contains("TOPE")) TStringToStdString(map["TOPE"].front()->toString(), song->mutable_performer());
|
||||
|
||||
// Skip TPE1 (which is the artist) here because we already fetched it
|
||||
|
||||
// non-standard: Apple, Microsoft
|
||||
if (map.contains("TPE2")) TStringToStdString(map["TPE2"].front()->toString(), song->mutable_albumartist());
|
||||
|
||||
if (map.contains("TCMP")) *compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
|
||||
|
||||
if (map.contains("TDOR")) {
|
||||
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
|
||||
}
|
||||
else if (map.contains("TORY")) {
|
||||
song->set_originalyear(map["TORY"].front()->toString().substr(0, 4).toInt());
|
||||
}
|
||||
|
||||
if (map.contains("USLT")) {
|
||||
TStringToStdString(map["USLT"].front()->toString(), song->mutable_lyrics());
|
||||
}
|
||||
else if (map.contains("SYLT")) {
|
||||
TStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
||||
}
|
||||
|
||||
if (map.contains("APIC")) song->set_art_embedded(true);
|
||||
|
||||
// Find a suitable comment tag. For now we ignore iTunNORM comments.
|
||||
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
||||
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
|
||||
|
||||
if (frame && TStringToQString(frame->description()) != QStringLiteral("iTunNORM")) {
|
||||
TStringToStdString(frame->text(), song->mutable_comment());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_playcount = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Playcount")) {
|
||||
TagLib::StringList frame_field_list = frame_fmps_playcount->fieldList();
|
||||
if (frame_field_list.size() > 1) {
|
||||
int playcount = TStringToQString(frame_field_list[1]).toInt();
|
||||
if (song->playcount() <= 0 && playcount > 0) {
|
||||
song->set_playcount(playcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_rating = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Rating")) {
|
||||
TagLib::StringList frame_field_list = frame_fmps_rating->fieldList();
|
||||
if (frame_field_list.size() > 1) {
|
||||
float rating = TStringToQString(frame_field_list[1]).toFloat();
|
||||
if (song->rating() <= 0 && rating > 0 && rating <= 1.0) {
|
||||
song->set_rating(rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.contains("POPM")) {
|
||||
const TagLib::ID3v2::PopularimeterFrame *frame = dynamic_cast<const TagLib::ID3v2::PopularimeterFrame*>(map["POPM"].front());
|
||||
if (frame) {
|
||||
if (song->playcount() <= 0 && frame->counter() > 0) {
|
||||
song->set_playcount(frame->counter());
|
||||
}
|
||||
if (song->rating() <= 0 && frame->rating() > 0) {
|
||||
song->set_rating(ConvertPOPMRating(frame->rating()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.contains("UFID")) {
|
||||
for (uint i = 0; i < map["UFID"].size(); ++i) {
|
||||
if (TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(map["UFID"][i])) {
|
||||
const TagLib::PropertyMap property_map = frame->asProperties();
|
||||
if (property_map.contains(kID3v2_MusicBrainz_RecordingID)) {
|
||||
TStringToStdString(property_map[kID3v2_MusicBrainz_RecordingID].toString(), song->mutable_musicbrainz_recording_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.contains("TXXX")) {
|
||||
for (uint i = 0; i < map["TXXX"].size(); ++i) {
|
||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>(map["TXXX"][i])) {
|
||||
const TagLib::StringList frame_field_list = frame->fieldList();
|
||||
if (frame_field_list.size() != 2) continue;
|
||||
if (frame->description() == kID3v2_AcoustID_ID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_AcoustID_Fingerprint) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_fingerprint());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_AlbumArtistID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_artist_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_ArtistID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_artist_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_OriginalArtistID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_artist_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_AlbumID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_OriginalAlbumID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_album_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_TrackID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_track_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_DiscID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_disc_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_ReleaseGroupID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_release_group_id());
|
||||
}
|
||||
if (frame->description() == kID3v2_MusicBrainz_WorkID) {
|
||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_work_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
||||
|
||||
if (map.contains("COMPOSER")) TStringToStdString(map["COMPOSER"].front(), song->mutable_composer());
|
||||
|
@ -824,7 +834,7 @@ void TagReaderTagLib::SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comment
|
|||
vorbis_comment->addField("PERFORMER", StdStringToTaglibString(song.performer()), true);
|
||||
vorbis_comment->addField("GROUPING", StdStringToTaglibString(song.grouping()), true);
|
||||
vorbis_comment->addField("DISCNUMBER", QStringToTaglibString(song.disc() <= 0 ? QString() : QString::number(song.disc())), true);
|
||||
vorbis_comment->addField("COMPILATION", QStringToTaglibString(song.compilation() ? "1" : QString()), true);
|
||||
vorbis_comment->addField("COMPILATION", QStringToTaglibString(song.compilation() ? QStringLiteral("1") : QString()), true);
|
||||
|
||||
// Try to be coherent, the two forms are used but the first one is preferred
|
||||
|
||||
|
@ -849,19 +859,19 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
|||
|
||||
QStringList save_tags_options;
|
||||
if (save_tags) {
|
||||
save_tags_options << "tags";
|
||||
save_tags_options << QStringLiteral("tags");
|
||||
}
|
||||
if (save_playcount) {
|
||||
save_tags_options << "playcount";
|
||||
save_tags_options << QStringLiteral("playcount");
|
||||
}
|
||||
if (save_rating) {
|
||||
save_tags_options << "rating";
|
||||
save_tags_options << QStringLiteral("rating");
|
||||
}
|
||||
if (save_cover) {
|
||||
save_tags_options << "embedded cover";
|
||||
save_tags_options << QStringLiteral("embedded cover");
|
||||
}
|
||||
|
||||
qLog(Debug) << "Saving" << save_tags_options.join(", ") << "to" << filename;
|
||||
qLog(Debug) << "Saving" << save_tags_options.join(QStringLiteral(", ")) << "to" << filename;
|
||||
|
||||
const Cover cover = LoadCoverFromRequest(request);
|
||||
|
||||
|
@ -943,14 +953,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
|||
TagLib::ID3v2::Tag *tag = file_mpeg->ID3v2Tag(true);
|
||||
if (!tag) return false;
|
||||
if (save_tags) {
|
||||
SetTextFrame("TPOS", song.disc() <= 0 ? QString() : QString::number(song.disc()), tag);
|
||||
SetTextFrame("TCOM", song.composer().empty() ? std::string() : song.composer(), tag);
|
||||
SetTextFrame("TIT1", song.grouping().empty() ? std::string() : song.grouping(), tag);
|
||||
SetTextFrame("TOPE", song.performer().empty() ? std::string() : song.performer(), tag);
|
||||
// Skip TPE1 (which is the artist) here because we already set it
|
||||
SetTextFrame("TPE2", song.albumartist().empty() ? std::string() : song.albumartist(), tag);
|
||||
SetTextFrame("TCMP", song.compilation() ? QString::number(1) : QString(), tag);
|
||||
SetUnsyncLyricsFrame(song.lyrics().empty() ? std::string() : song.lyrics(), tag);
|
||||
SaveID3v2Tag(tag, song);
|
||||
}
|
||||
if (save_playcount) {
|
||||
SetPlaycount(tag, song);
|
||||
|
@ -959,7 +962,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
|||
SetRating(tag, song);
|
||||
}
|
||||
if (save_cover) {
|
||||
SetEmbeddedArt(file_mpeg, tag, cover.data, cover.mime_type);
|
||||
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -985,6 +988,22 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
|||
}
|
||||
}
|
||||
|
||||
else if (TagLib::RIFF::WAV::File *file_wav = dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) {
|
||||
TagLib::ID3v2::Tag *tag = file_wav->ID3v2Tag();
|
||||
if (save_tags) {
|
||||
SaveID3v2Tag(tag, song);
|
||||
}
|
||||
if (save_playcount) {
|
||||
SetPlaycount(tag, song);
|
||||
}
|
||||
if (save_rating) {
|
||||
SetRating(tag, song);
|
||||
}
|
||||
if (save_cover) {
|
||||
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
|
||||
// apart, so we keep specific behavior for some formats by adding another "else if" block above.
|
||||
if (!is_flac) {
|
||||
|
@ -1016,6 +1035,19 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
|||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SaveID3v2Tag(TagLib::ID3v2::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
||||
|
||||
SetTextFrame("TPOS", song.disc() <= 0 ? QString() : QString::number(song.disc()), tag);
|
||||
SetTextFrame("TCOM", song.composer().empty() ? std::string() : song.composer(), tag);
|
||||
SetTextFrame("TIT1", song.grouping().empty() ? std::string() : song.grouping(), tag);
|
||||
SetTextFrame("TOPE", song.performer().empty() ? std::string() : song.performer(), tag);
|
||||
// Skip TPE1 (which is the artist) here because we already set it
|
||||
SetTextFrame("TPE2", song.albumartist().empty() ? std::string() : song.albumartist(), tag);
|
||||
SetTextFrame("TCMP", song.compilation() ? QString::number(1) : QString(), tag);
|
||||
SetUnsyncLyricsFrame(song.lyrics().empty() ? std::string() : song.lyrics(), tag);
|
||||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
||||
|
||||
tag->setItem("album artist", TagLib::APE::Item("album artist", TagLib::StringList(song.albumartist().c_str())));
|
||||
|
@ -1278,9 +1310,7 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, con
|
|||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const {
|
||||
|
||||
(void)file_mp3;
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const {
|
||||
|
||||
// Remove existing covers
|
||||
TagLib::ID3v2::FrameList apiclist = tag->frameListMap()["APIC"];
|
||||
|
@ -1311,10 +1341,10 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::T
|
|||
}
|
||||
else {
|
||||
TagLib::MP4::CoverArt::Format cover_format = TagLib::MP4::CoverArt::Format::JPEG;
|
||||
if (mime_type == "image/jpeg") {
|
||||
if (mime_type == QStringLiteral("image/jpeg")) {
|
||||
cover_format = TagLib::MP4::CoverArt::Format::JPEG;
|
||||
}
|
||||
else if (mime_type == "image/png") {
|
||||
else if (mime_type == QStringLiteral("image/png")) {
|
||||
cover_format = TagLib::MP4::CoverArt::Format::PNG;
|
||||
}
|
||||
else {
|
||||
|
@ -1360,7 +1390,7 @@ bool TagReaderTagLib::SaveEmbeddedArt(const spb::tagreader::SaveEmbeddedArtReque
|
|||
else if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
||||
TagLib::ID3v2::Tag *tag = file_mp3->ID3v2Tag();
|
||||
if (!tag) return false;
|
||||
SetEmbeddedArt(file_mp3, tag, cover.data, cover.mime_type);
|
||||
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
||||
}
|
||||
|
||||
// MP4/AAC
|
||||
|
@ -1427,7 +1457,7 @@ void TagReaderTagLib::SetPlaycount(TagLib::APE::Tag *tag, const spb::tagreader::
|
|||
|
||||
void TagReaderTagLib::SetPlaycount(TagLib::ID3v2::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
||||
|
||||
SetUserTextFrame("FMPS_Playcount", QString::number(song.playcount()), tag);
|
||||
SetUserTextFrame(QStringLiteral("FMPS_Playcount"), QString::number(song.playcount()), tag);
|
||||
TagLib::ID3v2::PopularimeterFrame *frame = GetPOPMFrameFromTag(tag);
|
||||
if (frame) {
|
||||
frame->setCounter(song.playcount());
|
||||
|
@ -1546,7 +1576,7 @@ void TagReaderTagLib::SetRating(TagLib::APE::Tag *tag, const spb::tagreader::Son
|
|||
|
||||
void TagReaderTagLib::SetRating(TagLib::ID3v2::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
||||
|
||||
SetUserTextFrame("FMPS_Rating", QString::number(song.rating()), tag);
|
||||
SetUserTextFrame(QStringLiteral("FMPS_Rating"), QString::number(song.rating()), tag);
|
||||
TagLib::ID3v2::PopularimeterFrame *frame = GetPOPMFrameFromTag(tag);
|
||||
if (frame) {
|
||||
frame->setRating(ConvertToPOPMRating(song.rating()));
|
||||
|
|
|
@ -68,10 +68,12 @@ class TagReaderTagLib : public TagReaderBase {
|
|||
private:
|
||||
spb::tagreader::SongMetadata_FileType GuessFileType(TagLib::FileRef *fileref) const;
|
||||
|
||||
void ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
||||
void ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
||||
void ParseAPETag(const TagLib::APE::ItemListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
||||
|
||||
void SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comment, const spb::tagreader::SongMetadata &song) const;
|
||||
void SaveID3v2Tag(TagLib::ID3v2::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
||||
void SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
||||
|
||||
void SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const;
|
||||
|
@ -98,7 +100,7 @@ class TagReaderTagLib : public TagReaderBase {
|
|||
|
||||
void SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -62,7 +62,7 @@ bool TagReaderWorker::HandleMessage(const spb::tagreader::Message &message, spb:
|
|||
return success;
|
||||
}
|
||||
else if (message.has_read_file_request()) {
|
||||
const QString filename = QString::fromUtf8(message.read_file_request().filename().data(), static_cast<qint64>(static_cast<qint64>(message.read_file_request().filename().size())));
|
||||
const QString filename = QString::fromUtf8(message.read_file_request().filename().data(), static_cast<qint64>(message.read_file_request().filename().size()));
|
||||
bool success = reader->ReadFile(filename, reply.mutable_read_file_response()->mutable_metadata());
|
||||
return success;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ bool TagReaderWorker::HandleMessage(const spb::tagreader::Message &message, spb:
|
|||
return success;
|
||||
}
|
||||
else if (message.has_load_embedded_art_request()) {
|
||||
const QString filename = QString::fromUtf8(message.load_embedded_art_request().filename().data(), static_cast<qint64>(static_cast<qint64>(message.load_embedded_art_request().filename().size())));
|
||||
const QString filename = QString::fromUtf8(message.load_embedded_art_request().filename().data(), static_cast<qint64>(message.load_embedded_art_request().filename().size()));
|
||||
QByteArray data = reader->LoadEmbeddedArt(filename);
|
||||
reply.mutable_load_embedded_art_response()->set_data(data.constData(), data.size());
|
||||
return true;
|
||||
|
@ -83,7 +83,7 @@ bool TagReaderWorker::HandleMessage(const spb::tagreader::Message &message, spb:
|
|||
return success;
|
||||
}
|
||||
else if (message.has_save_song_playcount_to_file_request()) {
|
||||
const QString filename = QString::fromUtf8(message.save_song_playcount_to_file_request().filename().data(), static_cast<qint64>(static_cast<qint64>(message.save_song_playcount_to_file_request().filename().size())));
|
||||
const QString filename = QString::fromUtf8(message.save_song_playcount_to_file_request().filename().data(), static_cast<qint64>(message.save_song_playcount_to_file_request().filename().size()));
|
||||
bool success = reader->SaveSongPlaycountToFile(filename, message.save_song_playcount_to_file_request().metadata());
|
||||
reply.mutable_save_song_playcount_to_file_response()->set_success(success);
|
||||
return success;
|
||||
|
|
|
@ -24,6 +24,7 @@ set(SOURCES
|
|||
core/networktimeouts.cpp
|
||||
core/networkproxyfactory.cpp
|
||||
core/qtfslistener.cpp
|
||||
core/settings.cpp
|
||||
core/settingsprovider.cpp
|
||||
core/signalchecker.cpp
|
||||
core/song.cpp
|
||||
|
@ -170,7 +171,6 @@ set(SOURCES
|
|||
covermanager/deezercoverprovider.cpp
|
||||
covermanager/qobuzcoverprovider.cpp
|
||||
covermanager/musixmatchcoverprovider.cpp
|
||||
covermanager/spotifycoverprovider.cpp
|
||||
covermanager/opentidalcoverprovider.cpp
|
||||
|
||||
lyrics/lyricsproviders.cpp
|
||||
|
@ -197,6 +197,7 @@ set(SOURCES
|
|||
settings/settingspage.cpp
|
||||
settings/behavioursettingspage.cpp
|
||||
settings/collectionsettingspage.cpp
|
||||
settings/collectionsettingsdirectorymodel.cpp
|
||||
settings/backendsettingspage.cpp
|
||||
settings/playlistsettingspage.cpp
|
||||
settings/scrobblersettingspage.cpp
|
||||
|
@ -307,6 +308,7 @@ set(HEADERS
|
|||
core/threadsafenetworkdiskcache.h
|
||||
core/networktimeouts.h
|
||||
core/qtfslistener.h
|
||||
core/settings.h
|
||||
core/songloader.h
|
||||
core/tagreaderclient.h
|
||||
core/taskmanager.h
|
||||
|
@ -416,7 +418,6 @@ set(HEADERS
|
|||
covermanager/deezercoverprovider.h
|
||||
covermanager/qobuzcoverprovider.h
|
||||
covermanager/musixmatchcoverprovider.h
|
||||
covermanager/spotifycoverprovider.h
|
||||
covermanager/opentidalcoverprovider.h
|
||||
|
||||
lyrics/lyricsproviders.h
|
||||
|
@ -439,6 +440,7 @@ set(HEADERS
|
|||
settings/settingspage.h
|
||||
settings/behavioursettingspage.h
|
||||
settings/collectionsettingspage.h
|
||||
settings/collectionsettingsdirectorymodel.h
|
||||
settings/backendsettingspage.h
|
||||
settings/playlistsettingspage.h
|
||||
settings/scrobblersettingspage.h
|
||||
|
@ -488,6 +490,7 @@ set(HEADERS
|
|||
widgets/qsearchfield.h
|
||||
widgets/ratingwidget.h
|
||||
widgets/forcescrollperpixel.h
|
||||
widgets/resizabletextedit.h
|
||||
|
||||
osd/osdbase.h
|
||||
osd/osdpretty.h
|
||||
|
@ -898,6 +901,25 @@ optional_source(HAVE_TIDAL
|
|||
settings/tidalsettingspage.ui
|
||||
)
|
||||
|
||||
optional_source(HAVE_SPOTIFY
|
||||
SOURCES
|
||||
spotify/spotifyservice.cpp
|
||||
spotify/spotifybaserequest.cpp
|
||||
spotify/spotifyrequest.cpp
|
||||
spotify/spotifyfavoriterequest.cpp
|
||||
settings/spotifysettingspage.cpp
|
||||
covermanager/spotifycoverprovider.cpp
|
||||
HEADERS
|
||||
spotify/spotifyservice.h
|
||||
spotify/spotifybaserequest.h
|
||||
spotify/spotifyrequest.h
|
||||
spotify/spotifyfavoriterequest.h
|
||||
settings/spotifysettingspage.h
|
||||
covermanager/spotifycoverprovider.h
|
||||
UI
|
||||
settings/spotifysettingspage.ui
|
||||
)
|
||||
|
||||
optional_source(HAVE_QOBUZ
|
||||
SOURCES
|
||||
qobuz/qobuzservice.cpp
|
||||
|
|
|
@ -108,7 +108,7 @@ void AnalyzerBase::paintEvent(QPaintEvent *e) {
|
|||
p.fillRect(e->rect(), palette().color(QPalette::Window));
|
||||
|
||||
switch (engine_->state()) {
|
||||
case EngineBase::State::Playing: {
|
||||
case EngineBase::State::Playing:{
|
||||
const EngineBase::Scope &thescope = engine_->scope(timeout_);
|
||||
int i = 0;
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include "core/logging.h"
|
||||
#include "core/shared_ptr.h"
|
||||
#include "core/settings.h"
|
||||
#include "engine/enginebase.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
@ -178,9 +179,9 @@ void AnalyzerContainer::ChangeFramerate(int new_framerate) {
|
|||
|
||||
void AnalyzerContainer::Load() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
QString type = s.value("type", "BlockAnalyzer").toString();
|
||||
QString type = s.value("type", QStringLiteral("BlockAnalyzer")).toString();
|
||||
current_framerate_ = s.value(kSettingsFramerate, kMediumFramerate).toInt();
|
||||
s.endGroup();
|
||||
|
||||
|
@ -191,7 +192,7 @@ void AnalyzerContainer::Load() {
|
|||
}
|
||||
else {
|
||||
for (int i = 0; i < analyzer_types_.count(); ++i) {
|
||||
if (type == analyzer_types_[i]->className()) {
|
||||
if (type == QString::fromLatin1(analyzer_types_[i]->className())) {
|
||||
ChangeAnalyzer(i);
|
||||
actions_[i]->setChecked(true);
|
||||
break;
|
||||
|
@ -215,7 +216,7 @@ void AnalyzerContainer::SaveFramerate(const int framerate) {
|
|||
|
||||
// For now, framerate is common for all analyzers. Maybe each analyzer should have its own framerate?
|
||||
current_framerate_ = framerate;
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue(kSettingsFramerate, current_framerate_);
|
||||
s.endGroup();
|
||||
|
@ -224,9 +225,9 @@ void AnalyzerContainer::SaveFramerate(const int framerate) {
|
|||
|
||||
void AnalyzerContainer::Save() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("type", current_analyzer_ ? current_analyzer_->metaObject()->className() : QVariant());
|
||||
s.setValue("type", current_analyzer_ ? QString::fromLatin1(current_analyzer_->metaObject()->className()) : QVariant());
|
||||
s.endGroup();
|
||||
|
||||
}
|
||||
|
|
|
@ -266,12 +266,12 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, int amount) {
|
|||
|
||||
// value is the best measure of contrast
|
||||
// if there is enough difference in value already, return fg unchanged
|
||||
if (dv > static_cast<int>(amount)) return fg;
|
||||
if (dv > amount) return fg;
|
||||
|
||||
int ds = abs(bs - fs);
|
||||
|
||||
// saturation is good enough too. But not as good. TODO adapt this a little
|
||||
if (ds > static_cast<int>(amount)) return fg;
|
||||
if (ds > amount) return fg;
|
||||
|
||||
int dh = abs(bh - fh);
|
||||
|
||||
|
@ -294,7 +294,7 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, int amount) {
|
|||
// low saturation on a low saturation is sad
|
||||
const int tmp = 50 - fs;
|
||||
fs = 50;
|
||||
if (static_cast<int>(amount) > tmp) {
|
||||
if (amount > tmp) {
|
||||
amount -= tmp;
|
||||
}
|
||||
else {
|
||||
|
@ -310,25 +310,25 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, int amount) {
|
|||
if (amount > 0) adjustToLimits(bs, fs, amount);
|
||||
|
||||
// see if we need to adjust the hue
|
||||
if (static_cast<int>(amount) > 0)
|
||||
fh += static_cast<int>(amount); // cycles around;
|
||||
if (amount > 0)
|
||||
fh += amount; // cycles around;
|
||||
|
||||
return QColor::fromHsv(fh, fs, fv);
|
||||
}
|
||||
|
||||
if (fv > bv && bv > static_cast<int>(amount)) {
|
||||
return QColor::fromHsv(fh, fs, bv - static_cast<int>(amount));
|
||||
if (fv > bv && bv > amount) {
|
||||
return QColor::fromHsv(fh, fs, bv - amount);
|
||||
}
|
||||
|
||||
if (fv < bv && fv > static_cast<int>(amount)) {
|
||||
if (fv < bv && fv > amount) {
|
||||
return QColor::fromHsv(fh, fs, fv - amount);
|
||||
}
|
||||
|
||||
if (fv > bv && (255 - fv > static_cast<int>(amount))) {
|
||||
if (fv > bv && (255 - fv > amount)) {
|
||||
return QColor::fromHsv(fh, fs, fv + amount);
|
||||
}
|
||||
|
||||
if (fv < bv && (255 - bv > static_cast<int>(amount))) {
|
||||
if (fv < bv && (255 - bv > amount)) {
|
||||
return QColor::fromHsv(fh, fs, bv + amount);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ void BoomAnalyzer::resizeEvent(QResizeEvent *e) {
|
|||
bands_ = qMin(static_cast<int>(static_cast<double>(width() + 1) / (kColumnWidth + 1)) + 1, kMaxBandCount);
|
||||
scope_.resize(bands_);
|
||||
|
||||
F_ = static_cast<double>(HEIGHT) / (log10(256) * static_cast<double>(1.1) /*<- max. amplitude*/);
|
||||
F_ = static_cast<double>(HEIGHT) / (log10(256) * 1.1 /*<- max. amplitude*/);
|
||||
|
||||
barPixmap_ = QPixmap(kColumnWidth - 2, HEIGHT);
|
||||
canvas_ = QPixmap(size());
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <QVector>
|
||||
#include <QtMath>
|
||||
|
||||
FHT::FHT(uint n) : num_((n < 3) ? 0 : 1 << n), exp2_((n < 3) ? static_cast<int>(-1) : static_cast<int>(n)) {
|
||||
FHT::FHT(uint n) : num_((n < 3) ? 0 : 1 << n), exp2_((n < 3) ? -1 : static_cast<int>(n)) {
|
||||
|
||||
if (n > 3) {
|
||||
buf_vector_.resize(num_);
|
||||
|
|
|
@ -65,8 +65,8 @@ RainbowAnalyzer::RainbowAnalyzer(const RainbowType rbtype, QWidget *parent)
|
|||
background_brush_(QColor(0x0f, 0x43, 0x73)) {
|
||||
|
||||
rainbowtype = rbtype;
|
||||
cat_dash_[0] = QPixmap(":/pictures/nyancat.png");
|
||||
cat_dash_[1] = QPixmap(":/pictures/rainbowdash.png");
|
||||
cat_dash_[0] = QPixmap(QStringLiteral(":/pictures/nyancat.png"));
|
||||
cat_dash_[1] = QPixmap(QStringLiteral(":/pictures/rainbowdash.png"));
|
||||
memset(history_, 0, sizeof(history_));
|
||||
|
||||
for (int i = 0; i < kRainbowBands; ++i) {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "core/thread.h"
|
||||
#include "core/song.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/threadutils.h"
|
||||
#include "collection.h"
|
||||
#include "collectionwatcher.h"
|
||||
|
@ -69,7 +70,7 @@ SCollection::SCollection(Application *app, QObject *parent)
|
|||
backend()->moveToThread(app->database()->thread());
|
||||
qLog(Debug) << &*backend_ << "moved to thread" << app->database()->thread();
|
||||
|
||||
backend_->Init(app->database(), app->task_manager(), Song::Source::Collection, kSongsTable, kFtsTable, kDirsTable, kSubdirsTable);
|
||||
backend_->Init(app->database(), app->task_manager(), Song::Source::Collection, QLatin1String(kSongsTable), QLatin1String(kFtsTable), QLatin1String(kDirsTable), QLatin1String(kSubdirsTable));
|
||||
|
||||
model_ = new CollectionModel(backend_, app_, this);
|
||||
|
||||
|
@ -107,7 +108,7 @@ void SCollection::Init() {
|
|||
watcher_->set_task_manager(app_->task_manager());
|
||||
|
||||
QObject::connect(&*backend_, &CollectionBackend::Error, this, &SCollection::Error);
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryDiscovered, watcher_, &CollectionWatcher::AddDirectory);
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory);
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, watcher_, &CollectionWatcher::RemoveDirectory);
|
||||
QObject::connect(&*backend_, &CollectionBackend::SongsRatingChanged, this, &SCollection::SongsRatingChanged);
|
||||
QObject::connect(&*backend_, &CollectionBackend::SongsStatisticsChanged, this, &SCollection::SongsPlaycountChanged);
|
||||
|
@ -179,7 +180,7 @@ void SCollection::ReloadSettings() {
|
|||
watcher_->ReloadSettingsAsync();
|
||||
model_->ReloadSettings();
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
save_playcounts_to_files_ = s.value("save_playcounts", false).toBool();
|
||||
save_ratings_to_files_ = s.value("save_ratings", false).toBool();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -132,8 +132,8 @@ class CollectionBackendInterface : public QObject {
|
|||
virtual Song GetSongByUrl(const QUrl &url, const qint64 beginning = 0) = 0;
|
||||
virtual Song GetSongByUrlAndTrack(const QUrl &url, const int track) = 0;
|
||||
|
||||
virtual void AddDirectory(const QString &path) = 0;
|
||||
virtual void RemoveDirectory(const CollectionDirectory &dir) = 0;
|
||||
virtual void AddDirectoryAsync(const QString &path) = 0;
|
||||
virtual void RemoveDirectoryAsync(const CollectionDirectory &dir) = 0;
|
||||
};
|
||||
|
||||
class CollectionBackend : public CollectionBackendInterface {
|
||||
|
@ -206,8 +206,8 @@ class CollectionBackend : public CollectionBackendInterface {
|
|||
Song GetSongByUrl(const QUrl &url, qint64 beginning = 0) override;
|
||||
Song GetSongByUrlAndTrack(const QUrl &url, const int track) override;
|
||||
|
||||
void AddDirectory(const QString &path) override;
|
||||
void RemoveDirectory(const CollectionDirectory &dir) override;
|
||||
void AddDirectoryAsync(const QString &path) override;
|
||||
void RemoveDirectoryAsync(const CollectionDirectory &dir) override;
|
||||
|
||||
bool ExecCollectionQuery(CollectionQuery *query, SongList &songs);
|
||||
bool ExecCollectionQuery(CollectionQuery *query, SongMap &songs);
|
||||
|
@ -239,6 +239,8 @@ class CollectionBackend : public CollectionBackendInterface {
|
|||
void UpdateTotalSongCount();
|
||||
void UpdateTotalArtistCount();
|
||||
void UpdateTotalAlbumCount();
|
||||
void AddDirectory(const QString &path);
|
||||
void RemoveDirectory(const CollectionDirectory &dir);
|
||||
void AddOrUpdateSongs(const SongList &songs);
|
||||
void UpdateSongsBySongID(const SongMap &new_songs);
|
||||
void UpdateMTimesOnly(const SongList &songs);
|
||||
|
@ -250,7 +252,7 @@ class CollectionBackend : public CollectionBackendInterface {
|
|||
void UpdateManualAlbumArt(const QString &effective_albumartist, const QString &album, const QUrl &art_manual);
|
||||
void UnsetAlbumArt(const QString &effective_albumartist, const QString &album);
|
||||
void ClearAlbumArt(const QString &effective_albumartist, const QString &album, const bool art_unset);
|
||||
void ForceCompilation(const QString &album, const QList<QString> &artists, const bool on);
|
||||
void ForceCompilation(const QString &album, const QStringList &artists, const bool on);
|
||||
void IncrementPlayCount(const int id);
|
||||
void IncrementSkipCount(const int id, const float progress);
|
||||
void ResetPlayStatistics(const int id, const bool save_tags = false);
|
||||
|
@ -270,7 +272,7 @@ class CollectionBackend : public CollectionBackendInterface {
|
|||
void ExpireSongs(const int directory_id, const int expire_unavailable_songs_days);
|
||||
|
||||
signals:
|
||||
void DirectoryDiscovered(const CollectionDirectory &dir, const CollectionSubdirectoryList &subdir);
|
||||
void DirectoryAdded(const CollectionDirectory &dir, const CollectionSubdirectoryList &subdir);
|
||||
void DirectoryDeleted(const CollectionDirectory &dir);
|
||||
|
||||
void SongsDiscovered(const SongList &songs);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -41,15 +42,18 @@ using std::make_shared;
|
|||
|
||||
CollectionDirectoryModel::CollectionDirectoryModel(SharedPtr<CollectionBackend> backend, QObject *parent)
|
||||
: QStandardItemModel(parent),
|
||||
dir_icon_(IconLoader::Load("document-open-folder")),
|
||||
dir_icon_(IconLoader::Load(QStringLiteral("document-open-folder"))),
|
||||
backend_(backend) {
|
||||
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryDiscovered, this, &CollectionDirectoryModel::DirectoryDiscovered);
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, this, &CollectionDirectoryModel::DirectoryDeleted);
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, this, &CollectionDirectoryModel::AddDirectory);
|
||||
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, this, &CollectionDirectoryModel::RemoveDirectory);
|
||||
|
||||
}
|
||||
|
||||
void CollectionDirectoryModel::DirectoryDiscovered(const CollectionDirectory &dir) {
|
||||
void CollectionDirectoryModel::AddDirectory(const CollectionDirectory &dir) {
|
||||
|
||||
directories_.insert(dir.id, dir);
|
||||
paths_.append(dir.path);
|
||||
|
||||
QStandardItem *item = new QStandardItem(dir.path);
|
||||
item->setData(dir.id, kIdRole);
|
||||
|
@ -59,7 +63,10 @@ void CollectionDirectoryModel::DirectoryDiscovered(const CollectionDirectory &di
|
|||
|
||||
}
|
||||
|
||||
void CollectionDirectoryModel::DirectoryDeleted(const CollectionDirectory &dir) {
|
||||
void CollectionDirectoryModel::RemoveDirectory(const CollectionDirectory &dir) {
|
||||
|
||||
directories_.remove(dir.id);
|
||||
paths_.removeAll(dir.path);
|
||||
|
||||
for (int i = 0; i < rowCount(); ++i) {
|
||||
if (item(i, 0)->data(kIdRole).toInt() == dir.id) {
|
||||
|
@ -71,26 +78,6 @@ void CollectionDirectoryModel::DirectoryDeleted(const CollectionDirectory &dir)
|
|||
|
||||
}
|
||||
|
||||
void CollectionDirectoryModel::AddDirectory(const QString &path) {
|
||||
|
||||
if (!backend_) return;
|
||||
|
||||
backend_->AddDirectory(path);
|
||||
|
||||
}
|
||||
|
||||
void CollectionDirectoryModel::RemoveDirectory(const QModelIndex &idx) {
|
||||
|
||||
if (!backend_ || !idx.isValid()) return;
|
||||
|
||||
CollectionDirectory dir;
|
||||
dir.path = idx.data().toString();
|
||||
dir.id = idx.data(kIdRole).toInt();
|
||||
|
||||
backend_->RemoveDirectory(dir);
|
||||
|
||||
}
|
||||
|
||||
QVariant CollectionDirectoryModel::data(const QModelIndex &idx, int role) const {
|
||||
|
||||
switch (role) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -26,15 +27,17 @@
|
|||
#include <QObject>
|
||||
#include <QStandardItemModel>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QIcon>
|
||||
|
||||
#include "core/shared_ptr.h"
|
||||
#include "collectiondirectory.h"
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
struct CollectionDirectory;
|
||||
class CollectionBackend;
|
||||
class MusicStorage;
|
||||
|
||||
|
@ -44,22 +47,24 @@ class CollectionDirectoryModel : public QStandardItemModel {
|
|||
public:
|
||||
explicit CollectionDirectoryModel(SharedPtr<CollectionBackend> collection_backend, QObject *parent = nullptr);
|
||||
|
||||
// To be called by GUIs
|
||||
void AddDirectory(const QString &path);
|
||||
void RemoveDirectory(const QModelIndex &idx);
|
||||
|
||||
QVariant data(const QModelIndex &idx, int role) const override;
|
||||
|
||||
SharedPtr<CollectionBackend> backend() const { return backend_; }
|
||||
|
||||
QMap<int, CollectionDirectory> directories() const { return directories_; }
|
||||
QStringList paths() const { return paths_; }
|
||||
|
||||
private slots:
|
||||
// To be called by the backend
|
||||
void DirectoryDiscovered(const CollectionDirectory &directories);
|
||||
void DirectoryDeleted(const CollectionDirectory &directories);
|
||||
void AddDirectory(const CollectionDirectory &directory);
|
||||
void RemoveDirectory(const CollectionDirectory &directory);
|
||||
|
||||
private:
|
||||
static const int kIdRole = Qt::UserRole + 1;
|
||||
|
||||
QIcon dir_icon_;
|
||||
SharedPtr<CollectionBackend> backend_;
|
||||
QMap<int, CollectionDirectory> directories_;
|
||||
QStringList paths_;
|
||||
QList<SharedPtr<MusicStorage>> storage_;
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ CollectionFilterOptions::CollectionFilterOptions() : filter_mode_(FilterMode::Al
|
|||
bool CollectionFilterOptions::Matches(const Song &song) const {
|
||||
|
||||
if (max_age_ != -1) {
|
||||
const qint64 cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - max_age_;
|
||||
const qint64 cutoff = QDateTime::currentSecsSinceEpoch() - max_age_;
|
||||
if (song.ctime() <= cutoff) return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include <QApplication>
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "core/iconloader.h"
|
||||
#include "core/song.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/settings.h"
|
||||
#include "collectionfilteroptions.h"
|
||||
#include "collectionmodel.h"
|
||||
#include "savedgroupingmanager.h"
|
||||
|
@ -72,34 +74,34 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
|
|||
|
||||
ui_->setupUi(this);
|
||||
|
||||
QString available_fields = Song::kFtsColumns.join(", ").replace(QRegularExpression("\\bfts"), "");
|
||||
available_fields += QString(", ") + Song::kNumericalColumns.join(", ");
|
||||
QString available_fields = Song::kFtsColumns.join(QStringLiteral(", ")).replace(QRegularExpression(QStringLiteral("\\bfts")), QLatin1String(""));
|
||||
available_fields += QStringLiteral(", ") + Song::kNumericalColumns.join(QStringLiteral(", "));
|
||||
|
||||
ui_->search_field->setToolTip(
|
||||
QString("<html><head/><body><p>") +
|
||||
QStringLiteral("<html><head/><body><p>") +
|
||||
tr("Prefix a word with a field name to limit the search to that field, e.g.:") +
|
||||
QString(" ") +
|
||||
QString("<span style=\"font-weight:600;\">") +
|
||||
QStringLiteral(" ") +
|
||||
QStringLiteral("<span style=\"font-weight:600;\">") +
|
||||
tr("artist") +
|
||||
QString(":</span><span style=\"font-style:italic;\">Strawbs</span> ") +
|
||||
tr("searches the collection for all artists that contain the word %1. ").arg("Strawbs") +
|
||||
QString("</p><p>") +
|
||||
QStringLiteral(":</span><span style=\"font-style:italic;\">Strawbs</span> ") +
|
||||
tr("searches the collection for all artists that contain the word %1. ").arg(QStringLiteral("Strawbs")) +
|
||||
QStringLiteral("</p><p>") +
|
||||
tr("Search terms for numerical fields can be prefixed with %1 or %2 to refine the search, e.g.: ")
|
||||
.arg(" =, !=, <, >, <=", ">=") +
|
||||
QString("<span style=\"font-weight:600;\">") +
|
||||
.arg(QStringLiteral(" =, !=, <, >, <="), QStringLiteral(">=")) +
|
||||
QStringLiteral("<span style=\"font-weight:600;\">") +
|
||||
tr("rating") +
|
||||
QString("</span>") +
|
||||
QString(":>=") +
|
||||
QString("<span style=\"font-weight:italic;\">4</span>") +
|
||||
QStringLiteral("</span>") +
|
||||
QStringLiteral(":>=") +
|
||||
QStringLiteral("<span style=\"font-weight:italic;\">4</span>") +
|
||||
|
||||
QString("</p><p><span style=\"font-weight:600;\">") +
|
||||
QStringLiteral("</p><p><span style=\"font-weight:600;\">") +
|
||||
tr("Available fields") +
|
||||
QString(": ") +
|
||||
QString("</span>") +
|
||||
QString("<span style=\"font-style:italic;\">") +
|
||||
QStringLiteral(": ") +
|
||||
QStringLiteral("</span>") +
|
||||
QStringLiteral("<span style=\"font-style:italic;\">") +
|
||||
available_fields +
|
||||
QString("</span>.") +
|
||||
QString("</p></body></html>")
|
||||
QStringLiteral("</span>.") +
|
||||
QStringLiteral("</p></body></html>")
|
||||
);
|
||||
|
||||
QObject::connect(ui_->search_field, &QSearchField::returnPressed, this, &CollectionFilterWidget::ReturnPressed);
|
||||
|
@ -109,7 +111,7 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
|
|||
filter_delay_->setSingleShot(true);
|
||||
|
||||
// Icons
|
||||
ui_->options->setIcon(IconLoader::Load("configure"));
|
||||
ui_->options->setIcon(IconLoader::Load(QStringLiteral("configure")));
|
||||
|
||||
// Filter by age
|
||||
QActionGroup *filter_age_group = new QActionGroup(this);
|
||||
|
@ -160,7 +162,7 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
|
|||
QObject::disconnect(model_, nullptr, this, nullptr);
|
||||
QObject::disconnect(model_, nullptr, group_by_dialog_, nullptr);
|
||||
QObject::disconnect(group_by_dialog_, nullptr, model_, nullptr);
|
||||
QList<QAction*> filter_ages = filter_ages_.keys();
|
||||
const QList<QAction*> filter_ages = filter_ages_.keys();
|
||||
for (QAction *action : filter_ages) {
|
||||
QObject::disconnect(action, &QAction::triggered, model_, nullptr);
|
||||
}
|
||||
|
@ -173,7 +175,7 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
|
|||
QObject::connect(model_, &CollectionModel::GroupingChanged, this, &CollectionFilterWidget::GroupingChanged);
|
||||
QObject::connect(group_by_dialog_, &GroupByDialog::Accepted, model_, &CollectionModel::SetGroupBy);
|
||||
|
||||
QList<QAction*> filter_ages = filter_ages_.keys();
|
||||
const QList<QAction*> filter_ages = filter_ages_.keys();
|
||||
for (QAction *action : filter_ages) {
|
||||
int age = filter_ages_[action];
|
||||
QObject::connect(action, &QAction::triggered, this, [this, age]() { model_->SetFilterAge(age); } );
|
||||
|
@ -181,7 +183,7 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
|
|||
|
||||
// Load settings
|
||||
if (!settings_group_.isEmpty()) {
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(settings_group_);
|
||||
int version = 0;
|
||||
if (s.contains(group_by_version())) version = s.value(group_by_version(), 0).toInt();
|
||||
|
@ -217,7 +219,7 @@ void CollectionFilterWidget::SetSettingsPrefix(const QString &prefix) {
|
|||
|
||||
void CollectionFilterWidget::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(AppearanceSettingsPage::kSettingsGroup);
|
||||
int iconsize = s.value(AppearanceSettingsPage::kIconSizeConfigureButtons, 20).toInt();
|
||||
s.endGroup();
|
||||
|
@ -229,10 +231,10 @@ void CollectionFilterWidget::ReloadSettings() {
|
|||
QString CollectionFilterWidget::group_by_version() const {
|
||||
|
||||
if (settings_prefix_.isEmpty()) {
|
||||
return "group_by_version";
|
||||
return QStringLiteral("group_by_version");
|
||||
}
|
||||
else {
|
||||
return QString("%1_group_by_version").arg(settings_prefix_);
|
||||
return QStringLiteral("%1_group_by_version").arg(settings_prefix_);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -240,10 +242,10 @@ QString CollectionFilterWidget::group_by_version() const {
|
|||
QString CollectionFilterWidget::group_by_key() const {
|
||||
|
||||
if (settings_prefix_.isEmpty()) {
|
||||
return "group_by";
|
||||
return QStringLiteral("group_by");
|
||||
}
|
||||
else {
|
||||
return QString("%1_group_by").arg(settings_prefix_);
|
||||
return QStringLiteral("%1_group_by").arg(settings_prefix_);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -253,10 +255,10 @@ QString CollectionFilterWidget::group_by_key(const int number) const { return gr
|
|||
QString CollectionFilterWidget::separate_albums_by_grouping_key() const {
|
||||
|
||||
if (settings_prefix_.isEmpty()) {
|
||||
return "separate_albums_by_grouping";
|
||||
return QStringLiteral("separate_albums_by_grouping");
|
||||
}
|
||||
else {
|
||||
return QString("%1_separate_albums_by_grouping").arg(settings_prefix_);
|
||||
return QStringLiteral("%1_separate_albums_by_grouping").arg(settings_prefix_);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -306,13 +308,13 @@ QActionGroup *CollectionFilterWidget::CreateGroupByActions(const QString &saved_
|
|||
ret->addAction(sep1);
|
||||
|
||||
// Read saved groupings
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(saved_groupings_settings_group);
|
||||
int version = s.value("version").toInt();
|
||||
if (version == 1) {
|
||||
QStringList saved = s.childKeys();
|
||||
for (int i = 0; i < saved.size(); ++i) {
|
||||
if (saved.at(i) == "version") continue;
|
||||
if (saved.at(i) == QStringLiteral("version")) continue;
|
||||
QByteArray bytes = s.value(saved.at(i)).toByteArray();
|
||||
QDataStream ds(&bytes, QIODevice::ReadOnly);
|
||||
CollectionModel::Grouping g;
|
||||
|
@ -323,7 +325,7 @@ QActionGroup *CollectionFilterWidget::CreateGroupByActions(const QString &saved_
|
|||
else {
|
||||
QStringList saved = s.childKeys();
|
||||
for (int i = 0; i < saved.size(); ++i) {
|
||||
if (saved.at(i) == "version") continue;
|
||||
if (saved.at(i) == QStringLiteral("version")) continue;
|
||||
s.remove(saved.at(i));
|
||||
}
|
||||
}
|
||||
|
@ -361,17 +363,17 @@ void CollectionFilterWidget::SaveGroupBy() {
|
|||
|
||||
qLog(Debug) << "Saving current grouping to" << name;
|
||||
|
||||
QSettings s;
|
||||
if (settings_group_.isEmpty() || settings_group_ == CollectionSettingsPage::kSettingsGroup) {
|
||||
Settings s;
|
||||
if (settings_group_.isEmpty() || settings_group_ == QLatin1String(CollectionSettingsPage::kSettingsGroup)) {
|
||||
s.beginGroup(SavedGroupingManager::kSavedGroupingsSettingsGroup);
|
||||
}
|
||||
else {
|
||||
s.beginGroup(QString(SavedGroupingManager::kSavedGroupingsSettingsGroup) + "_" + settings_group_);
|
||||
s.beginGroup(QLatin1String(SavedGroupingManager::kSavedGroupingsSettingsGroup) + QLatin1Char('_') + settings_group_);
|
||||
}
|
||||
QByteArray buffer;
|
||||
QDataStream datastream(&buffer, QIODevice::WriteOnly);
|
||||
datastream << model_->GetGroupBy();
|
||||
s.setValue("version", "1");
|
||||
s.setValue("version", QStringLiteral("1"));
|
||||
s.setValue(name, buffer);
|
||||
s.endGroup();
|
||||
|
||||
|
@ -425,7 +427,7 @@ void CollectionFilterWidget::GroupByClicked(QAction *action) {
|
|||
void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping g, const bool separate_albums_by_grouping) {
|
||||
|
||||
if (!settings_group_.isEmpty()) {
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(settings_group_);
|
||||
s.setValue(group_by_version(), 1);
|
||||
s.setValue(group_by_key(1), static_cast<int>(g[0]));
|
||||
|
@ -446,7 +448,8 @@ void CollectionFilterWidget::CheckCurrentGrouping(const CollectionModel::Groupin
|
|||
UpdateGroupByActions();
|
||||
}
|
||||
|
||||
for (QAction *action : group_by_group_->actions()) {
|
||||
const QList<QAction*> actions = group_by_group_->actions();
|
||||
for (QAction *action : actions) {
|
||||
if (action->property("group_by").isNull()) continue;
|
||||
|
||||
if (g == action->property("group_by").value<CollectionModel::Grouping>()) {
|
||||
|
@ -456,7 +459,6 @@ void CollectionFilterWidget::CheckCurrentGrouping(const CollectionModel::Groupin
|
|||
}
|
||||
|
||||
// Check the advanced action
|
||||
QList<QAction*> actions = group_by_group_->actions();
|
||||
QAction *action = actions.last();
|
||||
action->setChecked(true);
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ bool CollectionItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *vie
|
|||
if (text.isEmpty()) return false;
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::ToolTip: {
|
||||
case QEvent::ToolTip:{
|
||||
|
||||
QSize real_text = sizeHint(option, idx);
|
||||
QRect displayed_text = view->visualRect(idx);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -61,6 +61,7 @@
|
|||
#include "core/logging.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "core/sqlrow.h"
|
||||
#include "core/settings.h"
|
||||
#include "collectionfilteroptions.h"
|
||||
#include "collectionquery.h"
|
||||
#include "collectionqueryoptions.h"
|
||||
|
@ -91,8 +92,8 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
|
|||
total_artist_count_(0),
|
||||
total_album_count_(0),
|
||||
separate_albums_by_grouping_(false),
|
||||
artist_icon_(IconLoader::Load("folder-sound")),
|
||||
album_icon_(IconLoader::Load("cdcase")),
|
||||
artist_icon_(IconLoader::Load(QStringLiteral("folder-sound"))),
|
||||
album_icon_(IconLoader::Load(QStringLiteral("cdcase"))),
|
||||
init_task_id_(-1),
|
||||
use_pretty_covers_(true),
|
||||
show_dividers_(true),
|
||||
|
@ -109,7 +110,7 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
|
|||
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded);
|
||||
}
|
||||
|
||||
QIcon nocover = IconLoader::Load("cdcase");
|
||||
QIcon nocover = IconLoader::Load(QStringLiteral("cdcase"));
|
||||
if (!nocover.isNull()) {
|
||||
QList<QSize> nocover_sizes = nocover.availableSizes();
|
||||
no_cover_icon_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
@ -117,7 +118,7 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
|
|||
|
||||
if (app_ && !sIconCache) {
|
||||
sIconCache = new QNetworkDiskCache(this);
|
||||
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/" + kPixmapDiskCacheDir);
|
||||
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + QLatin1String(kPixmapDiskCacheDir));
|
||||
QObject::connect(app_, &Application::ClearPixmapDiskCache, this, &CollectionModel::ClearDiskCache);
|
||||
}
|
||||
|
||||
|
@ -177,7 +178,7 @@ void CollectionModel::set_sort_skips_articles(const bool sort_skips_articles) {
|
|||
|
||||
void CollectionModel::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
|
||||
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
|
||||
|
@ -247,7 +248,7 @@ void CollectionModel::SongsDiscovered(const SongList &songs) {
|
|||
GroupBy group_by = group_by_[i];
|
||||
if (group_by == GroupBy::None) break;
|
||||
|
||||
if (!key.isEmpty()) key.append("-");
|
||||
if (!key.isEmpty()) key.append(QLatin1Char('-'));
|
||||
|
||||
// Special case: if the song is a compilation and the current GroupBy level is Artists, then we want the Various Artists node :(
|
||||
if (IsArtistGroupBy(group_by) && song.is_compilation()) {
|
||||
|
@ -307,7 +308,7 @@ CollectionItem *CollectionModel::CreateCompilationArtistNode(const bool signal,
|
|||
if (parent != root_ && !parent->key.isEmpty()) parent->compilation_artist_node_->key.append(parent->key);
|
||||
parent->compilation_artist_node_->key.append(tr("Various artists"));
|
||||
parent->compilation_artist_node_->display_text = tr("Various artists");
|
||||
parent->compilation_artist_node_->sort_text = " various";
|
||||
parent->compilation_artist_node_->sort_text = QStringLiteral(" various");
|
||||
parent->compilation_artist_node_->container_level = parent->container_level + 1;
|
||||
|
||||
if (signal) endInsertRows();
|
||||
|
@ -329,33 +330,33 @@ QString CollectionModel::ContainerKey(const GroupBy group_by, const bool separat
|
|||
break;
|
||||
case GroupBy::Album:
|
||||
key = TextOrUnknown(song.album());
|
||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
|
||||
break;
|
||||
case GroupBy::AlbumDisc:
|
||||
key = PrettyAlbumDisc(song.album(), song.disc());
|
||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
|
||||
break;
|
||||
case GroupBy::YearAlbum:
|
||||
key = PrettyYearAlbum(song.year(), song.album());
|
||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
|
||||
break;
|
||||
case GroupBy::YearAlbumDisc:
|
||||
key = PrettyYearAlbumDisc(song.year(), song.album(), song.disc());
|
||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
|
||||
break;
|
||||
case GroupBy::OriginalYearAlbum:
|
||||
key = PrettyYearAlbum(song.effective_originalyear(), song.album());
|
||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
|
||||
break;
|
||||
case GroupBy::OriginalYearAlbumDisc:
|
||||
key = PrettyYearAlbumDisc(song.effective_originalyear(), song.album(), song.disc());
|
||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
|
||||
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
|
||||
break;
|
||||
case GroupBy::Disc:
|
||||
key = PrettyDisc(song.disc());
|
||||
|
@ -396,10 +397,10 @@ QString CollectionModel::ContainerKey(const GroupBy group_by, const bool separat
|
|||
}
|
||||
else {
|
||||
if (song.bitdepth() <= 0) {
|
||||
key = QString("%1 (%2)").arg(song.TextForFiletype(), QString::number(song.samplerate() / 1000.0, 'G', 5));
|
||||
key = QStringLiteral("%1 (%2)").arg(song.TextForFiletype(), QString::number(song.samplerate() / 1000.0, 'G', 5));
|
||||
}
|
||||
else {
|
||||
key = QString("%1 (%2/%3)").arg(song.TextForFiletype(), QString::number(song.samplerate() / 1000.0, 'G', 5)).arg(song.bitdepth());
|
||||
key = QStringLiteral("%1 (%2/%3)").arg(song.TextForFiletype(), QString::number(song.samplerate() / 1000.0, 'G', 5)).arg(song.bitdepth());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -430,10 +431,10 @@ QString CollectionModel::DividerKey(const GroupBy group_by, CollectionItem *item
|
|||
case GroupBy::Disc:
|
||||
case GroupBy::Genre:
|
||||
case GroupBy::Format:
|
||||
case GroupBy::FileType: {
|
||||
case GroupBy::FileType:{
|
||||
QChar c = item->sort_text[0];
|
||||
if (c.isDigit()) return "0";
|
||||
if (c == ' ') return QString();
|
||||
if (c.isDigit()) return QStringLiteral("0");
|
||||
if (c == QLatin1Char(' ')) return QString();
|
||||
if (c.decompositionTag() != QChar::NoDecomposition) {
|
||||
QString decomposition = c.decomposition();
|
||||
return QChar(decomposition[0]);
|
||||
|
@ -487,31 +488,31 @@ QString CollectionModel::DividerDisplayText(const GroupBy group_by, const QStrin
|
|||
case GroupBy::Genre:
|
||||
case GroupBy::FileType:
|
||||
case GroupBy::Format:
|
||||
if (key == "0") return "0-9";
|
||||
if (key == QLatin1String("0")) return QStringLiteral("0-9");
|
||||
return key.toUpper();
|
||||
|
||||
case GroupBy::YearAlbum:
|
||||
case GroupBy::YearAlbumDisc:
|
||||
case GroupBy::OriginalYearAlbum:
|
||||
case GroupBy::OriginalYearAlbumDisc:
|
||||
if (key == "0000") return tr("Unknown");
|
||||
if (key == QStringLiteral("0000")) return tr("Unknown");
|
||||
return key.toUpper();
|
||||
|
||||
case GroupBy::Year:
|
||||
case GroupBy::OriginalYear:
|
||||
if (key == "0000") return tr("Unknown");
|
||||
if (key == QStringLiteral("0000")) return tr("Unknown");
|
||||
return QString::number(key.toInt()); // To remove leading 0s
|
||||
|
||||
case GroupBy::Samplerate:
|
||||
if (key == "000") return tr("Unknown");
|
||||
if (key == QStringLiteral("000")) return tr("Unknown");
|
||||
return QString::number(key.toInt()); // To remove leading 0s
|
||||
|
||||
case GroupBy::Bitdepth:
|
||||
if (key == "000") return tr("Unknown");
|
||||
if (key == QStringLiteral("000")) return tr("Unknown");
|
||||
return QString::number(key.toInt()); // To remove leading 0s
|
||||
|
||||
case GroupBy::Bitrate:
|
||||
if (key == "000") return tr("Unknown");
|
||||
if (key == QStringLiteral("000")) return tr("Unknown");
|
||||
return QString::number(key.toInt()); // To remove leading 0s
|
||||
|
||||
case GroupBy::None:
|
||||
|
@ -631,13 +632,13 @@ QString CollectionModel::AlbumIconPixmapCacheKey(const QModelIndex &idx) const {
|
|||
idx_copy = idx_copy.parent();
|
||||
}
|
||||
|
||||
return Song::TextForSource(backend_->source()) + "/" + path.join("/");
|
||||
return Song::TextForSource(backend_->source()) + QLatin1Char('/') + path.join(QLatin1Char('/'));
|
||||
|
||||
}
|
||||
|
||||
QUrl CollectionModel::AlbumIconPixmapDiskCacheKey(const QString &cache_key) const {
|
||||
|
||||
return QUrl(QUrl::toPercentEncoding(cache_key));
|
||||
return QUrl(QString::fromLatin1(QUrl::toPercentEncoding(cache_key)));
|
||||
|
||||
}
|
||||
|
||||
|
@ -1054,86 +1055,86 @@ void CollectionModel::SetQueryColumnSpec(const GroupBy group_by, const bool sepa
|
|||
// Say what group_by of thing we want to get back from the database.
|
||||
switch (group_by) {
|
||||
case GroupBy::AlbumArtist:
|
||||
query_options->set_column_spec("DISTINCT effective_albumartist");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT effective_albumartist"));
|
||||
break;
|
||||
case GroupBy::Artist:
|
||||
query_options->set_column_spec("DISTINCT artist");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT artist"));
|
||||
break;
|
||||
case GroupBy::Album:{
|
||||
QString query("DISTINCT album, album_id");
|
||||
if (separate_albums_by_grouping) query.append(", grouping");
|
||||
QString query(QStringLiteral("DISTINCT album, album_id"));
|
||||
if (separate_albums_by_grouping) query.append(QStringLiteral(", grouping"));
|
||||
query_options->set_column_spec(query);
|
||||
break;
|
||||
}
|
||||
case GroupBy::AlbumDisc:{
|
||||
QString query("DISTINCT album, album_id, disc");
|
||||
if (separate_albums_by_grouping) query.append(", grouping");
|
||||
QString query(QStringLiteral("DISTINCT album, album_id, disc"));
|
||||
if (separate_albums_by_grouping) query.append(QStringLiteral(", grouping"));
|
||||
query_options->set_column_spec(query);
|
||||
break;
|
||||
}
|
||||
case GroupBy::YearAlbum:{
|
||||
QString query("DISTINCT year, album, album_id");
|
||||
if (separate_albums_by_grouping) query.append(", grouping");
|
||||
QString query(QStringLiteral("DISTINCT year, album, album_id"));
|
||||
if (separate_albums_by_grouping) query.append(QStringLiteral(", grouping"));
|
||||
query_options->set_column_spec(query);
|
||||
break;
|
||||
}
|
||||
case GroupBy::YearAlbumDisc:{
|
||||
QString query("DISTINCT year, album, album_id, disc");
|
||||
if (separate_albums_by_grouping) query.append(", grouping");
|
||||
QString query(QStringLiteral("DISTINCT year, album, album_id, disc"));
|
||||
if (separate_albums_by_grouping) query.append(QStringLiteral(", grouping"));
|
||||
query_options->set_column_spec(query);
|
||||
break;
|
||||
}
|
||||
case GroupBy::OriginalYearAlbum:{
|
||||
QString query("DISTINCT year, originalyear, album, album_id");
|
||||
if (separate_albums_by_grouping) query.append(", grouping");
|
||||
QString query(QStringLiteral("DISTINCT year, originalyear, album, album_id"));
|
||||
if (separate_albums_by_grouping) query.append(QStringLiteral(", grouping"));
|
||||
query_options->set_column_spec(query);
|
||||
break;
|
||||
}
|
||||
case GroupBy::OriginalYearAlbumDisc:{
|
||||
QString query("DISTINCT year, originalyear, album, album_id, disc");
|
||||
if (separate_albums_by_grouping) query.append(", grouping");
|
||||
QString query(QStringLiteral("DISTINCT year, originalyear, album, album_id, disc"));
|
||||
if (separate_albums_by_grouping) query.append(QStringLiteral(", grouping"));
|
||||
query_options->set_column_spec(query);
|
||||
break;
|
||||
}
|
||||
case GroupBy::Disc:
|
||||
query_options->set_column_spec("DISTINCT disc");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT disc"));
|
||||
break;
|
||||
case GroupBy::Year:
|
||||
query_options->set_column_spec("DISTINCT year");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT year"));
|
||||
break;
|
||||
case GroupBy::OriginalYear:
|
||||
query_options->set_column_spec("DISTINCT effective_originalyear");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT effective_originalyear"));
|
||||
break;
|
||||
case GroupBy::Genre:
|
||||
query_options->set_column_spec("DISTINCT genre");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT genre"));
|
||||
break;
|
||||
case GroupBy::Composer:
|
||||
query_options->set_column_spec("DISTINCT composer");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT composer"));
|
||||
break;
|
||||
case GroupBy::Performer:
|
||||
query_options->set_column_spec("DISTINCT performer");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT performer"));
|
||||
break;
|
||||
case GroupBy::Grouping:
|
||||
query_options->set_column_spec("DISTINCT grouping");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT grouping"));
|
||||
break;
|
||||
case GroupBy::FileType:
|
||||
query_options->set_column_spec("DISTINCT filetype");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT filetype"));
|
||||
break;
|
||||
case GroupBy::Format:
|
||||
query_options->set_column_spec("DISTINCT filetype, samplerate, bitdepth");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT filetype, samplerate, bitdepth"));
|
||||
break;
|
||||
case GroupBy::Samplerate:
|
||||
query_options->set_column_spec("DISTINCT samplerate");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT samplerate"));
|
||||
break;
|
||||
case GroupBy::Bitdepth:
|
||||
query_options->set_column_spec("DISTINCT bitdepth");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT bitdepth"));
|
||||
break;
|
||||
case GroupBy::Bitrate:
|
||||
query_options->set_column_spec("DISTINCT bitrate");
|
||||
query_options->set_column_spec(QStringLiteral("DISTINCT bitrate"));
|
||||
break;
|
||||
case GroupBy::None:
|
||||
case GroupBy::GroupByCount:
|
||||
query_options->set_column_spec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||
query_options->set_column_spec(QStringLiteral("%songs_table.ROWID, ") + Song::kColumnSpec);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1151,7 +1152,7 @@ void CollectionModel::AddQueryWhere(const GroupBy group_by, const bool separate_
|
|||
else {
|
||||
// Don't duplicate compilations outside the Various artists node
|
||||
query_options->set_compilation_requirement(CollectionQueryOptions::CompilationRequirement::Off);
|
||||
query_options->AddWhere("effective_albumartist", item->metadata.effective_albumartist());
|
||||
query_options->AddWhere(QStringLiteral("effective_albumartist"), item->metadata.effective_albumartist());
|
||||
}
|
||||
break;
|
||||
case GroupBy::Artist:
|
||||
|
@ -1161,85 +1162,85 @@ void CollectionModel::AddQueryWhere(const GroupBy group_by, const bool separate_
|
|||
else {
|
||||
// Don't duplicate compilations outside the Various artists node
|
||||
query_options->set_compilation_requirement(CollectionQueryOptions::CompilationRequirement::Off);
|
||||
query_options->AddWhere("artist", item->metadata.artist());
|
||||
query_options->AddWhere(QStringLiteral("artist"), item->metadata.artist());
|
||||
}
|
||||
break;
|
||||
case GroupBy::Album:
|
||||
query_options->AddWhere("album", item->metadata.album());
|
||||
query_options->AddWhere("album_id", item->metadata.album_id());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("album"), item->metadata.album());
|
||||
query_options->AddWhere(QStringLiteral("album_id"), item->metadata.album_id());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::AlbumDisc:
|
||||
query_options->AddWhere("album", item->metadata.album());
|
||||
query_options->AddWhere("album_id", item->metadata.album_id());
|
||||
query_options->AddWhere("disc", item->metadata.disc());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("album"), item->metadata.album());
|
||||
query_options->AddWhere(QStringLiteral("album_id"), item->metadata.album_id());
|
||||
query_options->AddWhere(QStringLiteral("disc"), item->metadata.disc());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::YearAlbum:
|
||||
query_options->AddWhere("year", item->metadata.year());
|
||||
query_options->AddWhere("album", item->metadata.album());
|
||||
query_options->AddWhere("album_id", item->metadata.album_id());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("year"), item->metadata.year());
|
||||
query_options->AddWhere(QStringLiteral("album"), item->metadata.album());
|
||||
query_options->AddWhere(QStringLiteral("album_id"), item->metadata.album_id());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::YearAlbumDisc:
|
||||
query_options->AddWhere("year", item->metadata.year());
|
||||
query_options->AddWhere("album", item->metadata.album());
|
||||
query_options->AddWhere("album_id", item->metadata.album_id());
|
||||
query_options->AddWhere("disc", item->metadata.disc());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("year"), item->metadata.year());
|
||||
query_options->AddWhere(QStringLiteral("album"), item->metadata.album());
|
||||
query_options->AddWhere(QStringLiteral("album_id"), item->metadata.album_id());
|
||||
query_options->AddWhere(QStringLiteral("disc"), item->metadata.disc());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::OriginalYearAlbum:
|
||||
query_options->AddWhere("year", item->metadata.year());
|
||||
query_options->AddWhere("originalyear", item->metadata.originalyear());
|
||||
query_options->AddWhere("album", item->metadata.album());
|
||||
query_options->AddWhere("album_id", item->metadata.album_id());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("year"), item->metadata.year());
|
||||
query_options->AddWhere(QStringLiteral("originalyear"), item->metadata.originalyear());
|
||||
query_options->AddWhere(QStringLiteral("album"), item->metadata.album());
|
||||
query_options->AddWhere(QStringLiteral("album_id"), item->metadata.album_id());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::OriginalYearAlbumDisc:
|
||||
query_options->AddWhere("year", item->metadata.year());
|
||||
query_options->AddWhere("originalyear", item->metadata.originalyear());
|
||||
query_options->AddWhere("album", item->metadata.album());
|
||||
query_options->AddWhere("album_id", item->metadata.album_id());
|
||||
query_options->AddWhere("disc", item->metadata.disc());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("year"), item->metadata.year());
|
||||
query_options->AddWhere(QStringLiteral("originalyear"), item->metadata.originalyear());
|
||||
query_options->AddWhere(QStringLiteral("album"), item->metadata.album());
|
||||
query_options->AddWhere(QStringLiteral("album_id"), item->metadata.album_id());
|
||||
query_options->AddWhere(QStringLiteral("disc"), item->metadata.disc());
|
||||
if (separate_albums_by_grouping) query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::Disc:
|
||||
query_options->AddWhere("disc", item->metadata.disc());
|
||||
query_options->AddWhere(QStringLiteral("disc"), item->metadata.disc());
|
||||
break;
|
||||
case GroupBy::Year:
|
||||
query_options->AddWhere("year", item->metadata.year());
|
||||
query_options->AddWhere(QStringLiteral("year"), item->metadata.year());
|
||||
break;
|
||||
case GroupBy::OriginalYear:
|
||||
query_options->AddWhere("effective_originalyear", item->metadata.effective_originalyear());
|
||||
query_options->AddWhere(QStringLiteral("effective_originalyear"), item->metadata.effective_originalyear());
|
||||
break;
|
||||
case GroupBy::Genre:
|
||||
query_options->AddWhere("genre", item->metadata.genre());
|
||||
query_options->AddWhere(QStringLiteral("genre"), item->metadata.genre());
|
||||
break;
|
||||
case GroupBy::Composer:
|
||||
query_options->AddWhere("composer", item->metadata.composer());
|
||||
query_options->AddWhere(QStringLiteral("composer"), item->metadata.composer());
|
||||
break;
|
||||
case GroupBy::Performer:
|
||||
query_options->AddWhere("performer", item->metadata.performer());
|
||||
query_options->AddWhere(QStringLiteral("performer"), item->metadata.performer());
|
||||
break;
|
||||
case GroupBy::Grouping:
|
||||
query_options->AddWhere("grouping", item->metadata.grouping());
|
||||
query_options->AddWhere(QStringLiteral("grouping"), item->metadata.grouping());
|
||||
break;
|
||||
case GroupBy::FileType:
|
||||
query_options->AddWhere("filetype", static_cast<int>(item->metadata.filetype()));
|
||||
query_options->AddWhere(QStringLiteral("filetype"), static_cast<int>(item->metadata.filetype()));
|
||||
break;
|
||||
case GroupBy::Format:
|
||||
query_options->AddWhere("filetype", static_cast<int>(item->metadata.filetype()));
|
||||
query_options->AddWhere("samplerate", item->metadata.samplerate());
|
||||
query_options->AddWhere("bitdepth", item->metadata.bitdepth());
|
||||
query_options->AddWhere(QStringLiteral("filetype"), static_cast<int>(item->metadata.filetype()));
|
||||
query_options->AddWhere(QStringLiteral("samplerate"), item->metadata.samplerate());
|
||||
query_options->AddWhere(QStringLiteral("bitdepth"), item->metadata.bitdepth());
|
||||
break;
|
||||
case GroupBy::Samplerate:
|
||||
query_options->AddWhere("samplerate", item->metadata.samplerate());
|
||||
query_options->AddWhere(QStringLiteral("samplerate"), item->metadata.samplerate());
|
||||
break;
|
||||
case GroupBy::Bitdepth:
|
||||
query_options->AddWhere("bitdepth", item->metadata.bitdepth());
|
||||
query_options->AddWhere(QStringLiteral("bitdepth"), item->metadata.bitdepth());
|
||||
break;
|
||||
case GroupBy::Bitrate:
|
||||
query_options->AddWhere("bitrate", item->metadata.bitrate());
|
||||
query_options->AddWhere(QStringLiteral("bitrate"), item->metadata.bitrate());
|
||||
break;
|
||||
case GroupBy::None:
|
||||
case GroupBy::GroupByCount:
|
||||
|
@ -1269,7 +1270,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
CollectionItem *item = InitItem(group_by, signal, parent, container_level);
|
||||
|
||||
if (parent != root_ && !parent->key.isEmpty()) {
|
||||
item->key = parent->key + "-";
|
||||
item->key = parent->key + QLatin1Char('-');
|
||||
}
|
||||
|
||||
switch (group_by) {
|
||||
|
@ -1290,7 +1291,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
case GroupBy::Album:{
|
||||
item->metadata.set_album(row.value(0).toString());
|
||||
item->metadata.set_album_id(row.value(1).toString());
|
||||
item->metadata.set_grouping(row.value(2).toString());
|
||||
if (separate_albums_by_grouping) item->metadata.set_grouping(row.value(2).toString());
|
||||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
item->display_text = TextOrUnknown(item->metadata.album());
|
||||
item->sort_text = SortTextForArtist(item->metadata.album(), sort_skips_articles_);
|
||||
|
@ -1300,7 +1301,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->metadata.set_album(row.value(0).toString());
|
||||
item->metadata.set_album_id(row.value(1).toString());
|
||||
item->metadata.set_disc(row.value(2).toInt());
|
||||
item->metadata.set_grouping(row.value(3).toString());
|
||||
if (separate_albums_by_grouping) item->metadata.set_grouping(row.value(3).toString());
|
||||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
item->display_text = PrettyAlbumDisc(item->metadata.album(), item->metadata.disc());
|
||||
item->sort_text = item->metadata.album() + SortTextForNumber(std::max(0, item->metadata.disc()));
|
||||
|
@ -1310,7 +1311,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->metadata.set_year(row.value(0).toInt());
|
||||
item->metadata.set_album(row.value(1).toString());
|
||||
item->metadata.set_album_id(row.value(2).toString());
|
||||
item->metadata.set_grouping(row.value(3).toString());
|
||||
if (separate_albums_by_grouping) item->metadata.set_grouping(row.value(3).toString());
|
||||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
item->display_text = PrettyYearAlbum(item->metadata.year(), item->metadata.album());
|
||||
item->sort_text = SortTextForNumber(std::max(0, item->metadata.year())) + item->metadata.grouping() + item->metadata.album();
|
||||
|
@ -1321,7 +1322,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->metadata.set_album(row.value(1).toString());
|
||||
item->metadata.set_album_id(row.value(2).toString());
|
||||
item->metadata.set_disc(row.value(3).toInt());
|
||||
item->metadata.set_grouping(row.value(4).toString());
|
||||
if (separate_albums_by_grouping) item->metadata.set_grouping(row.value(4).toString());
|
||||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
item->display_text = PrettyYearAlbumDisc(item->metadata.year(), item->metadata.album(), item->metadata.disc());
|
||||
item->sort_text = SortTextForNumber(std::max(0, item->metadata.year())) + item->metadata.album() + SortTextForNumber(std::max(0, item->metadata.disc()));
|
||||
|
@ -1332,7 +1333,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->metadata.set_originalyear(row.value(1).toInt());
|
||||
item->metadata.set_album(row.value(2).toString());
|
||||
item->metadata.set_album_id(row.value(3).toString());
|
||||
item->metadata.set_grouping(row.value(4).toString());
|
||||
if (separate_albums_by_grouping) item->metadata.set_grouping(row.value(4).toString());
|
||||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
item->display_text = PrettyYearAlbum(item->metadata.effective_originalyear(), item->metadata.album());
|
||||
item->sort_text = SortTextForNumber(std::max(0, item->metadata.effective_originalyear())) + item->metadata.grouping() + item->metadata.album();
|
||||
|
@ -1344,7 +1345,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->metadata.set_album(row.value(2).toString());
|
||||
item->metadata.set_album_id(row.value(3).toString());
|
||||
item->metadata.set_disc(row.value(4).toInt());
|
||||
item->metadata.set_grouping(row.value(5).toString());
|
||||
if (separate_albums_by_grouping) item->metadata.set_grouping(row.value(5).toString());
|
||||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
item->display_text = PrettyYearAlbumDisc(item->metadata.effective_originalyear(), item->metadata.album(), item->metadata.disc());
|
||||
item->sort_text = SortTextForNumber(std::max(0, item->metadata.effective_originalyear())) + item->metadata.album() + SortTextForNumber(std::max(0, item->metadata.disc()));
|
||||
|
@ -1363,7 +1364,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
const int year = std::max(0, item->metadata.year());
|
||||
item->display_text = QString::number(year);
|
||||
item->sort_text = SortTextForNumber(year) + " ";
|
||||
item->sort_text = SortTextForNumber(year) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::OriginalYear:{
|
||||
|
@ -1371,7 +1372,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
const int year = std::max(0, item->metadata.originalyear());
|
||||
item->display_text = QString::number(year);
|
||||
item->sort_text = SortTextForNumber(year) + " ";
|
||||
item->sort_text = SortTextForNumber(year) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::Genre:{
|
||||
|
@ -1424,7 +1425,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
const int samplerate = std::max(0, item->metadata.samplerate());
|
||||
item->display_text = QString::number(samplerate);
|
||||
item->sort_text = SortTextForNumber(samplerate) + " ";
|
||||
item->sort_text = SortTextForNumber(samplerate) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::Bitdepth:{
|
||||
|
@ -1432,7 +1433,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
const int bitdepth = std::max(0, item->metadata.bitdepth());
|
||||
item->display_text = QString::number(bitdepth);
|
||||
item->sort_text = SortTextForNumber(bitdepth) + " ";
|
||||
item->sort_text = SortTextForNumber(bitdepth) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::Bitrate:{
|
||||
|
@ -1440,7 +1441,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||
const int bitrate = std::max(0, item->metadata.bitrate());
|
||||
item->display_text = QString::number(bitrate);
|
||||
item->sort_text = SortTextForNumber(bitrate) + " ";
|
||||
item->sort_text = SortTextForNumber(bitrate) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::None:
|
||||
|
@ -1468,7 +1469,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
CollectionItem *item = InitItem(group_by, signal, parent, container_level);
|
||||
|
||||
if (parent != root_ && !parent->key.isEmpty()) {
|
||||
item->key = parent->key + "-";
|
||||
item->key = parent->key + QLatin1Char('-');
|
||||
}
|
||||
|
||||
switch (group_by) {
|
||||
|
@ -1562,7 +1563,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||
const int year = std::max(0, s.year());
|
||||
item->display_text = QString::number(year);
|
||||
item->sort_text = SortTextForNumber(year) + " ";
|
||||
item->sort_text = SortTextForNumber(year) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::OriginalYear:{
|
||||
|
@ -1570,7 +1571,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||
const int year = std::max(0, s.effective_originalyear());
|
||||
item->display_text = QString::number(year);
|
||||
item->sort_text = SortTextForNumber(year) + " ";
|
||||
item->sort_text = SortTextForNumber(year) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::Genre:{
|
||||
|
@ -1623,7 +1624,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||
const int samplerate = std::max(0, s.samplerate());
|
||||
item->display_text = QString::number(samplerate);
|
||||
item->sort_text = SortTextForNumber(samplerate) + " ";
|
||||
item->sort_text = SortTextForNumber(samplerate) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::Bitdepth:{
|
||||
|
@ -1631,7 +1632,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||
const int bitdepth = std::max(0, s.bitdepth());
|
||||
item->display_text = QString::number(bitdepth);
|
||||
item->sort_text = SortTextForNumber(bitdepth) + " ";
|
||||
item->sort_text = SortTextForNumber(bitdepth) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::Bitrate:{
|
||||
|
@ -1639,7 +1640,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||
const int bitrate = std::max(0, s.bitrate());
|
||||
item->display_text = QString::number(bitrate);
|
||||
item->sort_text = SortTextForNumber(bitrate) + " ";
|
||||
item->sort_text = SortTextForNumber(bitrate) + QLatin1Char(' ');
|
||||
break;
|
||||
}
|
||||
case GroupBy::None:
|
||||
|
@ -1658,7 +1659,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
|
|||
}
|
||||
|
||||
FinishItem(group_by, signal, create_divider, parent, item);
|
||||
if (s.url().scheme() == "cdda") item->lazy_loaded = true;
|
||||
if (s.url().scheme() == QStringLiteral("cdda")) item->lazy_loaded = true;
|
||||
|
||||
return item;
|
||||
|
||||
|
@ -1678,7 +1679,7 @@ void CollectionModel::FinishItem(const GroupBy group_by, const bool signal, cons
|
|||
if (create_divider && show_dividers_) {
|
||||
QString divider_key = DividerKey(group_by, item);
|
||||
if (!divider_key.isEmpty()) {
|
||||
item->sort_text.prepend(divider_key + " ");
|
||||
item->sort_text.prepend(divider_key + QLatin1Char(' '));
|
||||
}
|
||||
|
||||
if (!divider_key.isEmpty() && !divider_nodes_.contains(divider_key)) {
|
||||
|
@ -1689,7 +1690,7 @@ void CollectionModel::FinishItem(const GroupBy group_by, const bool signal, cons
|
|||
CollectionItem *divider = new CollectionItem(CollectionItem::Type_Divider, root_);
|
||||
divider->key = divider_key;
|
||||
divider->display_text = DividerDisplayText(group_by, divider_key);
|
||||
divider->sort_text = divider_key + " ";
|
||||
divider->sort_text = divider_key + QStringLiteral(" ");
|
||||
divider->lazy_loaded = true;
|
||||
|
||||
divider_nodes_[divider_key] = divider;
|
||||
|
@ -1712,14 +1713,14 @@ QString CollectionModel::TextOrUnknown(const QString &text) {
|
|||
QString CollectionModel::PrettyYearAlbum(const int year, const QString &album) {
|
||||
|
||||
if (year <= 0) return TextOrUnknown(album);
|
||||
return QString::number(year) + " - " + TextOrUnknown(album);
|
||||
return QString::number(year) + QStringLiteral(" - ") + TextOrUnknown(album);
|
||||
|
||||
}
|
||||
|
||||
QString CollectionModel::PrettyAlbumDisc(const QString &album, const int disc) {
|
||||
|
||||
if (disc <= 0 || Song::AlbumContainsDisc(album)) return TextOrUnknown(album);
|
||||
else return TextOrUnknown(album) + " - (Disc " + QString::number(disc) + ")";
|
||||
else return TextOrUnknown(album) + QStringLiteral(" - (Disc ") + QString::number(disc) + QStringLiteral(")");
|
||||
|
||||
}
|
||||
|
||||
|
@ -1728,9 +1729,9 @@ QString CollectionModel::PrettyYearAlbumDisc(const int year, const QString &albu
|
|||
QString str;
|
||||
|
||||
if (year <= 0) str = TextOrUnknown(album);
|
||||
else str = QString::number(year) + " - " + TextOrUnknown(album);
|
||||
else str = QString::number(year) + QStringLiteral(" - ") + TextOrUnknown(album);
|
||||
|
||||
if (!Song::AlbumContainsDisc(album) && disc > 0) str += " - (Disc " + QString::number(disc) + ")";
|
||||
if (!Song::AlbumContainsDisc(album) && disc > 0) str += QStringLiteral(" - (Disc ") + QString::number(disc) + QStringLiteral(")");
|
||||
|
||||
return str;
|
||||
|
||||
|
@ -1738,19 +1739,19 @@ QString CollectionModel::PrettyYearAlbumDisc(const int year, const QString &albu
|
|||
|
||||
QString CollectionModel::PrettyDisc(const int disc) {
|
||||
|
||||
return "Disc " + QString::number(std::max(1, disc));
|
||||
return QStringLiteral("Disc ") + QString::number(std::max(1, disc));
|
||||
|
||||
}
|
||||
|
||||
QString CollectionModel::SortText(QString text) {
|
||||
|
||||
if (text.isEmpty()) {
|
||||
text = " unknown";
|
||||
text = QStringLiteral(" unknown");
|
||||
}
|
||||
else {
|
||||
text = text.toLower();
|
||||
}
|
||||
text = text.remove(QRegularExpression("[^\\w ]", QRegularExpression::UseUnicodePropertiesOption));
|
||||
text = text.remove(QRegularExpression(QStringLiteral("[^\\w ]"), QRegularExpression::UseUnicodePropertiesOption));
|
||||
|
||||
return text;
|
||||
|
||||
|
@ -1764,7 +1765,7 @@ QString CollectionModel::SortTextForArtist(QString artist, const bool skip_artic
|
|||
for (const auto &i : Song::kArticles) {
|
||||
if (artist.startsWith(i)) {
|
||||
qint64 ilen = i.length();
|
||||
artist = artist.right(artist.length() - ilen) + ", " + i.left(ilen - 1);
|
||||
artist = artist.right(artist.length() - ilen) + QStringLiteral(", ") + i.left(ilen - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1776,27 +1777,27 @@ QString CollectionModel::SortTextForArtist(QString artist, const bool skip_artic
|
|||
|
||||
QString CollectionModel::SortTextForNumber(const int number) {
|
||||
|
||||
return QString("%1").arg(number, 4, 10, QChar('0'));
|
||||
return QStringLiteral("%1").arg(number, 4, 10, QLatin1Char('0'));
|
||||
}
|
||||
|
||||
QString CollectionModel::SortTextForYear(const int year) {
|
||||
|
||||
QString str = QString::number(year);
|
||||
return QString("0").repeated(qMax(0, 4 - str.length())) + str;
|
||||
return QStringLiteral("0").repeated(qMax(0, 4 - str.length())) + str;
|
||||
|
||||
}
|
||||
|
||||
QString CollectionModel::SortTextForBitrate(const int bitrate) {
|
||||
|
||||
QString str = QString::number(bitrate);
|
||||
return QString("0").repeated(qMax(0, 3 - str.length())) + str;
|
||||
return QStringLiteral("0").repeated(qMax(0, 3 - str.length())) + str;
|
||||
|
||||
}
|
||||
|
||||
QString CollectionModel::SortTextForSong(const Song &song) {
|
||||
|
||||
QString ret = QString::number(std::max(0, song.disc()) * 1000 + std::max(0, song.track()));
|
||||
ret.prepend(QString("0").repeated(6 - ret.length()));
|
||||
ret.prepend(QStringLiteral("0").repeated(6 - ret.length()));
|
||||
ret.append(song.url().toString());
|
||||
return ret;
|
||||
|
||||
|
@ -1818,7 +1819,7 @@ Qt::ItemFlags CollectionModel::flags(const QModelIndex &idx) const {
|
|||
}
|
||||
|
||||
QStringList CollectionModel::mimeTypes() const {
|
||||
return QStringList() << "text/uri-list";
|
||||
return QStringList() << QStringLiteral("text/uri-list");
|
||||
}
|
||||
|
||||
QMimeData *CollectionModel::mimeData(const QModelIndexList &indexes) const {
|
||||
|
@ -1858,10 +1859,10 @@ bool CollectionModel::CompareItems(const CollectionItem *a, const CollectionItem
|
|||
|
||||
}
|
||||
|
||||
qint64 CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const qint64 cache_size_default) {
|
||||
qint64 CollectionModel::MaximumCacheSize(Settings *s, const char *size_id, const char *size_unit_id, const qint64 cache_size_default) {
|
||||
|
||||
qint64 size = s->value(size_id, cache_size_default).toInt();
|
||||
int unit = s->value(size_unit_id, static_cast<int>(CollectionSettingsPage::CacheSizeUnit::MB)).toInt() + 1;
|
||||
qint64 size = s->value(QLatin1String(size_id), cache_size_default).toInt();
|
||||
int unit = s->value(QLatin1String(size_unit_id), static_cast<int>(CollectionSettingsPage::CacheSizeUnit::MB)).toInt() + 1;
|
||||
|
||||
do {
|
||||
size *= 1024;
|
||||
|
@ -1875,7 +1876,7 @@ qint64 CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, cons
|
|||
void CollectionModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls, SongList *songs, QSet<int> *song_ids) const {
|
||||
|
||||
switch (item->type) {
|
||||
case CollectionItem::Type_Container: {
|
||||
case CollectionItem::Type_Container:{
|
||||
const_cast<CollectionModel*>(this)->LazyPopulate(item);
|
||||
|
||||
QList<CollectionItem*> children = item->children;
|
||||
|
@ -2012,7 +2013,7 @@ void CollectionModel::ExpandAll(CollectionItem *item) const {
|
|||
if (!root_) return;
|
||||
|
||||
if (!item) item = root_;
|
||||
const_cast<CollectionModel*>(this)->LazyPopulate(const_cast<CollectionItem*>(item), false);
|
||||
const_cast<CollectionModel*>(this)->LazyPopulate(item, false);
|
||||
for (CollectionItem *child : item->children) {
|
||||
ExpandAll(child);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -55,7 +55,7 @@
|
|||
#include "collectionqueryoptions.h"
|
||||
#include "collectionitem.h"
|
||||
|
||||
class QSettings;
|
||||
class Settings;
|
||||
|
||||
class Application;
|
||||
class CollectionBackend;
|
||||
|
@ -82,7 +82,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
|||
LastRole
|
||||
};
|
||||
|
||||
// These values get saved in QSettings - don't change them
|
||||
// These values get saved in Settings - don't change them
|
||||
enum class GroupBy {
|
||||
None = 0,
|
||||
AlbumArtist = 1,
|
||||
|
@ -275,7 +275,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
|||
QVariant AlbumIcon(const QModelIndex &idx);
|
||||
QVariant data(const CollectionItem *item, const int role) const;
|
||||
bool CompareItems(const CollectionItem *a, const CollectionItem *b) const;
|
||||
static qint64 MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const qint64 cache_size_default);
|
||||
static qint64 MaximumCacheSize(Settings *s, const char *size_id, const char *size_unit_id, const qint64 cache_size_default);
|
||||
|
||||
private:
|
||||
SharedPtr<CollectionBackend> backend_;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -30,8 +30,8 @@
|
|||
#include <QStringBuilder>
|
||||
#include <QRegularExpression>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "core/sqlquery.h"
|
||||
#include "core/song.h"
|
||||
|
||||
#include "collectionquery.h"
|
||||
|
@ -39,7 +39,7 @@
|
|||
#include "utilities/searchparserutils.h"
|
||||
|
||||
CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_table, const QString &fts_table, const CollectionFilterOptions &filter_options)
|
||||
: QSqlQuery(db),
|
||||
: SqlQuery(db),
|
||||
songs_table_(songs_table),
|
||||
fts_table_(fts_table),
|
||||
include_unavailable_(false),
|
||||
|
@ -54,35 +54,35 @@ CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_ta
|
|||
// 3) Remove colons which don't correspond to column names.
|
||||
|
||||
// Split on whitespace
|
||||
QString filter_text = filter_options.filter_text().replace(QRegularExpression(":\\s+"), ":");
|
||||
QString filter_text = filter_options.filter_text().replace(QRegularExpression(QStringLiteral(":\\s+")), QStringLiteral(":"));
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
QStringList tokens(filter_text.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts));
|
||||
QStringList tokens(filter_text.split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts));
|
||||
#else
|
||||
QStringList tokens(filter_text.split(QRegularExpression("\\s+"), QString::SkipEmptyParts));
|
||||
QStringList tokens(filter_text.split(QRegularExpression(QStringLiteral("\\s+")), QString::SkipEmptyParts));
|
||||
#endif
|
||||
QString query;
|
||||
for (QString token : tokens) {
|
||||
token.remove('(')
|
||||
.remove(')')
|
||||
.remove('"')
|
||||
.replace('-', ' ');
|
||||
token.remove(QLatin1Char('('))
|
||||
.remove(QLatin1Char(')'))
|
||||
.remove(QLatin1Char('"'))
|
||||
.replace(QLatin1Char('-'), QLatin1Char(' '));
|
||||
|
||||
if (token.contains(':')) {
|
||||
const QString columntoken = token.section(':', 0, 0);
|
||||
QString subtoken = token.section(':', 1, -1).replace(":", " ").trimmed();
|
||||
if (token.contains(QLatin1Char(':'))) {
|
||||
const QString columntoken = token.section(QLatin1Char(':'), 0, 0);
|
||||
QString subtoken = token.section(QLatin1Char(':'), 1, -1).replace(QLatin1String(":"), QLatin1String(" ")).trimmed();
|
||||
if (subtoken.isEmpty()) continue;
|
||||
if (Song::kFtsColumns.contains("fts" + columntoken, Qt::CaseInsensitive)) {
|
||||
if (!query.isEmpty()) query.append(" ");
|
||||
query += "fts" + columntoken + ":\"" + subtoken + "\"*";
|
||||
if (Song::kFtsColumns.contains(QLatin1String("fts") + columntoken, Qt::CaseInsensitive)) {
|
||||
if (!query.isEmpty()) query.append(QLatin1String(" "));
|
||||
query += QStringLiteral("fts") + columntoken + QStringLiteral(":\"") + subtoken + QStringLiteral("\"*");
|
||||
}
|
||||
else if (Song::kNumericalColumns.contains(columntoken, Qt::CaseInsensitive)) {
|
||||
QString comparator = RemoveSqlOperator(subtoken);
|
||||
if (columntoken.compare("rating", Qt::CaseInsensitive) == 0) {
|
||||
if (columntoken.compare(QLatin1String("rating"), Qt::CaseInsensitive) == 0) {
|
||||
AddWhereRating(subtoken, comparator);
|
||||
}
|
||||
else if (columntoken.compare("length", Qt::CaseInsensitive) == 0) {
|
||||
else if (columntoken.compare(QLatin1String("length"), Qt::CaseInsensitive) == 0) {
|
||||
// Time is saved in nanoseconds, so add 9 0's
|
||||
QString parsedTime = QString::number(Utilities::ParseSearchTime(subtoken)) + "000000000";
|
||||
QString parsedTime = QString::number(Utilities::ParseSearchTime(subtoken)) + QStringLiteral("000000000");
|
||||
AddWhere(columntoken, parsedTime, comparator);
|
||||
}
|
||||
else {
|
||||
|
@ -91,20 +91,20 @@ CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_ta
|
|||
}
|
||||
// Not a valid filter, remove
|
||||
else {
|
||||
token = token.replace(":", " ").trimmed();
|
||||
token = token.replace(QLatin1String(":"), QLatin1String(" ")).trimmed();
|
||||
if (!token.isEmpty()) {
|
||||
if (!query.isEmpty()) query.append(" ");
|
||||
query += "\"" + token + "\"*";
|
||||
if (!query.isEmpty()) query.append(QLatin1Char(' '));
|
||||
query += QLatin1Char('\"') + token + QStringLiteral("\"*");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!query.isEmpty()) query.append(" ");
|
||||
query += "\"" + token + "\"*";
|
||||
if (!query.isEmpty()) query.append(QLatin1Char(' '));
|
||||
query += QLatin1Char('\"') + token + QStringLiteral("\"*");
|
||||
}
|
||||
}
|
||||
if (!query.isEmpty()) {
|
||||
where_clauses_ << "fts.%fts_table_noprefix MATCH ?";
|
||||
where_clauses_ << QStringLiteral("fts.%fts_table_noprefix MATCH ?");
|
||||
bound_values_ << query;
|
||||
join_with_fts_ = true;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_ta
|
|||
if (filter_options.max_age() != -1) {
|
||||
qint64 cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - filter_options.max_age();
|
||||
|
||||
where_clauses_ << "ctime > ?";
|
||||
where_clauses_ << QStringLiteral("ctime > ?");
|
||||
bound_values_ << cutoff;
|
||||
}
|
||||
|
||||
|
@ -126,23 +126,23 @@ CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_ta
|
|||
duplicates_only_ = filter_options.filter_mode() == CollectionFilterOptions::FilterMode::Duplicates;
|
||||
|
||||
if (filter_options.filter_mode() == CollectionFilterOptions::FilterMode::Untagged) {
|
||||
where_clauses_ << "(artist = '' OR album = '' OR title ='')";
|
||||
where_clauses_ << QStringLiteral("(artist = '' OR album = '' OR title ='')");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QString CollectionQuery::RemoveSqlOperator(QString &token) {
|
||||
|
||||
QString op = "=";
|
||||
static QRegularExpression rxOp("^(=|<[>=]?|>=?|!=)");
|
||||
QString op = QStringLiteral("=");
|
||||
static QRegularExpression rxOp(QStringLiteral("^(=|<[>=]?|>=?|!=)"));
|
||||
QRegularExpressionMatch match = rxOp.match(token);
|
||||
if (match.hasMatch()) {
|
||||
op = match.captured(0);
|
||||
}
|
||||
token.remove(rxOp);
|
||||
|
||||
if (op == "!=") {
|
||||
op = "<>";
|
||||
if (op == QStringLiteral("!=")) {
|
||||
op = QStringLiteral("<>");
|
||||
}
|
||||
|
||||
return op;
|
||||
|
@ -152,16 +152,16 @@ QString CollectionQuery::RemoveSqlOperator(QString &token) {
|
|||
void CollectionQuery::AddWhere(const QString &column, const QVariant &value, const QString &op) {
|
||||
|
||||
// Ignore 'literal' for IN
|
||||
if (op.compare("IN", Qt::CaseInsensitive) == 0) {
|
||||
if (op.compare(QLatin1String("IN"), Qt::CaseInsensitive) == 0) {
|
||||
QStringList values = value.toStringList();
|
||||
QStringList final_values;
|
||||
final_values.reserve(values.count());
|
||||
for (const QString &single_value : values) {
|
||||
final_values.append("?");
|
||||
final_values.append(QStringLiteral("?"));
|
||||
bound_values_ << single_value;
|
||||
}
|
||||
|
||||
where_clauses_ << QString("%1 IN (" + final_values.join(",") + ")").arg(column);
|
||||
where_clauses_ << QStringLiteral("%1 IN (%2)").arg(column, final_values.join(QStringLiteral(",")));
|
||||
}
|
||||
else {
|
||||
// Do integers inline - sqlite seems to get confused when you pass integers to bound parameters
|
||||
|
@ -170,7 +170,7 @@ void CollectionQuery::AddWhere(const QString &column, const QVariant &value, con
|
|||
#else
|
||||
if (value.type() == QVariant::Int) {
|
||||
#endif
|
||||
where_clauses_ << QString("%1 %2 %3").arg(column, op, value.toString());
|
||||
where_clauses_ << QStringLiteral("%1 %2 %3").arg(column, op, value.toString());
|
||||
}
|
||||
else if (
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
|
@ -179,11 +179,11 @@ void CollectionQuery::AddWhere(const QString &column, const QVariant &value, con
|
|||
value.type() == QVariant::String
|
||||
#endif
|
||||
&& value.toString().isNull()) {
|
||||
where_clauses_ << QString("%1 %2 ?").arg(column, op);
|
||||
bound_values_ << QString("");
|
||||
where_clauses_ << QStringLiteral("%1 %2 ?").arg(column, op);
|
||||
bound_values_ << QLatin1String("");
|
||||
}
|
||||
else {
|
||||
where_clauses_ << QString("%1 %2 ?").arg(column, op);
|
||||
where_clauses_ << QStringLiteral("%1 %2 ?").arg(column, op);
|
||||
bound_values_ << value;
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ void CollectionQuery::AddWhere(const QString &column, const QVariant &value, con
|
|||
|
||||
void CollectionQuery::AddWhereArtist(const QVariant &value) {
|
||||
|
||||
where_clauses_ << QString("((artist = ? AND albumartist = '') OR albumartist = ?)");
|
||||
where_clauses_ << QStringLiteral("((artist = ? AND albumartist = '') OR albumartist = ?)");
|
||||
bound_values_ << value;
|
||||
bound_values_ << value;
|
||||
|
||||
|
@ -205,26 +205,26 @@ void CollectionQuery::AddWhereRating(const QVariant &value, const QString &op) {
|
|||
// You can't query the database for a float, due to float precision errors,
|
||||
// So we have to use a certain tolerance, so that the searched value is definetly included.
|
||||
const float tolerance = 0.001F;
|
||||
if (op == "<") {
|
||||
AddWhere("rating", parsed_rating-tolerance, "<");
|
||||
if (op == QStringLiteral("<")) {
|
||||
AddWhere(QStringLiteral("rating"), parsed_rating-tolerance, QStringLiteral("<"));
|
||||
}
|
||||
else if (op == ">") {
|
||||
AddWhere("rating", parsed_rating+tolerance, ">");
|
||||
else if (op == QStringLiteral(">")) {
|
||||
AddWhere(QStringLiteral("rating"), parsed_rating+tolerance, QStringLiteral(">"));
|
||||
}
|
||||
else if (op == "<=") {
|
||||
AddWhere("rating", parsed_rating+tolerance, "<=");
|
||||
else if (op == QStringLiteral("<=")) {
|
||||
AddWhere(QStringLiteral("rating"), parsed_rating+tolerance, QStringLiteral("<="));
|
||||
}
|
||||
else if (op == ">=") {
|
||||
AddWhere("rating", parsed_rating-tolerance, ">=");
|
||||
else if (op == QStringLiteral(">=")) {
|
||||
AddWhere(QStringLiteral("rating"), parsed_rating-tolerance, QStringLiteral(">="));
|
||||
}
|
||||
else if (op == "<>") {
|
||||
where_clauses_ << QString("(rating<? OR rating>?)");
|
||||
else if (op == QStringLiteral("<>")) {
|
||||
where_clauses_ << QStringLiteral("(rating<? OR rating>?)");
|
||||
bound_values_ << parsed_rating - tolerance;
|
||||
bound_values_ << parsed_rating + tolerance;
|
||||
}
|
||||
else /* (op == "=") */ {
|
||||
AddWhere("rating", parsed_rating+tolerance, "<");
|
||||
AddWhere("rating", parsed_rating-tolerance, ">");
|
||||
AddWhere(QStringLiteral("rating"), parsed_rating+tolerance, QStringLiteral("<"));
|
||||
AddWhere(QStringLiteral("rating"), parsed_rating-tolerance, QStringLiteral(">"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -233,13 +233,13 @@ void CollectionQuery::AddCompilationRequirement(const bool compilation) {
|
|||
// The unary + is added to prevent sqlite from using the index idx_comp_artist.
|
||||
// When joining with fts, sqlite 3.8 has a tendency to use this index and thereby nesting the tables in an order which gives very poor performance
|
||||
|
||||
where_clauses_ << QString("+compilation_effective = %1").arg(compilation ? 1 : 0);
|
||||
where_clauses_ << QStringLiteral("+compilation_effective = %1").arg(compilation ? 1 : 0);
|
||||
|
||||
}
|
||||
|
||||
QString CollectionQuery::GetInnerQuery() const {
|
||||
return duplicates_only_
|
||||
? QString(" INNER JOIN (select * from duplicated_songs) dsongs "
|
||||
? QStringLiteral(" INNER JOIN (select * from duplicated_songs) dsongs "
|
||||
"ON (%songs_table.artist = dsongs.dup_artist "
|
||||
"AND %songs_table.album = dsongs.dup_album "
|
||||
"AND %songs_table.title = dsongs.dup_title) ")
|
||||
|
@ -251,26 +251,26 @@ bool CollectionQuery::Exec() {
|
|||
QString sql;
|
||||
|
||||
if (join_with_fts_) {
|
||||
sql = QString("SELECT %1 FROM %2 INNER JOIN %3 AS fts ON %2.ROWID = fts.ROWID").arg(column_spec_, songs_table_, fts_table_);
|
||||
sql = QStringLiteral("SELECT %1 FROM %2 INNER JOIN %3 AS fts ON %2.ROWID = fts.ROWID").arg(column_spec_, songs_table_, fts_table_);
|
||||
}
|
||||
else {
|
||||
sql = QString("SELECT %1 FROM %2 %3").arg(column_spec_, songs_table_, GetInnerQuery());
|
||||
sql = QStringLiteral("SELECT %1 FROM %2 %3").arg(column_spec_, songs_table_, GetInnerQuery());
|
||||
}
|
||||
|
||||
QStringList where_clauses(where_clauses_);
|
||||
if (!include_unavailable_) {
|
||||
where_clauses << "unavailable = 0";
|
||||
where_clauses << QStringLiteral("unavailable = 0");
|
||||
}
|
||||
|
||||
if (!where_clauses.isEmpty()) sql += " WHERE " + where_clauses.join(" AND ");
|
||||
if (!where_clauses.isEmpty()) sql += QStringLiteral(" WHERE ") + where_clauses.join(QStringLiteral(" AND "));
|
||||
|
||||
if (!order_by_.isEmpty()) sql += " ORDER BY " + order_by_;
|
||||
if (!order_by_.isEmpty()) sql += QStringLiteral(" ORDER BY ") + order_by_;
|
||||
|
||||
if (limit_ != -1) sql += " LIMIT " + QString::number(limit_);
|
||||
if (limit_ != -1) sql += QStringLiteral(" LIMIT ") + QString::number(limit_);
|
||||
|
||||
sql.replace("%songs_table", songs_table_);
|
||||
sql.replace("%fts_table_noprefix", fts_table_.section('.', -1, -1));
|
||||
sql.replace("%fts_table", fts_table_);
|
||||
sql.replace(QLatin1String("%songs_table"), songs_table_);
|
||||
sql.replace(QLatin1String("%fts_table_noprefix"), fts_table_.section(QLatin1Char('.'), -1, -1));
|
||||
sql.replace(QLatin1String("%fts_table"), fts_table_);
|
||||
|
||||
if (!QSqlQuery::prepare(sql)) return false;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -29,11 +29,12 @@
|
|||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "core/sqlquery.h"
|
||||
|
||||
#include "collectionfilteroptions.h"
|
||||
|
||||
class CollectionQuery : public QSqlQuery {
|
||||
class CollectionQuery : public SqlQuery {
|
||||
public:
|
||||
explicit CollectionQuery(const QSqlDatabase &db, const QString &songs_table, const QString &fts_table, const CollectionFilterOptions &filter_options = CollectionFilterOptions());
|
||||
|
||||
|
@ -41,7 +42,7 @@ class CollectionQuery : public QSqlQuery {
|
|||
QVariant value(const int column) const { return Value(column); }
|
||||
|
||||
bool Exec();
|
||||
bool exec() { return QSqlQuery::exec(); }
|
||||
bool exec() { return SqlQuery::exec(); }
|
||||
|
||||
bool Next();
|
||||
|
||||
|
@ -67,9 +68,9 @@ class CollectionQuery : public QSqlQuery {
|
|||
QString RemoveSqlOperator(QString &token);
|
||||
// Adds a fragment of WHERE clause. When executed, this Query will connect all the fragments with AND operator.
|
||||
// Please note that IN operator expects a QStringList as value.
|
||||
void AddWhere(const QString &column, const QVariant &value, const QString &op = "=");
|
||||
void AddWhere(const QString &column, const QVariant &value, const QString &op = QStringLiteral("="));
|
||||
void AddWhereArtist(const QVariant &value);
|
||||
void AddWhereRating(const QVariant &value, const QString &op = "=");
|
||||
void AddWhereRating(const QVariant &value, const QString &op = QStringLiteral("="));
|
||||
|
||||
void SetBoundValues(const QVariantList &bound_values) { bound_values_ = bound_values; }
|
||||
void SetDuplicatesOnly(const bool duplicates_only) { duplicates_only_ = duplicates_only; }
|
||||
|
|
|
@ -51,7 +51,7 @@ class CollectionQueryOptions {
|
|||
void set_query_have_compilations(const bool query_have_compilations) { query_have_compilations_ = query_have_compilations; }
|
||||
|
||||
QList<Where> where_clauses() const { return where_clauses_; }
|
||||
void AddWhere(const QString &column, const QVariant &value, const QString &op = "=");
|
||||
void AddWhere(const QString &column, const QVariant &value, const QString &op = QStringLiteral("="));
|
||||
|
||||
private:
|
||||
QString column_spec_;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include <QtGlobal>
|
||||
|
@ -52,6 +53,7 @@
|
|||
#include "core/mimedata.h"
|
||||
#include "core/musicstorage.h"
|
||||
#include "core/deletefiles.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/filemanagerutils.h"
|
||||
#include "collection.h"
|
||||
#include "collectionbackend.h"
|
||||
|
@ -80,7 +82,7 @@ CollectionView::CollectionView(QWidget *parent)
|
|||
total_song_count_(-1),
|
||||
total_artist_count_(-1),
|
||||
total_album_count_(-1),
|
||||
nomusic_(":/pictures/nomusic.png"),
|
||||
nomusic_(QStringLiteral(":/pictures/nomusic.png")),
|
||||
context_menu_(nullptr),
|
||||
action_load_(nullptr),
|
||||
action_add_to_playlist_(nullptr),
|
||||
|
@ -88,6 +90,7 @@ CollectionView::CollectionView(QWidget *parent)
|
|||
action_add_to_playlist_enqueue_next_(nullptr),
|
||||
action_open_in_new_playlist_(nullptr),
|
||||
action_organize_(nullptr),
|
||||
action_search_for_this_(nullptr),
|
||||
#ifndef Q_OS_WIN
|
||||
action_copy_to_device_(nullptr),
|
||||
#endif
|
||||
|
@ -109,7 +112,7 @@ CollectionView::CollectionView(QWidget *parent)
|
|||
setDragDropMode(QAbstractItemView::DragOnly);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
setStyleSheet("QTreeView::item{padding-top:1px;}");
|
||||
setStyleSheet(QStringLiteral("QTreeView::item{padding-top:1px;}"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -128,7 +131,7 @@ void CollectionView::SaveFocus() {
|
|||
last_selected_container_ = QString();
|
||||
|
||||
switch (type.toInt()) {
|
||||
case CollectionItem::Type_Song: {
|
||||
case CollectionItem::Type_Song:{
|
||||
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
|
||||
SongList songs = app_->collection_model()->GetChildSongs(index);
|
||||
if (!songs.isEmpty()) {
|
||||
|
@ -138,7 +141,7 @@ void CollectionView::SaveFocus() {
|
|||
}
|
||||
|
||||
case CollectionItem::Type_Container:
|
||||
case CollectionItem::Type_Divider: {
|
||||
case CollectionItem::Type_Divider:{
|
||||
QString text = model()->data(current, CollectionModel::Role_SortText).toString();
|
||||
last_selected_container_ = text;
|
||||
break;
|
||||
|
@ -197,7 +200,7 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
|
|||
break;
|
||||
|
||||
case CollectionItem::Type_Container:
|
||||
case CollectionItem::Type_Divider: {
|
||||
case CollectionItem::Type_Divider:{
|
||||
QString text = model()->data(current, CollectionModel::Role_SortText).toString();
|
||||
if (!last_selected_container_.isEmpty() && last_selected_container_ == text) {
|
||||
expand(current);
|
||||
|
@ -224,7 +227,7 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
|
|||
|
||||
void CollectionView::ReloadSettings() {
|
||||
|
||||
QSettings settings;
|
||||
Settings settings;
|
||||
|
||||
settings.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
SetAutoOpen(settings.value("auto_open", false).toBool());
|
||||
|
@ -364,29 +367,29 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||
|
||||
if (!context_menu_) {
|
||||
context_menu_ = new QMenu(this);
|
||||
action_add_to_playlist_ = context_menu_->addAction(IconLoader::Load("media-playback-start"), tr("Append to current playlist"), this, &CollectionView::AddToPlaylist);
|
||||
action_load_ = context_menu_->addAction(IconLoader::Load("media-playback-start"), tr("Replace current playlist"), this, &CollectionView::Load);
|
||||
action_open_in_new_playlist_ = context_menu_->addAction(IconLoader::Load("document-new"), tr("Open in new playlist"), this, &CollectionView::OpenInNewPlaylist);
|
||||
action_add_to_playlist_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("media-playback-start")), tr("Append to current playlist"), this, &CollectionView::AddToPlaylist);
|
||||
action_load_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("media-playback-start")), tr("Replace current playlist"), this, &CollectionView::Load);
|
||||
action_open_in_new_playlist_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("document-new")), tr("Open in new playlist"), this, &CollectionView::OpenInNewPlaylist);
|
||||
|
||||
context_menu_->addSeparator();
|
||||
action_add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, &CollectionView::AddToPlaylistEnqueue);
|
||||
action_add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue to play next"), this, &CollectionView::AddToPlaylistEnqueueNext);
|
||||
action_add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("go-next")), tr("Queue track"), this, &CollectionView::AddToPlaylistEnqueue);
|
||||
action_add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("go-next")), tr("Queue to play next"), this, &CollectionView::AddToPlaylistEnqueueNext);
|
||||
|
||||
context_menu_->addSeparator();
|
||||
|
||||
action_search_for_this_ = context_menu_->addAction(IconLoader::Load("edit-find"), tr("Search for this"), this, &CollectionView::SearchForThis);
|
||||
action_search_for_this_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("edit-find")), tr("Search for this"), this, &CollectionView::SearchForThis);
|
||||
|
||||
context_menu_->addSeparator();
|
||||
action_organize_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, &CollectionView::Organize);
|
||||
action_organize_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("edit-copy")), tr("Organize files..."), this, &CollectionView::Organize);
|
||||
#ifndef Q_OS_WIN
|
||||
action_copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, &CollectionView::CopyToDevice);
|
||||
action_copy_to_device_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("device")), tr("Copy to device..."), this, &CollectionView::CopyToDevice);
|
||||
#endif
|
||||
action_delete_files_ = context_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, &CollectionView::Delete);
|
||||
action_delete_files_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("edit-delete")), tr("Delete from disk..."), this, &CollectionView::Delete);
|
||||
|
||||
context_menu_->addSeparator();
|
||||
action_edit_track_ = context_menu_->addAction(IconLoader::Load("edit-rename"), tr("Edit track information..."), this, &CollectionView::EditTracks);
|
||||
action_edit_tracks_ = context_menu_->addAction(IconLoader::Load("edit-rename"), tr("Edit tracks information..."), this, &CollectionView::EditTracks);
|
||||
action_show_in_browser_ = context_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, &CollectionView::ShowInBrowser);
|
||||
action_edit_track_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("edit-rename")), tr("Edit track information..."), this, &CollectionView::EditTracks);
|
||||
action_edit_tracks_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("edit-rename")), tr("Edit tracks information..."), this, &CollectionView::EditTracks);
|
||||
action_show_in_browser_ = context_menu_->addAction(IconLoader::Load(QStringLiteral("document-open-folder")), tr("Show in file browser..."), this, &CollectionView::ShowInBrowser);
|
||||
|
||||
context_menu_->addSeparator();
|
||||
|
||||
|
@ -412,7 +415,7 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||
|
||||
context_menu_index_ = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(context_menu_index_);
|
||||
|
||||
QModelIndexList selected_indexes = qobject_cast<QSortFilterProxyModel*>(model())->mapSelectionToSource(selectionModel()->selection()).indexes();
|
||||
const QModelIndexList selected_indexes = qobject_cast<QSortFilterProxyModel*>(model())->mapSelectionToSource(selectionModel()->selection()).indexes();
|
||||
|
||||
int regular_elements = 0;
|
||||
int regular_editable = 0;
|
||||
|
@ -483,7 +486,8 @@ void CollectionView::SetShowInVarious(const bool on) {
|
|||
// We put through "Various Artists" changes one album at a time,
|
||||
// to make sure the old album node gets removed (due to all children removed), before the new one gets added
|
||||
QMultiMap<QString, QString> albums;
|
||||
for (const Song &song : GetSelectedSongs()) {
|
||||
const SongList songs = GetSelectedSongs();
|
||||
for (const Song &song : songs) {
|
||||
if (albums.find(song.album(), song.artist()) == albums.end())
|
||||
albums.insert(song.album(), song.artist());
|
||||
}
|
||||
|
@ -493,7 +497,7 @@ void CollectionView::SetShowInVarious(const bool on) {
|
|||
if (on && albums.keys().count() == 1) {
|
||||
const QStringList albums_list = albums.keys();
|
||||
const QString album = albums_list.first();
|
||||
SongList all_of_album = app_->collection_backend()->GetSongsByAlbum(album);
|
||||
const SongList all_of_album = app_->collection_backend()->GetSongsByAlbum(album);
|
||||
QSet<QString> other_artists;
|
||||
for (const Song &s : all_of_album) {
|
||||
if (!albums.contains(album, s.artist()) && !other_artists.contains(s.artist())) {
|
||||
|
@ -510,9 +514,9 @@ void CollectionView::SetShowInVarious(const bool on) {
|
|||
}
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QSet<QString> albums_set = QSet<QString>(albums.keyBegin(), albums.keyEnd());
|
||||
const QSet<QString> albums_set = QSet<QString>(albums.keyBegin(), albums.keyEnd());
|
||||
#else
|
||||
QSet<QString> albums_set = QSet<QString>::fromList(albums.keys());
|
||||
const QSet<QString> albums_set = QSet<QString>::fromList(albums.keys());
|
||||
#endif
|
||||
for (const QString &album : albums_set) {
|
||||
app_->collection_backend()->ForceCompilation(album, albums.values(album), on);
|
||||
|
@ -582,7 +586,7 @@ void CollectionView::SearchForThis() {
|
|||
if (!songs.isEmpty()) {
|
||||
last_selected_song_ = songs.last();
|
||||
}
|
||||
search = QString("title:%1").arg(last_selected_song_.title());
|
||||
search = QStringLiteral("title:%1").arg(last_selected_song_.title());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -598,53 +602,53 @@ void CollectionView::SearchForThis() {
|
|||
|
||||
switch (container_group_by) {
|
||||
case CollectionModel::GroupBy::AlbumArtist:
|
||||
search = QString("albumartist:%1").arg(item->metadata.effective_albumartist());
|
||||
search = QStringLiteral("albumartist:%1").arg(item->metadata.effective_albumartist());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Artist:
|
||||
search = QString("artist:%1").arg(item->metadata.artist());
|
||||
search = QStringLiteral("artist:%1").arg(item->metadata.artist());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Album:
|
||||
search = QString("album:%1").arg(item->metadata.album());
|
||||
search = QStringLiteral("album:%1").arg(item->metadata.album());
|
||||
break;
|
||||
case CollectionModel::GroupBy::AlbumDisc:
|
||||
search = QString("album:%1").arg(item->metadata.album());
|
||||
search = QStringLiteral("album:%1").arg(item->metadata.album());
|
||||
break;
|
||||
case CollectionModel::GroupBy::YearAlbum:
|
||||
case CollectionModel::GroupBy::YearAlbumDisc:{
|
||||
search = QString("year:%1 album:%2").arg(item->metadata.year()).arg(item->metadata.album());
|
||||
search = QStringLiteral("year:%1 album:%2").arg(item->metadata.year()).arg(item->metadata.album());
|
||||
break;
|
||||
}
|
||||
case CollectionModel::GroupBy::OriginalYearAlbum:
|
||||
case CollectionModel::GroupBy::OriginalYearAlbumDisc:{
|
||||
search = QString("year:%1 album:%2").arg(item->metadata.effective_originalyear()).arg(item->metadata.album());
|
||||
search = QStringLiteral("year:%1 album:%2").arg(item->metadata.effective_originalyear()).arg(item->metadata.album());
|
||||
break;
|
||||
}
|
||||
case CollectionModel::GroupBy::Year:
|
||||
search = QString("year:%1").arg(item->metadata.year());
|
||||
search = QStringLiteral("year:%1").arg(item->metadata.year());
|
||||
break;
|
||||
case CollectionModel::GroupBy::OriginalYear:
|
||||
search = QString("year:%1").arg(item->metadata.effective_originalyear());
|
||||
search = QStringLiteral("year:%1").arg(item->metadata.effective_originalyear());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Genre:
|
||||
search = QString("genre:%1").arg(item->metadata.genre());
|
||||
search = QStringLiteral("genre:%1").arg(item->metadata.genre());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Composer:
|
||||
search = QString("composer:%1").arg(item->metadata.composer());
|
||||
search = QStringLiteral("composer:%1").arg(item->metadata.composer());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Performer:
|
||||
search = QString("performer:%1").arg(item->metadata.performer());
|
||||
search = QStringLiteral("performer:%1").arg(item->metadata.performer());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Grouping:
|
||||
search = QString("grouping:%1").arg(item->metadata.grouping());
|
||||
search = QStringLiteral("grouping:%1").arg(item->metadata.grouping());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Samplerate:
|
||||
search = QString("samplerate:%1").arg(item->metadata.samplerate());
|
||||
search = QStringLiteral("samplerate:%1").arg(item->metadata.samplerate());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Bitdepth:
|
||||
search = QString("bitdepth:%1").arg(item->metadata.bitdepth());
|
||||
search = QStringLiteral("bitdepth:%1").arg(item->metadata.bitdepth());
|
||||
break;
|
||||
case CollectionModel::GroupBy::Bitrate:
|
||||
search = QString("bitrate:%1").arg(item->metadata.bitrate());
|
||||
search = QStringLiteral("bitrate:%1").arg(item->metadata.bitrate());
|
||||
break;
|
||||
default:
|
||||
search = model()->data(current, Qt::DisplayRole).toString();
|
||||
|
@ -761,7 +765,7 @@ void CollectionView::FilterReturnPressed() {
|
|||
|
||||
void CollectionView::ShowInBrowser() const {
|
||||
|
||||
SongList songs = GetSelectedSongs();
|
||||
const SongList songs = GetSelectedSongs();
|
||||
QList<QUrl> urls;
|
||||
urls.reserve(songs.count());
|
||||
for (const Song &song : songs) {
|
||||
|
@ -786,7 +790,7 @@ void CollectionView::Delete() {
|
|||
|
||||
if (!delete_files_) return;
|
||||
|
||||
SongList selected_songs = GetSelectedSongs();
|
||||
const SongList selected_songs = GetSelectedSongs();
|
||||
|
||||
SongList songs;
|
||||
QStringList files;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "core/logging.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/imageutils.h"
|
||||
#include "utilities/timeconstants.h"
|
||||
#include "collectiondirectory.h"
|
||||
|
@ -70,8 +71,8 @@
|
|||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
QStringList CollectionWatcher::sValidImages = QStringList() << "jpg" << "png" << "gif" << "jpeg";
|
||||
QStringList CollectionWatcher::kIgnoredExtensions = QStringList() << "tmp" << "tar" << "gz" << "bz2" << "xz" << "tbz" << "tgz" << "z" << "zip" << "rar";
|
||||
QStringList CollectionWatcher::sValidImages = QStringList() << QStringLiteral("jpg") << QStringLiteral("png") << QStringLiteral("gif") << QStringLiteral("jpeg");
|
||||
QStringList CollectionWatcher::kIgnoredExtensions = QStringList() << QStringLiteral("tmp") << QStringLiteral("tar") << QStringLiteral("gz") << QStringLiteral("bz2") << QStringLiteral("xz") << QStringLiteral("tbz") << QStringLiteral("tgz") << QStringLiteral("z") << QStringLiteral("zip") << QStringLiteral("rar");
|
||||
|
||||
CollectionWatcher::CollectionWatcher(Song::Source source, QObject *parent)
|
||||
: QObject(parent),
|
||||
|
@ -105,7 +106,7 @@ CollectionWatcher::CollectionWatcher(Song::Source source, QObject *parent)
|
|||
periodic_scan_timer_->setInterval(86400 * kMsecPerSec);
|
||||
periodic_scan_timer_->setSingleShot(false);
|
||||
|
||||
QStringList image_formats = ImageUtils::SupportedImageFormats();
|
||||
const QStringList image_formats = ImageUtils::SupportedImageFormats();
|
||||
for (const QString &format : image_formats) {
|
||||
if (!sValidImages.contains(format)) {
|
||||
sValidImages.append(format);
|
||||
|
@ -150,11 +151,11 @@ void CollectionWatcher::ReloadSettingsAsync() {
|
|||
void CollectionWatcher::ReloadSettings() {
|
||||
|
||||
const bool was_monitoring_before = monitor_;
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
scan_on_startup_ = s.value("startup_scan", true).toBool();
|
||||
monitor_ = s.value("monitor", true).toBool();
|
||||
QStringList filters = s.value("cover_art_patterns", QStringList() << "front" << "cover").toStringList();
|
||||
const QStringList filters = s.value("cover_art_patterns", QStringList() << QStringLiteral("front") << QStringLiteral("cover")).toStringList();
|
||||
if (source_ == Song::Source::Collection) {
|
||||
song_tracking_ = s.value("song_tracking", false).toBool();
|
||||
song_ebur128_loudness_analysis_ = s.value("song_ebur128_loudness_analysis", false).toBool();
|
||||
|
@ -182,7 +183,7 @@ void CollectionWatcher::ReloadSettings() {
|
|||
else if (monitor_ && !was_monitoring_before) {
|
||||
// Add all directories to all QFileSystemWatchers again
|
||||
for (const CollectionDirectory &dir : std::as_const(watched_dirs_)) {
|
||||
CollectionSubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id);
|
||||
const CollectionSubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id);
|
||||
for (const CollectionSubdirectory &subdir : subdirs) {
|
||||
AddWatch(dir, subdir.path);
|
||||
}
|
||||
|
@ -287,7 +288,7 @@ void CollectionWatcher::ScanTransaction::CommitNewOrUpdatedSongs() {
|
|||
touched_subdirs.clear();
|
||||
}
|
||||
|
||||
for (const CollectionSubdirectory &subdir : deleted_subdirs) {
|
||||
for (const CollectionSubdirectory &subdir : std::as_const(deleted_subdirs)) {
|
||||
if (watcher_->watched_dirs_.contains(dir_)) {
|
||||
watcher_->RemoveWatch(watcher_->watched_dirs_[dir_], subdir);
|
||||
}
|
||||
|
@ -296,7 +297,7 @@ void CollectionWatcher::ScanTransaction::CommitNewOrUpdatedSongs() {
|
|||
|
||||
if (watcher_->monitor_) {
|
||||
// Watch the new subdirectories
|
||||
for (const CollectionSubdirectory &subdir : new_subdirs) {
|
||||
for (const CollectionSubdirectory &subdir : std::as_const(new_subdirs)) {
|
||||
if (watcher_->watched_dirs_.contains(dir_)) {
|
||||
watcher_->AddWatch(watcher_->watched_dirs_[dir_], subdir.path);
|
||||
}
|
||||
|
@ -316,7 +317,7 @@ SongList CollectionWatcher::ScanTransaction::FindSongsInSubdirectory(const QStri
|
|||
if (cached_songs_dirty_) {
|
||||
const SongList songs = watcher_->backend_->FindSongsInDirectory(dir_);
|
||||
for (const Song &song : songs) {
|
||||
const QString p = song.url().toLocalFile().section('/', 0, -2);
|
||||
const QString p = song.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
|
||||
cached_songs_.insert(p, song);
|
||||
}
|
||||
cached_songs_dirty_ = false;
|
||||
|
@ -334,7 +335,7 @@ bool CollectionWatcher::ScanTransaction::HasSongsWithMissingFingerprint(const QS
|
|||
if (cached_songs_missing_fingerprint_dirty_) {
|
||||
const SongList songs = watcher_->backend_->SongsWithMissingFingerprint(dir_);
|
||||
for (const Song &song : songs) {
|
||||
const QString p = song.url().toLocalFile().section('/', 0, -2);
|
||||
const QString p = song.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
|
||||
cached_songs_missing_fingerprint_.insert(p, song);
|
||||
}
|
||||
cached_songs_missing_fingerprint_dirty_ = false;
|
||||
|
@ -349,7 +350,7 @@ bool CollectionWatcher::ScanTransaction::HasSongsWithMissingLoudnessCharacterist
|
|||
if (cached_songs_missing_loudness_characteristics_dirty_) {
|
||||
const SongList songs = watcher_->backend_->SongsWithMissingLoudnessCharacteristics(dir_);
|
||||
for (const Song &song : songs) {
|
||||
const QString p = song.url().toLocalFile().section('/', 0, -2);
|
||||
const QString p = song.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
|
||||
cached_songs_missing_loudness_characteristics_.insert(p, song);
|
||||
}
|
||||
cached_songs_missing_loudness_characteristics_dirty_ = false;
|
||||
|
@ -383,7 +384,7 @@ CollectionSubdirectoryList CollectionWatcher::ScanTransaction::GetImmediateSubdi
|
|||
}
|
||||
|
||||
CollectionSubdirectoryList ret;
|
||||
for (const CollectionSubdirectory &subdir : known_subdirs_) {
|
||||
for (const CollectionSubdirectory &subdir : std::as_const(known_subdirs_)) {
|
||||
if (subdir.path.left(subdir.path.lastIndexOf(QDir::separator())) == path && subdir.mtime != 0) {
|
||||
ret << subdir;
|
||||
}
|
||||
|
@ -416,7 +417,7 @@ void CollectionWatcher::AddDirectory(const CollectionDirectory &dir, const Colle
|
|||
transaction.SetKnownSubdirs(subdirs);
|
||||
transaction.AddToProgressMax(files_count);
|
||||
ScanSubdirectory(dir.path, CollectionSubdirectory(), files_count, &transaction);
|
||||
last_scan_time_ = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
last_scan_time_ = QDateTime::currentSecsSinceEpoch();
|
||||
}
|
||||
else {
|
||||
// We can do an incremental scan - looking at the mtimes of each subdirectory and only rescan if the directory has changed.
|
||||
|
@ -433,7 +434,7 @@ void CollectionWatcher::AddDirectory(const CollectionDirectory &dir, const Colle
|
|||
if (monitor_) AddWatch(dir, subdir.path);
|
||||
}
|
||||
|
||||
last_scan_time_ = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
last_scan_time_ = QDateTime::currentSecsSinceEpoch();
|
||||
|
||||
}
|
||||
|
||||
|
@ -480,7 +481,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
|
||||
// If a directory is moved then only its parent gets a changed notification, so we need to look and see if any of our children don't exist anymore.
|
||||
// If one has been removed, "rescan" it to get the deleted songs
|
||||
CollectionSubdirectoryList previous_subdirs = t->GetImmediateSubdirs(path);
|
||||
const CollectionSubdirectoryList previous_subdirs = t->GetImmediateSubdirs(path);
|
||||
for (const CollectionSubdirectory &prev_subdir : previous_subdirs) {
|
||||
if (!QFile::exists(prev_subdir.path) && prev_subdir.path != path) {
|
||||
ScanSubdirectory(prev_subdir.path, prev_subdir, 0, t, true);
|
||||
|
@ -510,7 +511,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
else {
|
||||
QString ext_part(ExtensionPart(child));
|
||||
QString dir_part(DirectoryPart(child));
|
||||
if (kIgnoredExtensions.contains(child_info.suffix(), Qt::CaseInsensitive) || child_info.baseName() == "qt_temp") {
|
||||
if (kIgnoredExtensions.contains(child_info.suffix(), Qt::CaseInsensitive) || child_info.baseName() == QStringLiteral("qt_temp")) {
|
||||
t->AddToProgress(1);
|
||||
}
|
||||
else if (sValidImages.contains(ext_part)) {
|
||||
|
@ -612,7 +613,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
Chromaprinter chromaprinter(file);
|
||||
fingerprint = chromaprinter.CreateFingerprint();
|
||||
if (fingerprint.isEmpty()) {
|
||||
fingerprint = "NONE";
|
||||
fingerprint = QStringLiteral("NONE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -639,11 +640,11 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
Chromaprinter chromaprinter(file);
|
||||
fingerprint = chromaprinter.CreateFingerprint();
|
||||
if (fingerprint.isEmpty()) {
|
||||
fingerprint = "NONE";
|
||||
fingerprint = QStringLiteral("NONE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (song_tracking_ && !fingerprint.isEmpty() && fingerprint != "NONE" && FindSongsByFingerprint(file, fingerprint, &matching_songs)) {
|
||||
if (song_tracking_ && !fingerprint.isEmpty() && fingerprint != QStringLiteral("NONE") && FindSongsByFingerprint(file, fingerprint, &matching_songs)) {
|
||||
|
||||
// The song is in the database and still on disk.
|
||||
// Check the mtime to see if it's been changed since it was added.
|
||||
|
@ -657,7 +658,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
|
||||
// Make sure the songs aren't deleted, as they still exist elsewhere with a different file path.
|
||||
bool matching_songs_has_cue = false;
|
||||
for (const Song &matching_song : matching_songs) {
|
||||
for (const Song &matching_song : std::as_const(matching_songs)) {
|
||||
QString matching_filename = matching_song.url().toLocalFile();
|
||||
if (!t->files_changed_path_.contains(matching_filename)) {
|
||||
t->files_changed_path_ << matching_filename;
|
||||
|
@ -690,7 +691,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
}
|
||||
else { // The song is on disk but not in the DB
|
||||
|
||||
SongList songs = ScanNewFile(file, path, fingerprint, new_cue, &cues_processed);
|
||||
const SongList songs = ScanNewFile(file, path, fingerprint, new_cue, &cues_processed);
|
||||
if (songs.isEmpty()) {
|
||||
t->AddToProgress(1);
|
||||
continue;
|
||||
|
@ -712,7 +713,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
}
|
||||
|
||||
// Look for deleted songs
|
||||
for (const Song &song : songs_in_db) {
|
||||
for (const Song &song : std::as_const(songs_in_db)) {
|
||||
QString file = song.url().toLocalFile();
|
||||
if (!song.unavailable() && !files_on_disk.contains(file) && !t->files_changed_path_.contains(file)) {
|
||||
qLog(Debug) << "Song deleted from disk:" << file;
|
||||
|
@ -738,7 +739,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||
}
|
||||
|
||||
// Recurse into the new subdirs that we found
|
||||
for (const CollectionSubdirectory &my_new_subdir : my_new_subdirs) {
|
||||
for (const CollectionSubdirectory &my_new_subdir : std::as_const(my_new_subdirs)) {
|
||||
if (stop_requested_ || abort_requested_) return;
|
||||
ScanSubdirectory(my_new_subdir.path, my_new_subdir, 0, t, true);
|
||||
}
|
||||
|
@ -892,50 +893,50 @@ void CollectionWatcher::AddChangedSong(const QString &file, const Song &matching
|
|||
}
|
||||
else {
|
||||
if (matching_song.url() != new_song.url()) {
|
||||
changes << "file path";
|
||||
changes << QStringLiteral("file path");
|
||||
notify_new = true;
|
||||
}
|
||||
if (matching_song.fingerprint() != new_song.fingerprint()) {
|
||||
changes << "fingerprint";
|
||||
changes << QStringLiteral("fingerprint");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsMetadataEqual(new_song)) {
|
||||
changes << "metadata";
|
||||
changes << QStringLiteral("metadata");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsPlayStatisticsEqual(new_song)) {
|
||||
changes << "play statistics";
|
||||
changes << QStringLiteral("play statistics");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsRatingEqual(new_song)) {
|
||||
changes << "rating";
|
||||
changes << QStringLiteral("rating");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsArtEqual(new_song)) {
|
||||
changes << "album art";
|
||||
changes << QStringLiteral("album art");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsAcoustIdEqual(new_song)) {
|
||||
changes << "acoustid";
|
||||
changes << QStringLiteral("acoustid");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsMusicBrainzEqual(new_song)) {
|
||||
changes << "musicbrainz";
|
||||
changes << QStringLiteral("musicbrainz");
|
||||
notify_new = true;
|
||||
}
|
||||
if (!matching_song.IsEBUR128Equal(new_song)) {
|
||||
changes << "ebur128 loudness characteristics";
|
||||
changes << QStringLiteral("ebur128 loudness characteristics");
|
||||
notify_new = true;
|
||||
}
|
||||
if (matching_song.mtime() != new_song.mtime()) {
|
||||
changes << "mtime";
|
||||
changes << QStringLiteral("mtime");
|
||||
}
|
||||
|
||||
if (changes.isEmpty()) {
|
||||
qLog(Debug) << "Song" << file << "unchanged.";
|
||||
}
|
||||
else {
|
||||
qLog(Debug) << "Song" << file << changes.join(", ") << "changed.";
|
||||
qLog(Debug) << "Song" << file << changes.join(QStringLiteral(", ")) << "changed.";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -990,7 +991,7 @@ void CollectionWatcher::AddWatch(const CollectionDirectory &dir, const QString &
|
|||
|
||||
void CollectionWatcher::RemoveWatch(const CollectionDirectory &dir, const CollectionSubdirectory &subdir) {
|
||||
|
||||
QStringList subdir_paths = subdir_mapping_.keys(dir);
|
||||
const QStringList subdir_paths = subdir_mapping_.keys(dir);
|
||||
for (const QString &subdir_path : subdir_paths) {
|
||||
if (subdir_path != subdir.path) continue;
|
||||
fs_watcher_->RemovePath(subdir_path);
|
||||
|
@ -1007,7 +1008,7 @@ void CollectionWatcher::RemoveDirectory(const CollectionDirectory &dir) {
|
|||
|
||||
// Stop watching the directory's subdirectories
|
||||
QStringList subdir_paths = subdir_mapping_.keys(dir);
|
||||
for (const QString &subdir_path : subdir_paths) {
|
||||
for (const QString &subdir_path : std::as_const(subdir_paths)) {
|
||||
fs_watcher_->RemovePath(subdir_path);
|
||||
subdir_mapping_.remove(subdir_path);
|
||||
}
|
||||
|
@ -1029,7 +1030,7 @@ bool CollectionWatcher::FindSongsByPath(const SongList &songs, const QString &pa
|
|||
bool CollectionWatcher::FindSongsByFingerprint(const QString &file, const QString &fingerprint, SongList *out) {
|
||||
|
||||
SongList songs = backend_->GetSongsByFingerprint(fingerprint);
|
||||
for (const Song &song : songs) {
|
||||
for (const Song &song : std::as_const(songs)) {
|
||||
QString filename = song.url().toLocalFile();
|
||||
QFileInfo info(filename);
|
||||
// Allow mulitiple songs in different directories with the same fingerprint.
|
||||
|
@ -1077,19 +1078,21 @@ void CollectionWatcher::DirectoryChanged(const QString &subdir) {
|
|||
|
||||
void CollectionWatcher::RescanPathsNow() {
|
||||
|
||||
QList<int> dirs = rescan_queue_.keys();
|
||||
const QList<int> dirs = rescan_queue_.keys();
|
||||
for (const int dir : dirs) {
|
||||
if (stop_requested_ || abort_requested_) break;
|
||||
ScanTransaction transaction(this, dir, false, false, mark_songs_unavailable_);
|
||||
|
||||
const QStringList paths = rescan_queue_[dir];
|
||||
|
||||
QMap<QString, quint64> subdir_files_count;
|
||||
for (const QString &path : rescan_queue_[dir]) {
|
||||
for (const QString &path : paths) {
|
||||
quint64 files_count = FilesCountForPath(&transaction, path);
|
||||
subdir_files_count[path] = files_count;
|
||||
transaction.AddToProgressMax(files_count);
|
||||
}
|
||||
|
||||
for (const QString &path : rescan_queue_[dir]) {
|
||||
for (const QString &path : paths) {
|
||||
if (stop_requested_ || abort_requested_) break;
|
||||
CollectionSubdirectory subdir;
|
||||
subdir.directory_id = dir;
|
||||
|
@ -1112,7 +1115,7 @@ QString CollectionWatcher::PickBestArt(const QStringList &art_automatic_list) {
|
|||
|
||||
QStringList filtered;
|
||||
|
||||
for (const QString &filter_text : best_art_filters_) {
|
||||
for (const QString &filter_text : std::as_const(best_art_filters_)) {
|
||||
// The images in the images list are represented by a full path, so we need to isolate just the filename
|
||||
for (const QString &art_automatic : art_automatic_list) {
|
||||
QFileInfo fileinfo(art_automatic);
|
||||
|
@ -1134,7 +1137,7 @@ QString CollectionWatcher::PickBestArt(const QStringList &art_automatic_list) {
|
|||
int biggest_size = 0;
|
||||
QString biggest_path;
|
||||
|
||||
for (const QString &path : filtered) {
|
||||
for (const QString &path : std::as_const(filtered)) {
|
||||
if (stop_requested_ || abort_requested_) break;
|
||||
|
||||
QImage image(path);
|
||||
|
@ -1197,7 +1200,7 @@ void CollectionWatcher::FullScanAsync() {
|
|||
|
||||
void CollectionWatcher::IncrementalScanCheck() {
|
||||
|
||||
qint64 duration = QDateTime::currentDateTime().toSecsSinceEpoch() - last_scan_time_;
|
||||
qint64 duration = QDateTime::currentSecsSinceEpoch() - last_scan_time_;
|
||||
if (duration >= 86400) {
|
||||
qLog(Debug) << "Performing periodic incremental scan.";
|
||||
IncrementalScanNow();
|
||||
|
@ -1232,14 +1235,14 @@ void CollectionWatcher::PerformScan(const bool incremental, const bool ignore_mt
|
|||
quint64 files_count = FilesCountForSubdirs(&transaction, subdirs, subdir_files_count);
|
||||
transaction.AddToProgressMax(files_count);
|
||||
|
||||
for (const CollectionSubdirectory &subdir : subdirs) {
|
||||
for (const CollectionSubdirectory &subdir : std::as_const(subdirs)) {
|
||||
if (stop_requested_ || abort_requested_) break;
|
||||
ScanSubdirectory(subdir.path, subdir, subdir_files_count[subdir.path], &transaction);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
last_scan_time_ = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
last_scan_time_ = QDateTime::currentSecsSinceEpoch();
|
||||
|
||||
emit CompilationsNeedUpdating();
|
||||
|
||||
|
@ -1308,10 +1311,10 @@ void CollectionWatcher::RescanSongs(const SongList &songs) {
|
|||
QStringList scanned_paths;
|
||||
for (const Song &song : songs) {
|
||||
if (stop_requested_ || abort_requested_) break;
|
||||
const QString song_path = song.url().toLocalFile().section('/', 0, -2);
|
||||
const QString song_path = song.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
|
||||
if (scanned_paths.contains(song_path)) continue;
|
||||
ScanTransaction transaction(this, song.directory_id(), false, true, mark_songs_unavailable_);
|
||||
CollectionSubdirectoryList subdirs(transaction.GetAllSubdirs());
|
||||
const CollectionSubdirectoryList subdirs = transaction.GetAllSubdirs();
|
||||
for (const CollectionSubdirectory &subdir : subdirs) {
|
||||
if (stop_requested_ || abort_requested_) break;
|
||||
if (subdir.path != song_path) continue;
|
||||
|
|
|
@ -252,14 +252,14 @@ class CollectionWatcher : public QObject {
|
|||
};
|
||||
|
||||
inline QString CollectionWatcher::NoExtensionPart(const QString &fileName) {
|
||||
return fileName.contains('.') ? fileName.section('.', 0, -2) : "";
|
||||
return fileName.contains(QLatin1Char('.')) ? fileName.section(QLatin1Char('.'), 0, -2) : QLatin1String("");
|
||||
}
|
||||
// Thanks Amarok
|
||||
inline QString CollectionWatcher::ExtensionPart(const QString &fileName) {
|
||||
return fileName.contains( '.' ) ? fileName.mid( fileName.lastIndexOf('.') + 1 ).toLower() : "";
|
||||
return fileName.contains(QLatin1Char('.')) ? fileName.mid(fileName.lastIndexOf(QLatin1Char('.')) + 1).toLower() : QLatin1String("");
|
||||
}
|
||||
inline QString CollectionWatcher::DirectoryPart(const QString &fileName) {
|
||||
return fileName.section('/', 0, -2);
|
||||
return fileName.section(QLatin1Char('/'), 0, -2);
|
||||
}
|
||||
|
||||
#endif // COLLECTIONWATCHER_H
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QStandardItemModel>
|
||||
#include <QItemSelectionModel>
|
||||
|
@ -36,6 +38,7 @@
|
|||
|
||||
#include "core/logging.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/settings.h"
|
||||
#include "settings/collectionsettingspage.h"
|
||||
#include "collectionmodel.h"
|
||||
#include "savedgroupingmanager.h"
|
||||
|
@ -56,7 +59,7 @@ SavedGroupingManager::SavedGroupingManager(const QString &saved_groupings_settin
|
|||
model_->setHorizontalHeaderItem(2, new QStandardItem(tr("Second Level")));
|
||||
model_->setHorizontalHeaderItem(3, new QStandardItem(tr("Third Level")));
|
||||
ui_->list->setModel(model_);
|
||||
ui_->remove->setIcon(IconLoader::Load("edit-delete"));
|
||||
ui_->remove->setIcon(IconLoader::Load(QStringLiteral("edit-delete")));
|
||||
ui_->remove->setEnabled(false);
|
||||
|
||||
ui_->remove->setShortcut(QKeySequence::Delete);
|
||||
|
@ -72,11 +75,11 @@ SavedGroupingManager::~SavedGroupingManager() {
|
|||
|
||||
QString SavedGroupingManager::GetSavedGroupingsSettingsGroup(const QString &settings_group) {
|
||||
|
||||
if (settings_group.isEmpty() || settings_group == CollectionSettingsPage::kSettingsGroup) {
|
||||
return kSavedGroupingsSettingsGroup;
|
||||
if (settings_group.isEmpty() || settings_group == QLatin1String(CollectionSettingsPage::kSettingsGroup)) {
|
||||
return QLatin1String(kSavedGroupingsSettingsGroup);
|
||||
}
|
||||
else {
|
||||
return QString(kSavedGroupingsSettingsGroup) + "_" + settings_group;
|
||||
return QLatin1String(kSavedGroupingsSettingsGroup) + QLatin1Char('_') + settings_group;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -85,67 +88,67 @@ QString SavedGroupingManager::GroupByToString(const CollectionModel::GroupBy g)
|
|||
|
||||
switch (g) {
|
||||
case CollectionModel::GroupBy::None:
|
||||
case CollectionModel::GroupBy::GroupByCount: {
|
||||
case CollectionModel::GroupBy::GroupByCount:{
|
||||
return tr("None");
|
||||
}
|
||||
case CollectionModel::GroupBy::AlbumArtist: {
|
||||
case CollectionModel::GroupBy::AlbumArtist:{
|
||||
return tr("Album artist");
|
||||
}
|
||||
case CollectionModel::GroupBy::Artist: {
|
||||
case CollectionModel::GroupBy::Artist:{
|
||||
return tr("Artist");
|
||||
}
|
||||
case CollectionModel::GroupBy::Album: {
|
||||
case CollectionModel::GroupBy::Album:{
|
||||
return tr("Album");
|
||||
}
|
||||
case CollectionModel::GroupBy::AlbumDisc: {
|
||||
case CollectionModel::GroupBy::AlbumDisc:{
|
||||
return tr("Album - Disc");
|
||||
}
|
||||
case CollectionModel::GroupBy::YearAlbum: {
|
||||
case CollectionModel::GroupBy::YearAlbum:{
|
||||
return tr("Year - Album");
|
||||
}
|
||||
case CollectionModel::GroupBy::YearAlbumDisc: {
|
||||
case CollectionModel::GroupBy::YearAlbumDisc:{
|
||||
return tr("Year - Album - Disc");
|
||||
}
|
||||
case CollectionModel::GroupBy::OriginalYearAlbum: {
|
||||
case CollectionModel::GroupBy::OriginalYearAlbum:{
|
||||
return tr("Original year - Album");
|
||||
}
|
||||
case CollectionModel::GroupBy::OriginalYearAlbumDisc: {
|
||||
case CollectionModel::GroupBy::OriginalYearAlbumDisc:{
|
||||
return tr("Original year - Album - Disc");
|
||||
}
|
||||
case CollectionModel::GroupBy::Disc: {
|
||||
case CollectionModel::GroupBy::Disc:{
|
||||
return tr("Disc");
|
||||
}
|
||||
case CollectionModel::GroupBy::Year: {
|
||||
case CollectionModel::GroupBy::Year:{
|
||||
return tr("Year");
|
||||
}
|
||||
case CollectionModel::GroupBy::OriginalYear: {
|
||||
case CollectionModel::GroupBy::OriginalYear:{
|
||||
return tr("Original year");
|
||||
}
|
||||
case CollectionModel::GroupBy::Genre: {
|
||||
case CollectionModel::GroupBy::Genre:{
|
||||
return tr("Genre");
|
||||
}
|
||||
case CollectionModel::GroupBy::Composer: {
|
||||
case CollectionModel::GroupBy::Composer:{
|
||||
return tr("Composer");
|
||||
}
|
||||
case CollectionModel::GroupBy::Performer: {
|
||||
case CollectionModel::GroupBy::Performer:{
|
||||
return tr("Performer");
|
||||
}
|
||||
case CollectionModel::GroupBy::Grouping: {
|
||||
case CollectionModel::GroupBy::Grouping:{
|
||||
return tr("Grouping");
|
||||
}
|
||||
case CollectionModel::GroupBy::FileType: {
|
||||
case CollectionModel::GroupBy::FileType:{
|
||||
return tr("File type");
|
||||
}
|
||||
case CollectionModel::GroupBy::Format: {
|
||||
case CollectionModel::GroupBy::Format:{
|
||||
return tr("Format");
|
||||
}
|
||||
case CollectionModel::GroupBy::Samplerate: {
|
||||
case CollectionModel::GroupBy::Samplerate:{
|
||||
return tr("Sample rate");
|
||||
}
|
||||
case CollectionModel::GroupBy::Bitdepth: {
|
||||
case CollectionModel::GroupBy::Bitdepth:{
|
||||
return tr("Bit depth");
|
||||
}
|
||||
case CollectionModel::GroupBy::Bitrate: {
|
||||
case CollectionModel::GroupBy::Bitrate:{
|
||||
return tr("Bitrate");
|
||||
}
|
||||
}
|
||||
|
@ -157,13 +160,13 @@ QString SavedGroupingManager::GroupByToString(const CollectionModel::GroupBy g)
|
|||
void SavedGroupingManager::UpdateModel() {
|
||||
|
||||
model_->setRowCount(0); // don't use clear, it deletes headers
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(saved_groupings_settings_group_);
|
||||
int version = s.value("version").toInt();
|
||||
if (version == 1) {
|
||||
QStringList saved = s.childKeys();
|
||||
for (int i = 0; i < saved.size(); ++i) {
|
||||
if (saved.at(i) == "version") continue;
|
||||
if (saved.at(i) == QStringLiteral("version")) continue;
|
||||
QByteArray bytes = s.value(saved.at(i)).toByteArray();
|
||||
QDataStream ds(&bytes, QIODevice::ReadOnly);
|
||||
CollectionModel::Grouping g;
|
||||
|
@ -181,7 +184,7 @@ void SavedGroupingManager::UpdateModel() {
|
|||
else {
|
||||
QStringList saved = s.childKeys();
|
||||
for (int i = 0; i < saved.size(); ++i) {
|
||||
if (saved.at(i) == "version") continue;
|
||||
if (saved.at(i) == QStringLiteral("version")) continue;
|
||||
s.remove(saved.at(i));
|
||||
}
|
||||
}
|
||||
|
@ -192,9 +195,10 @@ void SavedGroupingManager::UpdateModel() {
|
|||
void SavedGroupingManager::Remove() {
|
||||
|
||||
if (ui_->list->selectionModel()->hasSelection()) {
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(saved_groupings_settings_group_);
|
||||
for (const QModelIndex &idx : ui_->list->selectionModel()->selectedRows()) {
|
||||
const QModelIndexList indexes = ui_->list->selectionModel()->selectedRows();
|
||||
for (const QModelIndex &idx : indexes) {
|
||||
if (idx.isValid()) {
|
||||
qLog(Debug) << "Remove saved grouping: " << model_->item(idx.row(), 0)->text();
|
||||
s.remove(model_->item(idx.row(), 0)->text());
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#cmakedefine HAVE_SUBSONIC
|
||||
#cmakedefine HAVE_TIDAL
|
||||
#cmakedefine HAVE_SPOTIFY
|
||||
#cmakedefine HAVE_QOBUZ
|
||||
|
||||
#cmakedefine HAVE_MOODBAR
|
||||
|
|
|
@ -56,12 +56,12 @@ ContextAlbum::ContextAlbum(QWidget *parent)
|
|||
album_cover_choice_controller_(nullptr),
|
||||
downloading_covers_(false),
|
||||
timeline_fade_(new QTimeLine(kFadeTimeLineMs, this)),
|
||||
image_strawberry_(":/pictures/strawberry.png"),
|
||||
image_strawberry_(QStringLiteral(":/pictures/strawberry.png")),
|
||||
image_original_(image_strawberry_),
|
||||
pixmap_current_opacity_(1.0),
|
||||
desired_height_(width()) {
|
||||
|
||||
setObjectName("context-widget-album");
|
||||
setObjectName(QStringLiteral("context-widget-album"));
|
||||
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
|
||||
|
@ -266,7 +266,7 @@ void ContextAlbum::SearchCoverInProgress() {
|
|||
downloading_covers_ = true;
|
||||
|
||||
// Show a spinner animation
|
||||
spinner_animation_ = make_unique<QMovie>(":/pictures/spinner.gif", QByteArray(), this);
|
||||
spinner_animation_ = make_unique<QMovie>(QStringLiteral(":/pictures/spinner.gif"), QByteArray(), this);
|
||||
QObject::connect(&*spinner_animation_, &QMovie::updated, this, &ContextAlbum::Update);
|
||||
spinner_animation_->start();
|
||||
update();
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "core/application.h"
|
||||
#include "core/player.h"
|
||||
#include "core/song.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/strutils.h"
|
||||
#include "utilities/timeutils.h"
|
||||
#include "widgets/resizabletextedit.h"
|
||||
|
@ -112,25 +113,25 @@ ContextView::ContextView(QWidget *parent)
|
|||
|
||||
setLayout(layout_container_);
|
||||
|
||||
layout_container_->setObjectName("context-layout-container");
|
||||
layout_container_->setObjectName(QStringLiteral("context-layout-container"));
|
||||
layout_container_->setContentsMargins(0, 0, 0, 0);
|
||||
layout_container_->addWidget(scrollarea_);
|
||||
|
||||
scrollarea_->setObjectName("context-scrollarea");
|
||||
scrollarea_->setObjectName(QStringLiteral("context-scrollarea"));
|
||||
scrollarea_->setWidgetResizable(true);
|
||||
scrollarea_->setWidget(widget_scrollarea_);
|
||||
scrollarea_->setContentsMargins(0, 0, 0, 0);
|
||||
scrollarea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
scrollarea_->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
||||
widget_scrollarea_->setObjectName("context-widget-scrollarea");
|
||||
widget_scrollarea_->setObjectName(QStringLiteral("context-widget-scrollarea"));
|
||||
widget_scrollarea_->setLayout(layout_scrollarea_);
|
||||
widget_scrollarea_->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
textedit_top_->setReadOnly(true);
|
||||
textedit_top_->setFrameShape(QFrame::NoFrame);
|
||||
|
||||
layout_scrollarea_->setObjectName("context-layout-scrollarea");
|
||||
layout_scrollarea_->setObjectName(QStringLiteral("context-layout-scrollarea"));
|
||||
layout_scrollarea_->setContentsMargins(15, 15, 15, 15);
|
||||
layout_scrollarea_->addWidget(textedit_top_);
|
||||
layout_scrollarea_->addWidget(widget_album_);
|
||||
|
@ -291,20 +292,20 @@ void ContextView::ReloadSettings() {
|
|||
|
||||
QString default_font;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (QFontDatabase::families().contains(ContextSettingsPage::kDefaultFontFamily)) {
|
||||
if (QFontDatabase::families().contains(QLatin1String(ContextSettingsPage::kDefaultFontFamily))) {
|
||||
#else
|
||||
if (QFontDatabase().families().contains(ContextSettingsPage::kDefaultFontFamily)) {
|
||||
if (QFontDatabase().families().contains(QLatin1String(ContextSettingsPage::kDefaultFontFamily))) {
|
||||
#endif
|
||||
default_font = ContextSettingsPage::kDefaultFontFamily;
|
||||
default_font = QLatin1String(ContextSettingsPage::kDefaultFontFamily);
|
||||
}
|
||||
else {
|
||||
default_font = font().family();
|
||||
}
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
title_fmt_ = s.value(ContextSettingsPage::kSettingsTitleFmt, "%title% - %artist%").toString();
|
||||
summary_fmt_ = s.value(ContextSettingsPage::kSettingsSummaryFmt, "%album%").toString();
|
||||
title_fmt_ = s.value(ContextSettingsPage::kSettingsTitleFmt, QStringLiteral("%title% - %artist%")).toString();
|
||||
summary_fmt_ = s.value(ContextSettingsPage::kSettingsSummaryFmt, QStringLiteral("%album%")).toString();
|
||||
action_show_album_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::ALBUM)], true).toBool());
|
||||
action_show_data_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::TECHNICAL_DATA)], false).toBool());
|
||||
action_show_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS)], true).toBool());
|
||||
|
@ -390,7 +391,7 @@ void ContextView::FadeStopFinished() {
|
|||
}
|
||||
|
||||
void ContextView::SetLabelText(QLabel *label, int value, const QString &suffix, const QString &def) {
|
||||
label->setText(value <= 0 ? def : (QString::number(value) + " " + suffix));
|
||||
label->setText(value <= 0 ? def : (QString::number(value) + QLatin1Char(' ') + suffix));
|
||||
}
|
||||
|
||||
void ContextView::UpdateNoSong() {
|
||||
|
@ -409,15 +410,15 @@ void ContextView::NoSong() {
|
|||
QString html;
|
||||
if (collectionview_->TotalSongs() == 1) html += tr("%1 song").arg(collectionview_->TotalSongs());
|
||||
else html += tr("%1 songs").arg(collectionview_->TotalSongs());
|
||||
html += "<br />";
|
||||
html += QLatin1String("<br />");
|
||||
|
||||
if (collectionview_->TotalArtists() == 1) html += tr("%1 artist").arg(collectionview_->TotalArtists());
|
||||
else html += tr("%1 artists").arg(collectionview_->TotalArtists());
|
||||
html += "<br />";
|
||||
html += QLatin1String("<br />");
|
||||
|
||||
if (collectionview_->TotalAlbums() == 1) html += tr("%1 album").arg(collectionview_->TotalAlbums());
|
||||
else html += tr("%1 albums").arg(collectionview_->TotalAlbums());
|
||||
html += "<br />";
|
||||
html += QLatin1String("<br />");
|
||||
|
||||
label_stop_summary_->setFont(font_normal_);
|
||||
label_stop_summary_->setText(html);
|
||||
|
@ -438,7 +439,7 @@ void ContextView::UpdateFonts() {
|
|||
void ContextView::SetSong() {
|
||||
|
||||
textedit_top_->setFont(font_headline_);
|
||||
textedit_top_->SetText(QString("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song_playing_, "<br />", true), Utilities::ReplaceMessage(summary_fmt_, song_playing_, "<br />", true)));
|
||||
textedit_top_->SetText(QStringLiteral("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song_playing_, QStringLiteral("<br />"), true), Utilities::ReplaceMessage(summary_fmt_, song_playing_, QStringLiteral("<br />"), true)));
|
||||
|
||||
label_stop_summary_->clear();
|
||||
|
||||
|
@ -474,7 +475,7 @@ void ContextView::SetSong() {
|
|||
else {
|
||||
label_samplerate_title_->show();
|
||||
label_samplerate_->show();
|
||||
SetLabelText(label_samplerate_, song_playing_.samplerate(), "Hz");
|
||||
SetLabelText(label_samplerate_, song_playing_.samplerate(), QStringLiteral("Hz"));
|
||||
}
|
||||
if (song_playing_.bitdepth() <= 0) {
|
||||
label_bitdepth_title_->hide();
|
||||
|
@ -484,7 +485,7 @@ void ContextView::SetSong() {
|
|||
else {
|
||||
label_bitdepth_title_->show();
|
||||
label_bitdepth_->show();
|
||||
SetLabelText(label_bitdepth_, song_playing_.bitdepth(), "Bit");
|
||||
SetLabelText(label_bitdepth_, song_playing_.bitdepth(), QStringLiteral("Bit"));
|
||||
}
|
||||
if (song_playing_.bitrate() <= 0) {
|
||||
label_bitrate_title_->hide();
|
||||
|
@ -546,7 +547,7 @@ void ContextView::SetSong() {
|
|||
|
||||
void ContextView::UpdateSong(const Song &song) {
|
||||
|
||||
textedit_top_->SetText(QString("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song, "<br />", true), Utilities::ReplaceMessage(summary_fmt_, song, "<br />", true)));
|
||||
textedit_top_->SetText(QStringLiteral("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song, QStringLiteral("<br />"), true), Utilities::ReplaceMessage(summary_fmt_, song, QStringLiteral("<br />"), true)));
|
||||
|
||||
if (action_show_data_->isChecked()) {
|
||||
if (song.filetype() != song_playing_.filetype()) label_filetype_->setText(song.TextForFiletype());
|
||||
|
@ -571,7 +572,7 @@ void ContextView::UpdateSong(const Song &song) {
|
|||
else {
|
||||
label_samplerate_title_->show();
|
||||
label_samplerate_->show();
|
||||
SetLabelText(label_samplerate_, song.samplerate(), "Hz");
|
||||
SetLabelText(label_samplerate_, song.samplerate(), QStringLiteral("Hz"));
|
||||
}
|
||||
}
|
||||
if (song.bitdepth() != song_playing_.bitdepth()) {
|
||||
|
@ -583,7 +584,7 @@ void ContextView::UpdateSong(const Song &song) {
|
|||
else {
|
||||
label_bitdepth_title_->show();
|
||||
label_bitdepth_->show();
|
||||
SetLabelText(label_bitdepth_, song.bitdepth(), "Bit");
|
||||
SetLabelText(label_bitdepth_, song.bitdepth(), QStringLiteral("Bit"));
|
||||
}
|
||||
}
|
||||
if (song.bitrate() != song_playing_.bitrate()) {
|
||||
|
@ -632,10 +633,10 @@ void ContextView::UpdateLyrics(const quint64 id, const QString &provider, const
|
|||
if (static_cast<qint64>(id) != lyrics_id_) return;
|
||||
|
||||
if (lyrics.isEmpty()) {
|
||||
lyrics_ = "No lyrics found.\n";
|
||||
lyrics_ = QStringLiteral("No lyrics found.\n");
|
||||
}
|
||||
else {
|
||||
lyrics_ = lyrics + "\n\n(Lyrics from " + provider + ")\n";
|
||||
lyrics_ = lyrics + QStringLiteral("\n\n(Lyrics from ") + provider + QStringLiteral(")\n");
|
||||
}
|
||||
lyrics_id_ = -1;
|
||||
|
||||
|
@ -692,7 +693,7 @@ void ContextView::AlbumCoverLoaded(const Song &song, const QImage &image) {
|
|||
|
||||
void ContextView::ActionShowAlbum() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
s.setValue(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::ALBUM)], action_show_album_->isChecked());
|
||||
s.endGroup();
|
||||
|
@ -702,7 +703,7 @@ void ContextView::ActionShowAlbum() {
|
|||
|
||||
void ContextView::ActionShowData() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
s.setValue(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::TECHNICAL_DATA)], action_show_data_->isChecked());
|
||||
s.endGroup();
|
||||
|
@ -712,7 +713,7 @@ void ContextView::ActionShowData() {
|
|||
|
||||
void ContextView::ActionShowLyrics() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
s.setValue(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS)], action_show_lyrics_->isChecked());
|
||||
s.endGroup();
|
||||
|
@ -725,7 +726,7 @@ void ContextView::ActionShowLyrics() {
|
|||
|
||||
void ContextView::ActionSearchLyrics() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
s.setValue(ContextSettingsPage::kSettingsGroupEnable[static_cast<int>(ContextSettingsPage::ContextSettingsOrder::SEARCH_LYRICS)], action_search_lyrics_->isChecked());
|
||||
s.endGroup();
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
#include "covermanager/musicbrainzcoverprovider.h"
|
||||
#include "covermanager/deezercoverprovider.h"
|
||||
#include "covermanager/musixmatchcoverprovider.h"
|
||||
#include "covermanager/spotifycoverprovider.h"
|
||||
#include "covermanager/opentidalcoverprovider.h"
|
||||
|
||||
#include "lyrics/lyricsproviders.h"
|
||||
|
@ -90,6 +89,11 @@
|
|||
# include "covermanager/tidalcoverprovider.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SPOTIFY
|
||||
# include "spotify/spotifyservice.h"
|
||||
# include "covermanager/spotifycoverprovider.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_QOBUZ
|
||||
# include "qobuz/qobuzservice.h"
|
||||
# include "covermanager/qobuzcoverprovider.h"
|
||||
|
@ -143,11 +147,13 @@ class ApplicationImpl {
|
|||
cover_providers->AddProvider(new DiscogsCoverProvider(app, app->network()));
|
||||
cover_providers->AddProvider(new DeezerCoverProvider(app, app->network()));
|
||||
cover_providers->AddProvider(new MusixmatchCoverProvider(app, app->network()));
|
||||
cover_providers->AddProvider(new SpotifyCoverProvider(app, app->network()));
|
||||
cover_providers->AddProvider(new OpenTidalCoverProvider(app, app->network()));
|
||||
#ifdef HAVE_TIDAL
|
||||
cover_providers->AddProvider(new TidalCoverProvider(app, app->network()));
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
cover_providers->AddProvider(new SpotifyCoverProvider(app, app->network()));
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
cover_providers->AddProvider(new QobuzCoverProvider(app, app->network()));
|
||||
#endif
|
||||
|
@ -183,6 +189,9 @@ class ApplicationImpl {
|
|||
#ifdef HAVE_TIDAL
|
||||
internet_services->AddService(make_shared<TidalService>(app));
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
internet_services->AddService(make_shared<SpotifyService>(app));
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
internet_services->AddService(make_shared<QobuzService>(app));
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <QIODevice>
|
||||
#include <QDataStream>
|
||||
#include <QBuffer>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QByteArray>
|
||||
|
@ -100,7 +101,7 @@ CommandlineOptions::CommandlineOptions(int argc, char **argv)
|
|||
play_track_at_(-1),
|
||||
show_osd_(false),
|
||||
toggle_pretty_osd_(false),
|
||||
log_levels_(logging::kDefaultLogLevels) {
|
||||
log_levels_(QLatin1String(logging::kDefaultLogLevels)) {
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
Q_UNUSED(argv);
|
||||
|
@ -108,11 +109,11 @@ CommandlineOptions::CommandlineOptions(int argc, char **argv)
|
|||
|
||||
#ifdef Q_OS_MACOS
|
||||
// Remove -psn_xxx option that Mac passes when opened from Finder.
|
||||
RemoveArg("-psn", 1);
|
||||
RemoveArg(QStringLiteral("-psn"), 1);
|
||||
#endif
|
||||
|
||||
// Remove the -session option that KDE passes
|
||||
RemoveArg("-session", 2);
|
||||
RemoveArg(QStringLiteral("-session"), 2);
|
||||
|
||||
}
|
||||
|
||||
|
@ -212,9 +213,9 @@ bool CommandlineOptions::Parse() {
|
|||
if (c == -1) break;
|
||||
|
||||
switch (c) {
|
||||
case 'h': {
|
||||
case 'h':{
|
||||
QString translated_help_text =
|
||||
QString(kHelpText)
|
||||
QString::fromUtf8(kHelpText)
|
||||
.arg(QObject::tr("Usage"), QObject::tr("options"), QObject::tr("URL(s)"),
|
||||
QObject::tr("Player options"),
|
||||
QObject::tr("Start the playlist currently playing"),
|
||||
|
@ -301,16 +302,16 @@ bool CommandlineOptions::Parse() {
|
|||
volume_modifier_ = -4;
|
||||
break;
|
||||
case LongOptions::Quiet:
|
||||
log_levels_ = "1";
|
||||
log_levels_ = QStringLiteral("1");
|
||||
break;
|
||||
case LongOptions::Verbose:
|
||||
log_levels_ = "3";
|
||||
log_levels_ = QStringLiteral("3");
|
||||
break;
|
||||
case LongOptions::LogLevels:
|
||||
log_levels_ = OptArgToString(optarg);
|
||||
break;
|
||||
case LongOptions::Version: {
|
||||
QString version_text = QString(kVersionText).arg(STRAWBERRY_VERSION_DISPLAY);
|
||||
case LongOptions::Version:{
|
||||
QString version_text = QString::fromUtf8(kVersionText).arg(QStringLiteral(STRAWBERRY_VERSION_DISPLAY));
|
||||
std::cout << version_text.toLocal8Bit().constData() << std::endl;
|
||||
std::exit(0);
|
||||
}
|
||||
|
@ -364,7 +365,7 @@ bool CommandlineOptions::Parse() {
|
|||
const QString value = DecodeName(argv_[i]);
|
||||
QFileInfo fileinfo(value);
|
||||
if (fileinfo.exists()) {
|
||||
urls_ << QUrl::fromLocalFile(fileinfo.canonicalFilePath());
|
||||
urls_ << QUrl::fromLocalFile(QDir::cleanPath(fileinfo.filePath()));
|
||||
}
|
||||
else {
|
||||
urls_ << QUrl::fromUserInput(value);
|
||||
|
@ -416,7 +417,7 @@ void CommandlineOptions::Load(const QByteArray &serialized) {
|
|||
}
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
QString CommandlineOptions::OptArgToString(wchar_t *opt) {
|
||||
QString CommandlineOptions::OptArgToString(const wchar_t *opt) {
|
||||
|
||||
return QString::fromWCharArray(opt);
|
||||
|
||||
|
@ -427,9 +428,9 @@ QString CommandlineOptions::DecodeName(wchar_t *opt) {
|
|||
return QString::fromWCharArray(opt);
|
||||
}
|
||||
#else
|
||||
QString CommandlineOptions::OptArgToString(char *opt) {
|
||||
QString CommandlineOptions::OptArgToString(const char *opt) {
|
||||
|
||||
return QString(opt);
|
||||
return QString::fromUtf8(opt);
|
||||
}
|
||||
|
||||
QString CommandlineOptions::DecodeName(char *opt) {
|
||||
|
|
|
@ -108,10 +108,10 @@ class CommandlineOptions {
|
|||
void RemoveArg(const QString &starts_with, int count);
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
static QString OptArgToString(wchar_t *opt);
|
||||
static QString OptArgToString(const wchar_t *opt);
|
||||
static QString DecodeName(wchar_t *opt);
|
||||
#else
|
||||
static QString OptArgToString(char *opt);
|
||||
static QString OptArgToString(const char *opt);
|
||||
static QString DecodeName(char *opt);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <QObject>
|
||||
|
@ -47,10 +49,13 @@
|
|||
#include "sqlquery.h"
|
||||
#include "scopedtransaction.h"
|
||||
|
||||
const char *Database::kDatabaseFilename = "strawberry.db";
|
||||
const int Database::kSchemaVersion = 18;
|
||||
const int Database::kMinSupportedSchemaVersion = 10;
|
||||
const char *Database::kMagicAllSongsTables = "%allsongstables";
|
||||
|
||||
namespace {
|
||||
constexpr char kDatabaseFilename[] = "strawberry.db";
|
||||
constexpr int kMinSupportedSchemaVersion = 10;
|
||||
constexpr char kMagicAllSongsTables[] = "%allsongstables";
|
||||
} // namespace
|
||||
|
||||
int Database::sNextConnectionId = 1;
|
||||
QMutex Database::sNextConnectionIdMutex;
|
||||
|
@ -84,7 +89,8 @@ Database::~Database() {
|
|||
|
||||
QMutexLocker l(&connect_mutex_);
|
||||
|
||||
for (const QString &connection_id : QSqlDatabase::connectionNames()) {
|
||||
const QStringList connection_names = QSqlDatabase::connectionNames();
|
||||
for (const QString &connection_id : connection_names) {
|
||||
qLog(Error) << "Connection" << connection_id << "is still open!";
|
||||
}
|
||||
|
||||
|
@ -114,7 +120,7 @@ QSqlDatabase Database::Connect() {
|
|||
}
|
||||
}
|
||||
|
||||
const QString connection_id = QString("%1_thread_%2").arg(connection_id_).arg(reinterpret_cast<quint64>(QThread::currentThread()));
|
||||
const QString connection_id = QStringLiteral("%1_thread_%2").arg(connection_id_).arg(reinterpret_cast<quint64>(QThread::currentThread()));
|
||||
|
||||
// Try to find an existing connection for this thread
|
||||
QSqlDatabase db;
|
||||
|
@ -122,23 +128,23 @@ QSqlDatabase Database::Connect() {
|
|||
db = QSqlDatabase::database(connection_id);
|
||||
}
|
||||
else {
|
||||
db = QSqlDatabase::addDatabase("QSQLITE", connection_id);
|
||||
db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), connection_id);
|
||||
}
|
||||
if (db.isOpen()) {
|
||||
return db;
|
||||
}
|
||||
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=30000");
|
||||
db.setConnectOptions(QStringLiteral("QSQLITE_BUSY_TIMEOUT=30000"));
|
||||
//qLog(Debug) << "Opened database with connection id" << connection_id;
|
||||
|
||||
if (injected_database_name_.isNull()) {
|
||||
db.setDatabaseName(directory_ + "/" + kDatabaseFilename);
|
||||
db.setDatabaseName(directory_ + QLatin1Char('/') + QLatin1String(kDatabaseFilename));
|
||||
}
|
||||
else {
|
||||
db.setDatabaseName(injected_database_name_);
|
||||
}
|
||||
|
||||
if (!db.open()) {
|
||||
app_->AddError("Database: " + db.lastError().text());
|
||||
app_->AddError(QStringLiteral("Database: ") + db.lastError().text());
|
||||
return db;
|
||||
}
|
||||
|
||||
|
@ -154,16 +160,16 @@ QSqlDatabase Database::Connect() {
|
|||
|
||||
// Attach external databases
|
||||
QStringList keys = attached_databases_.keys();
|
||||
for (const QString &key : keys) {
|
||||
for (const QString &key : std::as_const(keys)) {
|
||||
QString filename = attached_databases_[key].filename_;
|
||||
|
||||
if (!injected_database_name_.isNull()) filename = injected_database_name_;
|
||||
|
||||
// Attach the db
|
||||
SqlQuery q(db);
|
||||
q.prepare("ATTACH DATABASE :filename AS :alias");
|
||||
q.BindValue(":filename", filename);
|
||||
q.BindValue(":alias", key);
|
||||
q.prepare(QStringLiteral("ATTACH DATABASE :filename AS :alias"));
|
||||
q.BindValue(QStringLiteral(":filename"), filename);
|
||||
q.BindValue(QStringLiteral(":alias"), key);
|
||||
if (!q.Exec()) {
|
||||
qFatal("Couldn't attach external database '%s'", key.toLatin1().constData());
|
||||
}
|
||||
|
@ -175,13 +181,13 @@ QSqlDatabase Database::Connect() {
|
|||
|
||||
// We might have to initialize the schema in some attached databases now, if they were deleted and don't match up with the main schema version.
|
||||
keys = attached_databases_.keys();
|
||||
for (const QString &key : keys) {
|
||||
for (const QString &key : std::as_const(keys)) {
|
||||
if (attached_databases_[key].is_temporary_ && attached_databases_[key].schema_.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// Find out if there are any tables in this database
|
||||
SqlQuery q(db);
|
||||
q.prepare(QString("SELECT ROWID FROM %1.sqlite_master WHERE type='table'").arg(key));
|
||||
q.prepare(QStringLiteral("SELECT ROWID FROM %1.sqlite_master WHERE type='table'").arg(key));
|
||||
if (!q.Exec() || !q.next()) {
|
||||
q.finish();
|
||||
ExecSchemaCommandsFromFile(db, attached_databases_[key].schema_, 0);
|
||||
|
@ -196,7 +202,7 @@ void Database::Close() {
|
|||
|
||||
QMutexLocker l(&connect_mutex_);
|
||||
|
||||
const QString connection_id = QString("%1_thread_%2").arg(connection_id_).arg(reinterpret_cast<quint64>(QThread::currentThread()));
|
||||
const QString connection_id = QStringLiteral("%1_thread_%2").arg(connection_id_).arg(reinterpret_cast<quint64>(QThread::currentThread()));
|
||||
|
||||
// Try to find an existing connection for this thread
|
||||
if (QSqlDatabase::connectionNames().contains(connection_id)) {
|
||||
|
@ -218,7 +224,7 @@ int Database::SchemaVersion(QSqlDatabase *db) {
|
|||
int schema_version = 0;
|
||||
{
|
||||
SqlQuery q(*db);
|
||||
q.prepare("SELECT version FROM schema_version");
|
||||
q.prepare(QStringLiteral("SELECT version FROM schema_version"));
|
||||
if (q.Exec() && q.next()) {
|
||||
schema_version = q.value(0).toInt();
|
||||
}
|
||||
|
@ -259,8 +265,8 @@ void Database::RecreateAttachedDb(const QString &database_name) {
|
|||
QSqlDatabase db(Connect());
|
||||
|
||||
SqlQuery q(db);
|
||||
q.prepare("DETACH DATABASE :alias");
|
||||
q.BindValue(":alias", database_name);
|
||||
q.prepare(QStringLiteral("DETACH DATABASE :alias"));
|
||||
q.BindValue(QStringLiteral(":alias"), database_name);
|
||||
if (!q.Exec()) {
|
||||
qLog(Warning) << "Failed to detach database" << database_name;
|
||||
return;
|
||||
|
@ -273,7 +279,8 @@ void Database::RecreateAttachedDb(const QString &database_name) {
|
|||
|
||||
// We can't just re-attach the database now because it needs to be done for each thread.
|
||||
// Close all the database connections, so each thread will re-attach it when they next connect.
|
||||
for (const QString &name : QSqlDatabase::connectionNames()) {
|
||||
const QStringList connection_names = QSqlDatabase::connectionNames();
|
||||
for (const QString &name : connection_names) {
|
||||
QSqlDatabase::removeDatabase(name);
|
||||
}
|
||||
|
||||
|
@ -289,9 +296,9 @@ void Database::AttachDatabaseOnDbConnection(const QString &database_name, const
|
|||
|
||||
// Attach the db
|
||||
SqlQuery q(db);
|
||||
q.prepare("ATTACH DATABASE :filename AS :alias");
|
||||
q.BindValue(":filename", database.filename_);
|
||||
q.BindValue(":alias", database_name);
|
||||
q.prepare(QStringLiteral("ATTACH DATABASE :filename AS :alias"));
|
||||
q.BindValue(QStringLiteral(":filename"), database.filename_);
|
||||
q.BindValue(QStringLiteral(":alias"), database_name);
|
||||
if (!q.Exec()) {
|
||||
qFatal("Couldn't attach external database '%s'", database_name.toLatin1().constData());
|
||||
}
|
||||
|
@ -305,8 +312,8 @@ void Database::DetachDatabase(const QString &database_name) {
|
|||
QSqlDatabase db(Connect());
|
||||
|
||||
SqlQuery q(db);
|
||||
q.prepare("DETACH DATABASE :alias");
|
||||
q.BindValue(":alias", database_name);
|
||||
q.prepare(QStringLiteral("DETACH DATABASE :alias"));
|
||||
q.BindValue(QStringLiteral(":alias"), database_name);
|
||||
if (!q.Exec()) {
|
||||
qLog(Warning) << "Failed to detach database" << database_name;
|
||||
return;
|
||||
|
@ -321,10 +328,10 @@ void Database::UpdateDatabaseSchema(int version, QSqlDatabase &db) {
|
|||
|
||||
QString filename;
|
||||
if (version == 0) {
|
||||
filename = ":/schema/schema.sql";
|
||||
filename = QStringLiteral(":/schema/schema.sql");
|
||||
}
|
||||
else {
|
||||
filename = QString(":/schema/schema-%1.sql").arg(version);
|
||||
filename = QStringLiteral(":/schema/schema-%1.sql").arg(version);
|
||||
qLog(Debug) << "Applying database schema update" << version << "from" << filename;
|
||||
}
|
||||
|
||||
|
@ -335,9 +342,9 @@ void Database::UpdateDatabaseSchema(int version, QSqlDatabase &db) {
|
|||
void Database::UrlEncodeFilenameColumn(const QString &table, QSqlDatabase &db) {
|
||||
|
||||
SqlQuery select(db);
|
||||
select.prepare(QString("SELECT ROWID, filename FROM %1").arg(table));
|
||||
select.prepare(QStringLiteral("SELECT ROWID, filename FROM %1").arg(table));
|
||||
SqlQuery update(db);
|
||||
update.prepare(QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table));
|
||||
update.prepare(QStringLiteral("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table));
|
||||
if (!select.Exec()) {
|
||||
ReportErrors(select);
|
||||
}
|
||||
|
@ -346,14 +353,14 @@ void Database::UrlEncodeFilenameColumn(const QString &table, QSqlDatabase &db) {
|
|||
const int rowid = select.value(0).toInt();
|
||||
const QString filename = select.value(1).toString();
|
||||
|
||||
if (filename.isEmpty() || filename.contains("://")) {
|
||||
if (filename.isEmpty() || filename.contains(QLatin1String("://"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const QUrl url = QUrl::fromLocalFile(filename);
|
||||
|
||||
update.BindValue(":filename", url.toEncoded());
|
||||
update.BindValue(":id", rowid);
|
||||
update.BindValue(QStringLiteral(":filename"), url.toEncoded());
|
||||
update.BindValue(QStringLiteral(":id"), rowid);
|
||||
if (!update.Exec()) {
|
||||
ReportErrors(update);
|
||||
}
|
||||
|
@ -370,8 +377,8 @@ void Database::ExecSchemaCommandsFromFile(QSqlDatabase &db, const QString &filen
|
|||
}
|
||||
QByteArray data = schema_file.readAll();
|
||||
QString schema = QString::fromUtf8(data);
|
||||
if (schema.contains("\r\n")) {
|
||||
schema = schema.replace("\r\n", "\n");
|
||||
if (schema.contains(QLatin1String("\r\n"))) {
|
||||
schema = schema.replace(QLatin1String("\r\n"), QLatin1String("\n"));
|
||||
}
|
||||
schema_file.close();
|
||||
ExecSchemaCommands(db, schema, schema_version, in_transaction);
|
||||
|
@ -381,8 +388,7 @@ void Database::ExecSchemaCommandsFromFile(QSqlDatabase &db, const QString &filen
|
|||
void Database::ExecSchemaCommands(QSqlDatabase &db, const QString &schema, int schema_version, bool in_transaction) {
|
||||
|
||||
// Run each command
|
||||
QStringList commands;
|
||||
commands = schema.split(QRegularExpression("; *\n\n"));
|
||||
QStringList commands = schema.split(QRegularExpression(QStringLiteral("; *\n\n")));
|
||||
|
||||
// We don't want this list to reflect possible DB schema changes, so we initialize it before executing any statements.
|
||||
// If no outer transaction is provided the song tables need to be queried before beginning an inner transaction!
|
||||
|
@ -405,16 +411,16 @@ void Database::ExecSongTablesCommands(QSqlDatabase &db, const QStringList &song_
|
|||
for (const QString &command : commands) {
|
||||
// There are now lots of "songs" tables that need to have the same schema: songs and device_*_songs.
|
||||
// We allow a magic value in the schema files to update all songs tables at once.
|
||||
if (command.contains(kMagicAllSongsTables)) {
|
||||
if (command.contains(QLatin1String(kMagicAllSongsTables))) {
|
||||
for (const QString &table : song_tables) {
|
||||
// Another horrible hack: device songs tables don't have matching _fts tables, so if this command tries to touch one, ignore it.
|
||||
if (table.startsWith("device_") && command.contains(QString(kMagicAllSongsTables) + "_fts")) {
|
||||
if (table.startsWith(QLatin1String("device_")) && command.contains(QLatin1String(kMagicAllSongsTables) + QStringLiteral("_fts"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
qLog(Info) << "Updating" << table << "for" << kMagicAllSongsTables;
|
||||
QString new_command(command);
|
||||
new_command.replace(kMagicAllSongsTables, table);
|
||||
new_command.replace(QLatin1String(kMagicAllSongsTables), table);
|
||||
SqlQuery query(db);
|
||||
query.prepare(new_command);
|
||||
if (!query.Exec()) {
|
||||
|
@ -442,18 +448,19 @@ QStringList Database::SongsTables(QSqlDatabase &db, const int schema_version) {
|
|||
QStringList ret;
|
||||
|
||||
// look for the tables in the main db
|
||||
for (const QString &table : db.tables()) {
|
||||
if (table == "songs" || table.endsWith("_songs")) ret << table;
|
||||
const QStringList &tables = db.tables();
|
||||
for (const QString &table : tables) {
|
||||
if (table == QStringLiteral("songs") || table.endsWith(QLatin1String("_songs"))) ret << table;
|
||||
}
|
||||
|
||||
// look for the tables in attached dbs
|
||||
QStringList keys = attached_databases_.keys();
|
||||
const QStringList keys = attached_databases_.keys();
|
||||
for (const QString &key : keys) {
|
||||
SqlQuery q(db);
|
||||
q.prepare(QString("SELECT NAME FROM %1.sqlite_master WHERE type='table' AND name='songs' OR name LIKE '%songs'").arg(key));
|
||||
q.prepare(QStringLiteral("SELECT NAME FROM %1.sqlite_master WHERE type='table' AND name='songs' OR name LIKE '%songs'").arg(key));
|
||||
if (q.Exec()) {
|
||||
while (q.next()) {
|
||||
QString tab_name = key + "." + q.value(0).toString();
|
||||
QString tab_name = key + QStringLiteral(".") + q.value(0).toString();
|
||||
ret << tab_name;
|
||||
}
|
||||
}
|
||||
|
@ -462,7 +469,7 @@ QStringList Database::SongsTables(QSqlDatabase &db, const int schema_version) {
|
|||
}
|
||||
}
|
||||
|
||||
ret << "playlist_items";
|
||||
ret << QStringLiteral("playlist_items");
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -488,20 +495,20 @@ bool Database::IntegrityCheck(const QSqlDatabase &db) {
|
|||
bool ok = false;
|
||||
// Ask for 10 error messages at most.
|
||||
SqlQuery q(db);
|
||||
q.prepare("PRAGMA integrity_check(10)");
|
||||
q.prepare(QStringLiteral("PRAGMA integrity_check(10)"));
|
||||
if (q.Exec()) {
|
||||
bool error_reported = false;
|
||||
while (q.next()) {
|
||||
QString message = q.value(0).toString();
|
||||
|
||||
// If no errors are found, a single row with the value "ok" is returned
|
||||
if (message == "ok") {
|
||||
if (message == QStringLiteral("ok")) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (!error_reported) { app_->AddError(tr("Database corruption detected.")); }
|
||||
app_->AddError("Database: " + message);
|
||||
app_->AddError(QStringLiteral("Database: ") + message);
|
||||
error_reported = true;
|
||||
}
|
||||
}
|
||||
|
@ -553,7 +560,7 @@ bool Database::OpenDatabase(const QString &filename, sqlite3 **connection) {
|
|||
void Database::BackupFile(const QString &filename) {
|
||||
|
||||
qLog(Debug) << "Starting database backup";
|
||||
QString dest_filename = QString("%1.bak").arg(filename);
|
||||
QString dest_filename = QStringLiteral("%1.bak").arg(filename);
|
||||
const int task_id = app_->task_manager()->StartTask(tr("Backing up database"));
|
||||
|
||||
sqlite3 *source_connection = nullptr;
|
||||
|
|
|
@ -50,6 +50,8 @@ class Database : public QObject {
|
|||
explicit Database(Application *app, QObject *parent = nullptr, const QString &database_name = QString());
|
||||
~Database() override;
|
||||
|
||||
static const int kSchemaVersion;
|
||||
|
||||
struct AttachedDatabase {
|
||||
AttachedDatabase() {}
|
||||
AttachedDatabase(const QString &filename, const QString &schema, bool is_temporary)
|
||||
|
@ -60,11 +62,6 @@ class Database : public QObject {
|
|||
bool is_temporary_;
|
||||
};
|
||||
|
||||
static const int kSchemaVersion;
|
||||
static const int kMinSupportedSchemaVersion;
|
||||
static const char *kDatabaseFilename;
|
||||
static const char *kMagicAllSongsTables;
|
||||
|
||||
void ExitAsync();
|
||||
QSqlDatabase Connect();
|
||||
void Close();
|
||||
|
@ -148,7 +145,7 @@ class MemoryDatabase : public Database {
|
|||
|
||||
public:
|
||||
explicit MemoryDatabase(Application *app, QObject *parent = nullptr)
|
||||
: Database(app, parent, ":memory:") {}
|
||||
: Database(app, parent, QStringLiteral(":memory:")) {}
|
||||
~MemoryDatabase() override {
|
||||
// Make sure Qt doesn't reuse the same database
|
||||
QSqlDatabase::removeDatabase(Connect().connectionName());
|
||||
|
|
|
@ -39,13 +39,13 @@ FilesystemMusicStorage::FilesystemMusicStorage(const Song::Source source, const
|
|||
bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job, QString &error_text) {
|
||||
|
||||
const QFileInfo src = QFileInfo(job.source_);
|
||||
const QFileInfo dest = QFileInfo(root_ + "/" + job.destination_);
|
||||
const QFileInfo dest = QFileInfo(root_ + QLatin1Char('/') + job.destination_);
|
||||
|
||||
QFileInfo cover_src;
|
||||
QFileInfo cover_dest;
|
||||
if (job.albumcover_ && !job.cover_source_.isEmpty() && !job.cover_dest_.isEmpty()) {
|
||||
cover_src = QFileInfo(job.cover_source_);
|
||||
cover_dest = QFileInfo(root_ + "/" + job.cover_dest_);
|
||||
cover_dest = QFileInfo(root_ + QLatin1Char('/') + job.cover_dest_);
|
||||
}
|
||||
|
||||
// Don't do anything if the destination is the same as the source
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
|
@ -29,6 +31,7 @@
|
|||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "settings.h"
|
||||
#include "iconmapper.h"
|
||||
#include "settings/appearancesettingspage.h"
|
||||
#include "iconloader.h"
|
||||
|
@ -39,14 +42,14 @@ bool IconLoader::custom_icons_ = false;
|
|||
void IconLoader::Init() {
|
||||
|
||||
#if !defined(Q_OS_MACOS) && !defined(Q_OS_WIN)
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(AppearanceSettingsPage::kSettingsGroup);
|
||||
system_icons_ = s.value("system_icons", false).toBool();
|
||||
s.endGroup();
|
||||
#endif
|
||||
|
||||
QDir dir;
|
||||
if (dir.exists(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/icons")) {
|
||||
if (dir.exists(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QStringLiteral("/icons"))) {
|
||||
custom_icons_ = true;
|
||||
}
|
||||
|
||||
|
@ -79,7 +82,8 @@ QIcon IconLoader::Load(const QString &name, const bool system_icon, const int fi
|
|||
if (icon_prop.allow_system_icon) {
|
||||
ret = QIcon::fromTheme(name);
|
||||
if (ret.isNull()) {
|
||||
for (const QString &alt_name : icon_prop.names) {
|
||||
const QStringList alt_names = icon_prop.names;
|
||||
for (const QString &alt_name : alt_names) {
|
||||
ret = QIcon::fromTheme(alt_name);
|
||||
if (!ret.isNull()) break;
|
||||
}
|
||||
|
@ -95,7 +99,8 @@ QIcon IconLoader::Load(const QString &name, const bool system_icon, const int fi
|
|||
else {
|
||||
int size_smallest = 0;
|
||||
int size_largest = 0;
|
||||
for (const QSize &s : ret.availableSizes()) {
|
||||
const QList<QSize> available_sizes = ret.availableSizes();
|
||||
for (const QSize &s : available_sizes) {
|
||||
if (s.width() != s.height()) {
|
||||
qLog(Warning) << "Can't use system icon for" << name << "icon is not proportional.";
|
||||
ret = QIcon();
|
||||
|
@ -118,8 +123,8 @@ QIcon IconLoader::Load(const QString &name, const bool system_icon, const int fi
|
|||
}
|
||||
|
||||
if (custom_icons_) {
|
||||
QString custom_icon_path = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/icons/%1x%2/%3.png";
|
||||
for (int s : sizes) {
|
||||
QString custom_icon_path = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QStringLiteral("/icons/%1x%2/%3.png");
|
||||
for (int s : std::as_const(sizes)) {
|
||||
QString filename(custom_icon_path.arg(s).arg(s).arg(name));
|
||||
if (QFile::exists(filename)) ret.addFile(filename, QSize(s, s));
|
||||
}
|
||||
|
@ -127,8 +132,8 @@ QIcon IconLoader::Load(const QString &name, const bool system_icon, const int fi
|
|||
qLog(Warning) << "Couldn't load icon" << name << "from custom icons.";
|
||||
}
|
||||
|
||||
const QString path(":/icons/%1x%2/%3.png");
|
||||
for (int s : sizes) {
|
||||
const QString path(QStringLiteral(":/icons/%1x%2/%3.png"));
|
||||
for (int s : std::as_const(sizes)) {
|
||||
QString filename(path.arg(s).arg(s).arg(name));
|
||||
if (QFile::exists(filename)) ret.addFile(filename, QSize(s, s));
|
||||
}
|
||||
|
|
|
@ -38,100 +38,100 @@ struct IconProperties {
|
|||
|
||||
static const QMap<QString, IconProperties> iconmapper_ = { // clazy:exclude=non-pod-global-static
|
||||
|
||||
{ "albums", { {"media-optical"}} },
|
||||
{ "alsa", { {}} },
|
||||
{ "application-exit", { {}} },
|
||||
{ "applications-internet", { {}} },
|
||||
{ "bluetooth", { {"preferences-system-bluetooth", "bluetooth-active"}} },
|
||||
{ "cdcase", { {"cdcover", "media-optical"}} },
|
||||
{ "media-optical", { {"cd"}} },
|
||||
{ "configure", { {}} },
|
||||
{ "device-ipod-nano", { {}} },
|
||||
{ "device-ipod", { {}} },
|
||||
{ "device-phone", { {}} },
|
||||
{ "device", { {"drive-removable-media-usb-pendrive"}} },
|
||||
{ "device-usb-drive", { {}} },
|
||||
{ "device-usb-flash", { {}} },
|
||||
{ "dialog-error", { {}} },
|
||||
{ "dialog-information", { {}} },
|
||||
{ "dialog-ok-apply", { {}} },
|
||||
{ "dialog-password", { {}} },
|
||||
{ "dialog-warning", { {}} },
|
||||
{ "document-download", { {"download"}} },
|
||||
{ "document-new", { {}} },
|
||||
{ "document-open-folder", { {}} },
|
||||
{ "document-open", { {}} },
|
||||
{ "document-save", { {}} },
|
||||
{ "document-search", { {}} },
|
||||
{ "document-open-remote", { {}} },
|
||||
{ "download", { {"applications-internet", "network-workgroup"}} },
|
||||
{ "edit-clear-list", { {"edit-clear-list","edit-clear-all"}} },
|
||||
{ "edit-clear-locationbar-ltr", { {"edit-clear-locationbar-ltr"}} },
|
||||
{ "edit-copy", { {}} },
|
||||
{ "edit-delete", { {}} },
|
||||
{ "edit-find", { {}} },
|
||||
{ "edit-redo", { {}} },
|
||||
{ "edit-rename", { {}} },
|
||||
{ "edit-undo", { {}} },
|
||||
{ "electrocompaniet", { {}} },
|
||||
{ "equalizer", { {"view-media-equalizer"}} },
|
||||
{ "folder-new", { {}} },
|
||||
{ "folder", { {}} },
|
||||
{ "folder-sound", { {"folder-music"}} },
|
||||
{ "footsteps", { {"go-jump"}} },
|
||||
{ "go-down", { {}} },
|
||||
{ "go-home", { {}} },
|
||||
{ "go-jump", { {}} },
|
||||
{ "go-next", { {}} },
|
||||
{ "go-previous", { {}} },
|
||||
{ "go-up", { {}} },
|
||||
{ "gstreamer", { {"phonon-gstreamer"}} },
|
||||
{ "headset", { {"audio-headset"}} },
|
||||
{ "help-hint", { {}} },
|
||||
{ "intel", { {}} },
|
||||
{ "jack", { {"audio-input-line"}} },
|
||||
{ "keyboard", { {"input-keyboard"}} },
|
||||
{ "list-add", { {}} },
|
||||
{ "list-remove", { {}} },
|
||||
{ "love", { {"heart", "emblem-favorite"}} },
|
||||
{ "mcintosh-player", { {}} },
|
||||
{ "mcintosh", { {}} },
|
||||
{ "mcintosh-text", { {}} },
|
||||
{ "media-eject", { {}} },
|
||||
{ "media-playback-pause", { {"media-pause"}} },
|
||||
{ "media-playlist-repeat", { {}} },
|
||||
{ "media-playlist-shuffle", { {""}} },
|
||||
{ "media-playback-start", { {"media-play", "media-playback-playing"}} },
|
||||
{ "media-seek-backward", { {}} },
|
||||
{ "media-seek-forward", { {}} },
|
||||
{ "media-skip-backward", { {}} },
|
||||
{ "media-skip-forward", { {}} },
|
||||
{ "media-playback-stop", { {"media-stop"}} },
|
||||
{ "moodbar", { {"preferences-desktop-icons"}} },
|
||||
{ "nvidia", { {}} },
|
||||
{ "pulseaudio", { {}} },
|
||||
{ "realtek", { {}} },
|
||||
{ "scrobble-disabled", { {}} },
|
||||
{ "scrobble", { {"love"}} },
|
||||
{ "search", { {}} },
|
||||
{ "soundcard", { {"audiocard", "audio-card"}} },
|
||||
{ "speaker", { {}} },
|
||||
{ "star-grey", { {}} },
|
||||
{ "star", { {}} },
|
||||
{ "strawberry", { {}} },
|
||||
{ "subsonic", { {}} },
|
||||
{ "tidal", { {}} },
|
||||
{ "tools-wizard", { {}} },
|
||||
{ "view-choose", { {}} },
|
||||
{ "view-fullscreen", { {}} },
|
||||
{ "view-media-lyrics", { {}} },
|
||||
{ "view-media-playlist", { {}} },
|
||||
{ "view-media-visualization", { {"preferences-desktop-theme"}} },
|
||||
{ "view-refresh", { {}} },
|
||||
{ "library-music", { {"vinyl"}} },
|
||||
{ "vlc", { {}} },
|
||||
{ "zoom-in", { {}} },
|
||||
{ "zoom-out", { {}, 0, 0 } }
|
||||
{ QStringLiteral("albums"), { {QStringLiteral("media-optical")}} },
|
||||
{ QStringLiteral("alsa"), { {}} },
|
||||
{ QStringLiteral("application-exit"), { {}} },
|
||||
{ QStringLiteral("applications-internet"), { {}} },
|
||||
{ QStringLiteral("bluetooth"), { {QStringLiteral("preferences-system-bluetooth"), QStringLiteral("bluetooth-active")}} },
|
||||
{ QStringLiteral("cdcase"), { {QStringLiteral("cdcover"), QStringLiteral("media-optical")}} },
|
||||
{ QStringLiteral("media-optical"), { {QStringLiteral("cd")}} },
|
||||
{ QStringLiteral("configure"), { {}} },
|
||||
{ QStringLiteral("device-ipod-nano"), { {}} },
|
||||
{ QStringLiteral("device-ipod"), { {}} },
|
||||
{ QStringLiteral("device-phone"), { {}} },
|
||||
{ QStringLiteral("device"), { {QStringLiteral("drive-removable-media-usb-pendrive")}} },
|
||||
{ QStringLiteral("device-usb-drive"), { {}} },
|
||||
{ QStringLiteral("device-usb-flash"), { {}} },
|
||||
{ QStringLiteral("dialog-error"), { {}} },
|
||||
{ QStringLiteral("dialog-information"), { {}} },
|
||||
{ QStringLiteral("dialog-ok-apply"), { {}} },
|
||||
{ QStringLiteral("dialog-password"), { {}} },
|
||||
{ QStringLiteral("dialog-warning"), { {}} },
|
||||
{ QStringLiteral("document-download"), { {QStringLiteral("download")}} },
|
||||
{ QStringLiteral("document-new"), { {}} },
|
||||
{ QStringLiteral("document-open-folder"), { {}} },
|
||||
{ QStringLiteral("document-open"), { {}} },
|
||||
{ QStringLiteral("document-save"), { {}} },
|
||||
{ QStringLiteral("document-search"), { {}} },
|
||||
{ QStringLiteral("document-open-remote"), { {}} },
|
||||
{ QStringLiteral("download"), { {QStringLiteral("applications-internet"), QStringLiteral("network-workgroup")}} },
|
||||
{ QStringLiteral("edit-clear-list"), { {QStringLiteral("edit-clear-list"), QStringLiteral("edit-clear-all")}} },
|
||||
{ QStringLiteral("edit-clear-locationbar-ltr"), { {QStringLiteral("edit-clear-locationbar-ltr")}} },
|
||||
{ QStringLiteral("edit-copy"), { {}} },
|
||||
{ QStringLiteral("edit-delete"), { {}} },
|
||||
{ QStringLiteral("edit-find"), { {}} },
|
||||
{ QStringLiteral("edit-redo"), { {}} },
|
||||
{ QStringLiteral("edit-rename"), { {}} },
|
||||
{ QStringLiteral("edit-undo"), { {}} },
|
||||
{ QStringLiteral("electrocompaniet"), { {}} },
|
||||
{ QStringLiteral("equalizer"), { {QStringLiteral("view-media-equalizer")}} },
|
||||
{ QStringLiteral("folder-new"), { {}} },
|
||||
{ QStringLiteral("folder"), { {}} },
|
||||
{ QStringLiteral("folder-sound"), { {QStringLiteral("folder-music")}} },
|
||||
{ QStringLiteral("footsteps"), { {QStringLiteral("go-jump")}} },
|
||||
{ QStringLiteral("go-down"), { {}} },
|
||||
{ QStringLiteral("go-home"), { {}} },
|
||||
{ QStringLiteral("go-jump"), { {}} },
|
||||
{ QStringLiteral("go-next"), { {}} },
|
||||
{ QStringLiteral("go-previous"), { {}} },
|
||||
{ QStringLiteral("go-up"), { {}} },
|
||||
{ QStringLiteral("gstreamer"), { {QStringLiteral("phonon-gstreamer")}} },
|
||||
{ QStringLiteral("headset"), { {QStringLiteral("audio-headset")}} },
|
||||
{ QStringLiteral("help-hint"), { {}} },
|
||||
{ QStringLiteral("intel"), { {}} },
|
||||
{ QStringLiteral("jack"), { {QStringLiteral("audio-input-line")}} },
|
||||
{ QStringLiteral("keyboard"), { {QStringLiteral("input-keyboard")}} },
|
||||
{ QStringLiteral("list-add"), { {}} },
|
||||
{ QStringLiteral("list-remove"), { {}} },
|
||||
{ QStringLiteral("love"), { {QStringLiteral("heart"), QStringLiteral("emblem-favorite")}} },
|
||||
{ QStringLiteral("mcintosh-player"), { {}} },
|
||||
{ QStringLiteral("mcintosh"), { {}} },
|
||||
{ QStringLiteral("mcintosh-text"), { {}} },
|
||||
{ QStringLiteral("media-eject"), { {}} },
|
||||
{ QStringLiteral("media-playback-pause"), { {QStringLiteral("media-pause")}} },
|
||||
{ QStringLiteral("media-playlist-repeat"), { {}} },
|
||||
{ QStringLiteral("media-playlist-shuffle"), { {QLatin1String("")}} },
|
||||
{ QStringLiteral("media-playback-start"), { {QStringLiteral("media-play"), QStringLiteral("media-playback-playing")}} },
|
||||
{ QStringLiteral("media-seek-backward"), { {}} },
|
||||
{ QStringLiteral("media-seek-forward"), { {}} },
|
||||
{ QStringLiteral("media-skip-backward"), { {}} },
|
||||
{ QStringLiteral("media-skip-forward"), { {}} },
|
||||
{ QStringLiteral("media-playback-stop"), { {QStringLiteral("media-stop")}} },
|
||||
{ QStringLiteral("moodbar"), { {QStringLiteral("preferences-desktop-icons")}} },
|
||||
{ QStringLiteral("nvidia"), { {}} },
|
||||
{ QStringLiteral("pulseaudio"), { {}} },
|
||||
{ QStringLiteral("realtek"), { {}} },
|
||||
{ QStringLiteral("scrobble-disabled"), { {}} },
|
||||
{ QStringLiteral("scrobble"), { {QStringLiteral("love")}} },
|
||||
{ QStringLiteral("search"), { {}} },
|
||||
{ QStringLiteral("soundcard"), { {QStringLiteral("audiocard"), QStringLiteral("audio-card")}} },
|
||||
{ QStringLiteral("speaker"), { {}} },
|
||||
{ QStringLiteral("star-grey"), { {}} },
|
||||
{ QStringLiteral("star"), { {}} },
|
||||
{ QStringLiteral("strawberry"), { {}} },
|
||||
{ QStringLiteral("subsonic"), { {}} },
|
||||
{ QStringLiteral("tidal"), { {}} },
|
||||
{ QStringLiteral("tools-wizard"), { {}} },
|
||||
{ QStringLiteral("view-choose"), { {}} },
|
||||
{ QStringLiteral("view-fullscreen"), { {}} },
|
||||
{ QStringLiteral("view-media-lyrics"), { {}} },
|
||||
{ QStringLiteral("view-media-playlist"), { {}} },
|
||||
{ QStringLiteral("view-media-visualization"), { {QStringLiteral("preferences-desktop-theme")}} },
|
||||
{ QStringLiteral("view-refresh"), { {}} },
|
||||
{ QStringLiteral("library-music"), { {QStringLiteral("vinyl")}} },
|
||||
{ QStringLiteral("vlc"), { {}} },
|
||||
{ QStringLiteral("zoom-in"), { {}} },
|
||||
{ QStringLiteral("zoom-out"), { {}, 0, 0 } }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -60,13 +60,12 @@
|
|||
#include <QDir>
|
||||
#include <QEvent>
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
QDebug operator<<(QDebug dbg, NSObject *object) {
|
||||
|
||||
QString ns_format = [[NSString stringWithFormat:@"%@", object] UTF8String];
|
||||
const QString ns_format = QString::fromUtf8([[NSString stringWithFormat:@"%@", object] UTF8String]);
|
||||
dbg.nospace() << ns_format;
|
||||
return dbg.space();
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void MacFSListener::EventStreamCallback(ConstFSEventStreamRef stream, void *user
|
|||
for (size_t i = 0; i < num_events; ++i) {
|
||||
QString path = QString::fromUtf8(paths[i]);
|
||||
qLog(Debug) << "Something changed at:" << path;
|
||||
while (path.endsWith('/')) {
|
||||
while (path.endsWith(QLatin1Char('/'))) {
|
||||
path.chop(1);
|
||||
}
|
||||
emit me->PathChanged(path);
|
||||
|
|
|
@ -70,7 +70,7 @@ class MacSystemTrayIconPrivate {
|
|||
MacSystemTrayIconPrivate() {
|
||||
dock_menu_ = [[NSMenu alloc] initWithTitle:@"DockMenu"];
|
||||
|
||||
QString title = QT_TR_NOOP("Now Playing");
|
||||
QString title = QT_TR_NOOP(QStringLiteral("Now Playing"));
|
||||
NSString *t = [[NSString alloc] initWithUTF8String:title.toUtf8().constData()];
|
||||
now_playing_ = [[NSMenuItem alloc] initWithTitle:t action:nullptr keyEquivalent:@""];
|
||||
now_playing_artist_ = [[NSMenuItem alloc] initWithTitle:@"Nothing to see here" action:nullptr keyEquivalent:@""];
|
||||
|
@ -89,7 +89,7 @@ class MacSystemTrayIconPrivate {
|
|||
|
||||
void AddMenuItem(QAction *action) {
|
||||
// Strip accelarators from name.
|
||||
QString text = action->text().remove("&");
|
||||
QString text = action->text().remove(QLatin1Char('&'));
|
||||
NSString *title = [[NSString alloc] initWithUTF8String: text.toUtf8().constData()];
|
||||
// Create an object that can receive user clicks and pass them on to the QAction.
|
||||
Target *target = [[Target alloc] initWithQAction:action];
|
||||
|
@ -152,10 +152,10 @@ class MacSystemTrayIconPrivate {
|
|||
|
||||
SystemTrayIcon::SystemTrayIcon(QObject *parent)
|
||||
: QObject(parent),
|
||||
normal_icon_(QPixmap(":/pictures/strawberry.png").scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation)),
|
||||
grey_icon_(QPixmap(":/pictures/strawberry-grey.png").scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation)),
|
||||
playing_icon_(":/pictures/tiny-play.png"),
|
||||
paused_icon_(":/pictures/tiny-pause.png"),
|
||||
normal_icon_(QPixmap(QStringLiteral(":/pictures/strawberry.png")).scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation)),
|
||||
grey_icon_(QPixmap(QStringLiteral(":/pictures/strawberry-grey.png")).scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation)),
|
||||
playing_icon_(QStringLiteral(":/pictures/tiny-play.png")),
|
||||
paused_icon_(QStringLiteral(":/pictures/tiny-pause.png")),
|
||||
trayicon_progress_(false),
|
||||
song_progress_(0) {
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
# include "qtsystemtrayicon.h"
|
||||
#endif
|
||||
#include "networkaccessmanager.h"
|
||||
#include "settings.h"
|
||||
#include "utilities/envutils.h"
|
||||
#include "utilities/filemanagerutils.h"
|
||||
#include "utilities/timeconstants.h"
|
||||
|
@ -176,6 +177,9 @@
|
|||
# include "tidal/tidalservice.h"
|
||||
# include "settings/tidalsettingspage.h"
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
# include "settings/spotifysettingspage.h"
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
# include "settings/qobuzsettingspage.h"
|
||||
#endif
|
||||
|
@ -301,13 +305,16 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
}),
|
||||
smartplaylists_view_(new SmartPlaylistsViewContainer(app, this)),
|
||||
#ifdef HAVE_SUBSONIC
|
||||
subsonic_view_(new InternetSongsView(app_, app->internet_services()->ServiceBySource(Song::Source::Subsonic), SubsonicSettingsPage::kSettingsGroup, SettingsDialog::Page::Subsonic, this)),
|
||||
subsonic_view_(new InternetSongsView(app_, app->internet_services()->ServiceBySource(Song::Source::Subsonic), QLatin1String(SubsonicSettingsPage::kSettingsGroup), SettingsDialog::Page::Subsonic, this)),
|
||||
#endif
|
||||
#ifdef HAVE_TIDAL
|
||||
tidal_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source::Tidal), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page::Tidal, this)),
|
||||
tidal_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source::Tidal), QLatin1String(TidalSettingsPage::kSettingsGroup), SettingsDialog::Page::Tidal, this)),
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
spotify_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source::Spotify), QLatin1String(SpotifySettingsPage::kSettingsGroup), SettingsDialog::Page::Spotify, this)),
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
qobuz_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source::Qobuz), QobuzSettingsPage::kSettingsGroup, SettingsDialog::Page::Qobuz, this)),
|
||||
qobuz_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source::Qobuz), QLatin1String(QobuzSettingsPage::kSettingsGroup), SettingsDialog::Page::Qobuz, this)),
|
||||
#endif
|
||||
radio_view_(new RadioViewContainer(this)),
|
||||
lastfm_import_dialog_(new LastFMImportDialog(app_->lastfm_import(), this)),
|
||||
|
@ -363,7 +370,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
// Initialize the UI
|
||||
ui_->setupUi(this);
|
||||
|
||||
setWindowIcon(IconLoader::Load("strawberry"));
|
||||
setWindowIcon(IconLoader::Load(QStringLiteral("strawberry")));
|
||||
|
||||
album_cover_choice_controller_->Init(app);
|
||||
|
||||
|
@ -375,30 +382,33 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
|
||||
|
||||
// Add tabs to the fancy tab widget
|
||||
ui_->tabs->AddTab(context_view_, "context", IconLoader::Load("strawberry", true, 0, 32), tr("Context"));
|
||||
ui_->tabs->AddTab(collection_view_, "collection", IconLoader::Load("library-music", true, 0, 32), tr("Collection"));
|
||||
ui_->tabs->AddTab(queue_view_, "queue", IconLoader::Load("footsteps", true, 0, 32), tr("Queue"));
|
||||
ui_->tabs->AddTab(playlist_list_, "playlists", IconLoader::Load("view-media-playlist", true, 0, 32), tr("Playlists"));
|
||||
ui_->tabs->AddTab(smartplaylists_view_, "smartplaylists", IconLoader::Load("view-media-playlist", true, 0, 32), tr("Smart playlists"));
|
||||
ui_->tabs->AddTab(file_view_, "files", IconLoader::Load("document-open", true, 0, 32), tr("Files"));
|
||||
ui_->tabs->AddTab(radio_view_, "radios", IconLoader::Load("radio", true, 0, 32), tr("Radios"));
|
||||
ui_->tabs->AddTab(context_view_, QStringLiteral("context"), IconLoader::Load(QStringLiteral("strawberry"), true, 0, 32), tr("Context"));
|
||||
ui_->tabs->AddTab(collection_view_, QStringLiteral("collection"), IconLoader::Load(QStringLiteral("library-music"), true, 0, 32), tr("Collection"));
|
||||
ui_->tabs->AddTab(queue_view_, QStringLiteral("queue"), IconLoader::Load(QStringLiteral("footsteps"), true, 0, 32), tr("Queue"));
|
||||
ui_->tabs->AddTab(playlist_list_, QStringLiteral("playlists"), IconLoader::Load(QStringLiteral("view-media-playlist"), true, 0, 32), tr("Playlists"));
|
||||
ui_->tabs->AddTab(smartplaylists_view_, QStringLiteral("smartplaylists"), IconLoader::Load(QStringLiteral("view-media-playlist"), true, 0, 32), tr("Smart playlists"));
|
||||
ui_->tabs->AddTab(file_view_, QStringLiteral("files"), IconLoader::Load(QStringLiteral("document-open"), true, 0, 32), tr("Files"));
|
||||
ui_->tabs->AddTab(radio_view_, QStringLiteral("radios"), IconLoader::Load(QStringLiteral("radio"), true, 0, 32), tr("Radios"));
|
||||
#ifndef Q_OS_WIN
|
||||
ui_->tabs->AddTab(device_view_, "devices", IconLoader::Load("device", true, 0, 32), tr("Devices"));
|
||||
ui_->tabs->AddTab(device_view_, QStringLiteral("devices"), IconLoader::Load(QStringLiteral("device"), true, 0, 32), tr("Devices"));
|
||||
#endif
|
||||
#ifdef HAVE_SUBSONIC
|
||||
ui_->tabs->AddTab(subsonic_view_, "subsonic", IconLoader::Load("subsonic", true, 0, 32), tr("Subsonic"));
|
||||
ui_->tabs->AddTab(subsonic_view_, QStringLiteral("subsonic"), IconLoader::Load(QStringLiteral("subsonic"), true, 0, 32), tr("Subsonic"));
|
||||
#endif
|
||||
#ifdef HAVE_TIDAL
|
||||
ui_->tabs->AddTab(tidal_view_, "tidal", IconLoader::Load("tidal", true, 0, 32), tr("Tidal"));
|
||||
ui_->tabs->AddTab(tidal_view_, QStringLiteral("tidal"), IconLoader::Load(QStringLiteral("tidal"), true, 0, 32), tr("Tidal"));
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
ui_->tabs->AddTab(spotify_view_, QLatin1String("spotify"), IconLoader::Load(QStringLiteral("spotify"), true, 0, 32), tr("Spotify"));
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
ui_->tabs->AddTab(qobuz_view_, "qobuz", IconLoader::Load("qobuz", true, 0, 32), tr("Qobuz"));
|
||||
ui_->tabs->AddTab(qobuz_view_, QStringLiteral("qobuz"), IconLoader::Load(QStringLiteral("qobuz"), true, 0, 32), tr("Qobuz"));
|
||||
#endif
|
||||
|
||||
// Add the playing widget to the fancy tab widget
|
||||
ui_->tabs->addBottomWidget(ui_->widget_playing);
|
||||
//ui_->tabs->SetBackgroundPixmap(QPixmap(":/pictures/strawberry-background.png"));
|
||||
ui_->tabs->Load(kSettingsGroup);
|
||||
ui_->tabs->setBackgroundPixmap(QPixmap(QStringLiteral(":/pictures/sidebar-background.png")));
|
||||
ui_->tabs->Load(QLatin1String(kSettingsGroup));
|
||||
|
||||
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
|
||||
QObject::connect(track_position_timer_, &QTimer::timeout, this, &MainWindow::UpdateTrackPosition);
|
||||
|
@ -447,59 +457,59 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
|
||||
// Help menu
|
||||
|
||||
ui_->action_about_strawberry->setIcon(IconLoader::Load("strawberry"));
|
||||
ui_->action_about_qt->setIcon(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"));
|
||||
ui_->action_about_strawberry->setIcon(IconLoader::Load(QStringLiteral("strawberry")));
|
||||
ui_->action_about_qt->setIcon(QIcon(QStringLiteral(":/qt-project.org/qmessagebox/images/qtlogo-64.png")));
|
||||
|
||||
// Music menu
|
||||
|
||||
ui_->action_open_file->setIcon(IconLoader::Load("document-open"));
|
||||
ui_->action_open_cd->setIcon(IconLoader::Load("media-optical"));
|
||||
ui_->action_previous_track->setIcon(IconLoader::Load("media-skip-backward"));
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-playback-start"));
|
||||
ui_->action_stop->setIcon(IconLoader::Load("media-playback-stop"));
|
||||
ui_->action_stop_after_this_track->setIcon(IconLoader::Load("media-playback-stop"));
|
||||
ui_->action_next_track->setIcon(IconLoader::Load("media-skip-forward"));
|
||||
ui_->action_quit->setIcon(IconLoader::Load("application-exit"));
|
||||
ui_->action_open_file->setIcon(IconLoader::Load(QStringLiteral("document-open")));
|
||||
ui_->action_open_cd->setIcon(IconLoader::Load(QStringLiteral("media-optical")));
|
||||
ui_->action_previous_track->setIcon(IconLoader::Load(QStringLiteral("media-skip-backward")));
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
ui_->action_stop->setIcon(IconLoader::Load(QStringLiteral("media-playback-stop")));
|
||||
ui_->action_stop_after_this_track->setIcon(IconLoader::Load(QStringLiteral("media-playback-stop")));
|
||||
ui_->action_next_track->setIcon(IconLoader::Load(QStringLiteral("media-skip-forward")));
|
||||
ui_->action_quit->setIcon(IconLoader::Load(QStringLiteral("application-exit")));
|
||||
|
||||
// Playlist
|
||||
|
||||
ui_->action_add_file->setIcon(IconLoader::Load("document-open"));
|
||||
ui_->action_add_folder->setIcon(IconLoader::Load("document-open-folder"));
|
||||
ui_->action_add_stream->setIcon(IconLoader::Load("document-open-remote"));
|
||||
ui_->action_shuffle_mode->setIcon(IconLoader::Load("media-playlist-shuffle"));
|
||||
ui_->action_repeat_mode->setIcon(IconLoader::Load("media-playlist-repeat"));
|
||||
ui_->action_new_playlist->setIcon(IconLoader::Load("document-new"));
|
||||
ui_->action_save_playlist->setIcon(IconLoader::Load("document-save"));
|
||||
ui_->action_load_playlist->setIcon(IconLoader::Load("document-open"));
|
||||
ui_->action_jump->setIcon(IconLoader::Load("go-jump"));
|
||||
ui_->action_clear_playlist->setIcon(IconLoader::Load("edit-clear-list"));
|
||||
ui_->action_shuffle->setIcon(IconLoader::Load("media-playlist-shuffle"));
|
||||
ui_->action_remove_duplicates->setIcon(IconLoader::Load("list-remove"));
|
||||
ui_->action_remove_unavailable->setIcon(IconLoader::Load("list-remove"));
|
||||
ui_->action_remove_from_playlist->setIcon(IconLoader::Load("list-remove"));
|
||||
ui_->action_save_all_playlists->setIcon(IconLoader::Load("document-save-all"));
|
||||
ui_->action_add_file->setIcon(IconLoader::Load(QStringLiteral("document-open")));
|
||||
ui_->action_add_folder->setIcon(IconLoader::Load(QStringLiteral("document-open-folder")));
|
||||
ui_->action_add_stream->setIcon(IconLoader::Load(QStringLiteral("document-open-remote")));
|
||||
ui_->action_shuffle_mode->setIcon(IconLoader::Load(QStringLiteral("media-playlist-shuffle")));
|
||||
ui_->action_repeat_mode->setIcon(IconLoader::Load(QStringLiteral("media-playlist-repeat")));
|
||||
ui_->action_new_playlist->setIcon(IconLoader::Load(QStringLiteral("document-new")));
|
||||
ui_->action_save_playlist->setIcon(IconLoader::Load(QStringLiteral("document-save")));
|
||||
ui_->action_load_playlist->setIcon(IconLoader::Load(QStringLiteral("document-open")));
|
||||
ui_->action_jump->setIcon(IconLoader::Load(QStringLiteral("go-jump")));
|
||||
ui_->action_clear_playlist->setIcon(IconLoader::Load(QStringLiteral("edit-clear-list")));
|
||||
ui_->action_shuffle->setIcon(IconLoader::Load(QStringLiteral("media-playlist-shuffle")));
|
||||
ui_->action_remove_duplicates->setIcon(IconLoader::Load(QStringLiteral("list-remove")));
|
||||
ui_->action_remove_unavailable->setIcon(IconLoader::Load(QStringLiteral("list-remove")));
|
||||
ui_->action_remove_from_playlist->setIcon(IconLoader::Load(QStringLiteral("list-remove")));
|
||||
ui_->action_save_all_playlists->setIcon(IconLoader::Load(QStringLiteral("document-save-all")));
|
||||
|
||||
// Configure
|
||||
|
||||
ui_->action_cover_manager->setIcon(IconLoader::Load("document-download"));
|
||||
ui_->action_edit_track->setIcon(IconLoader::Load("edit-rename"));
|
||||
ui_->action_edit_value->setIcon(IconLoader::Load("edit-rename"));
|
||||
ui_->action_selection_set_value->setIcon(IconLoader::Load("edit-rename"));
|
||||
ui_->action_equalizer->setIcon(IconLoader::Load("equalizer"));
|
||||
ui_->action_transcoder->setIcon(IconLoader::Load("tools-wizard"));
|
||||
ui_->action_update_collection->setIcon(IconLoader::Load("view-refresh"));
|
||||
ui_->action_full_collection_scan->setIcon(IconLoader::Load("view-refresh"));
|
||||
ui_->action_abort_collection_scan->setIcon(IconLoader::Load("dialog-error"));
|
||||
ui_->action_settings->setIcon(IconLoader::Load("configure"));
|
||||
ui_->action_import_data_from_last_fm->setIcon(IconLoader::Load("scrobble"));
|
||||
ui_->action_console->setIcon(IconLoader::Load("keyboard"));
|
||||
ui_->action_toggle_show_sidebar->setIcon(IconLoader::Load("view-choose"));
|
||||
ui_->action_auto_complete_tags->setIcon(IconLoader::Load("musicbrainz"));
|
||||
ui_->action_cover_manager->setIcon(IconLoader::Load(QStringLiteral("document-download")));
|
||||
ui_->action_edit_track->setIcon(IconLoader::Load(QStringLiteral("edit-rename")));
|
||||
ui_->action_edit_value->setIcon(IconLoader::Load(QStringLiteral("edit-rename")));
|
||||
ui_->action_selection_set_value->setIcon(IconLoader::Load(QStringLiteral("edit-rename")));
|
||||
ui_->action_equalizer->setIcon(IconLoader::Load(QStringLiteral("equalizer")));
|
||||
ui_->action_transcoder->setIcon(IconLoader::Load(QStringLiteral("tools-wizard")));
|
||||
ui_->action_update_collection->setIcon(IconLoader::Load(QStringLiteral("view-refresh")));
|
||||
ui_->action_full_collection_scan->setIcon(IconLoader::Load(QStringLiteral("view-refresh")));
|
||||
ui_->action_abort_collection_scan->setIcon(IconLoader::Load(QStringLiteral("dialog-error")));
|
||||
ui_->action_settings->setIcon(IconLoader::Load(QStringLiteral("configure")));
|
||||
ui_->action_import_data_from_last_fm->setIcon(IconLoader::Load(QStringLiteral("scrobble")));
|
||||
ui_->action_console->setIcon(IconLoader::Load(QStringLiteral("keyboard")));
|
||||
ui_->action_toggle_show_sidebar->setIcon(IconLoader::Load(QStringLiteral("view-choose")));
|
||||
ui_->action_auto_complete_tags->setIcon(IconLoader::Load(QStringLiteral("musicbrainz")));
|
||||
|
||||
// Scrobble
|
||||
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load("scrobble-disabled"));
|
||||
ui_->action_love->setIcon(IconLoader::Load("love"));
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load(QStringLiteral("scrobble-disabled")));
|
||||
ui_->action_love->setIcon(IconLoader::Load(QStringLiteral("love")));
|
||||
|
||||
// File view connections
|
||||
QObject::connect(file_view_, &FileView::AddToPlaylist, this, &MainWindow::AddToPlaylist);
|
||||
|
@ -558,7 +568,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
QObject::connect(ui_->action_abort_collection_scan, &QAction::triggered, &*app_->collection(), &SCollection::AbortScan);
|
||||
#if defined(HAVE_GSTREAMER)
|
||||
QObject::connect(ui_->action_add_files_to_transcoder, &QAction::triggered, this, &MainWindow::AddFilesToTranscoder);
|
||||
ui_->action_add_files_to_transcoder->setIcon(IconLoader::Load("tools-wizard"));
|
||||
ui_->action_add_files_to_transcoder->setIcon(IconLoader::Load(QStringLiteral("tools-wizard")));
|
||||
#else
|
||||
ui_->action_add_files_to_transcoder->setDisabled(true);
|
||||
#endif
|
||||
|
@ -568,8 +578,8 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
QObject::connect(&*app_->scrobbler(), &AudioScrobbler::ErrorMessage, this, &MainWindow::ShowErrorDialog);
|
||||
|
||||
// Playlist view actions
|
||||
ui_->action_next_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString("Ctrl+Tab") << QKeySequence::fromString("Ctrl+PgDown"));
|
||||
ui_->action_previous_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString("Ctrl+Shift+Tab") << QKeySequence::fromString("Ctrl+PgUp"));
|
||||
ui_->action_next_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString(QStringLiteral("Ctrl+Tab")) << QKeySequence::fromString(QStringLiteral("Ctrl+PgDown")));
|
||||
ui_->action_previous_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString(QStringLiteral("Ctrl+Shift+Tab")) << QKeySequence::fromString(QStringLiteral("Ctrl+PgUp")));
|
||||
|
||||
// Actions for switching tabs will be global to the entire window, so adding them here
|
||||
addAction(ui_->action_next_playlist);
|
||||
|
@ -688,9 +698,9 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
|
||||
QObject::connect(collection_view_group, &QActionGroup::triggered, this, &MainWindow::ChangeCollectionFilterMode);
|
||||
|
||||
QAction *collection_config_action = new QAction(IconLoader::Load("configure"), tr("Configure collection..."), this);
|
||||
QAction *collection_config_action = new QAction(IconLoader::Load(QStringLiteral("configure")), tr("Configure collection..."), this);
|
||||
QObject::connect(collection_config_action, &QAction::triggered, this, &MainWindow::ShowCollectionConfig);
|
||||
collection_view_->filter_widget()->SetSettingsGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
collection_view_->filter_widget()->SetSettingsGroup(QLatin1String(CollectionSettingsPage::kSettingsGroup));
|
||||
collection_view_->filter_widget()->Init(app_->collection()->model());
|
||||
|
||||
QAction *separator = new QAction(this);
|
||||
|
@ -723,6 +733,13 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
QObject::connect(qobuz_view_->search_view(), &InternetSearchView::AddToPlaylist, this, &MainWindow::AddToPlaylist);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SPOTIFY
|
||||
QObject::connect(spotify_view_->artists_collection_view(), &InternetCollectionView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
|
||||
QObject::connect(spotify_view_->albums_collection_view(), &InternetCollectionView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
|
||||
QObject::connect(spotify_view_->songs_collection_view(), &InternetCollectionView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
|
||||
QObject::connect(spotify_view_->search_view(), &InternetSearchView::AddToPlaylist, this, &MainWindow::AddToPlaylist);
|
||||
#endif
|
||||
|
||||
QObject::connect(radio_view_, &RadioViewContainer::Refresh, &*app_->radio_services(), &RadioServices::RefreshChannels);
|
||||
QObject::connect(radio_view_->view(), &RadioView::GetChannels, &*app_->radio_services(), &RadioServices::GetChannels);
|
||||
QObject::connect(radio_view_->view(), &RadioView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
|
||||
|
@ -731,14 +748,14 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
QObject::connect(playlist_menu_, &QMenu::aboutToHide, this, &MainWindow::PlaylistMenuHidden);
|
||||
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, &MainWindow::PlaylistPlay);
|
||||
playlist_menu_->addAction(ui_->action_stop);
|
||||
playlist_stop_after_ = playlist_menu_->addAction(IconLoader::Load("media-playback-stop"), tr("Stop after this track"), this, &MainWindow::PlaylistStopAfter);
|
||||
playlist_queue_ = playlist_menu_->addAction(IconLoader::Load("go-next"), tr("Toggle queue status"), this, &MainWindow::PlaylistQueue);
|
||||
playlist_queue_->setShortcut(QKeySequence("Ctrl+D"));
|
||||
playlist_stop_after_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("media-playback-stop")), tr("Stop after this track"), this, &MainWindow::PlaylistStopAfter);
|
||||
playlist_queue_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("go-next")), tr("Toggle queue status"), this, &MainWindow::PlaylistQueue);
|
||||
playlist_queue_->setShortcut(QKeySequence(QStringLiteral("Ctrl+D")));
|
||||
ui_->playlist->addAction(playlist_queue_);
|
||||
playlist_queue_play_next_ = playlist_menu_->addAction(IconLoader::Load("go-next"), tr("Queue selected tracks to play next"), this, &MainWindow::PlaylistQueuePlayNext);
|
||||
playlist_queue_play_next_->setShortcut(QKeySequence("Ctrl+Shift+D"));
|
||||
playlist_queue_play_next_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("go-next")), tr("Queue selected tracks to play next"), this, &MainWindow::PlaylistQueuePlayNext);
|
||||
playlist_queue_play_next_->setShortcut(QKeySequence(QStringLiteral("Ctrl+Shift+D")));
|
||||
ui_->playlist->addAction(playlist_queue_play_next_);
|
||||
playlist_skip_ = playlist_menu_->addAction(IconLoader::Load("media-skip-forward"), tr("Toggle skip status"), this, &MainWindow::PlaylistSkip);
|
||||
playlist_skip_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("media-skip-forward")), tr("Toggle skip status"), this, &MainWindow::PlaylistSkip);
|
||||
ui_->playlist->addAction(playlist_skip_);
|
||||
|
||||
playlist_menu_->addSeparator();
|
||||
|
@ -751,22 +768,22 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
#ifdef HAVE_MUSICBRAINZ
|
||||
playlist_menu_->addAction(ui_->action_auto_complete_tags);
|
||||
#endif
|
||||
playlist_rescan_songs_ = playlist_menu_->addAction(IconLoader::Load("view-refresh"), tr("Rescan song(s)..."), this, &MainWindow::RescanSongs);
|
||||
playlist_rescan_songs_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("view-refresh")), tr("Rescan song(s)..."), this, &MainWindow::RescanSongs);
|
||||
playlist_menu_->addAction(playlist_rescan_songs_);
|
||||
#ifdef HAVE_GSTREAMER
|
||||
playlist_menu_->addAction(ui_->action_add_files_to_transcoder);
|
||||
#endif
|
||||
playlist_menu_->addSeparator();
|
||||
playlist_copy_url_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy URL(s)..."), this, &MainWindow::PlaylistCopyUrl);
|
||||
playlist_show_in_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-find"), tr("Show in collection..."), this, &MainWindow::ShowInCollection);
|
||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, &MainWindow::PlaylistOpenInBrowser);
|
||||
playlist_organize_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, &MainWindow::PlaylistMoveToCollection);
|
||||
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, &MainWindow::PlaylistCopyToCollection);
|
||||
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, &MainWindow::PlaylistMoveToCollection);
|
||||
playlist_copy_url_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("edit-copy")), tr("Copy URL(s)..."), this, &MainWindow::PlaylistCopyUrl);
|
||||
playlist_show_in_collection_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("edit-find")), tr("Show in collection..."), this, &MainWindow::ShowInCollection);
|
||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("document-open-folder")), tr("Show in file browser..."), this, &MainWindow::PlaylistOpenInBrowser);
|
||||
playlist_organize_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("edit-copy")), tr("Organize files..."), this, &MainWindow::PlaylistMoveToCollection);
|
||||
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("edit-copy")), tr("Copy to collection..."), this, &MainWindow::PlaylistCopyToCollection);
|
||||
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("go-jump")), tr("Move to collection..."), this, &MainWindow::PlaylistMoveToCollection);
|
||||
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, &MainWindow::PlaylistCopyToDevice);
|
||||
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("device")), tr("Copy to device..."), this, &MainWindow::PlaylistCopyToDevice);
|
||||
#endif
|
||||
playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, &MainWindow::PlaylistDelete);
|
||||
playlist_delete_ = playlist_menu_->addAction(IconLoader::Load(QStringLiteral("edit-delete")), tr("Delete from disk..."), this, &MainWindow::PlaylistDelete);
|
||||
playlist_menu_->addSeparator();
|
||||
playlistitem_actions_separator_ = playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_->action_clear_playlist);
|
||||
|
@ -854,7 +871,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
QObject::connect(ui_->analyzer, &AnalyzerContainer::WheelEvent, this, &MainWindow::VolumeWheelEvent);
|
||||
|
||||
// Statusbar widgets
|
||||
ui_->playlist_summary->setMinimumWidth(QFontMetrics(font()).horizontalAdvance("WW selected of WW tracks - [ WW:WW ]"));
|
||||
ui_->playlist_summary->setMinimumWidth(QFontMetrics(font()).horizontalAdvance(QStringLiteral("WW selected of WW tracks - [ WW:WW ]")));
|
||||
ui_->status_bar_stack->setCurrentWidget(ui_->playlist_summary_page);
|
||||
QObject::connect(ui_->multi_loading_indicator, &MultiLoadingIndicator::TaskCountChange, this, &MainWindow::TaskCountChanged);
|
||||
|
||||
|
@ -881,7 +898,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
PlayingWidgetPositionChanged(ui_->widget_playing->show_above_status_bar());
|
||||
|
||||
StyleSheetLoader *css_loader = new StyleSheetLoader(this);
|
||||
css_loader->SetStyleSheet(this, ":/style/strawberry.css");
|
||||
css_loader->SetStyleSheet(this, QStringLiteral(":/style/strawberry.css"));
|
||||
|
||||
// Load playlists
|
||||
app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist);
|
||||
|
@ -952,7 +969,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
#else
|
||||
BehaviourSettingsPage::StartupBehaviour startupbehaviour = BehaviourSettingsPage::StartupBehaviour::Remember;
|
||||
{
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||
startupbehaviour = static_cast<BehaviourSettingsPage::StartupBehaviour>(s.value("startupbehaviour", static_cast<int>(BehaviourSettingsPage::StartupBehaviour::Remember)).toInt());
|
||||
s.endGroup();
|
||||
|
@ -975,7 +992,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
}
|
||||
[[fallthrough]];
|
||||
case BehaviourSettingsPage::StartupBehaviour::Remember:
|
||||
default: {
|
||||
default:{
|
||||
|
||||
was_maximized_ = settings_.value("maximized", true).toBool();
|
||||
if (was_maximized_) setWindowState(windowState() | Qt::WindowMaximized);
|
||||
|
@ -1008,7 +1025,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
QObject::connect(close_window_shortcut, &QShortcut::activated, this, &MainWindow::ToggleHide);
|
||||
|
||||
QAction *action_focus_search = new QAction(this);
|
||||
action_focus_search->setShortcuts(QList<QKeySequence>() << QKeySequence("Ctrl+F"));
|
||||
action_focus_search->setShortcuts(QList<QKeySequence>() << QKeySequence(QStringLiteral("Ctrl+F")));
|
||||
addAction(action_focus_search);
|
||||
QObject::connect(action_focus_search, &QAction::triggered, this, &MainWindow::FocusSearchField);
|
||||
|
||||
|
@ -1024,18 +1041,18 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
}
|
||||
|
||||
#ifdef HAVE_QTSPARKLE
|
||||
QUrl sparkle_url(QTSPARKLE_URL);
|
||||
QUrl sparkle_url(QString::fromLatin1(QTSPARKLE_URL));
|
||||
if (!sparkle_url.isEmpty()) {
|
||||
qLog(Debug) << "Creating Qt Sparkle updater";
|
||||
qtsparkle::Updater *updater = new qtsparkle::Updater(sparkle_url, this);
|
||||
updater->SetVersion(STRAWBERRY_VERSION_PACKAGE);
|
||||
updater->SetVersion(QStringLiteral(STRAWBERRY_VERSION_PACKAGE));
|
||||
QObject::connect(check_updates, &QAction::triggered, updater, &qtsparkle::Updater::CheckNow);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
if (!Utilities::GetEnv("SNAP").isEmpty() && !Utilities::GetEnv("SNAP_NAME").isEmpty()) {
|
||||
QSettings s;
|
||||
if (!Utilities::GetEnv(QStringLiteral("SNAP")).isEmpty() && !Utilities::GetEnv(QStringLiteral("SNAP_NAME")).isEmpty()) {
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
const bool ignore_snap = s.value("ignore_snap", false).toBool();
|
||||
s.endGroup();
|
||||
|
@ -1049,32 +1066,32 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
|
|||
|
||||
#if defined(Q_OS_MACOS)
|
||||
if (Utilities::ProcessTranslated()) {
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
const bool ignore_rosetta = s.value("ignore_rosetta", false).toBool();
|
||||
s.endGroup();
|
||||
if (!ignore_rosetta) {
|
||||
MessageDialog *rosetta_message = new MessageDialog(this);
|
||||
rosetta_message->set_settings_group(kSettingsGroup);
|
||||
rosetta_message->set_do_not_show_message_again("ignore_rosetta");
|
||||
rosetta_message->set_settings_group(QLatin1String(kSettingsGroup));
|
||||
rosetta_message->set_do_not_show_message_again(QStringLiteral("ignore_rosetta"));
|
||||
rosetta_message->setAttribute(Qt::WA_DeleteOnClose);
|
||||
rosetta_message->ShowMessage(tr("Strawberry running under Rosetta"), tr("You are running Strawberry under Rosetta. Running Strawberry under Rosetta is unsupported and known to have issues. You should download Strawberry for the correct CPU architecture from %1").arg("<a href=\"https://downloads.strawberrymusicplayer.org/\">downloads.strawberrymusicplayer.org</a>"), IconLoader::Load("dialog-warning"));
|
||||
rosetta_message->ShowMessage(tr("Strawberry running under Rosetta"), tr("You are running Strawberry under Rosetta. Running Strawberry under Rosetta is unsupported and known to have issues. You should download Strawberry for the correct CPU architecture from %1").arg(QStringLiteral("<a href=\"https://downloads.strawberrymusicplayer.org/\">downloads.strawberrymusicplayer.org</a>")), IconLoader::Load(QStringLiteral("dialog-warning")));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
const QString do_not_show_sponsor_message_key = QString("do_not_show_sponsor_message");
|
||||
constexpr char do_not_show_sponsor_message_key[] = "do_not_show_sponsor_message";
|
||||
const bool do_not_show_sponsor_message = s.value(do_not_show_sponsor_message_key, false).toBool();
|
||||
s.endGroup();
|
||||
if (!do_not_show_sponsor_message) {
|
||||
MessageDialog *sponsor_message = new MessageDialog(this);
|
||||
sponsor_message->set_settings_group(kSettingsGroup);
|
||||
sponsor_message->set_do_not_show_message_again(do_not_show_sponsor_message_key);
|
||||
sponsor_message->set_settings_group(QLatin1String(kSettingsGroup));
|
||||
sponsor_message->set_do_not_show_message_again(QLatin1String(do_not_show_sponsor_message_key));
|
||||
sponsor_message->setAttribute(Qt::WA_DeleteOnClose);
|
||||
sponsor_message->ShowMessage(tr("Sponsoring Strawberry"), tr("Strawberry is free and open source software. If you like Strawberry, please consider sponsoring the project. For more information about sponsorship see our website %1").arg("<a href= \"https://www.strawberrymusicplayer.org/\">www.strawberrymusicplayer.org</a>"), IconLoader::Load("dialog-information"));
|
||||
sponsor_message->ShowMessage(tr("Sponsoring Strawberry"), tr("Strawberry is free and open source software. If you like Strawberry, please consider sponsoring the project. For more information about sponsorship see our website %1").arg(QStringLiteral("<a href= \"https://www.strawberrymusicplayer.org/\">www.strawberrymusicplayer.org</a>")), IconLoader::Load(QStringLiteral("dialog-information")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1089,7 +1106,7 @@ MainWindow::~MainWindow() {
|
|||
|
||||
void MainWindow::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
constexpr bool keeprunning_available = true;
|
||||
|
@ -1187,6 +1204,18 @@ void MainWindow::ReloadSettings() {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SPOTIFY
|
||||
s.beginGroup(SpotifySettingsPage::kSettingsGroup);
|
||||
bool enable_spotify = s.value("enabled", false).toBool();
|
||||
s.endGroup();
|
||||
if (enable_spotify) {
|
||||
ui_->tabs->EnableTab(spotify_view_);
|
||||
}
|
||||
else {
|
||||
ui_->tabs->DisableTab(spotify_view_);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_QOBUZ
|
||||
s.beginGroup(QobuzSettingsPage::kSettingsGroup);
|
||||
bool enable_qobuz = s.value("enabled", false).toBool();
|
||||
|
@ -1235,6 +1264,9 @@ void MainWindow::ReloadAllSettings() {
|
|||
#ifdef HAVE_TIDAL
|
||||
tidal_view_->ReloadSettings();
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
spotify_view_->ReloadSettings();
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
qobuz_view_->ReloadSettings();
|
||||
#endif
|
||||
|
@ -1243,7 +1275,7 @@ void MainWindow::ReloadAllSettings() {
|
|||
|
||||
void MainWindow::RefreshStyleSheet() {
|
||||
QString contents(styleSheet());
|
||||
setStyleSheet("");
|
||||
setStyleSheet(QLatin1String(""));
|
||||
setStyleSheet(contents);
|
||||
}
|
||||
|
||||
|
@ -1252,7 +1284,7 @@ void MainWindow::SaveSettings() {
|
|||
SaveGeometry();
|
||||
SavePlaybackStatus();
|
||||
app_->player()->SaveVolume();
|
||||
ui_->tabs->SaveSettings(kSettingsGroup);
|
||||
ui_->tabs->SaveSettings(QLatin1String(kSettingsGroup));
|
||||
ui_->playlist->view()->SaveSettings();
|
||||
app_->scrobbler()->WriteCache();
|
||||
|
||||
|
@ -1328,11 +1360,11 @@ void MainWindow::EngineChanged(const EngineBase::Type enginetype) {
|
|||
|
||||
void MainWindow::MediaStopped() {
|
||||
|
||||
setWindowTitle("Strawberry Music Player");
|
||||
setWindowTitle(QStringLiteral("Strawberry Music Player"));
|
||||
|
||||
ui_->action_stop->setEnabled(false);
|
||||
ui_->action_stop_after_this_track->setEnabled(false);
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-playback-start"));
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
ui_->action_play_pause->setText(tr("Play"));
|
||||
|
||||
ui_->action_play_pause->setEnabled(true);
|
||||
|
@ -1365,7 +1397,7 @@ void MainWindow::MediaPaused() {
|
|||
|
||||
ui_->action_stop->setEnabled(true);
|
||||
ui_->action_stop_after_this_track->setEnabled(true);
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-playback-start"));
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
ui_->action_play_pause->setText(tr("Play"));
|
||||
|
||||
ui_->action_play_pause->setEnabled(true);
|
||||
|
@ -1381,7 +1413,7 @@ void MainWindow::MediaPlaying() {
|
|||
|
||||
ui_->action_stop->setEnabled(true);
|
||||
ui_->action_stop_after_this_track->setEnabled(true);
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-playback-pause"));
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load(QStringLiteral("media-playback-pause")));
|
||||
ui_->action_play_pause->setText(tr("Pause"));
|
||||
|
||||
bool enable_play_pause(false);
|
||||
|
@ -1507,7 +1539,7 @@ void MainWindow::SaveGeometry() {
|
|||
|
||||
void MainWindow::SavePlaybackStatus() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
|
||||
s.beginGroup(Player::kSettingsGroup);
|
||||
s.setValue("playback_state", static_cast<int>(app_->player()->GetState()));
|
||||
|
@ -1526,7 +1558,7 @@ void MainWindow::SavePlaybackStatus() {
|
|||
|
||||
void MainWindow::LoadPlaybackStatus() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
|
||||
s.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||
const bool resume_playback = s.value("resumeplayback", false).toBool();
|
||||
|
@ -1550,7 +1582,7 @@ void MainWindow::ResumePlayback() {
|
|||
|
||||
qLog(Debug) << "Resuming playback";
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(Player::kSettingsGroup);
|
||||
const EngineBase::State playback_state = static_cast<EngineBase::State>(s.value("playback_state", static_cast<int>(EngineBase::State::Empty)).toInt());
|
||||
int playback_playlist = s.value("playback_playlist", -1).toInt();
|
||||
|
@ -1726,7 +1758,7 @@ void MainWindow::Seeked(const qint64 microseconds) {
|
|||
|
||||
#ifdef HAVE_DBUS
|
||||
if (taskbar_progress_) {
|
||||
UpdateTaskbarProgress(true, position, length);
|
||||
UpdateTaskbarProgress(true, static_cast<double>(position) / static_cast<double>(length));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1746,7 +1778,7 @@ void MainWindow::UpdateTrackPosition() {
|
|||
|
||||
#ifdef HAVE_DBUS
|
||||
if (taskbar_progress_) {
|
||||
UpdateTaskbarProgress(true, position, length);
|
||||
UpdateTaskbarProgress(true, static_cast<double>(position) / static_cast<double>(length));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1777,14 +1809,14 @@ void MainWindow::UpdateTrackSliderPosition() {
|
|||
}
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
void MainWindow::UpdateTaskbarProgress(const bool visible, const double position, const double length) {
|
||||
void MainWindow::UpdateTaskbarProgress(const bool visible, const double progress) {
|
||||
|
||||
QVariantMap map;
|
||||
QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/strawberrymusicplayer/strawberry"), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update"));
|
||||
|
||||
map.insert(QStringLiteral("progress-visible"), visible);
|
||||
map.insert(QStringLiteral("progress"), position / length);
|
||||
msg << QString("application://org.strawberrymusicplayer.strawberry.desktop") << map;
|
||||
map.insert(QStringLiteral("progress"), progress);
|
||||
msg << QStringLiteral("application://org.strawberrymusicplayer.strawberry.desktop") << map;
|
||||
|
||||
QDBusConnection::sessionBus().send(msg);
|
||||
|
||||
|
@ -1915,11 +1947,11 @@ void MainWindow::PlaylistRightClick(const QPoint global_pos, const QModelIndex &
|
|||
// Is this song currently playing?
|
||||
if (app_->playlist_manager()->current()->current_row() == source_index.row() && app_->player()->GetState() == EngineBase::State::Playing) {
|
||||
playlist_play_pause_->setText(tr("Pause"));
|
||||
playlist_play_pause_->setIcon(IconLoader::Load("media-playback-pause"));
|
||||
playlist_play_pause_->setIcon(IconLoader::Load(QStringLiteral("media-playback-pause")));
|
||||
}
|
||||
else {
|
||||
playlist_play_pause_->setText(tr("Play"));
|
||||
playlist_play_pause_->setIcon(IconLoader::Load("media-playback-start"));
|
||||
playlist_play_pause_->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
}
|
||||
|
||||
// Are we allowed to pause?
|
||||
|
@ -2033,11 +2065,11 @@ void MainWindow::PlaylistRightClick(const QPoint global_pos, const QModelIndex &
|
|||
else playlist_skip_->setText(tr("Toggle skip status"));
|
||||
}
|
||||
|
||||
if (not_in_queue == 0) playlist_queue_->setIcon(IconLoader::Load("go-previous"));
|
||||
else playlist_queue_->setIcon(IconLoader::Load("go-next"));
|
||||
if (not_in_queue == 0) playlist_queue_->setIcon(IconLoader::Load(QStringLiteral("go-previous")));
|
||||
else playlist_queue_->setIcon(IconLoader::Load(QStringLiteral("go-next")));
|
||||
|
||||
if (in_skipped < selected) playlist_skip_->setIcon(IconLoader::Load("media-skip-forward"));
|
||||
else playlist_skip_->setIcon(IconLoader::Load("media-playback-start"));
|
||||
if (in_skipped < selected) playlist_skip_->setIcon(IconLoader::Load(QStringLiteral("media-skip-forward")));
|
||||
else playlist_skip_->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
|
||||
|
||||
if (!index.isValid()) {
|
||||
|
@ -2054,7 +2086,7 @@ void MainWindow::PlaylistRightClick(const QPoint global_pos, const QModelIndex &
|
|||
|
||||
QString column_name = Playlist::column_name(column);
|
||||
QString column_value = app_->playlist_manager()->current()->data(source_index).toString();
|
||||
if (column_value.length() > 25) column_value = column_value.left(25) + "...";
|
||||
if (column_value.length() > 25) column_value = column_value.left(25) + QStringLiteral("...");
|
||||
|
||||
ui_->action_selection_set_value->setText(tr("Set %1 to \"%2\"...").arg(column_name.toLower(), column_value));
|
||||
ui_->action_edit_value->setText(tr("Edit tag \"%1\"...").arg(column_name));
|
||||
|
@ -2100,7 +2132,7 @@ void MainWindow::PlaylistRightClick(const QPoint global_pos, const QModelIndex &
|
|||
// Create the playlist submenu if songs are selected.
|
||||
if (selected > 0) {
|
||||
QMenu *add_to_another_menu = new QMenu(tr("Add to another playlist"), this);
|
||||
add_to_another_menu->setIcon(IconLoader::Load("list-add"));
|
||||
add_to_another_menu->setIcon(IconLoader::Load(QStringLiteral("list-add")));
|
||||
|
||||
for (const PlaylistBackend::Playlist &playlist : app_->playlist_backend()->GetAllOpenPlaylists()) {
|
||||
// don't add the current playlist
|
||||
|
@ -2297,18 +2329,18 @@ void MainWindow::AddFile() {
|
|||
PlaylistParser parser(app_->collection_backend());
|
||||
|
||||
// Show dialog
|
||||
QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter, parser.filters(PlaylistParser::Type::Load), tr(kAllFilesFilterSpec)));
|
||||
QStringList filenames = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QStringLiteral("%1 (%2);;%3;;%4").arg(tr("Music"), QLatin1String(FileView::kFileFilter), parser.filters(PlaylistParser::Type::Load), tr(kAllFilesFilterSpec)));
|
||||
|
||||
if (file_names.isEmpty()) return;
|
||||
if (filenames.isEmpty()) return;
|
||||
|
||||
// Save last used directory
|
||||
settings_.setValue("add_media_path", file_names[0]);
|
||||
settings_.setValue("add_media_path", filenames[0]);
|
||||
|
||||
// Convert to URLs
|
||||
QList<QUrl> urls;
|
||||
urls.reserve(file_names.count());
|
||||
for (const QString &path : file_names) {
|
||||
urls << QUrl::fromLocalFile(QFileInfo(path).canonicalFilePath());
|
||||
urls.reserve(filenames.count());
|
||||
for (const QString &path : filenames) {
|
||||
urls << QUrl::fromLocalFile(QDir::cleanPath(path));
|
||||
}
|
||||
|
||||
MimeData *mimedata = new MimeData;
|
||||
|
@ -2331,7 +2363,7 @@ void MainWindow::AddFolder() {
|
|||
|
||||
// Add media
|
||||
MimeData *mimedata = new MimeData;
|
||||
mimedata->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath()));
|
||||
mimedata->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QDir::cleanPath(directory)));
|
||||
AddToPlaylist(mimedata);
|
||||
|
||||
}
|
||||
|
@ -2341,7 +2373,7 @@ void MainWindow::AddCDTracks() {
|
|||
MimeData *mimedata = new MimeData;
|
||||
// We are putting empty data, but we specify cdda mimetype to indicate that we want to load audio cd tracks
|
||||
mimedata->open_in_new_playlist_ = true;
|
||||
mimedata->setData(Playlist::kCddaMimeType, QByteArray());
|
||||
mimedata->setData(QLatin1String(Playlist::kCddaMimeType), QByteArray());
|
||||
AddToPlaylist(mimedata);
|
||||
|
||||
}
|
||||
|
@ -2375,7 +2407,7 @@ void MainWindow::ShowInCollection() {
|
|||
}
|
||||
QString search;
|
||||
if (!songs.isEmpty()) {
|
||||
search = "artist:" + songs.first().artist() + " album:" + songs.first().album();
|
||||
search = QStringLiteral("artist:") + songs.first().artist() + QStringLiteral(" album:") + songs.first().album();
|
||||
}
|
||||
collection_view_->filter_widget()->ShowInCollection(search);
|
||||
|
||||
|
@ -2468,9 +2500,9 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions &options) {
|
|||
break;
|
||||
|
||||
case CommandlineOptions::PlayerAction::ResizeWindow:{
|
||||
if (options.window_size().contains('x') && options.window_size().length() >= 4) {
|
||||
QString str_w = options.window_size().left(options.window_size().indexOf('x'));
|
||||
QString str_h = options.window_size().right(options.window_size().length() - options.window_size().indexOf('x') - 1);
|
||||
if (options.window_size().contains(QLatin1Char('x')) && options.window_size().length() >= 4) {
|
||||
QString str_w = options.window_size().left(options.window_size().indexOf(QLatin1Char('x')));
|
||||
QString str_h = options.window_size().right(options.window_size().length() - options.window_size().indexOf(QLatin1Char('x')) - 1);
|
||||
bool w_ok = false;
|
||||
bool h_ok = false;
|
||||
int w = str_w.toInt(&w_ok);
|
||||
|
@ -2509,7 +2541,7 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions &options) {
|
|||
|
||||
#ifdef HAVE_TIDAL
|
||||
for (const QUrl &url : options.urls()) {
|
||||
if (url.scheme() == "tidal" && url.host() == "login") {
|
||||
if (url.scheme() == QStringLiteral("tidal") && url.host() == QStringLiteral("login")) {
|
||||
emit AuthorizationUrlReceived(url);
|
||||
return;
|
||||
}
|
||||
|
@ -2587,7 +2619,7 @@ bool MainWindow::LoadUrl(const QString &url) {
|
|||
return true;
|
||||
}
|
||||
#ifdef HAVE_TIDAL
|
||||
else if (url.startsWith("tidal://login")) {
|
||||
else if (url.startsWith(QLatin1String("tidal://login"))) {
|
||||
emit AuthorizationUrlReceived(QUrl(url));
|
||||
return true;
|
||||
}
|
||||
|
@ -2951,11 +2983,11 @@ void MainWindow::CheckFullRescanRevisions() {
|
|||
|
||||
// if we have any...
|
||||
if (!reasons.isEmpty()) {
|
||||
QString message = tr("The version of Strawberry you've just updated to requires a full collection rescan because of the new features listed below:") + "<ul>";
|
||||
QString message = tr("The version of Strawberry you've just updated to requires a full collection rescan because of the new features listed below:") + QStringLiteral("<ul>");
|
||||
for (const QString &reason : reasons) {
|
||||
message += ("<li>" + reason + "</li>");
|
||||
message += QStringLiteral("<li>") + reason + QStringLiteral("</li>");
|
||||
}
|
||||
message += "</ul>" + tr("Would you like to run a full rescan right now?");
|
||||
message += QStringLiteral("</ul>") + tr("Would you like to run a full rescan right now?");
|
||||
if (QMessageBox::question(this, tr("Collection rescan notice"), message, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
app_->collection()->FullScan();
|
||||
}
|
||||
|
@ -3066,10 +3098,10 @@ void MainWindow::HandleNotificationPreview(const OSDBase::Behaviour type, const
|
|||
qLog(Debug) << "The current playlist is empty, showing a fake song";
|
||||
// Create a fake song
|
||||
Song fake(Song::Source::LocalFile);
|
||||
fake.Init("Title", "Artist", "Album", 123);
|
||||
fake.set_genre("Classical");
|
||||
fake.set_composer("Anonymous");
|
||||
fake.set_performer("Anonymous");
|
||||
fake.Init(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123);
|
||||
fake.set_genre(QStringLiteral("Classical"));
|
||||
fake.set_composer(QStringLiteral("Anonymous"));
|
||||
fake.set_performer(QStringLiteral("Anonymous"));
|
||||
fake.set_track(1);
|
||||
fake.set_disc(1);
|
||||
fake.set_year(2011);
|
||||
|
@ -3212,12 +3244,12 @@ void MainWindow::SetToggleScrobblingIcon(const bool value) {
|
|||
|
||||
if (value) {
|
||||
if (app_->playlist_manager()->active() && app_->playlist_manager()->active()->scrobbled())
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load("scrobble", true, 22));
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load(QStringLiteral("scrobble"), true, 22));
|
||||
else
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load("scrobble", true, 22)); // TODO: Create a faint version of the icon
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load(QStringLiteral("scrobble"), true, 22)); // TODO: Create a faint version of the icon
|
||||
}
|
||||
else {
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load("scrobble-disabled", true, 22));
|
||||
ui_->action_toggle_scrobbling->setIcon(IconLoader::Load(QStringLiteral("scrobble-disabled"), true, 22));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3262,7 +3294,7 @@ void MainWindow::PlaylistDelete() {
|
|||
app_->player()->Next();
|
||||
}
|
||||
|
||||
SharedPtr<MusicStorage> storage = make_shared<FilesystemMusicStorage>(Song::Source::LocalFile, "/");
|
||||
SharedPtr<MusicStorage> storage = make_shared<FilesystemMusicStorage>(Song::Source::LocalFile, QStringLiteral("/"));
|
||||
DeleteFiles *delete_files = new DeleteFiles(app_->task_manager(), storage, true);
|
||||
QObject::connect(delete_files, &DeleteFiles::Finished, this, &MainWindow::DeleteFilesFinished);
|
||||
delete_files->Start(selected_songs);
|
||||
|
@ -3294,6 +3326,11 @@ void MainWindow::FocusSearchField() {
|
|||
tidal_view_->FocusSearchField();
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
else if (ui_->tabs->currentIndex() == ui_->tabs->IndexOfTab(spotify_view_) && !spotify_view_->SearchFieldHasFocus()) {
|
||||
spotify_view_->FocusSearchField();
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
else if (ui_->tabs->currentIndex() == ui_->tabs->IndexOfTab(qobuz_view_) && !qobuz_view_->SearchFieldHasFocus()) {
|
||||
qobuz_view_->FocusSearchField();
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "platforminterface.h"
|
||||
#include "song.h"
|
||||
#include "tagreaderclient.h"
|
||||
#include "settings.h"
|
||||
#include "engine/enginebase.h"
|
||||
#include "osd/osdbase.h"
|
||||
#include "playlist/playlist.h"
|
||||
|
@ -293,7 +294,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||
void SetToggleScrobblingIcon(const bool value);
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
void UpdateTaskbarProgress(const bool visible, const double position = 0, const double length = 0);
|
||||
void UpdateTaskbarProgress(const bool visible, const double progress = 0);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -339,9 +340,18 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||
|
||||
SmartPlaylistsViewContainer *smartplaylists_view_;
|
||||
|
||||
#ifdef HAVE_SUBSONIC
|
||||
InternetSongsView *subsonic_view_;
|
||||
#endif
|
||||
#ifdef HAVE_TIDAL
|
||||
InternetTabsView *tidal_view_;
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
InternetTabsView *spotify_view_;
|
||||
#endif
|
||||
#ifdef HAVE_QOBUZ
|
||||
InternetTabsView *qobuz_view_;
|
||||
#endif
|
||||
|
||||
RadioViewContainer *radio_view_;
|
||||
|
||||
|
@ -379,7 +389,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||
|
||||
QTimer *track_position_timer_;
|
||||
QTimer *track_slider_timer_;
|
||||
QSettings settings_;
|
||||
Settings settings_;
|
||||
|
||||
bool keep_running_;
|
||||
bool playing_widget_;
|
||||
|
|
|
@ -424,7 +424,7 @@ QStringList MergedProxyModel::mimeTypes() const {
|
|||
QStringList ret;
|
||||
ret << sourceModel()->mimeTypes();
|
||||
|
||||
QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
const QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
for (const QAbstractItemModel *model : models) {
|
||||
ret << model->mimeTypes();
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ QAbstractItemModel *MergedProxyModel::GetModel(const QModelIndex &source_index)
|
|||
// This is essentially const_cast<QAbstractItemModel*>(source_index.model()), but without the const_cast
|
||||
const QAbstractItemModel *const_model = source_index.model();
|
||||
if (const_model == sourceModel()) return sourceModel();
|
||||
QList<QAbstractItemModel*> submodels = merge_points_.keys();
|
||||
const QList<QAbstractItemModel*> submodels = merge_points_.keys();
|
||||
for (QAbstractItemModel *submodel : submodels) {
|
||||
if (submodel == const_model) return submodel;
|
||||
}
|
||||
|
@ -522,7 +522,7 @@ void MergedProxyModel::DataChanged(const QModelIndex &top_left, const QModelInde
|
|||
void MergedProxyModel::LayoutAboutToBeChanged() {
|
||||
|
||||
old_merge_points_.clear();
|
||||
QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
const QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
for (QAbstractItemModel *model : models) {
|
||||
old_merge_points_[model] = merge_points_.value(model);
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ void MergedProxyModel::LayoutAboutToBeChanged() {
|
|||
|
||||
void MergedProxyModel::LayoutChanged() {
|
||||
|
||||
QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
const QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
for (QAbstractItemModel *model : models) {
|
||||
if (!old_merge_points_.contains(model)) continue;
|
||||
|
||||
|
|
|
@ -94,9 +94,9 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, MaybePlaylist &playlis
|
|||
|
||||
namespace mpris {
|
||||
|
||||
const char *Mpris2::kMprisObjectPath = "/org/mpris/MediaPlayer2";
|
||||
const char *Mpris2::kServiceName = "org.mpris.MediaPlayer2.strawberry";
|
||||
const char *Mpris2::kFreedesktopPath = "org.freedesktop.DBus.Properties";
|
||||
constexpr char kMprisObjectPath[] = "/org/mpris/MediaPlayer2";
|
||||
constexpr char kServiceName[] = "org.mpris.MediaPlayer2.strawberry";
|
||||
constexpr char kFreedesktopPath[] = "org.freedesktop.DBus.Properties";
|
||||
|
||||
Mpris2::Mpris2(Application *app, QObject *parent)
|
||||
: QObject(parent),
|
||||
|
@ -108,13 +108,13 @@ Mpris2::Mpris2(Application *app, QObject *parent)
|
|||
new Mpris2Player(this);
|
||||
new Mpris2Playlists(this);
|
||||
|
||||
if (!QDBusConnection::sessionBus().registerService(kServiceName)) {
|
||||
qLog(Warning) << "Failed to register" << QString(kServiceName) << "on the session bus";
|
||||
if (!QDBusConnection::sessionBus().registerService(QLatin1String(kServiceName))) {
|
||||
qLog(Warning) << "Failed to register" << kServiceName << "on the session bus";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QDBusConnection::sessionBus().registerObject(kMprisObjectPath, this)) {
|
||||
qLog(Warning) << "Failed to register" << QString(kMprisObjectPath) << "on the session bus";
|
||||
if (!QDBusConnection::sessionBus().registerObject(QLatin1String(kMprisObjectPath), this)) {
|
||||
qLog(Warning) << "Failed to register" << kMprisObjectPath << "on the session bus";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -131,18 +131,18 @@ Mpris2::Mpris2(Application *app, QObject *parent)
|
|||
|
||||
app_name_[0] = app_name_[0].toUpper();
|
||||
|
||||
QStringList data_dirs = QString(qgetenv("XDG_DATA_DIRS")).split(":");
|
||||
QStringList data_dirs = QString::fromUtf8(qgetenv("XDG_DATA_DIRS")).split(QLatin1Char(':'));
|
||||
|
||||
if (!data_dirs.contains("/usr/local/share")) {
|
||||
data_dirs.append("/usr/local/share");
|
||||
if (!data_dirs.contains(QStringLiteral("/usr/local/share"))) {
|
||||
data_dirs.append(QStringLiteral("/usr/local/share"));
|
||||
}
|
||||
|
||||
if (!data_dirs.contains("/usr/share")) {
|
||||
data_dirs.append("/usr/share");
|
||||
if (!data_dirs.contains(QStringLiteral("/usr/share"))) {
|
||||
data_dirs.append(QStringLiteral("/usr/share"));
|
||||
}
|
||||
|
||||
for (const QString &data_dir : data_dirs) {
|
||||
const QString desktopfilepath = QString("%1/applications/%2.desktop").arg(data_dir, QGuiApplication::desktopFileName());
|
||||
const QString desktopfilepath = QStringLiteral("%1/applications/%2.desktop").arg(data_dir, QGuiApplication::desktopFileName());
|
||||
if (QFile::exists(desktopfilepath)) {
|
||||
desktopfilepath_ = desktopfilepath;
|
||||
break;
|
||||
|
@ -150,7 +150,7 @@ Mpris2::Mpris2(Application *app, QObject *parent)
|
|||
}
|
||||
|
||||
if (desktopfilepath_.isEmpty()) {
|
||||
desktopfilepath_ = QGuiApplication::desktopFileName() + ".desktop";
|
||||
desktopfilepath_ = QGuiApplication::desktopFileName() + QStringLiteral(".desktop");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -165,37 +165,37 @@ void Mpris2::EngineStateChanged(EngineBase::State newState) {
|
|||
|
||||
if (newState != EngineBase::State::Playing && newState != EngineBase::State::Paused) {
|
||||
last_metadata_ = QVariantMap();
|
||||
EmitNotification("Metadata");
|
||||
EmitNotification(QStringLiteral("Metadata"));
|
||||
}
|
||||
|
||||
EmitNotification("CanPlay");
|
||||
EmitNotification("CanPause");
|
||||
EmitNotification("PlaybackStatus", PlaybackStatus(newState));
|
||||
if (newState == EngineBase::State::Playing) EmitNotification("CanSeek", CanSeek(newState));
|
||||
EmitNotification(QStringLiteral("CanPlay"));
|
||||
EmitNotification(QStringLiteral("CanPause"));
|
||||
EmitNotification(QStringLiteral("PlaybackStatus"), PlaybackStatus(newState));
|
||||
if (newState == EngineBase::State::Playing) EmitNotification(QStringLiteral("CanSeek"), CanSeek(newState));
|
||||
|
||||
}
|
||||
|
||||
void Mpris2::VolumeChanged() {
|
||||
EmitNotification("Volume");
|
||||
EmitNotification(QStringLiteral("Volume"));
|
||||
}
|
||||
|
||||
void Mpris2::ShuffleModeChanged() { EmitNotification("Shuffle"); }
|
||||
void Mpris2::ShuffleModeChanged() { EmitNotification(QStringLiteral("Shuffle")); }
|
||||
|
||||
void Mpris2::RepeatModeChanged() {
|
||||
|
||||
EmitNotification("LoopStatus");
|
||||
EmitNotification("CanGoNext", CanGoNext());
|
||||
EmitNotification("CanGoPrevious", CanGoPrevious());
|
||||
EmitNotification(QStringLiteral("LoopStatus"));
|
||||
EmitNotification(QStringLiteral("CanGoNext"), CanGoNext());
|
||||
EmitNotification(QStringLiteral("CanGoPrevious"), CanGoPrevious());
|
||||
|
||||
}
|
||||
|
||||
void Mpris2::EmitNotification(const QString &name, const QVariant &value) {
|
||||
EmitNotification(name, value, "org.mpris.MediaPlayer2.Player");
|
||||
EmitNotification(name, value, QStringLiteral("org.mpris.MediaPlayer2.Player"));
|
||||
}
|
||||
|
||||
void Mpris2::EmitNotification(const QString &name, const QVariant &value, const QString &mprisEntity) {
|
||||
|
||||
QDBusMessage msg = QDBusMessage::createSignal(kMprisObjectPath, kFreedesktopPath, "PropertiesChanged");
|
||||
QDBusMessage msg = QDBusMessage::createSignal(QLatin1String(kMprisObjectPath), QLatin1String(kFreedesktopPath), QStringLiteral("PropertiesChanged"));
|
||||
QVariantMap map;
|
||||
map.insert(name, value);
|
||||
QVariantList args = QVariantList() << mprisEntity << map << QStringList();
|
||||
|
@ -207,18 +207,18 @@ void Mpris2::EmitNotification(const QString &name, const QVariant &value, const
|
|||
void Mpris2::EmitNotification(const QString &name) {
|
||||
|
||||
QVariant value;
|
||||
if (name == "PlaybackStatus") value = PlaybackStatus();
|
||||
else if (name == "LoopStatus") value = LoopStatus();
|
||||
else if (name == "Shuffle") value = Shuffle();
|
||||
else if (name == "Metadata") value = Metadata();
|
||||
else if (name == "Rating") value = Rating();
|
||||
else if (name == "Volume") value = Volume();
|
||||
else if (name == "Position") value = Position();
|
||||
else if (name == "CanPlay") value = CanPlay();
|
||||
else if (name == "CanPause") value = CanPause();
|
||||
else if (name == "CanSeek") value = CanSeek();
|
||||
else if (name == "CanGoNext") value = CanGoNext();
|
||||
else if (name == "CanGoPrevious") value = CanGoPrevious();
|
||||
if (name == QStringLiteral("PlaybackStatus")) value = PlaybackStatus();
|
||||
else if (name == QStringLiteral("LoopStatus")) value = LoopStatus();
|
||||
else if (name == QStringLiteral("Shuffle")) value = Shuffle();
|
||||
else if (name == QStringLiteral("Metadata")) value = Metadata();
|
||||
else if (name == QStringLiteral("Rating")) value = Rating();
|
||||
else if (name == QStringLiteral("Volume")) value = Volume();
|
||||
else if (name == QStringLiteral("Position")) value = Position();
|
||||
else if (name == QStringLiteral("CanPlay")) value = CanPlay();
|
||||
else if (name == QStringLiteral("CanPause")) value = CanPause();
|
||||
else if (name == QStringLiteral("CanSeek")) value = CanSeek();
|
||||
else if (name == QStringLiteral("CanGoNext")) value = CanGoNext();
|
||||
else if (name == QStringLiteral("CanGoPrevious")) value = CanGoPrevious();
|
||||
|
||||
if (value.isValid()) EmitNotification(name, value);
|
||||
|
||||
|
@ -240,49 +240,49 @@ QString Mpris2::DesktopEntryAbsolutePath() const {
|
|||
|
||||
}
|
||||
|
||||
QString Mpris2::DesktopEntry() const { return QGuiApplication::desktopFileName() + ".desktop"; }
|
||||
QString Mpris2::DesktopEntry() const { return QGuiApplication::desktopFileName() + QStringLiteral(".desktop"); }
|
||||
|
||||
QStringList Mpris2::SupportedUriSchemes() const {
|
||||
|
||||
static QStringList res = QStringList() << "file"
|
||||
<< "http"
|
||||
<< "cdda"
|
||||
<< "smb"
|
||||
<< "sftp";
|
||||
static QStringList res = QStringList() << QStringLiteral("file")
|
||||
<< QStringLiteral("http")
|
||||
<< QStringLiteral("cdda")
|
||||
<< QStringLiteral("smb")
|
||||
<< QStringLiteral("sftp");
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
QStringList Mpris2::SupportedMimeTypes() const {
|
||||
|
||||
static QStringList res = QStringList() << "x-content/audio-player"
|
||||
<< "application/ogg"
|
||||
<< "application/x-ogg"
|
||||
<< "application/x-ogm-audio"
|
||||
<< "audio/flac"
|
||||
<< "audio/ogg"
|
||||
<< "audio/vorbis"
|
||||
<< "audio/aac"
|
||||
<< "audio/mp4"
|
||||
<< "audio/mpeg"
|
||||
<< "audio/mpegurl"
|
||||
<< "audio/vnd.rn-realaudio"
|
||||
<< "audio/x-flac"
|
||||
<< "audio/x-oggflac"
|
||||
<< "audio/x-vorbis"
|
||||
<< "audio/x-vorbis+ogg"
|
||||
<< "audio/x-speex"
|
||||
<< "audio/x-wav"
|
||||
<< "audio/x-wavpack"
|
||||
<< "audio/x-ape"
|
||||
<< "audio/x-mp3"
|
||||
<< "audio/x-mpeg"
|
||||
<< "audio/x-mpegurl"
|
||||
<< "audio/x-ms-wma"
|
||||
<< "audio/x-musepack"
|
||||
<< "audio/x-pn-realaudio"
|
||||
<< "audio/x-scpls"
|
||||
<< "video/x-ms-asf";
|
||||
static QStringList res = QStringList() << QStringLiteral("x-content/audio-player")
|
||||
<< QStringLiteral("application/ogg")
|
||||
<< QStringLiteral("application/x-ogg")
|
||||
<< QStringLiteral("application/x-ogm-audio")
|
||||
<< QStringLiteral("audio/flac")
|
||||
<< QStringLiteral("audio/ogg")
|
||||
<< QStringLiteral("audio/vorbis")
|
||||
<< QStringLiteral("audio/aac")
|
||||
<< QStringLiteral("audio/mp4")
|
||||
<< QStringLiteral("audio/mpeg")
|
||||
<< QStringLiteral("audio/mpegurl")
|
||||
<< QStringLiteral("audio/vnd.rn-realaudio")
|
||||
<< QStringLiteral("audio/x-flac")
|
||||
<< QStringLiteral("audio/x-oggflac")
|
||||
<< QStringLiteral("audio/x-vorbis")
|
||||
<< QStringLiteral("audio/x-vorbis+ogg")
|
||||
<< QStringLiteral("audio/x-speex")
|
||||
<< QStringLiteral("audio/x-wav")
|
||||
<< QStringLiteral("audio/x-wavpack")
|
||||
<< QStringLiteral("audio/x-ape")
|
||||
<< QStringLiteral("audio/x-mp3")
|
||||
<< QStringLiteral("audio/x-mpeg")
|
||||
<< QStringLiteral("audio/x-mpegurl")
|
||||
<< QStringLiteral("audio/x-ms-wma")
|
||||
<< QStringLiteral("audio/x-musepack")
|
||||
<< QStringLiteral("audio/x-pn-realaudio")
|
||||
<< QStringLiteral("audio/x-scpls")
|
||||
<< QStringLiteral("video/x-ms-asf");
|
||||
|
||||
return res;
|
||||
|
||||
|
@ -299,9 +299,9 @@ QString Mpris2::PlaybackStatus() const {
|
|||
QString Mpris2::PlaybackStatus(EngineBase::State state) const {
|
||||
|
||||
switch (state) {
|
||||
case EngineBase::State::Playing: return "Playing";
|
||||
case EngineBase::State::Paused: return "Paused";
|
||||
default: return "Stopped";
|
||||
case EngineBase::State::Playing: return QStringLiteral("Playing");
|
||||
case EngineBase::State::Paused: return QStringLiteral("Paused");
|
||||
default: return QStringLiteral("Stopped");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -309,14 +309,14 @@ QString Mpris2::PlaybackStatus(EngineBase::State state) const {
|
|||
QString Mpris2::LoopStatus() const {
|
||||
|
||||
if (!app_->playlist_manager()->sequence()) {
|
||||
return "None";
|
||||
return QStringLiteral("None");
|
||||
}
|
||||
|
||||
switch (app_->playlist_manager()->active() ? app_->playlist_manager()->active()->RepeatMode() : app_->playlist_manager()->sequence()->repeat_mode()) {
|
||||
case PlaylistSequence::RepeatMode::Album:
|
||||
case PlaylistSequence::RepeatMode::Playlist: return "Playlist";
|
||||
case PlaylistSequence::RepeatMode::Track: return "Track";
|
||||
default: return "None";
|
||||
case PlaylistSequence::RepeatMode::Playlist: return QStringLiteral("Playlist");
|
||||
case PlaylistSequence::RepeatMode::Track: return QStringLiteral("Track");
|
||||
default: return QStringLiteral("None");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -325,13 +325,13 @@ void Mpris2::SetLoopStatus(const QString &value) {
|
|||
|
||||
PlaylistSequence::RepeatMode mode = PlaylistSequence::RepeatMode::Off;
|
||||
|
||||
if (value == "None") {
|
||||
if (value == QStringLiteral("None")) {
|
||||
mode = PlaylistSequence::RepeatMode::Off;
|
||||
}
|
||||
else if (value == "Track") {
|
||||
else if (value == QStringLiteral("Track")) {
|
||||
mode = PlaylistSequence::RepeatMode::Track;
|
||||
}
|
||||
else if (value == "Playlist") {
|
||||
else if (value == QStringLiteral("Playlist")) {
|
||||
mode = PlaylistSequence::RepeatMode::Playlist;
|
||||
}
|
||||
|
||||
|
@ -381,18 +381,18 @@ void Mpris2::SetRating(double rating) {
|
|||
}
|
||||
|
||||
QDBusObjectPath Mpris2::current_track_id() const {
|
||||
return QDBusObjectPath(QString("/org/strawberrymusicplayer/strawberry/Track/%1").arg(QString::number(app_->playlist_manager()->active()->current_row())));
|
||||
return QDBusObjectPath(QStringLiteral("/org/strawberrymusicplayer/strawberry/Track/%1").arg(QString::number(app_->playlist_manager()->active()->current_row())));
|
||||
}
|
||||
|
||||
// We send Metadata change notification as soon as the process of changing song starts...
|
||||
void Mpris2::CurrentSongChanged(const Song &song) {
|
||||
|
||||
AlbumCoverLoaded(song);
|
||||
EmitNotification("CanPlay");
|
||||
EmitNotification("CanPause");
|
||||
EmitNotification("CanGoNext", CanGoNext());
|
||||
EmitNotification("CanGoPrevious", CanGoPrevious());
|
||||
EmitNotification("CanSeek", CanSeek());
|
||||
EmitNotification(QStringLiteral("CanPlay"));
|
||||
EmitNotification(QStringLiteral("CanPause"));
|
||||
EmitNotification(QStringLiteral("CanGoNext"), CanGoNext());
|
||||
EmitNotification(QStringLiteral("CanGoPrevious"), CanGoPrevious());
|
||||
EmitNotification(QStringLiteral("CanSeek"), CanSeek());
|
||||
|
||||
}
|
||||
|
||||
|
@ -403,7 +403,7 @@ void Mpris2::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &re
|
|||
song.ToXesam(&last_metadata_);
|
||||
|
||||
using mpris::AddMetadata;
|
||||
AddMetadata("mpris:trackid", current_track_id(), &last_metadata_);
|
||||
AddMetadata(QStringLiteral("mpris:trackid"), current_track_id(), &last_metadata_);
|
||||
|
||||
QUrl cover_url;
|
||||
if (result.album_cover.cover_url.isValid() && result.album_cover.cover_url.isLocalFile() && QFile(result.album_cover.cover_url.toLocalFile()).exists()) {
|
||||
|
@ -420,13 +420,13 @@ void Mpris2::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &re
|
|||
}
|
||||
|
||||
if (cover_url.isValid()) {
|
||||
AddMetadata("mpris:artUrl", cover_url.toString(), &last_metadata_);
|
||||
AddMetadata(QStringLiteral("mpris:artUrl"), cover_url.toString(), &last_metadata_);
|
||||
}
|
||||
|
||||
AddMetadata("year", song.year(), &last_metadata_);
|
||||
AddMetadata("bitrate", song.bitrate(), &last_metadata_);
|
||||
AddMetadata(QStringLiteral("year"), song.year(), &last_metadata_);
|
||||
AddMetadata(QStringLiteral("bitrate"), song.bitrate(), &last_metadata_);
|
||||
|
||||
EmitNotification("Metadata", last_metadata_);
|
||||
EmitNotification(QStringLiteral("Metadata"), last_metadata_);
|
||||
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,7 @@ bool Mpris2::CanPlay() const {
|
|||
|
||||
// This one's a bit different than MPRIS 1 - we want this to be true even when the song is already paused or stopped.
|
||||
bool Mpris2::CanPause() const {
|
||||
return (app_->player()->GetCurrentItem() && app_->player()->GetState() == EngineBase::State::Playing && !(app_->player()->GetCurrentItem()->options() & PlaylistItem::Option::PauseDisabled)) || PlaybackStatus() == "Paused" || PlaybackStatus() == "Stopped";
|
||||
return (app_->player()->GetCurrentItem() && app_->player()->GetState() == EngineBase::State::Playing && !(app_->player()->GetCurrentItem()->options() & PlaylistItem::Option::PauseDisabled)) || PlaybackStatus() == QStringLiteral("Paused") || PlaybackStatus() == QStringLiteral("Stopped");
|
||||
}
|
||||
|
||||
bool Mpris2::CanSeek() const { return CanSeek(app_->player()->GetState()); }
|
||||
|
@ -567,12 +567,12 @@ quint32 Mpris2::PlaylistCount() const {
|
|||
return app_->playlist_manager()->GetAllPlaylists().size();
|
||||
}
|
||||
|
||||
QStringList Mpris2::Orderings() const { return QStringList() << "User"; }
|
||||
QStringList Mpris2::Orderings() const { return QStringList() << QStringLiteral("User"); }
|
||||
|
||||
namespace {
|
||||
|
||||
QDBusObjectPath MakePlaylistPath(int id) {
|
||||
return QDBusObjectPath(QString("/org/strawberrymusicplayer/strawberry/PlaylistId/%1").arg(id));
|
||||
return QDBusObjectPath(QStringLiteral("/org/strawberrymusicplayer/strawberry/PlaylistId/%1").arg(id));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -594,7 +594,7 @@ MaybePlaylist Mpris2::ActivePlaylist() const {
|
|||
|
||||
void Mpris2::ActivatePlaylist(const QDBusObjectPath &playlist_id) {
|
||||
|
||||
QStringList split_path = playlist_id.path().split('/');
|
||||
QStringList split_path = playlist_id.path().split(QLatin1Char('/'));
|
||||
qLog(Debug) << Q_FUNC_INFO << playlist_id.path() << split_path;
|
||||
if (split_path.isEmpty()) {
|
||||
return;
|
||||
|
@ -648,7 +648,7 @@ void Mpris2::PlaylistChangedSlot(Playlist *playlist) {
|
|||
|
||||
void Mpris2::PlaylistCollectionChanged(Playlist *playlist) {
|
||||
Q_UNUSED(playlist);
|
||||
EmitNotification("PlaylistCount", "", "org.mpris.MediaPlayer2.Playlists");
|
||||
EmitNotification(QStringLiteral("PlaylistCount"), QLatin1String(""), QStringLiteral("org.mpris.MediaPlayer2.Playlists"));
|
||||
}
|
||||
|
||||
} // namespace mpris
|
||||
|
|
|
@ -232,10 +232,6 @@ class Mpris2 : public QObject {
|
|||
QString DesktopEntryAbsolutePath() const;
|
||||
|
||||
private:
|
||||
static const char *kMprisObjectPath;
|
||||
static const char *kServiceName;
|
||||
static const char *kFreedesktopPath;
|
||||
|
||||
Application *app_;
|
||||
|
||||
QString app_name_;
|
||||
|
|
|
@ -61,7 +61,7 @@ inline void AddMetadata(const QString &key, const QDBusObjectPath &metadata, QVa
|
|||
}
|
||||
|
||||
inline QString AsMPRISDateTimeType(const qint64 time) {
|
||||
return time != -1 ? QDateTime::fromSecsSinceEpoch(time).toString(Qt::ISODate) : "";
|
||||
return time != -1 ? QDateTime::fromSecsSinceEpoch(time).toString(Qt::ISODate) : QLatin1String("");
|
||||
}
|
||||
|
||||
} // namespace mpris
|
||||
|
|
|
@ -49,7 +49,7 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR
|
|||
user_agent = request.header(QNetworkRequest::UserAgentHeader).toByteArray();
|
||||
}
|
||||
else {
|
||||
user_agent = QString("%1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion()).toUtf8();
|
||||
user_agent = QStringLiteral("%1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion()).toUtf8();
|
||||
}
|
||||
|
||||
QNetworkRequest new_request(request);
|
||||
|
@ -57,7 +57,7 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR
|
|||
new_request.setHeader(QNetworkRequest::UserAgentHeader, user_agent);
|
||||
|
||||
if (op == QNetworkAccessManager::PostOperation && !new_request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
|
||||
new_request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
new_request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
|
||||
}
|
||||
|
||||
// Prefer the cache unless the caller has changed the setting already
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/settings.h"
|
||||
#include "networkproxyfactory.h"
|
||||
|
||||
NetworkProxyFactory *NetworkProxyFactory::sInstance = nullptr;
|
||||
|
@ -43,11 +44,10 @@ NetworkProxyFactory::NetworkProxyFactory()
|
|||
#ifdef Q_OS_LINUX
|
||||
// Linux uses environment variables to pass proxy configuration information, which systemProxyForQuery doesn't support for some reason.
|
||||
|
||||
QStringList urls;
|
||||
urls << QString::fromLocal8Bit(qgetenv("HTTP_PROXY"));
|
||||
urls << QString::fromLocal8Bit(qgetenv("http_proxy"));
|
||||
urls << QString::fromLocal8Bit(qgetenv("ALL_PROXY"));
|
||||
urls << QString::fromLocal8Bit(qgetenv("all_proxy"));
|
||||
const QStringList urls = QStringList() << QString::fromLocal8Bit(qgetenv("HTTP_PROXY"))
|
||||
<< QString::fromLocal8Bit(qgetenv("http_proxy"))
|
||||
<< QString::fromLocal8Bit(qgetenv("ALL_PROXY"))
|
||||
<< QString::fromLocal8Bit(qgetenv("all_proxy"));
|
||||
|
||||
qLog(Debug) << "Detected system proxy URLs:" << urls;
|
||||
|
||||
|
@ -78,7 +78,7 @@ void NetworkProxyFactory::ReloadSettings() {
|
|||
|
||||
QMutexLocker l(&mutex_);
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
mode_ = static_cast<Mode>(s.value("mode", static_cast<int>(Mode::System)).toInt());
|
||||
|
@ -112,7 +112,7 @@ QList<QNetworkProxy> NetworkProxyFactory::queryProxy(const QNetworkProxyQuery &q
|
|||
ret.setPort(env_url_.port());
|
||||
ret.setUser(env_url_.userName());
|
||||
ret.setPassword(env_url_.password());
|
||||
if (env_url_.scheme().startsWith("http")) {
|
||||
if (env_url_.scheme().startsWith(QLatin1String("http"))) {
|
||||
ret.setType(QNetworkProxy::HttpProxy);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/timeconstants.h"
|
||||
|
||||
#include "scoped_ptr.h"
|
||||
|
@ -67,6 +69,8 @@
|
|||
#include "settings/behavioursettingspage.h"
|
||||
#include "settings/playlistsettingspage.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
using std::make_shared;
|
||||
|
||||
const char *Player::kSettingsGroup = "Player";
|
||||
|
@ -94,7 +98,7 @@ Player::Player(Application *app, QObject *parent)
|
|||
seek_step_sec_(10),
|
||||
play_offset_nanosec_(0) {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
EngineBase::Type enginetype = EngineBase::TypeFromName(s.value("engine", EngineBase::Name(EngineBase::Type::GStreamer)).toString().toLower());
|
||||
s.endGroup();
|
||||
|
@ -102,7 +106,7 @@ Player::Player(Application *app, QObject *parent)
|
|||
CreateEngine(enginetype);
|
||||
|
||||
timer_save_volume_->setSingleShot(true);
|
||||
timer_save_volume_->setInterval(5000);
|
||||
timer_save_volume_->setInterval(5s);
|
||||
QObject::connect(timer_save_volume_, &QTimer::timeout, this, &Player::SaveVolume);
|
||||
|
||||
}
|
||||
|
@ -139,7 +143,7 @@ EngineBase::Type Player::CreateEngine(EngineBase::Type enginetype) {
|
|||
}
|
||||
|
||||
if (use_enginetype != enginetype) { // Engine was set to something else. Reset output and device.
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
s.setValue("engine", EngineBase::Name(use_enginetype));
|
||||
s.setValue("output", engine_->DefaultOutput());
|
||||
|
@ -159,7 +163,7 @@ EngineBase::Type Player::CreateEngine(EngineBase::Type enginetype) {
|
|||
|
||||
void Player::Init() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
|
||||
if (!engine_) {
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
|
@ -203,7 +207,7 @@ void Player::Init() {
|
|||
|
||||
void Player::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
|
||||
s.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
||||
continue_on_error_ = s.value("continue_on_error", false).toBool();
|
||||
|
@ -221,7 +225,7 @@ void Player::ReloadSettings() {
|
|||
|
||||
void Player::LoadVolume() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
const uint volume = s.value("volume", 100).toInt();
|
||||
s.endGroup();
|
||||
|
@ -232,7 +236,7 @@ void Player::LoadVolume() {
|
|||
|
||||
void Player::SaveVolume() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("volume", volume_);
|
||||
s.endGroup();
|
||||
|
@ -283,7 +287,7 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
|||
if (is_current) NextItem(stream_change_type_, autoscroll_);
|
||||
break;
|
||||
|
||||
case UrlHandler::LoadResult::Type::TrackAvailable: {
|
||||
case UrlHandler::LoadResult::Type::TrackAvailable:{
|
||||
|
||||
qLog(Debug) << "URL handler for" << result.media_url_ << "returned" << result.stream_url_;
|
||||
|
||||
|
@ -433,7 +437,8 @@ void Player::PlayPlaylistInternal(const EngineBase::TrackChangeFlags change, con
|
|||
play_offset_nanosec_ = 0;
|
||||
|
||||
Playlist *playlist = nullptr;
|
||||
for (Playlist *p : app_->playlist_manager()->GetAllPlaylists()) {
|
||||
const QList<Playlist*> playlists = app_->playlist_manager()->GetAllPlaylists();
|
||||
for (Playlist *p : playlists) {
|
||||
if (playlist_name == app_->playlist_manager()->GetPlaylistName(p->id())) {
|
||||
playlist = p;
|
||||
break;
|
||||
|
@ -497,7 +502,7 @@ void Player::PlayPause(const quint64 offset_nanosec, const Playlist::AutoScroll
|
|||
emit Resumed();
|
||||
break;
|
||||
|
||||
case EngineBase::State::Playing: {
|
||||
case EngineBase::State::Playing:{
|
||||
if (current_item_->options() & PlaylistItem::Option::PauseDisabled) {
|
||||
Stop();
|
||||
}
|
||||
|
@ -511,7 +516,7 @@ void Player::PlayPause(const quint64 offset_nanosec, const Playlist::AutoScroll
|
|||
|
||||
case EngineBase::State::Empty:
|
||||
case EngineBase::State::Error:
|
||||
case EngineBase::State::Idle: {
|
||||
case EngineBase::State::Idle:{
|
||||
pause_time_ = QDateTime();
|
||||
play_offset_nanosec_ = offset_nanosec;
|
||||
app_->playlist_manager()->SetActivePlaylist(app_->playlist_manager()->current_id());
|
||||
|
@ -531,7 +536,7 @@ void Player::UnPause() {
|
|||
if (current_item_ && pause_time_.isValid()) {
|
||||
const Song &song = current_item_->Metadata();
|
||||
if (url_handlers_.contains(song.url().scheme()) && song.stream_url_can_expire()) {
|
||||
const quint64 time = QDateTime::currentDateTime().toSecsSinceEpoch() - pause_time_.toSecsSinceEpoch();
|
||||
const quint64 time = QDateTime::currentSecsSinceEpoch() - pause_time_.toSecsSinceEpoch();
|
||||
if (time >= 30) { // Stream URL might be expired.
|
||||
qLog(Debug) << "Re-requesting stream URL for" << song.url();
|
||||
play_offset_nanosec_ = engine_->position_nanosec();
|
||||
|
|
|
@ -38,8 +38,8 @@ SystemTrayIcon::SystemTrayIcon(QObject *parent)
|
|||
: QSystemTrayIcon(parent),
|
||||
menu_(new QMenu),
|
||||
app_name_(QCoreApplication::applicationName()),
|
||||
pixmap_playing_(":/pictures/tiny-play.png"),
|
||||
pixmap_paused_(":/pictures/tiny-pause.png"),
|
||||
pixmap_playing_(QStringLiteral(":/pictures/tiny-play.png")),
|
||||
pixmap_paused_(QStringLiteral(":/pictures/tiny-pause.png")),
|
||||
action_play_pause_(nullptr),
|
||||
action_stop_(nullptr),
|
||||
action_stop_after_this_track_(nullptr),
|
||||
|
@ -51,8 +51,8 @@ SystemTrayIcon::SystemTrayIcon(QObject *parent)
|
|||
|
||||
app_name_[0] = app_name_[0].toUpper();
|
||||
|
||||
const QIcon icon = IconLoader::Load("strawberry");
|
||||
const QIcon icon_grey = IconLoader::Load("strawberry-grey");
|
||||
const QIcon icon = IconLoader::Load(QStringLiteral("strawberry"));
|
||||
const QIcon icon_grey = IconLoader::Load(QStringLiteral("strawberry-grey"));
|
||||
pixmap_normal_ = icon.pixmap(48, QIcon::Normal);
|
||||
if (icon_grey.isNull()) {
|
||||
pixmap_grey_ = icon.pixmap(48, QIcon::Disabled);
|
||||
|
@ -143,7 +143,7 @@ void SystemTrayIcon::SetPlaying(bool enable_play_pause) {
|
|||
|
||||
action_stop_->setEnabled(true);
|
||||
action_stop_after_this_track_->setEnabled(true);
|
||||
action_play_pause_->setIcon(IconLoader::Load("media-playback-pause"));
|
||||
action_play_pause_->setIcon(IconLoader::Load(QStringLiteral("media-playback-pause")));
|
||||
action_play_pause_->setText(tr("Pause"));
|
||||
action_play_pause_->setEnabled(enable_play_pause);
|
||||
|
||||
|
@ -156,7 +156,7 @@ void SystemTrayIcon::SetPaused() {
|
|||
|
||||
action_stop_->setEnabled(true);
|
||||
action_stop_after_this_track_->setEnabled(true);
|
||||
action_play_pause_->setIcon(IconLoader::Load("media-playback-start"));
|
||||
action_play_pause_->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
action_play_pause_->setText(tr("Play"));
|
||||
|
||||
action_play_pause_->setEnabled(true);
|
||||
|
@ -170,7 +170,7 @@ void SystemTrayIcon::SetStopped() {
|
|||
|
||||
action_stop_->setEnabled(false);
|
||||
action_stop_after_this_track_->setEnabled(false);
|
||||
action_play_pause_->setIcon(IconLoader::Load("media-playback-start"));
|
||||
action_play_pause_->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
action_play_pause_->setText(tr("Play"));
|
||||
|
||||
action_play_pause_->setEnabled(true);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QSettings>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
Settings::Settings(QObject *parent)
|
||||
: QSettings(parent) {}
|
||||
|
||||
Settings::Settings(const QString &filename, const Format format, QObject *parent)
|
||||
: QSettings(filename, format, parent) {}
|
||||
|
||||
// Compatibility with older Qt versions
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
|
||||
|
||||
void Settings::beginGroup(const char *prefix) {
|
||||
|
||||
QSettings::beginGroup(QLatin1String(prefix));
|
||||
|
||||
}
|
||||
|
||||
void Settings::beginGroup(const QString &prefix) {
|
||||
|
||||
QSettings::beginGroup(prefix);
|
||||
|
||||
}
|
||||
|
||||
bool Settings::contains(const char *key) const {
|
||||
|
||||
return QSettings::contains(QLatin1String(key));
|
||||
|
||||
}
|
||||
|
||||
bool Settings::contains(const QString &key) const {
|
||||
|
||||
return QSettings::contains(key);
|
||||
|
||||
}
|
||||
|
||||
QVariant Settings::value(const char *key, const QVariant &default_value) const {
|
||||
|
||||
return QSettings::value(QLatin1String(key), default_value);
|
||||
|
||||
}
|
||||
|
||||
QVariant Settings::value(const QString &key, const QVariant &default_value) const {
|
||||
|
||||
return QSettings::value(key, default_value);
|
||||
|
||||
}
|
||||
|
||||
void Settings::setValue(const char *key, const QVariant &value) {
|
||||
|
||||
QSettings::setValue(QLatin1String(key), value);
|
||||
|
||||
}
|
||||
|
||||
void Settings::setValue(const QString &key, const QVariant &value) {
|
||||
|
||||
QSettings::setValue(key, value);
|
||||
|
||||
}
|
||||
|
||||
int Settings::beginReadArray(const char *prefix) {
|
||||
|
||||
return QSettings::beginReadArray(QLatin1String(prefix));
|
||||
|
||||
}
|
||||
|
||||
int Settings::beginReadArray(const QString &prefix) {
|
||||
|
||||
return QSettings::beginReadArray(prefix);
|
||||
|
||||
}
|
||||
|
||||
void Settings::beginWriteArray(const char *prefix, int size) {
|
||||
|
||||
QSettings::beginWriteArray(QLatin1String(prefix), size);
|
||||
|
||||
}
|
||||
|
||||
void Settings::beginWriteArray(const QString &prefix, int size) {
|
||||
|
||||
QSettings::beginWriteArray(prefix, size);
|
||||
|
||||
}
|
||||
|
||||
void Settings::remove(const char *key) {
|
||||
|
||||
QSettings::remove(QLatin1String(key));
|
||||
|
||||
}
|
||||
|
||||
void Settings::remove(const QString &key) {
|
||||
|
||||
QSettings::remove(key);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <QSettings>
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
class Settings : public QSettings {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Settings(QObject *parent = nullptr);
|
||||
explicit Settings(const QString &filename, const Format format, QObject *parent = nullptr);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) // Compatibility with older Qt versions
|
||||
void beginGroup(const char *prefix);
|
||||
void beginGroup(const QString &prefix);
|
||||
bool contains(const char *key) const;
|
||||
bool contains(const QString &key) const;
|
||||
QVariant value(const char *key, const QVariant &default_value = QVariant()) const;
|
||||
QVariant value(const QString &key, const QVariant &default_value = QVariant()) const;
|
||||
void setValue(const char *key, const QVariant &value);
|
||||
void setValue(const QString &key, const QVariant &value);
|
||||
int beginReadArray(const char *prefix);
|
||||
int beginReadArray(const QString &prefix);
|
||||
void beginWriteArray(const char *prefix, int size = -1);
|
||||
void beginWriteArray(const QString &prefix, int size = -1);
|
||||
void remove(const char *key);
|
||||
void remove(const QString &key);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SETTINGS_H
|
|
@ -30,7 +30,7 @@ DefaultSettingsProvider::DefaultSettingsProvider() = default;
|
|||
void DefaultSettingsProvider::set_group(const char *group) {
|
||||
while (!backend_.group().isEmpty()) backend_.endGroup();
|
||||
|
||||
backend_.beginGroup(group);
|
||||
backend_.beginGroup(QLatin1String(group));
|
||||
}
|
||||
|
||||
QVariant DefaultSettingsProvider::value(const QString &key, const QVariant &default_value) const {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -42,6 +42,7 @@
|
|||
#include <QIcon>
|
||||
|
||||
class SqlQuery;
|
||||
class QSqlRecord;
|
||||
|
||||
class EngineMetadata;
|
||||
|
||||
|
@ -76,7 +77,8 @@ class Song {
|
|||
Subsonic = 7,
|
||||
Qobuz = 8,
|
||||
SomaFM = 9,
|
||||
RadioParadise = 10
|
||||
RadioParadise = 10,
|
||||
Spotify = 11
|
||||
};
|
||||
|
||||
// Don't change these values - they're stored in the database, and defined in the tag reader protobuf.
|
||||
|
@ -112,7 +114,9 @@ class Song {
|
|||
};
|
||||
|
||||
static const QStringList kColumns;
|
||||
static const QStringList kRowIdColumns;
|
||||
static const QString kColumnSpec;
|
||||
static const QString kRowIdColumnSpec;
|
||||
static const QString kBindSpec;
|
||||
static const QString kUpdateSpec;
|
||||
|
||||
|
@ -350,6 +354,7 @@ class Song {
|
|||
static bool save_embedded_cover_supported(const FileType filetype);
|
||||
bool save_embedded_cover_supported() const { return url().isLocalFile() && save_embedded_cover_supported(filetype()) && !has_cue(); };
|
||||
|
||||
static int ColumnIndex(const QString &field);
|
||||
static QString JoinSpec(const QString &table);
|
||||
|
||||
// Pretty accessors
|
||||
|
@ -416,7 +421,9 @@ class Song {
|
|||
void Init(const QString &title, const QString &artist, const QString &album, const qint64 length_nanosec);
|
||||
void Init(const QString &title, const QString &artist, const QString &album, const qint64 beginning, const qint64 end);
|
||||
void InitFromProtobuf(const spb::tagreader::SongMetadata &pb);
|
||||
void InitFromQuery(const SqlRow &query, const bool reliable_metadata);
|
||||
void InitFromQuery(const QSqlRecord &r, const bool reliable_metadata, const int col = 0);
|
||||
void InitFromQuery(const SqlQuery &query, const bool reliable_metadata, const int col = 0);
|
||||
void InitFromQuery(const SqlRow &row, const bool reliable_metadata, const int col = 0);
|
||||
void InitFromFilePartial(const QString &filename, const QFileInfo &fileinfo);
|
||||
void InitArtManual();
|
||||
void InitArtAutomatic();
|
||||
|
|
|
@ -82,15 +82,15 @@ SongLoader::SongLoader(SharedPtr<CollectionBackendInterface> collection_backend,
|
|||
success_(false) {
|
||||
|
||||
if (sRawUriSchemes.isEmpty()) {
|
||||
sRawUriSchemes << "udp"
|
||||
<< "mms"
|
||||
<< "mmsh"
|
||||
<< "mmst"
|
||||
<< "mmsu"
|
||||
<< "rtsp"
|
||||
<< "rtspu"
|
||||
<< "rtspt"
|
||||
<< "rtsph";
|
||||
sRawUriSchemes << QStringLiteral("udp")
|
||||
<< QStringLiteral("mms")
|
||||
<< QStringLiteral("mmsh")
|
||||
<< QStringLiteral("mmst")
|
||||
<< QStringLiteral("mmsu")
|
||||
<< QStringLiteral("rtsp")
|
||||
<< QStringLiteral("rtspu")
|
||||
<< QStringLiteral("rtspt")
|
||||
<< QStringLiteral("rtsph");
|
||||
}
|
||||
|
||||
timeout_timer_->setSingleShot(true);
|
||||
|
@ -237,8 +237,8 @@ SongLoader::Result SongLoader::LoadLocal(const QString &filename) {
|
|||
QSqlDatabase db(collection_backend_->db()->Connect());
|
||||
|
||||
CollectionQuery query(db, collection_backend_->songs_table(), collection_backend_->fts_table());
|
||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||
query.AddWhere("url", url.toEncoded());
|
||||
query.SetColumnSpec(QStringLiteral("%songs_table.ROWID, ") + Song::kColumnSpec);
|
||||
query.AddWhere(QStringLiteral("url"), url.toEncoded());
|
||||
|
||||
if (query.Exec() && query.Next()) {
|
||||
// We may have many results when the file has many sections
|
||||
|
@ -302,7 +302,7 @@ SongLoader::Result SongLoader::LoadLocalAsync(const QString &filename) {
|
|||
// It's a CUE - create virtual tracks
|
||||
QFile cue(matching_cue);
|
||||
if (cue.open(QIODevice::ReadOnly)) {
|
||||
const SongList songs = cue_parser_->Load(&cue, matching_cue, QDir(filename.section('/', 0, -2)));
|
||||
const SongList songs = cue_parser_->Load(&cue, matching_cue, QDir(filename.section(QLatin1Char('/'), 0, -2)));
|
||||
cue.close();
|
||||
for (const Song &song : songs) {
|
||||
if (song.is_valid()) songs_ << song;
|
||||
|
@ -542,9 +542,9 @@ void SongLoader::TypeFound(GstElement*, uint, GstCaps *caps, void *self) {
|
|||
if (instance->state_ != State::WaitingForType) return;
|
||||
|
||||
// Check the mimetype
|
||||
instance->mime_type_ = gst_structure_get_name(gst_caps_get_structure(caps, 0));
|
||||
instance->mime_type_ = QString::fromUtf8(gst_structure_get_name(gst_caps_get_structure(caps, 0)));
|
||||
qLog(Debug) << "Mime type is" << instance->mime_type_;
|
||||
if (instance->mime_type_ == "text/plain" || instance->mime_type_ == "text/uri-list") {
|
||||
if (instance->mime_type_ == QStringLiteral("text/plain") || instance->mime_type_ == QStringLiteral("text/uri-list")) {
|
||||
// Yeah it might be a playlist, let's get some data and have a better look
|
||||
instance->state_ = State::WaitingForMagic;
|
||||
return;
|
||||
|
@ -634,12 +634,12 @@ void SongLoader::ErrorMessageReceived(GstMessage *msg) {
|
|||
qLog(Error) << error->message;
|
||||
qLog(Error) << debugs;
|
||||
|
||||
QString message_str = error->message;
|
||||
QString message_str = QString::fromUtf8(error->message);
|
||||
|
||||
g_error_free(error);
|
||||
g_free(debugs);
|
||||
|
||||
if (state_ == State::WaitingForType && message_str == gst_error_get_message(GST_STREAM_ERROR, GST_STREAM_ERROR_TYPE_NOT_FOUND)) {
|
||||
if (state_ == State::WaitingForType && message_str == QString::fromUtf8(gst_error_get_message(GST_STREAM_ERROR, GST_STREAM_ERROR_TYPE_NOT_FOUND))) {
|
||||
// Don't give up - assume it's a playlist and see if one of our parsers can read it.
|
||||
state_ = State::WaitingForMagic;
|
||||
return;
|
||||
|
@ -697,10 +697,10 @@ void SongLoader::MagicReady() {
|
|||
|
||||
qLog(Debug) << "Magic says" << parser_->name();
|
||||
|
||||
if (parser_->name() == "ASX/INI" && url_.scheme() == "http") {
|
||||
if (parser_->name() == QStringLiteral("ASX/INI") && url_.scheme() == QStringLiteral("http")) {
|
||||
// This is actually a weird MS-WMSP stream. Changing the protocol to MMS from HTTP makes it playable.
|
||||
parser_ = nullptr;
|
||||
url_.setScheme("mms");
|
||||
url_.setScheme(QStringLiteral("mms"));
|
||||
StopTypefindAsync(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2021-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -38,13 +38,13 @@ void SqlQuery::BindValue(const QString &placeholder, const QVariant &value) {
|
|||
|
||||
void SqlQuery::BindStringValue(const QString &placeholder, const QString &value) {
|
||||
|
||||
BindValue(placeholder, value.isNull() ? "" : value);
|
||||
BindValue(placeholder, value.isNull() ? QLatin1String("") : value);
|
||||
|
||||
}
|
||||
|
||||
void SqlQuery::BindUrlValue(const QString &placeholder, const QUrl &value) {
|
||||
|
||||
BindValue(placeholder, value.isValid() ? value.toString(QUrl::FullyEncoded) : "");
|
||||
BindValue(placeholder, value.isValid() ? value.toString(QUrl::FullyEncoded) : QLatin1String(""));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2021-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -29,12 +29,15 @@
|
|||
#include <QString>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlRecord>
|
||||
|
||||
class SqlQuery : public QSqlQuery {
|
||||
|
||||
public:
|
||||
explicit SqlQuery(const QSqlDatabase &db) : QSqlQuery(db) {}
|
||||
|
||||
int columns() const { return QSqlQuery::record().count(); }
|
||||
|
||||
void BindValue(const QString &placeholder, const QVariant &value);
|
||||
void BindStringValue(const QString &placeholder, const QString &value);
|
||||
void BindUrlValue(const QString &placeholder, const QUrl &value);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,74 +20,22 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlRecord>
|
||||
|
||||
#include "sqlrow.h"
|
||||
|
||||
SqlRow::SqlRow(const QSqlQuery &query) { Init(query); }
|
||||
SqlRow::SqlRow(const SqlQuery &query) { Init(query); }
|
||||
|
||||
void SqlRow::Init(const QSqlQuery &query) {
|
||||
void SqlRow::Init(const SqlQuery &query) {
|
||||
|
||||
const QSqlRecord r = query.record();
|
||||
for (int i = 0; i < r.count(); ++i) {
|
||||
columns_by_number_.insert(i, query.value(i));
|
||||
const QString field_name = r.fieldName(i);
|
||||
if (!columns_by_name_.contains(field_name) || columns_by_name_[field_name].isNull()) {
|
||||
columns_by_name_.insert(field_name, query.value(i));
|
||||
}
|
||||
}
|
||||
record_ = query.record();
|
||||
|
||||
}
|
||||
|
||||
const QVariant SqlRow::value(const int number) const {
|
||||
const QVariant SqlRow::value(const int n) const {
|
||||
|
||||
if (columns_by_number_.contains(number)) {
|
||||
return columns_by_number_[number];
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
Q_ASSERT(n < record_.count());
|
||||
|
||||
return record_.value(n);
|
||||
|
||||
}
|
||||
|
||||
const QVariant SqlRow::value(const QString &name) const {
|
||||
|
||||
if (columns_by_name_.contains(name)) {
|
||||
return columns_by_name_[name];
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QString SqlRow::ValueToString(const QString &n) const {
|
||||
return value(n).isNull() ? QString() : value(n).toString();
|
||||
}
|
||||
|
||||
QUrl SqlRow::ValueToUrl(const QString &n) const {
|
||||
return value(n).isNull() ? QUrl() : QUrl(value(n).toString());
|
||||
}
|
||||
|
||||
int SqlRow::ValueToInt(const QString &n) const {
|
||||
return value(n).isNull() ? -1 : value(n).toInt();
|
||||
}
|
||||
|
||||
uint SqlRow::ValueToUInt(const QString &n) const {
|
||||
return value(n).isNull() || value(n).toInt() < 0 ? 0 : value(n).toInt();
|
||||
}
|
||||
|
||||
qint64 SqlRow::ValueToLongLong(const QString &n) const {
|
||||
return value(n).isNull() ? -1 : value(n).toLongLong();
|
||||
}
|
||||
|
||||
float SqlRow::ValueToFloat(const QString &n) const {
|
||||
return value(n).isNull() ? -1.0F : value(n).toFloat();
|
||||
}
|
||||
|
||||
bool SqlRow::ValueToBool(const QString &n) const {
|
||||
return !value(n).isNull() && value(n).toInt() == 1;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -24,33 +24,23 @@
|
|||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QUrl>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlRecord>
|
||||
|
||||
#include "sqlquery.h"
|
||||
|
||||
class SqlRow {
|
||||
|
||||
public:
|
||||
SqlRow(const QSqlQuery &query);
|
||||
explicit SqlRow(const SqlQuery &query);
|
||||
|
||||
const QVariant value(const int number) const;
|
||||
const QVariant value(const QString &name) const;
|
||||
|
||||
QString ValueToString(const QString &n) const;
|
||||
QUrl ValueToUrl(const QString &n) const;
|
||||
int ValueToInt(const QString &n) const;
|
||||
uint ValueToUInt(const QString &n) const;
|
||||
qint64 ValueToLongLong(const QString &n) const;
|
||||
float ValueToFloat(const QString &n) const;
|
||||
bool ValueToBool(const QString& n) const;
|
||||
int columns() const { return record_.count(); }
|
||||
const QSqlRecord &record() const { return record_; }
|
||||
const QVariant value(const int n) const;
|
||||
|
||||
private:
|
||||
SqlRow();
|
||||
|
||||
void Init(const QSqlQuery &query);
|
||||
|
||||
QMap<int, QVariant> columns_by_number_;
|
||||
QMap<QString, QVariant> columns_by_name_;
|
||||
void Init(const SqlQuery &query);
|
||||
|
||||
QSqlRecord record_;
|
||||
};
|
||||
|
||||
using SqlRowList = QList<SqlRow>;
|
||||
|
|
|
@ -176,7 +176,8 @@ void StyleHelper::setBaseColor(const QColor &newcolor) {
|
|||
|
||||
if (color.isValid() && color != m_baseColor) {
|
||||
m_baseColor = color;
|
||||
for (QWidget *w : QApplication::topLevelWidgets()) {
|
||||
const QList<QWidget*> widgets = QApplication::topLevelWidgets();
|
||||
for (QWidget *w : widgets) {
|
||||
w->update();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,32 +90,32 @@ void StyleSheetLoader::UpdateStyleSheet(QWidget *widget, SharedPtr<StyleSheetDat
|
|||
#else
|
||||
alt.setAlpha(130);
|
||||
#endif
|
||||
stylesheet.replace("%palette-alternate-base", QString("rgba(%1,%2,%3,%4)").arg(alt.red()).arg(alt.green()).arg(alt.blue()).arg(alt.alpha()));
|
||||
stylesheet.replace(QLatin1String("%palette-alternate-base"), QStringLiteral("rgba(%1,%2,%3,%4)").arg(alt.red()).arg(alt.green()).arg(alt.blue()).arg(alt.alpha()));
|
||||
}
|
||||
|
||||
ReplaceColor(&stylesheet, "Window", p, QPalette::Window);
|
||||
ReplaceColor(&stylesheet, "Background", p, QPalette::Window);
|
||||
ReplaceColor(&stylesheet, "WindowText", p, QPalette::WindowText);
|
||||
ReplaceColor(&stylesheet, "Base", p, QPalette::Base);
|
||||
ReplaceColor(&stylesheet, "AlternateBase", p, QPalette::AlternateBase);
|
||||
ReplaceColor(&stylesheet, "ToolTipBase", p, QPalette::ToolTipBase);
|
||||
ReplaceColor(&stylesheet, "ToolTipText", p, QPalette::ToolTipText);
|
||||
ReplaceColor(&stylesheet, "Text", p, QPalette::Text);
|
||||
ReplaceColor(&stylesheet, "Button", p, QPalette::Button);
|
||||
ReplaceColor(&stylesheet, "ButtonText", p, QPalette::ButtonText);
|
||||
ReplaceColor(&stylesheet, "BrightText", p, QPalette::BrightText);
|
||||
ReplaceColor(&stylesheet, "Light", p, QPalette::Light);
|
||||
ReplaceColor(&stylesheet, "Midlight", p, QPalette::Midlight);
|
||||
ReplaceColor(&stylesheet, "Dark", p, QPalette::Dark);
|
||||
ReplaceColor(&stylesheet, "Mid", p, QPalette::Mid);
|
||||
ReplaceColor(&stylesheet, "Shadow", p, QPalette::Shadow);
|
||||
ReplaceColor(&stylesheet, "Highlight", p, QPalette::Highlight);
|
||||
ReplaceColor(&stylesheet, "HighlightedText", p, QPalette::HighlightedText);
|
||||
ReplaceColor(&stylesheet, "Link", p, QPalette::Link);
|
||||
ReplaceColor(&stylesheet, "LinkVisited", p, QPalette::LinkVisited);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Window"), p, QPalette::Window);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Background"), p, QPalette::Window);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("WindowText"), p, QPalette::WindowText);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Base"), p, QPalette::Base);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("AlternateBase"), p, QPalette::AlternateBase);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("ToolTipBase"), p, QPalette::ToolTipBase);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("ToolTipText"), p, QPalette::ToolTipText);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Text"), p, QPalette::Text);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Button"), p, QPalette::Button);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("ButtonText"), p, QPalette::ButtonText);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("BrightText"), p, QPalette::BrightText);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Light"), p, QPalette::Light);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Midlight"), p, QPalette::Midlight);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Dark"), p, QPalette::Dark);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Mid"), p, QPalette::Mid);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Shadow"), p, QPalette::Shadow);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Highlight"), p, QPalette::Highlight);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("HighlightedText"), p, QPalette::HighlightedText);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("Link"), p, QPalette::Link);
|
||||
ReplaceColor(&stylesheet, QStringLiteral("LinkVisited"), p, QPalette::LinkVisited);
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
stylesheet.replace("macos", "*");
|
||||
stylesheet.replace(QStringLiteral("macos"), QStringLiteral("*"));
|
||||
#endif
|
||||
|
||||
if (stylesheet != styledata->stylesheet_current_) {
|
||||
|
@ -127,9 +127,9 @@ void StyleSheetLoader::UpdateStyleSheet(QWidget *widget, SharedPtr<StyleSheetDat
|
|||
|
||||
void StyleSheetLoader::ReplaceColor(QString *css, const QString &name, const QPalette &palette, const QPalette::ColorRole role) {
|
||||
|
||||
css->replace("%palette-" + name + "-lighter", palette.color(role).lighter().name(), Qt::CaseInsensitive);
|
||||
css->replace("%palette-" + name + "-darker", palette.color(role).darker().name(), Qt::CaseInsensitive);
|
||||
css->replace("%palette-" + name, palette.color(role).name(), Qt::CaseInsensitive);
|
||||
css->replace(QStringLiteral("%palette-") + name + QStringLiteral("-lighter"), palette.color(role).lighter().name(), Qt::CaseInsensitive);
|
||||
css->replace(QStringLiteral("%palette-") + name + QStringLiteral("-darker"), palette.color(role).darker().name(), Qt::CaseInsensitive);
|
||||
css->replace(QStringLiteral("%palette-") + name, palette.color(role).name(), Qt::CaseInsensitive);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/workerpool.h"
|
||||
|
@ -37,7 +36,10 @@
|
|||
#include "song.h"
|
||||
#include "tagreaderclient.h"
|
||||
|
||||
const char *TagReaderClient::kWorkerExecutableName = "strawberry-tagreader";
|
||||
namespace {
|
||||
constexpr char kWorkerExecutableName[] = "strawberry-tagreader";
|
||||
}
|
||||
|
||||
TagReaderClient *TagReaderClient::sInstance = nullptr;
|
||||
|
||||
TagReaderClient::TagReaderClient(QObject *parent) : QObject(parent), worker_pool_(new WorkerPool<HandlerType>(this)) {
|
||||
|
@ -45,7 +47,7 @@ TagReaderClient::TagReaderClient(QObject *parent) : QObject(parent), worker_pool
|
|||
sInstance = this;
|
||||
original_thread_ = thread();
|
||||
|
||||
worker_pool_->SetExecutableName(kWorkerExecutableName);
|
||||
worker_pool_->SetExecutableName(QLatin1String(kWorkerExecutableName));
|
||||
QObject::connect(worker_pool_, &WorkerPool<HandlerType>::WorkerFailedToStart, this, &TagReaderClient::WorkerFailedToStart);
|
||||
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ class TagReaderClient : public QObject {
|
|||
using HandlerType = AbstractMessageHandler<spb::tagreader::Message>;
|
||||
using ReplyType = HandlerType::ReplyType;
|
||||
|
||||
static const char *kWorkerExecutableName;
|
||||
|
||||
void Start();
|
||||
void ExitAsync();
|
||||
|
||||
|
|
|
@ -46,9 +46,9 @@ ThreadSafeNetworkDiskCache::ThreadSafeNetworkDiskCache(QObject *parent) : QAbstr
|
|||
if (!sCache) {
|
||||
sCache = new QNetworkDiskCache;
|
||||
#ifdef Q_OS_WIN32
|
||||
sCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/strawberry/networkcache");
|
||||
sCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + QStringLiteral("/strawberry/networkcache"));
|
||||
#else
|
||||
sCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/networkcache");
|
||||
sCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/networkcache"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QTranslator>
|
||||
#include <QString>
|
||||
|
@ -29,7 +31,7 @@
|
|||
Translations::Translations(QObject *parent) : QObject(parent) {}
|
||||
Translations::~Translations() {
|
||||
|
||||
for (QTranslator *t : translations_) {
|
||||
for (QTranslator *t : std::as_const(translations_)) {
|
||||
QCoreApplication::removeTranslator(t);
|
||||
delete t;
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ Translations::~Translations() {
|
|||
void Translations::LoadTranslation(const QString &prefix, const QString &path, const QString &language) {
|
||||
|
||||
QTranslator *t = new PoTranslator;
|
||||
if (t->load(prefix + "_" + language, path)) {
|
||||
if (t->load(prefix + QLatin1Char('_') + language, path)) {
|
||||
QCoreApplication::installTranslator(t);
|
||||
translations_ << t;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "core/song.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
#include "collection/collectionfilteroptions.h"
|
||||
#include "collection/collectionbackend.h"
|
||||
|
@ -102,16 +103,16 @@ AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget *parent)
|
|||
search_cover_auto_(nullptr),
|
||||
save_embedded_cover_override_(false) {
|
||||
|
||||
cover_from_file_ = new QAction(IconLoader::Load("document-open"), tr("Load cover from disk..."), this);
|
||||
cover_to_file_ = new QAction(IconLoader::Load("document-save"), tr("Save cover to disk..."), this);
|
||||
cover_from_url_ = new QAction(IconLoader::Load("download"), tr("Load cover from URL..."), this);
|
||||
search_for_cover_ = new QAction(IconLoader::Load("search"), tr("Search for album covers..."), this);
|
||||
unset_cover_ = new QAction(IconLoader::Load("list-remove"), tr("Unset cover"), this);
|
||||
delete_cover_ = new QAction(IconLoader::Load("list-remove"), tr("Delete cover"), this);
|
||||
clear_cover_ = new QAction(IconLoader::Load("list-remove"), tr("Clear cover"), this);
|
||||
cover_from_file_ = new QAction(IconLoader::Load(QStringLiteral("document-open")), tr("Load cover from disk..."), this);
|
||||
cover_to_file_ = new QAction(IconLoader::Load(QStringLiteral("document-save")), tr("Save cover to disk..."), this);
|
||||
cover_from_url_ = new QAction(IconLoader::Load(QStringLiteral("download")), tr("Load cover from URL..."), this);
|
||||
search_for_cover_ = new QAction(IconLoader::Load(QStringLiteral("search")), tr("Search for album covers..."), this);
|
||||
unset_cover_ = new QAction(IconLoader::Load(QStringLiteral("list-remove")), tr("Unset cover"), this);
|
||||
delete_cover_ = new QAction(IconLoader::Load(QStringLiteral("list-remove")), tr("Delete cover"), this);
|
||||
clear_cover_ = new QAction(IconLoader::Load(QStringLiteral("list-remove")), tr("Clear cover"), this);
|
||||
separator1_ = new QAction(this);
|
||||
separator1_->setSeparator(true);
|
||||
show_cover_ = new QAction(IconLoader::Load("zoom-in"), tr("Show fullsize..."), this);
|
||||
show_cover_ = new QAction(IconLoader::Load(QStringLiteral("zoom-in")), tr("Show fullsize..."), this);
|
||||
|
||||
search_cover_auto_ = new QAction(tr("Search automatically"), this);
|
||||
search_cover_auto_->setCheckable(true);
|
||||
|
@ -131,7 +132,7 @@ void AlbumCoverChoiceController::Init(Application *app) {
|
|||
app_ = app;
|
||||
|
||||
cover_fetcher_ = new AlbumCoverFetcher(app_->cover_providers(), app->network(), this);
|
||||
cover_searcher_ = new AlbumCoverSearcher(QIcon(":/pictures/cdcase.png"), app, this);
|
||||
cover_searcher_ = new AlbumCoverSearcher(QIcon(QStringLiteral(":/pictures/cdcase.png")), app, this);
|
||||
cover_searcher_->Init(cover_fetcher_);
|
||||
|
||||
QObject::connect(cover_fetcher_, &AlbumCoverFetcher::AlbumCoverFetched, this, &AlbumCoverChoiceController::AlbumCoverFetched);
|
||||
|
@ -140,11 +141,11 @@ void AlbumCoverChoiceController::Init(Application *app) {
|
|||
|
||||
void AlbumCoverChoiceController::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(CoversSettingsPage::kSettingsGroup);
|
||||
cover_options_.cover_type = static_cast<CoverOptions::CoverType>(s.value(CoversSettingsPage::kSaveType, static_cast<int>(CoverOptions::CoverType::Cache)).toInt());
|
||||
cover_options_.cover_filename = static_cast<CoverOptions::CoverFilename>(s.value(CoversSettingsPage::kSaveFilename, static_cast<int>(CoverOptions::CoverFilename::Pattern)).toInt());
|
||||
cover_options_.cover_pattern = s.value(CoversSettingsPage::kSavePattern, "%albumartist-%album").toString();
|
||||
cover_options_.cover_pattern = s.value(CoversSettingsPage::kSavePattern, QStringLiteral("%albumartist-%album")).toString();
|
||||
cover_options_.cover_overwrite = s.value(CoversSettingsPage::kSaveOverwrite, false).toBool();
|
||||
cover_options_.cover_lowercase = s.value(CoversSettingsPage::kSaveLowercase, false).toBool();
|
||||
cover_options_.cover_replace_spaces = s.value(CoversSettingsPage::kSaveReplaceSpaces, false).toBool();
|
||||
|
@ -175,7 +176,7 @@ AlbumCoverImageResult AlbumCoverChoiceController::LoadImageFromFile(Song *song)
|
|||
return AlbumCoverImageResult();
|
||||
}
|
||||
|
||||
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + ";;" + tr(kAllFilesFilter));
|
||||
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + QStringLiteral(";;") + tr(kAllFilesFilter));
|
||||
if (cover_file.isEmpty()) return AlbumCoverImageResult();
|
||||
|
||||
QFile file(cover_file);
|
||||
|
@ -206,7 +207,7 @@ QUrl AlbumCoverChoiceController::LoadCoverFromFile(Song *song) {
|
|||
|
||||
if (!song->url().isValid() || !song->url().isLocalFile() || song->effective_albumartist().isEmpty() || song->album().isEmpty()) return QUrl();
|
||||
|
||||
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + ";;" + tr(kAllFilesFilter));
|
||||
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + QStringLiteral(";;") + tr(kAllFilesFilter));
|
||||
if (cover_file.isEmpty() || QImage(cover_file).isNull()) return QUrl();
|
||||
|
||||
switch (get_save_album_cover_type()) {
|
||||
|
@ -230,32 +231,32 @@ QUrl AlbumCoverChoiceController::LoadCoverFromFile(Song *song) {
|
|||
|
||||
void AlbumCoverChoiceController::SaveCoverToFileManual(const Song &song, const AlbumCoverImageResult &result) {
|
||||
|
||||
QString initial_file_name = "/";
|
||||
QString initial_file_name = QStringLiteral("/");
|
||||
|
||||
if (!song.effective_albumartist().isEmpty()) {
|
||||
initial_file_name = initial_file_name + song.effective_albumartist();
|
||||
}
|
||||
initial_file_name = initial_file_name + "-" + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + ".jpg";
|
||||
initial_file_name = initial_file_name + QLatin1Char('-') + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + QStringLiteral(".jpg");
|
||||
initial_file_name = initial_file_name.toLower();
|
||||
initial_file_name.replace(QRegularExpression("\\s"), "-");
|
||||
initial_file_name.remove(QRegularExpression(QString(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption));
|
||||
initial_file_name.replace(QRegularExpression(QStringLiteral("\\s")), QStringLiteral("-"));
|
||||
initial_file_name.remove(QRegularExpression(QLatin1String(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption));
|
||||
|
||||
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + ";;" + tr(kAllFilesFilter));
|
||||
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + QStringLiteral(";;") + tr(kAllFilesFilter));
|
||||
|
||||
if (save_filename.isEmpty()) return;
|
||||
|
||||
QFileInfo fileinfo(save_filename);
|
||||
if (fileinfo.suffix().isEmpty()) {
|
||||
save_filename.append(".jpg");
|
||||
save_filename.append(QStringLiteral(".jpg"));
|
||||
fileinfo.setFile(save_filename);
|
||||
}
|
||||
|
||||
if (!QImageWriter::supportedImageFormats().contains(fileinfo.completeSuffix().toUtf8().toLower())) {
|
||||
save_filename = Utilities::PathWithoutFilenameExtension(save_filename) + ".jpg";
|
||||
save_filename = Utilities::PathWithoutFilenameExtension(save_filename) + QStringLiteral(".jpg");
|
||||
fileinfo.setFile(save_filename);
|
||||
}
|
||||
|
||||
if (result.is_jpeg() && fileinfo.completeSuffix().compare("jpg", Qt::CaseInsensitive) == 0) {
|
||||
if (result.is_jpeg() && fileinfo.completeSuffix().compare(QLatin1String("jpg"), Qt::CaseInsensitive) == 0) {
|
||||
QFile file(save_filename);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qLog(Error) << "Failed to open cover file" << save_filename << "for writing:" << file.errorString();
|
||||
|
@ -289,8 +290,8 @@ QString AlbumCoverChoiceController::GetInitialPathForFileDialog(const Song &song
|
|||
}
|
||||
|
||||
// If no automatic art, start in the song's folder
|
||||
if (!song.url().isEmpty() && song.url().isValid() && song.url().isLocalFile() && song.url().toLocalFile().contains('/')) {
|
||||
return song.url().toLocalFile().section('/', 0, -2) + filename;
|
||||
if (!song.url().isEmpty() && song.url().isValid() && song.url().isLocalFile() && song.url().toLocalFile().contains(QLatin1Char('/'))) {
|
||||
return song.url().toLocalFile().section(QLatin1Char('/'), 0, -2) + filename;
|
||||
}
|
||||
|
||||
return QDir::home().absolutePath() + filename;
|
||||
|
@ -422,7 +423,7 @@ void AlbumCoverChoiceController::ShowCover(const Song &song, const QImage &image
|
|||
|
||||
for (const AlbumCoverLoaderOptions::Type type : cover_types_) {
|
||||
switch (type) {
|
||||
case AlbumCoverLoaderOptions::Type::Unset: {
|
||||
case AlbumCoverLoaderOptions::Type::Unset:{
|
||||
if (song.art_unset()) {
|
||||
return;
|
||||
}
|
||||
|
@ -472,13 +473,13 @@ void AlbumCoverChoiceController::ShowCover(const Song &song, const QPixmap &pixm
|
|||
|
||||
// Use Artist - Album as the window title
|
||||
QString title_text(song.effective_albumartist());
|
||||
if (!song.effective_album().isEmpty()) title_text += " - " + song.effective_album();
|
||||
if (!song.effective_album().isEmpty()) title_text += QStringLiteral(" - ") + song.effective_album();
|
||||
|
||||
QLabel *label = new QLabel(dialog);
|
||||
label->setPixmap(pixmap);
|
||||
|
||||
// Add (WxHpx) to the title before possibly resizing
|
||||
title_text += " (" + QString::number(pixmap.width()) + "x" + QString::number(pixmap.height()) + "px)";
|
||||
title_text += QStringLiteral(" (") + QString::number(pixmap.width()) + QLatin1Char('x') + QString::number(pixmap.height()) + QStringLiteral("px)");
|
||||
|
||||
// If the cover is larger than the screen, resize the window 85% seems to be enough to account for title bar and taskbar etc.
|
||||
QScreen *screen = Utilities::GetScreen(this);
|
||||
|
@ -574,9 +575,10 @@ void AlbumCoverChoiceController::SaveArtManualToSong(Song *song, const QUrl &art
|
|||
case Song::Source::SomaFM:
|
||||
case Song::Source::Unknown:
|
||||
break;
|
||||
case Song::Source::Tidal:
|
||||
case Song::Source::Qobuz:
|
||||
case Song::Source::Subsonic:
|
||||
case Song::Source::Tidal:
|
||||
case Song::Source::Spotify:
|
||||
case Song::Source::Qobuz:
|
||||
InternetServicePtr service = app_->internet_services()->ServiceBySource(song->source());
|
||||
if (!service) break;
|
||||
if (service->artists_collection_backend()) {
|
||||
|
@ -655,7 +657,7 @@ QUrl AlbumCoverChoiceController::SaveCoverToFileAutomatic(const Song::Source sou
|
|||
const AlbumCoverImageResult &result,
|
||||
const bool force_overwrite) {
|
||||
|
||||
QString filepath = CoverUtils::CoverFilePath(cover_options_, source, artist, album, album_id, album_dir, result.cover_url, "jpg");
|
||||
QString filepath = CoverUtils::CoverFilePath(cover_options_, source, artist, album, album_id, album_dir, result.cover_url, QStringLiteral("jpg"));
|
||||
if (filepath.isEmpty()) return QUrl();
|
||||
|
||||
QFile file(filepath);
|
||||
|
@ -663,7 +665,7 @@ QUrl AlbumCoverChoiceController::SaveCoverToFileAutomatic(const Song::Source sou
|
|||
if (source == Song::Source::Collection && !cover_options_.cover_overwrite && !force_overwrite && get_save_album_cover_type() == CoverOptions::CoverType::Album && cover_options_.cover_filename == CoverOptions::CoverFilename::Pattern && file.exists()) {
|
||||
while (file.exists()) {
|
||||
QFileInfo fileinfo(file.fileName());
|
||||
file.setFileName(fileinfo.path() + "/0" + fileinfo.fileName());
|
||||
file.setFileName(fileinfo.path() + QStringLiteral("/0") + fileinfo.fileName());
|
||||
}
|
||||
filepath = file.fileName();
|
||||
}
|
||||
|
@ -744,7 +746,7 @@ bool AlbumCoverChoiceController::IsKnownImageExtension(const QString &suffix) {
|
|||
|
||||
if (!sImageExtensions) {
|
||||
sImageExtensions = new QSet<QString>();
|
||||
(*sImageExtensions) << "png" << "jpg" << "jpeg" << "bmp" << "gif" << "xpm" << "pbm" << "pgm" << "ppm" << "xbm";
|
||||
(*sImageExtensions) << QStringLiteral("png") << QStringLiteral("jpg") << QStringLiteral("jpeg") << QStringLiteral("bmp") << QStringLiteral("gif") << QStringLiteral("xpm") << QStringLiteral("pbm") << QStringLiteral("pgm") << QStringLiteral("ppm") << QStringLiteral("xbm");
|
||||
}
|
||||
|
||||
return sImageExtensions->contains(suffix);
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include "albumcoverexport.h"
|
||||
#include "ui_albumcoverexport.h"
|
||||
|
||||
#include "core/settings.h"
|
||||
|
||||
const char *AlbumCoverExport::kSettingsGroup = "AlbumCoverExport";
|
||||
|
||||
AlbumCoverExport::AlbumCoverExport(QWidget *parent) : QDialog(parent), ui_(new Ui_AlbumCoverExport) {
|
||||
|
@ -47,17 +49,17 @@ AlbumCoverExport::~AlbumCoverExport() { delete ui_; }
|
|||
|
||||
AlbumCoverExport::DialogResult AlbumCoverExport::Exec() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
// Restore last accepted settings
|
||||
ui_->fileName->setText(s.value("fileName", "cover").toString());
|
||||
ui_->fileName->setText(s.value("fileName", QStringLiteral("cover")).toString());
|
||||
ui_->doNotOverwrite->setChecked(static_cast<OverwriteMode>(s.value("overwrite", static_cast<int>(OverwriteMode::None)).toInt()) == OverwriteMode::None);
|
||||
ui_->overwriteAll->setChecked(static_cast<OverwriteMode>(s.value("overwrite", static_cast<int>(OverwriteMode::All)).toInt()) == OverwriteMode::All);
|
||||
ui_->overwriteSmaller->setChecked(static_cast<OverwriteMode>(s.value("overwrite", static_cast<int>(OverwriteMode::Smaller)).toInt()) == OverwriteMode::Smaller);
|
||||
ui_->forceSize->setChecked(s.value("forceSize", false).toBool());
|
||||
ui_->width->setText(s.value("width", "").toString());
|
||||
ui_->height->setText(s.value("height", "").toString());
|
||||
ui_->width->setText(s.value("width", QLatin1String("")).toString());
|
||||
ui_->height->setText(s.value("height", QLatin1String("")).toString());
|
||||
ui_->export_downloaded->setChecked(s.value("export_downloaded", true).toBool());
|
||||
ui_->export_embedded->setChecked(s.value("export_embedded", false).toBool());
|
||||
|
||||
|
@ -69,7 +71,7 @@ AlbumCoverExport::DialogResult AlbumCoverExport::Exec() {
|
|||
if (!result.cancelled_) {
|
||||
QString fileName = ui_->fileName->text();
|
||||
if (fileName.isEmpty()) {
|
||||
fileName = "cover";
|
||||
fileName = QStringLiteral("cover");
|
||||
}
|
||||
OverwriteMode overwrite_mode = ui_->doNotOverwrite->isChecked() ? OverwriteMode::None : (ui_->overwriteAll->isChecked() ? OverwriteMode::All : OverwriteMode::Smaller);
|
||||
bool forceSize = ui_->forceSize->isChecked();
|
||||
|
|
|
@ -52,7 +52,7 @@ AlbumCoverFetcher::AlbumCoverFetcher(SharedPtr<CoverProviders> cover_providers,
|
|||
|
||||
AlbumCoverFetcher::~AlbumCoverFetcher() {
|
||||
|
||||
QList<AlbumCoverFetcherSearch*> searches = active_requests_.values();
|
||||
const QList<AlbumCoverFetcherSearch*> searches = active_requests_.values();
|
||||
for (AlbumCoverFetcherSearch *search : searches) {
|
||||
search->disconnect();
|
||||
search->deleteLater();
|
||||
|
@ -105,7 +105,7 @@ void AlbumCoverFetcher::Clear() {
|
|||
|
||||
queued_requests_.clear();
|
||||
|
||||
QList<AlbumCoverFetcherSearch*> searches = active_requests_.values();
|
||||
const QList<AlbumCoverFetcherSearch*> searches = active_requests_.values();
|
||||
for (AlbumCoverFetcherSearch *search : searches) {
|
||||
search->Cancel();
|
||||
search->deleteLater();
|
||||
|
|
|
@ -83,7 +83,7 @@ void AlbumCoverFetcherSearch::TerminateSearch() {
|
|||
void AlbumCoverFetcherSearch::Start(SharedPtr<CoverProviders> cover_providers) {
|
||||
|
||||
// Ignore Radio Paradise "commercial" break.
|
||||
if (request_.artist.compare("commercial-free", Qt::CaseInsensitive) == 0 && request_.title.compare("listener-supported", Qt::CaseInsensitive) == 0) {
|
||||
if (request_.artist.compare(QLatin1String("commercial-free"), Qt::CaseInsensitive) == 0 && request_.title.compare(QLatin1String("listener-supported"), Qt::CaseInsensitive) == 0) {
|
||||
TerminateSearch();
|
||||
return;
|
||||
}
|
||||
|
@ -167,51 +167,51 @@ void AlbumCoverFetcherSearch::ProviderSearchResults(CoverProvider *provider, con
|
|||
// This is done since we can't match the album titles, and we want to prevent compilation or live albums from being picked before studio albums for streams.
|
||||
// TODO: Make these regular expressions.
|
||||
if (request_album.isEmpty() && (
|
||||
result_album.contains("hits", Qt::CaseInsensitive) ||
|
||||
result_album.contains("greatest", Qt::CaseInsensitive) ||
|
||||
result_album.contains("best", Qt::CaseInsensitive) ||
|
||||
result_album.contains("collection", Qt::CaseInsensitive) ||
|
||||
result_album.contains("classics", Qt::CaseInsensitive) ||
|
||||
result_album.contains("singles", Qt::CaseInsensitive) ||
|
||||
result_album.contains("bootleg", Qt::CaseInsensitive) ||
|
||||
result_album.contains("live", Qt::CaseInsensitive) ||
|
||||
result_album.contains("concert", Qt::CaseInsensitive) ||
|
||||
result_album.contains("essential", Qt::CaseInsensitive) ||
|
||||
result_album.contains("ultimate", Qt::CaseInsensitive) ||
|
||||
result_album.contains("karaoke", Qt::CaseInsensitive) ||
|
||||
result_album.contains("mixtape", Qt::CaseInsensitive) ||
|
||||
result_album.contains("country rock", Qt::CaseInsensitive) ||
|
||||
result_album.contains("indie folk", Qt::CaseInsensitive) ||
|
||||
result_album.contains("soft rock", Qt::CaseInsensitive) ||
|
||||
result_album.contains("folk music", Qt::CaseInsensitive) ||
|
||||
result_album.contains("60's rock", Qt::CaseInsensitive) ||
|
||||
result_album.contains("60's romance", Qt::CaseInsensitive) ||
|
||||
result_album.contains("60s music", Qt::CaseInsensitive) ||
|
||||
result_album.contains("late 60s", Qt::CaseInsensitive) ||
|
||||
result_album.contains("the 60s", Qt::CaseInsensitive) ||
|
||||
result_album.contains("folk and blues", Qt::CaseInsensitive) ||
|
||||
result_album.contains("60 from the 60's", Qt::CaseInsensitive) ||
|
||||
result_album.contains("classic psychedelic", Qt::CaseInsensitive) ||
|
||||
result_album.contains("playlist: acoustic", Qt::CaseInsensitive) ||
|
||||
result_album.contains("90's rnb playlist", Qt::CaseInsensitive) ||
|
||||
result_album.contains("rock 80s", Qt::CaseInsensitive) ||
|
||||
result_album.contains("classic 80s", Qt::CaseInsensitive) ||
|
||||
result_album.contains("rock anthems", Qt::CaseInsensitive) ||
|
||||
result_album.contains("rock songs", Qt::CaseInsensitive) ||
|
||||
result_album.contains("rock 2019", Qt::CaseInsensitive) ||
|
||||
result_album.contains("guitar anthems", Qt::CaseInsensitive) ||
|
||||
result_album.contains("driving anthems", Qt::CaseInsensitive) ||
|
||||
result_album.contains("traffic jam jams", Qt::CaseInsensitive) ||
|
||||
result_album.contains("perfect background music", Qt::CaseInsensitive) ||
|
||||
result_album.contains("70's gold", Qt::CaseInsensitive) ||
|
||||
result_album.contains("rockfluence", Qt::CaseInsensitive) ||
|
||||
result_album.contains("acoustic dinner accompaniment", Qt::CaseInsensitive) ||
|
||||
result_album.contains("complete studio albums", Qt::CaseInsensitive) ||
|
||||
result_album.contains("mellow rock", Qt::CaseInsensitive)
|
||||
result_album.contains(QLatin1String("hits"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("greatest"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("best"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("collection"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("classics"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("singles"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("bootleg"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("live"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("concert"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("essential"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("ultimate"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("karaoke"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("mixtape"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("country rock"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("indie folk"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("soft rock"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("folk music"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("60's rock"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("60's romance"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("60s music"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("late 60s"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("the 60s"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("folk and blues"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("60 from the 60's"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("classic psychedelic"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("playlist: acoustic"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("90's rnb playlist"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("rock 80s"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("classic 80s"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("rock anthems"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("rock songs"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("rock 2019"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("guitar anthems"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("driving anthems"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("traffic jam jams"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("perfect background music"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("70's gold"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("rockfluence"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("acoustic dinner accompaniment"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("complete studio albums"), Qt::CaseInsensitive) ||
|
||||
result_album.contains(QLatin1String("mellow rock"), Qt::CaseInsensitive)
|
||||
)) {
|
||||
results_copy[i].score_match -= 1;
|
||||
}
|
||||
else if (request_album.isEmpty() && result_album.contains("soundtrack", Qt::CaseInsensitive)) {
|
||||
else if (request_album.isEmpty() && result_album.contains(QLatin1String("soundtrack"), Qt::CaseInsensitive)) {
|
||||
results_copy[i].score_match -= 0.5;
|
||||
}
|
||||
|
||||
|
@ -320,8 +320,8 @@ void AlbumCoverFetcherSearch::ProviderCoverFetchFinished(QNetworkReply *reply) {
|
|||
}
|
||||
else {
|
||||
QString mimetype = reply->header(QNetworkRequest::ContentTypeHeader).toString();
|
||||
if (mimetype.contains(';')) {
|
||||
mimetype = mimetype.left(mimetype.indexOf(';'));
|
||||
if (mimetype.contains(QLatin1Char(';'))) {
|
||||
mimetype = mimetype.left(mimetype.indexOf(QLatin1Char(';')));
|
||||
}
|
||||
if (ImageUtils::SupportedImageMimeTypes().contains(mimetype, Qt::CaseInsensitive) || ImageUtils::SupportedImageFormats().contains(mimetype, Qt::CaseInsensitive)) {
|
||||
QByteArray image_data = reply->readAll();
|
||||
|
|
|
@ -41,7 +41,7 @@ class AlbumCoverImageResult {
|
|||
QImage image;
|
||||
|
||||
bool is_valid() const { return !image_data.isNull() || !image.isNull(); }
|
||||
bool is_jpeg() const { return mime_type == "image/jpeg" && !image_data.isEmpty(); }
|
||||
bool is_jpeg() const { return mime_type == QStringLiteral("image/jpeg") && !image_data.isEmpty(); }
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AlbumCoverImageResult)
|
||||
|
|
|
@ -120,7 +120,7 @@ class AlbumCoverLoader : public QObject {
|
|||
private slots:
|
||||
void Exit();
|
||||
void ProcessTasks();
|
||||
void LoadRemoteImageFinished(QNetworkReply *reply, TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QUrl &cover_url);
|
||||
void LoadRemoteImageFinished(QNetworkReply *reply, AlbumCoverLoader::TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QUrl &cover_url);
|
||||
|
||||
private:
|
||||
static const int kMaxRedirects = 3;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/settings.h"
|
||||
#include "settings/coverssettingspage.h"
|
||||
|
||||
AlbumCoverLoaderOptions::AlbumCoverLoaderOptions(const Options _options, const QSize _desired_scaled_size, const qreal _device_pixel_ratio, const Types &_types)
|
||||
|
@ -33,21 +34,21 @@ AlbumCoverLoaderOptions::Types AlbumCoverLoaderOptions::LoadTypes() {
|
|||
|
||||
Types cover_types;
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(CoversSettingsPage::kSettingsGroup);
|
||||
const QStringList all_cover_types = QStringList() << "art_unset" << "art_embedded" << "art_manual" << "art_automatic";
|
||||
const QStringList all_cover_types = QStringList() << QStringLiteral("art_unset") << QStringLiteral("art_embedded") << QStringLiteral("art_manual") << QStringLiteral("art_automatic");
|
||||
const QStringList cover_types_strlist = s.value(CoversSettingsPage::kTypes, all_cover_types).toStringList();
|
||||
for (const QString &cover_type_str : cover_types_strlist) {
|
||||
if (cover_type_str == "art_unset") {
|
||||
if (cover_type_str == QStringLiteral("art_unset")) {
|
||||
cover_types << AlbumCoverLoaderOptions::Type::Unset;
|
||||
}
|
||||
else if (cover_type_str == "art_embedded") {
|
||||
else if (cover_type_str == QStringLiteral("art_embedded")) {
|
||||
cover_types << AlbumCoverLoaderOptions::Type::Embedded;
|
||||
}
|
||||
else if (cover_type_str == "art_manual") {
|
||||
else if (cover_type_str == QStringLiteral("art_manual")) {
|
||||
cover_types << AlbumCoverLoaderOptions::Type::Manual;
|
||||
}
|
||||
else if (cover_type_str == "art_automatic") {
|
||||
else if (cover_type_str == QStringLiteral("art_automatic")) {
|
||||
cover_types << AlbumCoverLoaderOptions::Type::Automatic;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "core/tagreaderclient.h"
|
||||
#include "core/database.h"
|
||||
#include "core/sqlrow.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/strutils.h"
|
||||
#include "utilities/fileutils.h"
|
||||
#include "utilities/imageutils.h"
|
||||
|
@ -112,8 +113,8 @@ AlbumCoverManager::AlbumCoverManager(Application *app, SharedPtr<CollectionBacke
|
|||
cover_searcher_(nullptr),
|
||||
cover_export_(nullptr),
|
||||
cover_exporter_(new AlbumCoverExporter(this)),
|
||||
artist_icon_(IconLoader::Load("folder-sound")),
|
||||
all_artists_icon_(IconLoader::Load("library-music")),
|
||||
artist_icon_(IconLoader::Load(QStringLiteral("folder-sound"))),
|
||||
all_artists_icon_(IconLoader::Load(QStringLiteral("library-music"))),
|
||||
image_nocover_thumbnail_(ImageUtils::GenerateNoCoverImage(QSize(120, 120), devicePixelRatio())),
|
||||
icon_nocover_item_(QPixmap::fromImage(image_nocover_thumbnail_)),
|
||||
context_menu_(new QMenu(this)),
|
||||
|
@ -126,12 +127,12 @@ AlbumCoverManager::AlbumCoverManager(Application *app, SharedPtr<CollectionBacke
|
|||
ui_->albums->set_cover_manager(this);
|
||||
|
||||
// Icons
|
||||
ui_->action_fetch->setIcon(IconLoader::Load("download"));
|
||||
ui_->export_covers->setIcon(IconLoader::Load("document-save"));
|
||||
ui_->view->setIcon(IconLoader::Load("view-choose"));
|
||||
ui_->button_fetch->setIcon(IconLoader::Load("download"));
|
||||
ui_->action_add_to_playlist->setIcon(IconLoader::Load("media-playback-start"));
|
||||
ui_->action_load->setIcon(IconLoader::Load("media-playback-start"));
|
||||
ui_->action_fetch->setIcon(IconLoader::Load(QStringLiteral("download")));
|
||||
ui_->export_covers->setIcon(IconLoader::Load(QStringLiteral("document-save")));
|
||||
ui_->view->setIcon(IconLoader::Load(QStringLiteral("view-choose")));
|
||||
ui_->button_fetch->setIcon(IconLoader::Load(QStringLiteral("download")));
|
||||
ui_->action_add_to_playlist->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
ui_->action_load->setIcon(IconLoader::Load(QStringLiteral("media-playback-start")));
|
||||
|
||||
album_cover_choice_controller_->Init(app_);
|
||||
|
||||
|
@ -218,7 +219,7 @@ void AlbumCoverManager::Init() {
|
|||
QObject::connect(ui_->action_load, &QAction::triggered, this, &AlbumCoverManager::LoadSelectedToPlaylist);
|
||||
|
||||
// Restore settings
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
if (s.contains("geometry")) {
|
||||
|
@ -279,12 +280,12 @@ void AlbumCoverManager::closeEvent(QCloseEvent *e) {
|
|||
|
||||
void AlbumCoverManager::LoadGeometry() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
if (s.contains("geometry")) {
|
||||
if (s.contains(QStringLiteral("geometry"))) {
|
||||
restoreGeometry(s.value("geometry").toByteArray());
|
||||
}
|
||||
if (s.contains("splitter_state")) {
|
||||
if (s.contains(QStringLiteral("splitter_state"))) {
|
||||
ui_->splitter->restoreState(s.value("splitter_state").toByteArray());
|
||||
}
|
||||
else {
|
||||
|
@ -300,7 +301,7 @@ void AlbumCoverManager::LoadGeometry() {
|
|||
|
||||
void AlbumCoverManager::SaveSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("geometry", saveGeometry());
|
||||
s.setValue("splitter_state", ui_->splitter->saveState());
|
||||
|
@ -397,7 +398,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) {
|
|||
display_text = album_info.album;
|
||||
}
|
||||
else {
|
||||
display_text = album_info.album_artist + " - " + album_info.album;
|
||||
display_text = album_info.album_artist + QStringLiteral(" - ") + album_info.album;
|
||||
}
|
||||
|
||||
AlbumItem *album_item = new AlbumItem(icon_nocover_item_, display_text, ui_->albums);
|
||||
|
@ -413,7 +414,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) {
|
|||
album_item->setToolTip(album_info.album);
|
||||
}
|
||||
else {
|
||||
album_item->setToolTip(album_info.album_artist + " - " + album_info.album);
|
||||
album_item->setToolTip(album_info.album_artist + QStringLiteral(" - ") + album_info.album);
|
||||
}
|
||||
|
||||
album_item->setData(Role_ArtEmbedded, album_info.art_embedded);
|
||||
|
@ -497,7 +498,7 @@ bool AlbumCoverManager::ShouldHide(const AlbumItem &album_item, const QString &f
|
|||
return false;
|
||||
}
|
||||
|
||||
QStringList query = filter.split(' ');
|
||||
QStringList query = filter.split(QLatin1Char(' '));
|
||||
for (const QString &s : query) {
|
||||
bool in_text = album_item.text().contains(s, Qt::CaseInsensitive);
|
||||
bool in_albumartist = album_item.data(Role_AlbumArtist).toString().contains(s, Qt::CaseInsensitive);
|
||||
|
@ -558,7 +559,7 @@ void AlbumCoverManager::UpdateStatusText() {
|
|||
.arg(fetch_statistics_.missing_images_);
|
||||
|
||||
if (fetch_statistics_.bytes_transferred_ > 0) {
|
||||
message += ", " + tr("%1 transferred").arg(Utilities::PrettySize(fetch_statistics_.bytes_transferred_));
|
||||
message += QStringLiteral(", ") + tr("%1 transferred").arg(Utilities::PrettySize(fetch_statistics_.bytes_transferred_));
|
||||
}
|
||||
|
||||
statusBar()->showMessage(message);
|
||||
|
@ -632,7 +633,7 @@ Song AlbumCoverManager::AlbumItemAsSong(AlbumItem *album_item) {
|
|||
QString title = album_item->data(Role_Album).toString();
|
||||
QString artist_name = album_item->data(Role_AlbumArtist).toString();
|
||||
if (!artist_name.isEmpty()) {
|
||||
result.set_title(artist_name + " - " + title);
|
||||
result.set_title(artist_name + QStringLiteral(" - ") + title);
|
||||
}
|
||||
else {
|
||||
result.set_title(title);
|
||||
|
@ -876,13 +877,13 @@ SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex &idx) const {
|
|||
QSqlDatabase db(collection_backend_->db()->Connect());
|
||||
|
||||
CollectionQuery q(db, collection_backend_->songs_table(), collection_backend_->fts_table());
|
||||
q.SetColumnSpec("ROWID," + Song::kColumnSpec);
|
||||
q.AddWhere("album", idx.data(Role_Album).toString());
|
||||
q.SetOrderBy("disc, track, title");
|
||||
q.SetColumnSpec(Song::kRowIdColumnSpec);
|
||||
q.AddWhere(QStringLiteral("album"), idx.data(Role_Album).toString());
|
||||
q.SetOrderBy(QStringLiteral("disc, track, title"));
|
||||
|
||||
QString albumartist = idx.data(Role_AlbumArtist).toString();
|
||||
if (!albumartist.isEmpty()) {
|
||||
q.AddWhere("effective_albumartist", albumartist);
|
||||
q.AddWhere(QStringLiteral("effective_albumartist"), albumartist);
|
||||
}
|
||||
|
||||
q.AddCompilationRequirement(albumartist.isEmpty());
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
|
@ -57,7 +59,7 @@ QMimeData *AlbumCoverManagerList::mimeData(const QList<QListWidgetItem*> items)
|
|||
// Get URLs from the songs
|
||||
QList<QUrl> urls;
|
||||
urls.reserve(songs.count());
|
||||
for (const Song &song : songs) {
|
||||
for (const Song &song : std::as_const(songs)) {
|
||||
urls << song.url();
|
||||
}
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ void AlbumCoverSearcher::SearchFinished(const quint64 id, const CoverProviderSea
|
|||
|
||||
QStandardItem *item = new QStandardItem;
|
||||
item->setIcon(no_cover_icon_);
|
||||
item->setText(result.artist + " - " + result.album);
|
||||
item->setText(result.artist + QStringLiteral(" - ") + result.album);
|
||||
item->setData(result.image_url, Role_ImageURL);
|
||||
item->setData(new_id, Role_ImageRequestId);
|
||||
item->setData(false, Role_ImageFetchFinished);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QFile>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
|
@ -64,7 +66,7 @@ void CoverExportRunnable::ProcessAndExportCover() {
|
|||
QImage image;
|
||||
QString extension;
|
||||
|
||||
for (const AlbumCoverLoaderOptions::Type cover_type : cover_types_) {
|
||||
for (const AlbumCoverLoaderOptions::Type cover_type : std::as_const(cover_types_)) {
|
||||
switch (cover_type) {
|
||||
case AlbumCoverLoaderOptions::Type::Unset:
|
||||
if (song_.art_unset()) {
|
||||
|
@ -76,7 +78,7 @@ void CoverExportRunnable::ProcessAndExportCover() {
|
|||
if (song_.art_embedded() && dialog_result_.export_embedded_) {
|
||||
image = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song_.url().toLocalFile());
|
||||
if (!image.isNull()) {
|
||||
extension = "jpg";
|
||||
extension = QStringLiteral("jpg");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -84,7 +86,7 @@ void CoverExportRunnable::ProcessAndExportCover() {
|
|||
if (dialog_result_.export_downloaded_ && song_.art_manual_is_valid()) {
|
||||
const QString cover_path = song_.art_manual().toLocalFile();
|
||||
if (image.load(cover_path)) {
|
||||
extension = cover_path.section('.', -1);
|
||||
extension = cover_path.section(QLatin1Char('.'), -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -92,7 +94,7 @@ void CoverExportRunnable::ProcessAndExportCover() {
|
|||
if (dialog_result_.export_downloaded_ && song_.art_automatic_is_valid()) {
|
||||
const QString cover_path = song_.art_automatic().toLocalFile();
|
||||
if (image.load(cover_path)) {
|
||||
extension = cover_path.section('.', -1);
|
||||
extension = cover_path.section(QLatin1Char('.'), -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -110,8 +112,8 @@ void CoverExportRunnable::ProcessAndExportCover() {
|
|||
image = image.scaled(QSize(dialog_result_.width_, dialog_result_.height_), Qt::IgnoreAspectRatio);
|
||||
}
|
||||
|
||||
QString cover_dir = song_.url().toLocalFile().section('/', 0, -2);
|
||||
QString new_file = cover_dir + '/' + dialog_result_.filename_ + '.' + (song_.art_embedded() ? "jpg" : extension);
|
||||
QString cover_dir = song_.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
|
||||
QString new_file = cover_dir + QLatin1Char('/') + dialog_result_.filename_ + QLatin1Char('.') + (song_.art_embedded() ? QStringLiteral("jpg") : extension);
|
||||
|
||||
// If the file exists, do not override!
|
||||
if (dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode::None && QFile::exists(new_file)) {
|
||||
|
@ -156,7 +158,7 @@ void CoverExportRunnable::ExportCover() {
|
|||
QString cover_path;
|
||||
bool embedded_cover = false;
|
||||
|
||||
for (const AlbumCoverLoaderOptions::Type cover_type : cover_types_) {
|
||||
for (const AlbumCoverLoaderOptions::Type cover_type : std::as_const(cover_types_)) {
|
||||
switch (cover_type) {
|
||||
case AlbumCoverLoaderOptions::Type::Unset:
|
||||
if (song_.art_unset()) {
|
||||
|
@ -169,7 +171,7 @@ void CoverExportRunnable::ExportCover() {
|
|||
image = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song_.url().toLocalFile());
|
||||
if (!image.isNull()) {
|
||||
embedded_cover = true;
|
||||
extension = "jpg";
|
||||
extension = QStringLiteral("jpg");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -177,7 +179,7 @@ void CoverExportRunnable::ExportCover() {
|
|||
if (dialog_result_.export_downloaded_ && song_.art_manual_is_valid()) {
|
||||
cover_path = song_.art_manual().toLocalFile();
|
||||
if (image.load(cover_path)) {
|
||||
extension = cover_path.section('.', -1);
|
||||
extension = cover_path.section(QLatin1Char('.'), -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -185,7 +187,7 @@ void CoverExportRunnable::ExportCover() {
|
|||
if (dialog_result_.export_downloaded_ && song_.art_automatic_is_valid()) {
|
||||
cover_path = song_.art_automatic().toLocalFile();
|
||||
if (image.load(cover_path)) {
|
||||
extension = cover_path.section('.', -1);
|
||||
extension = cover_path.section(QLatin1Char('.'), -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -198,8 +200,8 @@ void CoverExportRunnable::ExportCover() {
|
|||
return;
|
||||
}
|
||||
|
||||
QString cover_dir = song_.url().toLocalFile().section('/', 0, -2);
|
||||
QString new_file = cover_dir + '/' + dialog_result_.filename_ + '.' + extension;
|
||||
QString cover_dir = song_.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
|
||||
QString new_file = cover_dir + QLatin1Char('/') + dialog_result_.filename_ + QLatin1Char('.') + extension;
|
||||
|
||||
// If the file exists, do not override!
|
||||
if (dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode::None && QFile::exists(new_file)) {
|
||||
|
|
|
@ -56,7 +56,7 @@ CoverFromURLDialog::~CoverFromURLDialog() {
|
|||
AlbumCoverImageResult CoverFromURLDialog::Exec() {
|
||||
|
||||
// reset state
|
||||
ui_->url->setText("");
|
||||
ui_->url->setText(QLatin1String(""));
|
||||
last_album_cover_ = AlbumCoverImageResult();
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
|
@ -30,6 +32,7 @@
|
|||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/settings.h"
|
||||
#include "coverprovider.h"
|
||||
#include "coverproviders.h"
|
||||
|
||||
|
@ -51,14 +54,14 @@ void CoverProviders::ReloadSettings() {
|
|||
|
||||
QMap<int, QString> all_providers;
|
||||
QList<CoverProvider*> old_providers = cover_providers_.keys();
|
||||
for (CoverProvider *provider : old_providers) {
|
||||
for (CoverProvider *provider : std::as_const(old_providers)) {
|
||||
if (!provider->is_enabled()) continue;
|
||||
all_providers.insert(provider->order(), provider->name());
|
||||
}
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(CoversSettingsPage::kSettingsGroup);
|
||||
QStringList providers_enabled = s.value(CoversSettingsPage::kProviders, QStringList() << all_providers.values()).toStringList();
|
||||
const QStringList providers_enabled = s.value(CoversSettingsPage::kProviders, QStringList() << all_providers.values()).toStringList();
|
||||
s.endGroup();
|
||||
|
||||
int i = 0;
|
||||
|
@ -73,7 +76,7 @@ void CoverProviders::ReloadSettings() {
|
|||
}
|
||||
|
||||
old_providers = cover_providers_.keys();
|
||||
for (CoverProvider *provider : old_providers) {
|
||||
for (CoverProvider *provider : std::as_const(old_providers)) {
|
||||
if (!new_providers.contains(provider)) {
|
||||
provider->set_enabled(false);
|
||||
provider->set_order(++i);
|
||||
|
@ -84,7 +87,7 @@ void CoverProviders::ReloadSettings() {
|
|||
|
||||
CoverProvider *CoverProviders::ProviderByName(const QString &name) const {
|
||||
|
||||
QList<CoverProvider*> cover_providers = cover_providers_.keys();
|
||||
const QList<CoverProvider*> cover_providers = cover_providers_.keys();
|
||||
for (CoverProvider *provider : cover_providers) {
|
||||
if (provider->name() == name) return provider;
|
||||
}
|
||||
|
|