Commit 9713eb29 authored by Tranter Madi's avatar Tranter Madi 🌧 Committed by Nate Graham
Browse files

Polish Now playing page

- Remove the redundant song, album, and artist names from the page, as they
  are always shown elsewhere too
- Use a two-column layout with separated metadata and lyrics when there's room,
  collapsing to a one-column layout with view switcher buttons when there's not
- Add an appropriate placeholder message when no lyrics are available
- Add an option to not show blurred album art background
parent 84747bb4
Pipeline #59873 passed with stage
in 8 minutes and 40 seconds
......@@ -11,6 +11,11 @@
</entry>
</group>
<group name="PlayerSettings">
<entry key="ShowNowPlayingBackground" type="Bool">
<default>
true
</default>
</entry>
<entry key="ShowProgressOnTaskBar" type="Bool" >
<default>
true
......
......@@ -338,6 +338,7 @@ void ElisaApplication::configChanged()
currentConfiguration->load();
currentConfiguration->read();
Q_EMIT showNowPlayingBackgroundChanged();
Q_EMIT showProgressOnTaskBarChanged();
Q_EMIT showSystemTrayIconChanged();
Q_EMIT embeddedViewChanged();
......@@ -586,6 +587,13 @@ ManageHeaderBar *ElisaApplication::manageHeaderBar() const
return d->mManageHeaderBar.get();
}
bool ElisaApplication::showNowPlayingBackground() const
{
auto currentConfiguration = Elisa::ElisaConfiguration::self();
return currentConfiguration->showNowPlayingBackground();
}
bool ElisaApplication::showProgressOnTaskBar() const
{
auto currentConfiguration = Elisa::ElisaConfiguration::self();
......
......@@ -78,6 +78,10 @@ class ELISALIB_EXPORT ElisaApplication : public QObject
READ manageHeaderBar
NOTIFY manageHeaderBarChanged)
Q_PROPERTY(bool showNowPlayingBackground
READ showNowPlayingBackground
NOTIFY showNowPlayingBackgroundChanged)
Q_PROPERTY(bool showProgressOnTaskBar
READ showProgressOnTaskBar
NOTIFY showProgressOnTaskBarChanged)
......@@ -125,6 +129,8 @@ public:
[[nodiscard]] ManageHeaderBar *manageHeaderBar() const;
[[nodiscard]] bool showNowPlayingBackground() const;
[[nodiscard]] bool showProgressOnTaskBar() const;
[[nodiscard]] bool showSystemTrayIcon() const;
......@@ -157,6 +163,8 @@ Q_SIGNALS:
void initializationDone();
void showNowPlayingBackgroundChanged();
void showProgressOnTaskBarChanged();
void showSystemTrayIconChanged();
......
......@@ -72,6 +72,7 @@ void ElisaConfigurationDialog::setRootPath(const QStringList &rootPath)
void ElisaConfigurationDialog::save()
{
Elisa::ElisaConfiguration::setRootPath(mRootPath);
Elisa::ElisaConfiguration::setShowNowPlayingBackground(mShowNowPlayingBackground);
Elisa::ElisaConfiguration::setShowProgressOnTaskBar(mShowProgressInTaskBar);
Elisa::ElisaConfiguration::setShowSystemTrayIcon(mShowSystemTrayIcon);
Elisa::ElisaConfiguration::setForceUsageOfFastFileSearch(!mForceUsageOfSlowFileSystemIndexing);
......@@ -120,6 +121,18 @@ void ElisaConfigurationDialog::cancel()
}
}
void ElisaConfigurationDialog::setShowNowPlayingBackground(bool showNowPlayingBackground)
{
if (mShowNowPlayingBackground == showNowPlayingBackground) {
return;
}
mShowNowPlayingBackground = showNowPlayingBackground;
Q_EMIT showNowPlayingBackgroundChanged();
setDirty();
}
void ElisaConfigurationDialog::setShowProgressInTaskBar(bool showProgressInTaskBar)
{
if (mShowProgressInTaskBar == showProgressInTaskBar) {
......@@ -213,6 +226,9 @@ void ElisaConfigurationDialog::configChanged()
mRootPath = Elisa::ElisaConfiguration::rootPath();
Q_EMIT rootPathChanged(mRootPath);
mShowNowPlayingBackground = Elisa::ElisaConfiguration::showNowPlayingBackground();
Q_EMIT showNowPlayingBackgroundChanged();
mShowProgressInTaskBar = Elisa::ElisaConfiguration::showProgressOnTaskBar();
Q_EMIT showProgressInTaskBarChanged();
......
......@@ -29,6 +29,12 @@ class ELISALIB_EXPORT ElisaConfigurationDialog : public QObject
WRITE setForceUsageOfSlowFileSystemIndexing
NOTIFY forceUsageOfSlowFileSystemIndexingChanged)
Q_PROPERTY(bool showNowPlayingBackground
READ showNowPlayingBackground
WRITE setShowNowPlayingBackground
NOTIFY showNowPlayingBackgroundChanged)
Q_PROPERTY(bool showProgressInTaskBar
READ showProgressInTaskBar
WRITE setShowProgressInTaskBar
......@@ -76,6 +82,12 @@ public:
return mIsDirty;
}
[[nodiscard]] bool showNowPlayingBackground() const
{
return mShowNowPlayingBackground;
}
[[nodiscard]] bool showProgressInTaskBar() const
{
return mShowProgressInTaskBar;
......@@ -120,6 +132,8 @@ Q_SIGNALS:
void isDirtyChanged();
void showNowPlayingBackgroundChanged();
void showProgressInTaskBarChanged();
void showSystemTrayIconChanged();
......@@ -142,6 +156,8 @@ public Q_SLOTS:
void cancel();
void setShowNowPlayingBackground(bool showNowPlayingBackground);
void setShowProgressInTaskBar(bool showProgressInTaskBar);
void setShowSystemTrayIcon(bool showSystemTrayIcon);
......@@ -170,6 +186,8 @@ private:
bool mIsDirty = false;
bool mShowNowPlayingBackground = true;
bool mShowProgressInTaskBar = true;
bool mShowSystemTrayIcon = false;
......
......@@ -392,6 +392,7 @@ Module {
isPointer: true
}
Property { name: "manageHeaderBar"; type: "ManageHeaderBar"; isReadonly: true; isPointer: true }
Property { name: "showNowPlayingBackground"; type: "bool"; isReadonly: true }
Property { name: "showProgressOnTaskBar"; type: "bool"; isReadonly: true }
Property { name: "showSystemTrayIcon"; type: "bool"; isReadonly: true }
Signal {
......@@ -453,6 +454,7 @@ Module {
exportMetaObjectRevisions: [0]
Property { name: "rootPath"; type: "QStringList" }
Property { name: "forceUsageOfFastFileSearch"; type: "bool" }
Property { name: "showNowPlayingBackground"; type: "bool" }
Property { name: "showProgressInTaskBar"; type: "bool" }
Property { name: "showSystemTrayIcon"; type: "bool" }
Property { name: "embeddedView"; type: "ElisaUtils::PlayListEntryType" }
......@@ -467,6 +469,10 @@ Module {
Parameter { name: "rootPath"; type: "QStringList" }
}
Method { name: "save" }
Method {
name: "setNowPlayingBackground"
Parameter { name: "showNowPlayingBackground"; type: "bool" }
}
Method {
name: "setShowProgressInTaskBar"
Parameter { name: "showProgressInTaskBar"; type: "bool" }
......
......@@ -19,7 +19,7 @@ Kirigami.Page {
property int databaseId: 0
property var trackType
property alias songTitle: titleLabel.text
property string songTitle: ''
property string albumName: ''
property string artistName: ''
property url albumArtUrl: ''
......@@ -62,7 +62,7 @@ Kirigami.Page {
Kirigami.Theme.colorSet: Kirigami.Theme.Window
RowLayout {
anchors.fill: parent
spacing: Kirigami.Units.largeSpacing
spacing: 0
FlatButtonWithToolTip {
id: showSidebarButton
......@@ -99,6 +99,39 @@ Kirigami.Page {
opacity: 0
}
ButtonGroup {
id: nowPlayingButtons
onCheckedButtonChanged: {
persistentSettings.nowPlayingPreferLyric = nowPlayingButtons.checkedButton === showLyricButton
}
}
FlatButtonWithToolTip {
id: showMetaDataButton
ButtonGroup.group: nowPlayingButtons
readonly property alias item: allMetaDataScroll
checkable: true
checked: !persistentSettings.nowPlayingPreferLyric
display: topItem.isWidescreen ? AbstractButton.TextBesideIcon : AbstractButton.IconOnly
icon.name: "documentinfo"
text: i18nc("One of the 'now playing' views", "Metadata")
visible: !contentLayout.wideMode
}
FlatButtonWithToolTip {
id: showLyricButton
ButtonGroup.group: nowPlayingButtons
readonly property alias item: lyricScroll
checkable: true
checked: persistentSettings.nowPlayingPreferLyric
display: topItem.isWidescreen ? AbstractButton.TextBesideIcon : AbstractButton.IconOnly
icon.name: "view-media-lyrics"
text: i18nc("One of the 'now playing' views", "Lyrics")
visible: !contentLayout.wideMode
}
FlatButtonWithToolTip {
id: showPlaylistButton
visible: Kirigami.Settings.isMobile
......@@ -116,177 +149,75 @@ Kirigami.Page {
}
}
// Container to hold both the blurred background and the scrollview
// We can't make the scrollview a child of the background item since then
// everything in the scrollview will be blurred and transparent too!
Item {
anchors.fill: parent
// Blurred album art background
Image {
id: albumArtBackground
Loader {
active: ElisaApplication.showNowPlayingBackground && !topItem.nothingPlaying
anchors.fill: parent
visible: !topItem.nothingPlaying
sourceComponent: Image {
id: albumArtBackground
anchors.fill: parent
source: albumArtUrl.toString() === '' ? Qt.resolvedUrl(elisaTheme.defaultAlbumImage) : albumArtUrl
source: albumArtUrl.toString() === '' ? Qt.resolvedUrl(elisaTheme.defaultAlbumImage) : albumArtUrl
sourceSize.width: topItem.width
sourceSize.height: topItem.height
sourceSize.width: topItem.width
sourceSize.height: topItem.height
asynchronous: true
asynchronous: true
fillMode: Image.PreserveAspectCrop
fillMode: Image.PreserveAspectCrop
layer.enabled: true
opacity: 0.2
layer.effect: FastBlur {
source: albumArtBackground
// anchors.fill: parent
radius: 40
layer.enabled: true
opacity: 0.2
layer.effect: FastBlur {
source: albumArtBackground
// anchors.fill: parent
radius: 40
}
}
}
// Scrollview to hold all the content
ScrollView {
id: scrollView
anchors.fill: parent
clip: true
RowLayout {
id: contentLayout
property bool wideMode: allMetaDataLoader.width <= width * 0.5
&& allMetaDataLoader.height <= height
anchors.fill: parent
visible: !topItem.nothingPlaying
contentHeight: content.height
// This Item holds only the content layout so we can center the
// ColumnLayout within it to provide appropriate margins. We
// can't do this if the ColumnLayout is directly inside the
// ScrollView
Item {
width: scrollView.width - scrollView.ScrollBar.vertical.width
// Layout holding the Title + metadata + lyrics labels
ColumnLayout {
id: content
anchors.top: parent.top
anchors.topMargin: Kirigami.Units.largeSpacing
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.largeSpacing * 2
anchors.right: parent.right
anchors.rightMargin: Kirigami.Units.largeSpacing * 2
// No bottom anchors so it can grow
// Grid layout to hold the song, artist, and album names
// This is so we can vertically align the icons
GridLayout {
id: gridlayout
Layout.minimumWidth: Kirigami.Units.gridUnit * 12
Layout.alignment: Qt.AlignHCenter
columns: 2
// Row 1: Song stuff
// -----------------
// Column 1: Song icon
Image {
source: "image://icon/view-media-track"
Layout.preferredWidth: sourceSize.width
Layout.preferredHeight: sourceSize.height
sourceSize {
width: Kirigami.Units.iconSizes.smallMedium
height: Kirigami.Units.iconSizes.smallMedium
}
}
// Column 2: Song title
LabelWithToolTip {
id: titleLabel
Layout.maximumWidth: gridlayout.width
Layout.alignment: Qt.AlignLeft
spacing: 0
level: 1
// Metadata
ScrollView {
id: allMetaDataScroll
elide: Text.ElideNone
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignLeft
}
implicitWidth: {
if (contentLayout.wideMode) {
return contentLayout.width * 0.5
} else {
return showMetaDataButton.checked? contentLayout.width : 0
}
}
// Row 2: Artist stuff
// -----------------
// Column 1: Artist icon
Image {
source: "image://icon/view-media-artist"
visible: artistName !== ''
Layout.preferredWidth: sourceSize.width
Layout.preferredHeight: sourceSize.height
sourceSize {
width: Kirigami.Units.iconSizes.smallMedium
height: Kirigami.Units.iconSizes.smallMedium
}
}
// Column 2: Artist name
Kirigami.LinkButton {
Layout.maximumWidth: gridlayout.width
Layout.alignment: Qt.AlignLeft
text: artistName !== '' ? artistName : ""
opacity: 0.6
visible: artistName !== ''
elide: Text.ElideNone
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignLeft
font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.20)
font.bold: true
color: Kirigami.Theme.textColor
onClicked: {
openArtist();
}
}
implicitHeight: Math.min(allMetaDataLoader.height, parent.height)
// Row 3: Album stuff
// -----------------
// Column 1: Album icon
Image {
source: "image://icon/view-media-album-cover"
visible: albumName !== ''
Layout.preferredWidth: sourceSize.width
Layout.preferredHeight: sourceSize.height
sourceSize {
width: Kirigami.Units.iconSizes.smallMedium
height: Kirigami.Units.iconSizes.smallMedium
}
}
// Column 2: Album name
Kirigami.LinkButton {
Layout.maximumWidth: gridlayout.width
Layout.alignment: Qt.AlignLeft
text: albumName !== '' ? albumName : ""
opacity: 0.6
visible: albumName !== ''
elide: Text.ElideNone
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignLeft
font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.20)
font.bold: true
color: Kirigami.Theme.textColor
onClicked: {
openAlbum();
}
}
}
contentWidth: implicitWidth
contentHeight: allMetaDataLoader.height
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
// Horizontal line separating title and subtitle from metadata
Kirigami.Separator {
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing * 5
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing * 5
Layout.bottomMargin: Kirigami.Units.largeSpacing
}
Loader {
id: allMetaDataLoader
// Metadata
Kirigami.FormLayout {
id: allMetaData
property real margins: Kirigami.Units.largeSpacing + allMetaDataScroll.ScrollBar.vertical.width
width: (implicitWidth + margins <= contentLayout.width * 0.5 ? contentLayout.width * 0.5 : contentLayout.width) - margins
x: (parent.width - width) * 0.5
Layout.fillWidth: true
sourceComponent: Kirigami.FormLayout {
id: allMetaData
Repeater {
id: trackData
......@@ -295,41 +226,79 @@ Kirigami.Page {
delegate: RowLayout {
Kirigami.FormData.label: "<b>" + model.name + ":</b>"
MediaTrackMetadataDelegate {
Layout.maximumWidth: contentLayout.width - allMetaDataLoader.margins
index: model.index
name: model.name
display: model.display
type: model.type
readOnly: true
Layout.fillWidth: true
}
}
}
}
// Horizontal line separating metadata from lyrics
Kirigami.Separator {
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing * 5
Layout.rightMargin: Kirigami.Units.largeSpacing * 5
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.bottomMargin: Kirigami.Units.largeSpacing
// We need unload Kirigami.FormLayout and recreate it
// to avoid lots of warnings in the terminal
Timer {
id: resetTimer
interval: 0
onTriggered: {
allMetaDataLoader.active = true
}
}
Connections {
target: metaDataModel
function onModelAboutToBeReset() {
allMetaDataLoader.active = false
}
function onModelReset() {
resetTimer.restart()
}
}
}
}
// Lyric
ScrollView {
id: lyricScroll
visible: metaDataModel.lyrics !== ""
implicitWidth: {
if (contentLayout.wideMode) {
return contentLayout.width * 0.5
} else {
return showLyricButton.checked? contentLayout.width : 0
}
}
// Lyrics
Label {
text: metaDataModel.lyrics
implicitHeight: Math.min(lyricItem.height, parent.height)
wrapMode: Text.WordWrap
contentWidth: implicitWidth
contentHeight: lyricItem.height
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
horizontalAlignment: Label.AlignHCenter
// Lyrics
Item {
id: lyricItem
property real margins: Kirigami.Units.largeSpacing + lyricScroll.ScrollBar.vertical.width
width: lyricScroll.width - margins
height: lyricLabel.visible? lyricLabel.height : lyricPlaceholder.height
x: Kirigami.Units.largeSpacing
Layout.fillWidth: true
Layout.bottomMargin: Kirigami.Units.largeSpacing * 2
visible: metaDataModel.lyrics !== ""
Label {
id: lyricLabel
text: metaDataModel.lyrics
wrapMode: Text.WordWrap
horizontalAlignment: contentLayout.wideMode? Text.AlignLeft : Text.AlignHCenter
visible: text !== ""
width: parent.width
}
Kirigami.PlaceholderMessage {
id: lyricPlaceholder
visible: !lyricLabel.visible
text: i18n("No lyrics found")
icon.name: "view-media-lyrics"
width: parent.width
}
}
}
......
......@@ -138,6 +138,8 @@ Kirigami.ApplicationWindow {
property bool showPlaylist: true
property bool headerBarIsMaximized: false
property bool nowPlayingPreferLyric: false
}
Connections {
......
......@@ -17,7 +17,7 @@ RowLayout {
property string name
property int index
property var type
property string display
property var display
property bool isRemovable
property bool readOnly
......@@ -26,24 +26,27 @@ RowLayout {
signal edited()
signal deleteField()
Layout.maximumWidth: Infinity
Loader {
id: textDisplayLoader
active: readOnly && (type === EditableTrackMetadataModel.TextEntry || type === EditableTrackMetadataModel.IntegerEntry
|| type === EditableTrackMetadataModel.UrlEntry || type === EditableTrackMetadataModel.DurationEntry)
active: readOnly && (type === EditableTrackMetadataModel.TextEntry || type === EditableTrackMetadataModel.IntegerEntry || type === EditableTrackMetadataModel.UrlEntry || type === EditableTrackMetadataModel.DurationEntry) && typeof display !== "undefined"
visible: active
Layout.maximumWidth: Math.min(Kirigami.Units.gridUnit * 20, parent.Layout.maximumWidth)
sourceComponent: LabelWithToolTip {
text: display
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
wrapMode: Text.WordWrap
}
}
Loader {
id: longTextDisplayLoader
active: readOnly && (type === EditableTrackMetadataModel.LongTextEntry)
active: readOnly && (type === EditableTrackMetadataModel.LongTextEntry) && typeof display !== "undefined"
visible: active
Layout.maximumWidth: Kirigami.Units.gridUnit * 20
Layout.maximumWidth: Math.min(Kirigami.Units.gridUnit * 20, parent.Layout.maximumWidth)
sourceComponent: Label {
text: display
......@@ -54,11 +57,12 @@ RowLayout {
}
Loader {
active: readOnly && (type === EditableTrackMetadataModel.DateEntry)
active: readOnly && (type === EditableTrackMetadataModel.DateEntry) && typeof display !== "undefined"
visible: active