Skip to main content
2 of 3
deleted 7 characters in body
Reinderien
  • 71.1k
  • 5
  • 76
  • 256
  • You have a pile of unstructured, global code; this needs to be organized into functions and maybe classes
  • Close your cursor once you're done with it, ideally via context management
  • Order your query using the database itself, to make grouping less painful; also query in order of hierarchy (artist, album, song)
  • You don't need entries; just add items one at a time
  • 4 should not be hard-coded
  • Your repeated set comprehensions can be greatly simplified (i.e. abolished) via itertools.groupby

This example code localises the MySQL import because I don't have it; I've generated fake data instead.

import sys
from dataclasses import dataclass
from itertools import groupby
from typing import Iterable, Callable

from PyQt6.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem


@dataclass
class Song:
    artist: str
    album: str
    title: str

    @classmethod
    def from_db(cls) -> Iterable['Song']:
        from mysql.connector import connect

        with connect(
            user='Estranger',
            password='********',
            host='127.0.0.1',
            port=3306,
            database='Music',
        ) as conn, conn.cursor() as cursor:
            cursor.execute(
                'select artist, album, title from songs '
                'order by artist, album'
            )
            for row in cursor.fetchall():
                yield cls(*row)

    @classmethod
    def fake_rows(cls) -> Iterable['Song']:
        return (
            cls('Weird Al Yankovic', 'Running with Scissors', 'Pretty Fly for a Rabbi'),
            cls('Weird Al Yankovic', 'Running with Scissors', 'Albuquerque'),
            cls('Weird Al Yankovic', 'Off the Deep End', "I Can't Watch This"),
            cls('Weird Al Yankovic', 'Off the Deep End', 'Smells like Nirvana'),
            cls('The Arrogant Worms', "C'est Cheese", 'Mounted Animal Nature Trail'),
        )

    @staticmethod
    def by_artist(self): return self.artist
    @staticmethod
    def by_album(self): return self.album


class GUI:
    HEADERS = ('Name', 'Artist', 'Album', 'Title')

    def __init__(self, songs):
        app = QApplication(sys.argv)

        tree = QTreeWidget()
        # a reference needs to be held or this will be garbage-collected
        self.tree = tree
        tree.resize(1280, 720)
        tree.setWindowTitle('tree')
        frame = tree.frameGeometry()
        center = tree.screen().availableGeometry().center()
        frame.moveCenter(center)
        tree.move(frame.topLeft())
        tree.setColumnCount(len(self.HEADERS))
        tree.setHeaderLabels(self.HEADERS)

        for artist, after_artist in groupby(songs, Song.by_artist):
            artist_node = QTreeWidgetItem((artist,))
            for album, after_album in groupby(after_artist, Song.by_album):
                album_node = QTreeWidgetItem((album, artist, album))
                for song in after_album:
                    song_node = QTreeWidgetItem((song.title, artist, album, song.title))
                    album_node.addChild(song_node)
                artist_node.addChild(album_node)
            tree.addTopLevelItem(artist_node)

        tree.show()

        self.run: Callable[[], int] = app.exec


def main() -> None:
    songs = Song.fake_rows()
    gui = GUI(songs)
    exit(gui.run())


if __name__ == '__main__':
    main()

test run

Reinderien
  • 71.1k
  • 5
  • 76
  • 256