class MainWindow(QQuickWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.setClearBeforeRendering(False) self.beforeRendering.connect(self._render, type=Qt.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._previous_focus = None # type: Optional["QQuickItem"] self._app = QCoreApplication.instance() # Remove previously added input devices (if any). This can happen if the window was re-loaded. self._app.getController().removeInputDevice("qt_mouse") self._app.getController().removeInputDevice("qt_key") self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect( self._onSceneChanged) self._preferences = Application.getInstance().getPreferences() self._preferences.addPreference("general/window_width", 1280) self._preferences.addPreference("general/window_height", 720) self._preferences.addPreference("general/window_left", 50) self._preferences.addPreference("general/window_top", 50) self._preferences.addPreference("general/window_state", Qt.WindowNoState) # Restore window geometry self.setWidth(int(self._preferences.getValue("general/window_width"))) self.setHeight(int( self._preferences.getValue("general/window_height"))) self.setPosition( int(self._preferences.getValue("general/window_left")), int(self._preferences.getValue("general/window_top"))) # Make sure restored geometry is not outside the currently available screens screen_found = False for s in range(0, self._app.desktop().screenCount()): if self.geometry().intersects( self._app.desktop().availableGeometry(s)): screen_found = True break if not screen_found: self.setPosition(50, 50) self.setWindowState( int(self._preferences.getValue("general/window_state"))) self._mouse_x = 0 self._mouse_y = 0 self._mouse_pressed = False self._viewport_rect = QRectF(0, 0, 1.0, 1.0) self.closing.connect(self.preClosing) Application.getInstance().setMainWindow(self) self._fullscreen = False self._allow_resize = True # This event is triggered before hideEvent(self, event) event and might prevent window closing if # does not pass the check, for example if USB printer is printing # The implementation is in Cura.qml preClosing = pyqtSignal("QQuickCloseEvent*", arguments=["close"]) def setAllowResize(self, allow_resize: bool): if self._allow_resize != allow_resize: if not allow_resize: self.setMaximumHeight(self.height()) self.setMinimumHeight(self.height()) self.setMaximumWidth(self.width()) self.setMinimumWidth(self.width()) else: self.setMaximumHeight(16777215) self.setMinimumHeight(0) self.setMaximumWidth(16777215) self.setMinimumWidth(0) self._allow_resize = allow_resize @pyqtSlot() def toggleFullscreen(self): if self._fullscreen: self.setVisibility( QQuickWindow.Windowed) # Switch back to windowed else: self.setVisibility(QQuickWindow.FullScreen) # Go to fullscreen self._fullscreen = not self._fullscreen def getBackgroundColor(self): return self._background_color def setBackgroundColor(self, color): self._background_color = color self._app.getRenderer().setBackgroundColor(color) backgroundColor = pyqtProperty(QColor, fget=getBackgroundColor, fset=setBackgroundColor) mousePositionChanged = pyqtSignal() @pyqtProperty(int, notify=mousePositionChanged) def mouseX(self): return self._mouse_x @pyqtProperty(int, notify=mousePositionChanged) def mouseY(self): return self._mouse_y def setViewportRect(self, rect): if rect != self._viewport_rect: self._viewport_rect = rect self._updateViewportGeometry( self.width() * self.devicePixelRatio(), self.height() * self.devicePixelRatio()) self.viewportRectChanged.emit() viewportRectChanged = pyqtSignal() @pyqtProperty(QRectF, fset=setViewportRect, notify=viewportRectChanged) def viewportRect(self): return self._viewport_rect # Warning! Never reimplemented this as a QExposeEvent can cause a deadlock with QSGThreadedRender due to both trying # to claim the Python GIL. # def event(self, event): def mousePressEvent(self, event): super().mousePressEvent(event) if event.isAccepted(): return if self.activeFocusItem( ) is not None and self.activeFocusItem() != self._previous_focus: self.activeFocusItem().setFocus(False) self._previous_focus = self.activeFocusItem() self._mouse_device.handleEvent(event) self._mouse_pressed = True def mouseMoveEvent(self, event): self._mouse_x = event.x() self._mouse_y = event.y() if self._mouse_pressed: self.mousePositionChanged.emit() super().mouseMoveEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) self._mouse_pressed = False def keyPressEvent(self, event): super().keyPressEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def wheelEvent(self, event): super().wheelEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def moveEvent(self, event): QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection) def resizeEvent(self, event): super().resizeEvent(event) win_w = event.size().width() * self.devicePixelRatio() win_h = event.size().height() * self.devicePixelRatio() self._updateViewportGeometry(win_w, win_h) QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection) def hideEvent(self, event): if Application.getInstance().getMainWindow() == self: Application.getInstance().windowClosed() renderCompleted = Signal(type=Signal.Queued) def _render(self): renderer = self._app.getRenderer() view = self._app.getController().getActiveView() renderer.beginRendering() view.beginRendering() renderer.render() view.endRendering() renderer.endRendering() self.renderCompleted.emit() def _onSceneChanged(self, object): self.update() @pyqtSlot() def _onWindowGeometryChanged(self): if self.windowState() == Qt.WindowNoState: self._preferences.setValue("general/window_width", self.width()) self._preferences.setValue("general/window_height", self.height()) self._preferences.setValue("general/window_left", self.x()) self._preferences.setValue("general/window_top", self.y()) self._preferences.setValue("general/window_state", Qt.WindowNoState) elif self.windowState() == Qt.WindowMaximized: self._preferences.setValue("general/window_state", Qt.WindowMaximized) def _updateViewportGeometry(self, width: int, height: int): view_width = width * self._viewport_rect.width() view_height = height * self._viewport_rect.height() for camera in self._app.getController().getScene().getAllCameras(): camera.setWindowSize(width, height) if camera.getAutoAdjustViewPort(): camera.setViewportSize(view_width, view_height) projection_matrix = Matrix() if camera.isPerspective(): if view_width is not 0: projection_matrix.setPerspective( 30, view_width / view_height, 1, 500) else: projection_matrix.setOrtho(-view_width / 2, view_width / 2, -view_height / 2, view_height / 2, -500, 500) camera.setProjectionMatrix(projection_matrix) self._app.getRenderer().setViewportSize(view_width, view_height) self._app.getRenderer().setWindowSize(width, height)
class MainWindow(QQuickWindow): def __init__(self, parent = None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.setClearBeforeRendering(False) self.beforeRendering.connect(self._render, type=Qt.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._app = QCoreApplication.instance() self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect(self._onSceneChanged) self._preferences = Preferences.getInstance() self._preferences.addPreference("general/window_width", 1280) self._preferences.addPreference("general/window_height", 720) self.setWidth(int(self._preferences.getValue("general/window_width"))) self.setHeight(int(self._preferences.getValue("general/window_height"))) self._mouse_x = 0 self._mouse_y = 0 def getBackgroundColor(self): return self._background_color def setBackgroundColor(self, color): self._background_color = color self._app.getRenderer().setBackgroundColor(color) backgroundColor = pyqtProperty(QColor, fget=getBackgroundColor, fset=setBackgroundColor) mousePositionChanged = pyqtSignal() @pyqtProperty(int, notify = mousePositionChanged) def mouseX(self): return self._mouse_x @pyqtProperty(int, notify = mousePositionChanged) def mouseY(self): return self._mouse_y # Warning! Never reimplemented this as a QExposeEvent can cause a deadlock with QSGThreadedRender due to both trying # to claim the Python GIL. # def event(self, event): def mousePressEvent(self, event): super().mousePressEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseMoveEvent(self, event): self._mouse_x = event.x() self._mouse_y = event.y() self.mousePositionChanged.emit() super().mouseMoveEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def keyPressEvent(self, event): super().keyPressEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def wheelEvent(self, event): super().wheelEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def resizeEvent(self, event): super().resizeEvent(event) w = event.size().width() * self.devicePixelRatio() h = event.size().height() * self.devicePixelRatio() for camera in self._app.getController().getScene().getAllCameras(): camera.setViewportSize(w, h) proj = Matrix() if camera.isPerspective(): proj.setPerspective(30, w/h, 1, 500) else: proj.setOrtho(-w / 2, w / 2, -h / 2, h / 2, -500, 500) camera.setProjectionMatrix(proj) self._preferences.setValue("general/window_width", event.size().width()) self._preferences.setValue("general/window_height", event.size().height()) self._app.getRenderer().setViewportSize(w, h) def hideEvent(self, event): Application.getInstance().windowClosed() def _render(self): renderer = self._app.getRenderer() view = self._app.getController().getActiveView() renderer.beginRendering() view.beginRendering() renderer.renderQueuedNodes() view.endRendering() renderer.endRendering() def _onSceneChanged(self, object): self.update()
class MainWindow(QQuickWindow): def __init__(self, parent = None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.setClearBeforeRendering(False) self.beforeRendering.connect(self._render, type=Qt.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._app = QCoreApplication.instance() self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect(self._onSceneChanged) self._preferences = Preferences.getInstance() self._preferences.addPreference("general/window_width", 1280) self._preferences.addPreference("general/window_height", 720) self._preferences.addPreference("general/window_left", 50) self._preferences.addPreference("general/window_top", 50) self._preferences.addPreference("general/window_state", Qt.WindowNoState) # Restore window geometry self.setWidth(int(self._preferences.getValue("general/window_width"))) self.setHeight(int(self._preferences.getValue("general/window_height"))) self.setPosition(int(self._preferences.getValue("general/window_left")), int(self._preferences.getValue("general/window_top"))) # Make sure restored geometry is not outside the currently available screens if not self.geometry().intersects(self.screen().availableGeometry()): self.setPosition(50,50) self.setWindowState(int(self._preferences.getValue("general/window_state"))) self._mouse_x = 0 self._mouse_y = 0 self._viewport_rect = QRectF(0, 0, 1.0, 1.0) Application.getInstance().setMainWindow(self) self._fullscreen = False @pyqtSlot() def toggleFullscreen(self): if self._fullscreen: self.setVisibility(QQuickWindow.Windowed) # Switch back to windowed else: self.setVisibility(QQuickWindow.FullScreen) # Go to fullscreen self._fullscreen = not self._fullscreen def getBackgroundColor(self): return self._background_color def setBackgroundColor(self, color): self._background_color = color self._app.getRenderer().setBackgroundColor(color) backgroundColor = pyqtProperty(QColor, fget=getBackgroundColor, fset=setBackgroundColor) mousePositionChanged = pyqtSignal() @pyqtProperty(int, notify = mousePositionChanged) def mouseX(self): return self._mouse_x @pyqtProperty(int, notify = mousePositionChanged) def mouseY(self): return self._mouse_y def setViewportRect(self, rect): if rect != self._viewport_rect: self._viewport_rect = rect self._updateViewportGeometry(self.width() * self.devicePixelRatio(), self.height() * self.devicePixelRatio()) self.viewportRectChanged.emit() viewportRectChanged = pyqtSignal() @pyqtProperty(QRectF, fset = setViewportRect, notify = viewportRectChanged) def viewportRect(self): return self._viewport_rect # Warning! Never reimplemented this as a QExposeEvent can cause a deadlock with QSGThreadedRender due to both trying # to claim the Python GIL. # def event(self, event): def mousePressEvent(self, event): super().mousePressEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseMoveEvent(self, event): self._mouse_x = event.x() self._mouse_y = event.y() self.mousePositionChanged.emit() super().mouseMoveEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def keyPressEvent(self, event): super().keyPressEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def wheelEvent(self, event): super().wheelEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def moveEvent(self, event): QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection); def resizeEvent(self, event): super().resizeEvent(event) win_w = event.size().width() * self.devicePixelRatio() win_h = event.size().height() * self.devicePixelRatio() self._updateViewportGeometry(win_w, win_h) QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection); def hideEvent(self, event): Application.getInstance().windowClosed() def _render(self): renderer = self._app.getRenderer() view = self._app.getController().getActiveView() renderer.beginRendering() view.beginRendering() renderer.renderQueuedNodes() view.endRendering() renderer.endRendering() def _onSceneChanged(self, object): self.update() @pyqtSlot() def _onWindowGeometryChanged(self): if self.windowState() == Qt.WindowNoState: self._preferences.setValue("general/window_width", self.width()) self._preferences.setValue("general/window_height", self.height()) self._preferences.setValue("general/window_left", self.x()) self._preferences.setValue("general/window_top", self.y()) self._preferences.setValue("general/window_state", Qt.WindowNoState) elif self.windowState() == Qt.WindowMaximized: self._preferences.setValue("general/window_state", Qt.WindowMaximized) def _updateViewportGeometry(self, width, height): view_w = width * self._viewport_rect.width() view_h = height * self._viewport_rect.height() for camera in self._app.getController().getScene().getAllCameras(): camera.setViewportSize(view_w, view_h) proj = Matrix() if camera.isPerspective(): proj.setPerspective(30, view_w / view_h, 1, 500) else: proj.setOrtho(-view_w / 2, view_w / 2, -view_h / 2, view_h / 2, -500, 500) camera.setProjectionMatrix(proj) self._app.getRenderer().setViewportSize(view_w, view_h) self._app.getRenderer().setWindowSize(width, height)
class MainWindow(QQuickWindow): def __init__(self, parent = None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.setClearBeforeRendering(False) self.beforeRendering.connect(self._render, type=Qt.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._previous_focus = None self._app = QCoreApplication.instance() self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect(self._onSceneChanged) self._preferences = Preferences.getInstance() self._preferences.addPreference("general/window_width", 1280) self._preferences.addPreference("general/window_height", 720) self._preferences.addPreference("general/window_left", 50) self._preferences.addPreference("general/window_top", 50) self._preferences.addPreference("general/window_state", Qt.WindowNoState) # Restore window geometry self.setWidth(int(self._preferences.getValue("general/window_width"))) self.setHeight(int(self._preferences.getValue("general/window_height"))) self.setPosition(int(self._preferences.getValue("general/window_left")), int(self._preferences.getValue("general/window_top"))) # Make sure restored geometry is not outside the currently available screens if not self.geometry().intersects(self.screen().availableGeometry()): self.setPosition(50,50) self.setWindowState(int(self._preferences.getValue("general/window_state"))) self._mouse_x = 0 self._mouse_y = 0 self._viewport_rect = QRectF(0, 0, 1.0, 1.0) Application.getInstance().setMainWindow(self) self._fullscreen = False @pyqtSlot() def toggleFullscreen(self): if self._fullscreen: self.setVisibility(QQuickWindow.Windowed) # Switch back to windowed else: self.setVisibility(QQuickWindow.FullScreen) # Go to fullscreen self._fullscreen = not self._fullscreen def getBackgroundColor(self): return self._background_color def setBackgroundColor(self, color): self._background_color = color self._app.getRenderer().setBackgroundColor(color) backgroundColor = pyqtProperty(QColor, fget=getBackgroundColor, fset=setBackgroundColor) mousePositionChanged = pyqtSignal() @pyqtProperty(int, notify = mousePositionChanged) def mouseX(self): return self._mouse_x @pyqtProperty(int, notify = mousePositionChanged) def mouseY(self): return self._mouse_y def setViewportRect(self, rect): if rect != self._viewport_rect: self._viewport_rect = rect self._updateViewportGeometry(self.width() * self.devicePixelRatio(), self.height() * self.devicePixelRatio()) self.viewportRectChanged.emit() viewportRectChanged = pyqtSignal() @pyqtProperty(QRectF, fset = setViewportRect, notify = viewportRectChanged) def viewportRect(self): return self._viewport_rect # Warning! Never reimplemented this as a QExposeEvent can cause a deadlock with QSGThreadedRender due to both trying # to claim the Python GIL. # def event(self, event): def mousePressEvent(self, event): super().mousePressEvent(event) if event.isAccepted(): return if self.activeFocusItem() != None and self.activeFocusItem() != self._previous_focus: self.activeFocusItem().setFocus(False) self._previous_focus = self.activeFocusItem() self._mouse_device.handleEvent(event) def mouseMoveEvent(self, event): self._mouse_x = event.x() self._mouse_y = event.y() self.mousePositionChanged.emit() super().mouseMoveEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def keyPressEvent(self, event): super().keyPressEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def wheelEvent(self, event): super().wheelEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def moveEvent(self, event): QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection); def resizeEvent(self, event): super().resizeEvent(event) win_w = event.size().width() * self.devicePixelRatio() win_h = event.size().height() * self.devicePixelRatio() self._updateViewportGeometry(win_w, win_h) QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection); def hideEvent(self, event): Application.getInstance().windowClosed() def _render(self): renderer = self._app.getRenderer() view = self._app.getController().getActiveView() renderer.beginRendering() view.beginRendering() renderer.render() view.endRendering() renderer.endRendering() def _onSceneChanged(self, object): self.update() @pyqtSlot() def _onWindowGeometryChanged(self): if self.windowState() == Qt.WindowNoState: self._preferences.setValue("general/window_width", self.width()) self._preferences.setValue("general/window_height", self.height()) self._preferences.setValue("general/window_left", self.x()) self._preferences.setValue("general/window_top", self.y()) self._preferences.setValue("general/window_state", Qt.WindowNoState) elif self.windowState() == Qt.WindowMaximized: self._preferences.setValue("general/window_state", Qt.WindowMaximized) def _updateViewportGeometry(self, width, height): view_w = width * self._viewport_rect.width() view_h = height * self._viewport_rect.height() for camera in self._app.getController().getScene().getAllCameras(): camera.setViewportSize(view_w, view_h) camera.setWindowSize(width, height) proj = Matrix() if camera.isPerspective(): proj.setPerspective(30, view_w / view_h, 1, 500) else: proj.setOrtho(-view_w / 2, view_w / 2, -view_h / 2, view_h / 2, -500, 500) camera.setProjectionMatrix(proj) self._app.getRenderer().setViewportSize(view_w, view_h) self._app.getRenderer().setWindowSize(width, height)
class MainWindow(QQuickWindow): def __init__(self, parent = None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.setClearBeforeRendering(False) self.beforeRendering.connect(self._render, type = Qt.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._previous_focus = None # type: Optional["QQuickItem"] self._app = QCoreApplication.instance() # Remove previously added input devices (if any). This can happen if the window was re-loaded. self._app.getController().removeInputDevice("qt_mouse") self._app.getController().removeInputDevice("qt_key") self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect(self._onSceneChanged) self._preferences = Application.getInstance().getPreferences() self._preferences.addPreference("general/window_width", 1280) self._preferences.addPreference("general/window_height", 720) self._preferences.addPreference("general/window_left", 50) self._preferences.addPreference("general/window_top", 50) self._preferences.addPreference("general/window_state", Qt.WindowNoState) # Restore window geometry self.setWidth(int(self._preferences.getValue("general/window_width"))) self.setHeight(int(self._preferences.getValue("general/window_height"))) self.setPosition(int(self._preferences.getValue("general/window_left")), int(self._preferences.getValue("general/window_top"))) # Make sure restored geometry is not outside the currently available screens screen_found = False for s in range(0, self._app.desktop().screenCount()): if self.geometry().intersects(self._app.desktop().availableGeometry(s)): screen_found = True break if not screen_found: self.setPosition(50, 50) self.setWindowState(int(self._preferences.getValue("general/window_state"))) self._mouse_x = 0 self._mouse_y = 0 self._mouse_pressed = False self._viewport_rect = QRectF(0, 0, 1.0, 1.0) self.closing.connect(self.preClosing) Application.getInstance().setMainWindow(self) self._fullscreen = False self._allow_resize = True # This event is triggered before hideEvent(self, event) event and might prevent window closing if # does not pass the check, for example if USB printer is printing # The implementation is in Cura.qml preClosing = pyqtSignal("QQuickCloseEvent*", arguments = ["close"]) def setAllowResize(self, allow_resize: bool): if self._allow_resize != allow_resize: if not allow_resize: self.setMaximumHeight(self.height()) self.setMinimumHeight(self.height()) self.setMaximumWidth(self.width()) self.setMinimumWidth(self.width()) else: self.setMaximumHeight(16777215) self.setMinimumHeight(0) self.setMaximumWidth(16777215) self.setMinimumWidth(0) self._allow_resize = allow_resize @pyqtSlot() def toggleFullscreen(self): if self._fullscreen: self.setVisibility(QQuickWindow.Windowed) # Switch back to windowed else: self.setVisibility(QQuickWindow.FullScreen) # Go to fullscreen self._fullscreen = not self._fullscreen def getBackgroundColor(self): return self._background_color def setBackgroundColor(self, color): self._background_color = color self._app.getRenderer().setBackgroundColor(color) backgroundColor = pyqtProperty(QColor, fget=getBackgroundColor, fset=setBackgroundColor) mousePositionChanged = pyqtSignal() @pyqtProperty(int, notify = mousePositionChanged) def mouseX(self): return self._mouse_x @pyqtProperty(int, notify = mousePositionChanged) def mouseY(self): return self._mouse_y def setViewportRect(self, rect): if rect != self._viewport_rect: self._viewport_rect = rect self._updateViewportGeometry(self.width() * self.devicePixelRatio(), self.height() * self.devicePixelRatio()) self.viewportRectChanged.emit() viewportRectChanged = pyqtSignal() @pyqtProperty(QRectF, fset = setViewportRect, notify = viewportRectChanged) def viewportRect(self): return self._viewport_rect # Warning! Never reimplemented this as a QExposeEvent can cause a deadlock with QSGThreadedRender due to both trying # to claim the Python GIL. # def event(self, event): def mousePressEvent(self, event): super().mousePressEvent(event) if event.isAccepted(): return if self.activeFocusItem() is not None and self.activeFocusItem() != self._previous_focus: self.activeFocusItem().setFocus(False) self._previous_focus = self.activeFocusItem() self._mouse_device.handleEvent(event) self._mouse_pressed = True def mouseMoveEvent(self, event): self._mouse_x = event.x() self._mouse_y = event.y() if self._mouse_pressed: self.mousePositionChanged.emit() super().mouseMoveEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) self._mouse_pressed = False def keyPressEvent(self, event): super().keyPressEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def wheelEvent(self, event): super().wheelEvent(event) if event.isAccepted(): return self._mouse_device.handleEvent(event) def moveEvent(self, event): QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection) def resizeEvent(self, event): super().resizeEvent(event) win_w = event.size().width() * self.devicePixelRatio() win_h = event.size().height() * self.devicePixelRatio() self._updateViewportGeometry(win_w, win_h) QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection) def hideEvent(self, event): if Application.getInstance().getMainWindow() == self: Application.getInstance().windowClosed() renderCompleted = Signal(type = Signal.Queued) def _render(self): renderer = self._app.getRenderer() view = self._app.getController().getActiveView() renderer.beginRendering() view.beginRendering() renderer.render() view.endRendering() renderer.endRendering() self.renderCompleted.emit() def _onSceneChanged(self, object): self.update() @pyqtSlot() def _onWindowGeometryChanged(self): self._preferences.setValue("general/window_width", self.width()) self._preferences.setValue("general/window_height", self.height()) self._preferences.setValue("general/window_left", self.x()) self._preferences.setValue("general/window_top", self.y()) # This is a workaround for QTBUG-30085 if self.windowState() in (Qt.WindowNoState, Qt.WindowMaximized): self._preferences.setValue("general/window_state", self.windowState()) def _updateViewportGeometry(self, width: int, height: int): view_width = width * self._viewport_rect.width() view_height = height * self._viewport_rect.height() for camera in self._app.getController().getScene().getAllCameras(): camera.setWindowSize(width, height) if camera.getAutoAdjustViewPort(): camera.setViewportSize(view_width, view_height) projection_matrix = Matrix() if camera.isPerspective(): if view_width is not 0: projection_matrix.setPerspective(30, view_width / view_height, 1, 500) else: projection_matrix.setOrtho(-view_width / 2, view_width / 2, -view_height / 2, view_height / 2, -500, 500) camera.setProjectionMatrix(projection_matrix) self._app.getRenderer().setViewportSize(view_width, view_height) self._app.getRenderer().setWindowSize(width, height)
class MainWindow(QQuickWindow): """QQuickWindow subclass that provides the main window.""" DEFAULT_WINDOW_WIDTH = 1280 DEFAULT_WINDOW_HEIGHT = 720 DEFAULT_WINDOW_LEFT = 50 DEFAULT_WINDOW_TOP = 50 def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.beforeRenderPassRecording.connect( self._render, type=Qt.ConnectionType.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._previous_focus = None # type: Optional["QQuickItem"] self._app = QCoreApplication.instance() # Remove previously added input devices (if any). This can happen if the window was re-loaded. self._app.getController().removeInputDevice("qt_mouse") self._app.getController().removeInputDevice("qt_key") self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect( self._onSceneChanged) self._app.getController().activeViewChanged.connect( self._onActiveViewChanged) Selection.selectionChanged.connect(self._onSceneChanged) self._preferences = Application.getInstance().getPreferences() self._preferences.addPreference("general/window_width", self.DEFAULT_WINDOW_WIDTH) self._preferences.addPreference("general/window_height", self.DEFAULT_WINDOW_HEIGHT) self._preferences.addPreference("general/window_left", self.DEFAULT_WINDOW_LEFT) self._preferences.addPreference("general/window_top", self.DEFAULT_WINDOW_TOP) self._preferences.addPreference("general/window_state", Qt.WindowState.WindowNoState.value) self._preferences.addPreference("general/restore_window_geometry", True) restored_geometry = QRect( int(self._preferences.getValue("general/window_left")), int(self._preferences.getValue("general/window_top")), int(self._preferences.getValue("general/window_width")), int(self._preferences.getValue("general/window_height"))) if not self._preferences.getValue("general/restore_window_geometry"): # Ignore whatever the preferences said. Logger.log( "i", "Not restoring window geometry from preferences because 'restore_window_geometry' is false" ) restored_geometry = QRect(self.DEFAULT_WINDOW_LEFT, self.DEFAULT_WINDOW_TOP, self.DEFAULT_WINDOW_WIDTH, self.DEFAULT_WINDOW_HEIGHT) # Make sure restored geometry is not outside the currently available screens screen_found = False for screen in self._app.screens(): if restored_geometry.intersects(screen.availableGeometry()): screen_found = True break if not screen_found: Logger.log( "w", "Could not restore to previous location on screen, since the sizes or number of monitors " "have changed since then") # Unable to find the screen that this window used to be on, so just use the defaults restored_geometry = QRect(self.DEFAULT_WINDOW_LEFT, self.DEFAULT_WINDOW_TOP, self.DEFAULT_WINDOW_WIDTH, self.DEFAULT_WINDOW_HEIGHT) self.setGeometry(restored_geometry) # Translate window state back to enum. try: window_state = int( self._preferences.getValue("general/window_state")) except ValueError: self._preferences.resetPreference("general/window_state") window_state = int( self._preferences.getValue("general/window_state")) if window_state == Qt.WindowState.WindowNoState.value: self.setWindowState(Qt.WindowState.WindowNoState) elif window_state == Qt.WindowState.WindowMaximized.value: self.setWindowState(Qt.WindowState.WindowMaximized) self._mouse_x = 0 self._mouse_y = 0 self._mouse_pressed = False self._viewport_rect = QRectF(0, 0, 1.0, 1.0) self.closing.connect(self.preClosing) Application.getInstance().setMainWindow(self) self._fullscreen = False self._full_render_required = True self._allow_resize = True # This event is triggered before hideEvent(self, event) event and might prevent window closing if # does not pass the check, for example if USB printer is printing # The implementation is in Cura.qml preClosing = pyqtSignal("QQuickCloseEvent*", arguments=["close"]) def setAllowResize(self, allow_resize: bool): if self._allow_resize != allow_resize: if not allow_resize: self.setMaximumHeight(self.height()) self.setMinimumHeight(self.height()) self.setMaximumWidth(self.width()) self.setMinimumWidth(self.width()) else: self.setMaximumHeight(16777215) self.setMinimumHeight(0) self.setMaximumWidth(16777215) self.setMinimumWidth(0) self._allow_resize = allow_resize @pyqtSlot() def toggleFullscreen(self): if self._fullscreen: self.setVisibility( QQuickWindow.Visibility.Windowed) # Switch back to windowed else: self.setVisibility( QQuickWindow.Visibility.FullScreen) # Go to fullscreen self._fullscreen = not self._fullscreen @pyqtSlot() def exitFullscreen(self): self.setVisibility(QQuickWindow.Visibility.Windowed) self._fullscreen = False def getBackgroundColor(self): return self._background_color def setBackgroundColor(self, color): self._background_color = color self._app.getRenderer().setBackgroundColor(color) backgroundColor = pyqtProperty(QColor, fget=getBackgroundColor, fset=setBackgroundColor) mousePositionChanged = pyqtSignal() @pyqtProperty(int, notify=mousePositionChanged) def mouseX(self): return self._mouse_x @pyqtProperty(int, notify=mousePositionChanged) def mouseY(self): return self._mouse_y def setViewportRect(self, rect): if rect != self._viewport_rect: self._viewport_rect = rect self._updateViewportGeometry( self.width() * self.devicePixelRatio(), self.height() * self.devicePixelRatio()) self.viewportRectChanged.emit() viewportRectChanged = pyqtSignal() @pyqtProperty(QRectF, fset=setViewportRect, notify=viewportRectChanged) def viewportRect(self): return self._viewport_rect # Warning! Never reimplemented this as a QExposeEvent can cause a deadlock with QSGThreadedRender due to both trying # to claim the Python GIL. # def event(self, event): @pyqtSlot(QObject) def mousePressed(self, event): if event is None: return wrap_event = MouseEventWrapper(event.property("x"), event.property("y"), event.property("buttons"), event.property("button"), QEvent.Type.MouseButtonPress) self._mouse_pressed = True self._mouse_device.handleEvent(wrap_event) @pyqtSlot(QObject) def mouseMoved(self, event): if event is None: return wrap_event = MouseEventWrapper(event.property("x"), event.property("y"), event.property("buttons"), event.property("button"), QEvent.Type.MouseMove) self._mouse_device.handleEvent(wrap_event) @pyqtSlot(QObject) def wheel(self, event): if event is None: return wrap_event = MouseEventWrapper(event.property("x"), event.property("y"), event.property("buttons"), event.property("button"), QEvent.Type.Wheel, event.property("angleDelta")) self._mouse_device.handleEvent(wrap_event) @pyqtSlot(QObject) def mouseReleased(self, event): if event is None: return wrap_event = MouseEventWrapper(event.property("x"), event.property("y"), event.property("buttons"), event.property("button"), QEvent.Type.MouseButtonRelease) self._mouse_pressed = False self._mouse_device.handleEvent(wrap_event) def mousePressEvent(self, event): event.setAccepted(False) super().mousePressEvent(event) if event.isAccepted(): return if self.activeFocusItem( ) is not None and self.activeFocusItem() != self._previous_focus: self.activeFocusItem().setFocus(False) self._previous_focus = self.activeFocusItem() def mouseMoveEvent(self, event): event.setAccepted(False) self._mouse_x = event.pos().x() self._mouse_y = event.pos().y() if self._mouse_pressed: self.mousePositionChanged.emit() super().mouseMoveEvent(event) def mouseReleaseEvent(self, event): event.setAccepted(False) super().mouseReleaseEvent(event) if event.isAccepted(): return def keyPressEvent(self, event): super().keyPressEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def keyReleaseEvent(self, event): super().keyReleaseEvent(event) if event.isAccepted(): return self._key_device.handleEvent(event) def wheelEvent(self, event): event.setAccepted(False) super().wheelEvent(event) def moveEvent(self, event): QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.ConnectionType.QueuedConnection) def resizeEvent(self, event): super().resizeEvent(event) win_w = event.size().width() * self.devicePixelRatio() win_h = event.size().height() * self.devicePixelRatio() self._updateViewportGeometry(win_w, win_h) QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.ConnectionType.QueuedConnection) def hideEvent(self, event): if Application.getInstance().getMainWindow() == self: Application.getInstance().windowClosed() renderCompleted = Signal(type=Signal.Queued) def _render(self): self.beginExternalCommands() if self._full_render_required: renderer = self._app.getRenderer() view = self._app.getController().getActiveView() renderer.beginRendering() view.beginRendering() renderer.render() view.endRendering() renderer.endRendering() self._full_render_required = False self.renderCompleted.emit() else: self._app.getRenderer().reRenderLast() self.endExternalCommands() def _onSceneChanged(self, object=None): self._full_render_required = True self.update() def _onActiveViewChanged(self): self._full_render_required = True self.update() @pyqtSlot() def _onWindowGeometryChanged(self): # Do not store maximised window geometry, but store state instead # Using windowState instead of isMaximized is a workaround for QTBUG-30085 if self.windowState() == Qt.WindowState.WindowNoState: self._preferences.setValue("general/window_width", self.width()) self._preferences.setValue("general/window_height", self.height()) self._preferences.setValue("general/window_left", self.x()) self._preferences.setValue("general/window_top", self.y()) if self.windowState() in (Qt.WindowState.WindowNoState, Qt.WindowState.WindowMaximized): self._preferences.setValue("general/window_state", self.windowState().value) def _updateViewportGeometry(self, width: int, height: int) -> None: view_width = round(width * self._viewport_rect.width()) view_height = round(height * self._viewport_rect.height()) for camera in self._app.getController().getScene().getAllCameras(): camera.setWindowSize(width, height) if camera.getAutoAdjustViewPort(): camera.setViewportSize(view_width, view_height) self._app.getRenderer().setViewportSize(view_width, view_height) self._app.getRenderer().setWindowSize(width, height)