Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions SubDrome/Artist/ArtistDisplay.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import QtQuick 2.15

Rectangle {
id: artistDisplay
color: "transparent"

function loadArtists(artists) {
artistListModel.clear();
contentStack.currentIndex = 3;

if (!artists) {
artists = apiHandler.get_artists();
}
for (let i = 0; i < artists.length; i++) {
let artist = artists[i];
artistListModel.append({
id: artist[0],
name: artist[1],
albumCount: artist[2]
});
}
}

ListModel { id: artistListModel }

ArtistDisplayTopper {
id: topper
anchors {
top: parent.top
left: parent.left
right: parent.right
}

implicitHeight: 50
}

Rectangle {
anchors {
top: topper.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
anchors.margins: 20
color: "#424242"
radius: 10
clip: true

ListView {
id: artistListView
anchors {
fill: parent
margins: 20
}
model: artistListModel

delegate: Rectangle {
width: parent.width
height: 40
color: index % 2 === 0 ? "#333" : "#222"

Row {
anchors.fill: parent
spacing: 10

Image {
source: "qrc:/icons/artist.svg"
width: 40
height: 40
fillMode: Image.PreserveAspectFit
}

Text {
text: model.name
color: "white"
font.pixelSize: 18
verticalAlignment: Text.AlignVCenter
}

Text {
text: model.albumCount + " albums"
color: "#888"
font.pixelSize: 14
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
30 changes: 30 additions & 0 deletions SubDrome/Artist/ArtistDisplayTopper.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import QtQuick 2.15
import QtQuick.Controls 2.15

Rectangle {
id: topper
color: "transparent"

TextField {
id: searchField
anchors {
left: parent.left
top: parent.top
leftMargin: 20
topMargin: 20
}
width: 200
placeholderText: "Search"
placeholderTextColor: "#888"
color: "white"
font.pixelSize: 16
background: Rectangle {
color: "#424242"
radius: 5
border.color: "#888"
}
onTextChanged: {
artistDisplay.loadArtists(apiHandler.search_artists(text, 1));
}
}
}
1 change: 1 addition & 0 deletions SubDrome/Artist/qmldir
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ArtistDisplay 1.0 ArtistDisplay.qml
2 changes: 1 addition & 1 deletion SubDrome/Bars/Sidebar.qml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Rectangle {
onClicked: { albumDisplay.loadAlbums("frequent", 1) } }

SidebarItem { iconSource: "qrc:/icons/artist.svg"; label: "Artists";
onClicked: { } }
onClicked: { artistDisplay.loadArtists() } }
SidebarItem { iconSource: "qrc:/icons/song.svg"; label: "Songs";
onClicked: { } }
SidebarItem { iconSource: "qrc:/icons/playlist.svg"; label: "Playlists";
Expand Down
5 changes: 5 additions & 0 deletions SubDrome/Player.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Album 1.0
import Bars 1.0
import Queue 1.0
import Playlist 1.0
import Artist 1.0

Rectangle {
Rectangle {
Expand Down Expand Up @@ -56,6 +57,10 @@ Rectangle {
PlaylistPage {
id: playlistPage
}

ArtistDisplay {
id: artistDisplay
}
}
}

Expand Down
70 changes: 64 additions & 6 deletions SubDrome/api_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,22 +191,39 @@ def download_song(self, song_id: str) -> str:
pass
return ""

@Slot(str, int)
def search_albums(self, query: str, page: int) -> None:
def _general_search(self, query: str, page: int) -> dict:
"""
Search for albums
Perform a general search on the Subsonic server.
:param query: The search query.
:param page: The page number.
:return: A dictionary containing search results or an empty dictionary if the request fails.
"""
extra_params = {
"query": query,
"artistCount": 20,
"artistOffset": page * 20 - 20,
"albumCount": 20,
"albumOffset": page * 20 - 20
"albumOffset": page * 20 - 20,
"songCount": 20,
"songOffset": page * 20 - 20
}
response = self._send_request("search2", extra_params)
response = self._send_request("search3", extra_params)
if response.get("status") == "ok":
return response.get("searchResult3", {})
return {}

@Slot(str, int)
def search_albums(self, query: str, page: int) -> None:
"""
Search for albums
:param query: The search query.
:param page: The page number.
"""
search_result = self._general_search(query, page)
response_albums = search_result.get("album", [])
if response_albums:
albums = []
for album in response.get("searchResult2", {}).get("album", []):
for album in response_albums:
cover_id = album.get("coverArt", "")
album_id = album.get("id", "")
self.thread_manager.start(lambda cid=cover_id, aid=album_id: self.get_cover_art(cid, aid))
Expand All @@ -218,6 +235,28 @@ def search_albums(self, query: str, page: int) -> None:
])
self.albumsUpdated.emit(albums)

@Slot(str, int, result="QVariant")
def search_artists(self, query: str, page: int) -> list:
"""
Search for artists
:param query: The search query.
:param page: The page number.
:return: A list of artists matching the search query.
"""
search_result = self._general_search(query, page)
response_artists = search_result.get("artist", [])
if response_artists:
artists = []
for artist in response_artists:
artist_id = artist.get("id", "")
artists.append([
artist_id,
artist.get("name"),
artist.get("albumCount")
])
return artists
return [[]]

@Slot()
def update_playlist_list(self) -> None:
"""
Expand Down Expand Up @@ -301,3 +340,22 @@ def set_rating(self, target_id: str, rating: int) -> None:
"rating": rating
}
self._send_request("setRating", extra_params)

@Slot(result="QVariant")
def get_artists(self) -> list:
"""
Fetch the list of artists from the server.
:return: A list of artists with their ID, name, and album count.
"""
response = self._send_request("getArtists")
if response.get("status") == "ok":
artists = []
for indices in response.get("artists", {}).get("index", []):
for artist in indices.get("artist", []):
artists.append([
artist.get("id", ""),
artist.get("name", ""),
artist.get("albumCount", 0)
])
return artists
return [[]]