Replace text buttons with SVG icons, rebrand to Getting To It
This commit is contained in:
+16
-12
@@ -4,10 +4,12 @@ from PySide6.QtWidgets import (
|
|||||||
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||||
QPushButton, QFrame, QSizePolicy, QGridLayout
|
QPushButton, QFrame, QSizePolicy, QGridLayout
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt, QTimer
|
from PySide6.QtCore import Qt, QTimer, QSize
|
||||||
from PySide6.QtGui import QFont
|
from PySide6.QtGui import QFont
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from icons import icon_play, icon_pause, icon_eject
|
||||||
|
|
||||||
|
|
||||||
class CartSlot(QFrame):
|
class CartSlot(QFrame):
|
||||||
def __init__(self, cart_key: str, slot_number: int, engine, parent=None):
|
def __init__(self, cart_key: str, slot_number: int, engine, parent=None):
|
||||||
@@ -15,6 +17,8 @@ class CartSlot(QFrame):
|
|||||||
self.cart_key = cart_key
|
self.cart_key = cart_key
|
||||||
self.slot_number = slot_number
|
self.slot_number = slot_number
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
|
self._playing_icon = False
|
||||||
|
self._playing_icon = False
|
||||||
|
|
||||||
self.setFrameStyle(QFrame.Box | QFrame.Raised)
|
self.setFrameStyle(QFrame.Box | QFrame.Raised)
|
||||||
self.setLineWidth(1)
|
self.setLineWidth(1)
|
||||||
@@ -108,13 +112,13 @@ class CartSlot(QFrame):
|
|||||||
btn_col = QVBoxLayout()
|
btn_col = QVBoxLayout()
|
||||||
btn_col.setSpacing(4)
|
btn_col.setSpacing(4)
|
||||||
|
|
||||||
self.btn_play = QPushButton("▶")
|
self.btn_play = QPushButton()
|
||||||
self.btn_play.setFixedSize(60, 44)
|
self.btn_play.setFixedSize(60, 44)
|
||||||
self.btn_play.setFont(QFont("Arial", 13, QFont.Bold))
|
self.btn_play.setIconSize(QSize(22, 22))
|
||||||
|
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #1a6b3a;
|
background-color: #1a6b3a;
|
||||||
color: #00ff41;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
@@ -122,13 +126,13 @@ class CartSlot(QFrame):
|
|||||||
QPushButton:pressed { background-color: #0a5a2a; }
|
QPushButton:pressed { background-color: #0a5a2a; }
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.btn_eject = QPushButton("⏏")
|
self.btn_eject = QPushButton()
|
||||||
self.btn_eject.setFixedSize(60, 30)
|
self.btn_eject.setFixedSize(60, 30)
|
||||||
self.btn_eject.setFont(QFont("Arial", 11, QFont.Bold))
|
self.btn_eject.setIconSize(QSize(18, 18))
|
||||||
|
self.btn_eject.setIcon(icon_eject("#ff4444"))
|
||||||
self.btn_eject.setStyleSheet("""
|
self.btn_eject.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #8a1a1a;
|
background-color: #8a1a1a;
|
||||||
color: #ff4444;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
@@ -179,11 +183,11 @@ class CartSlot(QFrame):
|
|||||||
self._set_ui_playing()
|
self._set_ui_playing()
|
||||||
|
|
||||||
def _set_ui_playing(self):
|
def _set_ui_playing(self):
|
||||||
self.btn_play.setText("⏸")
|
self.btn_play.setIcon(icon_pause("#ffffff"))
|
||||||
|
self._playing_icon = True
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #00aa33;
|
background-color: #00aa33;
|
||||||
color: white;
|
|
||||||
border: 1px solid #00ff41;
|
border: 1px solid #00ff41;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
@@ -195,11 +199,11 @@ class CartSlot(QFrame):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _set_ui_stopped(self):
|
def _set_ui_stopped(self):
|
||||||
self.btn_play.setText("▶")
|
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||||
|
self._playing_icon = False
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #1a6b3a;
|
background-color: #1a6b3a;
|
||||||
color: #00ff41;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
@@ -233,7 +237,7 @@ class CartSlot(QFrame):
|
|||||||
def _refresh_display(self):
|
def _refresh_display(self):
|
||||||
deck = self.engine.decks[self.cart_key]
|
deck = self.engine.decks[self.cart_key]
|
||||||
|
|
||||||
if not deck.playing and self.btn_play.text() == "⏸":
|
if not deck.playing and self._playing_icon:
|
||||||
self._set_ui_stopped()
|
self._set_ui_stopped()
|
||||||
self.status_label.setText("STOPPED")
|
self.status_label.setText("STOPPED")
|
||||||
|
|
||||||
|
|||||||
+33
-26
@@ -4,11 +4,16 @@ from PySide6.QtWidgets import (
|
|||||||
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||||
QPushButton, QFrame, QSizePolicy
|
QPushButton, QFrame, QSizePolicy
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt, QTimer, Signal
|
from PySide6.QtCore import Qt, QTimer, Signal, QSize
|
||||||
from PySide6.QtGui import QFont, QColor, QPainter, QPen
|
from PySide6.QtGui import QFont, QColor, QPainter, QPen
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from icons import (
|
||||||
|
icon_play, icon_pause, icon_stop, icon_skip_start,
|
||||||
|
icon_skip_end, icon_skip_back, icon_skip_forward, icon_eject
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class WaveformWidget(QFrame):
|
class WaveformWidget(QFrame):
|
||||||
"""Displays downsampled waveform with playhead position."""
|
"""Displays downsampled waveform with playhead position."""
|
||||||
@@ -207,18 +212,18 @@ class LCDDisplay(QFrame):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_transport_button(text: str,
|
def make_icon_button(icon: QIcon,
|
||||||
color: str = "#3a3a3a",
|
color: str = "#3a3a3a",
|
||||||
text_color: str = "white",
|
icon_color: str = "white",
|
||||||
width: int = 52,
|
width: int = 52,
|
||||||
height: int = 48) -> QPushButton:
|
height: int = 48) -> QPushButton:
|
||||||
btn = QPushButton(text)
|
btn = QPushButton()
|
||||||
btn.setFixedSize(width, height)
|
btn.setFixedSize(width, height)
|
||||||
btn.setFont(QFont("Arial", 11, QFont.Bold))
|
btn.setIconSize(QSize(22, 22))
|
||||||
|
btn.setIcon(icon)
|
||||||
btn.setStyleSheet(f"""
|
btn.setStyleSheet(f"""
|
||||||
QPushButton {{
|
QPushButton {{
|
||||||
background-color: {color};
|
background-color: {color};
|
||||||
color: {text_color};
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}}
|
}}
|
||||||
@@ -244,6 +249,8 @@ class DeckWidget(QWidget):
|
|||||||
self.accent_color = accent_color
|
self.accent_color = accent_color
|
||||||
self.current_theme = None
|
self.current_theme = None
|
||||||
self.flash_state = False
|
self.flash_state = False
|
||||||
|
self._playing_icon = False
|
||||||
|
self._playing_icon = False
|
||||||
|
|
||||||
# Convert "DECK 1" to "DECK_001"
|
# Convert "DECK 1" to "DECK_001"
|
||||||
deck_num = label.split()[-1]
|
deck_num = label.split()[-1]
|
||||||
@@ -295,12 +302,12 @@ class DeckWidget(QWidget):
|
|||||||
transport = QHBoxLayout()
|
transport = QHBoxLayout()
|
||||||
transport.setSpacing(6)
|
transport.setSpacing(6)
|
||||||
|
|
||||||
self.btn_to_start = make_transport_button("⏮", "#3a3a3a", "white", 52, 48)
|
self.btn_to_start = make_icon_button(icon_skip_start())
|
||||||
self.btn_back_15 = make_transport_button("-15", "#3a3a3a", "#aaaaaa", 52, 48)
|
self.btn_back_15 = make_icon_button(icon_skip_back(), icon_color="#aaaaaa")
|
||||||
self.btn_play = make_transport_button("▶", "#1a6b3a", "#00ff41", 68, 48)
|
self.btn_play = make_icon_button(icon_play(), "#1a6b3a", "#00ff41", 68, 48)
|
||||||
self.btn_fwd_15 = make_transport_button("+15", "#3a3a3a", "#aaaaaa", 52, 48)
|
self.btn_fwd_15 = make_icon_button(icon_skip_forward(), icon_color="#aaaaaa")
|
||||||
self.btn_to_end = make_transport_button("⏭", "#3a3a3a", "white", 52, 48)
|
self.btn_to_end = make_icon_button(icon_skip_end())
|
||||||
self.btn_stop = make_transport_button("■", "#8a1a1a", "#ff4444", 52, 48)
|
self.btn_stop = make_icon_button(icon_stop(), "#8a1a1a", "#ff4444")
|
||||||
|
|
||||||
transport.addWidget(self.btn_to_start)
|
transport.addWidget(self.btn_to_start)
|
||||||
transport.addWidget(self.btn_back_15)
|
transport.addWidget(self.btn_back_15)
|
||||||
@@ -377,11 +384,11 @@ class DeckWidget(QWidget):
|
|||||||
if deck.playing:
|
if deck.playing:
|
||||||
deck.pause()
|
deck.pause()
|
||||||
deck.go_to_start()
|
deck.go_to_start()
|
||||||
self.btn_play.setText("▶")
|
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||||
|
self._playing_icon = False
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #1a6b3a;
|
background-color: #1a6b3a;
|
||||||
color: #00ff41;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
@@ -399,11 +406,11 @@ class DeckWidget(QWidget):
|
|||||||
return
|
return
|
||||||
if deck.playing:
|
if deck.playing:
|
||||||
deck.pause()
|
deck.pause()
|
||||||
self.btn_play.setText("▶")
|
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||||
|
self._playing_icon = False
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #1a6b3a;
|
background-color: #1a6b3a;
|
||||||
color: #00ff41;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
@@ -413,11 +420,11 @@ class DeckWidget(QWidget):
|
|||||||
self.lcd.set_playing(False)
|
self.lcd.set_playing(False)
|
||||||
else:
|
else:
|
||||||
deck.play()
|
deck.play()
|
||||||
self.btn_play.setText("⏸")
|
self.btn_play.setIcon(icon_pause("#ffffff"))
|
||||||
|
self._playing_icon = True
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #00aa33;
|
background-color: #00aa33;
|
||||||
color: white;
|
|
||||||
border: 1px solid #00ff41;
|
border: 1px solid #00ff41;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
@@ -431,11 +438,11 @@ class DeckWidget(QWidget):
|
|||||||
def _stop_eject(self):
|
def _stop_eject(self):
|
||||||
deck = self.engine.decks[self.deck_key]
|
deck = self.engine.decks[self.deck_key]
|
||||||
deck.stop()
|
deck.stop()
|
||||||
self.btn_play.setText("▶")
|
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||||
|
self._playing_icon = False
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #1a6b3a;
|
background-color: #1a6b3a;
|
||||||
color: #00ff41;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
@@ -471,12 +478,12 @@ class DeckWidget(QWidget):
|
|||||||
self.lcd.update_status("LOADED")
|
self.lcd.update_status("LOADED")
|
||||||
|
|
||||||
# Sync button if stopped manually
|
# Sync button if stopped manually
|
||||||
if not deck.playing and self.btn_play.text() == "⏸":
|
if not deck.playing and self._playing_icon:
|
||||||
self.btn_play.setText("▶")
|
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||||
|
self._playing_icon = False
|
||||||
self.btn_play.setStyleSheet("""
|
self.btn_play.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #1a6b3a;
|
background-color: #1a6b3a;
|
||||||
color: #00ff41;
|
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-5
@@ -13,9 +13,11 @@ from PySide6.QtWidgets import (
|
|||||||
QLineEdit, QFormLayout, QDialogButtonBox,
|
QLineEdit, QFormLayout, QDialogButtonBox,
|
||||||
QFileDialog
|
QFileDialog
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt, Signal
|
from PySide6.QtCore import Qt, Signal, QSize
|
||||||
from PySide6.QtGui import QFont
|
from PySide6.QtGui import QFont
|
||||||
|
|
||||||
|
from icons import icon_plus, icon_delete, icon_export
|
||||||
|
|
||||||
musicbrainzngs.set_useragent("RadioPanel", "1.0", "radio@panel.local")
|
musicbrainzngs.set_useragent("RadioPanel", "1.0", "radio@panel.local")
|
||||||
|
|
||||||
|
|
||||||
@@ -111,13 +113,13 @@ class HistoryEntry(QFrame):
|
|||||||
|
|
||||||
root.addLayout(text_col, stretch=1)
|
root.addLayout(text_col, stretch=1)
|
||||||
|
|
||||||
self._del_btn = QPushButton("✕")
|
self._del_btn = QPushButton()
|
||||||
self._del_btn.setFixedSize(24, 24)
|
self._del_btn.setFixedSize(24, 24)
|
||||||
self._del_btn.setFont(QFont("Arial", 10, QFont.Bold))
|
self._del_btn.setIconSize(QSize(14, 14))
|
||||||
|
self._del_btn.setIcon(icon_delete("#ff4444"))
|
||||||
self._del_btn.setStyleSheet("""
|
self._del_btn.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #5a1a1a;
|
background-color: #5a1a1a;
|
||||||
color: #ff4444;
|
|
||||||
border: 1px solid #444;
|
border: 1px solid #444;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
@@ -243,8 +245,10 @@ class HistoryWidget(QFrame):
|
|||||||
bar = QHBoxLayout()
|
bar = QHBoxLayout()
|
||||||
bar.setSpacing(4)
|
bar.setSpacing(4)
|
||||||
|
|
||||||
self._add_btn = QPushButton("+ ADD")
|
self._add_btn = QPushButton("ADD")
|
||||||
self._add_btn.setFixedHeight(28)
|
self._add_btn.setFixedHeight(28)
|
||||||
|
self._add_btn.setIconSize(QSize(16, 16))
|
||||||
|
self._add_btn.setIcon(icon_plus("#00ff41"))
|
||||||
self._add_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
self._add_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||||
self._add_btn.setStyleSheet("""
|
self._add_btn.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
@@ -298,6 +302,8 @@ class HistoryWidget(QFrame):
|
|||||||
|
|
||||||
self._export_txt_btn = QPushButton("EXPORT TXT")
|
self._export_txt_btn = QPushButton("EXPORT TXT")
|
||||||
self._export_txt_btn.setFixedHeight(28)
|
self._export_txt_btn.setFixedHeight(28)
|
||||||
|
self._export_txt_btn.setIconSize(QSize(16, 16))
|
||||||
|
self._export_txt_btn.setIcon(icon_export("#aaaaaa"))
|
||||||
self._export_txt_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
self._export_txt_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||||
self._export_txt_btn.setStyleSheet("""
|
self._export_txt_btn.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
@@ -313,6 +319,8 @@ class HistoryWidget(QFrame):
|
|||||||
|
|
||||||
self._export_csv_btn = QPushButton("EXPORT CSV")
|
self._export_csv_btn = QPushButton("EXPORT CSV")
|
||||||
self._export_csv_btn.setFixedHeight(28)
|
self._export_csv_btn.setFixedHeight(28)
|
||||||
|
self._export_csv_btn.setIconSize(QSize(16, 16))
|
||||||
|
self._export_csv_btn.setIcon(icon_export("#aaaaaa"))
|
||||||
self._export_csv_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
self._export_csv_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||||
self._export_csv_btn.setStyleSheet("""
|
self._export_csv_btn.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
# icons.py -- QPainter-drawn icons for Radio Panel
|
||||||
|
#
|
||||||
|
# Each function takes (color: str) and returns a QIcon painted at 24x24.
|
||||||
|
# All icons are simple geometric shapes -- clean, broadcast-console look.
|
||||||
|
|
||||||
|
from PySide6.QtGui import QPainter, QColor, QPen, QBrush, QPixmap, QIcon, QPainterPath
|
||||||
|
from PySide6.QtCore import Qt, QRectF, QPointF
|
||||||
|
|
||||||
|
_S = 24
|
||||||
|
|
||||||
|
|
||||||
|
def _make_icon(paint_fn, color: str) -> QIcon:
|
||||||
|
pix = QPixmap(_S, _S)
|
||||||
|
pix.fill(Qt.transparent)
|
||||||
|
p = QPainter(pix)
|
||||||
|
p.setRenderHint(QPainter.Antialiasing)
|
||||||
|
paint_fn(p, QRectF(2, 2, _S - 4, _S - 4), QColor(color))
|
||||||
|
p.end()
|
||||||
|
return QIcon(pix)
|
||||||
|
|
||||||
|
|
||||||
|
# ── Transport Icons ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def icon_play(color: str = "#00ff41") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
path = QPainterPath()
|
||||||
|
path.moveTo(r.left(), r.top())
|
||||||
|
path.lineTo(r.right(), r.center().y())
|
||||||
|
path.lineTo(r.left(), r.bottom())
|
||||||
|
path.closeSubpath()
|
||||||
|
p.drawPath(path)
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_pause(color: str = "#ffffff") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
w = r.width() * 0.32
|
||||||
|
p.drawRect(QRectF(r.left(), r.top(), w, r.height()))
|
||||||
|
p.drawRect(QRectF(r.right() - w, r.top(), w, r.height()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_stop(color: str = "#ff4444") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
margin = r.width() * 0.18
|
||||||
|
p.drawRect(r.adjusted(margin, margin, -margin, -margin))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_skip_start(color: str = "#ffffff") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
w = r.width() * 0.35
|
||||||
|
# Two triangles pointing left
|
||||||
|
path = QPainterPath()
|
||||||
|
path.moveTo(r.right(), r.top())
|
||||||
|
path.lineTo(r.left(), r.center().y())
|
||||||
|
path.lineTo(r.right(), r.bottom())
|
||||||
|
path.closeSubpath()
|
||||||
|
p.drawPath(path)
|
||||||
|
path2 = QPainterPath()
|
||||||
|
path2.moveTo(r.center().x(), r.top())
|
||||||
|
path2.lineTo(r.left(), r.center().y())
|
||||||
|
path2.lineTo(r.center().x(), r.bottom())
|
||||||
|
path2.closeSubpath()
|
||||||
|
p.drawPath(path2)
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_skip_end(color: str = "#ffffff") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
path = QPainterPath()
|
||||||
|
path.moveTo(r.left(), r.top())
|
||||||
|
path.lineTo(r.right(), r.center().y())
|
||||||
|
path.lineTo(r.left(), r.bottom())
|
||||||
|
path.closeSubpath()
|
||||||
|
p.drawPath(path)
|
||||||
|
path2 = QPainterPath()
|
||||||
|
path2.moveTo(r.center().x(), r.top())
|
||||||
|
path2.lineTo(r.right(), r.center().y())
|
||||||
|
path2.lineTo(r.center().x(), r.bottom())
|
||||||
|
path2.closeSubpath()
|
||||||
|
p.drawPath(path2)
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_skip_back(color: str = "#aaaaaa") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
path = QPainterPath()
|
||||||
|
path.moveTo(r.right() * 0.7, r.top())
|
||||||
|
path.lineTo(r.left(), r.center().y())
|
||||||
|
path.lineTo(r.right() * 0.7, r.bottom())
|
||||||
|
path.closeSubpath()
|
||||||
|
p.drawPath(path)
|
||||||
|
# Vertical bar
|
||||||
|
bar_w = r.width() * 0.12
|
||||||
|
p.drawRect(QRectF(r.right() - bar_w, r.top(), bar_w, r.height()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_skip_forward(color: str = "#aaaaaa") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
p.setBrush(c)
|
||||||
|
path = QPainterPath()
|
||||||
|
path.moveTo(r.left() + r.width() * 0.3, r.top())
|
||||||
|
path.lineTo(r.right(), r.center().y())
|
||||||
|
path.lineTo(r.left() + r.width() * 0.3, r.bottom())
|
||||||
|
path.closeSubpath()
|
||||||
|
p.drawPath(path)
|
||||||
|
bar_w = r.width() * 0.12
|
||||||
|
p.drawRect(QRectF(r.left(), r.top(), bar_w, r.height()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_eject(color: str = "#ff4444") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
pen = QPen(c, r.width() * 0.12)
|
||||||
|
pen.setCapStyle(Qt.RoundCap)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.setBrush(Qt.NoBrush)
|
||||||
|
# Upward triangle
|
||||||
|
mid_x = r.center().x()
|
||||||
|
path = QPainterPath()
|
||||||
|
path.moveTo(r.left() + r.width() * 0.2, r.center().y() + r.height() * 0.1)
|
||||||
|
path.lineTo(mid_x, r.top() + r.height() * 0.2)
|
||||||
|
path.lineTo(r.right() - r.width() * 0.2, r.center().y() + r.height() * 0.1)
|
||||||
|
p.drawPath(path)
|
||||||
|
# Horizontal line
|
||||||
|
p.drawLine(QPointF(r.left() + r.width() * 0.2, r.bottom() - r.height() * 0.1),
|
||||||
|
QPointF(r.right() - r.width() * 0.2, r.bottom() - r.height() * 0.1))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
# ── Action Icons ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def icon_plus(color: str = "#00ff41") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
pen = QPen(c, r.width() * 0.12)
|
||||||
|
pen.setCapStyle(Qt.RoundCap)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.setBrush(Qt.NoBrush)
|
||||||
|
mid = r.center()
|
||||||
|
p.drawLine(QPointF(mid.x(), r.top()), QPointF(mid.x(), r.bottom()))
|
||||||
|
p.drawLine(QPointF(r.left(), mid.y()), QPointF(r.right(), mid.y()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_delete(color: str = "#ff4444") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
pen = QPen(c, r.width() * 0.12)
|
||||||
|
pen.setCapStyle(Qt.RoundCap)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.setBrush(Qt.NoBrush)
|
||||||
|
p.drawLine(QPointF(r.left(), r.top()), QPointF(r.right(), r.bottom()))
|
||||||
|
p.drawLine(QPointF(r.right(), r.top()), QPointF(r.left(), r.bottom()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_save(color: str = "#aaaaaa") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
pen = QPen(c, r.width() * 0.12)
|
||||||
|
pen.setCapStyle(Qt.RoundCap)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.setBrush(Qt.NoBrush)
|
||||||
|
# Arrow down into tray
|
||||||
|
mid_x = r.center().x()
|
||||||
|
p.drawLine(QPointF(mid_x, r.top()), QPointF(mid_x, r.bottom() - r.height() * 0.15))
|
||||||
|
# Arrow head
|
||||||
|
p.drawLine(QPointF(mid_x - r.width() * 0.25, r.bottom() - r.height() * 0.4),
|
||||||
|
QPointF(mid_x, r.bottom() - r.height() * 0.15))
|
||||||
|
p.drawLine(QPointF(mid_x + r.width() * 0.25, r.bottom() - r.height() * 0.4),
|
||||||
|
QPointF(mid_x, r.bottom() - r.height() * 0.15))
|
||||||
|
# Tray bottom line
|
||||||
|
p.drawLine(QPointF(r.left(), r.bottom()), QPointF(r.right(), r.bottom()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_load(color: str = "#aaaaaa") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
pen = QPen(c, r.width() * 0.12)
|
||||||
|
pen.setCapStyle(Qt.RoundCap)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.setBrush(Qt.NoBrush)
|
||||||
|
# Arrow up from tray
|
||||||
|
mid_x = r.center().x()
|
||||||
|
p.drawLine(QPointF(mid_x, r.bottom()), QPointF(mid_x, r.top() + r.height() * 0.15))
|
||||||
|
p.drawLine(QPointF(mid_x - r.width() * 0.25, r.top() + r.height() * 0.35),
|
||||||
|
QPointF(mid_x, r.top() + r.height() * 0.1))
|
||||||
|
p.drawLine(QPointF(mid_x + r.width() * 0.25, r.top() + r.height() * 0.35),
|
||||||
|
QPointF(mid_x, r.top() + r.height() * 0.1))
|
||||||
|
p.drawLine(QPointF(r.left(), r.bottom()), QPointF(r.right(), r.bottom()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_export(color: str = "#aaaaaa") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
pen = QPen(c, r.width() * 0.12)
|
||||||
|
pen.setCapStyle(Qt.RoundCap)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.setBrush(Qt.NoBrush)
|
||||||
|
# Box
|
||||||
|
margin = r.width() * 0.15
|
||||||
|
p.drawRect(r.adjusted(margin, margin, -margin, -margin))
|
||||||
|
# Arrow out of box (top-right)
|
||||||
|
p.drawLine(QPointF(r.right() - margin, r.top() + margin),
|
||||||
|
QPointF(r.right(), r.top()))
|
||||||
|
p.drawLine(QPointF(r.right() - r.width() * 0.3, r.top()),
|
||||||
|
QPointF(r.right(), r.top()))
|
||||||
|
p.drawLine(QPointF(r.right(), r.top() + r.height() * 0.3),
|
||||||
|
QPointF(r.right(), r.top()))
|
||||||
|
return _make_icon(paint, color)
|
||||||
|
|
||||||
|
|
||||||
|
def icon_theme(color: str = "#00ff41") -> QIcon:
|
||||||
|
def paint(p, r, c):
|
||||||
|
p.setPen(Qt.NoPen)
|
||||||
|
# Draw 4 coloured quadrants
|
||||||
|
mid = r.center()
|
||||||
|
colors = [QColor("#00ff41"), QColor("#ffaa00"),
|
||||||
|
QColor("#00aaff"), QColor("#ff4444")]
|
||||||
|
for i, col in enumerate(colors):
|
||||||
|
path = QPainterPath()
|
||||||
|
if i == 0:
|
||||||
|
path.moveTo(mid)
|
||||||
|
path.arcTo(r, 0, 90)
|
||||||
|
path.closeSubpath()
|
||||||
|
elif i == 1:
|
||||||
|
path.moveTo(mid)
|
||||||
|
path.arcTo(r, 270, 90)
|
||||||
|
path.closeSubpath()
|
||||||
|
elif i == 2:
|
||||||
|
path.moveTo(mid)
|
||||||
|
path.arcTo(r, 180, 90)
|
||||||
|
path.closeSubpath()
|
||||||
|
else:
|
||||||
|
path.moveTo(mid)
|
||||||
|
path.arcTo(r, 90, 90)
|
||||||
|
path.closeSubpath()
|
||||||
|
p.setBrush(col)
|
||||||
|
p.drawPath(path)
|
||||||
|
# White circle in centre
|
||||||
|
p.setBrush(QColor("#ffffff"))
|
||||||
|
p.drawEllipse(mid, r.width() * 0.15, r.height() * 0.15)
|
||||||
|
return _make_icon(paint, color)
|
||||||
@@ -24,7 +24,7 @@ class RadioPanelWindow(QMainWindow):
|
|||||||
|
|
||||||
self.engine = AudioEngine()
|
self.engine = AudioEngine()
|
||||||
|
|
||||||
self.setWindowTitle("Radio Panel")
|
self.setWindowTitle("Getting To It")
|
||||||
self.setMinimumSize(1280, 720)
|
self.setMinimumSize(1280, 720)
|
||||||
self.resize(1920, 1080)
|
self.resize(1920, 1080)
|
||||||
self._apply_global_style(THEMES[0])
|
self._apply_global_style(THEMES[0])
|
||||||
@@ -204,7 +204,7 @@ class RadioPanelWindow(QMainWindow):
|
|||||||
def main():
|
def main():
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
app.setApplicationName("Radio Panel")
|
app.setApplicationName("Radio Panel")
|
||||||
app.setOrganizationName("GTI")
|
app.setOrganizationName("Getting To It")
|
||||||
|
|
||||||
palette = QPalette()
|
palette = QPalette()
|
||||||
palette.setColor(QPalette.Window, QColor("#0d0d0d"))
|
palette.setColor(QPalette.Window, QColor("#0d0d0d"))
|
||||||
|
|||||||
+9
-1
@@ -6,11 +6,15 @@ from PySide6.QtWidgets import (
|
|||||||
QListWidget, QListWidgetItem, QAbstractItemView,
|
QListWidget, QListWidgetItem, QAbstractItemView,
|
||||||
QMenu, QSplitter
|
QMenu, QSplitter
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt, QTimer
|
from PySide6.QtCore import Qt, QTimer, QSize, QSize
|
||||||
from PySide6.QtGui import QFont, QColor, QAction
|
from PySide6.QtGui import QFont, QColor, QAction
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from icons import icon_save, icon_load
|
||||||
|
|
||||||
|
from icons import icon_save, icon_load
|
||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────
|
# ─────────────────────────────────────────
|
||||||
# PLAYLIST ITEM
|
# PLAYLIST ITEM
|
||||||
@@ -606,6 +610,8 @@ class PlaylistWidget(QWidget):
|
|||||||
|
|
||||||
self._save_btn = QPushButton("SAVE")
|
self._save_btn = QPushButton("SAVE")
|
||||||
self._save_btn.setFixedHeight(28)
|
self._save_btn.setFixedHeight(28)
|
||||||
|
self._save_btn.setIconSize(QSize(16, 16))
|
||||||
|
self._save_btn.setIcon(icon_save("#aaaaaa"))
|
||||||
self._save_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
self._save_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||||
self._save_btn.setStyleSheet("""
|
self._save_btn.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
@@ -621,6 +627,8 @@ class PlaylistWidget(QWidget):
|
|||||||
|
|
||||||
self._load_btn = QPushButton("LOAD")
|
self._load_btn = QPushButton("LOAD")
|
||||||
self._load_btn.setFixedHeight(28)
|
self._load_btn.setFixedHeight(28)
|
||||||
|
self._load_btn.setIconSize(QSize(16, 16))
|
||||||
|
self._load_btn.setIcon(icon_load("#aaaaaa"))
|
||||||
self._load_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
self._load_btn.setFont(QFont("Arial", 9, QFont.Bold))
|
||||||
self._load_btn.setStyleSheet("""
|
self._load_btn.setStyleSheet("""
|
||||||
QPushButton {
|
QPushButton {
|
||||||
|
|||||||
+9
-4
@@ -1,10 +1,14 @@
|
|||||||
# top_bar_widget.py
|
# top_bar_widget.py
|
||||||
|
|
||||||
from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QPushButton
|
from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QPushButton
|
||||||
from PySide6.QtCore import Qt, QTimer, Signal
|
from PySide6.QtCore import Qt, QTimer, Signal, QSize
|
||||||
from PySide6.QtGui import QFont
|
from PySide6.QtGui import QFont
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from icons import icon_theme
|
||||||
|
|
||||||
|
from icons import icon_theme
|
||||||
|
|
||||||
|
|
||||||
THEMES = [
|
THEMES = [
|
||||||
# Dark themes
|
# Dark themes
|
||||||
@@ -229,16 +233,17 @@ class TopBarWidget(QFrame):
|
|||||||
layout.setSpacing(12)
|
layout.setSpacing(12)
|
||||||
|
|
||||||
# Theme cycle button
|
# Theme cycle button
|
||||||
self.theme_btn = QPushButton("◈")
|
self.theme_btn = QPushButton()
|
||||||
self.theme_btn.setFixedSize(40, 40)
|
self.theme_btn.setFixedSize(40, 40)
|
||||||
self.theme_btn.setFont(QFont("Arial", 16, QFont.Bold))
|
self.theme_btn.setIconSize(QSize(22, 22))
|
||||||
|
self.theme_btn.setIcon(icon_theme())
|
||||||
self.theme_btn.setToolTip("Cycle colour theme")
|
self.theme_btn.setToolTip("Cycle colour theme")
|
||||||
self.theme_btn.clicked.connect(self._cycle_theme)
|
self.theme_btn.clicked.connect(self._cycle_theme)
|
||||||
self._style_theme_btn()
|
self._style_theme_btn()
|
||||||
layout.addWidget(self.theme_btn)
|
layout.addWidget(self.theme_btn)
|
||||||
|
|
||||||
# Station name
|
# Station name
|
||||||
self.station_label = QLabel("RADIO PANEL")
|
self.station_label = QLabel("GETTING TO IT")
|
||||||
self.station_label.setFont(QFont("Arial", 16, QFont.Bold))
|
self.station_label.setFont(QFont("Arial", 16, QFont.Bold))
|
||||||
self.station_label.setStyleSheet(
|
self.station_label.setStyleSheet(
|
||||||
"color: #444444; background: transparent; border: none;"
|
"color: #444444; background: transparent; border: none;"
|
||||||
|
|||||||
Reference in New Issue
Block a user