1#
2# Copyright 2018 Pixar
3#
4# Licensed under the Apache License, Version 2.0 (the "Apache License")
5# with the following modification; you may not use this file except in
6# compliance with the Apache License and the following modification to it:
7# Section 6. Trademarks. is deleted and replaced with:
8#
9# 6. Trademarks. This License does not grant permission to use the trade
10#    names, trademarks, service marks, or product names of the Licensor
11#    and its affiliates, except as required to comply with Section 4(c) of
12#    the License and to reproduce the content of the NOTICE file.
13#
14# You may obtain a copy of the Apache License at
15#
16#     http://www.apache.org/licenses/LICENSE-2.0
17#
18# Unless required by applicable law or agreed to in writing, software
19# distributed under the Apache License with the above modification is
20# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21# KIND, either express or implied. See the Apache License for the specific
22# language governing permissions and limitations under the Apache License.
23#
24
25from .qt import QtCore
26from pxr import UsdGeom, Sdf
27from pxr.UsdAppUtils.complexityArgs import RefinementComplexities
28
29from .common import (RenderModes, ColorCorrectionModes, PickModes,
30                     SelectionHighlightModes, CameraMaskModes,
31                     PrintWarning)
32
33from . import settings2
34from .settings2 import StateSource
35from pxr.UsdUtils.constantsGroup import ConstantsGroup
36from .freeCamera import FreeCamera
37from .common import ClearColors, HighlightColors
38
39
40# Map of clear color names to rgba color tuples in linear space.
41_CLEAR_COLORS_DICT = {
42    ClearColors.BLACK:       (0.0, 0.0, 0.0, 1.0),
43    ClearColors.DARK_GREY:   (0.07074, 0.07074, 0.07074, 1.0),
44    ClearColors.LIGHT_GREY:  (0.45626, 0.45626, 0.45626, 1.0),
45    ClearColors.WHITE:       (1.0, 1.0, 1.0, 1.0)}
46
47
48# Map of highlight color names to rgba color tuples in linear space.
49_HIGHLIGHT_COLORS_DICT = {
50    HighlightColors.WHITE:   (1.0, 1.0, 1.0, 0.5),
51    HighlightColors.YELLOW:  (1.0, 1.0, 0.0, 0.5),
52    HighlightColors.CYAN:    (0.0, 1.0, 1.0, 0.5)}
53
54
55# Default values for default material components.
56DEFAULT_AMBIENT = 0.2
57DEFAULT_SPECULAR = 0.1
58
59
60def visibleViewSetting(f):
61    def wrapper(self, *args, **kwargs):
62        f(self, *args, **kwargs)
63        # If f raises an exception, the signal is not emitted.
64        self.signalVisibleSettingChanged.emit()
65        self.signalSettingChanged.emit()
66    return wrapper
67
68
69def invisibleViewSetting(f):
70    def wrapper(self, *args, **kwargs):
71        f(self, *args, **kwargs)
72        # If f raises an exception, the signal is not emitted.
73        self.signalSettingChanged.emit()
74    return wrapper
75
76
77class ViewSettingsDataModel(QtCore.QObject, StateSource):
78    """Data model containing settings related to the rendered view of a USD
79    file.
80    """
81
82    # emitted when any view setting changes
83    signalSettingChanged = QtCore.Signal()
84
85    # emitted when any view setting which may affect the rendered image changes
86    signalVisibleSettingChanged = QtCore.Signal()
87
88    # emitted when autoClipping changes value, so that clients can initialize
89    # it efficiently.  This signal will be emitted *before*
90    # signalVisibleSettingChanged when autoClipping changes.
91    signalAutoComputeClippingPlanesChanged = QtCore.Signal()
92
93    # emitted when any aspect of the defaultMaterial changes
94    signalDefaultMaterialChanged = QtCore.Signal()
95
96    # emitted when any setting affecting the GUI style changes
97    signalStyleSettingsChanged = QtCore.Signal()
98
99    def __init__(self, rootDataModel, parent):
100        QtCore.QObject.__init__(self)
101        StateSource.__init__(self, parent, "model")
102
103        self._rootDataModel = rootDataModel
104
105        self._cameraMaskColor = tuple(self.stateProperty("cameraMaskColor", default=[0.1, 0.1, 0.1, 1.0]))
106        self._cameraReticlesColor = tuple(self.stateProperty("cameraReticlesColor", default=[0.0, 0.7, 1.0, 1.0]))
107        self._defaultMaterialAmbient = self.stateProperty("defaultMaterialAmbient", default=DEFAULT_AMBIENT)
108        self._defaultMaterialSpecular = self.stateProperty("defaultMaterialSpecular", default=DEFAULT_SPECULAR)
109        self._redrawOnScrub = self.stateProperty("redrawOnScrub", default=True)
110        self._renderMode = self.stateProperty("renderMode", default=RenderModes.SMOOTH_SHADED)
111        self._freeCameraFOV = self.stateProperty("freeCameraFOV", default=60.0)
112        self._colorCorrectionMode = self.stateProperty("colorCorrectionMode", default=ColorCorrectionModes.SRGB)
113        self._pickMode = self.stateProperty("pickMode", default=PickModes.PRIMS)
114
115        # We need to store the trinary selHighlightMode state here,
116        # because the stageView only deals in True/False (because it
117        # cannot know anything about playback state).
118        self._selHighlightMode = self.stateProperty("selectionHighlightMode", default=SelectionHighlightModes.ONLY_WHEN_PAUSED)
119
120        # We store the highlightColorName so that we can compare state during
121        # initialization without inverting the name->value logic
122        self._highlightColorName = self.stateProperty("highlightColor", default="Yellow")
123        self._ambientLightOnly = self.stateProperty("cameraLightEnabled", default=True)
124        self._domeLightEnabled = self.stateProperty("domeLightEnabled", default=False)
125        self._clearColorText = self.stateProperty("backgroundColor", default="Grey (Dark)")
126        self._autoComputeClippingPlanes = self.stateProperty("autoComputeClippingPlanes", default=False)
127        self._showBBoxPlayback = self.stateProperty("showBBoxesDuringPlayback", default=False)
128        self._showBBoxes = self.stateProperty("showBBoxes", default=True)
129        self._showAABBox = self.stateProperty("showAABBox", default=True)
130        self._showOBBox = self.stateProperty("showOBBox", default=True)
131        self._displayGuide = self.stateProperty("displayGuide", default=False)
132        self._displayProxy = self.stateProperty("displayProxy", default=True)
133        self._displayRender = self.stateProperty("displayRender", default=False)
134        self._displayPrimId = self.stateProperty("displayPrimId", default=False)
135        self._enableSceneMaterials = self.stateProperty("enableSceneMaterials", default=True)
136        self._enableSceneLights = self.stateProperty("enableSceneLights", default=True)
137        self._cullBackfaces = self.stateProperty("cullBackfaces", default=False)
138        self._showInactivePrims = self.stateProperty("showInactivePrims", default=True)
139
140        showAllMasterPrims = self.stateProperty("showAllMasterPrims", default=False)
141        self._showAllPrototypePrims = self.stateProperty("showAllPrototypePrims", default=False)
142        # XXX: For backwards compatibility, we use the "showAllMasterPrims"
143        # saved state to drive the new "showAllPrototypePrims" state. We
144        # can remove "showAllMasterPrims" in a later release.
145        self._showAllPrototypePrims = showAllMasterPrims
146
147        self._showUndefinedPrims = self.stateProperty("showUndefinedPrims", default=False)
148        self._showAbstractPrims = self.stateProperty("showAbstractPrims", default=False)
149        self._rolloverPrimInfo = self.stateProperty("rolloverPrimInfo", default=False)
150        self._displayCameraOracles = self.stateProperty("cameraOracles", default=False)
151        self._cameraMaskMode = self.stateProperty("cameraMaskMode", default=CameraMaskModes.NONE)
152        self._showMask_Outline = self.stateProperty("cameraMaskOutline", default=False)
153        self._showReticles_Inside = self.stateProperty("cameraReticlesInside", default=False)
154        self._showReticles_Outside = self.stateProperty("cameraReticlesOutside", default=False)
155        self._showHUD = self.stateProperty("showHUD", default=True)
156
157        self._showHUD_Info = self.stateProperty("showHUDInfo", default=False)
158        # XXX Until we can make the "Subtree Info" stats-gathering faster
159        # we do not want the setting to persist from session to session.
160        self._showHUD_Info = False
161
162        self._showHUD_Complexity = self.stateProperty("showHUDComplexity", default=True)
163        self._showHUD_Performance = self.stateProperty("showHUDPerformance", default=True)
164        self._showHUD_GPUstats = self.stateProperty("showHUDGPUStats", default=False)
165
166        self._complexity = RefinementComplexities.LOW
167        self._freeCamera = None
168        self._cameraPath = None
169        self._fontSize = self.stateProperty("fontSize", default=10)
170
171    def onSaveState(self, state):
172        state["cameraMaskColor"] = list(self._cameraMaskColor)
173        state["cameraReticlesColor"] = list(self._cameraReticlesColor)
174        state["defaultMaterialAmbient"] = self._defaultMaterialAmbient
175        state["defaultMaterialSpecular"] = self._defaultMaterialSpecular
176        state["redrawOnScrub"] = self._redrawOnScrub
177        state["renderMode"] = self._renderMode
178        state["freeCameraFOV"] = self._freeCameraFOV
179        state["colorCorrectionMode"] = self._colorCorrectionMode
180        state["pickMode"] = self._pickMode
181        state["selectionHighlightMode"] = self._selHighlightMode
182        state["highlightColor"] = self._highlightColorName
183        state["cameraLightEnabled"] = self._ambientLightOnly
184        state["domeLightEnabled"] = self._domeLightEnabled
185        state["backgroundColor"] = self._clearColorText
186        state["autoComputeClippingPlanes"] = self._autoComputeClippingPlanes
187        state["showBBoxesDuringPlayback"] = self._showBBoxPlayback
188        state["showBBoxes"] = self._showBBoxes
189        state["showAABBox"] = self._showAABBox
190        state["showOBBox"] = self._showOBBox
191        state["displayGuide"] = self._displayGuide
192        state["displayProxy"] = self._displayProxy
193        state["displayRender"] = self._displayRender
194        state["displayPrimId"] = self._displayPrimId
195        state["enableSceneMaterials"] = self._enableSceneMaterials
196        state["enableSceneLights"] = self._enableSceneLights
197        state["cullBackfaces"] = self._cullBackfaces
198        state["showInactivePrims"] = self._showInactivePrims
199        state["showAllPrototypePrims"] = self._showAllPrototypePrims
200        state["showAllMasterPrims"] = self._showAllPrototypePrims
201        state["showUndefinedPrims"] = self._showUndefinedPrims
202        state["showAbstractPrims"] = self._showAbstractPrims
203        state["rolloverPrimInfo"] = self._rolloverPrimInfo
204        state["cameraOracles"] = self._displayCameraOracles
205        state["cameraMaskMode"] = self._cameraMaskMode
206        state["cameraMaskOutline"] = self._showMask_Outline
207        state["cameraReticlesInside"] = self._showReticles_Inside
208        state["cameraReticlesOutside"] = self._showReticles_Outside
209        state["showHUD"] = self._showHUD
210        state["showHUDInfo"] = self._showHUD_Info
211        state["showHUDComplexity"] = self._showHUD_Complexity
212        state["showHUDPerformance"] = self._showHUD_Performance
213        state["showHUDGPUStats"] = self._showHUD_GPUstats
214        state["fontSize"] = self._fontSize
215
216    @property
217    def cameraMaskColor(self):
218        return self._cameraMaskColor
219
220    @cameraMaskColor.setter
221    @visibleViewSetting
222    def cameraMaskColor(self, color):
223        self._cameraMaskColor = color
224
225    @property
226    def cameraReticlesColor(self):
227        return self._cameraReticlesColor
228
229    @cameraReticlesColor.setter
230    @visibleViewSetting
231    def cameraReticlesColor(self, color):
232        self._cameraReticlesColor = color
233
234    @property
235    def defaultMaterialAmbient(self):
236        return self._defaultMaterialAmbient
237
238    @defaultMaterialAmbient.setter
239    @visibleViewSetting
240    def defaultMaterialAmbient(self, value):
241        if value != self._defaultMaterialAmbient:
242            self._defaultMaterialAmbient = value
243            self.signalDefaultMaterialChanged.emit()
244
245    @property
246    def defaultMaterialSpecular(self):
247        return self._defaultMaterialSpecular
248
249    @defaultMaterialSpecular.setter
250    @visibleViewSetting
251    def defaultMaterialSpecular(self, value):
252        if value != self._defaultMaterialSpecular:
253            self._defaultMaterialSpecular = value
254            self.signalDefaultMaterialChanged.emit()
255
256    @visibleViewSetting
257    def setDefaultMaterial(self, ambient, specular):
258        if (ambient != self._defaultMaterialAmbient
259                or specular != self._defaultMaterialSpecular):
260            self._defaultMaterialAmbient = ambient
261            self._defaultMaterialSpecular = specular
262            self.signalDefaultMaterialChanged.emit()
263
264    def resetDefaultMaterial(self):
265        self.setDefaultMaterial(DEFAULT_AMBIENT, DEFAULT_SPECULAR)
266
267    @property
268    def complexity(self):
269        return self._complexity
270
271    @complexity.setter
272    @visibleViewSetting
273    def complexity(self, value):
274        if value not in RefinementComplexities.ordered():
275            raise ValueError("Expected Complexity, got: '{}'.".format(value))
276        self._complexity = value
277
278    @property
279    def renderMode(self):
280        return self._renderMode
281
282    @renderMode.setter
283    @visibleViewSetting
284    def renderMode(self, value):
285        self._renderMode = value
286
287    @property
288    def freeCameraFOV(self):
289        return self._freeCameraFOV
290
291    @freeCameraFOV.setter
292    @visibleViewSetting
293    def freeCameraFOV(self, value):
294        if self._freeCamera:
295            # Setting the freeCamera's fov will trigger our own update
296            self._freeCamera.fov = value
297        else:
298            self._freeCameraFOV = value
299
300    @visibleViewSetting
301    def _updateFOV(self):
302        if self._freeCamera:
303            self._freeCameraFOV = self.freeCamera.fov
304
305    @property
306    def colorCorrectionMode(self):
307        return self._colorCorrectionMode
308
309    @colorCorrectionMode.setter
310    @visibleViewSetting
311    def colorCorrectionMode(self, value):
312        self._colorCorrectionMode = value
313
314    @property
315    def pickMode(self):
316        return self._pickMode
317
318    @pickMode.setter
319    @invisibleViewSetting
320    def pickMode(self, value):
321        self._pickMode = value
322
323    @property
324    def showAABBox(self):
325        return self._showAABBox
326
327    @showAABBox.setter
328    @visibleViewSetting
329    def showAABBox(self, value):
330        self._showAABBox = value
331
332    @property
333    def showOBBox(self):
334        return self._showOBBox
335
336    @showOBBox.setter
337    @visibleViewSetting
338    def showOBBox(self, value):
339        self._showOBBox = value
340
341    @property
342    def showBBoxes(self):
343        return self._showBBoxes
344
345    @showBBoxes.setter
346    @visibleViewSetting
347    def showBBoxes(self, value):
348        self._showBBoxes = value
349
350    @property
351    def autoComputeClippingPlanes(self):
352        return self._autoComputeClippingPlanes
353
354    @autoComputeClippingPlanes.setter
355    @visibleViewSetting
356    def autoComputeClippingPlanes(self, value):
357        self._autoComputeClippingPlanes = value
358        self.signalAutoComputeClippingPlanesChanged.emit()
359
360    @property
361    def showBBoxPlayback(self):
362        return self._showBBoxPlayback
363
364    @showBBoxPlayback.setter
365    @visibleViewSetting
366    def showBBoxPlayback(self, value):
367        self._showBBoxPlayback = value
368
369    @property
370    def displayGuide(self):
371        return self._displayGuide
372
373    @displayGuide.setter
374    @visibleViewSetting
375    def displayGuide(self, value):
376        self._displayGuide = value
377
378    @property
379    def displayProxy(self):
380        return self._displayProxy
381
382    @displayProxy.setter
383    @visibleViewSetting
384    def displayProxy(self, value):
385        self._displayProxy = value
386
387    @property
388    def displayRender(self):
389        return self._displayRender
390
391    @displayRender.setter
392    @visibleViewSetting
393    def displayRender(self, value):
394        self._displayRender = value
395
396    @property
397    def displayCameraOracles(self):
398        return self._displayCameraOracles
399
400    @displayCameraOracles.setter
401    @visibleViewSetting
402    def displayCameraOracles(self, value):
403        self._displayCameraOracles = value
404
405    @property
406    def displayPrimId(self):
407        return self._displayPrimId
408
409    @displayPrimId.setter
410    @visibleViewSetting
411    def displayPrimId(self, value):
412        self._displayPrimId = value
413
414    @property
415    def enableSceneMaterials(self):
416        return self._enableSceneMaterials
417
418    @enableSceneMaterials.setter
419    @visibleViewSetting
420    def enableSceneMaterials(self, value):
421        self._enableSceneMaterials = value
422
423    @property
424    def enableSceneLights(self):
425        return self._enableSceneLights
426
427    @enableSceneLights.setter
428    @visibleViewSetting
429    def enableSceneLights(self, value):
430        self._enableSceneLights = value
431
432    @property
433    def cullBackfaces(self):
434        return self._cullBackfaces
435
436    @cullBackfaces.setter
437    @visibleViewSetting
438    def cullBackfaces(self, value):
439        self._cullBackfaces = value
440
441    @property
442    def showInactivePrims(self):
443        return self._showInactivePrims
444
445    @showInactivePrims.setter
446    @invisibleViewSetting
447    def showInactivePrims(self, value):
448        self._showInactivePrims = value
449
450    @property
451    def showAllPrototypePrims(self):
452        return self._showAllPrototypePrims
453
454    @showAllPrototypePrims.setter
455    @invisibleViewSetting
456    def showAllPrototypePrims(self, value):
457        self._showAllPrototypePrims = value
458
459    @property
460    def showUndefinedPrims(self):
461        return self._showUndefinedPrims
462
463    @showUndefinedPrims.setter
464    @invisibleViewSetting
465    def showUndefinedPrims(self, value):
466        self._showUndefinedPrims = value
467
468    @property
469    def showAbstractPrims(self):
470        return self._showAbstractPrims
471
472    @showAbstractPrims.setter
473    @invisibleViewSetting
474    def showAbstractPrims(self, value):
475        self._showAbstractPrims = value
476
477    @property
478    def rolloverPrimInfo(self):
479        return self._rolloverPrimInfo
480
481    @rolloverPrimInfo.setter
482    @invisibleViewSetting
483    def rolloverPrimInfo(self, value):
484        self._rolloverPrimInfo = value
485
486    @property
487    def cameraMaskMode(self):
488        return self._cameraMaskMode
489
490    @cameraMaskMode.setter
491    @visibleViewSetting
492    def cameraMaskMode(self, value):
493        self._cameraMaskMode = value
494
495    @property
496    def showMask(self):
497        return self._cameraMaskMode in (CameraMaskModes.FULL, CameraMaskModes.PARTIAL)
498
499    @property
500    def showMask_Opaque(self):
501        return self._cameraMaskMode == CameraMaskModes.FULL
502
503    @property
504    def showMask_Outline(self):
505        return self._showMask_Outline
506
507    @showMask_Outline.setter
508    @visibleViewSetting
509    def showMask_Outline(self, value):
510        self._showMask_Outline = value
511
512    @property
513    def showReticles_Inside(self):
514        return self._showReticles_Inside
515
516    @showReticles_Inside.setter
517    @visibleViewSetting
518    def showReticles_Inside(self, value):
519        self._showReticles_Inside = value
520
521    @property
522    def showReticles_Outside(self):
523        return self._showReticles_Outside
524
525    @showReticles_Outside.setter
526    @visibleViewSetting
527    def showReticles_Outside(self, value):
528        self._showReticles_Outside = value
529
530    @property
531    def showHUD(self):
532        return self._showHUD
533
534    @showHUD.setter
535    @visibleViewSetting
536    def showHUD(self, value):
537        self._showHUD = value
538
539    @property
540    def showHUD_Info(self):
541        return self._showHUD_Info
542
543    @showHUD_Info.setter
544    @visibleViewSetting
545    def showHUD_Info(self, value):
546        self._showHUD_Info = value
547
548    @property
549    def showHUD_Complexity(self):
550        return self._showHUD_Complexity
551
552    @showHUD_Complexity.setter
553    @visibleViewSetting
554    def showHUD_Complexity(self, value):
555        self._showHUD_Complexity = value
556
557    @property
558    def showHUD_Performance(self):
559        return self._showHUD_Performance
560
561    @showHUD_Performance.setter
562    @visibleViewSetting
563    def showHUD_Performance(self, value):
564        self._showHUD_Performance = value
565
566    @property
567    def showHUD_GPUstats(self):
568        return self._showHUD_GPUstats
569
570    @showHUD_GPUstats.setter
571    @visibleViewSetting
572    def showHUD_GPUstats(self, value):
573        self._showHUD_GPUstats = value
574
575    @property
576    def ambientLightOnly(self):
577        return self._ambientLightOnly
578
579    @ambientLightOnly.setter
580    @visibleViewSetting
581    def ambientLightOnly(self, value):
582        self._ambientLightOnly = value
583
584    @property
585    def domeLightEnabled(self):
586        return self._domeLightEnabled
587
588    @domeLightEnabled.setter
589    @visibleViewSetting
590    def domeLightEnabled(self, value):
591        self._domeLightEnabled = value
592
593    @property
594    def clearColorText(self):
595        return self._clearColorText
596
597    @clearColorText.setter
598    @visibleViewSetting
599    def clearColorText(self, value):
600        if value not in ClearColors:
601            raise ValueError("Unknown clear color: '{}'".format(value))
602        self._clearColorText = value
603
604    @property
605    def clearColor(self):
606        return _CLEAR_COLORS_DICT[self._clearColorText]
607
608    @property
609    def highlightColorName(self):
610        return self._highlightColorName
611
612    @highlightColorName.setter
613    @visibleViewSetting
614    def highlightColorName(self, value):
615        if value not in HighlightColors:
616            raise ValueError("Unknown highlight color: '{}'".format(value))
617        self._highlightColorName = value
618
619    @property
620    def highlightColor(self):
621        return _HIGHLIGHT_COLORS_DICT[self._highlightColorName]
622
623    @property
624    def selHighlightMode(self):
625        return self._selHighlightMode
626
627    @selHighlightMode.setter
628    @visibleViewSetting
629    def selHighlightMode(self, value):
630        if value not in SelectionHighlightModes:
631            raise ValueError("Unknown highlight mode: '{}'".format(value))
632        self._selHighlightMode = value
633
634    @property
635    def redrawOnScrub(self):
636        return self._redrawOnScrub
637
638    @redrawOnScrub.setter
639    @visibleViewSetting
640    def redrawOnScrub(self, value):
641        self._redrawOnScrub = value
642
643    @property
644    def freeCamera(self):
645        return self._freeCamera
646
647    @freeCamera.setter
648    @visibleViewSetting
649    def freeCamera(self, value):
650        # ViewSettingsDataModel does not guarantee it will hold a valid
651        # FreeCamera, but if one is set, we will keep the dataModel's stateful
652        # FOV ('freeCameraFOV') in sync with the FreeCamera
653
654        if not isinstance(value, FreeCamera) and value != None:
655            raise TypeError("Free camera must be a FreeCamera object.")
656        if self._freeCamera:
657            self._freeCamera.signalFrustumChanged.disconnect(self._updateFOV)
658        self._freeCamera = value
659        if self._freeCamera:
660            self._freeCamera.signalFrustumChanged.connect(self._updateFOV)
661            self._freeCameraFOV = self._freeCamera.fov
662
663    @property
664    def cameraPath(self):
665        return self._cameraPath
666
667    @cameraPath.setter
668    @visibleViewSetting
669    def cameraPath(self, value):
670        if ((not isinstance(value, Sdf.Path) or not value.IsPrimPath())
671                and value is not None):
672            raise TypeError("Expected prim path, got: {}".format(value))
673        self._cameraPath = value
674
675    @property
676    def cameraPrim(self):
677        if self.cameraPath is not None and self._rootDataModel.stage is not None:
678            return self._rootDataModel.stage.GetPrimAtPath(self.cameraPath)
679        else:
680            return None
681
682    @cameraPrim.setter
683    def cameraPrim(self, value):
684        if value is not None:
685            if value.IsA(UsdGeom.Camera):
686                self.cameraPath = value.GetPrimPath()
687            else:
688                PrintWarning("Incorrect Prim Type",
689                    "Attempted to view the scene using the prim '%s', but "
690                    "the prim is not a UsdGeom.Camera." % (value.GetName()))
691        else:
692            self.cameraPath = None
693
694    @property
695    def fontSize(self):
696        return self._fontSize
697
698    @fontSize.setter
699    @visibleViewSetting
700    def fontSize(self, value):
701        if value != self._fontSize:
702            self._fontSize = value
703            self.signalStyleSettingsChanged.emit()
704
705