git.lucas.co / hou-control
git clone https://git.lucas.co/hou-control.git

python3.11libs/hc/hcstatusbar.py (5.4K)

  1 import hou
  2 from PySide6.QtCore import QEvent, QObject, Qt, QTimer
  3 from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QPushButton, QWidget
  4 
  5 
  6 HCSTATUSBAR_HEIGHT = 48
  7 HCSTATUSBAR_WIDTH = 500
  8 HCSTATUSBAR_MARGIN = 4
  9 HCSTATUSBAR_RIGHT_MARGIN = 360
 10 HCSTATUSBAR_STYLE = """
 11     QFrame#hc_status_overlay {
 12         background: #2a2a2a;
 13         border: 1px solid #444;
 14     }
 15     QFrame#hc_status_overlay QLabel {
 16         color: #ccc;
 17         background: transparent;
 18         padding: 0 6px;
 19     }
 20     QFrame#hc_status_overlay QPushButton {
 21         color: #eee;
 22         background: #3a3a3a;
 23         border: 1px solid #555;
 24         padding: 0 10px;
 25     }
 26     QFrame#hc_status_overlay QPushButton:hover {
 27         background: #4a4a4a;
 28     }
 29 """
 30 
 31 
 32 class _ResizeFilter(QObject):
 33     def __init__(self, manager):
 34         super().__init__(manager.overlay)
 35         self.manager = manager
 36 
 37     def eventFilter(self, obj, event):
 38         if event.type() == QEvent.Resize:
 39             self.manager._pin()
 40         return False
 41 
 42 
 43 class HCStatusBar:
 44     OVERLAY_NAME = "hc_status_overlay"
 45     TAB_TYPE_LABEL = "hc_status_tab_type"
 46     AUTOSAVE_LABEL = "hc_status_autosave"
 47 
 48     def __init__(self):
 49         self.main = hou.qt.mainWindow()
 50         self.overlay = self._findOverlay()
 51 
 52     def _findOverlay(self):
 53         return self.main.findChild(QFrame, self.OVERLAY_NAME)
 54 
 55     def _ensureOverlay(self):
 56         if self.overlay is not None and self.overlay.parent() is self.main:
 57             return self.overlay
 58         frame = QFrame(self.main)
 59         frame.setObjectName(self.OVERLAY_NAME)
 60         frame.setStyleSheet(HCSTATUSBAR_STYLE)
 61         layout = QHBoxLayout(frame)
 62         layout.setContentsMargins(2, 0, 2, 0)
 63         layout.setSpacing(4)
 64         layout.addStretch()
 65         frame.setLayout(layout)
 66         filt = _ResizeFilter(self)
 67         self.main.installEventFilter(filt)
 68         frame._hc_filter = filt  # keep reference alive
 69         self.overlay = frame
 70         self._pin()
 71         frame.show()
 72         frame.raise_()
 73         self._installLabels()
 74         return frame
 75 
 76     def _installLabels(self):
 77         frame = self.overlay
 78         layout = frame.layout()
 79 
 80         tab_lbl = QLabel("—", frame)
 81         tab_lbl.setObjectName(self.TAB_TYPE_LABEL)
 82         layout.insertWidget(0, tab_lbl)
 83 
 84         autosave_lbl = QLabel("—", frame)
 85         autosave_lbl.setObjectName(self.AUTOSAVE_LABEL)
 86         layout.insertWidget(1, autosave_lbl)
 87 
 88         timer = QTimer(frame)
 89         timer.timeout.connect(self._refreshTabType)
 90         timer.start(250)
 91         frame._hc_tab_type_timer = timer
 92 
 93         self._refreshTabType()
 94         self.updateAutosave()
 95 
 96     def _refreshTabType(self):
 97         if self.overlay is None:
 98             return
 99         lbl = self.overlay.findChild(QLabel, self.TAB_TYPE_LABEL)
100         if lbl is None:
101             return
102         from .hcsession import HCSession
103         tab = HCSession().currentTab()
104         if tab is None:
105             lbl.setText("—")
106             return
107         lbl.setText(tab.hou_tab.type().name())
108 
109     def updateAutosave(self):
110         if self.overlay is None:
111             return
112         lbl = self.overlay.findChild(QLabel, self.AUTOSAVE_LABEL)
113         if lbl is None:
114             return
115         autosave = hou.getPreference("autoSave")
116         lbl.setText("Autosave: On" if autosave == "1" else "Autosave: Off")
117 
118     def _pin(self):
119         if self.overlay is None:
120             return
121         x = self.main.width() - HCSTATUSBAR_WIDTH - HCSTATUSBAR_RIGHT_MARGIN
122         y = self.main.height() - HCSTATUSBAR_HEIGHT - HCSTATUSBAR_MARGIN
123         self.overlay.setGeometry(x, y, HCSTATUSBAR_WIDTH, HCSTATUSBAR_HEIGHT)
124         self.overlay.raise_()
125 
126 
127     """ Show / Hide """
128 
129 
130     def show(self):
131         self._ensureOverlay()
132 
133     def hide(self):
134         if self.overlay is not None:
135             self.overlay.hide()
136 
137     def isVisible(self):
138         return self.overlay is not None and self.overlay.isVisible()
139 
140 
141     """ Add """
142 
143 
144     def addButton(self, name, label, callback):
145         frame = self._ensureOverlay()
146         self.removeWidget(name)
147         btn = QPushButton(label, frame)
148         btn.setObjectName(name)
149         btn.clicked.connect(callback)
150         frame.layout().addWidget(btn)
151         frame.raise_()
152         return btn
153 
154     def addLabel(self, name, text):
155         frame = self._ensureOverlay()
156         self.removeWidget(name)
157         lbl = QLabel(text, frame)
158         lbl.setObjectName(name)
159         frame.layout().addWidget(lbl)
160         frame.raise_()
161         return lbl
162 
163     def addWidget(self, name, widget):
164         frame = self._ensureOverlay()
165         self.removeWidget(name)
166         widget.setObjectName(name)
167         widget.setParent(frame)
168         frame.layout().addWidget(widget)
169         frame.raise_()
170         return widget
171 
172 
173     """ Remove """
174 
175 
176     def removeWidget(self, name):
177         if self.overlay is None:
178             return
179         existing = self.overlay.findChild(QWidget, name)
180         if existing is not None:
181             self.overlay.layout().removeWidget(existing)
182             existing.setParent(None)
183             existing.deleteLater()
184 
185     def clear(self):
186         if self.overlay is None:
187             return
188         self.overlay.setParent(None)
189         self.overlay.deleteLater()
190         self.overlay = None
191 
192 
193     """ Query """
194 
195 
196     def exists(self):
197         return self._findOverlay() is not None
198 
199     def widget(self, name):
200         if self.overlay is None:
201             return None
202         return self.overlay.findChild(QWidget, name)