Commit 6089288a authored by Nate Graham's avatar Nate Graham
Browse files

Optional "favorite" style ratings

This commit adds an optional and off-by-default mode to display ratings
as "favorite"/"not favorite" rather than zero to five stars. This
supports people whose rating habits lead them to rate certain songs
with five stars but never use the 1, 2, 3, or 4 star ratings. In this
style, you're basically using the rating system to mark your favorite
songs rather than really rating them. This new mode makes that a bit
more natural for people who prefer that style.

In terms of implementation, when using this mode, songs with 5 stars are
considered to be "favorite" songs, and songs with any other rating are
considered to be "not favorite". Marking a song as a favorite internally
sets it to 5 stars, and it will appear as a 5-star song in other apps.

Note that I have used the existing star-style "rating" and
"rating-unrated" icons for this mode due to the absence of an adequate
pair of filled/unfilled heart icons in the Breeze icon theme. If those
are later added, it could be swit...
parent afcbfca2
Pipeline #87007 passed with stage
in 7 minutes and 54 seconds
......@@ -31,7 +31,12 @@
false
</default>
</entry>
</group>
<entry key="UseFavoriteStyleRatings" type="Bool" >
<default>
false
</default>
</entry>
</group>
<group name="Views">
<entry key="EmbeddedView" type="Enum">
<choices>
......
......@@ -624,6 +624,13 @@ bool ElisaApplication::showSystemTrayIcon() const
return currentConfiguration->showSystemTrayIcon();
}
bool ElisaApplication::useFavoriteStyleRatings() const
{
auto currentConfiguration = Elisa::ElisaConfiguration::self();
return currentConfiguration->useFavoriteStyleRatings();
}
ElisaUtils::PlayListEntryType ElisaApplication::embeddedView() const
{
ElisaUtils::PlayListEntryType result = ElisaUtils::Unknown;
......
......@@ -90,6 +90,10 @@ class ELISALIB_EXPORT ElisaApplication : public QObject
READ showSystemTrayIcon
NOTIFY showSystemTrayIconChanged)
Q_PROPERTY(bool useFavoriteStyleRatings
READ useFavoriteStyleRatings
NOTIFY useFavoriteStyleRatingsChanged)
Q_PROPERTY(QAbstractItemModel* colorSchemesModel
READ colorSchemesModel
CONSTANT)
......@@ -135,6 +139,8 @@ public:
[[nodiscard]] bool showSystemTrayIcon() const;
[[nodiscard]] bool useFavoriteStyleRatings() const;
[[nodiscard]] ElisaUtils::PlayListEntryType embeddedView() const;
int initialViewIndex() const;
......@@ -169,6 +175,8 @@ Q_SIGNALS:
void showSystemTrayIconChanged();
void useFavoriteStyleRatingsChanged();
void commitDataRequest(QSessionManager &manager);
void embeddedViewChanged();
......
......@@ -78,6 +78,7 @@ void ElisaConfigurationDialog::save()
Elisa::ElisaConfiguration::setForceUsageOfFastFileSearch(!mForceUsageOfSlowFileSystemIndexing);
Elisa::ElisaConfiguration::setPlayAtStartup(mPlayAtStartup);
Elisa::ElisaConfiguration::setColorScheme(mColorScheme);
Elisa::ElisaConfiguration::setUseFavoriteStyleRatings(mUseFavoriteStyleRatings);
Elisa::ElisaConfiguration::setEmbeddedView(Elisa::ElisaConfiguration::EnumEmbeddedView::NoView);
switch (mEmbeddedView)
......@@ -215,6 +216,17 @@ void ElisaConfigurationDialog::setColorScheme(const QString &scheme)
setDirty();
}
void ElisaConfigurationDialog::setUseFavoriteStyleRatings(bool useFavoriteStyleRatings)
{
if (mUseFavoriteStyleRatings == useFavoriteStyleRatings) {
return;
}
mUseFavoriteStyleRatings = useFavoriteStyleRatings;
Q_EMIT useFavoriteStyleRatingsChanged();
setDirty();
}
void ElisaConfigurationDialog::removeMusicLocation(QString location)
{
mRootPath.removeAll(location);
......@@ -241,6 +253,9 @@ void ElisaConfigurationDialog::configChanged()
mColorScheme = Elisa::ElisaConfiguration::colorScheme();
Q_EMIT colorSchemeChanged();
mUseFavoriteStyleRatings = Elisa::ElisaConfiguration::useFavoriteStyleRatings();
Q_EMIT useFavoriteStyleRatingsChanged();
mForceUsageOfSlowFileSystemIndexing = !Elisa::ElisaConfiguration::forceUsageOfFastFileSearch();
Q_EMIT forceUsageOfSlowFileSystemIndexingChanged();
......
......@@ -69,6 +69,11 @@ Q_PROPERTY(bool showNowPlayingBackground
WRITE setColorScheme
NOTIFY colorSchemeChanged)
Q_PROPERTY(bool useFavoriteStyleRatings
READ useFavoriteStyleRatings
WRITE setUseFavoriteStyleRatings
NOTIFY useFavoriteStyleRatingsChanged)
public:
explicit ElisaConfigurationDialog(QObject *parent = nullptr);
......@@ -123,6 +128,11 @@ public:
return mColorScheme;
}
[[nodiscard]] bool useFavoriteStyleRatings() const
{
return mUseFavoriteStyleRatings;
}
Q_INVOKABLE void removeMusicLocation(QString location);
......@@ -148,6 +158,8 @@ Q_SIGNALS:
void colorSchemeChanged();
void useFavoriteStyleRatingsChanged();
public Q_SLOTS:
void setRootPath(const QStringList &rootPath);
......@@ -172,6 +184,8 @@ public Q_SLOTS:
void setColorScheme(const QString &scheme);
void setUseFavoriteStyleRatings(bool useFavoriteStyleRatings);
private Q_SLOTS:
void configChanged();
......@@ -196,6 +210,8 @@ private:
bool mPlayAtStartup = false;
bool mUseFavoriteStyleRatings = false;
QString mColorScheme;
ElisaUtils::PlayListEntryType mEmbeddedView = ElisaUtils::Unknown;
......
......@@ -279,6 +279,27 @@ FocusScope {
onClicked: callOpenMetaDataView(trackUrl, dataType)
}
FlatButtonWithToolTip {
visible: ElisaApplication.useFavoriteStyleRatings
text: rating == 10 ? i18n("Un-mark this song as a favorite") : i18n("Mark this song as a favorite")
icon.name: rating == 10 ? "rating" : "rating-unrated"
onClicked: {
var newRating = 0;
if (rating == 10) {
newRating = 0;
// Change icon immediately in case backend is slow
icon.name = "rating-unrated";
} else {
newRating = 10;
// Change icon immediately in case backend is slow
icon.name = "rating";
}
trackRatingChanged(trackUrl, newRating);
}
}
FlatButtonWithToolTip {
id: enqueueButton
height: singleLineHeight
......@@ -305,7 +326,7 @@ FocusScope {
// ratings (desktop)
RatingStar {
id: ratingWidget
visible: !Kirigami.Settings.isMobile
visible: !Kirigami.Settings.isMobile && !ElisaApplication.useFavoriteStyleRatings
readOnly: false
starRating: rating
......@@ -318,6 +339,17 @@ FocusScope {
trackRatingChanged(trackUrl, starRating);
}
}
Kirigami.Icon {
visible: !Kirigami.Settings.isMobile && ElisaApplication.useFavoriteStyleRatings && !hoverLoader.active && rating == 10
implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
source: "rating"
}
LabelWithToolTip {
id: durationLabel
......@@ -381,6 +413,21 @@ FocusScope {
text: i18nc("Show track metadata", "View details")
}
MobileContextMenuEntry {
visible: ElisaApplication.useFavoriteStyleRatings
onClicked: {
var newRating = 0;
if (rating == 10) {
newRating = 0;
} else {
newRating = 10;
}
contextMenu.close();
}
icon: rating == 10 ? "rating-unrated" : "rating"
text: rating == 10 ? i18n("Mark this song as no longer being a favorite", "Un-mark as favorite") : i18n("Mark this song as a favorite", "Mark as favorite")
}
MobileContextMenuEntry {
onClicked: {
enqueue();
......@@ -393,6 +440,8 @@ FocusScope {
RatingStar {
id: ratingWidgetMobile
visible: !ElisaApplication.useFavoriteStyleRatings
starRating: rating
Layout.alignment: Qt.AlignHCenter
......
......@@ -103,22 +103,52 @@ RowLayout {
active: type === EditableTrackMetadataModel.RatingEntry && typeof display !== "undefined"
visible: active
sourceComponent: RatingStar {
starRating: display
sourceComponent: ElisaApplication.useFavoriteStyleRatings ? favoriteButton : ratingStars
readOnly: false
Component {
id: ratingStars
hoverWidgetOpacity: 1
RatingStar {
starRating: delegateRow.display
anchors.verticalCenter: parent.verticalCenter
height: Kirigami.Units.gridUnit
readOnly: false
onRatingEdited: {
if (display !== starRating) {
display = starRating
ElisaApplication.musicManager.updateSingleFileMetaData(url, DataTypes.RatingRole, starRating)
edited()
hoverWidgetOpacity: 1
anchors.verticalCenter: parent.verticalCenter
height: Kirigami.Units.gridUnit
onRatingEdited: {
if (display !== starRating) {
display = starRating
ElisaApplication.musicManager.updateSingleFileMetaData(url, DataTypes.RatingRole, starRating)
edited()
}
}
}
}
Component {
id: favoriteButton
FlatButtonWithToolTip {
text: delegateRow.display == 10 ? i18n("Un-mark this song as a favorite") : i18n("Mark this song as a favorite")
icon.name: delegateRow.display == 10 ? "rating" : "rating-unrated"
onClicked: {
var newRating = 0;
if (delegateRow.display == 10) {
newRating = 0;
// Change icon immediately in case backend is slow
icon.name = "rating-unrated";
} else {
newRating = 10;
// Change icon immediately in case backend is slow
icon.name = "rating";
}
ElisaApplication.musicManager.updateSingleFileMetaData(url, DataTypes.RatingRole, newRating)
edited()
}
}
}
......
......@@ -365,21 +365,36 @@ Item {
},
Item {
width: Kirigami.Units.largeSpacing
visible: showRating
visible: showRating && !ElisaApplication.useFavoriteStyleRatings
},
LabelWithToolTip {
text: i18n("Filter by rating: ")
visible: showRating
visible: showRating && !ElisaApplication.useFavoriteStyleRatings
},
RatingStar {
id: ratingFilter
objectName: 'ratingFilter'
visible: showRating
visible: showRating && !ElisaApplication.useFavoriteStyleRatings
hoverWidgetOpacity: 1
readOnly: false
},
Button {
visible: showRating && ElisaApplication.useFavoriteStyleRatings
text: i18n("Limit to Favorited Songs")
icon.name: "rating"
checkable: true
checked: ratingFilter.starRating == 10
onToggled: {
if (checked) {
ratingFilter.starRating = 10;
} else {
ratingFilter.starRating = 0;
}
}
}
]
}
......
......@@ -209,15 +209,42 @@ BasePlayListDelegate {
id: ratingButton
objectName: 'ratingButton'
visible: !ElisaApplication.useFavoriteStyleRatings
enabled: isValid
text: i18nc("Show track rating", "Set track rating")
icon.name: "view-media-favorite"
onClicked: {
playListEntry.editingRating = true;
}
}
FlatButtonWithToolTip {
id: favoriteButton
objectName: 'favoriteButton'
visible: ElisaApplication.useFavoriteStyleRatings
enabled: isValid
text: rating == 10 ? i18n("Un-mark this song as a favorite") : i18n("Mark this song as a favorite")
icon.name: rating == 10 ? "rating" : "rating-unrated"
onClicked: {
var newRating = 0;
if (rating == 10) {
newRating = 0;
// Change icon immediately in case backend is slow
icon.name = "rating-unrated";
} else {
newRating = 10;
// Change icon immediately in case backend is slow
icon.name = "rating";
}
ElisaApplication.musicManager.updateSingleFileMetaData(playListEntry.fileName, DataTypes.RatingRole, newRating);
}
}
FlatButtonWithToolTip {
id: playPauseButton
......@@ -264,15 +291,23 @@ BasePlayListDelegate {
readOnly: false
starRating: rating
visible: playListEntry.editingRating || (rating > 0 && !containsMouse && !isSelected && !playListEntry.activeFocus && !simpleMode)
visible: playListEntry.editingRating || (rating > 0 && !containsMouse && !isSelected && !playListEntry.activeFocus && !simpleMode && !ElisaApplication.useFavoriteStyleRatings)
onRatingEdited: {
ElisaApplication.musicManager.updateSingleFileMetaData(playListEntry.fileName, DataTypes.RatingRole, starRating);
playListEntry.editingRating = false;
}
}
Kirigami.Icon {
visible: rating == 10 && !containsMouse && !isSelected && !playListEntry.activeFocus && !simpleMode && ElisaApplication.useFavoriteStyleRatings
implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: "rating"
}
LabelWithToolTip {
id: durationLabel
......
......@@ -65,6 +65,35 @@ ColumnLayout {
Accessible.onPressAction: onToggled
}
Item {
Kirigami.FormData.isSection: true
}
QQC2.ButtonGroup { id: ratingStyleGroup }
QQC2.RadioButton {
Kirigami.FormData.label: i18n("Song rating style:")
text: i18n("0-5 stars")
QQC2.ButtonGroup.group: ratingStyleGroup
checked: !ElisaConfigurationDialog.useFavoriteStyleRatings
onToggled: ElisaConfigurationDialog.useFavoriteStyleRatings = !checked
Accessible.onToggleAction: onToggled
Accessible.onPressAction: onToggled
}
QQC2.RadioButton {
text: i18n("Favorite/not favorite")
QQC2.ButtonGroup.group: ratingStyleGroup
checked: ElisaConfigurationDialog.useFavoriteStyleRatings
onToggled: ElisaConfigurationDialog.useFavoriteStyleRatings = checked
Accessible.onToggleAction: onToggled
Accessible.onPressAction: onToggled
}
// select colour scheme (mobile only, since desktop has it in the application menu)
QQC2.Button {
visible: Kirigami.Settings.isMobile
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment