diff --git a/autotests/qmltests/tst_NavigationActionBar.qml b/autotests/qmltests/tst_NavigationActionBar.qml
index 245c0100..da2a3fdc 100644
--- a/autotests/qmltests/tst_NavigationActionBar.qml
+++ b/autotests/qmltests/tst_NavigationActionBar.qml
@@ -1,300 +1,298 @@
/*
* Copyright 2018 Alexander Stippich .
*/
import QtQuick 2.3
import QtTest 1.0
import "../../src/qml"
FocusScope {
Item {
id: persistentSettings
property bool expandedFilterView: false
}
function i18nc(string1,string2) {
return string2
}
function i18n(string) {
return string;
}
Item {
id: elisaTheme
property int layoutHorizontalMargin: 8
property int layoutVerticalMargin: 6
- property int ratingStarSize: 15
- property int navigationBarHeight: 100
- property int smallControlButtonSize: 22
+ property int ratingStarSize: 16
}
SystemPalette {
id: myPalette
colorGroup: SystemPalette.Active
}
NavigationActionBar {
id: navigationActionBar1
mainTitle: 'testTitle1'
secondaryTitle: 'secondaryTitle1'
enableGoBack: true
allowArtistNavigation: true
showRating: true
expandedFilterView: persistentSettings.expandedFilterView
height: 100
}
NavigationActionBar {
id: navigationActionBar2
mainTitle: 'testTitle2'
secondaryTitle: 'secondaryTitle2'
enableGoBack: false
allowArtistNavigation: false
showRating: false
expandedFilterView: persistentSettings.expandedFilterView
height: 100
y: 200
}
TestCase {
name: "TestNavigationActionBar"
SignalSpy {
id: enqueueSpy1
target: navigationActionBar1
signalName: "enqueue"
}
SignalSpy {
id: enqueueSpy2
target: navigationActionBar2
signalName: "enqueue"
}
SignalSpy {
id: replaceAndPlaySpy1
target: navigationActionBar1
signalName: "replaceAndPlay"
}
SignalSpy {
id: replaceAndPlaySpy2
target: navigationActionBar2
signalName: "replaceAndPlay"
}
SignalSpy {
id: goBackSpy1
target: navigationActionBar1
signalName: "goBack"
}
SignalSpy {
id: goBackSpy2
target: navigationActionBar2
signalName: "goBack"
}
SignalSpy {
id: showArtistSpy1
target: navigationActionBar1
signalName: "showArtist"
}
SignalSpy {
id: showArtistSpy2
target: navigationActionBar2
signalName: "showArtist"
}
when: windowShown
function init() {
enqueueSpy1.clear();
enqueueSpy2.clear();
replaceAndPlaySpy1.clear();
replaceAndPlaySpy2.clear();
goBackSpy1.clear();
goBackSpy2.clear();
showArtistSpy1.clear();
showArtistSpy2.clear();
persistentSettings.expandedFilterView = false;
}
function test_goBack() {
compare(enqueueSpy1.count, 0);
compare(enqueueSpy2.count, 0);
compare(replaceAndPlaySpy1.count, 0);
compare(replaceAndPlaySpy2.count, 0);
compare(goBackSpy1.count, 0);
compare(goBackSpy2.count, 0);
compare(showArtistSpy1.count, 0);
compare(showArtistSpy2.count, 0);
var goPreviousButtonItem1 = findChild(navigationActionBar1, "goPreviousButton");
verify(goPreviousButtonItem1 !== null, "valid goPreviousButton")
mouseClick(goPreviousButtonItem1);
wait(200)
compare(goBackSpy1.count, 1);
var goPreviousButtonItem2 = findChild(navigationActionBar2, "goPreviousButton");
verify(goPreviousButtonItem2 !== null, "valid goPreviousButton")
mouseClick(goPreviousButtonItem2);
wait(200)
compare(goBackSpy2.count, 0);
}
function test_enqueue() {
compare(enqueueSpy1.count, 0);
compare(enqueueSpy2.count, 0);
compare(replaceAndPlaySpy1.count, 0);
compare(replaceAndPlaySpy2.count, 0);
compare(goBackSpy1.count, 0);
compare(goBackSpy2.count, 0);
compare(showArtistSpy1.count, 0);
compare(showArtistSpy2.count, 0);
var enqueueButtonItem = findChild(navigationActionBar1, "enqueueButton");
verify(enqueueButtonItem !== null, "valid enqueueButton")
mouseClick(enqueueButtonItem);
compare(enqueueSpy1.count, 1);
}
function test_filterState() {
compare(enqueueSpy1.count, 0);
compare(enqueueSpy2.count, 0);
compare(replaceAndPlaySpy1.count, 0);
compare(replaceAndPlaySpy2.count, 0);
compare(goBackSpy1.count, 0);
compare(goBackSpy2.count, 0);
compare(showArtistSpy1.count, 0);
compare(showArtistSpy2.count, 0);
var showFilterButtonItem1 = findChild(navigationActionBar1, "showFilterButton");
verify(showFilterButtonItem1 !== null, "valid showFilterButton")
mouseClick(showFilterButtonItem1);
compare(navigationActionBar1.state,'expanded')
var showFilterButtonItem2 = findChild(navigationActionBar2, "showFilterButton");
verify(showFilterButtonItem2 !== null, "valid showFilterButton")
mouseClick(showFilterButtonItem2);
compare(navigationActionBar2.expandedFilterView, false)
compare(navigationActionBar2.state, 'collapsed')
}
function test_replaceAndPlay() {
compare(enqueueSpy1.count, 0);
compare(enqueueSpy2.count, 0);
compare(replaceAndPlaySpy1.count, 0);
compare(replaceAndPlaySpy2.count, 0);
compare(goBackSpy1.count, 0);
compare(goBackSpy2.count, 0);
compare(showArtistSpy1.count, 0);
compare(showArtistSpy2.count, 0);
var replaceAndPlayButtonItem = findChild(navigationActionBar1, "replaceAndPlayButton");
verify(replaceAndPlayButtonItem !== null, "valid replaceAndPlayButton")
mouseClick(replaceAndPlayButtonItem);
compare(replaceAndPlaySpy1.count, 1);
}
function test_showArtist() {
compare(enqueueSpy1.count, 0);
compare(enqueueSpy2.count, 0);
compare(replaceAndPlaySpy1.count, 0);
compare(replaceAndPlaySpy2.count, 0);
compare(goBackSpy1.count, 0);
compare(goBackSpy2.count, 0);
compare(showArtistSpy1.count, 0);
compare(showArtistSpy2.count, 0);
var showArtistButtonItem1 = findChild(navigationActionBar1, "showArtistButton");
verify(showArtistButtonItem1 !== null, "valid showArtistButton")
mouseClick(showArtistButtonItem1);
compare(showArtistSpy1.count, 1);
var showArtistButtonItem2 = findChild(navigationActionBar2, "showArtistButton");
verify(showArtistButtonItem2 !== null, "valid showArtistButton")
mouseClick(showArtistButtonItem2);
compare(showArtistSpy2.count, 0);
}
function test_filterRating() {
persistentSettings.expandedFilterView = true;
wait(200);
var ratingFilterItem1 = findChild(navigationActionBar1, "ratingFilter");
verify(ratingFilterItem1 !== null, "valid ratingFilter")
mouseClick(ratingFilterItem1,1);
compare(navigationActionBar1.filterRating, 2);
mouseClick(ratingFilterItem1,1);
compare(navigationActionBar1.filterRating, 0);
mouseClick(ratingFilterItem1,1 + elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 4);
mouseClick(ratingFilterItem1,1 + elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 0);
mouseClick(ratingFilterItem1,1 + 2 * elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 6);
mouseClick(ratingFilterItem1,1 + 2 * elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 0);
mouseClick(ratingFilterItem1,1 + 3 * elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 8);
mouseClick(ratingFilterItem1,1 + 3 * elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 0);
mouseClick(ratingFilterItem1,1 + 4 * elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 10);
mouseClick(ratingFilterItem1,1 + 4 * elisaTheme.ratingStarSize);
compare(navigationActionBar1.filterRating, 0);
var ratingFilterItem2 = findChild(navigationActionBar2, "ratingFilter");
verify(ratingFilterItem2 !== null, "valid ratingFilter")
mouseClick(ratingFilterItem2,1);
compare(navigationActionBar2.filterRating, 0);
mouseClick(ratingFilterItem2,1 + elisaTheme.ratingStarSize);
compare(navigationActionBar2.filterRating, 0);
mouseClick(ratingFilterItem2,1 + 2 * elisaTheme.ratingStarSize);
compare(navigationActionBar2.filterRating, 0);
mouseClick(ratingFilterItem2,1 + 3 * elisaTheme.ratingStarSize);
compare(navigationActionBar2.filterRating, 0);
mouseClick(ratingFilterItem2,1 + 4 * elisaTheme.ratingStarSize);
compare(navigationActionBar2.filterRating, 0);
}
function test_filterText() {
navigationActionBar1.expandedFilterView = true
navigationActionBar2.expandedFilterView = false
wait(300)
var textsFilterItem1 = findChild(navigationActionBar1, "filterTextInput");
verify(textsFilterItem1 !== null, "valid filterTextInput")
textsFilterItem1.focus = false
compare(textsFilterItem1.focus, false);
mouseClick(textsFilterItem1);
compare(textsFilterItem1.focus, true);
keyClick(Qt.Key_T);
keyClick(Qt.Key_E);
keyClick(Qt.Key_S);
keyClick(Qt.Key_T);
compare(navigationActionBar1.filterText, 'test');
wait(300)
mouseClick(textsFilterItem1,textsFilterItem1.width - 20);
compare(navigationActionBar1.filterText, "");
}
}
}
diff --git a/autotests/qmltests/tst_PlayListEntry.qml b/autotests/qmltests/tst_PlayListEntry.qml
index 2a1e7083..11eaf080 100644
--- a/autotests/qmltests/tst_PlayListEntry.qml
+++ b/autotests/qmltests/tst_PlayListEntry.qml
@@ -1,124 +1,122 @@
/*
* Copyright 2018 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.3
import QtTest 1.0
import "../../src/qml"
import org.kde.elisa 1.0
Item {
height: 50
width: 300
PlayListEntry {
id: playListEntry
height: 50
width: 300
isAlternateColor: false
isSingleDiscAlbum: false
title: "hello"
isValid: true
isPlaying: MediaPlayList.IsPaused
isSelected: true
containsMouse: false
function i18nc() {
return ""
}
SystemPalette {
id: myPalette
}
Item {
id: elisaTheme
property int layoutHorizontalMargin: 8
- property int ratingStarSize: 15
property int playListDelegateHeight: 28
- property int smallControlButtonSize: 22
}
}
TestCase {
name: "TestPlayListEntry"
SignalSpy {
id: startPlaybackSpy
target: playListEntry
signalName: "startPlayback"
}
SignalSpy {
id: pausePlaybackSpy
target: playListEntry
signalName: "pausePlayback"
}
SignalSpy {
id: removeFromPlaylistSpy
target: playListEntry
signalName: "removeFromPlaylist"
}
SignalSpy {
id: switchToTrackSpy
target: playListEntry
signalName: "switchToTrack"
}
when: windowShown
function init() {
startPlaybackSpy.clear();
pausePlaybackSpy.clear();
removeFromPlaylistSpy.clear();
switchToTrackSpy.clear();
}
function test_playnow_click() {
compare(startPlaybackSpy.count, 0);
compare(pausePlaybackSpy.count, 0);
compare(removeFromPlaylistSpy.count, 0);
compare(switchToTrackSpy.count, 0);
playListEntry.forceActiveFocus();
compare(startPlaybackSpy.count, 0);
compare(pausePlaybackSpy.count, 0);
compare(removeFromPlaylistSpy.count, 0);
compare(switchToTrackSpy.count, 0);
var playPauseButtonItem = findChild(playListEntry, "playPauseButton");
verify(playPauseButtonItem !== null, "valid playPauseButton")
mouseMove(playPauseButtonItem, playPauseButtonItem.width / 2, playPauseButtonItem.height / 2);
wait(300);
mouseClick(playPauseButtonItem);
compare(startPlaybackSpy.count, 1);
compare(pausePlaybackSpy.count, 0);
compare(removeFromPlaylistSpy.count, 0);
compare(switchToTrackSpy.count, 1);
}
}
}
diff --git a/src/qml/BaseTheme.qml b/src/qml/BaseTheme.qml
index 3b35f203..a51e3dab 100644
--- a/src/qml/BaseTheme.qml
+++ b/src/qml/BaseTheme.qml
@@ -1,77 +1,74 @@
/*
* Copyright 2017 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.7
import QtQuick.Controls 2.2
Item {
property string defaultAlbumImage: 'image://icon/media-optical-audio'
property string defaultArtistImage: 'image://icon/view-media-artist'
property string defaultBackgroundImage: 'qrc:///background.png'
property string nowPlayingIcon: 'image://icon/view-media-lyrics'
property string artistIcon: 'image://icon/view-media-artist'
property string albumIcon: 'image://icon/view-media-album-cover'
property string albumCoverIcon: 'image://icon/media-optical-audio'
property string playlistIcon: 'image://icon/view-media-playlist'
property string tracksIcon: 'image://icon/view-media-track'
property string genresIcon: 'image://icon/view-media-genre'
property string clearIcon: 'image://icon/edit-clear'
property string recentlyPlayedTracksIcon: 'image://icon/media-playlist-play'
property string frequentlyPlayedTracksIcon: 'image://icon/view-media-playcount'
property string pausedIndicatorIcon: 'image://icon/media-playback-paused'
property string playingIndicatorIcon: 'image://icon/media-playback-playing'
property string ratingIcon: 'image://icon/rating'
property string ratingUnratedIcon: 'image://icon/rating-unrated'
property string errorIcon: 'image://icon/error'
property string folderIcon: 'image://icon/document-open-folder'
property int layoutHorizontalMargin: 8
property int layoutVerticalMargin: 6
property int playListAlbumArtSize: 60
property int coverImageSize: 180
property int contextCoverImageSize: 100
property int smallImageSize: 32
property int tooltipRadius: 3
property int shadowOffset: 2
property int delegateToolButtonSize: 34
- property int ratingStarSize: 15
-
property int mediaPlayerControlHeight: 42
property real mediaPlayerControlOpacity: 0.6
- property int smallControlButtonSize: 22
property int volumeSliderWidth: 100
property int dragDropPlaceholderHeight: 28
property int gridDelegateSize: 170
property int viewSelectorDelegateHeight: 24
property int headerToolbarHeight: 48
property int footerToolbarHeight: 30
property int viewSelectorSmallSizeThreshold: 800
Label {
id: fontSize
}
}
diff --git a/src/qml/FlatButtonWithToolTip.qml b/src/qml/FlatButtonWithToolTip.qml
index 6babd8fb..0e8ba635 100644
--- a/src/qml/FlatButtonWithToolTip.qml
+++ b/src/qml/FlatButtonWithToolTip.qml
@@ -1,46 +1,47 @@
/*
* Copyright 2018 Alexander Stippich
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 2.3
+import org.kde.kirigami 2.5 as Kirigami
import org.kde.elisa 1.0
Button {
id: flatButtonWithToolTip
activeFocusOnTab: true
Keys.onReturnPressed: flatButtonWithToolTip.clicked()
Accessible.onPressAction: flatButtonWithToolTip.clicked()
flat: true
display: AbstractButton.IconOnly
- icon.width: elisaTheme.smallControlButtonSize
- icon.height: elisaTheme.smallControlButtonSize
+ icon.width: Kirigami.Units.iconSizes.smallMedium
+ icon.height: Kirigami.Units.iconSizes.smallMedium
implicitWidth: icon.width + 16
implicitHeight: icon.height + 16
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: flatButtonWithToolTip.text
}
diff --git a/src/qml/HeaderBar.qml b/src/qml/HeaderBar.qml
index 5aee6dfb..9b3de9a0 100644
--- a/src/qml/HeaderBar.qml
+++ b/src/qml/HeaderBar.qml
@@ -1,428 +1,427 @@
/*
* Copyright 2016 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.2
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
FocusScope {
id: headerBar
property string title
property string artist
property string albumArtist
property string album
property string image
property string newImage
property string oldImage
property string tracksCount
property int trackRating
property int albumID
property bool ratingVisible
property alias playerControl: playControlItem
property alias isMaximized: playControlItem.isMaximized
property int imageSourceSize: 512
signal openArtist()
signal openAlbum()
signal openNowPlaying()
onImageChanged:
{
if (changeBackgroundTransition.running) {
changeBackgroundTransition.complete()
}
newImage = image
changeBackgroundTransition.start()
}
Item {
id: background
anchors.fill: parent
ImageWithFallback {
id: oldBackground
source: oldImage
fallback: elisaTheme.defaultBackgroundImage
asynchronous: true
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
sourceSize.width: imageSourceSize
opacity: 1
layer.enabled: true
layer.effect: HueSaturation {
cached: true
lightness: -0.5
saturation: 0.9
layer.enabled: true
layer.effect: GaussianBlur {
cached: true
radius: 256
deviation: 12
samples: 129
transparentBorder: false
}
}
}
ImageWithFallback {
id: newBackground
source: newImage
fallback: Qt.resolvedUrl(elisaTheme.defaultBackgroundImage)
asynchronous: true
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
sourceSize.width: imageSourceSize
visible: false
opacity: 0
layer.enabled: true
layer.effect: HueSaturation {
cached: true
lightness: -0.5
saturation: 0.9
layer.enabled: true
layer.effect: GaussianBlur {
cached: true
radius: 256
deviation: 12
samples: 129
transparentBorder: false
}
}
}
}
MediaPlayerControl {
id: playControlItem
focus: true
anchors.left: background.left
anchors.right: background.right
anchors.bottom: background.bottom
height: elisaTheme.mediaPlayerControlHeight
}
ColumnLayout {
id: contentZone
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: playControlItem.top
spacing: 0
RowLayout {
spacing: 0
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
Layout.fillHeight: true
Item {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.preferredHeight: contentZone.height * 0.9
Layout.minimumHeight: contentZone.height * 0.9
Layout.maximumHeight: contentZone.height * 0.9
Layout.preferredWidth: contentZone.height * 0.9
Layout.minimumWidth: contentZone.height * 0.9
Layout.maximumWidth: contentZone.height * 0.9
Layout.leftMargin: !LayoutMirroring.enabled ? contentZone.width * 0.15 : 0
Layout.rightMargin: LayoutMirroring.enabled ? contentZone.width * 0.15 : 0
ImageWithFallback {
id: oldMainIcon
anchors.fill: parent
asynchronous: true
mipmap: true
source: oldImage
fallback: Qt.resolvedUrl(elisaTheme.defaultAlbumImage)
sourceSize {
width: imageSourceSize
height: imageSourceSize
}
fillMode: Image.PreserveAspectFit
}
ImageWithFallback {
id: newMainIcon
anchors.fill: parent
asynchronous: true
mipmap: true
source: newImage
fallback: Qt.resolvedUrl(elisaTheme.defaultAlbumImage)
visible: false
opacity: 0
sourceSize {
width: imageSourceSize
height: imageSourceSize
}
fillMode: Image.PreserveAspectFit
}
}
ColumnLayout {
spacing: 0
Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.preferredHeight: contentZone.height * 0.9
Layout.minimumHeight: contentZone.height * 0.9
Layout.maximumHeight: contentZone.height * 0.9
Layout.fillWidth: true
LabelWithToolTip {
id: mainLabel
text: title
Layout.alignment: Qt.AlignLeft
elide: Text.ElideRight
// Hardcoded because the headerbar blur always makes a dark-ish
// background, so we don't want to use a color scheme color that
// might also be dark
color: "white"
level: 1
font.bold: true
Layout.bottomMargin: albumLabel.height * 0.5
MouseArea {
id: titleMouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
openNowPlaying()
}
}
}
LabelWithToolTip {
id: authorLabel
text: artist
Layout.alignment: Qt.AlignLeft
elide: Text.ElideRight
// Hardcoded because the headerbar blur always makes a dark-ish
// background, so we don't want to use a color scheme color that
// might also be dark
color: "white"
level: 3
MouseArea {
id: authorMouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
openArtist()
}
}
}
LabelWithToolTip {
id: albumLabel
text: album
Layout.alignment: Qt.AlignLeft
elide: Text.ElideRight
// Hardcoded because the headerbar blur always makes a dark-ish
// background, so we don't want to use a color scheme color that
// might also be dark
color: "white"
level: 3
MouseArea {
id: albumMouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
openAlbum()
}
}
}
RatingStar {
id: mainRating
visible: ratingVisible
- starSize: elisaTheme.ratingStarSize
starRating: trackRating
Layout.alignment: Qt.AlignLeft
}
Loader {
active: headerBar.isMaximized
visible: headerBar.isMaximized
sourceComponent:
SimplePlayListView {
id: playList
playListModel: elisa.mediaPlayList
anchors.fill: parent
}
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.topMargin: elisaTheme.layoutHorizontalMargin * 6
Layout.bottomMargin: elisaTheme.layoutHorizontalMargin * 2
Layout.leftMargin: elisaTheme.layoutHorizontalMargin * 7
Layout.rightMargin: elisaTheme.layoutHorizontalMargin * 2
}
}
}
}
LabelWithToolTip {
id: remainingTracksLabel
text: tracksCount > 0 ? i18np("1 track remaining", "%1 tracks remaining", tracksCount) : i18n("No remaining tracks")
elide: Text.ElideRight
visible: tracksCount >= 0
// Hardcoded because the headerbar blur always makes a dark-ish
// background, so we don't want to use a color scheme color that
// might also be dark
color: "white"
anchors.right: contentZone.right
anchors.bottom: contentZone.bottom
anchors.rightMargin: elisaTheme.layoutHorizontalMargin * 2
anchors.bottomMargin: elisaTheme.layoutHorizontalMargin * 2
}
SequentialAnimation {
id: changeBackgroundTransition
PropertyAction {
targets: [newBackground, newMainIcon]
property: 'opacity'
value: 0
}
PropertyAction {
targets: [newBackground, newMainIcon]
property: 'visible'
value: true
}
PropertyAction {
target: newBackground
property: "source"
value: (newImage ? newImage : Qt.resolvedUrl(elisaTheme.defaultBackgroundImage))
}
PropertyAction {
target: newMainIcon
property: "source"
value: (newImage ? newImage : Qt.resolvedUrl(elisaTheme.defaultAlbumImage))
}
ParallelAnimation {
NumberAnimation {
targets: [newBackground, newMainIcon, mainLabel, authorLabel, remainingTracksLabel, albumLabel]
property: 'opacity'
from: 0
to: 1
duration: 250
easing.type: Easing.Linear
}
NumberAnimation {
targets: [oldBackground, oldMainIcon]
property: 'opacity'
from: 1
to: 0
duration: 250
easing.type: Easing.Linear
}
}
PropertyAction {
target: headerBar
property: "oldImage"
value: image
}
PropertyAction {
target: oldBackground
property: 'source'
value: (headerBar.oldImage ? headerBar.oldImage : Qt.resolvedUrl(elisaTheme.defaultBackgroundImage))
}
PropertyAction {
target: oldMainIcon
property: 'source'
value: (headerBar.oldImage ? headerBar.oldImage : Qt.resolvedUrl(elisaTheme.defaultAlbumImage))
}
PropertyAction {
targets: [oldBackground, oldMainIcon]
property: 'opacity'
value: 1
}
PropertyAction {
targets: [newBackground, newMainIcon]
property: 'visible'
value: false
}
onStopped:
{
oldImage = newImage
}
}
}
diff --git a/src/qml/ListBrowserDelegate.qml b/src/qml/ListBrowserDelegate.qml
index 4846996b..20de6400 100644
--- a/src/qml/ListBrowserDelegate.qml
+++ b/src/qml/ListBrowserDelegate.qml
@@ -1,423 +1,421 @@
/*
* Copyright 2016-2017 Matthieu Gallien
* Copyright 2017 Alexander Stippich
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
import org.kde.elisa 1.0
FocusScope {
id: mediaTrack
property url trackUrl
property var dataType
property string title
property string artist
property string album
property string albumArtist
property string duration
property url imageUrl
property int trackNumber
property int discNumber
property int rating
property bool hideDiscNumber
property bool isSelected
property bool isAlternateColor
property bool detailedView: true
signal clicked()
signal enqueue(var url, var entryType, var name)
signal replaceAndPlay(var url, var entryType, var name)
signal callOpenMetaDataView(var url, var entryType)
Accessible.role: Accessible.ListItem
Accessible.name: title
Accessible.description: title
Keys.onReturnPressed: enqueue(trackUrl, dataType, title)
Keys.onEnterPressed: enqueue(trackUrl, dataType, title)
TextMetrics {
id: mainLabelSize
font: mainLabel.font
text: mainLabel.text
}
property int singleLineHeight: elisaTheme.layoutVerticalMargin * 2 + mainLabelSize.height
height: singleLineHeight + (detailedView ? mainLabelSize.height : 0)
Rectangle {
id: rowRoot
anchors.fill: parent
z: 1
color: (isAlternateColor ? myPalette.alternateBase : myPalette.base)
}
MouseArea {
id: hoverArea
anchors.fill: parent
z: 2
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onClicked: {
mediaTrack.clicked()
}
onDoubleClicked: enqueue(trackUrl, dataType, title)
RowLayout {
anchors.fill: parent
spacing: 0
LabelWithToolTip {
id: mainLabel
visible: !detailedView
text: {
if (trackNumber !== 0 && trackNumber !== -1 && trackNumber !== undefined) {
if (albumArtist !== undefined && artist !== albumArtist)
return i18nc("%1: track number. %2: track title. %3: artist name",
"%1 - %2 - %3",
trackNumber.toLocaleString(Qt.locale(), 'f', 0),
title, artist);
else
return i18nc("%1: track number. %2: track title.",
"%1 - %2",
trackNumber.toLocaleString(Qt.locale(), 'f', 0),
title);
} else {
if (albumArtist !== undefined && artist !== albumArtist)
return i18nc("%1: track title. %2: artist name",
"%1 - %2",
title, artist);
else
return i18nc("%1: track title",
"%1",
title);
}
}
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
color: myPalette.text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
Layout.leftMargin: {
if (!LayoutMirroring.enabled)
return (!hideDiscNumber ? elisaTheme.layoutHorizontalMargin * 4 : elisaTheme.layoutHorizontalMargin)
else
return 0
}
Layout.rightMargin: {
if (LayoutMirroring.enabled)
return (!hideDiscNumber ? elisaTheme.layoutHorizontalMargin * 4 : elisaTheme.layoutHorizontalMargin)
else
return 0
}
}
ImageWithFallback {
id: coverImageElement
Layout.preferredHeight: mediaTrack.height - elisaTheme.layoutVerticalMargin
Layout.preferredWidth: mediaTrack.height - elisaTheme.layoutVerticalMargin
Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutVerticalMargin : 0
Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutVerticalMargin : 0
Layout.alignment: Qt.AlignCenter
visible: detailedView
sourceSize.width: mediaTrack.height - elisaTheme.layoutVerticalMargin
sourceSize.height: mediaTrack.height - elisaTheme.layoutVerticalMargin
fillMode: Image.PreserveAspectFit
smooth: true
source: imageUrl
fallback: elisaTheme.defaultAlbumImage
asynchronous: true
layer.enabled: !usingFallback
layer.effect: DropShadow {
source: coverImageElement
radius: 10
spread: 0.1
samples: 21
color: myPalette.shadow
}
}
ColumnLayout {
visible: detailedView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
spacing: 0
LabelWithToolTip {
id: mainLabelDetailed
level: 4
text: {
if (trackNumber >= 0) {
return i18nc("%1: track number. %2: track title", "%1 - %2",
trackNumber.toLocaleString(Qt.locale(), 'f', 0), title);
} else {
return title;
}
}
horizontalAlignment: Text.AlignLeft
color: myPalette.text
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.fillWidth: true
Layout.topMargin: elisaTheme.layoutVerticalMargin / 2
elide: Text.ElideRight
}
Item {
Layout.fillHeight: true
}
LabelWithToolTip {
id: artistLabel
text: {
var labelText = ""
if (artist) {
labelText += artist
}
if (album !== '') {
labelText += ' - ' + album
if (!hideDiscNumber && discNumber !== -1) {
labelText += ' - CD ' + discNumber
}
}
return labelText;
}
horizontalAlignment: Text.AlignLeft
opacity: 0.6
color: myPalette.text
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.fillWidth: true
Layout.bottomMargin: elisaTheme.layoutVerticalMargin / 2
elide: Text.ElideRight
}
}
Loader {
id: hoverLoader
active: false
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.rightMargin: 10
z: 1
opacity: 0
sourceComponent: Row {
anchors.centerIn: parent
FlatButtonWithToolTip {
id: detailsButton
height: singleLineHeight
width: singleLineHeight
text: i18nc("Show track metadata", "View Details")
icon.name: "help-about"
onClicked: callOpenMetaDataView(trackUrl, dataType)
}
FlatButtonWithToolTip {
id: enqueueButton
height: singleLineHeight
width: singleLineHeight
text: i18nc("Enqueue current track", "Enqueue")
icon.name: "list-add"
onClicked: enqueue(trackUrl, dataType, title)
}
FlatButtonWithToolTip {
id: clearAndEnqueueButton
scale: LayoutMirroring.enabled ? -1 : 1
height: singleLineHeight
width: singleLineHeight
text: i18nc("Clear play list and enqueue current track", "Play Now and Replace Play List")
icon.name: "media-playback-start"
onClicked: replaceAndPlay(trackUrl, dataType, title)
}
}
}
RatingStar {
id: ratingWidget
- starSize: elisaTheme.ratingStarSize
-
starRating: rating
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.leftMargin: elisaTheme.layoutHorizontalMargin
Layout.rightMargin: elisaTheme.layoutHorizontalMargin
}
LabelWithToolTip {
id: durationLabel
text: duration
font.weight: Font.Light
color: myPalette.text
horizontalAlignment: Text.AlignRight
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.rightMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
Layout.leftMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0
}
}
}
states: [
State {
name: 'notSelected'
when: !mediaTrack.activeFocus && !hoverArea.containsMouse && !mediaTrack.isSelected
PropertyChanges {
target: hoverLoader
active: false
}
PropertyChanges {
target: hoverLoader
opacity: 0.0
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 0.0
}
PropertyChanges {
target: rowRoot
color: (isAlternateColor ? myPalette.alternateBase : myPalette.base)
}
PropertyChanges {
target: rowRoot
opacity: 1
}
},
State {
name: 'hovered'
when: !mediaTrack.activeFocus && hoverArea.containsMouse
PropertyChanges {
target: hoverLoader
active: true
}
PropertyChanges {
target: hoverLoader
opacity: 1.0
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 1.0
}
PropertyChanges {
target: rowRoot
color: myPalette.highlight
}
PropertyChanges {
target: rowRoot
opacity: 0.2
}
},
State {
name: 'selected'
when: !mediaTrack.activeFocus && mediaTrack.isSelected
PropertyChanges {
target: hoverLoader
active: false
}
PropertyChanges {
target: hoverLoader
opacity: 0.0
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 1.0
}
PropertyChanges {
target: rowRoot
color: myPalette.mid
}
PropertyChanges {
target: rowRoot
opacity: 1.
}
},
State {
name: 'focused'
when: mediaTrack.activeFocus
PropertyChanges {
target: hoverLoader
active: true
}
PropertyChanges {
target: hoverLoader
opacity: 1.0
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 1.0
}
PropertyChanges {
target: rowRoot
color: myPalette.highlight
}
PropertyChanges {
target: rowRoot
opacity: 0.6
}
}
]
}
diff --git a/src/qml/MetaDataDelegate.qml b/src/qml/MetaDataDelegate.qml
index dbc21a9d..4a6f9e0a 100644
--- a/src/qml/MetaDataDelegate.qml
+++ b/src/qml/MetaDataDelegate.qml
@@ -1,132 +1,131 @@
/*
* Copyright 2016 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
import org.kde.elisa 1.0
RowLayout {
id: delegateRow
spacing: 0
height: (model.type === EditableTrackMetadataModel.LongTextEntry ? longTextDisplayLoader.height : (metaDataLabelMetric.boundingRect.height + elisaTheme.layoutVerticalMargin / 2))
TextMetrics {
id: metaDataLabelMetric
text: 'Metadata Name'
}
Label {
id: metaDataLabels
text: i18nc("Label for a piece of metadata, e.g. 'Album Artist:'", "%1:", model.name)
font.weight: Font.Bold
horizontalAlignment: Text.AlignRight
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: 0.8 * elisaTheme.coverImageSize
Layout.rightMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0
Layout.leftMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0
}
Loader {
id: textDisplayLoader
active: model.type === EditableTrackMetadataModel.TextEntry || model.type === EditableTrackMetadataModel.IntegerEntry
visible: model.type === EditableTrackMetadataModel.TextEntry || model.type === EditableTrackMetadataModel.IntegerEntry
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
sourceComponent: LabelWithToolTip {
text: model.display
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
anchors.fill: parent
}
}
Loader {
id: longTextDisplayLoader
active: model.type === EditableTrackMetadataModel.LongTextEntry
visible: model.type === EditableTrackMetadataModel.LongTextEntry
Layout.fillWidth: true
Layout.maximumWidth: delegateRow.width - (0.8 * elisaTheme.coverImageSize + elisaTheme.layoutHorizontalMargin * 2)
Layout.alignment: Qt.AlignTop
sourceComponent: Label {
text: model.display
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
anchors.fill: parent
wrapMode: Text.WordWrap
}
}
Loader {
active: model.type === EditableTrackMetadataModel.DateEntry
visible: model.type === EditableTrackMetadataModel.DateEntry
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
sourceComponent: LabelWithToolTip {
text: rawDate.toLocaleDateString()
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
anchors.fill: parent
property date rawDate: new Date(model.display)
}
}
Loader {
active: model.type === EditableTrackMetadataModel.RatingEntry
visible: model.type === EditableTrackMetadataModel.RatingEntry
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
sourceComponent: RatingStar {
starRating: model.display
- starSize: elisaTheme.ratingStarSize
readOnly: true
anchors {
left: parent.left
top: parent.top
bottom: parent.bottom
}
}
}
}
diff --git a/src/qml/NavigationActionBar.qml b/src/qml/NavigationActionBar.qml
index 2141aed8..1b3be24c 100644
--- a/src/qml/NavigationActionBar.qml
+++ b/src/qml/NavigationActionBar.qml
@@ -1,240 +1,239 @@
/*
* Copyright 2016 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQml 2.2
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import org.kde.kirigami 2.8 as Kirigami
ColumnLayout {
id: navigationBar
spacing: 0
property string mainTitle
property string secondaryTitle
property url image
property bool allowArtistNavigation: false
property bool showEnqueueButton: true
property bool showCreateRadioButton
property string labelText
property bool showRating: true
property alias filterText: filterTextInput.text
property alias filterRating: ratingFilter.starRating
property bool enableGoBack: true
property bool expandedFilterView
property bool enableSorting: true
property bool sortOrder
signal enqueue();
signal replaceAndPlay();
signal createRadio();
signal goBack();
signal showArtist();
signal sort(var order);
HeaderFooterToolbar {
type: filterRow.visible? "other" : "header"
contentItems: [
FlatButtonWithToolTip {
id: goPreviousButton
objectName: 'goPreviousButton'
visible: enableGoBack
text: i18nc("navigate back in the views stack", "Back")
icon.name: (Qt.application.layoutDirection == Qt.RightToLeft) ? "go-next" : "go-previous"
onClicked: goBack()
},
Item {
id: spacer
Layout.preferredWidth: elisaTheme.layoutHorizontalMargin
visible: goPreviousButton.visible
},
Image {
id: mainIcon
source: image
Layout.preferredHeight: authorAndAlbumLayout.height
Layout.preferredWidth: height
sourceSize.height: height
sourceSize.width: width
fillMode: Image.PreserveAspectFit
asynchronous: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
},
Item {
Layout.preferredWidth: elisaTheme.layoutHorizontalMargin
visible: mainIcon.visible
},
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
id: authorAndAlbumLayout
LabelWithToolTip {
id: albumLabel
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
text: mainTitle
level: authorLabel.visible ? 4 : 1
font.weight: authorLabel.visible ? Font.Bold : Font.Normal
elide: Text.ElideRight
}
LabelWithToolTip {
id: authorLabel
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
text: secondaryTitle
elide: Text.ElideRight
visible: secondaryTitle !== ""
}
},
FlatButtonWithToolTip {
objectName: 'createRadioButton'
visible: showCreateRadioButton
text: i18nc("Create a new radio", "Create a radio")
icon.name: "media-track-add-amarok"
onClicked: createRadio()
},
FlatButtonWithToolTip {
objectName: 'enqueueButton'
visible: !showCreateRadioButton
text: i18nc("Add current list to playlist", "Enqueue")
icon.name: "list-add"
onClicked: enqueue()
},
FlatButtonWithToolTip {
objectName: 'replaceAndPlayButton'
visible: !showCreateRadioButton
text: i18n("Play now, replacing contents of Playlist")
icon.name: "media-playback-start"
onClicked: replaceAndPlay()
},
FlatButtonWithToolTip {
objectName: 'showArtistButton'
visible: allowArtistNavigation && !showCreateRadioButton
text: i18nc("Button to navigate to the artist of the album", "Display Artist")
icon.name: "view-media-artist"
onClicked: showArtist()
},
FlatButtonWithToolTip {
objectName: 'sortAscendingButton'
visible: enableSorting && !showCreateRadioButton
text: i18nc("Toggle between ascending and descending order", "Toggle sort order")
icon.name: sortOrder ? "view-sort-ascending" : "view-sort-descending"
onClicked: sortOrder ? sort(Qt.DescendingOrder) : sort(Qt.AscendingOrder)
},
FlatButtonWithToolTip {
objectName: 'showFilterButton'
visible: !showCreateRadioButton
text: !navigationBar.expandedFilterView ? i18nc("Show filters in the navigation bar", "Show Search Options") : i18nc("Hide filters in the navigation bar", "Hide Search Options")
icon.name: 'search'
checkable: true
checked: expandedFilterView
onClicked: persistentSettings.expandedFilterView = !persistentSettings.expandedFilterView
}
]
}
HeaderFooterToolbar {
type: "header"
id: filterRow
visible: opacity > 0.0
opacity: 0
contentItems: [
Kirigami.SearchField {
id: filterTextInput
objectName: 'filterTextInput'
Layout.fillWidth: true
focusSequence: ""
Accessible.role: Accessible.EditableText
placeholderText: i18n("Search for album name, artist, etc.")
Keys.onEscapePressed: persistentSettings.expandedFilterView = false;
},
Item {
width: elisaTheme.layoutHorizontalMargin
},
LabelWithToolTip {
text: i18n("Filter by rating: ")
visible: showRating
},
RatingStar {
id: ratingFilter
objectName: 'ratingFilter'
visible: showRating
hoverWidgetOpacity: 1
readOnly: false
- starSize: elisaTheme.ratingStarSize
}
]
}
states: [
State {
name: 'collapsed'
when: !expandedFilterView
PropertyChanges {
target: filterRow
opacity: 0.0
}
StateChangeScript {
// Focus main content view since that's probably what the user
// wants to interact with next
script: contentDirectoryView.forceActiveFocus();
}
},
State {
name: 'expanded'
when: expandedFilterView
PropertyChanges {
target: filterRow
opacity: 1.0
}
StateChangeScript {
script: filterTextInput.forceActiveFocus()
}
}
]
transitions: Transition {
from: "expanded,collapsed"
PropertyAnimation {
properties: "opacity"
easing.type: Easing.Linear
duration: 250
}
}
}
diff --git a/src/qml/PlayListEntry.qml b/src/qml/PlayListEntry.qml
index 82afc2e5..bdccaebe 100644
--- a/src/qml/PlayListEntry.qml
+++ b/src/qml/PlayListEntry.qml
@@ -1,394 +1,393 @@
/*
* Copyright 2016-2017 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
+import org.kde.kirigami 2.5 as Kirigami
import org.kde.elisa 1.0
FocusScope {
id: playListEntry
property var index
property bool isSingleDiscAlbum
property int isPlaying
property bool isSelected
property bool isValid
property bool isAlternateColor
property bool containsMouse
property int databaseId: 0
property var entryType
property string title
property string artist
property string album
property string albumArtist
property string duration
property url fileName
property url imageUrl
property int trackNumber
property int discNumber
property int rating
property bool hasValidDiscNumber: true
property int scrollBarWidth
property bool simpleMode: false
signal startPlayback()
signal pausePlayback()
signal removeFromPlaylist(var trackIndex)
signal switchToTrack(var trackIndex)
Accessible.role: Accessible.ListItem
Accessible.name: title + ' ' + album + ' ' + artist
TextMetrics {
id: mainCompactLabelSize
font: mainCompactLabel.font
text: mainCompactLabel.text
}
Keys.onReturnPressed: {
playListEntry.switchToTrack(playListEntry.index)
playListEntry.startPlayback()
}
height: mainCompactLabelSize.height + 2 * elisaTheme.layoutVerticalMargin
Loader {
id: metadataLoader
active: false
onLoaded: item.show()
sourceComponent: MediaTrackMetadataView {
fileName: playListEntry.fileName
showImage: entryType !== ElisaUtils.Radio
modelType: entryType
showTrackFileName: entryType !== ElisaUtils.Radio
showDeleteButton: entryType === ElisaUtils.Radio
showApplyButton: entryType === ElisaUtils.Radio
editableMetadata: entryType === ElisaUtils.Radio
onRejected: metadataLoader.active = false
}
}
Rectangle {
id: entryBackground
anchors.fill: parent
anchors.rightMargin: LayoutMirroring.enabled ? scrollBarWidth : 0
z: 1
color: simpleMode ? "transparent" : myPalette.base
height: playListEntry.height
}
RowLayout {
id: trackRow
z: 2
anchors.fill: parent
anchors.leftMargin: elisaTheme.layoutHorizontalMargin
anchors.rightMargin: LayoutMirroring.enabled ? scrollBarWidth : 0
spacing: elisaTheme.layoutHorizontalMargin / 4
// Container for the play/pause icon and the track/disc label
Item {
TextMetrics {
id: fakeLabel
text: '99/9'
}
Layout.minimumWidth: fakeLabel.width
Layout.preferredWidth: fakeLabel.width
Layout.maximumWidth: fakeLabel.width
Layout.preferredHeight: playListEntry.height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0
Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0
Image {
id: playIcon
anchors.centerIn: parent
source: (isPlaying === MediaPlayList.IsPlaying ?
Qt.resolvedUrl(elisaTheme.playingIndicatorIcon) : Qt.resolvedUrl(elisaTheme.pausedIndicatorIcon))
- width: elisaTheme.smallControlButtonSize
- height: elisaTheme.smallControlButtonSize
- sourceSize.width: elisaTheme.smallControlButtonSize
- sourceSize.height: elisaTheme.smallControlButtonSize
+ width: Kirigami.Units.iconSizes.smallMedium
+ height: Kirigami.Units.iconSizes.smallMedium
+ sourceSize.width: Kirigami.Units.iconSizes.smallMedium
+ sourceSize.height: Kirigami.Units.iconSizes.smallMedium
fillMode: Image.PreserveAspectFit
mirror: LayoutMirroring.enabled
layer.enabled: simpleMode
layer.effect: ColorOverlay {
cached: true
color: myPalette.highlightedText
}
visible: isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused
}
Label {
id: trackAndDiscNumberLabel
anchors.fill: parent
anchors.rightMargin: LayoutMirroring.enabled ? 0 : elisaTheme.layoutHorizontalMargin
anchors.leftMargin: !LayoutMirroring.enabled ? 0 : elisaTheme.layoutHorizontalMargin
horizontalAlignment: Text.AlignRight
text: {
var trackNumberString;
if (trackNumber !== -1) {
trackNumberString = Number(trackNumber).toLocaleString(Qt.locale(), 'f', 0);
} else {
trackNumberString = ''
}
if (!isSingleDiscAlbum && discNumber !== 0 ) {
return trackNumberString + "/" + Number(discNumber).toLocaleString(Qt.locale(), 'f', 0)
} else {
return trackNumberString
}
}
font.weight: (isPlaying ? Font.Bold : Font.Light)
color: simpleMode ? myPalette.highlightedText : myPalette.text
visible: isValid && !playIcon.visible
}
}
LabelWithToolTip {
id: mainCompactLabel
text: title
font.weight: (isPlaying ? Font.Bold : Font.Normal)
color: simpleMode ? myPalette.highlightedText : myPalette.text
Layout.maximumWidth: mainCompactLabel.implicitWidth + 1
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
visible: isValid
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
LabelWithToolTip {
id: mainInvalidCompactLabel
text: title
color: simpleMode ? myPalette.highlightedText : myPalette.text
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
visible: !isValid
elide: Text.ElideRight
}
Item {
Layout.fillWidth: true
Layout.preferredWidth: 0
}
Loader {
id: hoverLoader
active: false
visible: active
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
sourceComponent: Row {
anchors.centerIn: parent
enabled: isValid
FlatButtonWithToolTip {
id: infoButton
objectName: 'infoButton'
implicitHeight: playListEntry.height
implicitWidth: playListEntry.height
text: i18nc("Show track metadata", "View Details")
icon.name: "help-about"
onClicked: {
if (metadataLoader.active === false) {
metadataLoader.active = true
}
else {
metadataLoader.item.close();
metadataLoader.active = false
}
}
}
FlatButtonWithToolTip {
id: playPauseButton
objectName: 'playPauseButton'
implicitHeight: playListEntry.height
implicitWidth: playListEntry.height
scale: LayoutMirroring.enabled ? -1 : 1 // We can mirror the symmetrical pause icon
text: (isPlaying === MediaPlayList.IsPlaying) ? i18nc("Pause current track from play list", "Pause") : i18nc("Play this track from play list", "Play")
icon.name: (isPlaying === MediaPlayList.IsPlaying) ? "media-playback-pause" : "media-playback-start"
onClicked: if (isPlaying === MediaPlayList.IsPlaying) {
playListEntry.pausePlayback()
} else {
playListEntry.switchToTrack(playListEntry.index)
playListEntry.startPlayback()
}
}
FlatButtonWithToolTip {
id: removeButton
objectName: 'removeButton'
implicitHeight: playListEntry.height
implicitWidth: playListEntry.height
text: i18nc("Remove current track from play list", "Remove")
icon.name: "error"
onClicked: playListEntry.removeFromPlaylist(playListEntry.index)
}
}
}
RatingStar {
id: ratingWidget
starRating: rating
- starSize: elisaTheme.ratingStarSize
-
visible: rating > 0
}
LabelWithToolTip {
id: durationLabel
text: duration
font.weight: (isPlaying ? Font.Bold : Font.Normal)
color: simpleMode ? myPalette.highlightedText : myPalette.text
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.leftMargin: elisaTheme.layoutHorizontalMargin
Layout.rightMargin: elisaTheme.layoutHorizontalMargin
horizontalAlignment: Text.AlignRight
}
}
states: [
State {
name: 'notSelected'
when: !containsMouse && !isSelected && !playListEntry.activeFocus && !simpleMode
PropertyChanges {
target: hoverLoader
active: false
}
PropertyChanges {
target: entryBackground
color: (isAlternateColor ? myPalette.alternateBase : myPalette.base)
}
PropertyChanges {
target: entryBackground
opacity: 1.
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 0.0
}
},
State {
name: 'hovered'
when: containsMouse && !playListEntry.activeFocus && !simpleMode
PropertyChanges {
target: hoverLoader
active: true
}
PropertyChanges {
target: entryBackground
color: myPalette.highlight
}
PropertyChanges {
target: entryBackground
opacity: 0.2
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 1.0
}
},
State {
name: 'selected'
when: !playListEntry.activeFocus && isSelected && !simpleMode
PropertyChanges {
target: hoverLoader
active: false
}
PropertyChanges {
target: entryBackground
color: myPalette.mid
}
PropertyChanges {
target: entryBackground
opacity: 1.
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 1.0
}
},
State {
name: 'focused'
when: playListEntry.activeFocus && !simpleMode
PropertyChanges {
target: hoverLoader
active: true
}
PropertyChanges {
target: entryBackground
color: myPalette.highlight
}
PropertyChanges {
target: entryBackground
opacity: 0.6
}
PropertyChanges {
target: ratingWidget
hoverWidgetOpacity: 1.0
}
}
]
}
diff --git a/src/qml/RatingStar.qml b/src/qml/RatingStar.qml
index d8c14cf2..bcfecfee 100644
--- a/src/qml/RatingStar.qml
+++ b/src/qml/RatingStar.qml
@@ -1,89 +1,89 @@
/*
* Copyright 2016 Matthieu Gallien
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
+import org.kde.kirigami 2.5 as Kirigami
Row {
- property int starSize
property int starRating
property bool readOnly: true
property double hoverBrightness: 0.5
property double hoverContrast: 0.5
property double hoverWidgetOpacity: 0
property int hoveredRating: 0
spacing: 0
opacity: starRating > 0 ? 1 : (readOnly ? 0 : hoverWidgetOpacity)
Repeater {
model: 5
Item {
property int ratingThreshold: 2 + index * 2
- height: starSize
- width: starSize
+ height: Kirigami.Units.iconSizes.small
+ width: Kirigami.Units.iconSizes.small
Image {
- width: starSize
- height: starSize
+ width: Kirigami.Units.iconSizes.small
+ height: Kirigami.Units.iconSizes.small
anchors.centerIn: parent
- sourceSize.width: starSize
- sourceSize.height: starSize
+ sourceSize.width: Kirigami.Units.iconSizes.small
+ sourceSize.height: Kirigami.Units.iconSizes.small
fillMode: Image.PreserveAspectFit
layer.enabled: hoveredRating >= ratingThreshold
layer.effect: BrightnessContrast {
brightness: hoverBrightness
contrast: hoverContrast
}
source: if (starRating >= ratingThreshold || hoveredRating >= ratingThreshold)
Qt.resolvedUrl(elisaTheme.ratingIcon)
else
Qt.resolvedUrl(elisaTheme.ratingUnratedIcon)
opacity: if (starRating >= ratingThreshold || hoveredRating >= ratingThreshold)
1
else
0.7
}
MouseArea {
anchors.fill: parent
enabled: !readOnly
acceptedButtons: Qt.LeftButton
hoverEnabled: true
onClicked: if (starRating !== ratingThreshold) {
starRating = ratingThreshold
} else {
starRating = 0
}
onEntered: hoveredRating = ratingThreshold
onExited: hoveredRating = 0
}
}
}
}