Initial commit - Radio Panel v0.1
This commit is contained in:
@@ -0,0 +1,605 @@
|
||||
# playlist_widget.py
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QPushButton, QFileDialog, QFrame, QSizePolicy,
|
||||
QListWidget, QListWidgetItem, QAbstractItemView,
|
||||
QMenu, QSplitter
|
||||
)
|
||||
from PySide6.QtCore import Qt, QTimer
|
||||
from PySide6.QtGui import QFont, QColor, QAction
|
||||
import os
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# PLAYLIST ITEM
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class PlaylistItem(QListWidgetItem):
|
||||
def __init__(self, filepath: str):
|
||||
self.filepath = filepath
|
||||
self.filename = os.path.basename(filepath)
|
||||
display = os.path.splitext(self.filename)[0]
|
||||
super().__init__(display)
|
||||
self.setFont(QFont("Courier New", 10, QFont.Bold))
|
||||
self.setForeground(QColor("#cccccc"))
|
||||
self.setToolTip(filepath)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# HOUR DISPLAY + CLOCK
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class HourDisplay(QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setFrameStyle(QFrame.Box | QFrame.Sunken)
|
||||
self.setFixedHeight(44)
|
||||
self.setStyleSheet("""
|
||||
QFrame {
|
||||
background-color: #0a0a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 3px;
|
||||
}
|
||||
""")
|
||||
|
||||
layout = QHBoxLayout(self)
|
||||
layout.setContentsMargins(8, 2, 8, 2)
|
||||
|
||||
self.hour_label = QLabel("HOUR --:--")
|
||||
self.hour_label.setFont(QFont("Courier New", 12, QFont.Bold))
|
||||
self.hour_label.setStyleSheet(
|
||||
"color: #4488ff; background: transparent; border: none;"
|
||||
)
|
||||
self.hour_label.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(self.hour_label)
|
||||
|
||||
self.clock_label = QLabel("00:00:00")
|
||||
self.clock_label.setFont(QFont("Courier New", 12, QFont.Bold))
|
||||
self.clock_label.setStyleSheet(
|
||||
"color: #aaaaaa; background: transparent; border: none;"
|
||||
)
|
||||
self.clock_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
layout.addWidget(self.clock_label)
|
||||
|
||||
self.clock_timer = QTimer(self)
|
||||
self.clock_timer.setInterval(1000)
|
||||
self.clock_timer.timeout.connect(self._update_clock)
|
||||
self.clock_timer.start()
|
||||
self._update_clock()
|
||||
|
||||
def _update_clock(self):
|
||||
from datetime import datetime
|
||||
now = datetime.now()
|
||||
self.clock_label.setText(now.strftime("%H:%M:%S"))
|
||||
self.hour_label.setText(f"HOUR {now.strftime('%H:00')}")
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# DECK SELECTOR
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class DeckSelector(QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setFixedHeight(36)
|
||||
self.setStyleSheet("""
|
||||
QFrame {
|
||||
background-color: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 3px;
|
||||
}
|
||||
""")
|
||||
|
||||
layout = QHBoxLayout(self)
|
||||
layout.setContentsMargins(6, 2, 6, 2)
|
||||
layout.setSpacing(6)
|
||||
|
||||
label = QLabel("SEND TO:")
|
||||
label.setFont(QFont("Arial", 9, QFont.Bold))
|
||||
label.setStyleSheet("color: #888; background: transparent; border: none;")
|
||||
layout.addWidget(label)
|
||||
|
||||
self.deck1_btn = QPushButton("DECK 1")
|
||||
self.deck1_btn.setCheckable(True)
|
||||
self.deck1_btn.setChecked(True)
|
||||
self.deck1_btn.setFixedHeight(26)
|
||||
self.deck1_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||
self._style_btn(self.deck1_btn, "#00897b")
|
||||
|
||||
self.deck2_btn = QPushButton("DECK 2")
|
||||
self.deck2_btn.setCheckable(True)
|
||||
self.deck2_btn.setFixedHeight(26)
|
||||
self.deck2_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||
self._style_btn(self.deck2_btn, "#f9ca24")
|
||||
|
||||
self.deck1_btn.clicked.connect(lambda: self._select("deck1"))
|
||||
self.deck2_btn.clicked.connect(lambda: self._select("deck2"))
|
||||
|
||||
layout.addWidget(self.deck1_btn)
|
||||
layout.addWidget(self.deck2_btn)
|
||||
layout.addStretch()
|
||||
|
||||
self._selected = "deck1"
|
||||
|
||||
def _style_btn(self, btn: QPushButton, accent: str):
|
||||
btn.setStyleSheet(f"""
|
||||
QPushButton {{
|
||||
background-color: #2a2a2a;
|
||||
color: #888;
|
||||
border: 1px solid #444;
|
||||
border-radius: 3px;
|
||||
padding: 0 8px;
|
||||
}}
|
||||
QPushButton:checked {{
|
||||
background-color: #1a1a1a;
|
||||
color: {accent};
|
||||
border: 1px solid {accent};
|
||||
}}
|
||||
QPushButton:hover {{ background-color: #333; }}
|
||||
""")
|
||||
|
||||
def _select(self, deck: str):
|
||||
self._selected = deck
|
||||
self.deck1_btn.setChecked(deck == "deck1")
|
||||
self.deck2_btn.setChecked(deck == "deck2")
|
||||
|
||||
@property
|
||||
def selected_deck(self) -> str:
|
||||
return self._selected
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# BASE PLAYLIST PANEL
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class BasePlaylistPanel(QWidget):
|
||||
AUDIO_FILTER = (
|
||||
"Audio Files "
|
||||
"(*.wav *.flac *.mp3 *.m4a *.mp4 *.ogg *.opus *.aac *.aiff)"
|
||||
)
|
||||
AUDIO_EXTENSIONS = {
|
||||
'.wav', '.flac', '.mp3', '.m4a', '.mp4',
|
||||
'.ogg', '.opus', '.aac', '.aiff'
|
||||
}
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
def _make_list(self) -> QListWidget:
|
||||
lst = QListWidget()
|
||||
lst.setStyleSheet("""
|
||||
QListWidget {
|
||||
background-color: #0d0d0d;
|
||||
color: #cccccc;
|
||||
border: 1px solid #333;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
}
|
||||
QListWidget::item {
|
||||
padding: 5px 6px;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
QListWidget::item:selected {
|
||||
background-color: #1a3a5a;
|
||||
color: #ffffff;
|
||||
}
|
||||
QListWidget::item:hover {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
QScrollBar:vertical {
|
||||
background: #1a1a1a;
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
QScrollBar::handle:vertical {
|
||||
background: #444;
|
||||
border-radius: 4px;
|
||||
}
|
||||
""")
|
||||
lst.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
lst.setDragDropMode(QAbstractItemView.InternalMove)
|
||||
lst.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
return lst
|
||||
|
||||
def _make_btn(self, text: str, color: str, height: int = 28) -> QPushButton:
|
||||
btn = QPushButton(text)
|
||||
btn.setFixedHeight(height)
|
||||
btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||
btn.setStyleSheet(f"""
|
||||
QPushButton {{
|
||||
background-color: {color};
|
||||
color: #cccccc;
|
||||
border: 1px solid #444;
|
||||
border-radius: 3px;
|
||||
}}
|
||||
QPushButton:hover {{ background-color: #555; }}
|
||||
QPushButton:pressed {{ background-color: #222; }}
|
||||
""")
|
||||
return btn
|
||||
|
||||
def _add_files_to(self, lst: QListWidget):
|
||||
paths, _ = QFileDialog.getOpenFileNames(
|
||||
self, "Add Files",
|
||||
os.path.expanduser("~"),
|
||||
self.AUDIO_FILTER
|
||||
)
|
||||
for path in paths:
|
||||
self._add_item_to(lst, path)
|
||||
self._update_count(lst)
|
||||
|
||||
def _add_folder_to(self, lst: QListWidget):
|
||||
folder = QFileDialog.getExistingDirectory(
|
||||
self, "Add Folder",
|
||||
os.path.expanduser("~")
|
||||
)
|
||||
if not folder:
|
||||
return
|
||||
for root_dir, dirs, files in os.walk(folder):
|
||||
dirs.sort()
|
||||
for filename in sorted(files):
|
||||
ext = os.path.splitext(filename)[1].lower()
|
||||
if ext in self.AUDIO_EXTENSIONS:
|
||||
self._add_item_to(lst, os.path.join(root_dir, filename))
|
||||
self._update_count(lst)
|
||||
|
||||
def _add_item_to(self, lst: QListWidget, filepath: str):
|
||||
for i in range(lst.count()):
|
||||
item = lst.item(i)
|
||||
if isinstance(item, PlaylistItem) and item.filepath == filepath:
|
||||
return
|
||||
lst.addItem(PlaylistItem(filepath))
|
||||
|
||||
def _update_count(self, lst: QListWidget, label: QLabel = None):
|
||||
n = lst.count()
|
||||
if label:
|
||||
label.setText(f"{n} track{'s' if n != 1 else ''}")
|
||||
|
||||
def _highlight(self, item: PlaylistItem,
|
||||
active: bool = False, queued: bool = False):
|
||||
if active:
|
||||
item.setForeground(QColor("#00ff41"))
|
||||
elif queued:
|
||||
item.setForeground(QColor("#f9ca24"))
|
||||
else:
|
||||
item.setForeground(QColor("#cccccc"))
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# TRACK PLAYLIST PANEL
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class TrackPlaylistPanel(BasePlaylistPanel):
|
||||
def __init__(self, engine, deck_widgets: dict, parent=None):
|
||||
super().__init__(parent)
|
||||
self.engine = engine
|
||||
self.deck_widgets = deck_widgets
|
||||
self._build_ui()
|
||||
|
||||
def _build_ui(self):
|
||||
self.setStyleSheet("""
|
||||
QWidget {
|
||||
background-color: #111111;
|
||||
border: 2px solid #333333;
|
||||
border-radius: 6px;
|
||||
}
|
||||
""")
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(8, 8, 8, 8)
|
||||
root.setSpacing(6)
|
||||
|
||||
header = QLabel("PLAYLIST")
|
||||
header.setFont(QFont("Arial", 12, QFont.Bold))
|
||||
header.setStyleSheet(
|
||||
"color: #aaaaaa; background: transparent; border: none; padding: 2px;"
|
||||
)
|
||||
header.setAlignment(Qt.AlignCenter)
|
||||
root.addWidget(header)
|
||||
|
||||
self.hour_display = HourDisplay()
|
||||
root.addWidget(self.hour_display)
|
||||
|
||||
self.deck_selector = DeckSelector()
|
||||
root.addWidget(self.deck_selector)
|
||||
|
||||
self.playlist = self._make_list()
|
||||
self.playlist.itemDoubleClicked.connect(self._send_to_deck)
|
||||
self.playlist.customContextMenuRequested.connect(self._context_menu)
|
||||
root.addWidget(self.playlist)
|
||||
|
||||
row1 = QHBoxLayout()
|
||||
row1.setSpacing(4)
|
||||
self.btn_add_files = self._make_btn("ADD FILES", "#2a5a8a")
|
||||
self.btn_add_folder = self._make_btn("ADD FOLDER", "#2a4a6a")
|
||||
row1.addWidget(self.btn_add_files)
|
||||
row1.addWidget(self.btn_add_folder)
|
||||
root.addLayout(row1)
|
||||
|
||||
row2 = QHBoxLayout()
|
||||
row2.setSpacing(4)
|
||||
self.btn_send_deck = self._make_btn("→ LOAD DECK", "#1a5a3a")
|
||||
self.btn_send_queue = self._make_btn("→ QUEUE", "#1a3a2a")
|
||||
row2.addWidget(self.btn_send_deck)
|
||||
row2.addWidget(self.btn_send_queue)
|
||||
root.addLayout(row2)
|
||||
|
||||
row3 = QHBoxLayout()
|
||||
row3.setSpacing(4)
|
||||
self.btn_remove = self._make_btn("REMOVE", "#5a1a1a")
|
||||
self.btn_clear = self._make_btn("CLEAR ALL", "#3a1a1a")
|
||||
row3.addWidget(self.btn_remove)
|
||||
row3.addWidget(self.btn_clear)
|
||||
root.addLayout(row3)
|
||||
|
||||
self.count_label = QLabel("0 tracks")
|
||||
self.count_label.setFont(QFont("Courier New", 9))
|
||||
self.count_label.setStyleSheet(
|
||||
"color: #555; background: transparent; border: none;"
|
||||
)
|
||||
self.count_label.setAlignment(Qt.AlignCenter)
|
||||
root.addWidget(self.count_label)
|
||||
|
||||
self.btn_add_files.clicked.connect(
|
||||
lambda: self._add_files_to(self.playlist)
|
||||
)
|
||||
self.btn_add_folder.clicked.connect(
|
||||
lambda: self._add_folder_to(self.playlist)
|
||||
)
|
||||
self.btn_send_deck.clicked.connect(self._send_to_deck)
|
||||
self.btn_send_queue.clicked.connect(self._send_to_queue)
|
||||
self.btn_remove.clicked.connect(self._remove_selected)
|
||||
self.btn_clear.clicked.connect(self._clear_all)
|
||||
|
||||
def _send_to_deck(self, item=None):
|
||||
if item is None:
|
||||
item = self.playlist.currentItem()
|
||||
if not isinstance(item, PlaylistItem):
|
||||
return
|
||||
deck_key = self.deck_selector.selected_deck
|
||||
self.engine.load_track(deck_key, item.filepath)
|
||||
name = os.path.splitext(item.filename)[0]
|
||||
if deck_key in self.deck_widgets:
|
||||
self.deck_widgets[deck_key].set_track_name(name)
|
||||
self._highlight(item, active=True)
|
||||
|
||||
def _send_to_queue(self):
|
||||
item = self.playlist.currentItem()
|
||||
if not isinstance(item, PlaylistItem):
|
||||
return
|
||||
deck_key = self.deck_selector.selected_deck
|
||||
self.engine.load_queue(deck_key, item.filepath)
|
||||
name = os.path.splitext(item.filename)[0]
|
||||
if deck_key in self.deck_widgets:
|
||||
self.deck_widgets[deck_key].set_queue_name(name)
|
||||
self._highlight(item, queued=True)
|
||||
|
||||
def _remove_selected(self):
|
||||
row = self.playlist.currentRow()
|
||||
if row >= 0:
|
||||
self.playlist.takeItem(row)
|
||||
self._update_count(self.playlist, self.count_label)
|
||||
|
||||
def _clear_all(self):
|
||||
self.playlist.clear()
|
||||
self._update_count(self.playlist, self.count_label)
|
||||
|
||||
def _context_menu(self, position):
|
||||
item = self.playlist.itemAt(position)
|
||||
if not isinstance(item, PlaylistItem):
|
||||
return
|
||||
|
||||
menu = QMenu(self)
|
||||
menu.setStyleSheet("""
|
||||
QMenu {
|
||||
background-color: #1e1e1e;
|
||||
color: #cccccc;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
QMenu::item:selected { background-color: #1a3a5a; }
|
||||
""")
|
||||
|
||||
def load(deck_key):
|
||||
self.engine.load_track(deck_key, item.filepath)
|
||||
name = os.path.splitext(item.filename)[0]
|
||||
if deck_key in self.deck_widgets:
|
||||
self.deck_widgets[deck_key].set_track_name(name)
|
||||
self._highlight(item, active=True)
|
||||
|
||||
def queue(deck_key):
|
||||
self.engine.load_queue(deck_key, item.filepath)
|
||||
name = os.path.splitext(item.filename)[0]
|
||||
if deck_key in self.deck_widgets:
|
||||
self.deck_widgets[deck_key].set_queue_name(name)
|
||||
self._highlight(item, queued=True)
|
||||
|
||||
a1 = QAction("Load → Deck 1", self)
|
||||
a2 = QAction("Load → Deck 2", self)
|
||||
a3 = QAction("Queue → Deck 1", self)
|
||||
a4 = QAction("Queue → Deck 2", self)
|
||||
ar = QAction("Remove", self)
|
||||
|
||||
a1.triggered.connect(lambda: load("deck1"))
|
||||
a2.triggered.connect(lambda: load("deck2"))
|
||||
a3.triggered.connect(lambda: queue("deck1"))
|
||||
a4.triggered.connect(lambda: queue("deck2"))
|
||||
ar.triggered.connect(
|
||||
lambda: self.playlist.takeItem(self.playlist.row(item))
|
||||
)
|
||||
|
||||
menu.addAction(a1)
|
||||
menu.addAction(a2)
|
||||
menu.addSeparator()
|
||||
menu.addAction(a3)
|
||||
menu.addAction(a4)
|
||||
menu.addSeparator()
|
||||
menu.addAction(ar)
|
||||
menu.exec(self.playlist.viewport().mapToGlobal(position))
|
||||
self._update_count(self.playlist, self.count_label)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# CART PLAYLIST PANEL
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class CartPlaylistPanel(BasePlaylistPanel):
|
||||
def __init__(self, engine, cart_slots: list, parent=None):
|
||||
super().__init__(parent)
|
||||
self.engine = engine
|
||||
self.cart_slots = cart_slots
|
||||
self._build_ui()
|
||||
|
||||
def _build_ui(self):
|
||||
self.setStyleSheet("""
|
||||
QWidget {
|
||||
background-color: #111111;
|
||||
border: 2px solid #cc3300;
|
||||
border-radius: 6px;
|
||||
}
|
||||
""")
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(8, 8, 8, 8)
|
||||
root.setSpacing(6)
|
||||
|
||||
header = QLabel("CART PLAYLIST")
|
||||
header.setFont(QFont("Arial", 12, QFont.Bold))
|
||||
header.setStyleSheet(
|
||||
"color: #cc3300; background: transparent; border: none; padding: 2px;"
|
||||
)
|
||||
header.setAlignment(Qt.AlignCenter)
|
||||
root.addWidget(header)
|
||||
|
||||
self.playlist = self._make_list()
|
||||
self.playlist.itemDoubleClicked.connect(self._send_to_next_free_cart)
|
||||
self.playlist.customContextMenuRequested.connect(self._context_menu)
|
||||
root.addWidget(self.playlist)
|
||||
|
||||
row1 = QHBoxLayout()
|
||||
row1.setSpacing(4)
|
||||
self.btn_add_files = self._make_btn("ADD FILES", "#5a2a00")
|
||||
self.btn_add_folder = self._make_btn("ADD FOLDER", "#4a2000")
|
||||
row1.addWidget(self.btn_add_files)
|
||||
row1.addWidget(self.btn_add_folder)
|
||||
root.addLayout(row1)
|
||||
|
||||
row2 = QHBoxLayout()
|
||||
row2.setSpacing(4)
|
||||
self.btn_remove = self._make_btn("REMOVE", "#5a1a1a")
|
||||
self.btn_clear = self._make_btn("CLEAR ALL", "#3a1a1a")
|
||||
row2.addWidget(self.btn_remove)
|
||||
row2.addWidget(self.btn_clear)
|
||||
root.addLayout(row2)
|
||||
|
||||
self.count_label = QLabel("0 tracks")
|
||||
self.count_label.setFont(QFont("Courier New", 9))
|
||||
self.count_label.setStyleSheet(
|
||||
"color: #555; background: transparent; border: none;"
|
||||
)
|
||||
self.count_label.setAlignment(Qt.AlignCenter)
|
||||
root.addWidget(self.count_label)
|
||||
|
||||
self.btn_add_files.clicked.connect(
|
||||
lambda: self._add_files_to(self.playlist)
|
||||
)
|
||||
self.btn_add_folder.clicked.connect(
|
||||
lambda: self._add_folder_to(self.playlist)
|
||||
)
|
||||
self.btn_remove.clicked.connect(self._remove_selected)
|
||||
self.btn_clear.clicked.connect(self._clear_all)
|
||||
|
||||
def _send_to_cart(self, item: PlaylistItem, cart_index: int):
|
||||
if not isinstance(item, PlaylistItem):
|
||||
return
|
||||
slot = self.cart_slots[cart_index]
|
||||
slot.load_track(item.filepath)
|
||||
self._highlight(item, active=True)
|
||||
|
||||
def _send_to_next_free_cart(self, item=None):
|
||||
if item is None:
|
||||
item = self.playlist.currentItem()
|
||||
if not isinstance(item, PlaylistItem):
|
||||
return
|
||||
for i in range(4):
|
||||
cart_key = f"cart{i + 1}"
|
||||
if self.engine.decks[cart_key].track is None:
|
||||
self._send_to_cart(item, i)
|
||||
return
|
||||
self._send_to_cart(item, 0)
|
||||
|
||||
def _remove_selected(self):
|
||||
row = self.playlist.currentRow()
|
||||
if row >= 0:
|
||||
self.playlist.takeItem(row)
|
||||
self._update_count(self.playlist, self.count_label)
|
||||
|
||||
def _clear_all(self):
|
||||
self.playlist.clear()
|
||||
self._update_count(self.playlist, self.count_label)
|
||||
|
||||
def _context_menu(self, position):
|
||||
item = self.playlist.itemAt(position)
|
||||
if not isinstance(item, PlaylistItem):
|
||||
return
|
||||
|
||||
menu = QMenu(self)
|
||||
menu.setStyleSheet("""
|
||||
QMenu {
|
||||
background-color: #1e1e1e;
|
||||
color: #cccccc;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
QMenu::item:selected { background-color: #1a3a5a; }
|
||||
""")
|
||||
|
||||
for i in range(4):
|
||||
action = QAction(f"Load → Cart {i + 1}", self)
|
||||
action.triggered.connect(
|
||||
lambda checked, idx=i: self._send_to_cart(item, idx)
|
||||
)
|
||||
menu.addAction(action)
|
||||
|
||||
menu.addSeparator()
|
||||
ar = QAction("Remove", self)
|
||||
ar.triggered.connect(
|
||||
lambda: self.playlist.takeItem(self.playlist.row(item))
|
||||
)
|
||||
menu.addAction(ar)
|
||||
menu.exec(self.playlist.viewport().mapToGlobal(position))
|
||||
self._update_count(self.playlist, self.count_label)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# COMBINED PLAYLIST WIDGET
|
||||
# ─────────────────────────────────────────
|
||||
|
||||
class PlaylistWidget(QWidget):
|
||||
def __init__(self, engine, deck_widgets: dict,
|
||||
cart_slots: list, parent=None):
|
||||
super().__init__(parent)
|
||||
self.engine = engine
|
||||
|
||||
# Expandable - no fixed width
|
||||
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
self.setMinimumWidth(200)
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(0, 0, 0, 0)
|
||||
root.setSpacing(0)
|
||||
|
||||
splitter = QSplitter(Qt.Vertical)
|
||||
splitter.setStyleSheet("""
|
||||
QSplitter::handle {
|
||||
background-color: #333;
|
||||
height: 4px;
|
||||
}
|
||||
""")
|
||||
|
||||
self.track_panel = TrackPlaylistPanel(engine, deck_widgets)
|
||||
self.cart_panel = CartPlaylistPanel(engine, cart_slots)
|
||||
|
||||
splitter.addWidget(self.track_panel)
|
||||
splitter.addWidget(self.cart_panel)
|
||||
splitter.setSizes([600, 400])
|
||||
|
||||
root.addWidget(splitter)
|
||||
Reference in New Issue
Block a user