summaryrefslogtreecommitdiff
path: root/tidal_dl_ng/ui
diff options
context:
space:
mode:
authorWarry <FunWarry@users.noreply.github.com>2025-12-29 17:37:39 +0100
committerWarry <FunWarry@users.noreply.github.com>2025-12-29 17:37:39 +0100
commit296c6c7d6b319b38958b2aacb9904f18f6f46fd1 (patch)
treea3e72a9326defee5804cc9387ecee779b9bf02a2 /tidal_dl_ng/ui
parent75868b32d07aafe46b69649d2da0dc2c833f112d (diff)
downloadtidal-dl-ng-296c6c7d6b319b38958b2aacb9904f18f6f46fd1.tar.gz
feat: Add playlist management functionality and compliance checks
- Introduced a new "Playlists" column in results view with visual indicators for membership. - Added `playlist_api.py` to handle playlist-related operations (fetch, add, remove tracks). - Implemented `PlaylistManagerDialog` for seamless playlist addition/removal with caching. - Integrated compliance check script (`check_agents_compliance.py`) for ensuring coding standards. - Added extensive documentation (`playlist_membership_manager.md`) covering architecture and flow. - Updated GUI logic and QStandardItemModel setup to include playlist data. - Included unit tests for playlist management components and API.
Diffstat (limited to 'tidal_dl_ng/ui')
-rw-r--r--tidal_dl_ng/ui/dialog_playlist_manager.py115
-rw-r--r--tidal_dl_ng/ui/dialog_playlist_manager.ui147
2 files changed, 262 insertions, 0 deletions
diff --git a/tidal_dl_ng/ui/dialog_playlist_manager.py b/tidal_dl_ng/ui/dialog_playlist_manager.py
new file mode 100644
index 0000000..17327f6
--- /dev/null
+++ b/tidal_dl_ng/ui/dialog_playlist_manager.py
@@ -0,0 +1,115 @@
+################################################################################
+## Form generated from reading UI file 'dialog_playlist_manager.ui'
+##
+## Created by: Qt User Interface Compiler version 6.10.0
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import QCoreApplication, QMetaObject, QRect, QSize, Qt
+from PySide6.QtWidgets import (
+ QFrame,
+ QHBoxLayout,
+ QLabel,
+ QPushButton,
+ QScrollArea,
+ QSizePolicy,
+ QSpacerItem,
+ QVBoxLayout,
+ QWidget,
+)
+
+
+class Ui_DialogPlaylistManager:
+ def setupUi(self, DialogPlaylistManager):
+ if not DialogPlaylistManager.objectName():
+ DialogPlaylistManager.setObjectName("DialogPlaylistManager")
+ DialogPlaylistManager.resize(609, 760)
+ DialogPlaylistManager.setMinimumSize(QSize(520, 560))
+ self.verticalLayoutRoot = QVBoxLayout(DialogPlaylistManager)
+ self.verticalLayoutRoot.setObjectName("verticalLayoutRoot")
+ self.horizontalLayoutHeader = QHBoxLayout()
+ self.horizontalLayoutHeader.setObjectName("horizontalLayoutHeader")
+ self.labelTitle = QLabel(DialogPlaylistManager)
+ self.labelTitle.setObjectName("labelTitle")
+ self.labelTitle.setWordWrap(True)
+
+ self.horizontalLayoutHeader.addWidget(self.labelTitle)
+
+ self.verticalLayoutRoot.addLayout(self.horizontalLayoutHeader)
+
+ self.frameSeparator = QFrame(DialogPlaylistManager)
+ self.frameSeparator.setObjectName("frameSeparator")
+ self.frameSeparator.setFrameShape(QFrame.Shape.HLine)
+ self.frameSeparator.setFrameShadow(QFrame.Shadow.Sunken)
+
+ self.verticalLayoutRoot.addWidget(self.frameSeparator)
+
+ self.scrollArea = QScrollArea(DialogPlaylistManager)
+ self.scrollArea.setObjectName("scrollArea")
+ self.scrollArea.setWidgetResizable(True)
+ self.scrollAreaWidgetContents = QWidget()
+ self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
+ self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 589, 666))
+ self.verticalLayoutList = QVBoxLayout(self.scrollAreaWidgetContents)
+ self.verticalLayoutList.setObjectName("verticalLayoutList")
+ self.labelEmpty = QLabel(self.scrollAreaWidgetContents)
+ self.labelEmpty.setObjectName("labelEmpty")
+ self.labelEmpty.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+ self.verticalLayoutList.addWidget(self.labelEmpty)
+
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
+
+ self.verticalLayoutList.addItem(self.verticalSpacer)
+
+ self.scrollArea.setWidget(self.scrollAreaWidgetContents)
+
+ self.verticalLayoutRoot.addWidget(self.scrollArea)
+
+ self.frameFooterSeparator = QFrame(DialogPlaylistManager)
+ self.frameFooterSeparator.setObjectName("frameFooterSeparator")
+ self.frameFooterSeparator.setFrameShape(QFrame.Shape.HLine)
+ self.frameFooterSeparator.setFrameShadow(QFrame.Shadow.Sunken)
+
+ self.verticalLayoutRoot.addWidget(self.frameFooterSeparator)
+
+ self.horizontalLayoutFooter = QHBoxLayout()
+ self.horizontalLayoutFooter.setObjectName("horizontalLayoutFooter")
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
+
+ self.horizontalLayoutFooter.addItem(self.horizontalSpacer)
+
+ self.buttonClose = QPushButton(DialogPlaylistManager)
+ self.buttonClose.setObjectName("buttonClose")
+
+ self.horizontalLayoutFooter.addWidget(self.buttonClose)
+
+ self.verticalLayoutRoot.addLayout(self.horizontalLayoutFooter)
+
+ self.retranslateUi(DialogPlaylistManager)
+ self.buttonClose.clicked.connect(DialogPlaylistManager.accept)
+
+ self.buttonClose.setDefault(True)
+
+ QMetaObject.connectSlotsByName(DialogPlaylistManager)
+
+ # setupUi
+
+ def retranslateUi(self, DialogPlaylistManager):
+ DialogPlaylistManager.setWindowTitle(
+ QCoreApplication.translate("DialogPlaylistManager", "G\u00e9rer les playlists", None)
+ )
+ self.labelTitle.setText(
+ QCoreApplication.translate(
+ "DialogPlaylistManager",
+ 'G\u00e9rer les playlists pour : <b><span style="color:#1e88e5;">Titre de la Piste</span></b>',
+ None,
+ )
+ )
+ self.labelEmpty.setText(
+ QCoreApplication.translate("DialogPlaylistManager", "Aucune playlist disponible.", None)
+ )
+ self.buttonClose.setText(QCoreApplication.translate("DialogPlaylistManager", "Fermer", None))
+
+ # retranslateUi
diff --git a/tidal_dl_ng/ui/dialog_playlist_manager.ui b/tidal_dl_ng/ui/dialog_playlist_manager.ui
new file mode 100644
index 0000000..5f7b831
--- /dev/null
+++ b/tidal_dl_ng/ui/dialog_playlist_manager.ui
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogPlaylistManager</class>
+ <widget class="QDialog" name="DialogPlaylistManager">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>609</width>
+ <height>760</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>520</width>
+ <height>560</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Gérer les playlists</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayoutRoot">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayoutHeader">
+ <item>
+ <widget class="QLabel" name="labelTitle">
+ <property name="text">
+ <string>Gérer les playlists pour : &lt;b&gt;&lt;span style=&quot;color:#1e88e5;&quot;&gt;Titre de la Piste&lt;/span&gt;&lt;/b&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QFrame" name="frameSeparator">
+ <property name="frameShape">
+ <enum>QFrame::Shape::HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Shadow::Sunken</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>589</width>
+ <height>666</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayoutList">
+ <item>
+ <widget class="QLabel" name="labelEmpty">
+ <property name="text">
+ <string>Aucune playlist disponible.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignmentFlag::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Orientation::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="frameFooterSeparator">
+ <property name="frameShape">
+ <enum>QFrame::Shape::HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Shadow::Sunken</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayoutFooter">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose">
+ <property name="text">
+ <string>Fermer</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>DialogPlaylistManager</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>20</x>
+ <y>20</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>20</x>
+ <y>20</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>