diff --git a/main.qml b/main.qml index f6539d6..75c64dc 100644 --- a/main.qml +++ b/main.qml @@ -1,883 +1,883 @@ import QtQuick 2.10 import QtQuick.Controls 2.10 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.1 import "utils" import "widgets" import "widgets/PlaylistsView" import "widgets/MainPlaylist" import "widgets/SettingsView" import "widgets/SearchView" import "widgets/CloudView" import "view_models" import "view_models/BabeTable" import "services/local" import "services/web" //import "services/web/Spotify" import "view_models/BabeGrid" import "widgets/InfoView" import "db/Queries.js" as Q import "utils/Help.js" as H import "utils/Player.js" as Player import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import Player 1.0 import AlbumsList 1.0 import TracksList 1.0 import PlaylistsList 1.0 Maui.ApplicationWindow { id: root title: qsTr("vvave") /***************************************************/ /******************** ALIASES ********************/ /*************************************************/ property alias mainPlaylist: mainPlaylist property alias selectionBar: _selectionBar property alias progressBar: progressBar property alias dialog : _dialogLoader.item Maui.App.iconName: "qrc:/assets/vvave.svg" Maui.App.description: qsTr("VVAVE will handle your whole music collection by retreaving semantic information from the web. Just relax, enjoy and discover your new music ") /***************************************************/ /******************** PLAYBACK ********************/ /*************************************************/ property bool isShuffle: Maui.FM.loadSettings("SHUFFLE","PLAYBACK", false) property var currentTrack: ({ fav: "0", stars: "0" }) property int currentTrackIndex: -1 property int prevTrackIndex: 0 property string currentArtwork: !mainlistEmpty ? mainPlaylist.listModel.get(0).artwork : "" property bool currentBabe: currentTrack.fav == "0" ? false : true property alias durationTimeLabel: player.duration property string progressTimeLabel: player.transformTime((player.duration/1000) *(player.pos/ 1000)) property alias isPlaying: player.playing property int onQueue: 0 property bool mainlistEmpty: !mainPlaylist.table.count > 0 /***************************************************/ /******************** HANDLERS ********************/ /*************************************************/ readonly property var viewsIndex: ({ tracks: 0, cloud : 1, albums: 2, artists: 3, playlists: 4, folders: 5, youtube: 6, search: 7}) property string syncPlaylist: "" property bool sync: false property string infoMsg: "" property bool infoLabels: Maui.FM.loadSettings("LABELS", "PLAYBACK", false) == "true" ? true : false property bool focusView : false property bool selectionMode : false /***************************************************/ /******************** UI COLORS *******************/ /*************************************************/ readonly property color babeColor: "#f84172" /*SIGNALS*/ signal missingAlert(var track) /*HANDLE EVENTS*/ onClosing: Player.savePlaylist() onMissingAlert: { var message = qsTr("Missing file...") var messageBody = track.title + " by " + track.artist + " is missing.\nDo you want to remove it from your collection?" notify("dialog-question", message, messageBody, function () { mainPlaylist.list.remove(mainPlaylist.table.currentIndex) }) } /*COMPONENTS*/ Player { id: player volume: 100 onFinishedChanged: if (!mainlistEmpty) { if (currentTrack.url) mainPlaylist.list.countUp(currentTrackIndex) Player.nextTrack() } } FloatingDisk { id: _floatingDisk opacity: 1 - _drawer.position } headBar.middleContent : Maui.ActionGroup { id: _actionGroup Layout.fillWidth: true Layout.fillHeight: true Layout.minimumWidth: implicitWidth currentIndex : swipeView.currentIndex onCurrentIndexChanged: swipeView.currentIndex = currentIndex hiddenActions: [ Action { text: qsTr("Folders") icon.name: "folder" }, Action { text: qsTr("YouTube") icon.name: "internet-services" } ] Action { icon.name: "view-media-track" text: qsTr("Tracks") } Action { text: qsTr("Cloud") icon.name: "folder-cloud" } Action { text: qsTr("Albums") icon.name: /*"album"*/ "view-media-album-cover" } Action { text: qsTr("Artists") icon.name: "view-media-artist" } Action { text: qsTr("Playlists") icon.name: "view-media-playlist" } } onSearchButtonClicked: { _actionGroup.currentIndex = viewsIndex.search // searchView.searchInput.forceActiveFocus() } Loader { id: _dialogLoader } InfoView { id: infoView maxWidth: parent.width * 0.8 maxHeight: parent.height * 0.9 } Loader { id: _focusViewLoader active: focusView source: "widgets/FocusView.qml" } Component { id: _shareDialogComponent Maui.ShareDialog {} } Component { id: _fmDialogComponent Maui.FileDialog { } } SourcesDialog { id: sourcesDialog } mainMenu: [ // Maui.MenuItem // { // text: "Vvave Stream" // icon.name: "headphones" // onTriggered: // { // pageStack.currentIndex = 1 // currentView = viewsIndex.vvave // } // }, // Maui.MenuItem // { // text: qsTr("Linking") // icon.name: "view-links" // onTriggered: // { // pageStack.currentIndex = 1 // currentView = viewsIndex.linking // if(!isLinked) linkingView.linkingConf.open() // } // }, // Maui.MenuItem // { // text: qsTr("Cloud") // icon.name: "folder-cloud" // onTriggered: // { // pageStack.currentIndex = 1 // currentView = viewsIndex.cloud // } // }, // Maui.MenuItem // { // text: qsTr("Spotify") // icon.name: "internet-services" // onTriggered: // { // pageStack.currentIndex = 1 // currentView = viewsIndex.spotify // } // }, MenuSeparator{}, MenuItem { text: qsTr("Sources") icon.name: "folder-add" onTriggered: sourcesDialog.open() }, MenuItem { text: qsTr("Open") icon.name: "folder-add" onTriggered: { _dialogLoader.sourceComponent = _fmDialogComponent root.dialog.settings.onlyDirs = false root.dialog.currentPath = "file:///home/camilo/Music" root.dialog.settings.filterType = Maui.FMList.AUDIO console.log("SETTIGN FILTER TYPE FISR", root.dialog.settings.filterType, Maui.FMList.AUDIO) root.dialog.show(function(paths) { vvave.openUrls(paths) root.dialog.close() }) } }/*, Menu { title: qsTr("Collection") // icon.name: "settings-configure" MenuItem { text: qsTr("Re-Scan") onTriggered: bae.refreshCollection(); } MenuItem { text: qsTr("Refresh...") onTriggered: H.refreshCollection(); } MenuItem { text: qsTr("Clean") onTriggered: bae.removeMissingTracks(); } }*/ // Maui.Menu // { // title: qsTr("Settings...") // // Kirigami.Action // // { // // text: "Brainz" // // Kirigami.Action // // { // // id: brainzToggle // // text: checked ? "Turn OFF" : "Turn ON" // // checked: bae.brainzState() // // checkable: true // // onToggled: // // { // // checked = !checked // // bae.saveSetting("AUTO", checked, "BRAINZ") // //// bae.brainz(checked) // // } // // } // // } // Maui.MenuItem // { // text: "Info label" + checked ? "ON" : "OFF" // checked: infoLabels // checkable: true // onToggled: // { // infoLabels = checked // bae.saveSetting("LABELS", infoLabels ? true : false, "PLAYBACK") // } // } // Maui.MenuItem // { // text: "Autoplay" // checked: autoplay // checkable: true // onToggled: // { // autoplay = checked // bae.saveSetting("AUTOPLAY", autoplay ? true : false, "BABE") // } // } // } ] Playlists { id: playlistsList } PlaylistDialog { id: playlistDialog } sideBar: Maui.AbstractSideBar { id: _drawer width: visible ? Math.min(Kirigami.Units.gridUnit * (Kirigami.Settings.isMobile? 18 : 15), root.width) : 0 modal: !isWide - + closePolicy: Popup.CloseOnEscapse | Popup.NoAutoClose height: _drawer.modal ? implicitHeight - _mainPage.footer.height : implicitHeight MainPlaylist { id: mainPlaylist anchors.fill: parent Connections { target: mainPlaylist onCoverPressed: Player.appendAll(tracks) onCoverDoubleClicked: Player.playAll(tracks) } } } Maui.Page { id: _mainPage anchors.fill: parent footer: ColumnLayout { id: _footerLayout visible: !mainlistEmpty height: visible ? Maui.Style.toolBarHeight * 1.2 : 0 width: parent.width spacing: 0 Kirigami.Separator { Layout.fillWidth: true } Slider { id: progressBar Layout.preferredHeight: Maui.Style.unit * (Kirigami.Settings.isMobile ? 6 : 8) Layout.fillWidth: true padding: 0 from: 0 to: 1000 value: player.pos spacing: 0 focus: true onMoved: { player.pos = value } background: Rectangle { implicitWidth: progressBar.width implicitHeight: progressBar.height width: progressBar.availableWidth height: implicitHeight color: "transparent" Rectangle { width: progressBar.visualPosition * parent.width height: progressBar.height color: Kirigami.Theme.highlightColor } } handle: Rectangle { x: progressBar.leftPadding + progressBar.visualPosition * (progressBar.availableWidth - width) y: -(progressBar.height * 0.8) implicitWidth: progressBar.pressed ? Maui.Style.iconSizes.medium : 0 implicitHeight: progressBar.pressed ? Maui.Style.iconSizes.medium : 0 radius: progressBar.pressed ? Maui.Style.iconSizes.medium : 0 color: Kirigami.Theme.highlightColor } } Maui.ToolBar { Layout.fillHeight: true Layout.fillWidth: true position: ToolBar.Footer middleContent: [ ToolButton { id: babeBtnIcon icon.name: "love" enabled: currentTrackIndex >= 0 icon.color: currentBabe ? babeColor : Kirigami.Theme.textColor onClicked: if (!mainlistEmpty) { mainPlaylist.list.fav(currentTrackIndex, !(mainPlaylist.listModel.get(currentTrackIndex).fav == "1")) currentBabe = mainPlaylist.listModel.get(currentTrackIndex).fav == "1" } }, ToolButton { icon.name: "media-skip-backward" icon.color: Kirigami.Theme.textColor onClicked: Player.previousTrack() onPressAndHold: Player.playAt(prevTrackIndex) }, ToolButton { id: playIcon enabled: currentTrackIndex >= 0 icon.color: Kirigami.Theme.textColor icon.name: isPlaying ? "media-playback-pause" : "media-playback-start" onClicked: player.playing = !player.playing }, ToolButton { id: nextBtn icon.color: Kirigami.Theme.textColor icon.name: "media-skip-forward" onClicked: Player.nextTrack() onPressAndHold: Player.playAt(Player.shuffle()) }, ToolButton { id: shuffleBtn icon.color: babeColor icon.name: isShuffle ? "media-playlist-shuffle" : "media-playlist-normal" onClicked: { isShuffle = !isShuffle Maui.FM.saveSettings("SHUFFLE", isShuffle, "PLAYBACK") } } ] } } ColumnLayout { anchors.fill: parent SwipeView { id: swipeView Layout.fillHeight: true Layout.fillWidth: true // interactive: Kirigami.Settings.isMobile currentIndex: _actionGroup.currentIndex onCurrentIndexChanged: _actionGroup.currentIndex = currentIndex clip: true onCurrentItemChanged: currentItem.forceActiveFocus() TracksView { id: tracksView Connections { target: vvave onRefreshTables: tracksView.list.refresh() } Connections { target: tracksView onRowClicked: Player.quickPlay(tracksView.listModel.get(index)) onQuickPlayTrack: Player.quickPlay(tracksView.listModel.get(index)) onAppendTrack: Player.addTrack(tracksView.listModel.get(index)) onPlayAll: Player.playAll( tracksView.listModel.getAll()) onAppendAll: Player.appendAll( tracksView.listModel.getAll()) onQueueTrack: Player.queueTracks([tracksView.listModel.get(index)], index) } } Loader { active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem || item sourceComponent: CloudView { id: cloudView } } Loader { active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem || item sourceComponent: AlbumsView { id: albumsView holder.emoji: "qrc:/assets/MusicBox.png" holder.isMask: false holder.title : "No Albums!" holder.body: "Add new music sources" holder.emojiSize: Maui.Style.iconSizes.huge title: count + qsTr(" albums") list.query: Albums.ALBUMS list.sortBy: Albums.ALBUM Connections { target: vvave onRefreshTables: albumsView.list.refresh() } Connections { target: albumsView onRowClicked: Player.quickPlay(track) onAppendTrack: Player.addTrack(track) onPlayTrack: Player.quickPlay(track) onAlbumCoverClicked: albumsView.populateTable(album, artist) onAlbumCoverPressedAndHold: { var query = Q.GET.albumTracks_.arg(album) query = query.arg(artist) mainPlaylist.list.clear() mainPlaylist.list.sortBy = Tracks.NONE mainPlaylist.list.query = query Player.playAt(0) } onPlayAll: Player.playAll(albumsView.listModel.getAll()) onAppendAll: Player.appendAll(albumsView.listModel.getAll()) } } } Loader { active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem || item sourceComponent: AlbumsView { id: artistsView holder.emoji: "qrc:/assets/MusicBox.png" holder.isMask: false holder.title : qsTr("No Artists!") holder.body: qsTr("Add new music sources") holder.emojiSize: Maui.Style.iconSizes.huge title: count + qsTr(" artists") list.query: Albums.ARTISTS list.sortBy: Albums.ARTIST table.list.sortBy: Tracks.NONE Connections { target: vvave onRefreshTables: artistsView.list.refresh() } Connections { target: artistsView onRowClicked: Player.quickPlay(track) onAppendTrack: Player.addTrack(track) onPlayTrack: Player.quickPlay(track) onAlbumCoverClicked: artistsView.populateTable(undefined, artist) onAlbumCoverPressedAndHold: { var query = Q.GET.artistTracks_.arg(artist) mainPlaylist.list.clear() mainPlaylist.list.sortBy = Tracks.NONE mainPlaylist.list.query = query Player.playAt(0) } onPlayAll: Player.artistsView(albumsView.listModel.getAll()) onAppendAll: Player.artistsView(albumsView.listModel.getAll()) } } } Loader { active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem || item sourceComponent:PlaylistsView { id: playlistsView Connections { target: playlistsView onRowClicked: Player.quickPlay(track) onAppendTrack: Player.addTrack(track) onPlayTrack: Player.quickPlay(track) onPlayAll: Player.playAll(playlistsView.listModel.getAll()) onAppendAll: Player.appendAll(playlistsView.listModel.getAll()) onPlaySync: { Player.playAll(playlistsView.listModel.getAll()) root.sync = true root.syncPlaylist = playlist root.infoMsg = qsTr("Syncing to ") + playlist } } } } Loader { active: SwipeView.isCurrentItem || item sourceComponent: FoldersView { id: foldersView Connections { target: vvave onRefreshTables: foldersView.populate() } Connections { target: foldersView.list onRowClicked: Player.quickPlay(foldersView.list.model.get(index)) onQuickPlayTrack: Player.quickPlay(foldersView.list.model.get(index)) onAppendTrack: Player.addTrack(foldersView.listModel.get(index)) onPlayAll: Player.playAll(foldersView.listModel.getAll()) onAppendAll: Player.appendAll(foldersView.listModel.getAll()) onQueueTrack: Player.queueTracks([foldersView.list.model.get(index)], index) } } } Loader { active: SwipeView.isCurrentItem || item sourceComponent: YouTube { id: youtubeView } } Loader { active: SwipeView.isCurrentItem || (item && item.listView.count > 0) sourceComponent: SearchTable { id: searchView Connections { target: searchView onRowClicked: Player.quickPlay(searchView.listModel.get(index)) onQuickPlayTrack: Player.quickPlay(searchView.listModel.get(index)) onAppendTrack: Player.addTrack(searchView.listModel.get(index)) onPlayAll: Player.playAll(searchView.listModel.getAll()) onAppendAll: Player.appendAll(searchView.listModel.getAll()) onArtworkDoubleClicked: { var query = Q.GET.albumTracks_.arg( searchView.listModel.get( index).album) query = query.arg(searchView.listModel.get(index).artist) mainPlaylist.list.clear() mainPlaylist.list.sortBy = Tracks.NONE mainPlaylist.list.query = query Player.playAt(0) } } } } } Maui.SelectionBar { id: _selectionBar property alias listView: _selectionBar.selectionList Layout.fillWidth: true Layout.margins: Maui.Style.space.big Layout.topMargin: Maui.Style.space.small Layout.bottomMargin: Maui.Style.space.big onIconClicked: _contextMenu.popup() onExitClicked: { root.selectionMode = false clear() } SelectionBarMenu { id: _contextMenu } } } } /*animations*/ /*FUNCTIONS*/ function infoMsgAnim() { animBg.running = true animTxt.running = true } function toggleMaximized() { if (root.visibility === Window.Maximized) { root.showNormal(); } else { root.showMaximized(); } } /*CONNECTIONS*/ Connections { target: vvave onRefreshTables: H.refreshCollection(size) // onRefreshTracks: H.refreshTracks() // onRefreshAlbums: H.refreshAlbums() // onRefreshArtists: H.refreshArtists() // onCoverReady: // { // root.currentArtwork = path // currentTrack.artwork = currentArtwork // mainPlaylist.list.update(currentTrack, currentTrackIndex); // } // onTrackLyricsReady: // { // console.log(lyrics) // if (url === currentTrack.url) // Player.setLyrics(lyrics) // } // onSkipTrack: Player.nextTrack() // onBabeIt: if (!mainlistEmpty) // { // mainPlaylist.list.fav(currentTrackIndex, !(mainPlaylist.list.get(currentTrackIndex).fav == "1")) // currentBabe = mainPlaylist.list.get(currentTrackIndex).fav == "1" // } onOpenFiles: { Player.appendTracksAt(tracks, 0) Player.playAt(0) } } Component.onCompleted: { if(isAndroid) { Maui.Android.statusbarColor(Kirigami.Theme.backgroundColor, true) Maui.Android.navBarColor(Kirigami.Theme.backgroundColor, true) } } } diff --git a/utils/bae.h b/utils/bae.h index b360079..3af68f9 100644 --- a/utils/bae.h +++ b/utils/bae.h @@ -1,460 +1,459 @@ #ifndef BAE_H #define BAE_H #include "string" #include #include #include #include #include #include #include #include #include #include #include #ifdef STATIC_MAUIKIT #include "fmh.h" #else #include #endif #include #define BABE_MAJOR_VERSION 0 #define BABE_MINOR_VERSION 1 #define BABE_PATCH_VERSION 0 #define BABE_VERSION_STR "0.1.0" #define BABE_VERSION KDE_MAKE_VERSION(0,1,0) using namespace std; namespace BAE { Q_NAMESPACE enum SEG { HALF = 500, ONE = 1000, ONEHALF = 1500, TWO = 2000, THREE = 3000 }; enum SearchT { LIKE, SIMILAR }; typedef QMap SEARCH; static const SEARCH SearchTMap { { BAE::SearchT::LIKE, "like" }, { BAE::SearchT::SIMILAR, "similar" } }; enum class W : uint_fast8_t { ALL, NONE, LIKE, TAG, SIMILAR, UNKNOWN, DONE, DESC, ASC, CODE, MSG }; static const QMap SLANG = { {W::ALL, "ALL"}, {W::NONE, "NONE"}, {W::LIKE, "LIKE"}, {W::SIMILAR, "SIMILAR"}, {W::UNKNOWN, "UNKNOWN"}, {W::DONE, "DONE"}, {W::DESC, "DESC"}, {W::ASC, "ASC"}, {W::TAG, "TAG"}, {W::MSG, "MSG"}, {W::CODE, "CODE"} }; enum class TABLE : uint8_t { ALBUMS, ARTISTS, MOODS, PLAYLISTS, SOURCES, SOURCES_TYPES, TRACKS, TRACKS_MOODS, TRACKS_PLAYLISTS, TAGS, ALBUMS_TAGS, ARTISTS_TAGS, TRACKS_TAGS, LOGS, FOLDERS, ALL, NONE }; static const QMap TABLEMAP = { {TABLE::ALBUMS,"albums"}, {TABLE::ARTISTS,"artists"}, {TABLE::MOODS,"moods"}, {TABLE::PLAYLISTS,"playlists"}, {TABLE::SOURCES,"sources"}, {TABLE::SOURCES_TYPES,"sources_types"}, {TABLE::TRACKS,"tracks"}, {TABLE::TRACKS_MOODS,"tracks_moods"}, {TABLE::TRACKS_PLAYLISTS,"tracks_playlists"}, {TABLE::TAGS,"tags"}, {TABLE::ALBUMS_TAGS,"albums_tags"}, {TABLE::ARTISTS_TAGS,"artists_tags"}, {TABLE::TRACKS_TAGS,"tracks_tags"}, {TABLE::LOGS,"logs"}, {TABLE::FOLDERS,"folders"} }; enum class KEY :uint8_t { URL = 0, SOURCES_URL = 1, TRACK = 2, TITLE = 3, ARTIST = 4, ALBUM = 5, DURATION = 6, PLAYED = 7, BABE = 8, STARS = 9, RELEASE_DATE = 10, ADD_DATE = 11, LYRICS = 12, GENRE = 13, ART = 14, TAG = 15, MOOD = 16, PLAYLIST = 17, ARTWORK = 18, WIKI = 19, SOURCE_TYPE = 20, CONTEXT = 21, RETRIEVAL_DATE = 22, COMMENT = 23, ID = 24, SQL = 25, NONE = 26 }; typedef QMap DB; typedef QList DB_LIST; static const DB KEYMAP = { {KEY::URL, "url"}, {KEY::SOURCES_URL, "sources_url"}, {KEY::TRACK, "track"}, {KEY::TITLE, "title"}, {KEY::ARTIST, "artist"}, {KEY::ALBUM, "album"}, {KEY::DURATION, "duration"}, {KEY::PLAYED, "played"}, {KEY::BABE, "babe"}, {KEY::STARS, "stars"}, {KEY::RELEASE_DATE, "releaseDate"}, {KEY::ADD_DATE, "addDate"}, {KEY::LYRICS, "lyrics"}, {KEY::GENRE, "genre"}, {KEY::ART, "art"}, {KEY::TAG, "tag"}, {KEY::MOOD, "mood"}, {KEY::PLAYLIST, "playlist"}, {KEY::ARTWORK, "artwork"}, {KEY::WIKI, "wiki"}, {KEY::SOURCE_TYPE, "source_types_id"}, {KEY::CONTEXT, "context"}, {KEY::RETRIEVAL_DATE, "retrieval_date"}, {KEY::ID, "id"}, {KEY::COMMENT, "comment"}, {KEY::SQL, "sql"} }; static const DB TracksColsMap = { {KEY::URL, KEYMAP[KEY::URL]}, {KEY::SOURCES_URL, KEYMAP[KEY::SOURCES_URL]}, {KEY::TRACK, KEYMAP[KEY::TRACK]}, {KEY::TITLE, KEYMAP[KEY::TITLE]}, {KEY::ARTIST, KEYMAP[KEY::ARTIST]}, {KEY::ALBUM, KEYMAP[KEY::ALBUM]}, {KEY::DURATION, KEYMAP[KEY::DURATION]}, {KEY::PLAYED, KEYMAP[KEY::PLAYED]}, {KEY::BABE, KEYMAP[KEY::BABE]}, {KEY::STARS, KEYMAP[KEY::STARS]}, {KEY::RELEASE_DATE, KEYMAP[KEY::RELEASE_DATE]}, {KEY::ADD_DATE, KEYMAP[KEY::ADD_DATE]}, {KEY::LYRICS, KEYMAP[KEY::LYRICS]}, {KEY::GENRE, KEYMAP[KEY::GENRE]}, {KEY::ART, KEYMAP[KEY::ART]} }; inline QString transformTime(const qint64 &value) { QString tStr; if (value) { QTime time((value/3600)%60, (value/60)%60, value%60, (value*1000)%1000); QString format = "mm:ss"; if (value > 3600) format = "hh:mm:ss"; tStr = time.toString(format); } return tStr.isEmpty() ? "00:00" : tStr; } inline QString getNameFromLocation(const QString &str) { QString ret; int index = 0; for(int i = str.size() - 1; i >= 0; i--) if(str[i] == '/') { index = i + 1; i = -1; } for(; index < str.size(); index++) ret.push_back(str[index]); return ret; } const QString SettingPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)+"/vvave/").toLocalFile(); -const QString ArtworkPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/vvave/artwork/").toString(); const QString CollectionDBPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/vvave/").toLocalFile(); #ifdef Q_OS_ANDROID -const QString CachePath = BAE::ArtworkPath; +const QString CachePath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/vvave/").toString(); #else const QString CachePath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)+"/vvave/").toString(); #endif const QString YoutubeCachePath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)+"/vvave/youtube/").toLocalFile(); const QString NotifyDir = SettingPath; const QString MusicPath = FMH::MusicPath; const QString HomePath = FMH::HomePath; const QString DownloadsPath = FMH::DownloadsPath; const QString BabePort = "8483"; const QString LinkPort = "3333"; const QString appName = QStringLiteral("vvave"); const QString displayName = QStringLiteral("vvave"); const QString version = BABE_VERSION_STR; const QString description = QStringLiteral("Music player"); const QString orgName = QStringLiteral("Maui"); const QString orgDomain = QStringLiteral("org.maui.vvave"); const QString DBName = "collection.db"; const QStringList MoodColors = {"#F0FF01","#01FF5B","#3DAEFD","#B401FF","#E91E63"}; const QStringList defaultSources = QStringList() << BAE::MusicPath << BAE::DownloadsPath << BAE::YoutubeCachePath; inline QString fixTitle(const QString &title,const QString &s,const QString &e) { QString newTitle; for(int i=0; i«»,.?/{}\'\"\\\[\\\]\\\\]"))); QString title = str; title = title.remove(QChar::Null); title = title.contains(QChar('\u0000')) ? title.replace(QChar('\u0000'),"") : title; title = title.contains("(") && title.contains(")") ? fixTitle(title, "(",")") : title; title = title.contains("[") && title.contains("]") ? fixTitle(title, "[","]") : title; title = title.contains("{") && title.contains("}") ? fixTitle(title, "{","}") : title; title = title.contains("ft", Qt::CaseInsensitive) ? removeSubstring(title, "ft") : title; title = title.contains("ft.", Qt::CaseInsensitive) ? removeSubstring(title, "ft.") : title; title = title.contains("featuring", Qt::CaseInsensitive) ? removeSubstring(title, "featuring"):title; title = title.contains("feat", Qt::CaseInsensitive) ? removeSubstring(title, "feat") : title; title = title.contains("official video", Qt::CaseInsensitive) ? removeSubstring(title, "official video"):title; title = title.contains("live", Qt::CaseInsensitive) ? removeSubstring(title, "live") : title; title = title.contains("...") ? title.replace("..." ,"") : title; title = title.contains("|") ? title.replace("|", "") : title; title = title.contains("|") ? removeSubstring(title, "|") : title; title = title.contains('"') ? title.replace('"', "") : title; title = title.contains(":") ? title.replace(":", "") : title; // title=title.contains("&")? title.replace("&", "and"):title; //qDebug()<<"fixed string:"<bytesAvailable()) return true; else return false; } } #endif // BAE_H diff --git a/view_models/BabeTable/BabeTable.qml b/view_models/BabeTable/BabeTable.qml index 4f85e9b..5425293 100644 --- a/view_models/BabeTable/BabeTable.qml +++ b/view_models/BabeTable/BabeTable.qml @@ -1,498 +1,496 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui 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: control // cacheBuffer : 300 property alias list : _tracksList property alias listModel : _tracksModel property alias removeDialog : _removeDialog property bool trackNumberVisible property bool coverArtVisible : false property bool allowMenu: true - + property bool showQuickActions : true property bool group : false property alias contextMenu : contextMenu property alias contextMenuItems : contextMenu.contentData property alias playAllBtn : playAllBtn property alias appendBtn : appendBtn signal rowClicked(int index) signal rowDoubleClicked(int index) signal rowPressed(int index) signal quickPlayTrack(int index) signal queueTrack(int index) signal appendTrack(int index) signal artworkDoubleClicked(int index) signal playAll() signal appendAll() focus: true holder.visible: list.count === 0 listView.spacing: Maui.Style.space.small * (Kirigami.Settings.isMobile ? 1.4 : 1.2) headBar.leftContent: [ ToolButton { id : playAllBtn - // text: qsTr("Play all") icon.name : "media-playlist-play" onClicked: playAll() }, + ToolButton { id: appendBtn - // text: qsTr("Append") - icon.name : "media-playlist-append"//"media-repeat-track-amarok" + icon.name : "media-playlist-append" onClicked: appendAll() }] headBar.rightContent: [ ToolButton { icon.name: "item-select" onClicked: selectionMode = !selectionMode checkable: false checked: selectionMode }, Maui.ToolButtonMenu { id: sortBtn icon.name: "view-sort" visible: list.count > 2 MenuItem { text: qsTr("Title") checkable: true checked: list.sortBy === Tracks.TITLE onTriggered: list.sortBy = Tracks.TITLE autoExclusive: true } MenuItem { text: qsTr("Track") checkable: true checked: list.sortBy === Tracks.TRACK onTriggered: list.sortBy = Tracks.TRACK autoExclusive: true } MenuItem { text: qsTr("Artist") checkable: true checked: list.sortBy === Tracks.ARTIST onTriggered: list.sortBy = Tracks.ARTIST autoExclusive: true } MenuItem { text: qsTr("Album") checkable: true checked: list.sortBy === Tracks.ALBUM onTriggered: list.sortBy = Tracks.ALBUM autoExclusive: true } MenuItem { text: qsTr("Most played") checkable: true checked: list.sortBy === Tracks.COUNT onTriggered: list.sortBy = Tracks.COUNT autoExclusive: true } MenuItem { text: qsTr("Rate") checkable: true checked: list.sortBy === Tracks.RATE onTriggered: list.sortBy = Tracks.RATE autoExclusive: true } MenuItem { text: qsTr("Favorite") checkable: true checked: list.sortBy === Tracks.FAV onTriggered: list.sortBy = Tracks.FAV autoExclusive: true } MenuItem { text: qsTr("Release date") checkable: true checked: list.sortBy === Tracks.RELEASEDATE onTriggered: list.sortBy = Tracks.RELEASEDATE autoExclusive: true } MenuItem { text: qsTr("Add date") checkable: true checked: list.sortBy === Tracks.ADDDATE onTriggered: list.sortBy = Tracks.ADDDATE autoExclusive: true } MenuSeparator{} MenuItem { text: qsTr("Group") checkable: true checked: group onTriggered: { group = !group groupBy() } } }, ToolButton { id: _filterButton icon.name: "view-filter" checkable: true visible: list.count > 10 } ] listView.header: Maui.ToolBar { - Kirigami.Theme.backgroundColor: control.Kirigami.Theme.backgroundColor + Kirigami.Theme.inherit: false +// Kirigami.Theme.backgroundColor: control.Kirigami.Theme.backgroundColor visible: _filterButton.checked && _filterButton.visible width: control.width position: ToolBar.Header z: listView.z + 9 middleContent: Maui.TextField { Layout.fillWidth: true onAccepted: listModel.setFilterString(text) onTextChanged: listModel.setFilterString(text) } } Maui.Dialog { id: _removeDialog property int index title: qsTr("Remove track") message: qsTr("You can delete the file from your computer or remove it from your collection") rejectButton.text: qsTr("Delete") acceptButton.text: qsTr("Remove") page.padding: Maui.Style.space.huge onAccepted: { list.remove(listView.currentIndex) close() } onRejected: { if(Maui.FM.removeFile(list.get(index).url)) list.remove(listView.currentIndex) close() } } TableMenu { id: contextMenu MenuSeparator {} MenuItem { text: qsTr("Go to Artist") onTriggered: goToArtist() } 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)]) onPlayClicked: quickPlayTrack(listView.currentIndex) onAppendClicked: appendTrack(listView.currentIndex) onSaveToClicked: { playlistDialog.tracks = [list.get(listView.currentIndex).url] playlistDialog.open() } onOpenWithClicked: Maui.FM.openLocation([list.get(listView.currentIndex).url]) - onRemoveClicked: + onDeleteClicked: { _removeDialog.index= listView.currentIndex _removeDialog.open() } onRateClicked: { list.rate(listView.currentIndex, rate); } onColorClicked: { list.color(listView.currentIndex, color); } onInfoClicked: { infoView.show(list.get(listView.currentIndex)) } onCopyToClicked: { cloudView.list.upload(listView.currentIndex) } onShareClicked: { const url = list.get(listView.currentIndex).url if(isAndroid) { Maui.Android.shareDialog(url) return } _dialogLoader.sourceComponent = _shareDialogComponent root.dialog.show([url]) } } section.criteria: ViewSection.FullString section.delegate: Maui.LabelDelegate { id: _sectionDelegate label: section isSection: true width: control.width Kirigami.Theme.backgroundColor: "#333" Kirigami.Theme.textColor: "#fafafa" background: Rectangle { color: Kirigami.Theme.backgroundColor } } Maui.BaseModel { id: _tracksModel list: _tracksList recursiveFilteringEnabled: true sortCaseSensitivity: Qt.CaseInsensitive filterCaseSensitivity: Qt.CaseInsensitive } Tracks { id: _tracksList onSortByChanged: if(control.group) control.groupBy() } model: _tracksModel // property alias animBabe: delegate.animBabe delegate: TableDelegate { id: delegate - width: listView.width - number : trackNumberVisible ? true : false coverArt : coverArtVisible ? (control.width > 200) : coverArtVisible - + showQuickActions: control.showQuickActions onPressAndHold: if(Kirigami.Settings.isMobile && allowMenu) openItemMenu(index) onRightClicked: if(allowMenu) openItemMenu(index) onLeftEmblemClicked: H.addToSelection(list.get(index)) isSelected: selectionBar.contains(model.url) onClicked: { currentIndex = index if(selectionMode) { H.addToSelection(list.get(listView.currentIndex)) return } if(Kirigami.Settings.isMobile) rowClicked(index) } onDoubleClicked: { currentIndex = index if(!Kirigami.Settings.isMobile) rowClicked(index) } onPlay: { currentIndex = index quickPlayTrack(index) } onAppend: { currentIndex = index appendTrack(index) } onArtworkCoverClicked: { currentIndex = index goToAlbum() } Connections { target: selectionBar onPathRemoved: { if(path === model.url) delegate.isSelected = false } onPathAdded: { if(path === model.url) delegate.isSelected = true } onCleared: delegate.isSelected = false } } function openItemMenu(index) { currentIndex = index contextMenu.rate = list.get(currentIndex).rate contextMenu.fav = list.get(currentIndex).fav == "1" contextMenu.popup() rowPressed(index) } function saveList() { var trackList = [] if(list.count > 0) { for(var i = 0; i < list.count; ++i) - trackList.push(list.get(i).url) + trackList.push(listModel.get(i).url) playlistDialog.tracks = trackList playlistDialog.open() } } function queueList() { var trackList = [] if(list.count > 0) { for(var i = 0; i < list.count; ++i) trackList.push(list.get(i)) Player.queueTracks(trackList) } } function goToAlbum() { swipeView.currentIndex = viewsIndex.albums const item = list.get(listView.currentIndex) swipeView.currentItem.item.populateTable(item.album, item.artist) contextMenu.close() } function goToArtist() { swipeView.currentIndex = viewsIndex.artists const item = list.get(listView.currentIndex) swipeView.currentItem.item.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; case Tracks.COUNT: prop = "count" break } section.property = prop } } diff --git a/view_models/BabeTable/TableDelegate.qml b/view_models/BabeTable/TableDelegate.qml index 432c111..3623441 100644 --- a/view_models/BabeTable/TableDelegate.qml +++ b/view_models/BabeTable/TableDelegate.qml @@ -1,103 +1,111 @@ import QtQuick 2.10 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.10 import QtGraphicalEffects 1.0 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import "../../view_models" import "../../utils/Help.js" as H Maui.ItemDelegate { id: control isCurrentItem: ListView.isCurrentItem || isSelected + property bool showQuickActions: true property bool number : false property bool coverArt : false property bool showEmblem: true property bool keepEmblemOverlay: selectionMode - property bool isSelected : false - property string trackMood : model.color readonly property color bgColor : Kirigami.Theme.backgroundColor readonly property int altHeight : Maui.Style.rowHeight * 1.4 readonly property bool sameAlbum : { if(coverArt) { if(list.get(index-1)) { if(list.get(index-1).album === album && list.get(index-1).artist === artist) true else false }else false }else false } width: parent.width height: sameAlbum ? Maui.Style.rowHeight : altHeight padding: 0 rightPadding: leftPadding leftPadding: Maui.Style.space.small signal play() signal append() signal leftClicked() signal leftEmblemClicked(int index) signal artworkCoverClicked() signal artworkCoverDoubleClicked() Kirigami.Theme.backgroundColor: trackMood.length > 0 ? Qt.tint(bgColor, Qt.rgba(Qt.lighter(trackMood, 1.3).r, Qt.lighter(trackMood, 1.3).g, Qt.lighter(trackMood, 1.3).b, 0.3)): bgColor function rate(stars) { trackRating.text = stars } RowLayout { anchors.fill: parent Item { Layout.fillHeight: true Layout.preferredWidth: _leftEmblemIcon.height + Maui.Style.space.small visible: (control.keepEmblemOverlay || control.isSelected) && control.showEmblem Maui.Badge { id: _leftEmblemIcon anchors.centerIn: parent iconName: control.isSelected ? "list-remove" : "list-add" onClicked: control.leftEmblemClicked(index) size: Maui.Style.iconSizes.small } } Maui.ListItemTemplate { id: _template Layout.fillWidth: true Layout.fillHeight: true isCurrentItem: control.isCurrentItem iconSizeHint: height - Maui.Style.space.small label1.text: control.number ? model.track + ". " + model.title : model.title label2.text: model.artist + " | " + model.album label2.visible: control.coverArt ? !control.sameAlbum : true label3.text: model.fav ? (model.fav == "1" ? "\uf2D1" : "") : "" label3.font.family: "Material Design Icons" label4.font.family: "Material Design Icons" label4.text: model.rate ? H.setStars(model.rate) : "" iconVisible: !control.sameAlbum && control.coverArt imageSource: model.artwork ? model.artwork : "qrc:/assets/cover.png" } + + ToolButton + { + Layout.fillHeight: true + Layout.preferredWidth: implicitWidth + visible: showQuickActions && (Kirigami.Settings.isMobile ? true : control.hovered) + icon.name: "media-playlist-append" + onClicked: control.append() + } } } diff --git a/view_models/BabeTable/TableMenu.qml b/view_models/BabeTable/TableMenu.qml index 6b73337..112eab3 100644 --- a/view_models/BabeTable/TableMenu.qml +++ b/view_models/BabeTable/TableMenu.qml @@ -1,286 +1,296 @@ import QtQuick 2.0 import QtQuick 2.10 import QtQuick.Controls 2.10 import QtQuick.Layouts 1.3 import "../../utils" import ".." import "../../utils/Help.js" as H import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.6 as Kirigami Menu { id: control width: Maui.Style.unit * 200 property int rate : 0 property bool fav : false property string starColor : "#FFC107" property string starReg : Kirigami.Theme.textColor property string starIcon: "draw-star" signal removeClicked() signal favClicked() signal queueClicked() signal playClicked() signal saveToClicked() signal openWithClicked() signal editClicked() signal shareClicked() signal selectClicked() signal rateClicked(int rate) signal colorClicked(color color) signal infoClicked() signal copyToClicked() signal appendClicked() + signal deleteClicked() property alias menuItem : control.contentData - MenuItem { text: qsTr("Select...") onTriggered: { H.addToSelection(list.get(listView.currentIndex)) if(Kirigami.Settings.isMobile) selectionMode = true contextMenu.close() } } MenuSeparator {} MenuItem { text: qsTr("Play") onTriggered: { playClicked() close() } } MenuItem { text: qsTr("Queue") onTriggered: { queueClicked() close() } } MenuItem { text: qsTr("Append") onTriggered: { appendClicked() close() } } + MenuItem + { + text: qsTr("Remove") + onTriggered: + { + removeClicked() + list.remove(listView.currentIndex) + close() + } + } + MenuSeparator{} MenuItem { text: !fav ? qsTr("Fav it"): qsTr("UnFav it") onTriggered: { favClicked() close() } - } + } MenuItem { text: qsTr("Add to") onTriggered: { saveToClicked() close() } } MenuSeparator {} MenuItem { text: qsTr("Share...") onTriggered: { shareClicked() close() } } // MenuItem // { // visible: Maui.App.handleAccounts // text: qsTr("Copy to cloud") // onTriggered: // { // copyToClicked() // close() // } // } MenuItem { text: qsTr("Show in folder") visible: !isAndroid onTriggered: { openWithClicked() close() } } MenuSeparator {} MenuItem { visible: false text: qsTr("Edit.") onTriggered: { editClicked() close() } } // Maui.MenuItem // { // text: qsTr("Info...") // onTriggered: // { // infoClicked() // close() // } // } MenuItem { - text: qsTr("Remove") + text: qsTr("Delete") Kirigami.Theme.textColor: Kirigami.Theme.negativeTextColor onTriggered: { - removeClicked() - // listModel.remove(list.currentIndex) + deleteClicked() close() } } MenuSeparator {} MenuItem { id: starsRow width: parent.width height: Maui.Style.iconSizes.medium + Maui.Style.space.small RowLayout { anchors.fill: parent ToolButton { Layout.fillWidth: true Layout.fillHeight: true icon.name: starIcon icon.width: Maui.Style.iconSizes.medium icon.color: rate >= 1 ? starColor :starReg onClicked: { rate = 1 rateClicked(rate) close() } } ToolButton { Layout.fillWidth: true Layout.fillHeight: true icon.width: Maui.Style.iconSizes.medium icon.name: starIcon icon.color: rate >= 2 ? starColor :starReg onClicked: { rate = 2 rateClicked(rate) close() } } ToolButton { Layout.fillWidth: true Layout.fillHeight: true icon.width: Maui.Style.iconSizes.medium icon.name: starIcon icon.color: rate >= 3 ? starColor :starReg onClicked: { rate = 3 rateClicked(rate) close() } } ToolButton { Layout.fillWidth: true Layout.fillHeight: true icon.width: Maui.Style.iconSizes.medium icon.name: starIcon icon.color: rate >= 4 ? starColor :starReg onClicked: { rate = 4 rateClicked(rate) close() } } ToolButton { Layout.fillWidth: true Layout.fillHeight: true icon.width: Maui.Style.iconSizes.medium icon.name: starIcon icon.color: rate >= 5 ? starColor :starReg onClicked: { rate = 5 rateClicked(rate) close() } } } } MenuItem { id: colorsRow width: parent.width height: Maui.Style.iconSizes.medium + Maui.Style.space.small ColorTagsBar { anchors.fill: parent onColorClicked: { control.colorClicked(color) control.close() } } } } diff --git a/widgets/MainPlaylist/AlbumsRoll.qml b/widgets/MainPlaylist/AlbumsRoll.qml index 953d2c2..e30f013 100644 --- a/widgets/MainPlaylist/AlbumsRoll.qml +++ b/widgets/MainPlaylist/AlbumsRoll.qml @@ -1,118 +1,124 @@ import QtQuick.Controls 2.10 import QtQuick 2.10 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import QtGraphicalEffects 1.0 import "../../view_models/BabeGrid" import "../../utils/Player.js" as Player Maui.ToolBar { id: control visible: !mainlistEmpty padding: 0 height: Maui.Style.toolBarHeight * 1.2 background: Item { Image { id: artworkBg height: parent.height width: parent.width sourceSize.width: parent.width sourceSize.height: parent.height fillMode: Image.PreserveAspectCrop antialiasing: true smooth: true asynchronous: true cache: true source: currentArtwork } FastBlur { id: fastBlur anchors.fill: parent source: artworkBg radius: 100 transparentBorder: false cached: true Rectangle { anchors.fill: parent color: Kirigami.Theme.backgroundColor opacity: 0.8 } } Kirigami.Separator { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right } } + rightContent: ToolButton + { + icon.name: "document-save" + onClicked: mainPlaylist.table.saveList() + } + middleContent: ListView { id: _listView Layout.fillWidth: true Layout.preferredHeight: Maui.Style.toolBarHeight orientation: ListView.Horizontal clip: true focus: true interactive: true currentIndex: currentTrackIndex spacing: Maui.Style.space.medium cacheBuffer: control.width * 1 onCurrentIndexChanged: positionViewAtIndex(currentIndex, ListView.Center) highlightFollowsCurrentItem: true highlightMoveDuration: 0 snapMode: ListView.SnapToOneItem model: mainPlaylist.listModel highlightRangeMode: ListView.StrictlyEnforceRange keyNavigationEnabled: true keyNavigationWraps : true onMovementEnded: { var index = indexAt(contentX, contentY) if(index !== currentTrackIndex) Player.playAt(index) } delegate: Maui.ItemDelegate { id: _delegate height: _listView.height width: _listView.width padding: 0 Kirigami.Theme.inherit: true Maui.ListItemTemplate { anchors.fill: parent iconSizeHint: height - Maui.Style.space.small imageSource: model.artwork ? model.artwork : "qrc:/assets/cover.png" label1.text: model.title label2.text: model.artist + " | " + model.album } onClicked: focusView = true background: null } } } diff --git a/widgets/MainPlaylist/MainPlaylist.qml b/widgets/MainPlaylist/MainPlaylist.qml index 800dd9e..d8f4a2e 100644 --- a/widgets/MainPlaylist/MainPlaylist.qml +++ b/widgets/MainPlaylist/MainPlaylist.qml @@ -1,141 +1,142 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import QtGraphicalEffects 1.0 import org.kde.kirigami 2.2 as Kirigami import org.kde.mauikit 1.0 as Maui import "../../utils/Player.js" as Player import "../../db/Queries.js" as Q import "../../utils" import "../../widgets" import "../../view_models" import "../../view_models/BabeTable" Maui.Page { id: mainPlaylistRoot property alias list : table.list property alias listModel: table.listModel property alias listView : table.listView property alias table: table property alias menu : playlistMenu property alias contextMenu: table.contextMenu signal coverDoubleClicked(var tracks) signal coverPressed(var tracks) focus: true headBar.visible: false PlaylistMenu { id: playlistMenu onClearOut: Player.clearOutPlaylist() onClean: Player.cleanPlaylist() onSaveToClicked: table.saveList() } footer: AlbumsRoll { id: _albumsRoll width: table.width position: ToolBar.Footer } BabeTable { id: table anchors.fill: parent focus: true headBar.visible: false footBar.visible: false coverArtVisible: true holder.emoji: "qrc:/assets/dialog-information.svg" holder.isMask: false holder.title : "Meh!" holder.body: "Start putting together your playlist!" holder.emojiSize: Maui.Style.iconSizes.huge onRowClicked: play(index) + showQuickActions: false onArtworkDoubleClicked: contextMenu.babeIt(index) property int startContentY Component.onCompleted: { var lastplaylist = Maui.FM.loadSettings("LASTPLAYLIST", "PLAYLIST", []) var n = lastplaylist.length if(n>0) { for(var i = 0; i < n; i++) { var where = "url = \""+lastplaylist[i]+"\"" var query = Q.GET.tracksWhere_.arg(where) table.list.appendQuery(query); } }else { where = "fav = 1" query = Q.GET.tracksWhere_.arg(where) table.list.appendQuery(query); } // if(autoplay) // Player.playAt(0) } } // function goFocusMode() // { // if(focusMode) // { // if(isMobile) // { // root.width = screenWidth // root.height= screenHeight // }else // { // cover.y = 0 // root.maximumWidth = screenWidth // root.minimumWidth = columnWidth // root.maximumHeight = screenHeight // root.minimumHeight = columnWidth // root.width = columnWidth // root.height = 700 // } // }else // { // if(isMobile) // { // }else // { // root.maximumWidth = columnWidth // root.minimumWidth = columnWidth // root.maximumHeight = columnWidth // root.minimumHeight = columnWidth // // root.footer.visible = false // // mainlistContext.visible = false // } // } // focusMode = !focusMode // } function play(index) { prevTrackIndex = currentTrackIndex Player.playAt(index) } }