diff --git a/logs/app.log b/logs/app.log index 4be0660c..d1df26ad 100644 --- a/logs/app.log +++ b/logs/app.log @@ -61,3 +61,46 @@ 2025-07-09 12:06:29 - newmusic.main - INFO - change_page:139 - Changed to page: downloads 2025-07-09 12:06:30 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard 2025-07-09 12:06:56 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:11:30 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:11:33 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard +2025-07-09 12:11:38 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:11:40 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard +2025-07-09 12:11:44 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:11:48 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:11:49 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard +2025-07-09 12:12:47 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:15:18 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:16:35 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:20:05 - newmusic.main - INFO - closeEvent:152 - Closing application... +2025-07-09 12:25:43 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-09 12:25:43 - newmusic.main - INFO - main:173 - Starting NewMusic application +2025-07-09 12:25:43 - newmusic.spotify_client - INFO - _setup_client:84 - Successfully authenticated with Spotify as broquethomas +2025-07-09 12:25:43 - newmusic.plex_client - INFO - _find_music_library:98 - Found music library: Music +2025-07-09 12:25:43 - newmusic.plex_client - INFO - _setup_client:84 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-09 12:25:43 - newmusic.soulseek_client - INFO - _setup_client:88 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-09 12:25:44 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard +2025-07-09 12:25:50 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:25:51 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:25:52 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:25:52 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:25:54 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:25:54 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:25:55 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:25:55 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard +2025-07-09 12:26:03 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:26:06 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:26:09 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:26:56 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:26:56 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:27:16 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:27:16 - newmusic.main - INFO - change_page:139 - Changed to page: dashboard +2025-07-09 12:28:06 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:28:07 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:28:08 - newmusic.main - INFO - change_page:139 - Changed to page: settings +2025-07-09 12:28:09 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:28:09 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:28:40 - newmusic.main - INFO - change_page:139 - Changed to page: sync +2025-07-09 12:28:42 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:28:42 - newmusic.main - INFO - change_page:139 - Changed to page: downloads +2025-07-09 12:28:43 - newmusic.main - INFO - change_page:139 - Changed to page: artists +2025-07-09 12:28:44 - newmusic.main - INFO - change_page:139 - Changed to page: settings diff --git a/ui/__pycache__/sidebar.cpython-312.pyc b/ui/__pycache__/sidebar.cpython-312.pyc index 5e4f3d82..b90eedab 100644 Binary files a/ui/__pycache__/sidebar.cpython-312.pyc and b/ui/__pycache__/sidebar.cpython-312.pyc differ diff --git a/ui/pages/__pycache__/downloads.cpython-312.pyc b/ui/pages/__pycache__/downloads.cpython-312.pyc index ba47f4b5..0f527e16 100644 Binary files a/ui/pages/__pycache__/downloads.cpython-312.pyc and b/ui/pages/__pycache__/downloads.cpython-312.pyc differ diff --git a/ui/pages/__pycache__/sync.cpython-312.pyc b/ui/pages/__pycache__/sync.cpython-312.pyc index 7c2d5e38..aecfe7a5 100644 Binary files a/ui/pages/__pycache__/sync.cpython-312.pyc and b/ui/pages/__pycache__/sync.cpython-312.pyc differ diff --git a/ui/pages/downloads.py b/ui/pages/downloads.py index 26f0e876..0ff5cfd3 100644 --- a/ui/pages/downloads.py +++ b/ui/pages/downloads.py @@ -436,7 +436,7 @@ class DownloadsPage(QWidget): def create_missing_tracks_section(self): section = QFrame() - section.setFixedHeight(200) + section.setFixedHeight(250) section.setStyleSheet(""" QFrame { background: #282828; @@ -456,6 +456,10 @@ class DownloadsPage(QWidget): title_label.setFont(QFont("Arial", 16, QFont.Weight.Bold)) title_label.setStyleSheet("color: #ffffff;") + count_label = QLabel("23 tracks") + count_label.setFont(QFont("Arial", 11)) + count_label.setStyleSheet("color: #b3b3b3;") + download_all_btn = QPushButton("📥 Download All") download_all_btn.setFixedSize(120, 35) download_all_btn.setStyleSheet(""" @@ -473,16 +477,108 @@ class DownloadsPage(QWidget): """) header_layout.addWidget(title_label) + header_layout.addWidget(count_label) header_layout.addStretch() header_layout.addWidget(download_all_btn) - # Missing tracks list (simplified) - missing_text = QLabel("23 tracks are missing from your Plex library and available for download") - missing_text.setFont(QFont("Arial", 12)) - missing_text.setStyleSheet("color: #b3b3b3;") + # Missing tracks scroll area + missing_scroll = QScrollArea() + missing_scroll.setWidgetResizable(True) + missing_scroll.setStyleSheet(""" + QScrollArea { + border: none; + background: transparent; + } + QScrollBar:vertical { + background: #404040; + width: 6px; + border-radius: 3px; + } + QScrollBar::handle:vertical { + background: #1db954; + border-radius: 3px; + } + """) + + missing_widget = QWidget() + missing_layout = QVBoxLayout(missing_widget) + missing_layout.setSpacing(8) + missing_layout.setContentsMargins(0, 0, 0, 0) + + # Sample missing tracks with playlist info + missing_tracks = [ + ("Song Title 1", "Artist Name 1", "Liked Songs"), + ("Another Track", "Different Artist", "Road Trip Mix"), + ("Cool Song", "Band Name", "Workout Playlist"), + ("Missing Hit", "Popular Artist", "Discover Weekly"), + ("Rare Track", "Indie Artist", "Chill Vibes") + ] + + for track_title, artist, playlist in missing_tracks: + track_item = self.create_missing_track_item(track_title, artist, playlist) + missing_layout.addWidget(track_item) + + missing_layout.addStretch() + missing_scroll.setWidget(missing_widget) layout.addLayout(header_layout) - layout.addWidget(missing_text) + layout.addWidget(missing_scroll) + + return section + + def create_missing_track_item(self, track_title: str, artist: str, playlist: str): + item = QFrame() + item.setFixedHeight(45) + item.setStyleSheet(""" + QFrame { + background: #333333; + border-radius: 6px; + border: 1px solid #404040; + } + QFrame:hover { + background: #3a3a3a; + border: 1px solid #1db954; + } + """) + + layout = QHBoxLayout(item) + layout.setContentsMargins(12, 8, 12, 8) + layout.setSpacing(10) + + # Track info + info_layout = QVBoxLayout() + info_layout.setSpacing(2) + + track_label = QLabel(f"{track_title} - {artist}") + track_label.setFont(QFont("Arial", 10, QFont.Weight.Medium)) + track_label.setStyleSheet("color: #ffffff;") + + playlist_label = QLabel(f"from: {playlist}") + playlist_label.setFont(QFont("Arial", 9)) + playlist_label.setStyleSheet("color: #1db954;") + + info_layout.addWidget(track_label) + info_layout.addWidget(playlist_label) + + # Download button + download_btn = QPushButton("📥") + download_btn.setFixedSize(30, 30) + download_btn.setStyleSheet(""" + QPushButton { + background: rgba(29, 185, 84, 0.2); + border: 1px solid #1db954; + border-radius: 15px; + color: #1db954; + font-size: 12px; + } + QPushButton:hover { + background: #1db954; + color: #000000; + } + """) + + layout.addLayout(info_layout) layout.addStretch() + layout.addWidget(download_btn) - return section \ No newline at end of file + return item \ No newline at end of file diff --git a/ui/pages/sync.py b/ui/pages/sync.py index 26dec7de..380c5c53 100644 --- a/ui/pages/sync.py +++ b/ui/pages/sync.py @@ -186,15 +186,9 @@ class SyncOptionsPanel(QFrame): quality_layout.addWidget(self.quality_combo) quality_layout.addStretch() - # Update metadata option - self.update_metadata = QCheckBox("Update metadata from Spotify") - self.update_metadata.setChecked(True) - self.update_metadata.setStyleSheet(self.download_missing.styleSheet()) - layout.addWidget(title_label) layout.addWidget(self.download_missing) layout.addLayout(quality_layout) - layout.addWidget(self.update_metadata) class SyncPage(QWidget): def __init__(self, parent=None): diff --git a/ui/sidebar.py b/ui/sidebar.py index c45bbff1..9cc8e876 100644 --- a/ui/sidebar.py +++ b/ui/sidebar.py @@ -52,14 +52,15 @@ class SidebarButton(QPushButton): if self.is_active: self.setStyleSheet(""" SidebarButton { - background: rgba(29, 185, 84, 0.2); - border-left: 3px solid #1db954; - border-radius: 0px; + background: rgba(29, 185, 84, 0.15); + border-left: 4px solid #1db954; + border-radius: 12px; text-align: left; padding: 0px; } SidebarButton:hover { - background: rgba(29, 185, 84, 0.3); + background: rgba(29, 185, 84, 0.25); + transform: scale(1.02); } """) self.text_label.setStyleSheet("color: #1db954; font-weight: bold;") @@ -68,8 +69,8 @@ class SidebarButton(QPushButton): color: #1db954; font-size: 16px; font-weight: bold; - border-radius: 12px; - background: rgba(29, 185, 84, 0.2); + border-radius: 14px; + background: rgba(29, 185, 84, 0.25); } """) else: @@ -77,12 +78,13 @@ class SidebarButton(QPushButton): SidebarButton { background: transparent; border: none; - border-radius: 0px; + border-radius: 12px; text-align: left; padding: 0px; } SidebarButton:hover { - background: rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.08); + border-left: 2px solid rgba(255, 255, 255, 0.3); } """) self.text_label.setStyleSheet("color: #b3b3b3;") @@ -91,8 +93,8 @@ class SidebarButton(QPushButton): color: #b3b3b3; font-size: 16px; font-weight: bold; - border-radius: 12px; - background: rgba(255, 255, 255, 0.1); + border-radius: 14px; + background: rgba(255, 255, 255, 0.08); } """) @@ -104,18 +106,27 @@ class StatusIndicator(QWidget): self.setup_ui() def setup_ui(self): + self.setFixedHeight(35) # Ensure enough height layout = QHBoxLayout(self) - layout.setContentsMargins(15, 5, 15, 5) - layout.setSpacing(10) + layout.setContentsMargins(15, 8, 15, 8) + layout.setSpacing(12) - # Status dot + # Status dot with rounded background self.status_dot = QLabel("●") - self.status_dot.setFixedSize(12, 12) + self.status_dot.setFixedSize(16, 16) self.status_dot.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.status_dot.setStyleSheet(""" + QLabel { + border-radius: 8px; + font-size: 12px; + font-weight: bold; + } + """) # Service name self.service_label = QLabel(self.service_name) - self.service_label.setFont(QFont("Arial", 9)) + self.service_label.setFont(QFont("Arial", 10, QFont.Weight.Medium)) + self.service_label.setMinimumWidth(80) # Ensure text doesn't get cut off layout.addWidget(self.status_dot) layout.addWidget(self.service_label) @@ -126,11 +137,27 @@ class StatusIndicator(QWidget): def update_status(self, connected: bool): self.is_connected = connected if connected: - self.status_dot.setStyleSheet("color: #1db954;") - self.service_label.setStyleSheet("color: #ffffff;") + self.status_dot.setStyleSheet(""" + QLabel { + color: #1db954; + background: rgba(29, 185, 84, 0.15); + border-radius: 8px; + font-size: 12px; + font-weight: bold; + } + """) + self.service_label.setStyleSheet("color: #ffffff; font-weight: 500;") else: - self.status_dot.setStyleSheet("color: #e22134;") - self.service_label.setStyleSheet("color: #b3b3b3;") + self.status_dot.setStyleSheet(""" + QLabel { + color: #e22134; + background: rgba(226, 33, 52, 0.15); + border-radius: 8px; + font-size: 12px; + font-weight: bold; + } + """) + self.service_label.setStyleSheet("color: #b3b3b3; font-weight: 400;") class ModernSidebar(QWidget): page_changed = pyqtSignal(str) @@ -171,21 +198,29 @@ class ModernSidebar(QWidget): def create_header(self): header = QWidget() - header.setFixedHeight(80) - header.setStyleSheet("background: #121212; border-bottom: 1px solid #282828;") + header.setFixedHeight(85) + header.setStyleSheet(""" + QWidget { + background: #121212; + border-bottom: 1px solid #282828; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + } + """) layout = QVBoxLayout(header) - layout.setContentsMargins(20, 20, 20, 20) + layout.setContentsMargins(20, 22, 20, 22) + layout.setSpacing(3) # App name app_name = QLabel("NewMusic") - app_name.setFont(QFont("Arial", 18, QFont.Weight.Bold)) - app_name.setStyleSheet("color: #ffffff;") + app_name.setFont(QFont("Arial", 19, QFont.Weight.Bold)) + app_name.setStyleSheet("color: #ffffff; letter-spacing: -0.5px;") # Subtitle subtitle = QLabel("Music Sync & Manager") - subtitle.setFont(QFont("Arial", 9)) - subtitle.setStyleSheet("color: #b3b3b3;") + subtitle.setFont(QFont("Arial", 10)) + subtitle.setStyleSheet("color: #b3b3b3; opacity: 0.8;") layout.addWidget(app_name) layout.addWidget(subtitle) @@ -194,9 +229,15 @@ class ModernSidebar(QWidget): def create_navigation(self): nav_widget = QWidget() + nav_widget.setStyleSheet(""" + QWidget { + background: #121212; + border-radius: 8px; + } + """) layout = QVBoxLayout(nav_widget) - layout.setContentsMargins(0, 20, 0, 20) - layout.setSpacing(5) + layout.setContentsMargins(8, 20, 8, 20) + layout.setSpacing(6) # Navigation buttons nav_items = [ @@ -220,17 +261,24 @@ class ModernSidebar(QWidget): def create_status_section(self): status_widget = QWidget() - status_widget.setFixedHeight(120) - status_widget.setStyleSheet("background: #181818; border-top: 1px solid #282828;") + status_widget.setFixedHeight(140) # Increased height + status_widget.setStyleSheet(""" + QWidget { + background: #181818; + border-top: 1px solid #282828; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + } + """) layout = QVBoxLayout(status_widget) - layout.setContentsMargins(0, 15, 0, 15) - layout.setSpacing(8) + layout.setContentsMargins(0, 18, 0, 18) # Better margins + layout.setSpacing(6) # Tighter spacing between items # Status title status_title = QLabel("Connection Status") - status_title.setFont(QFont("Arial", 10, QFont.Weight.Bold)) - status_title.setStyleSheet("color: #ffffff; padding: 0 15px;") + status_title.setFont(QFont("Arial", 11, QFont.Weight.Bold)) + status_title.setStyleSheet("color: #ffffff; padding: 0 15px; margin-bottom: 5px;") layout.addWidget(status_title) # Status indicators