86 lines
4.0 KiB
Python
86 lines
4.0 KiB
Python
from PyQt5.QtCore import Qt, QTimer, QDir, QSize, QDateTime, QRect, QThread, pyqtSignal, QMutex, QObject, QEvent
|
|
from PyQt5.QtGui import (QImage, QPixmap, QIcon, QColor, QKeySequence, QPainter,
|
|
QPen, QBrush)
|
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout,
|
|
QWidget, QLabel, QPushButton, QComboBox, QSpinBox,
|
|
QFileDialog, QMessageBox, QMenu, QAction, QActionGroup, QGridLayout, QGroupBox,
|
|
QDockWidget, QScrollArea, QToolButton, QDialog,
|
|
QShortcut, QListWidget, QFormLayout, QLineEdit,
|
|
QCheckBox, QTabWidget, QListWidgetItem, QSplitter,
|
|
QProgressBar, QSizePolicy)
|
|
|
|
class CollapsibleDock(QDockWidget):
|
|
"""Custom dock widget with collapse/expand functionality"""
|
|
|
|
def __init__(self, title, parent=None):
|
|
super().__init__(title, parent)
|
|
self.setFeatures(QDockWidget.DockWidgetClosable |
|
|
QDockWidget.DockWidgetMovable |
|
|
QDockWidget.DockWidgetFloatable)
|
|
# Allow docking only on sides to avoid central area clipping
|
|
self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
|
|
# Prefer keeping a minimum width but allow vertical expansion
|
|
self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
# Ensure the dock paints its own background (prevents visual bleed/clip)
|
|
self.setAttribute(Qt.WA_StyledBackground, True)
|
|
|
|
# Create a widget for the title bar that contains both toggle button and close button
|
|
title_widget = QWidget()
|
|
title_layout = QHBoxLayout(title_widget)
|
|
title_layout.setContentsMargins(0, 0, 0, 0)
|
|
title_layout.setSpacing(0)
|
|
# Ensure title bar doesn't force tiny width
|
|
title_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
self.toggle_button = QToolButton()
|
|
self.toggle_button.setIcon(QIcon.fromTheme("arrow-left"))
|
|
self.toggle_button.setIconSize(QSize(16, 16))
|
|
self.toggle_button.setStyleSheet("border: none;")
|
|
self.toggle_button.clicked.connect(self.toggle_collapse)
|
|
|
|
title_layout.addWidget(self.toggle_button)
|
|
title_layout.addStretch()
|
|
|
|
self.setTitleBarWidget(title_widget)
|
|
self.collapsed = False
|
|
self.original_size = None
|
|
self.original_minimum_width = None
|
|
self.original_maximum_width = None
|
|
|
|
def toggle_collapse(self):
|
|
"""Toggle between collapsed and expanded states"""
|
|
if self.collapsed:
|
|
self.expand()
|
|
else:
|
|
self.collapse()
|
|
|
|
def collapse(self):
|
|
"""Collapse the dock widget (fully hide)."""
|
|
if not self.collapsed:
|
|
self.original_size = self.size()
|
|
self.original_minimum_width = self.minimumWidth()
|
|
self.original_maximum_width = self.maximumWidth()
|
|
# Fully hide the dock to avoid any clipping/overlap with camera panes
|
|
self.setVisible(False)
|
|
self.toggle_button.setIcon(QIcon.fromTheme("arrow-right"))
|
|
self.collapsed = True
|
|
|
|
def expand(self):
|
|
"""Expand (show) the dock widget"""
|
|
if self.collapsed:
|
|
# Restore previous constraints, falling back to sensible defaults
|
|
minw = self.original_minimum_width if self.original_minimum_width is not None else 250
|
|
self.setMinimumWidth(minw)
|
|
self.setMaximumWidth(self.original_maximum_width if self.original_maximum_width is not None else 16777215)
|
|
# Show and restore size
|
|
self.setVisible(True)
|
|
if self.original_size:
|
|
self.resize(self.original_size)
|
|
else:
|
|
self.resize(max(minw, 250), self.height())
|
|
# Make sure the dock is on top of central widgets
|
|
self.raise_()
|
|
self.toggle_button.setIcon(QIcon.fromTheme("arrow-left"))
|
|
self.collapsed = False
|
|
|