Browse Source

Get default settings view to work as sidebar component

ChrisTerBeke 7 years ago
parent
commit
3c863fc388

+ 21 - 16
cura/CuraApplication.py

@@ -32,13 +32,11 @@ from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
 from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
 from UM.Operations.GroupedOperation import GroupedOperation
 from UM.Operations.SetTransformOperation import SetTransformOperation
+
 from cura.Arrange import Arrange
-from cura.Settings.SettingsSidebarView import SettingsSidebarView
 from cura.ShapeArray import ShapeArray
 from cura.ConvexHullDecorator import ConvexHullDecorator
 from cura.SetParentOperation import SetParentOperation
-from cura.Sidebar.SidebarController import SidebarController
-from cura.Sidebar.SidebarViewModel import SidebarViewModel
 from cura.SliceableObjectDecorator import SliceableObjectDecorator
 from cura.BlockSlicingDecorator import BlockSlicingDecorator
 
@@ -78,6 +76,11 @@ from cura.Settings.ContainerManager import ContainerManager
 from cura.Settings.GlobalStack import GlobalStack
 from cura.Settings.ExtruderStack import ExtruderStack
 
+from cura.Sidebar.SidebarController import SidebarController
+from cura.Sidebar.SidebarControllerProxy import SidebarControllerProxy
+from cura.Sidebar.SidebarViewModel import SidebarViewModel
+from cura.Settings.SettingsSidebarView import SettingsSidebarView
+
 from PyQt5.QtCore import QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
 from UM.FlameProfiler import pyqtSlot
 from PyQt5.QtGui import QColor, QIcon
@@ -131,6 +134,7 @@ class CuraApplication(QtApplication):
     stacksValidationFinished = pyqtSignal()  # Emitted whenever a validation is finished
 
     def __init__(self):
+
         # this list of dir names will be used by UM to detect an old cura directory
         for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]:
             Resources.addExpectedDirNameInData(dir_name)
@@ -159,7 +163,6 @@ class CuraApplication(QtApplication):
 
         SettingDefinition.addSettingType("extruder", None, str, Validator)
         SettingDefinition.addSettingType("optional_extruder", None, str, None)
-
         SettingDefinition.addSettingType("[int]", None, str, None)
 
         SettingFunction.registerOperator("extruderValues", ExtruderManager.getExtruderValues)
@@ -184,7 +187,8 @@ class CuraApplication(QtApplication):
         ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.DefinitionChangesContainer)
 
         ##  Initialise the version upgrade manager with Cura's storage paths.
-        import UM.VersionUpgradeManager #Needs to be here to prevent circular dependencies.
+        #   Needs to be here to prevent circular dependencies.
+        import UM.VersionUpgradeManager
 
         UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions(
             {
@@ -323,6 +327,11 @@ class CuraApplication(QtApplication):
 
         self._need_to_show_user_agreement = not Preferences.getInstance().getValue("general/accepted_user_agreement")
 
+        # Set the active sidebar view based on user preferences
+        preferences.addPreference("cura/active_sidebar_view", "default")
+        active_sidebar_view = preferences.getValue("cura/active_sidebar_view")
+        self._sidebar_controller.setActiveSidebarView(active_sidebar_view)
+
         for key in [
             "dialog_load_path",  # dialog_save_path is in LocalFileOutputDevicePlugin
             "dialog_profile_path",
@@ -678,7 +687,6 @@ class CuraApplication(QtApplication):
         controller = self.getController()
 
         controller.setActiveView("SolidView")
-
         controller.setCameraTool("CameraTool")
         controller.setSelectionTool("SelectionTool")
 
@@ -741,6 +749,11 @@ class CuraApplication(QtApplication):
 
             self.exec_()
 
+    ##  Get the SidebarController of this application.
+    #   \returns SidebarControllers \type{SidebarController}
+    def getSidebarController(self) -> SidebarController:
+        return self._sidebar_controller
+
     def getMachineManager(self, *args):
         if self._machine_manager is None:
             self._machine_manager = MachineManager.createMachineManager()
@@ -786,14 +799,6 @@ class CuraApplication(QtApplication):
     def getPrintInformation(self):
         return self._print_information
 
-    ##  Get the SidebarController of this application.
-    #   A sidebar controller is created if it wasn't yet.
-    #   \returns SidebarControllers \type{SidebarController}
-    def getSidebarController(self) -> SidebarController:
-        if self._sidebar_controller is None:
-            self._sidebar_controller = SidebarController(self)
-        return self._sidebar_controller
-
     ##  Registers objects for the QML engine to use.
     #
     #   \param engine The QML engine.
@@ -808,6 +813,7 @@ class CuraApplication(QtApplication):
 
         qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
 
+        qmlRegisterType(SidebarViewModel, "Cura", 1, 0, "SidebarViewModel")
         qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
         qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
         qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel)
@@ -819,8 +825,7 @@ class CuraApplication(QtApplication):
         qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
         qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel")
         qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager)
-        qmlRegisterSingletonType(SidebarController, "Cura", 1, 0, "SidebarController", self.getSidebarController)
-        qmlRegisterType(SidebarViewModel, "Cura", 1, 0, "SidebarViewModel")
+        qmlRegisterSingletonType(SidebarControllerProxy, "Cura", 1, 0, "SidebarController", SidebarControllerProxy.createSidebarControllerProxy)
 
         # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work.
         actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")))

+ 11 - 5
cura/Settings/SettingsSidebarView.py

@@ -1,23 +1,29 @@
 # Copyright (c) 2017 Ultimaker B.V.
-from PyQt5.QtCore import QObject
+import os.path
+from PyQt5.QtCore import QObject, QUrl
+
 from UM.i18n import i18nCatalog
 from cura.Sidebar.SidebarView import SidebarView
 i18n_catalog = i18nCatalog("cura")
 
 class SettingsSidebarView(QObject, SidebarView):
 
-    def __init__(self):
-        super().__init__()
+    def __init__(self, parent = None):
+        super().__init__(parent)
 
     ##  As the default sidebar is not a plugin, we have a get plugin ID method to allow the sidebar view model to get the needed data.
     def getPluginId(self):
         return "default"
 
-    ##  As the default sidebar is not a plugin, we have a get meta data method here to allow the sidebar view model to get the needed data.
+    ##  As the default sidebar is not a plugin, we have a add meta data method here to allow the sidebar view model to get the needed data.
     def getMetaData(self):
         return {
             "sidebar_view": {
                 "name": i18n_catalog.i18nc("", "Print settings"),
-                "weight": 1
+                "weight": 0
             }
         }
+
+    ##  As the default sidebar is not a plugin, we have a get component path method here to allow the sidebar controller to get the needed data.
+    def getComponentPath(self):
+        return QUrl("SidebarSettings.qml")

+ 17 - 14
cura/Sidebar/SidebarController.py

@@ -1,9 +1,7 @@
 # Copyright (c) 2017 Ultimaker B.V.
 from UM.Logger import Logger
-from UM.PluginRegistry import PluginRegistry
 from UM.Signal import Signal
-from .SidebarView import SidebarView
-from typing import Optional, Dict
+from UM.PluginRegistry import PluginRegistry
 
 # The sidebar controller manages available sidebar components and decides which one to display.
 # The cura.qml file uses this controller to repeat over the sidebars and show the active index.
@@ -14,6 +12,7 @@ class SidebarController:
         self._sidebar_views = {}
         self._active_sidebar_view = None
 
+        # Register the sidebar_view plugin type so plugins can expose custom sidebar views.
         PluginRegistry.addType("sidebar_view", self.addSidebarView)
 
     ##  Emitted when the list of views changes.
@@ -26,28 +25,32 @@ class SidebarController:
     def getApplication(self):
         return self._application
 
+    ##  Get all sidebar views registered in this controller.
+    def getAllSidebarViews(self):
+        return self._sidebar_views
+
     ##  Add a sidebar view to the registry.
     #   It get's a unique name based on the plugin ID.
-    def addSidebarView(self, sidebar_view: SidebarView):
-        name = sidebar_view.getPluginId()
-        if name not in self._sidebar_views:
-            self._sidebar_views[name] = sidebar_view
+    def addSidebarView(self, sidebar_view):
+        sidebar_view_id = sidebar_view.getPluginId()
+        if sidebar_view_id not in self._sidebar_views:
+            self._sidebar_views[sidebar_view_id] = sidebar_view
             self.sidebarViewsChanged.emit()
 
     ##  Get a registered sidebar view by name.
     #   The name is the ID of the plugin that registered the view.
-    def getSidebarView(self, name: str) -> Optional[SidebarView]:
+    def getSidebarView(self, name: str):
         try:
             return self._sidebar_views[name]
         except KeyError:
             Logger.log("e", "Unable to find %s in sidebar view list", name)
             return None
 
+    ##  Get the active sidebar view.
+    def getActiveSidebarView(self):
+        return self._active_sidebar_view
+
     ##  Change the active sidebar view to one of the registered views.
-    def setActiveSidebarView(self, name: str):
-        print("setting active sidebar view")
+    def setActiveSidebarView(self, sidebar_view_id: str):
+        self._active_sidebar_view = self._sidebar_views[sidebar_view_id]
         self.activeSidebarViewChanged.emit()
-
-    ##  Get all sidebar views registered in this controller.
-    def getAllSidebarViews(self) -> Dict[SidebarView]:
-        return self._sidebar_views

+ 36 - 0
cura/Sidebar/SidebarControllerProxy.py

@@ -0,0 +1,36 @@
+# Copyright (c) 2017 Ultimaker B.V.
+from PyQt5.QtCore import QObject, pyqtSlot, QUrl, pyqtProperty, pyqtSignal
+from UM.Application import Application
+
+
+##  The sidebar controller proxy acts a proxy between the sidebar controller and the QMl context of the controller.
+class SidebarControllerProxy(QObject):
+
+    def __init__(self, parent = None):
+        super().__init__(parent)
+        self._controller = Application.getInstance().getSidebarController()
+        self._controller.activeSidebarViewChanged.connect(self._onActiveSidebarComponentChanged)
+
+    ##  Emitted when the active view changes.
+    activeSidebarViewChanged = pyqtSignal()
+
+    @classmethod
+    def createSidebarControllerProxy(self, engine, script_engine):
+        return SidebarControllerProxy()
+
+    @pyqtSlot()
+    def setActiveView(self, sidebar_view):
+        self._controller.setActiveSidebarView(sidebar_view)
+
+    @pyqtProperty(QUrl, notify = activeSidebarViewChanged)
+    def activeComponentPath(self):
+        if not self._controller.getActiveSidebarView():
+            return QUrl()
+        return self._controller.getActiveSidebarView().getComponentPath()
+
+    @pyqtSlot(QUrl)
+    def getSidebarComponentPath(self, sidebar_id):
+        self._controller.getSidebarView(sidebar_id).getComponentPath()
+
+    def _onActiveSidebarComponentChanged(self):
+        self.activeSidebarViewChanged.emit()

+ 13 - 2
cura/Sidebar/SidebarView.py

@@ -1,7 +1,9 @@
 # Copyright (c) 2017 Ultimaker B.V.
+from PyQt5.QtCore import QUrl
 
+from UM.Logger import Logger
 from UM.PluginObject import PluginObject
-
+from UM.PluginRegistry import PluginRegistry
 
 #   Abstract class for sidebar view objects.
 #   By default the sidebar is Cura's settings, slicing and printing overview.
@@ -10,4 +12,13 @@ class SidebarView(PluginObject):
 
     def __init__(self):
         super().__init__()
-        print("sidebar view hello")
+        self._view = None
+
+    ##  Get the path to the component QML file as QUrl
+    def getComponentPath(self):
+        try:
+            sidebar_component_file_path = PluginRegistry.getInstance().getMetaData(self.getPluginId())["sidebar_view"]["sidebar_component"]
+            return QUrl.fromLocalFile(sidebar_component_file_path)
+        except KeyError:
+            Logger.log("w", "Could not find sidebar component QML file for %s", self.getPluginId())
+            return QUrl()

+ 5 - 3
cura_app.py

@@ -22,9 +22,10 @@ if Platform.isLinux(): # Needed for platform.linux_distribution, which is not av
 if Platform.isWindows() and hasattr(sys, "frozen"):
     try:
         del os.environ["PYTHONPATH"]
-    except KeyError: pass
+    except KeyError:
+        pass
 
-#WORKAROUND: GITHUB-704 GITHUB-708
+# WORKAROUND: GITHUB-704 GITHUB-708
 # It looks like setuptools creates a .pth file in
 # the default /usr/lib which causes the default site-packages
 # to be inserted into sys.path before PYTHONPATH.
@@ -45,6 +46,7 @@ def exceptHook(hook_type, value, traceback):
     _crash_handler = CrashHandler(hook_type, value, traceback)
     _crash_handler.show()
 
+
 sys.excepthook = exceptHook
 
 # Workaround for a race condition on certain systems where there
@@ -75,7 +77,7 @@ faulthandler.enable()
 # Force an instance of CuraContainerRegistry to be created and reused later.
 cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance()
 
-# This prestart up check is needed to determine if we should start the application at all.
+# This pre-start up check is needed to determine if we should start the application at all.
 if not cura.CuraApplication.CuraApplication.preStartUp():
     sys.exit(0)
 

+ 13 - 8
resources/qml/Cura.qml

@@ -366,19 +366,24 @@ UM.MainWindow
                 onStopMonitoringPrint: base.showPrintMonitor = false
             }
 
-            Sidebar
+            Loader
             {
-                id: sidebar;
+                id: sidebar
 
                 anchors
                 {
-                    top: topbar.bottom;
-                    bottom: parent.bottom;
-                    right: parent.right;
+                    top: topbar.bottom
+                    bottom: parent.bottom
+                    right: parent.right
                 }
-                z: 1
-                width: UM.Theme.getSize("sidebar").width;
-                monitoringPrint: base.showPrintMonitor
+
+                width: UM.Theme.getSize("sidebar").width
+
+                // all sidebar components will have access to the show print monitor flag
+                property bool showPrintMonitor: base.showPrintMonitor
+
+                // dynamically get the component from the sidebar controller
+                source: Cura.SidebarController.activeComponentPath
             }
 
             Rectangle

+ 21 - 0
resources/qml/SidebarSettings.qml

@@ -0,0 +1,21 @@
+// Copyright (c) 2017 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+
+Sidebar
+{
+    id: sidebarSettings
+
+    property bool showPrintMonitor: false
+
+    anchors {
+        top: parent.top
+        bottom: parent.bottom
+        left: parent.left
+        right: parent.right
+    }
+
+    width: parent.width
+    monitoringPrint: showPrintMonitor
+}