This commit is contained in:
Broque Thomas 2025-07-24 12:56:46 -07:00
parent 2668d0613f
commit 4405e33aef

View file

@ -509,7 +509,7 @@ class PlaylistDetailsModal(QDialog):
def setup_ui(self):
self.setWindowTitle(f"Playlist Details - {self.playlist.name}")
self.setFixedSize(900, 700)
self.setFixedSize(1200, 800)
self.setStyleSheet("""
QDialog {
background: #191414;
@ -518,8 +518,8 @@ class PlaylistDetailsModal(QDialog):
""")
main_layout = QVBoxLayout(self)
main_layout.setContentsMargins(30, 30, 30, 30)
main_layout.setSpacing(20)
main_layout.setContentsMargins(32, 32, 32, 32)
main_layout.setSpacing(24)
# Header section
header = self.create_header()
@ -537,59 +537,57 @@ class PlaylistDetailsModal(QDialog):
def create_header(self):
header = QFrame()
header.setFixedHeight(120)
header.setStyleSheet("""
QFrame {
background: #282828;
border-radius: 12px;
border-radius: 16px;
border: 1px solid #404040;
}
""")
layout = QVBoxLayout(header)
layout.setContentsMargins(25, 20, 25, 20)
layout.setSpacing(10)
layout.setContentsMargins(32, 24, 32, 24)
layout.setSpacing(12)
# Playlist name
# Playlist name - larger, more prominent
name_label = QLabel(self.playlist.name)
name_label.setFont(QFont("Arial", 20, QFont.Weight.Bold))
name_label.setFont(QFont("SF Pro Display", 24, QFont.Weight.Bold))
name_label.setStyleSheet("color: #ffffff; border: none; background: transparent;")
# Playlist info
# Playlist info in a more compact horizontal layout
info_layout = QHBoxLayout()
info_layout.setSpacing(20)
info_layout.setSpacing(24)
# Track count
# Track count with icon-like styling
track_count = QLabel(f"{self.playlist.total_tracks} tracks")
track_count.setFont(QFont("Arial", 12))
track_count.setFont(QFont("SF Pro Text", 14, QFont.Weight.Medium))
track_count.setStyleSheet("color: #b3b3b3; border: none; background: transparent;")
# Owner
# Owner with subtle separator
owner = QLabel(f"by {self.playlist.owner}")
owner.setFont(QFont("Arial", 12))
owner.setFont(QFont("SF Pro Text", 14))
owner.setStyleSheet("color: #b3b3b3; border: none; background: transparent;")
# Public/Private status
# Status with accent color
visibility = "Public" if self.playlist.public else "Private"
if self.playlist.collaborative:
visibility = "Collaborative"
status = QLabel(visibility)
status.setFont(QFont("Arial", 12))
status.setStyleSheet("color: #1db954; border: none; background: transparent;")
status.setFont(QFont("SF Pro Text", 14, QFont.Weight.Medium))
status.setStyleSheet("""
color: #1db954;
border: none;
background: rgba(29, 185, 84, 0.1);
padding: 4px 12px;
border-radius: 12px;
""")
info_layout.addWidget(track_count)
info_layout.addWidget(owner)
info_layout.addWidget(status)
info_layout.addStretch()
# Description (if available)
if self.playlist.description:
desc_label = QLabel(self.playlist.description)
desc_label.setFont(QFont("Arial", 11))
desc_label.setStyleSheet("color: #b3b3b3; border: none; background: transparent;")
desc_label.setWordWrap(True)
desc_label.setMaximumHeight(60)
layout.addWidget(desc_label)
layout.addWidget(name_label)
layout.addLayout(info_layout)
@ -600,21 +598,16 @@ class PlaylistDetailsModal(QDialog):
container.setStyleSheet("""
QFrame {
background: #282828;
border-radius: 12px;
border-radius: 16px;
border: 1px solid #404040;
}
""")
layout = QVBoxLayout(container)
layout.setContentsMargins(25, 20, 25, 20)
layout.setSpacing(15)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# Section title
title = QLabel("Tracks")
title.setFont(QFont("Arial", 16, QFont.Weight.Bold))
title.setStyleSheet("color: #ffffff; border: none; background: transparent;")
# Track table
# Track table with professional styling
self.track_table = QTableWidget()
self.track_table.setColumnCount(4)
self.track_table.setHorizontalHeaderLabels(["Track", "Artist", "Album", "Duration"])
@ -623,160 +616,198 @@ class PlaylistDetailsModal(QDialog):
track_count = len(self.playlist.tracks) if self.playlist.tracks else 1
self.track_table.setRowCount(track_count)
# Style the table
# Professional table styling
self.track_table.setStyleSheet("""
QTableWidget {
background: #181818;
border: 1px solid #404040;
border-radius: 8px;
gridline-color: #404040;
background: #282828;
border: none;
border-radius: 16px;
gridline-color: transparent;
color: #ffffff;
font-size: 11px;
font-size: 13px;
selection-background-color: rgba(29, 185, 84, 0.2);
}
QTableWidget::item {
padding: 8px;
border-bottom: 1px solid #333333;
padding: 16px 24px;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
background: transparent;
}
QTableWidget::item:hover {
background: rgba(255, 255, 255, 0.02);
}
QTableWidget::item:selected {
background: #1db954;
color: #000000;
background: rgba(29, 185, 84, 0.15);
color: #ffffff;
}
QHeaderView {
background: transparent;
border: none;
}
QHeaderView::section {
background: #404040;
color: #ffffff;
padding: 10px;
background: transparent;
color: #b3b3b3;
padding: 16px 24px;
border: none;
font-weight: bold;
font-size: 11px;
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
font-weight: 600;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
QHeaderView::section:hover {
background: rgba(255, 255, 255, 0.02);
}
""")
# Populate table
# Populate table with proper styling
if self.playlist.tracks:
for row, track in enumerate(self.playlist.tracks):
# Track name
# Track name with proper styling
track_item = QTableWidgetItem(track.name)
track_item.setFlags(track_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
track_item.setFont(QFont("SF Pro Text", 13, QFont.Weight.Medium))
self.track_table.setItem(row, 0, track_item)
# Artist(s)
# Artist(s) with subtle styling
artists = ", ".join(track.artists)
artist_item = QTableWidgetItem(artists)
artist_item.setFlags(artist_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
artist_item.setFont(QFont("SF Pro Text", 13))
self.track_table.setItem(row, 1, artist_item)
# Album
# Album with subtle styling
album_item = QTableWidgetItem(track.album)
album_item.setFlags(album_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
album_item.setFont(QFont("SF Pro Text", 13))
self.track_table.setItem(row, 2, album_item)
# Duration
# Duration with monospace font
duration = self.format_duration(track.duration_ms)
duration_item = QTableWidgetItem(duration)
duration_item.setFlags(duration_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
duration_item.setFont(QFont("SF Mono", 12))
self.track_table.setItem(row, 3, duration_item)
else:
# Show placeholder while tracks are being loaded
placeholder_item = QTableWidgetItem("Tracks will load momentarily...")
placeholder_item = QTableWidgetItem("Loading tracks...")
placeholder_item.setFlags(placeholder_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
self.track_table.setItem(0, 0, placeholder_item)
self.track_table.setSpan(0, 0, 1, 4)
# Set optimal column widths with proportional sizing
# Professional column configuration
header = self.track_table.horizontalHeader()
header.setVisible(True)
header.show()
header.setStretchLastSection(False)
header.setHighlightSections(False)
header.setDefaultAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
# Calculate available width (modal is 900px, account for margins/scrollbar)
available_width = 850
# Calculate available width (modal is 1200px, account for margins)
available_width = 1136 # 1200 - 64px margins
# Set proportional widths: Track(40%), Artist(25%), Album(25%), Duration(10%)
track_width = int(available_width * 0.40) # ~340px
artist_width = int(available_width * 0.25) # ~212px
album_width = int(available_width * 0.25) # ~212px
duration_width = 80 # Fixed 80px
# Professional proportional widths
track_width = int(available_width * 0.35) # ~398px
artist_width = int(available_width * 0.28) # ~318px
album_width = int(available_width * 0.28) # ~318px
duration_width = 100 # Fixed 100px
# Apply column widths with interactive resize capability
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Interactive) # Track name
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Interactive) # Artist
header.setSectionResizeMode(2, QHeaderView.ResizeMode.Interactive) # Album
header.setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed) # Duration
# Apply column widths with proper resize modes
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Interactive)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Interactive)
header.setSectionResizeMode(2, QHeaderView.ResizeMode.Interactive)
header.setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed)
self.track_table.setColumnWidth(0, track_width)
self.track_table.setColumnWidth(1, artist_width)
self.track_table.setColumnWidth(2, album_width)
self.track_table.setColumnWidth(3, duration_width)
# Set minimum widths to prevent columns from becoming too narrow
header.setMinimumSectionSize(100) # Minimum 100px for any column
# Set minimum widths for professional look
header.setMinimumSectionSize(120)
# Hide row numbers
# Hide row numbers and configure table behavior
self.track_table.verticalHeader().setVisible(False)
self.track_table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.track_table.setAlternatingRowColors(False)
layout.addWidget(title)
layout.addWidget(self.track_table)
return container
def create_buttons(self):
button_layout = QHBoxLayout()
button_layout.setSpacing(15)
button_layout.setSpacing(16)
button_layout.setContentsMargins(0, 0, 0, 0)
# Close button
# Close button with subtle styling
close_btn = QPushButton("Close")
close_btn.setFixedSize(100, 40)
close_btn.setFixedSize(100, 44)
close_btn.clicked.connect(self.close)
close_btn.setStyleSheet("""
QPushButton {
background: #404040;
border: none;
border-radius: 20px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 22px;
color: #ffffff;
font-size: 12px;
font-weight: bold;
font-size: 13px;
font-weight: 600;
font-family: 'SF Pro Text';
}
QPushButton:hover {
background: #505050;
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.15);
}
QPushButton:pressed {
background: rgba(255, 255, 255, 0.02);
}
""")
# Sync button
sync_btn = QPushButton("Sync This Playlist")
sync_btn.setFixedSize(150, 40)
sync_btn.setStyleSheet("""
QPushButton {
background: #1db954;
border: none;
border-radius: 20px;
color: #000000;
font-size: 12px;
font-weight: bold;
}
QPushButton:hover {
background: #1ed760;
}
""")
# Download missing tracks button
# Download missing tracks button with outline style
download_btn = QPushButton("Download Missing Tracks")
download_btn.setFixedSize(180, 40)
download_btn.setFixedSize(200, 44)
download_btn.setStyleSheet("""
QPushButton {
background: transparent;
border: 1px solid #1db954;
border-radius: 20px;
border-radius: 22px;
color: #1db954;
font-size: 12px;
font-weight: bold;
font-size: 13px;
font-weight: 600;
font-family: 'SF Pro Text';
}
QPushButton:hover {
background: rgba(29, 185, 84, 0.1);
background: rgba(29, 185, 84, 0.08);
border-color: #1ed760;
color: #1ed760;
}
QPushButton:pressed {
background: rgba(29, 185, 84, 0.15);
}
""")
# Connect download missing tracks button
download_btn.clicked.connect(self.on_download_missing_tracks_clicked)
# Sync button with primary styling
sync_btn = QPushButton("Sync This Playlist")
sync_btn.setFixedSize(160, 44)
sync_btn.setStyleSheet("""
QPushButton {
background: #1db954;
border: none;
border-radius: 22px;
color: #ffffff;
font-size: 13px;
font-weight: 600;
font-family: 'SF Pro Text';
}
QPushButton:hover {
background: #1ed760;
}
QPushButton:pressed {
background: #169c46;
}
""")
# Connect sync button
# Connect button signals
download_btn.clicked.connect(self.on_download_missing_tracks_clicked)
sync_btn.clicked.connect(self.on_sync_playlist_clicked)
button_layout.addStretch()