Commit fc97b2b6 authored by Matthieu Gallien's avatar Matthieu Gallien 🎵
Browse files

basic working feedback for the user when creating/editing radios

parent 0c1a7d1f
......@@ -26,6 +26,7 @@ set(elisaLib_SOURCES
models/alltracksproxymodel.cpp
models/singlealbumproxymodel.cpp
models/trackmetadatamodel.cpp
models/editabletrackmetadatamodel.cpp
models/trackcontextmetadatamodel.cpp
models/viewsmodel.cpp
localFileConfiguration/elisaconfigurationdialog.cpp
......
......@@ -48,6 +48,7 @@
#include "models/datamodel.h"
#include "models/trackmetadatamodel.h"
#include "models/trackcontextmetadatamodel.h"
#include "models/editabletrackmetadatamodel.h"
#include "models/viewsmodel.h"
#include "models/gridviewproxymodel.h"
#include "models/alltracksproxymodel.h"
......@@ -124,6 +125,7 @@ void ElisaQmlTestPlugin::registerTypes(const char *uri)
qmlRegisterType<DataModel>(uri, 1, 0, "DataModel");
qmlRegisterType<TrackMetadataModel>(uri, 1, 0, "TrackMetadataModel");
qmlRegisterType<TrackContextMetaDataModel>(uri, 1, 0, "TrackContextMetaDataModel");
qmlRegisterType<EditableTrackMetadataModel>(uri, 1, 0, "EditableTrackMetadataModel");
qmlRegisterType<ViewsModel>(uri, 1, 0, "ViewsModel");
qmlRegisterType<GridViewProxyModel>(uri, 1, 0, "GridViewProxyModel");
qmlRegisterType<AllTracksProxyModel>(uri, 1, 0, "AllTracksProxyModel");
......
/*
* Copyright 2020 Matthieu Gallien <matthieu_gallien@yahoo.fr>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "editabletrackmetadatamodel.h"
#include <QDebug>
EditableTrackMetadataModel::EditableTrackMetadataModel(QObject *parent)
: TrackMetadataModel(parent)
{
}
bool EditableTrackMetadataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
auto result = TrackMetadataModel::setData(index, value, role);
if (result) {
if (!mIsDirty) {
mIsDirty = true;
Q_EMIT isDirtyChanged();
}
validData();
}
return result;
}
void EditableTrackMetadataModel::saveData()
{
mIsDirty = false;
Q_EMIT isDirtyChanged();
QString imageUrl = dataFromType(DataTypes::ImageUrlRole).toString();
if (!imageUrl.isEmpty()
&& !imageUrl.startsWith(QStringLiteral("http://"))
&& !imageUrl.startsWith(QStringLiteral("https://"))
&& !imageUrl.startsWith(QStringLiteral("file://"))) {
auto newTrackData = allTrackData();
newTrackData[DataTypes::ImageUrlRole] = QStringLiteral("file:/").append(imageUrl);
Q_EMIT saveRadioData(newTrackData);
} else {
Q_EMIT saveRadioData(allTrackData());
}
}
void EditableTrackMetadataModel::filterDataFromTrackData()
{
TrackMetadataModel::filterDataFromTrackData();
validData();
}
void EditableTrackMetadataModel::fillLyricsDataFromTrack()
{
TrackMetadataModel::fillLyricsDataFromTrack();
validData();
}
void EditableTrackMetadataModel::validData()
{
bool newValidState = true;
const auto &resourceData = dataFromType(TrackDataType::key_type::ResourceRole);
if (resourceData.canConvert<QUrl>()) {
const auto resourceUrl = resourceData.toUrl();
newValidState = !resourceUrl.scheme().isEmpty() && resourceUrl.isValid() && !resourceUrl.isRelative();
} else {
newValidState = false;
}
if (newValidState) {
const auto &titleData = dataFromType(TrackDataType::key_type::TitleRole);
newValidState = newValidState && !titleData.toString().isEmpty();
}
if (mIsDataValid != newValidState) {
mIsDataValid = newValidState;
Q_EMIT isDataValidChanged();
}
}
#include "moc_editabletrackmetadatamodel.cpp"
/*
* Copyright 2020 Matthieu Gallien <matthieu_gallien@yahoo.fr>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef EDITABLETRACKMETADATAMODEL_H
#define EDITABLETRACKMETADATAMODEL_H
#include "elisaLib_export.h"
#include "trackmetadatamodel.h"
class ELISALIB_EXPORT EditableTrackMetadataModel : public TrackMetadataModel
{
Q_OBJECT
Q_PROPERTY(bool isDataValid
READ isDataValid
NOTIFY isDataValidChanged)
Q_PROPERTY(bool isDirty
READ isDirty
NOTIFY isDirtyChanged)
public:
explicit EditableTrackMetadataModel(QObject *parent = nullptr);
bool isDataValid() const
{
return mIsDataValid;
}
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
bool isDirty() const
{
return mIsDirty;
}
Q_SIGNALS:
void isDataValidChanged();
void isDirtyChanged();
public Q_SLOTS:
void saveData();
protected:
void filterDataFromTrackData() override;
void fillLyricsDataFromTrack() override;
private:
void validData();
bool mIsDataValid = false;
bool mIsDirty = false;
};
#endif // EDITABLETRACKMETADATAMODEL_H
......@@ -278,7 +278,7 @@ QVariant TrackMetadataModel::data(const QModelIndex &index, int role) const
bool TrackMetadataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (data(index, role) != value) {
const auto dataType = mTrackKeys[index.row()];
auto dataType = mTrackKeys[index.row()];
mTrackData[dataType] = value;
mFullData[dataType] = value;
......@@ -414,6 +414,11 @@ void TrackMetadataModel::fillLyricsDataFromTrack()
endInsertRows();
}
const TrackMetadataModel::TrackDataType &TrackMetadataModel::allTrackData() const
{
return mTrackData;
}
void TrackMetadataModel::lyricsValueIsReady()
{
if (!mLyricsValueWatcher.result().isEmpty()) {
......@@ -503,14 +508,11 @@ void TrackMetadataModel::fillDataForNewRadio()
mTrackData.clear();
mTrackKeys.clear();
for (auto role : {
DataTypes::TitleRole,
DataTypes::ResourceRole,
DataTypes::CommentRole,
DataTypes::ImageUrlRole,
DataTypes::DatabaseIdRole
auto allRoles = {DataTypes::TitleRole, DataTypes::ResourceRole,
DataTypes::CommentRole, DataTypes::ImageUrlRole,
DataTypes::DatabaseIdRole};
}) {
for (auto role : allRoles) {
mTrackKeys.push_back(role);
if (role == DataTypes::DatabaseIdRole) {
mTrackData[role] = -1;
......@@ -545,19 +547,6 @@ void TrackMetadataModel::setDatabase(DatabaseInterface *trackDatabase)
initialize(nullptr, trackDatabase);
}
void TrackMetadataModel::saveData()
{
QString imageUrl = mTrackData[DataTypes::ImageUrlRole].toString();
if (!imageUrl.isEmpty()
&& !imageUrl.startsWith(QStringLiteral("http://"))
&& !imageUrl.startsWith(QStringLiteral("https://"))
&& !imageUrl.startsWith(QStringLiteral("file://"))) {
mTrackData[DataTypes::ImageUrlRole] = QStringLiteral("file:/").append(imageUrl);
}
Q_EMIT saveRadioData(mTrackData);
}
void TrackMetadataModel::deleteRadio()
{
if (mTrackData[DataTypes::DatabaseIdRole]>=0) {
......
......@@ -136,8 +136,6 @@ public Q_SLOTS:
void setDatabase(DatabaseInterface *trackDatabase);
void saveData();
void deleteRadio();
void radioData(const TrackMetadataModel::TrackDataType &radiosData);
......@@ -157,6 +155,8 @@ protected:
virtual void fillLyricsDataFromTrack();
const TrackDataType& allTrackData() const;
private Q_SLOTS:
void lyricsValueIsReady();
......
......@@ -56,8 +56,8 @@ RowLayout {
Loader {
id: textDisplayLoader
active: model.type === TrackMetadataModel.TextEntry || model.type === TrackMetadataModel.UrlEntry || model.type === TrackMetadataModel.IntegerEntry
visible: model.type === TrackMetadataModel.TextEntry || model.type === TrackMetadataModel.UrlEntry || model.type === TrackMetadataModel.IntegerEntry
active: model.type === EditableTrackMetadataModel.TextEntry || model.type === EditableTrackMetadataModel.UrlEntry || model.type === EditableTrackMetadataModel.IntegerEntry
visible: model.type === EditableTrackMetadataModel.TextEntry || model.type === EditableTrackMetadataModel.UrlEntry || model.type === EditableTrackMetadataModel.IntegerEntry
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
......@@ -69,26 +69,12 @@ RowLayout {
anchors.fill: parent
validator: ((model.type === TrackMetadataModel.UrlEntry) ? urlValidator : allValidator)
placeholderText: ((model.type === TrackMetadataModel.UrlEntry) ? 'https://' : '')
color: acceptableInput ? myPalette.text : 'red'
onTextEdited: {
if (model.display !== text) {
model.display = text
delegateRow.radioEdited()
}
}
RegExpValidator {
id: allValidator
regExp: /.*/
}
RegExpValidator {
id: urlValidator
regExp: /http[s]?:\/\/.+/
}
}
}
}
......@@ -22,6 +22,7 @@ import QtQuick.Window 2.2
import QtQml.Models 2.2
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import org.kde.kirigami 2.5 as Kirigami
import org.kde.elisa 1.0
Window {
......@@ -45,7 +46,7 @@ Window {
title: isCreation ? i18nc("Window title for track metadata", "Create a Radio") :
i18nc("Window title for track metadata", "View Details")
TrackMetadataModel {
EditableTrackMetadataModel {
id: realModel
manager: elisa.musicManager
......@@ -134,7 +135,6 @@ Window {
EditableMetaDataDelegate {
width: scrollBar.visible ? (!LayoutMirroring.enabled ? trackData.width - scrollBar.width : trackData.width) : trackData.width
onRadioEdited: applyButton.enabled = true
}
}
......@@ -172,6 +172,20 @@ Window {
}
}
Kirigami.InlineMessage {
id: formInvalidNotification
text: i18n("Data are not valid. Radio cannot be created or modified.")
type: Kirigami.MessageType.Error
showCloseButton: false
visible: !realModel.isDataValid
Layout.topMargin: 5
Layout.fillWidth: true
Layout.rightMargin: elisaTheme.layoutHorizontalMargin
Layout.leftMargin: elisaTheme.layoutHorizontalMargin
}
RowLayout {
spacing: elisaTheme.layoutVerticalMargin
......@@ -203,17 +217,17 @@ Window {
Button {
id: applyButton
enabled: realModel.isDataValid && realModel.isDirty
text: i18n("Apply")
DialogButtonBox.buttonRole: DialogButtonBox.ApplyRole
onClicked:
{
realModel.saveData()
enabled = false
if (!deleteButtonBox.visible && editableMetadata) {
deleteButtonBox.visible = true
}
}
enabled: false
}
Button {
text: i18n("Close")
......
......@@ -25,7 +25,7 @@ RowLayout {
id: delegateRow
spacing: 0
height: (model.type === TrackMetadataModel.LongTextEntry ? longTextDisplayLoader.height : (metaDataLabelMetric.boundingRect.height + elisaTheme.layoutVerticalMargin / 2))
height: (model.type === EditableTrackMetadataModel.LongTextEntry ? longTextDisplayLoader.height : (metaDataLabelMetric.boundingRect.height + elisaTheme.layoutVerticalMargin / 2))
TextMetrics {
id: metaDataLabelMetric
......@@ -51,8 +51,8 @@ RowLayout {
Loader {
id: textDisplayLoader
active: model.type === TrackMetadataModel.TextEntry || model.type === TrackMetadataModel.IntegerEntry
visible: model.type === TrackMetadataModel.TextEntry || model.type === TrackMetadataModel.IntegerEntry
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
......@@ -71,8 +71,8 @@ RowLayout {
Loader {
id: longTextDisplayLoader
active: model.type === TrackMetadataModel.LongTextEntry
visible: model.type === TrackMetadataModel.LongTextEntry
active: model.type === EditableTrackMetadataModel.LongTextEntry
visible: model.type === EditableTrackMetadataModel.LongTextEntry
Layout.fillWidth: true
Layout.maximumWidth: delegateRow.width - (0.8 * elisaTheme.coverImageSize + elisaTheme.layoutHorizontalMargin * 2)
......@@ -91,8 +91,8 @@ RowLayout {
}
Loader {
active: model.type === TrackMetadataModel.DateEntry
visible: model.type === TrackMetadataModel.DateEntry
active: model.type === EditableTrackMetadataModel.DateEntry
visible: model.type === EditableTrackMetadataModel.DateEntry
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
......@@ -110,8 +110,8 @@ RowLayout {
}
Loader {
active: model.type === TrackMetadataModel.RatingEntry
visible: model.type === TrackMetadataModel.RatingEntry
active: model.type === EditableTrackMetadataModel.RatingEntry
visible: model.type === EditableTrackMetadataModel.RatingEntry
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
......
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