diff --git a/main.qml b/main.qml index fb38d26..525584a 100644 --- a/main.qml +++ b/main.qml @@ -1,925 +1,930 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.1 import QtQuick.Window 2.0 import "services/local" import "utils" import "widgets" import "widgets/MyBeatView" import "widgets/PlaylistsView" import "widgets/MainPlaylist" import "widgets/SettingsView" import "widgets/SearchView" import "view_models" import "view_models/BabeDialog" import "services/web" import "db/Queries.js" as Q import "utils/Player.js" as Player import "utils/Help.js" as H import org.kde.kirigami 2.2 as Kirigami import Link.Codes 1.0 Kirigami.ApplicationWindow { id: root visible: true width: Screen.width * (isMobile ? 1 : 0.4) minimumWidth: !isMobile ? columnWidth : 0 minimumHeight: !isMobile ? columnWidth + 64 : 0 height: Screen.height * (isMobile ? 1 : 0.4) title: qsTr("vvave") // wideScreen: root.width > coverSize /*ALIASES*/ property alias playIcon: playIcon property alias babeBtnIcon: babeBtnIcon property alias progressBar: progressBar property alias animFooter: animFooter property alias mainPlaylist: mainPlaylist readonly property bool isMobile : Kirigami.Settings.isMobile readonly property bool isAndroid: bae.isAndroid() /***************************************************/ /******************** PLAYBACK ********************/ /*************************************************/ property bool isShuffle: false property var currentTrack: ({ babe: "0", stars: "0" }) property int currentTrackIndex: 0 property int prevTrackIndex: 0 property string currentArtwork: !mainlistEmpty ? mainPlaylist.list.model.get( 0).artwork : "" property bool currentBabe: currentTrack.babe == "0" ? false : true property string durationTimeLabel: "00:00" property string progressTimeLabel: "00:00" property bool isPlaying: false property bool autoplay: bae.loadSetting("AUTOPLAY", "BABE", false) === "true" ? true : false property int onQueue: 0 property bool mainlistEmpty: !mainPlaylist.table.count > 0 /***************************************************/ /******************** UI PROPS ********************/ /*************************************************/ readonly property real opacityLevel: 0.8 readonly property int wideSize: Screen.width * 0.5 readonly property int rowHeight: (defaultFontSize*2) + space.big readonly property int rowHeightAlt: (defaultFontSize*2) + space.big readonly property int headerHeight: rowHeight property int toolBarIconSize: bae.loadSetting("ICON_SIZE", "BABE", iconSizes.medium) - property int toolBarHeight: isMobile ? 48 : Kirigami.Units.iconSizes.smallMedium + Kirigami.Units.smallSpacing*2 + property int toolBarHeight: Kirigami.Units.iconSizes.medium + (Kirigami.Settings.isMobile ? Kirigami.Units.smallSpacing : Kirigami.Units.largeSpacing) property int miniArtSize: iconSizes.large property int columnWidth: Kirigami.Units.gridUnit * 17 property int coverSize: isAndroid ? Math.sqrt(root.width * root.height) * 0.4 : - columnWidth * (isMobile ? 0.5 : 0.6) + columnWidth * (isMobile ? 0.7 : 0.6) /***************************************************/ /******************** HANDLERS ********************/ /*************************************************/ property int currentView: viewsIndex.tracks readonly property var viewsIndex: ({ tracks: 0, albums: 1, artists: 2, playlists: 3, babeit: 4, search: 5, youtube: 6, linking: 7 }) property string syncPlaylist: "" property bool sync: false property string infoMsg: "" property bool infoLabels: bae.loadSetting("PLAYBACKINFO", "BABE", false) == "true" ? true : false property bool isLinked: false property bool isServing: false /* ANDROID THEMING*/ Material.theme: Material.Light Material.accent: babeColor Material.background: viewBackgroundColor Material.primary: backgroundColor Material.foreground: textColor /***************************************************/ /******************** UI UNITS ********************/ /*************************************************/ property int iconSize : iconSizes.medium readonly property real factor : Kirigami.Units.gridUnit * (isMobile ? 0.2 : 0.2) readonly property int contentMargins: space.medium readonly property int defaultFontSize: Kirigami.Theme.defaultFont.pointSize readonly property var fontSizes: ({ tiny: defaultFontSize * 0.4, small: (isMobile ? defaultFontSize * 0.4 : defaultFontSize * 0.6), medium: (isMobile ? defaultFontSize * 0.6 : defaultFontSize * 0.8), default: (isMobile ? defaultFontSize * 0.8 : defaultFontSize), big: (isMobile ? defaultFontSize : defaultFontSize * 1.2), large: (isMobile ? defaultFontSize * 1.2 : defaultFontSize * 1.4) }) readonly property var space : ({ tiny: Kirigami.Units.smallSpacing, small: Kirigami.Units.smallSpacing*2, medium: Kirigami.Units.largeSpacing, big: Kirigami.Units.largeSpacing*2, large: Kirigami.Units.largeSpacing*3, huge: Kirigami.Units.largeSpacing*4, enormus: Kirigami.Units.largeSpacing*5 }) readonly property var iconSizes : ({ tiny : Kirigami.Units.iconSizes.small*0.5, small : (isMobile ? Kirigami.Units.iconSizes.small*0.5: Kirigami.Units.iconSizes.small), medium : (isMobile ? (isAndroid ? 22 : Kirigami.Units.iconSizes.small) : Kirigami.Units.iconSizes.smallMedium), big: (isMobile ? Kirigami.Units.iconSizes.smallMedium : Kirigami.Units.iconSizes.medium), large: (isMobile ? Kirigami.Units.iconSizes.medium : Kirigami.Units.iconSizes.large), huge: (isMobile ? Kirigami.Units.iconSizes.large : Kirigami.Units.iconSizes.huge), enormous: (isMobile ? Kirigami.Units.iconSizes.huge : Kirigami.Units.iconSizes.enormous) }) /***************************************************/ /**************************************************/ /*************************************************/ /***************************************************/ /******************** UI COLORS *******************/ /*************************************************/ property string backgroundColor: Kirigami.Theme.backgroundColor property string textColor: Kirigami.Theme.textColor property string highlightColor: Kirigami.Theme.highlightColor property string highlightedTextColor: Kirigami.Theme.highlightedTextColor property string buttonBackgroundColor: Kirigami.Theme.buttonBackgroundColor property string viewBackgroundColor: Kirigami.Theme.viewBackgroundColor property string altColor: Kirigami.Theme.complementaryBackgroundColor property string babeColor: bae.babeColor() readonly property string darkBackgroundColor: "#303030" readonly property string darktextColor: "#FAFAFA" readonly property string darkBabeHighlightColor: "#29B6F6" readonly property string darkHighlightTextColor: darktextColor readonly property string darkMidColor: "#1d1d1d" readonly property string darkMidLightColor: "#282828" readonly property string darkDarkColor: "#191919" readonly property string darkBaseColor: "#212121" readonly property string darkAltColor: darkDarkColor readonly property string darkShadowColor: darkAltColor /***************************************************/ /**************************************************/ /*************************************************/ /*SIGNALS*/ signal missingAlert(var track) /*CONF*/ pageStack.defaultColumnWidth: columnWidth pageStack.initialPage: [mainPlaylist, views] pageStack.interactive: isMobile pageStack.separatorVisible: pageStack.wideMode overlay.modal: Rectangle { color: isAndroid ? darkColor : "transparent" opacity: 0.5 height: root.height - playbackControls.height - toolbar.height y: toolbar.height } overlay.modeless: Rectangle { color: "transparent" } /*HANDLE EVENTS*/ onWidthChanged: if (isMobile) { if (width > height) mainPlaylist.cover.visible = false else mainPlaylist.cover.visible = true } onClosing: Player.savePlaylist() // pageStack.onCurrentIndexChanged: // { // if(pageStack.currentIndex === 0 && isMobile && !pageStack.wideMode) // { // bae.androidStatusBarColor(babeColor) // Material.background = babeColor // }else // { // bae.androidStatusBarColor(babeAltColor) // Material.background = babeAltColor // } // } onMissingAlert: { missingDialog.message = track.title + " by " + track.artist + " is missing" missingDialog.messageBody = "Do you want to remove it from your collection?" missingDialog.open() } /*COMPONENTS*/ BabeNotify { id: babeNotify } BabeMessage { id: missingDialog width: isMobile ? parent.width * 0.9 : parent.width * 0.4 title: "Missing file" onAccepted: { bae.removeTrack(currentTrack.url) mainPlaylist.table.model.remove(mainPlaylist.table.currentIndex) } } /* UI */ header: BabeBar { id: toolbar + width: root.width + height: toolBarHeight + visible: true currentIndex: currentView onSettingsViewClicked: settingsDrawer.visible ? settingsDrawer.close( ) : settingsDrawer.open() onTracksViewClicked: { pageStack.currentIndex = 1 currentView = viewsIndex.tracks } onAlbumsViewClicked: { pageStack.currentIndex = 1 currentView = viewsIndex.albums } onArtistsViewClicked: { pageStack.currentIndex = 1 currentView = viewsIndex.artists } onPlaylistsViewClicked: { pageStack.currentIndex = 1 currentView = viewsIndex.playlists } onBabeViewClicked: { pageStack.currentIndex = 1 currentView = viewsIndex.babeit } onSearchViewClicked: { pageStack.currentIndex = 1 currentView = viewsIndex.search searchView.searchInput.forceActiveFocus() } } footer: ToolBar { id: playbackControls position: ToolBar.Footer - height: visible ? headerHeight : 0 + width: root.width + height: toolBarHeight + visible: true focus: true leftPadding: 0 rightPadding: 0 FastBlur { width: parent.width height: parent.height-1 y:1 source: mainPlaylist.artwork radius: 100 transparentBorder: false cached: true z: -999 } Rectangle { id: footerBg anchors.fill: parent color: darkBaseColor opacity: opacityLevel z: -999 SequentialAnimation { id: animFooter PropertyAnimation { target: footerBg property: "color" easing.type: Easing.InOutQuad from: "black" to: darkBaseColor duration: 500 } } } Slider { id: progressBar height: iconSizes.small width: parent.width anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top padding: 0 from: 0 to: 1000 value: 0 spacing: 0 focus: true onMoved: player.seek(player.duration() / 1000 * value) background: Rectangle { x: progressBar.leftPadding y: progressBar.y implicitWidth: 200 implicitHeight: iconSizes.tiny*0.1 width: progressBar.availableWidth height: implicitHeight color: "transparent" Rectangle { width: progressBar.visualPosition * parent.width height: iconSizes.tiny*0.1 color: babeColor } } handle: Rectangle { x: progressBar.leftPadding + progressBar.visualPosition * (progressBar.availableWidth - width) y: progressBar.y - (height / 2) implicitWidth: progressBar.pressed ? iconSizes.medium : 0 implicitHeight: progressBar.pressed ? iconSizes.medium : 0 radius: progressBar.pressed ? iconSizes.medium : 0 color: babeColor } } GridLayout { id: playbackControlsLayout anchors.fill: parent height: parent.height width: parent.width columnSpacing: 0 rows: 2 columns: 2 Item { Layout.alignment: Qt.AlignLeft Layout.fillHeight: true - Layout.maximumWidth: miniArtwork.visible ? headerHeight : 0 - Layout.minimumWidth: miniArtwork.visible ? headerHeight : 0 - Layout.minimumHeight: miniArtwork.visible ? headerHeight : 0 - Layout.maximumHeight: miniArtwork.visible ? headerHeight : 0 + Layout.maximumWidth: miniArtwork.visible ? toolBarHeight : 0 + Layout.minimumWidth: miniArtwork.visible ? toolBarHeight : 0 + Layout.minimumHeight: miniArtwork.visible ? toolBarHeight : 0 + Layout.maximumHeight: miniArtwork.visible ? toolBarHeight : 0 Layout.row: 1 Layout.rowSpan: 2 Layout.column: 1 anchors.verticalCenter: parent.top z: progressBar.z+1 Rectangle { visible: miniArtwork.visible anchors.centerIn: parent height: miniArtSize + miniArtSize*0.05 width: miniArtSize + miniArtSize*0.05 color: darktextColor opacity: opacityLevel z: -999 radius: Math.min(width, height) } RotationAnimator on rotation { from: 0 to: 360 duration: 5000 loops: Animation.Infinite running: miniArtwork.visible && isPlaying } Image { id: miniArtwork visible: ((!pageStack.wideMode && pageStack.currentIndex !== 0) || !mainPlaylist.cover.visible) && !mainlistEmpty focus: true height: miniArtSize width: miniArtSize // anchors.left: parent.left anchors.centerIn: parent source: { if (currentArtwork) (currentArtwork.length > 0 && currentArtwork !== "NONE") ? "file://" + encodeURIComponent( currentArtwork) : "qrc:/assets/cover.png" else "qrc:/assets/cover.png" } fillMode: Image.PreserveAspectFit cache: false antialiasing: true MouseArea { anchors.fill: parent onClicked: { if (!isMobile && pageStack.wideMode) root.width = columnWidth pageStack.currentIndex = 0 } } layer.enabled: true layer.effect: OpacityMask { maskSource: Item { width: miniArtwork.width height: miniArtwork.height Rectangle { anchors.centerIn: parent width: miniArtwork.adapt ? miniArtwork.width : Math.min( miniArtwork.width, miniArtwork.height) height: miniArtwork.adapt ? miniArtwork.height : width radius: Math.min(width, height) } } } } } Item { Layout.alignment: Qt.AlignCenter Layout.fillWidth: true Layout.fillHeight: true Layout.row: 2 Layout.column: 2 Layout.maximumHeight: playbackInfo.visible ? playbackInfo.font.pointSize * 2 : 0 Label { id: playbackInfo visible: !mainlistEmpty && infoLabels // anchors.top: playIcon.bottom // anchors.horizontalCenter: playIcon.horizontalCenter width: parent.width height: parent.height horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter text: progressTimeLabel + " / " + (currentTrack ? (currentTrack.title ? currentTrack.title + " - " + currentTrack.artist : "--- - " + currentTrack.artist) : "") + " / " + durationTimeLabel color: darktextColor - font.pointSize: fontSizes.tiny + font.pointSize: fontSizes.small elide: Text.ElideRight } } RowLayout { Layout.fillWidth: true Layout.fillHeight: true Layout.alignment: Qt.AlignCenter Layout.row: 1 Layout.column: 2 BabeButton { id: babeBtnIcon iconName: "love" iconColor: currentBabe ? babeColor : darktextColor onClicked: if (!mainlistEmpty) { var value = mainPlaylist.contextMenu.babeIt( currentTrackIndex) currentBabe = value } } BabeButton { id: previousBtn iconColor: darktextColor iconName: "media-skip-backward" onClicked: Player.previousTrack() onPressAndHold: Player.playAt(prevTrackIndex) } BabeButton { id: playIcon iconColor: darktextColor iconName: isPlaying ? "media-playback-pause" : "media-playback-start" onClicked: { if (isPlaying) Player.pauseTrack() else Player.resumeTrack() } } BabeButton { id: nextBtn iconColor: darktextColor iconName: "media-skip-forward" onClicked: Player.nextTrack() onPressAndHold: Player.playAt(Player.shuffle()) } BabeButton { id: shuffleBtn iconColor: darktextColor iconName: isShuffle ? "media-playlist-shuffle" : "media-playlist-repeat" onClicked: isShuffle = !isShuffle } } } } background: Rectangle { anchors.fill: parent color: altColor z: -999 } globalDrawer: SettingsView { id: settingsDrawer // contentItem.implicitWidth: columnWidth onIconSizeChanged: toolBarIconSize = size } Item { id: message visible: infoMsg.length > 0 && sync anchors.bottom: parent.bottom width: pageStack.wideMode ? columnWidth : parent.width height: toolBarIconSize z: 999 Rectangle { id: infoBg anchors.fill: parent z: -999 color: altColor opacity: opacityLevel SequentialAnimation { id: animBg PropertyAnimation { target: infoBg property: "color" easing.type: Easing.InOutQuad to: babeColor duration: 250 } PropertyAnimation { target: infoBg property: "color" easing.type: Easing.InOutQuad to: altColor duration: 500 } } } Label { id: infoTxt anchors.centerIn: parent anchors.fill: parent height: parent.height width: parent.width font.pointSize: fontSizes.medium text: infoMsg horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter color: textColor SequentialAnimation { id: animTxt PropertyAnimation { target: infoTxt property: "color" easing.type: Easing.InOutQuad to: "white" duration: 250 } PropertyAnimation { target: infoTxt property: "color" easing.type: Easing.InOutQuad to: textColor duration: 500 } } } } MainPlaylist { id: mainPlaylist anchors.fill: parent clip: true Connections { target: mainPlaylist onCoverPressed: Player.appendAll(tracks) onCoverDoubleClicked: Player.playAll(tracks) } } Page { id: views anchors.fill: parent clip: true // focusPolicy: Qt.WheelFocus // visualFocus: true Column { anchors.fill: parent SwipeView { id: swipeView width: parent.width height: parent.height Component.onCompleted: contentItem.interactive = isMobile currentIndex: currentView onCurrentItemChanged: currentItem.forceActiveFocus() onCurrentIndexChanged: { currentView = currentIndex if (pageStack.currentIndex === 0) mainPlaylist.list.forceActiveFocus() else if (currentView === viewsIndex.tracks) tracksView.forceActiveFocus() else if (currentView === viewsIndex.search) searchView.forceActiveFocus() if (!babeitView.isConnected && currentIndex === viewsIndex.babeit) babeitView.logginDialog.open() } TracksView { id: tracksView Connections { target: tracksView onRowClicked: Player.addTrack( tracksView.model.get(index)) onQuickPlayTrack: Player.quickPlay( tracksView.model.get(index)) onPlayAll: Player.playAll(bae.get(Q.GET.allTracks)) onAppendAll: Player.appendAll(bae.get(Q.GET.allTracks)) onQueueTrack: Player.queueTracks( [tracksView.model.get(index)]) } } AlbumsView { id: albumsView Connections { target: albumsView onRowClicked: Player.addTrack(track) onPlayAlbum: Player.playAll(tracks) onAppendAlbum: Player.appendAll(tracks) onPlayTrack: Player.quickPlay(track) } } ArtistsView { id: artistsView Connections { target: artistsView onRowClicked: Player.addTrack(track) onPlayAlbum: Player.playAll(tracks) onAppendAlbum: Player.appendAll(tracks) onPlayTrack: Player.quickPlay(track) } } PlaylistsView { id: playlistsView Connections { target: playlistsView onRowClicked: Player.addTrack(track) onQuickPlayTrack: Player.quickPlay(track) onPlayAll: Player.playAll(tracks) onAppendAll: Player.appendAll(tracks) onPlaySync: { var tracks = bae.get(Q.GET.playlistTracks_.arg( playlist)) Player.playAll(tracks) root.sync = true root.syncPlaylist = playlist root.infoMsg = "Syncing to " + playlist console.log("ALLOW PLAYLIOST SYNC FOR: ", root.syncPlaylist = playlist) } } } BabeitView { id: babeitView } SearchTable { id: searchView Connections { target: searchView.searchTable onRowClicked: Player.addTrack( searchView.searchTable.model.get( index)) onQuickPlayTrack: Player.quickPlay( searchView.searchTable.model.get( index)) onPlayAll: Player.playAll(searchView.searchRes) onAppendAll: Player.appendAll(searchView.searchRes) onArtworkDoubleClicked: { var query = Q.GET.albumTracks_.arg( searchView.searchTable.model.get( index).album) query = query.arg(searchView.searchTable.model.get( index).artist) Player.playAll(bae.get(query)) } } } YouTube { id: youtubeView } LinkingView { id: linkingView } } } } /*animations*/ pageStack.layers.popEnter: Transition { PauseAnimation { duration: Kirigami.Units.longDuration } } pageStack.layers.popExit: Transition { YAnimator { from: 0 to: pageStack.layers.height duration: Kirigami.Units.longDuration easing.type: Easing.OutCubic } } pageStack.layers.pushEnter: Transition { YAnimator { from: pageStack.layers.height to: 0 duration: Kirigami.Units.longDuration easing.type: Easing.OutCubic } } pageStack.layers.pushExit: Transition { PauseAnimation { duration: Kirigami.Units.longDuration } } pageStack.layers.replaceEnter: Transition { YAnimator { from: pageStack.layers.width to: 0 duration: Kirigami.Units.longDuration easing.type: Easing.OutCubic } } pageStack.layers.replaceExit: Transition { PauseAnimation { duration: Kirigami.Units.longDuration } } /*FUNCTIONS*/ function infoMsgAnim() { animBg.running = true animTxt.running = true } Component.onCompleted: { // if(isMobile) settingsDrawer.switchColorScheme(bae.loadSetting("THEME", "BABE", "Dark")) // console.log(Imagine.url, Imagine.path) bae.androidStatusBarColor(viewBackgroundColor) } /*CONNECTIONS*/ Connections { target: player onPos: progressBar.value = pos onTiming: progressTimeLabel = time onDurationChanged: durationTimeLabel = time onFinished: if (!mainlistEmpty) { if (currentTrack.url) bae.playedTrack(currentTrack.url) Player.nextTrack() } onIsPlaying: isPlaying = playing } Connections { target: bae onRefreshTables: H.refreshCollection(size) onRefreshTracks: H.refreshTracks() onRefreshAlbums: H.refreshAlbums() onRefreshArtists: H.refreshArtists() onTrackLyricsReady: { if (url === currentTrack.url) Player.setLyrics(lyrics) } onSkipTrack: Player.nextTrack() onBabeIt: Player.babeTrack() } } diff --git a/services/web/YouTube.qml b/services/web/YouTube.qml index 77dc921..7044b3e 100644 --- a/services/web/YouTube.qml +++ b/services/web/YouTube.qml @@ -1,327 +1,319 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import "../../view_models" import "../../view_models/BabeTable" import org.kde.kirigami 2.2 as Kirigami Page { id: youtubeViewRoot property var searchRes : [] clip: true property alias viewer : youtubeViewer property int openVideo : 0 Connections { target: youtube onQueryResultsReady: { searchRes = res; populate(searchRes) youtubeTable.forceActiveFocus() if(openVideo > 0) { console.log("trying to open video") watchVideo(youtubeTable.model.get(openVideo-1)) openVideo = 0 } } } function watchVideo(track) { if(track && track.url) { var url = track.url if(url && url.length > 0) { youtubeViewer.currentYt = track youtubeViewer.webView.url = url+"?autoplay=1" stackView.push(youtubeViewer) } } } function playTrack(url) { if(url && url.length > 0) { var newURL = url.replace("embed/", "watch?v=") console.log(newURL) youtubePlayer.item.url = newURL+"?autoplay=1+&vq=tiny" youtubePlayer.item.runJavaScript("document.title", function(result) { console.log(result); }); } } function runSearch(searchTxt) { if(searchTxt) if(searchTxt !== youtubeTable.headerBarTitle) { youtubeTable.headerBarTitle = searchTxt youtube.getQuery(searchTxt, bae.loadSetting("YOUTUBELIMIT", "BABE", 25)) } } function clearSearch() { searchInput.clear() youtubeTable.clearTable() youtubeTable.headerBarTitle = "" searchRes = [] } function populate(tracks) { youtubeTable.clearTable() for(var i in tracks) youtubeTable.model.append(tracks[i]) } Loader { id: youtubePlayer source: isAndroid ? "qrc:/services/web/YoutubePlayer_A.qml" : "qrc:/services/web/YoutubePlayer.qml" } BabePopup { id: configPopup parent: parent margins: contentMargins GridLayout { anchors.centerIn: parent width: parent.width*0.8 height: parent.height*0.9 columns: 1 rows: 6 Item { Layout.column: 1 Layout.row: 1 Layout.fillWidth: true Layout.fillHeight: true } Label { text: qsTr("Custom API Key") verticalAlignment: Qt.AlignVCenter elide: Text.ElideRight font.pointSize: fontSizes.default Layout.column: 1 Layout.row: 2 Layout.fillWidth: true } TextField { Layout.column: 1 Layout.row: 3 Layout.fillWidth: true text: bae.loadSetting("YOUTUBEKEY", "BABE", youtube.getKey()) } Label { text: qsTr("Search results") verticalAlignment: Qt.AlignVCenter elide: Text.ElideRight font.pointSize: fontSizes.default Layout.column: 1 Layout.row: 4 Layout.fillWidth: true } SpinBox { Layout.alignment: Qt.AlignRight Layout.column: 1 Layout.row: 5 Layout.fillWidth: true from: 1 to: 50 value: bae.loadSetting("YOUTUBELIMIT", "BABE", 25) editable: true onValueChanged: { bae.saveSetting("YOUTUBELIMIT", value, "BABE") } } Item { Layout.column: 1 Layout.row: 6 Layout.fillWidth: true Layout.fillHeight: true } } } StackView { id: stackView anchors.fill: parent focus: true pushEnter: Transition { PropertyAnimation { property: "opacity" from: 0 to:1 duration: 200 } } pushExit: Transition { PropertyAnimation { property: "opacity" from: 1 to:0 duration: 200 } } popEnter: Transition { PropertyAnimation { property: "opacity" from: 0 to:1 duration: 200 } } popExit: Transition { PropertyAnimation { property: "opacity" from: 1 to:0 duration: 200 } } initialItem: Item { id: youtubeList ColumnLayout { anchors.fill: parent width: parent.width height: parent.height Layout.margins: 0 spacing: 0 BabeTable { id: youtubeTable Layout.fillHeight: true Layout.fillWidth: true trackNumberVisible: false headerBarVisible: true headerBarExit: true headerBarExitIcon: "edit-clear" holder.message: "No YouTube results!" coverArtVisible: true trackDuration: true trackRating: true onExit: clearSearch() isArtworkRemote: true allowMenu: false appendBtn.visible: false playAllBtn.visible: false menuBtn.visible: false headerBarRight: BabeButton { id: menuBtn iconName: "application-menu" onClicked: configPopup.open() } onRowClicked: { watchVideo(youtubeTable.model.get(index)) } onQuickPlayTrack: { playTrack(youtubeTable.model.get(index).url) } } - Kirigami.Separator - { - visible: !isMobile - Layout.fillWidth: true - width: parent.width - height: 1 - } - ToolBar { id: searchBox Layout.fillWidth: true - position: ToolBar.Footer + position: ToolBar.Footer RowLayout { anchors.fill: parent TextInput { id: searchInput color: textColor Layout.fillWidth: true Layout.fillHeight: true horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter selectByMouse: !isMobile selectionColor: highlightColor selectedTextColor: highlightedTextColor focus: true text: "" wrapMode: TextEdit.Wrap onAccepted: runSearch(searchInput.text) } BabeButton { Layout.rightMargin: contentMargins iconName: "edit-clear" onClicked: searchInput.clear() } } } } } YoutubeViewer { id: youtubeViewer } } } diff --git a/view_models/BabeButton.qml b/view_models/BabeButton.qml index 0bd4446..b19363c 100644 --- a/view_models/BabeButton.qml +++ b/view_models/BabeButton.qml @@ -1,63 +1,61 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import "../utils" import org.kde.kirigami 2.2 as Kirigami ToolButton { id: babeButton property string iconName property int iconSize : toolBarIconSize property color iconColor: textColor readonly property string defaultColor : textColor property bool anim : false - // icon.name: isAndroid ? "" : babeButton.iconName - // icon.width: isAndroid ? 0 : babeButton.iconSize - // icon.height: isAndroid ? 0 : babeButton.iconSize - // icon.color: isAndroid ? "transparent" : (iconColor || defaultColor) + icon.name: isAndroid ? "" : babeButton.iconName + icon.width: isAndroid ? 0 : babeButton.iconSize + icon.height: isAndroid ? 0 : babeButton.iconSize + icon.color: isAndroid ? "transparent" : (down ? babeColor : (iconColor || defaultColor)) onClicked: if(anim) animIcon.running = true flat: true highlighted: false - Kirigami.Icon - { - id: kirigamIcon - anchors.centerIn: parent - width: iconSize - height: iconSize - visible: !isAndroid - source: isAndroid ? "" : iconName - isMask: false - color: iconColor || defaultColor - - } +// Kirigami.Icon +// { +// id: kirigamIcon +// anchors.centerIn: parent +// width: iconSize +// height: iconSize +// visible: !isAndroid +// source: isAndroid ? "" : iconName +// isMask: false +// color: iconColor || defaultColor + +// } BabeIcon { id: babeIcon visible: isAndroid icon: babeButton.iconName iconColor: babeButton.iconColor || babeButton.defaultColor iconSize: babeButton.iconSize } SequentialAnimation { id: animIcon PropertyAnimation { target: babeIcon property: "color" easing.type: Easing.InOutQuad from: babeColor to: iconColor duration: 500 } } } - - diff --git a/view_models/BabeDialog/BabeDialog.qml b/view_models/BabeDialog/BabeDialog.qml index 67222e9..62e9ccb 100644 --- a/view_models/BabeDialog/BabeDialog.qml +++ b/view_models/BabeDialog/BabeDialog.qml @@ -1,25 +1,25 @@ import QtQuick 2.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.1 Dialog { width: columnWidth * 0.9 height: parent.height*0.5 x: (parent.width - width) / 2 y: (parent.height - height) / 2 parent: ApplicationWindow.overlay modal: true - margins: 1 - padding: 2 + margins: 0 + padding: space.tiny Material.accent: babeColor Material.background: backgroundColor Material.primary: backgroundColor Material.foreground: textColor } diff --git a/view_models/BabeGrid/BabeGrid.qml b/view_models/BabeGrid/BabeGrid.qml index f2013cc..b9be12e 100644 --- a/view_models/BabeGrid/BabeGrid.qml +++ b/view_models/BabeGrid/BabeGrid.qml @@ -1,120 +1,119 @@ import QtQuick.Controls 2.2 import QtQuick 2.9 import ".." Pane { id: gridPage - padding: 20 + padding: space.big // readonly property int screenSize : bae.screenGeometry("width")*bae.screenGeometry("height"); - property int hintSize : Math.sqrt(root.width*root.height)*0.3 +// property int hintSize : Math.sqrt(root.width*root.height)*0.3 - property int albumCoverSize: isMobile ? iconSizes.huge : iconSizes.enormous - readonly property int albumSpacing: albumCoverSize*0.5 + space.big + property int albumCoverSize: isMobile ? iconSizes.enormous : iconSizes.enormous + readonly property int albumSpacing: albumCoverSize*0.5 + (isMobile ? space.small : space.big) property int albumCoverRadius : albumCoverSize*0.05 property bool albumCardVisible : true property alias gridModel: gridModel property alias grid: grid signal albumCoverClicked(string album, string artist) signal albumCoverPressed(string album, string artist) signal bgClicked() onWidthChanged: grid.forceLayout() function clearGrid() { gridModel.clear() } MouseArea { anchors.fill: parent onClicked: bgClicked() } BabeHolder { visible: grid.count === 0 message: "No albums..." } ListModel {id: gridModel} GridView { id: grid clip: true MouseArea { anchors.fill: parent onClicked: bgClicked() z: -999 } width: parent.width height: parent.height cellWidth: albumCoverSize + albumSpacing cellHeight: albumCoverSize + albumSpacing focus: true boundsBehavior: Flickable.StopAtBounds flickableDirection: Flickable.AutoFlickDirection snapMode: GridView.SnapToRow // flow: GridView.FlowTopToBottom // maximumFlickVelocity: albumSize*8 model: gridModel delegate: BabeAlbum { id: albumDelegate albumSize : albumCoverSize albumRadius: albumCoverRadius albumCard: albumCardVisible height: grid.cellHeight width: grid.cellWidth Connections { target: albumDelegate onAlbumClicked: { var album = grid.model.get(index).album var artist = grid.model.get(index).artist albumCoverClicked(album, artist) grid.currentIndex = index } onAlbumPressed: { var album = grid.model.get(index).album var artist = grid.model.get(index).artist albumCoverPressed(album, artist) } } } ScrollBar.vertical:BabeScrollBar { visible: true } onWidthChanged: { var amount = parseInt(width/(albumCoverSize + albumSpacing),10) var leftSpace = parseInt(width-(amount*(albumCoverSize + albumSpacing)), 10) var size = parseInt((albumCoverSize + albumSpacing)+(parseInt(leftSpace/amount, 10)), 10) size = size > albumCoverSize + albumSpacing? size : albumCoverSize + albumSpacing cellWidth = size // grid.cellHeight = size } } - } diff --git a/view_models/BabeMenu/BabeMenu.qml b/view_models/BabeMenu/BabeMenu.qml index b2491e3..16b7578 100644 --- a/view_models/BabeMenu/BabeMenu.qml +++ b/view_models/BabeMenu/BabeMenu.qml @@ -1,27 +1,27 @@ import QtQuick 2.0 import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.1 Menu { x: parent.width / 2 - width / 2 y: parent.height / 2 - height / 2 modal: true focus: true parent: ApplicationWindow.overlay - margins: 1 - padding: 2 + margins: space.tiny + padding: space.tiny // enter: Transition // { // NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } // } Material.accent: babeColor Material.background: backgroundColor Material.primary: backgroundColor Material.foreground: textColor } diff --git a/view_models/BabeTable/PlaylistDialog.qml b/view_models/BabeTable/PlaylistDialog.qml index 82489dc..c8b4a9b 100644 --- a/view_models/BabeTable/PlaylistDialog.qml +++ b/view_models/BabeTable/PlaylistDialog.qml @@ -1,124 +1,125 @@ import QtQuick 2.0 import QtQuick.Controls 2.2 import org.kde.kirigami 2.2 as Kirigami import QtQuick.Layouts 1.3 import "../../view_models/BabeDialog" import "../../view_models" import "../../utils/Player.js" as Player import "../../db/Queries.js" as Q BabeDialog { title: "Add "+ tracks.length +" tracks to..." standardButtons: Dialog.Save | Dialog.Cancel property var tracks : [] ColumnLayout { - spacing: 20 + spacing: space.small anchors.fill: parent BabeList { id: playlistsList Layout.fillHeight: true Layout.fillWidth: true headerBarVisible: false holder.message: "

There's not playlists


Create a new one and start adding tracks to it

" ListModel { id: listModel } model: listModel delegate: BabeDelegate { id: delegate label: playlist Connections { target: delegate onClicked: playlistsList.currentIndex = index onPressAndHold: { playlistsList.currentIndex = index Player.addToPlaylist(tracks, playlistsList.model.get(playlistsList.currentIndex).playlist) close() } } } } RowLayout { Layout.fillWidth: true - Layout.margins: contentMargins + Layout.margins: space.small TextField { Layout.fillWidth: true + width: parent.width id: newPlaylistField color: textColor placeholderText: qsTr("New playlist") onAccepted: { addPlaylist() clear() close() } } BabeButton { iconName: "checkbox" iconColor: textColor onClicked: addPlaylist() } } } onOpened: { newPlaylistField.clear() playlistsList.clearTable() var playlists = bae.get(Q.GET.playlists) if(playlists.length > 0) for(var i in playlists) playlistsList.model.append(playlists[i]) // newPlaylistField.forceActiveFocus() } onAccepted: { if(newPlaylistField.text && newPlaylistField.text.length > 0) { addPlaylist() Player.addToPlaylist(tracks,newPlaylistField.text.trim()) } else Player.addToPlaylist(tracks, playlistsList.model.get(playlistsList.currentIndex).playlist) } function addPlaylist() { if (newPlaylistField.text) { var title = newPlaylistField.text.trim() if(bae.addPlaylist(title)) { playlistsList.model.insert(0, {playlist: title}) playlistsView.playlistViewModel.model.insert(9, {playlist: title}) playlistsList.list.positionViewAtBeginning() } newPlaylistField.clear() } } } diff --git a/view_models/BabeTable/TableDelegate.qml b/view_models/BabeTable/TableDelegate.qml index 58bac4c..387aea7 100644 --- a/view_models/BabeTable/TableDelegate.qml +++ b/view_models/BabeTable/TableDelegate.qml @@ -1,357 +1,359 @@ import QtQuick 2.9 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 import "../../view_models" import QtGraphicalEffects 1.0 import "../../utils/Help.js" as H import org.kde.kirigami 2.2 as Kirigami ItemDelegate { id: delegateRoot + readonly property int altHeight : rowHeight * 1.2 + width: parent.width - height: sameAlbum ? rowHeight : rowHeight*1.2 + height: sameAlbum ? rowHeight : altHeight clip: true autoExclusive: true signal play() signal rightClicked() signal leftClicked() signal artworkCoverClicked() signal artworkCoverDoubleClicked() readonly property bool sameAlbum : { if(coverArt) { if(listModel.get(index-1)) { if(listModel.get(index-1).album === album && listModel.get(index-1).artist === artist) true else false }else false }else false } property color bgColor : backgroundColor property color color : foregroundColor property color highlightColor : highlightedTextColor property string textColor: ListView.isCurrentItem ? highlightColor : color property bool number : false property bool quickPlay : true property bool coverArt : false property bool menuItem : false property bool trackDurationVisible : false property bool trackRatingVisible: false // property bool playingIndicator: false property string trackMood : art property alias trackRating : trackRating property bool remoteArtwork: false // NumberAnimation on x // { // running: ListView.isCurrentItem // from: 0; to: 100 // } Rectangle { anchors.fill: parent color: { if(trackMood.length > 0) Qt.lighter(trackMood) else index % 2 === 0 ? Qt.darker(bgColor) : "transparent" } opacity: 0.1 } MouseArea { anchors.fill: parent acceptedButtons: Qt.RightButton pressAndHoldInterval: 3000 onClicked: { - if(!root.isMobile && mouse.button === Qt.RightButton) + if(!isMobile && mouse.button === Qt.RightButton) rightClicked() } // onPressAndHold: // { // pressAndHold(mouse) // } } RowLayout { id: gridLayout anchors.fill: parent spacing: 0 Item { visible: coverArt Layout.fillHeight: true Layout.alignment: Qt.AlignLeft - width: sameAlbum ? rowHeight : parent.height + width: altHeight + height: parent.height ToolButton { visible: !sameAlbum - height: parent.height - width: parent.height - anchors.verticalCenter: parent.verticalCenter + anchors.fill: parent Image { id: artworkCover anchors.fill: parent sourceSize.width: parent.height sourceSize.height: parent.height source: typeof artwork === 'undefined' ? "qrc:/assets/cover.png" : remoteArtwork ? artwork : ((artwork && artwork.length > 0 && artwork !== "NONE")? "file://"+encodeURIComponent(artwork) : "qrc:/assets/cover.png") fillMode: Image.PreserveAspectFit cache: true antialiasing: false smooth: true } onDoubleClicked: artworkCoverDoubleClicked() onClicked: artworkCoverClicked() - onPressAndHold: if(root.isMobile) artworkCoverDoubleClicked() + onPressAndHold: if(isMobile) artworkCoverDoubleClicked() } } Item { visible: quickPlay Layout.fillHeight: true - width: sameAlbum ? rowHeight : parent.height - Layout.margins: 0 + width: rowHeight + height: parent.height + Layout.leftMargin: space.small BabeButton { id: playBtn anchors.centerIn: parent iconName: "media-playback-start" iconColor: textColor onClicked: play() anim: true } } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignLeft Layout.margins: space.tiny - Layout.leftMargin: coverArt ? contentMargins : 0 + Layout.leftMargin: space.small anchors.verticalCenter: parent.verticalCenter GridLayout { anchors.fill: parent rows: 2 columns: 4 rowSpacing: 0 Label { id: trackNumber visible: number width: 16 Layout.fillHeight: true Layout.row: 1 Layout.column: 1 Layout.alignment: Qt.AlignCenter verticalAlignment: Qt.AlignVCenter text: track + ". " font.bold: true elide: Text.ElideRight font.pointSize: fontSizes.default color: textColor } Label { id: trackTitle Layout.maximumWidth: gridLayout.width *0.5 Layout.fillWidth: true Layout.fillHeight: true Layout.row: 1 Layout.column: 2 verticalAlignment: Qt.AlignVCenter text: title font.bold: !sameAlbum elide: Text.ElideRight font.pointSize: fontSizes.default color: textColor } Label { id: trackInfo visible: coverArt ? !sameAlbum : true Layout.fillWidth: true Layout.fillHeight: true Layout.maximumWidth: gridLayout.width*0.4 Layout.row: 2 Layout.column: 2 verticalAlignment: Qt.AlignVCenter text: artist + " | " + album font.bold: false elide: Text.ElideRight font.pointSize: fontSizes.medium color: textColor } // Item // { // Layout.row: 1 // Layout.rowSpan: 2 // Layout.column: 4 // height: 48 // width: height // Layout.fillWidth: true // Layout.fillHeight: true // Layout.alignment: Qt.AlignCenter // AnimatedImage // { // id: animation // cache: true // visible: playingIndicator // height: 22 // width: 22 // horizontalAlignment: Qt.AlignLeft // verticalAlignment: Qt.AlignVCenter // source: "qrc:/assets/bars.gif" // } // } // Label // { // id: trackDuration // visible: trackDurationVisible // Layout.alignment: Qt.AlignRight // Layout.fillWidth: true // Layout.fillHeight: true // Layout.row: 1 // Layout.column: 3 // horizontalAlignment: Qt.AlignRight // verticalAlignment: Qt.AlignVCenter // text: player.transformTime(duration) // font.bold: false // elide: Text.ElideRight // font.pointSize: 8 // color: textColor // } Label { id: trackBabe font.family: "Material Design Icons" visible: babe == "1" Layout.alignment: Qt.AlignRight Layout.fillWidth: true Layout.fillHeight: true Layout.row: 1 Layout.column: /*trackDurationVisible &&*/ sameAlbum ? 4 : 3 horizontalAlignment: Qt.AlignRight verticalAlignment: Qt.AlignVCenter text: babe == "1" ? "\uf2D1" : "" font.bold: false elide: Text.ElideRight font.pointSize: fontSizes.small color: textColor // onTextChanged: animBabe.start() // SequentialAnimation // { // id: animBabe // PropertyAnimation // { // target: trackBabe // property: "color" // easing.type: Easing.InOutQuad // to: babeColor // duration: 250 // } // PropertyAnimation // { // target: trackBabe // property: "color" // easing.type: Easing.InOutQuad // to: textColor // duration: 500 // } // } } Label { font.family: "Material Design Icons" id: trackRating visible: trackRatingVisible Layout.fillWidth: true Layout.fillHeight: true Layout.alignment: Qt.AlignRight Layout.row: /*trackRatingVisible && */sameAlbum ? 1 : 2 Layout.column: 3 // Layout.columnSpan: trackRatingVisible && sameAlbum ? 4 : 3 horizontalAlignment: Qt.AlignRight verticalAlignment: Qt.AlignVCenter text: H.setStars(stars) font.bold: false elide: Text.ElideRight font.pointSize: fontSizes.small color: textColor } } } // Item // { // visible: menuItem // Layout.fillHeight: true // width: sameAlbum ? rowHeight : parent.height // BabeButton // { // id: menuBtn // anchors.centerIn: parent // iconName: "overflow-menu" // iconColor: textColor // onClicked: rightClicked() // } // } } } diff --git a/view_models/BabeTable/TableMenu.qml b/view_models/BabeTable/TableMenu.qml index 7931e90..719f849 100644 --- a/view_models/BabeTable/TableMenu.qml +++ b/view_models/BabeTable/TableMenu.qml @@ -1,286 +1,288 @@ import QtQuick 2.0 import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import "../../view_models/BabeMenu" import "../../utils" import ".." import "../../utils/Player.js" as Player import "../../utils/Help.js" as H BabeMenu { property int rate : 0 property bool babe : false property string starColor : "#FFC107" property string starReg : textColor property string starIcon: "draw-star" signal trackRemoved(string url) property alias menuItem : customItems.children function queueIt(index) { Player.queueTracks([list.model.get(index)]) } function rateIt(rank) { rate = rank if(bae.rateTrack(list.model.get(list.currentIndex).url, rate)) { list.currentItem.trackRating.text = H.setStars(rate) list.model.get(list.currentIndex).stars = rate } close() } function moodIt(color) { if(bae.colorTagTrack(list.model.get(list.currentIndex).url, color)) { list.currentItem.trackMood = color list.model.get(list.currentIndex).art = color } close() } function babeIt(index) { if(list.count>0) { console.log(index); var url = listModel.get(index).url var value = listModel.get(index).babe == "1" ? false : true if(bae.babeTrack(url, value)) list.model.get(index).babe = value ? "1" : "0" return value } } BabePopup { id: sendToPopup parent: babeTableRoot leftPadding: 1 rightPadding: 1 topPadding: contentMargins bottomPadding: contentMargins BabeList { id: sentToList headerBarVisible: false anchors.fill: parent holder.message: qsTr("There's not avalible devices") model: ListModel { id: model } delegate: BabeDelegate { id: delegate label : name Connections { target: delegate onClicked: { sentToList.currentIndex = index console.log(sentToList.model.get(index).name,sentToList.model.get(index).key) bae.sendToDevice(sentToList.model.get(index).name, sentToList.model.get(index).key, babeTableRoot.model.get(babeTableRoot.currentIndex).url) } } } } onOpened: { sentToList.clearTable() var devices = bae.getDevices() for( var i in devices) sentToList.model.append({name: devices[i].name, key: devices[i].key }) } } Label { id: titleLabel - visible: root.isMobile - padding: root.isMobile ? contentMargins : 0 + visible: isAndroid + padding: isAndroid ? space.small : 0 font.bold: true width: parent.width - height: root.isMobile ? iconSizes.medium : 0 + height: isAndroid ? iconSizes.medium : 0 horizontalAlignment: Qt.AlignHCenter elide: Text.ElideRight text: list.currentIndex >= 0 ? list.model.get(list.currentIndex).title : "" color: textColor } BabeMenuItem { text: babe == false ? "Babe it" : "UnBabe it" onTriggered: { babeIt(list.currentIndex) close() } } BabeMenuItem { text: "Queue" onTriggered: { queueIt(list.currentIndex) close() } } BabeMenuItem { text: "Save to..." onTriggered: { playlistDialog.tracks = [list.model.get(list.currentIndex).url] playlistDialog.open() close() } } BabeMenuItem { - text: isMobile ? qsTr("Open with...") : qsTr("Show in folder...") + text: isAndroid ? qsTr("Open with...") : qsTr("Show in folder...") onTriggered: { - !isMobile ? + !isAndroid ? bae.showFolder(list.model.get(list.currentIndex).url) : bae.openFile(list.model.get(list.currentIndex).url) close() } } BabeMenuItem { text: "Edit..." onTriggered: {close()} } BabeMenuItem { text: "Send to..." onTriggered: { isAndroid ? bae.sendTrack(list.model.get(list.currentIndex).url) : sendToPopup.open() close() } } BabeMenuItem { text: "Remove" onTriggered: { trackRemoved(list.model.get(list.currentIndex).url) listModel.remove(list.currentIndex) close() } } Column { id: customItems } BabeMenuItem { id: starsRow width: parent.width - height: toolBarIconSize + height: iconSizes.small RowLayout { anchors.fill: parent BabeButton { Layout.fillWidth: true Layout.fillHeight: true iconName: starIcon + iconSize: iconSizes.small iconColor: rate >= 1 ? starColor :starReg onClicked: rateIt(1) } BabeButton { Layout.fillWidth: true Layout.fillHeight: true - + iconSize: iconSizes.small iconName: starIcon iconColor: rate >= 2 ? starColor :starReg onClicked: rateIt(2) } BabeButton { Layout.fillWidth: true Layout.fillHeight: true - + iconSize: iconSizes.small iconName: starIcon iconColor: rate >= 3 ? starColor :starReg onClicked: rateIt(3) } BabeButton { Layout.fillWidth: true Layout.fillHeight: true - + iconSize: iconSizes.small iconName: starIcon iconColor: rate >= 4 ? starColor :starReg onClicked: rateIt(4) } BabeButton { Layout.fillWidth: true Layout.fillHeight: true - + iconSize: iconSizes.small iconName: starIcon iconColor: rate >= 5 ? starColor :starReg onClicked: rateIt(5) } } } BabeMenuItem { id: colorsRow width: parent.width + height: iconSizes.small ColorTagsBar { anchors.fill: parent onColorClicked: moodIt(color) } } } diff --git a/view_models/ColorTagsBar.qml b/view_models/ColorTagsBar.qml index 52810d7..c8148a6 100644 --- a/view_models/ColorTagsBar.qml +++ b/view_models/ColorTagsBar.qml @@ -1,114 +1,114 @@ import QtQuick 2.9 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { - property int recSize : 16 - readonly property int recRadius : 4 + property int recSize : iconSizes.small + readonly property int recRadius : recSize*0.05 signal colorClicked(string color) RowLayout { width: parent.width anchors.fill: parent anchors.centerIn: parent ToolButton { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignCenter flat: true Rectangle { anchors.centerIn: parent width: recSize height: recSize color: bae.moodColor(0) radius: recRadius border.color: altColor border.width: 1 } onClicked: colorClicked(bae.moodColor(0)) } ToolButton { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignCenter flat: true Rectangle { anchors.centerIn: parent width: recSize height: recSize color: bae.moodColor(1) radius: recRadius border.color: altColor border.width: 1 } onClicked: colorClicked(bae.moodColor(1)) } ToolButton { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignCenter flat: true Rectangle { anchors.centerIn: parent width: recSize height: recSize color: bae.moodColor(2) radius: recRadius border.color: altColor border.width: 1 } onClicked: colorClicked(bae.moodColor(2)) } ToolButton { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignCenter flat: true Rectangle { anchors.centerIn: parent width: recSize height: recSize color: bae.moodColor(3) radius: recRadius border.color: altColor border.width: 1 } onClicked: colorClicked(bae.moodColor(3)) } ToolButton { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignCenter flat: true Rectangle { anchors.centerIn: parent width: recSize height: recSize color: bae.moodColor(4) radius: recRadius border.color: altColor border.width: 1 } onClicked: colorClicked(bae.moodColor(4)) } } } diff --git a/widgets/BabeBar.qml b/widgets/BabeBar.qml index b22440b..654ea0a 100644 --- a/widgets/BabeBar.qml +++ b/widgets/BabeBar.qml @@ -1,230 +1,230 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.2 as Kirigami import "../utils" import "../view_models" ToolBar { position: ToolBar.Header property alias babeBar : babeBar property string accentColor : babeColor property string textColor : textColor property int currentIndex : 0 property bool accent : pageStack.wideMode || (!pageStack.wideMode && pageStack.currentIndex === 1) signal tracksViewClicked() signal albumsViewClicked() signal artistsViewClicked() signal playlistsViewClicked() signal babeViewClicked() // signal playlistViewClicked() signal searchViewClicked() signal settingsViewClicked() - width: parent.width + id: babeBar // Rectangle // { // anchors.fill: isMobile ? parent : undefined // color: bgColor // visible: !isMobile // } RowLayout { anchors.fill: parent Item { Layout.alignment: Qt.AlignLeft Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { id: settingsView anchors.centerIn: parent anchors.left: parent.left iconName: "application-menu" iconColor: settingsDrawer.visible ? babeColor : textColor/*(pageStack.wideMode || pageStack.currentIndex === 0 ) && !isMobile ? accentColor : textColor*/ onClicked: settingsViewClicked() hoverEnabled: !isMobile ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Settings") } } Item { Layout.fillWidth: true Layout.fillHeight: true Layout.minimumWidth: 0 } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { id: tracksView anchors.centerIn: parent iconName: "view-media-track" iconColor: accent && currentIndex === viewsIndex.tracks ? accentColor : textColor onClicked: tracksViewClicked() hoverEnabled: true ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Tracks") } } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { id: albumsView anchors.centerIn: parent iconName: /*"album"*/ "view-media-album-cover" iconColor: accent && currentIndex === viewsIndex.albums ? accentColor : textColor onClicked: albumsViewClicked() hoverEnabled: true ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Albums") } } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { id: artistsView anchors.centerIn: parent iconName: "view-media-artist" iconColor: accent && currentIndex === viewsIndex.artists ? accentColor : textColor onClicked: artistsViewClicked() hoverEnabled: true ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Artists") } } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { id: playlistsView anchors.centerIn: parent iconName: "view-media-playlist" iconColor: accent && currentIndex === viewsIndex.playlists ? accentColor : textColor onClicked: playlistsViewClicked() hoverEnabled: !isMobile ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Playlists") } } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { anchors.centerIn: parent iconName: "love" iconColor: accent && currentIndex === viewsIndex.babeit ? accentColor : textColor onClicked: babeViewClicked() hoverEnabled: !isMobile ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Babe") } } Item { Layout.fillWidth: true Layout.fillHeight: true Layout.minimumWidth: 0 } Item { Layout.alignment: Qt.AlignRight Layout.fillHeight: true Layout.fillWidth: true Layout.maximumWidth: toolBarIconSize*2 Layout.maximumHeight: toolBarIconSize BabeButton { id: searchView anchors.centerIn: parent // visible: !(searchInput.focus || searchInput.text) iconColor: accent && currentIndex === viewsIndex.search ? accentColor : textColor iconName: "edit-find" //"search" onClicked: searchViewClicked() hoverEnabled: !isMobile ToolTip.delay: 1000 ToolTip.timeout: 5000 ToolTip.visible: hovered && !isMobile ToolTip.text: qsTr("Search") } } } } diff --git a/widgets/SearchView/SearchTable.qml b/widgets/SearchView/SearchTable.qml index 2fe0403..0765f7f 100644 --- a/widgets/SearchView/SearchTable.qml +++ b/widgets/SearchView/SearchTable.qml @@ -1,178 +1,158 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import org.kde.kirigami 2.2 as Kirigami import QtQuick.Layouts 1.3 import "../../view_models" import QtGraphicalEffects 1.0 import "../../view_models/BabeTable" import "../../db/Queries.js" as Q Page { property alias searchInput : searchInput property alias searchTable : searchTable property var searchRes : [] property var savedQueries : [] property bool autoSuggestions : bae.loadSetting("AUTOSUGGESTIONS", "BABE", false) === "true" ? true : false function runSearch(searchTxt) { if(searchTxt) if(searchTxt !== searchTable.headerBarTitle) { if(savedQueries.indexOf(searchTxt) < 0) { savedQueries.unshift(searchTxt) // suggestionsPopup.model.insert(0, {suggestion: searchInput.text}) bae.saveSetting("QUERIES", savedQueries.join(","), "BABE") } searchTable.headerBarTitle = searchTxt var queries = searchTxt.split(",") searchRes = bae.searchFor(queries) populate(searchView.searchRes) searchTable.forceActiveFocus() suggestionsPopup.close() } } function clearSearch() { searchInput.clear() searchTable.clearTable() searchTable.headerBarTitle = "" searchRes = [] suggestionsPopup.close() } function populate(tracks) { searchTable.clearTable() for(var i in tracks) searchTable.model.append(tracks[i]) } SearchSuggestions { id: suggestionsPopup focus: false parent: searchBox width: parent.width*0.9 height: 200 modal: false closePolicy: Popup.CloseOnPressOutsideParent y: -(height+contentMargins*2) } Rectangle { visible: suggestionsPopup.visible width: parent.width height: parent.height-searchBox.height color: darkDarkColor z: 999 opacity: 0.5 } ColumnLayout { anchors.fill: parent width: parent.width height: parent.height Layout.margins: 0 spacing: 0 BabeTable { id: searchTable Layout.fillHeight: true Layout.fillWidth: true trackNumberVisible: false headerBarVisible: true headerBarExit: true headerBarExitIcon: "edit-clear" - holder.message: "No search results!" + holder.message: "

No search results!

Try with another query

" coverArtVisible: true trackDuration: true trackRating: true onExit: clearSearch() } - Kirigami.Separator - { - visible: !isMobile - Layout.fillWidth: true - width: parent.width - height: 1 - } - ToolBar { id: searchBox Layout.fillWidth: true -// width: parent.width -// height: toolBarHeight position: ToolBar.Footer - Rectangle - { - anchors.fill: parent - z: -999 - color: backgroundColor - } - - RowLayout { anchors.fill: parent BabeButton { - Layout.leftMargin: contentMargins visible: true iconName: "view-filter" iconColor: autoSuggestions ? babeColor : textColor onClicked: { autoSuggestions = !autoSuggestions bae.saveSetting("AUTOSUGGESTIONS", autoSuggestions, "BABE") if(!autoSuggestions) suggestionsPopup.close() } } TextInput { id: searchInput color: textColor Layout.fillWidth: true Layout.fillHeight: true horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter selectByMouse: !isMobile selectionColor: highlightColor selectedTextColor: highlightedTextColor focus: true text: "" wrapMode: TextEdit.Wrap //activeFocusOnPress: true onAccepted: runSearch(searchInput.text) // onActiveFocusChanged: if(activeFocus && autoSuggestions) suggestionsPopup.open() onTextEdited: if(autoSuggestions) suggestionsPopup.updateSuggestions() } BabeButton { - Layout.rightMargin: contentMargins iconName: "edit-clear" onClicked: searchInput.clear() } } } } }