| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- """
- Audio Spectrogram Panel
- Panel for displaying audio spectrogram visualization.
- """
- from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QFrame, QSizePolicy
- from PyQt5.QtCore import Qt, pyqtSignal
- from PyQt5.QtGui import QFont, QPixmap, QCursor
- from ui.widgets.panel_header import PanelHeader
- class ClickableLabel(QLabel):
- """Label that emits a signal when clicked."""
- clicked = pyqtSignal()
-
- def __init__(self, parent=None):
- super().__init__(parent)
- self.setCursor(QCursor(Qt.PointingHandCursor))
-
- def mousePressEvent(self, event):
- """Emit clicked signal on mouse press."""
- self.clicked.emit()
- super().mousePressEvent(event)
- class AudioSpectrogramPanel(QWidget):
- """
- Panel for audio spectrogram display and settings.
-
- Signals:
- spectrogram_clicked: Emitted when spectrogram is clicked for enlarged view
- """
-
- spectrogram_clicked = pyqtSignal()
-
- def __init__(self, parent=None):
- super().__init__(parent)
- self.current_pixmap = None
- self.current_audio_path = None
- self.init_ui()
-
- def init_ui(self):
- """Initialize the panel UI."""
- # Set size policy to expand equally
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
-
- layout = QVBoxLayout(self)
- layout.setContentsMargins(0, 0, 0, 0)
- layout.setSpacing(0)
-
- # Main panel container with card styling
- self.setStyleSheet("""
- QWidget {
- background-color: white;
- border: 1px solid #ddd;
- }
- """)
-
- # Header
- header = QWidget()
- header.setFixedHeight(25)
- header.setStyleSheet("background-color: #16a085;")
- header_layout = QHBoxLayout(header)
- header_layout.setContentsMargins(10, 0, 10, 0)
- header_layout.setSpacing(0)
-
- title = QLabel("Audio Spectrogram")
- title.setStyleSheet("color: white; font-weight: bold; font-size: 16px;")
-
- status_indicator = QWidget()
- status_indicator.setFixedSize(10, 10)
- status_indicator.setStyleSheet("background-color: #27ae60; border-radius: 5px;")
-
- header_layout.addWidget(title)
- header_layout.addStretch()
- header_layout.addWidget(status_indicator)
-
- # Visualization area
- visualization = QWidget()
- visualization.setMinimumSize(250, 250)
- # visualization.setMaximumSize(500, 500)
- visualization.setStyleSheet("""
- background-color: #2c3e50;
- border: 1px solid #34495e;
- border-top: none;
- """)
-
- visualization_layout = QVBoxLayout(visualization)
- visualization_layout.setContentsMargins(0, 0, 0, 0)
- visualization_layout.setSpacing(0)
-
- # Frequency range label
- range_label = QLabel("0-8kHz Range")
- range_label.setStyleSheet("color: #bdc3c7; font-size: 12px;")
- range_label.setAlignment(Qt.AlignCenter)
- # range_label.setFixedHeight(15)
- visualization_layout.addWidget(range_label)
-
- # Spectrogram display (clickable)
- self.spectrogram_label = ClickableLabel()
- self.spectrogram_label.setAlignment(Qt.AlignCenter)
- self.spectrogram_label.setMinimumHeight(200)
- self.spectrogram_label.setScaledContents(False)
- self.spectrogram_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
- self.spectrogram_label.setStyleSheet("""
- QLabel {
- background-color: #2c3e50;
- border: none;
- color: #bdc3c7;
- }
- QLabel:hover {
- background-color: #34495e;
- }
- """)
- self.spectrogram_label.setText("No audio loaded\n\nClick to view details")
- self.spectrogram_label.setToolTip("Click to enlarge and view audio details")
- self.spectrogram_label.clicked.connect(self._on_spectrogram_clicked)
- visualization_layout.addWidget(self.spectrogram_label, 1)
-
- layout.addWidget(header)
- layout.addWidget(visualization, 1)
-
- def update_spectrogram(self, pixmap: QPixmap, sample_rate: float = 44100,
- duration: float = 0, audio_path: str = None):
- """
- Update the spectrogram display.
-
- Args:
- pixmap: Spectrogram image as QPixmap
- sample_rate: Audio sample rate in Hz
- duration: Audio duration in seconds
- audio_path: Path to the audio file for playback
- """
- # Store original pixmap and audio path for enlargement
- self.current_pixmap = pixmap
- self.current_audio_path = audio_path
-
- # Force widget to update geometry first
- self.spectrogram_label.updateGeometry()
-
- # Get actual dimensions, with better fallbacks
- label_width = self.spectrogram_label.width()
- label_height = self.spectrogram_label.height()
-
- # Use parent widget size if label size not yet determined
- if label_width < 100:
- parent_width = self.width() if self.width() > 100 else 380
- label_width = parent_width - 20
-
- if label_height < 100:
- label_height = 220
-
- # Scale to fit width while preserving aspect ratio
- scaled_pixmap = pixmap.scaledToWidth(
- int(label_width),
- Qt.SmoothTransformation
- )
- self.spectrogram_label.setPixmap(scaled_pixmap)
-
- def clear_spectrogram(self):
- """Clear the spectrogram display."""
- self.current_pixmap = None
- self.current_audio_path = None
- self.spectrogram_label.clear()
- self.spectrogram_label.setText("No audio loaded\n\nClick to view details")
-
- def _on_spectrogram_clicked(self):
- """Handle spectrogram click to show enlarged view with waveform and playback."""
- if self.current_pixmap is not None:
- from ui.dialogs.spectrogram_preview_dialog import SpectrogramPreviewDialog
- dialog = SpectrogramPreviewDialog(
- self.current_pixmap,
- self.current_audio_path,
- self
- )
- dialog.exec_()
|