diff --git a/models/tracks/tracksmodel.cpp b/models/tracks/tracksmodel.cpp index 5bfd4e7..e969e62 100644 --- a/models/tracks/tracksmodel.cpp +++ b/models/tracks/tracksmodel.cpp @@ -1,231 +1,248 @@ #include "tracksmodel.h" #include "db/collectionDB.h" TracksModel::TracksModel(QObject *parent) : BaseList(parent) { this->db = CollectionDB::getInstance(); connect(this, &TracksModel::queryChanged, this, &TracksModel::setList); } FMH::MODEL_LIST TracksModel::items() const { return this->list; } void TracksModel::setQuery(const QString &query) { if(this->query == query) return; this->query = query; qDebug()<< "setting query"<< this->query; emit this->queryChanged(); } QString TracksModel::getQuery() const { return this->query; } void TracksModel::setSortBy(const SORTBY &sort) { if(this->sort == sort) return; this->sort = sort; this->preListChanged(); this->sortList(); this->postListChanged(); emit this->sortByChanged(); } TracksModel::SORTBY TracksModel::getSortBy() const { return this->sort; } void TracksModel::sortList() { if(this->sort == TracksModel::SORTBY::NONE) return; const auto key = static_cast(this->sort); qDebug()<< "SORTING LIST BY"<< this->sort; qSort(this->list.begin(), this->list.end(), [key](const FMH::MODEL &e1, const FMH::MODEL &e2) -> bool { auto role = key; switch(role) { case FMH::MODEL_KEY::RELEASEDATE: case FMH::MODEL_KEY::RATE: case FMH::MODEL_KEY::FAV: { if(e1[role].toInt() > e2[role].toInt()) return true; break; } case FMH::MODEL_KEY::TRACK: { if(e1[role].toInt() < e2[role].toInt()) return true; break; } case FMH::MODEL_KEY::ADDDATE: { auto currentTime = QDateTime::currentDateTime(); auto date1 = QDateTime::fromString(e1[role], Qt::TextDate); auto date2 = QDateTime::fromString(e2[role], Qt::TextDate); if(date1.secsTo(currentTime) < date2.secsTo(currentTime)) return true; break; } case FMH::MODEL_KEY::TITLE: case FMH::MODEL_KEY::ARTIST: case FMH::MODEL_KEY::ALBUM: case FMH::MODEL_KEY::FORMAT: { const auto str1 = QString(e1[role]).toLower(); const auto str2 = QString(e2[role]).toLower(); if(str1 < str2) return true; break; } default: if(e1[role] < e2[role]) return true; } return false; }); } void TracksModel::setList() { emit this->preListChanged(); this->list = this->db->getDBData(this->query); qDebug()<< "my LIST" ; this->sortList(); emit this->postListChanged(); } QVariantMap TracksModel::get(const int &index) const { if(index >= this->list.size() || index < 0) return QVariantMap(); QVariantMap res; const auto item = this->list.at(index); for(auto key : item.keys()) res.insert(FMH::MODEL_NAME[key], item[key]); return res; } void TracksModel::append(const QVariantMap &item) { if(item.isEmpty()) return; emit this->preItemAppended(); FMH::MODEL model; for(auto key : item.keys()) model.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); qDebug() << "Appending item to list" << item; this->list << model; qDebug()<< this->list; emit this->postItemAppended(); } void TracksModel::append(const QVariantMap &item, const int &at) { if(item.isEmpty()) return; if(at > this->list.size() || at < 0) return; qDebug()<< "trying to append at" << at << item["title"]; emit this->preItemAppendedAt(at); FMH::MODEL model; for(auto key : item.keys()) model.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); this->list.insert(at, model); emit this->postItemAppended(); } void TracksModel::appendQuery(const QString &query) { if(this->query.isEmpty()) return; emit this->preListChanged(); this->list << this->db->getDBData(query); emit this->postListChanged(); } void TracksModel::clear() { emit this->preListChanged(); this->list.clear(); emit this->postListChanged(); } bool TracksModel::color(const int &index, const QString &color) { if(index >= this->list.size() || index < 0) return false; auto item = this->list[index]; if(this->db->colorTagTrack(item[FMH::MODEL_KEY::URL], color)) { this->list[index][FMH::MODEL_KEY::COLOR] = color; emit this->updateModel(index, {FMH::MODEL_KEY::COLOR}); return true; } return false; } bool TracksModel::fav(const int &index, const bool &value) { if(index >= this->list.size() || index < 0) return false; auto item = this->list[index]; if(this->db->favTrack(item[FMH::MODEL_KEY::URL], value)) { this->list[index][FMH::MODEL_KEY::FAV] = value ? "1" : "0"; emit this->updateModel(index, {FMH::MODEL_KEY::FAV}); return true; } return false; } + +bool TracksModel::rate(const int &index, const int &value) +{ + if(index >= this->list.size() || index < 0) + return false; + + auto item = this->list[index]; + if(this->db->rateTrack(item[FMH::MODEL_KEY::URL], value)) + { + this->list[index][FMH::MODEL_KEY::RATE] = QString::number(value); + emit this->updateModel(index, {FMH::MODEL_KEY::RATE}); + + return true; + } + + return false; +} diff --git a/models/tracks/tracksmodel.h b/models/tracks/tracksmodel.h index 21db45b..868db7f 100644 --- a/models/tracks/tracksmodel.h +++ b/models/tracks/tracksmodel.h @@ -1,64 +1,65 @@ #ifndef TRACKSMODEL_H #define TRACKSMODEL_H #include #include "models/baselist.h" class CollectionDB; class TracksModel : public BaseList { Q_OBJECT Q_PROPERTY(QString query READ getQuery WRITE setQuery NOTIFY queryChanged()) Q_PROPERTY(TracksModel::SORTBY sortBy READ getSortBy WRITE setSortBy NOTIFY sortByChanged) public: enum SORTBY : uint_fast8_t { ADDDATE = FMH::MODEL_KEY::ADDDATE, RELEASEDATE = FMH::MODEL_KEY::RELEASEDATE, FORMAT = FMH::MODEL_KEY::FORMAT, ARTIST = FMH::MODEL_KEY::ARTIST, TITLE = FMH::MODEL_KEY::TITLE, ALBUM = FMH::MODEL_KEY::ALBUM, RATE = FMH::MODEL_KEY::RATE, FAV = FMH::MODEL_KEY::FAV, TRACK = FMH::MODEL_KEY::TRACK, NONE }; Q_ENUM(SORTBY) explicit TracksModel(QObject *parent = nullptr); FMH::MODEL_LIST items() const override; void setQuery(const QString &query); QString getQuery() const; void setSortBy(const TracksModel::SORTBY &sort); TracksModel::SORTBY getSortBy() const; private: CollectionDB *db; FMH::MODEL_LIST list; void sortList(); void setList(); QString query; TracksModel::SORTBY sort = TracksModel::SORTBY::ADDDATE; signals: void queryChanged(); void sortByChanged(); public slots: QVariantMap get(const int &index) const override; void append(const QVariantMap &item); void append(const QVariantMap &item, const int &at); void appendQuery(const QString &query); void clear(); bool color(const int &index, const QString &color); bool fav(const int &index, const bool &value); + bool rate(const int &index, const int &value); }; #endif // TRACKSMODEL_H diff --git a/view_models/BabeTable/BabeTable.qml b/view_models/BabeTable/BabeTable.qml index 01c34e0..6e52a25 100644 --- a/view_models/BabeTable/BabeTable.qml +++ b/view_models/BabeTable/BabeTable.qml @@ -1,420 +1,418 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.2 as Kirigami import org.kde.mauikit 1.0 as Maui import BaseModel 1.0 import TracksList 1.0 import "../../utils/Player.js" as Player import "../../utils/Help.js" as H import "../../db/Queries.js" as Q import ".." BabeList { id: babeTableRoot // cacheBuffer : 300 property alias list : _tracksList property alias listModel : _tracksModel property alias listView : babeTableRoot.listView property bool trackNumberVisible property bool quickPlayVisible : true property bool coverArtVisible : false property bool menuItemVisible : isMobile property bool trackDuration property bool trackRating property bool allowMenu: true property bool isArtworkRemote : false property bool showIndicator : false property bool group : false property alias headerMenu: headerMenu property alias contextMenu : contextMenu property alias playAllBtn : playAllBtn property alias appendBtn : appendBtn property alias menuBtn : menuBtn signal rowClicked(int index) signal rowPressed(int index) signal quickPlayTrack(int index) signal queueTrack(int index) signal artworkDoubleClicked(int index) signal playAll() signal appendAll() // altToolBars: true onGroupChanged: groupBy() focus: true headBar.leftContent: [ Maui.ToolButton { id : playAllBtn visible : headBar.visible && count > 0 anim : true iconName : "media-playlist-play" onClicked : playAll() }, Maui.ToolButton { id: sortBtn anim: true iconName: "view-sort" onClicked: sortMenu.popup() Maui.Menu { id: sortMenu Maui.MenuItem { text: qsTr("Title") checkable: true checked: list.sortBy === Tracks.TITLE onTriggered: list.sortBy = Tracks.TITLE } Maui.MenuItem { text: qsTr("Track") checkable: true checked: list.sortBy === Tracks.TRACK onTriggered: list.sortBy = Tracks.TRACK } Maui.MenuItem { text: qsTr("Artist") checkable: true checked: list.sortBy === Tracks.ARTIST onTriggered: list.sortBy = Tracks.ARTIST } Maui.MenuItem { text: qsTr("Album") checkable: true checked: list.sortBy === Tracks.ALBUM onTriggered: list.sortBy = Tracks.ALBUM } Maui.MenuItem { text: qsTr("Rate") checkable: true checked: list.sortBy === Tracks.RATE onTriggered: list.sortBy = Tracks.RATE } Maui.MenuItem { text: qsTr("Fav") checkable: true checked: list.sortBy === Tracks.FAV onTriggered: list.sortBy = Tracks.FAV } Maui.MenuItem { text: qsTr("Release date") checkable: true checked: list.sortBy === Tracks.RELEASEDATE onTriggered: list.sortBy = Tracks.RELEASEDATE } Maui.MenuItem { text: qsTr("Add date") checkable: true checked: list.sortBy === Tracks.ADDDATE onTriggered: list.sortBy = Tracks.ADDDATE } MenuSeparator{} Maui.MenuItem { text: qsTr("Group") checkable: true checked: group onTriggered: group = !group } } } ] headBar.rightContent: [ Maui.ToolButton { id: appendBtn visible: headBar.visible && count > 0 anim : true iconName : "media-playlist-append"//"media-repeat-track-amarok" onClicked: appendAll() }, Maui.ToolButton { id: menuBtn iconName: /*"application-menu"*/ "overflow-menu" onClicked: headerMenu.popup() } ] HeaderMenu { id: headerMenu onSaveListClicked: saveList() onQueueListClicked: queueList() } TableMenu { id: contextMenu menuItem: [ Maui.MenuItem { text: qsTr("Select...") onTriggered: { H.addToSelection(listView.model.get(listView.currentIndex)) contextMenu.close() } }, MenuSeparator {}, Maui.MenuItem { text: qsTr("Go to Artist") onTriggered: goToArtist() }, Maui.MenuItem { text: qsTr("Go to Album") onTriggered: goToAlbum() } ] onFavClicked: { list.fav(listView.currentIndex, !(list.get(listView.currentIndex).fav == "1")) } onQueueClicked: Player.queueTracks([list.get(listView.currentIndex)]) onSaveToClicked: { playlistDialog.tracks = paths playlistDialog.open() } onOpenWithClicked: bae.showFolder(paths) onRemoveClicked: { listModel.remove(listView.currentIndex) } onRateClicked: { - var value = H.rateIt(paths, rate) - listView.currentItem.rate(H.setStars(value)) - listView.model.get(listView.currentIndex).rate = value + list.rate(listView.currentIndex, rate); } onColorClicked: { - list.color(listView.currentIndex, color); + list.color(listView.currentIndex, color); } } listView.highlightFollowsCurrentItem: false listView.highlightMoveDuration: 0 listView.highlight: Rectangle { } section.criteria: ViewSection.FullString section.delegate: Maui.LabelDelegate { label: section isSection: true boldLabel: true colorScheme.backgroundColor: "#333" colorScheme.textColor: "#fafafa" background: Rectangle { color: colorScheme.backgroundColor } } BaseModel { id: _tracksModel list: _tracksList } Tracks { id: _tracksList onSortByChanged: if(babeTableRoot.group) babeTableRoot.groupBy() } model: _tracksModel // property alias animBabe: delegate.animBabe delegate: TableDelegate { id: delegate width: listView.width number : trackNumberVisible ? true : false quickPlay: quickPlayVisible coverArt : coverArtVisible trackDurationVisible : trackDuration trackRatingVisible : trackRating menuItem: menuItemVisible remoteArtwork: isArtworkRemote playingIndicator: showIndicator onPressAndHold: if(isMobile && allowMenu) openItemMenu(index) onRightClicked: if(allowMenu) openItemMenu(index) onClicked: { currentIndex = index if(selectionMode) { H.addToSelection(listView.model.get(listView.currentIndex)) return } if(isMobile) rowClicked(index) } onDoubleClicked: { currentIndex = index if(!isMobile) rowClicked(index) } onPlay: { currentIndex = index quickPlayTrack(index) } onArtworkCoverClicked: { currentIndex = index goToAlbum() } } function openItemMenu(index) { currentIndex = index contextMenu.rate = list.get(currentIndex).rate contextMenu.fav = list.get(currentIndex).fav == "1" contextMenu.show([list.get(currentIndex).url]) rowPressed(index) console.log(list.get(currentIndex).fav) } function saveList() { var trackList = [] if(model.count > 0) { for(var i = 0; i < model.count; ++i) trackList.push(model.get(i).url) playlistDialog.tracks = trackList playlistDialog.open() } } function queueList() { var trackList = [] if(model.count > 0) { for(var i = 0; i < model.count; ++i) trackList.push(model.get(i)) Player.queueTracks(trackList) } } function goToAlbum() { root.pageStack.currentIndex = 1 root.currentView = viewsIndex.albums var item = listView.model.get(listView.currentIndex) albumsView.populateTable(item.album, item.artist) contextMenu.close() } function goToArtist() { root.pageStack.currentIndex = 1 root.currentView = viewsIndex.artists var item = listView.model.get(listView.currentIndex) artistsView.populateTable(undefined, item.artist) contextMenu.close() } function groupBy() { var prop = "undefined" if(group) switch(list.sortBy) { case Tracks.TITLE: prop = "title" break case Tracks.ARTIST: prop = "artist" break case Tracks.ALBUM: prop = "album" break case Tracks.RATE: prop = "rate" break case Tracks.FAV: prop = "fav" break case Tracks.ADDDATE: prop = "adddate" break case Tracks.RELEASEDATE: prop = "releasedate" break } section.property = prop } } diff --git a/view_models/BabeTable/TableMenu.qml b/view_models/BabeTable/TableMenu.qml index 3a775f4..69f5cdf 100644 --- a/view_models/BabeTable/TableMenu.qml +++ b/view_models/BabeTable/TableMenu.qml @@ -1,221 +1,220 @@ import QtQuick 2.0 import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import "../../utils" import ".." import org.kde.mauikit 1.0 as Maui Maui.Menu { id: control property var paths : [] property int rate : 0 property bool fav : false property string starColor : "#FFC107" property string starReg : textColor property string starIcon: "draw-star" signal removeClicked(var paths) signal favClicked(var paths) signal queueClicked(var paths) signal saveToClicked(var paths) signal openWithClicked(var paths) signal editClicked(var paths) signal shareClicked(var paths) signal selectClicked(var paths) signal rateClicked(var paths, int rate) signal colorClicked(var paths, string color) property alias menuItem : customItems.children Maui.MenuItem { text: !fav ? qsTr("Fav it"): qsTr("UnFav it") onTriggered: { favClicked(paths) close() } } Maui.MenuItem { text: qsTr("Queue") onTriggered: { queueClicked(paths) close() } } Maui.MenuItem { text: qsTr("Save to...") onTriggered: { saveToClicked(paths) close() } } Maui.MenuItem { text: isAndroid ? qsTr("Open with...") : qsTr("Show in folder...") onTriggered: { openWithClicked(paths) close() } } Maui.MenuItem { text: qsTr("Edit...") onTriggered: { editClicked(paths) close() } } Maui.MenuItem { text: qsTr("Share...") onTriggered: { shareClicked(paths) isAndroid ? Maui.Android.shareDialog(paths) : shareDialog.show(paths) close() } } Maui.MenuItem { text: qsTr("Remove") onTriggered: { removeClicked(paths) // listModel.remove(list.currentIndex) close() } } Column { id: customItems width: parent.implicitWidth } Maui.MenuItem { id: starsRow width: parent.width height: iconSizes.medium + space.small RowLayout { anchors.fill: parent Maui.ToolButton { Layout.fillWidth: true Layout.fillHeight: true iconName: starIcon size: iconSizes.medium iconColor: rate >= 1 ? starColor :starReg onClicked: { rate = 1 rateClicked(paths, rate) close() } } Maui.ToolButton { Layout.fillWidth: true Layout.fillHeight: true size: iconSizes.medium iconName: starIcon iconColor: rate >= 2 ? starColor :starReg onClicked: { rate = 2 rateClicked(paths, rate) close() } } Maui.ToolButton { Layout.fillWidth: true Layout.fillHeight: true size: iconSizes.medium iconName: starIcon iconColor: rate >= 3 ? starColor :starReg onClicked: { rate = 3 rateClicked(paths, rate) close() } } Maui.ToolButton { Layout.fillWidth: true Layout.fillHeight: true size: iconSizes.medium iconName: starIcon iconColor: rate >= 4 ? starColor :starReg onClicked: { rate = 4 rateClicked(paths, rate) close() } } Maui.ToolButton { Layout.fillWidth: true Layout.fillHeight: true size: iconSizes.medium iconName: starIcon iconColor: rate >= 5 ? starColor :starReg onClicked: { rate = 5 rateClicked(paths, rate) close() } } } - } Maui.MenuItem { id: colorsRow width: parent.width height: iconSizes.medium + space.small ColorTagsBar { anchors.fill: parent onColorClicked: control.colorClicked(paths, color) } } function show(urls) { paths = urls contextMenu.popup() } }