| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- """
- Multispectral Analysis Panel
- Panel for displaying multispectral camera analysis (coming soon feature).
- """
- from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy
- from PyQt5.QtCore import Qt
- from PyQt5.QtGui import QFont, QPixmap, QImage, QCursor
- from ui.widgets.panel_header import PanelHeader
- from ui.widgets.coming_soon_overlay import ComingSoonOverlay
- from ui.dialogs.image_preview_dialog import ImagePreviewDialog
- class MultispectralPanel(QWidget):
- """
- Panel for multispectral camera analysis.
- Currently shows "COMING SOON" placeholder for future camera integration.
- """
-
- def __init__(self, parent=None):
- super().__init__(parent)
- 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: #8e44ad;")
- header_layout = QHBoxLayout(header)
- header_layout.setContentsMargins(10, 0, 10, 0)
- header_layout.setSpacing(0)
-
- title = QLabel("Multispectral Analysis")
- 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)
-
- # Content area
- self.content = QWidget()
- self.content.setMinimumSize(250, 250)
- # content.setMaximumSize(400, 400)
- self.content.setStyleSheet("""
- background-color: #8e44ad;
- border: 1px solid #9b59b6;
- border-top: none;
- """)
-
- content_layout = QVBoxLayout(self.content)
- content_layout.setAlignment(Qt.AlignCenter)
- content_layout.setSpacing(5)
-
- # Image display label (initially hidden)
- self.image_label = QLabel()
- self.image_label.setAlignment(Qt.AlignCenter)
- self.image_label.setScaledContents(False) # We'll scale manually for better control
- self.image_label.setMinimumSize(250, 250)
- self.image_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
- self.image_label.setStyleSheet("""
- QLabel {
- background-color: #2c3e50;
- border: 2px solid #34495e;
- }
- """)
- self.image_label.hide()
- self.image_label.setCursor(QCursor(Qt.PointingHandCursor))
- self.image_label.mousePressEvent = self._on_image_clicked
- self.current_pixmap = None # Store the original pixmap for dialog
- content_layout.addWidget(self.image_label, 1) # Give it stretch factor
-
- # Main text container (shown by default)
- self.text_container = QWidget()
- text_layout = QVBoxLayout(self.text_container)
- text_layout.setAlignment(Qt.AlignCenter)
- text_layout.setSpacing(2)
-
- # Spectral data text
- data_label = QLabel("8-Band Spectral Data")
- data_label.setFont(QFont("Arial", 12))
- data_label.setStyleSheet("color: #e8daef;")
- data_label.setAlignment(Qt.AlignCenter)
- text_layout.addWidget(data_label)
-
- # NIR enhancement text
- enhancement_label = QLabel("NIR Enhancement Active\n(Coming soon)")
- enhancement_label.setFont(QFont("Arial", 10))
- enhancement_label.setStyleSheet("color: #d5a6df;")
- enhancement_label.setAlignment(Qt.AlignCenter)
- text_layout.addWidget(enhancement_label)
-
- content_layout.addWidget(self.text_container)
-
- # Band selection area
- bands_frame = QWidget()
- bands_frame.setMaximumHeight(40)
- bands_layout = QHBoxLayout(bands_frame)
- bands_layout.setContentsMargins(10, 5, 10, 5)
-
- bands_label = QLabel("Active Bands:")
- bands_label.setStyleSheet("font-weight: bold; font-size: 12px;")
-
- bands_layout.addWidget(bands_label)
-
- bands_data = [
- ("680nm", "#e74c3c"),
- ("750nm", "#f39c12"),
- ("850nm", "#27ae60"),
- ("950nm", "#3498db")
- ]
-
- for band_name, color in bands_data:
- band_frame = QWidget()
- band_layout = QHBoxLayout(band_frame)
- band_layout.setContentsMargins(0, 0, 0, 0)
- band_layout.setSpacing(5)
-
- color_box = QWidget()
- color_box.setFixedSize(20, 12)
- color_box.setStyleSheet(f"background-color: {color};")
-
- name_label = QLabel(band_name)
- name_label.setStyleSheet("font-size: 12px;")
-
- band_layout.addWidget(color_box)
- band_layout.addWidget(name_label)
- bands_layout.addWidget(band_frame)
-
- bands_layout.addStretch()
-
- layout.addWidget(header)
- layout.addWidget(self.content, 1)
- layout.addWidget(bands_frame, 0)
-
- # Tooltip
- self.setToolTip("Multispectral camera analysis - Coming with hardware integration")
-
- def set_image(self, pixmap: QPixmap):
- """Display an image in the panel."""
- if pixmap and not pixmap.isNull():
- # Store the original pixmap for dialog display
- self.current_pixmap = pixmap
-
- # Show the image label
- self.image_label.show()
- self.text_container.hide()
-
- # Update the pixmap - use a timer to ensure layout is complete
- from PyQt5.QtCore import QTimer
- QTimer.singleShot(50, self._update_image_display)
-
- # Also try immediate update in case widget is already sized
- self._update_image_display()
-
- # Update tooltip to indicate clickability
- self.image_label.setToolTip("Click to view full-size image")
-
- def _update_image_display(self):
- """Update the image display with proper scaling."""
- if self.current_pixmap and not self.current_pixmap.isNull() and self.image_label.isVisible():
- # Get the current size of the label
- label_size = self.image_label.size()
- if label_size.width() <= 0 or label_size.height() <= 0:
- # If not yet sized, use minimum size
- label_size = self.image_label.minimumSize()
-
- # Calculate scaled size maintaining aspect ratio
- scaled_pixmap = self.current_pixmap.scaled(
- label_size.width(),
- label_size.height(),
- Qt.KeepAspectRatio,
- Qt.SmoothTransformation
- )
-
- self.image_label.setPixmap(scaled_pixmap)
-
- def resizeEvent(self, event):
- """Handle resize events to update image scaling."""
- super().resizeEvent(event)
- if self.current_pixmap and not self.current_pixmap.isNull():
- # Use QTimer to update after layout is complete
- from PyQt5.QtCore import QTimer
- QTimer.singleShot(10, self._update_image_display)
-
- def update_image(self, pixmap: QPixmap):
- """Update the displayed image (alias for set_image)."""
- self.set_image(pixmap)
-
- def clear(self):
- """Clear the image display and show default text."""
- self.image_label.clear()
- self.image_label.hide()
- self.text_container.show()
- self.current_pixmap = None
-
- def _on_image_clicked(self, event):
- """Handle click on image to show full-size dialog."""
- if self.current_pixmap and not self.current_pixmap.isNull():
- dialog = ImagePreviewDialog(
- self.current_pixmap,
- title="Multispectral Analysis - Grad-CAM Visualization",
- parent=self
- )
- dialog.exec_()
-
- def _create_band_indicator(self, wavelength: str, color: str) -> QWidget:
- """Create a band indicator widget."""
- widget = QWidget()
- layout = QHBoxLayout(widget)
- layout.setContentsMargins(0, 0, 0, 0)
- layout.setSpacing(3)
-
- # Color box
- color_box = QLabel()
- color_box.setFixedSize(20, 12)
- color_box.setStyleSheet(f"background-color: {color}; border: 1px solid #2c3e50;")
- layout.addWidget(color_box)
-
- # Wavelength label
- wavelength_label = QLabel(wavelength)
- wavelength_label.setFont(QFont("Arial", 8))
- wavelength_label.setStyleSheet("color: #2c3e50;")
- layout.addWidget(wavelength_label)
-
- return widget
|