| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- """
- Image Preview Dialog
- Dialog for displaying enlarged view of images/spectrograms with zoom functionality.
- """
- from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QPushButton, QHBoxLayout, QScrollArea
- from PyQt5.QtCore import Qt
- from PyQt5.QtGui import QPixmap, QFont
- class ImagePreviewDialog(QDialog):
- """
- Dialog for displaying enlarged image previews with zoom functionality.
-
- Features:
- - Enlarged view of spectrograms/images
- - Zoom in/out with buttons or keyboard (+/- or scroll wheel)
- - Click anywhere or press ESC to close
- - Clean, professional appearance
- """
-
- def __init__(self, pixmap: QPixmap, title: str = "Preview", parent=None):
- """
- Initialize the preview dialog.
-
- Args:
- pixmap: QPixmap to display
- title: Dialog title
- parent: Parent widget
- """
- super().__init__(parent)
- self.original_pixmap = pixmap
- self.setWindowTitle(title)
- self.setModal(True)
- self.zoom_level = 1.0
- self.min_zoom = 0.25
- self.max_zoom = 4.0
- self.init_ui()
-
- def init_ui(self):
- """Initialize the dialog UI."""
- layout = QVBoxLayout(self)
- layout.setContentsMargins(0, 0, 0, 0)
- layout.setSpacing(0)
-
- # Header
- header = QLabel(self.windowTitle())
- header.setAlignment(Qt.AlignCenter)
- header.setStyleSheet("""
- QLabel {
- background-color: #2c3e50;
- color: white;
- font-weight: bold;
- font-size: 12px;
- padding: 10px;
- }
- """)
- layout.addWidget(header)
-
- # Scroll area for image with zoom
- scroll_area = QScrollArea()
- scroll_area.setStyleSheet("""
- QScrollArea {
- background-color: #2c3e50;
- border: none;
- }
- """)
- scroll_area.setWidgetResizable(True)
-
- # Image display label
- self.image_label = QLabel()
- self.image_label.setAlignment(Qt.AlignCenter)
- self.image_label.setStyleSheet("""
- QLabel {
- background-color: #2c3e50;
- padding: 20px;
- }
- """)
-
- # Initial scaling to fit dialog (max 1200x800)
- initial_pixmap = self.original_pixmap.scaled(
- 1200, 800, Qt.KeepAspectRatio, Qt.SmoothTransformation
- )
- self.image_label.setPixmap(initial_pixmap)
- self.zoom_level = 1.0
- self.current_display_pixmap = initial_pixmap
-
- scroll_area.setWidget(self.image_label)
- layout.addWidget(scroll_area)
-
- # Control buttons and zoom info
- controls_layout = QHBoxLayout()
- controls_layout.setContentsMargins(10, 10, 10, 10)
- controls_layout.setSpacing(10)
-
- # Zoom out button
- zoom_out_button = QPushButton("🔍− Zoom Out")
- zoom_out_button.setFont(QFont("Arial", 10))
- zoom_out_button.setFixedHeight(35)
- zoom_out_button.setStyleSheet("""
- QPushButton {
- background-color: #34495e;
- color: white;
- border: none;
- font-weight: bold;
- border-radius: 4px;
- }
- QPushButton:hover {
- background-color: #2c3e50;
- }
- QPushButton:pressed {
- background-color: #1a252f;
- }
- """)
- zoom_out_button.clicked.connect(self.zoom_out)
- controls_layout.addWidget(zoom_out_button)
-
- # Zoom level label
- self.zoom_label = QLabel("100%")
- self.zoom_label.setAlignment(Qt.AlignCenter)
- self.zoom_label.setFont(QFont("Arial", 10, QFont.Bold))
- self.zoom_label.setStyleSheet("color: white; min-width: 60px;")
- controls_layout.addWidget(self.zoom_label)
-
- # Zoom in button
- zoom_in_button = QPushButton("Zoom In 🔍+")
- zoom_in_button.setFont(QFont("Arial", 10))
- zoom_in_button.setFixedHeight(35)
- zoom_in_button.setStyleSheet("""
- QPushButton {
- background-color: #34495e;
- color: white;
- border: none;
- font-weight: bold;
- border-radius: 4px;
- }
- QPushButton:hover {
- background-color: #2c3e50;
- }
- QPushButton:pressed {
- background-color: #1a252f;
- }
- """)
- zoom_in_button.clicked.connect(self.zoom_in)
- controls_layout.addWidget(zoom_in_button)
-
- # Reset zoom button
- reset_button = QPushButton("Reset (R)")
- reset_button.setFont(QFont("Arial", 10))
- reset_button.setFixedHeight(35)
- reset_button.setStyleSheet("""
- QPushButton {
- background-color: #7f8c8d;
- color: white;
- border: none;
- font-weight: bold;
- border-radius: 4px;
- }
- QPushButton:hover {
- background-color: #6c7a7d;
- }
- QPushButton:pressed {
- background-color: #5a6667;
- }
- """)
- reset_button.clicked.connect(self.reset_zoom)
- controls_layout.addWidget(reset_button)
-
- # Close button
- close_button = QPushButton("Close (ESC)")
- close_button.setFont(QFont("Arial", 10))
- close_button.setFixedHeight(35)
- close_button.setStyleSheet("""
- QPushButton {
- background-color: #e74c3c;
- color: white;
- border: none;
- font-weight: bold;
- border-radius: 4px;
- }
- QPushButton:hover {
- background-color: #c0392b;
- }
- QPushButton:pressed {
- background-color: #a93226;
- }
- """)
- close_button.clicked.connect(self.accept)
- controls_layout.addWidget(close_button)
-
- layout.addLayout(controls_layout)
-
- # Set dialog size
- self.resize(1280, 900)
-
- def zoom_in(self):
- """Increase zoom level."""
- if self.zoom_level < self.max_zoom:
- self.zoom_level *= 1.25
- if self.zoom_level > self.max_zoom:
- self.zoom_level = self.max_zoom
- self._update_display()
-
- def zoom_out(self):
- """Decrease zoom level."""
- if self.zoom_level > self.min_zoom:
- self.zoom_level /= 1.25
- if self.zoom_level < self.min_zoom:
- self.zoom_level = self.min_zoom
- self._update_display()
-
- def reset_zoom(self):
- """Reset to initial zoom level."""
- self.zoom_level = 1.0
- # Re-scale to fit dialog
- scaled_pixmap = self.original_pixmap.scaled(
- 1200, 800, Qt.KeepAspectRatio, Qt.SmoothTransformation
- )
- self.image_label.setPixmap(scaled_pixmap)
- self.current_display_pixmap = scaled_pixmap
- self._update_zoom_label()
-
- def _update_display(self):
- """Update the displayed image based on current zoom level."""
- # Calculate new size based on original pixmap and zoom level
- new_width = int(self.original_pixmap.width() * self.zoom_level)
- new_height = int(self.original_pixmap.height() * self.zoom_level)
-
- # Scale the image
- scaled_pixmap = self.original_pixmap.scaled(
- new_width, new_height, Qt.KeepAspectRatio, Qt.SmoothTransformation
- )
- self.image_label.setPixmap(scaled_pixmap)
- self.current_display_pixmap = scaled_pixmap
- self._update_zoom_label()
-
- def _update_zoom_label(self):
- """Update zoom percentage label."""
- zoom_percentage = int(self.zoom_level * 100)
- self.zoom_label.setText(f"{zoom_percentage}%")
-
- def mousePressEvent(self, event):
- """Close dialog on mouse click outside the scroll area."""
- # Only close if clicking on dialog background, not on scroll area
- if not self.image_label.geometry().contains(self.mapFromGlobal(event.globalPos())):
- self.accept()
-
- def wheelEvent(self, event):
- """Handle mouse wheel for zooming."""
- if event.angleDelta().y() > 0:
- self.zoom_in()
- else:
- self.zoom_out()
-
- def keyPressEvent(self, event):
- """Handle keyboard shortcuts for zooming."""
- if event.key() == Qt.Key_Escape:
- self.accept()
- elif event.key() == Qt.Key_Plus or event.key() == Qt.Key_Equal:
- self.zoom_in()
- elif event.key() == Qt.Key_Minus:
- self.zoom_out()
- elif event.key() == Qt.Key_R:
- self.reset_zoom()
- else:
- super().keyPressEvent(event)
|