Files
mucapy/mucapy/CollpsibleDock.py
2025-11-02 15:55:13 +01:00

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