Skip to content

Commit 853c0f4

Browse files
committed
status bar messages to indicate rendering and viewing progress
1 parent fbf8c8c commit 853c0f4

File tree

5 files changed

+71
-38
lines changed

5 files changed

+71
-38
lines changed

cq_editor/main_window.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import sys
22

3-
from PyQt5.QtWidgets import (QLabel, QMainWindow, QToolBar, QDockWidget, QAction)
3+
from typing import Optional
4+
from PyQt5.QtCore import pyqtSlot, Qt
5+
from PyQt5.QtGui import QPalette, QColor
6+
from PyQt5.QtWidgets import (QLabel, QMainWindow, QToolBar, QDockWidget, QAction, QApplication)
47

58
import cadquery as cq
69

@@ -55,6 +58,8 @@ def __init__(self,parent=None):
5558
self.restoreWindow()
5659
self.restoreComponentState()
5760

61+
self.on_idle()
62+
5863
def closeEvent(self,event):
5964

6065
self.saveWindow()
@@ -192,7 +197,7 @@ def prepare_toolbar(self):
192197
self.toolbar = QToolBar('Main toolbar',self,objectName='Main toolbar')
193198

194199
for c in self.components.values():
195-
add_actions(self.toolbar,c.toolbarActions())
200+
add_actions(self.toolbar, c.toolbarActions())
196201

197202
self.addToolBar(self.toolbar)
198203

@@ -203,18 +208,25 @@ def prepare_statusbar(self):
203208

204209
def prepare_actions(self):
205210

211+
self.components['debugger'].sigRenderStarted \
212+
.connect(self.on_render_start)
206213
self.components['debugger'].sigRendered\
207214
.connect(self.components['object_tree'].addObjects)
208215
self.components['debugger'].sigTraceback\
209216
.connect(self.components['traceback_viewer'].addTraceback)
217+
self.components['debugger'].sigRendered \
218+
.connect(lambda _: self.on_idle())
219+
self.components['debugger'].sigTraceback \
220+
.connect(lambda _: self.on_idle())
221+
210222
self.components['debugger'].sigLocals\
211223
.connect(self.components['variables_viewer'].update_frame)
212224
self.components['debugger'].sigLocals\
213225
.connect(self.components['console'].push_vars)
214226

215-
self.components['object_tree'].sigObjectsAdded[list]\
216-
.connect(self.components['viewer'].display_many)
217-
self.components['object_tree'].sigObjectsAdded[list,bool]\
227+
self.components['object_tree'].sigObjectsAdded[list, list]\
228+
.connect(lambda objects, names: self.components['viewer'].display_many(objects, None, names))
229+
self.components['object_tree'].sigObjectsAdded[list, bool, list]\
218230
.connect(self.components['viewer'].display_many)
219231
self.components['object_tree'].sigItemChanged.\
220232
connect(self.components['viewer'].update_item)
@@ -229,6 +241,8 @@ def prepare_actions(self):
229241

230242
self.components['viewer'].sigObjectSelected\
231243
.connect(self.components['object_tree'].handleGraphicalSelection)
244+
self.components['viewer'].sigDisplayProgress \
245+
.connect(self.on_display_progress)
232246

233247
self.components['traceback_viewer'].sigHighlightLine\
234248
.connect(self.components['editor'].go_to_line)
@@ -332,6 +346,25 @@ def handle_filename_change(self, fname):
332346
new_title = fname if fname else "*"
333347
self.setWindowTitle(f"{self.name}: {new_title}")
334348

335-
if __name__ == "__main__":
349+
def on_idle(self):
350+
self.set_status_message('Idle', '#000000')
336351

337-
pass
352+
@pyqtSlot()
353+
def on_render_start(self):
354+
self.set_status_message('Rendering...', '#ff0000')
355+
356+
@pyqtSlot(int, int, str)
357+
def on_display_progress(self, current: int, total: int, name: Optional[str]):
358+
if current == total:
359+
self.on_idle()
360+
else:
361+
message = f'Displaying Shape {current + 1} / {total}'
362+
if name:
363+
message += f' ({name})'
364+
self.set_status_message(message, '#0000ff')
365+
366+
def set_status_message(self, message: str, color: str):
367+
self.statusBar().showMessage(message)
368+
self.statusBar().setStyleSheet(f'color: {color}')
369+
# required because rendering is currently done on the main thread
370+
QApplication.processEvents()

cq_editor/widgets/debugger.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class Debugger(QObject,ComponentMixin):
110110
{'name': 'Change working dir to script dir','type': 'bool', 'value': True}])
111111

112112

113+
sigRenderStarted = pyqtSignal()
113114
sigRendered = pyqtSignal(dict)
114115
sigLocals = pyqtSignal(dict)
115116
sigTraceback = pyqtSignal(object,str)
@@ -221,6 +222,7 @@ def _cleanup_locals(self,module,injected_names):
221222

222223
@pyqtSlot(bool)
223224
def render(self):
225+
self.sigRenderStarted.emit()
224226

225227
if self.preferences['Reload CQ']:
226228
reload_cq()

cq_editor/widgets/object_tree.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class ObjectTree(QWidget,ComponentMixin):
9191
{'name': 'Clear all before each run', 'type': 'bool', 'value': True},
9292
{'name': 'STL precision','type': 'float', 'value': .1}])
9393

94-
sigObjectsAdded = pyqtSignal([list],[list,bool])
94+
sigObjectsAdded = pyqtSignal([list, list],[list, bool, list])
9595
sigObjectsRemoved = pyqtSignal(list)
9696
sigCQObjectSelected = pyqtSignal(object)
9797
sigAISObjectsSelected = pyqtSignal(list)
@@ -195,6 +195,7 @@ def addLines(self):
195195

196196
origin = (0,0,0)
197197
ais_list = []
198+
names = []
198199

199200
for name,color,direction in zip(('X','Y','Z'),
200201
('red','lawngreen','blue'),
@@ -208,8 +209,9 @@ def addLines(self):
208209
ais=line))
209210

210211
ais_list.append(line)
212+
names.append(name)
211213

212-
self.sigObjectsAdded.emit(ais_list)
214+
self.sigObjectsAdded.emit(ais_list, names)
213215

214216
def _current_properties(self):
215217

@@ -242,6 +244,7 @@ def addObjects(self,objects,clean=False,root=None):
242244
self.removeObjects()
243245

244246
ais_list = []
247+
names = []
245248

246249
#remove empty objects
247250
objects_f = {k:v for k,v in objects.items() if not is_obj_empty(v.shape)}
@@ -260,28 +263,29 @@ def addObjects(self,objects,clean=False,root=None):
260263

261264
if child.properties['Visible']:
262265
ais_list.append(ais)
263-
266+
names.append(name)
267+
264268
root.addChild(child)
265269

266270
if request_fit_view:
267-
self.sigObjectsAdded[list,bool].emit(ais_list,True)
271+
self.sigObjectsAdded[list, bool, list].emit(ais_list, True, names)
268272
else:
269-
self.sigObjectsAdded[list].emit(ais_list)
273+
self.sigObjectsAdded[list, list].emit(ais_list, names)
270274

271275
@pyqtSlot(object,str,object)
272276
def addObject(self,obj,name='',options={}):
273277

274278
root = self.CQ
275279

276-
ais,shape_display = make_AIS(obj, options)
280+
ais, shape_display = make_AIS(obj, options)
277281

278282
root.addChild(ObjectTreeItem(name,
279283
shape=obj,
280284
shape_display=shape_display,
281285
ais=ais,
282286
sig=self.sigObjectPropertiesChanged))
283287

284-
self.sigObjectsAdded.emit([ais])
288+
self.sigObjectsAdded.emit([ais], name)
285289

286290
@pyqtSlot(list)
287291
@pyqtSlot()
@@ -305,7 +309,7 @@ def stashObjects(self,action : bool):
305309
self.removeObjects()
306310
self.CQ.addChildren(self._stash)
307311
ais_list = [el.ais for el in self._stash]
308-
self.sigObjectsAdded.emit(ais_list)
312+
self.sigObjectsAdded.emit(ais_list, [''] * len(ais_list))
309313

310314
@pyqtSlot()
311315
def removeSelected(self):

cq_editor/widgets/traceback_viewer.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ def __init__(self,parent):
3535

3636
self.tree = TracebackTree(self)
3737
self.current_exception = QLabel(self)
38-
self.current_exception.setStyleSheet(\
39-
"QLabel {color : red; }");
38+
self.current_exception.setStyleSheet("QLabel {color : red; }");
4039

4140
layout(self,
4241
(self.current_exception,

cq_editor/widgets/viewer.py

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3+
from typing import List, Optional
34
from PyQt5.QtWidgets import (QWidget, QPushButton, QDialog, QTreeWidget,
45
QTreeWidgetItem, QVBoxLayout, QFileDialog,
56
QHBoxLayout, QFrame, QLabel, QApplication,
@@ -45,6 +46,7 @@ class OCCViewer(QWidget,ComponentMixin):
4546
IMAGE_EXTENSIONS = 'png'
4647

4748
sigObjectSelected = pyqtSignal(list)
49+
sigDisplayProgress = pyqtSignal(int, int, str)
4850

4951
def __init__(self,parent=None):
5052

@@ -140,31 +142,23 @@ def clear(self):
140142
context.PurgeDisplay()
141143
context.RemoveAll(True)
142144

143-
def _display(self,shape):
144-
145-
ais = make_AIS(shape)
146-
self.canvas.context.Display(shape,True)
147-
148-
self.displayed_shapes.append(shape)
149-
self.displayed_ais.append(ais)
150-
151-
#self.canvas._display.Repaint()
152-
153145
@pyqtSlot(object)
154-
def display(self,ais):
155-
156-
context = self._get_context()
157-
context.Display(ais,True)
158-
159-
if self.preferences['Fit automatically']: self.fit()
146+
def display(self, ais):
147+
self.display_many([ais])
160148

161149
@pyqtSlot(list)
162-
@pyqtSlot(list,bool)
163-
def display_many(self,ais_list,fit=None):
150+
@pyqtSlot(list, bool, list)
151+
def display_many(self, ais_list, fit: Optional[bool] = None, names: Optional[List] = None):
152+
if names is None:
153+
names = [None] * len(ais_list)
154+
assert len(ais_list) == len(names)
164155

165156
context = self._get_context()
166-
for ais in ais_list:
167-
context.Display(ais,True)
157+
num_objects = len(ais_list)
158+
for i, (ais, name) in enumerate(zip(ais_list, names)):
159+
self.sigDisplayProgress.emit(i, num_objects, name)
160+
context.Display(ais, True)
161+
self.sigDisplayProgress.emit(num_objects, num_objects, None)
168162

169163
if self.preferences['Fit automatically'] and fit is None:
170164
self.fit()
@@ -184,7 +178,8 @@ def update_item(self,item,col):
184178
def remove_items(self,ais_items):
185179

186180
ctx = self._get_context()
187-
for ais in ais_items: ctx.Erase(ais,True)
181+
for ais in ais_items:
182+
ctx.Erase(ais,True)
188183

189184
@pyqtSlot()
190185
def redraw(self):

0 commit comments

Comments
 (0)