Implement switching sidebar views

This commit is contained in:
ChrisTerBeke 2017-12-04 19:37:03 +01:00
parent 3c863fc388
commit caf56587fe
8 changed files with 121 additions and 72 deletions

View file

@ -201,6 +201,10 @@ class CuraApplication(QtApplication):
}
)
## As of Cura 3.2, the sidebar is controlled by a controller.
# This functionality was added to allow plugins registering custom sidebar views.
self._sidebar_controller = SidebarController(self)
self._currently_loading_files = []
self._non_sliceable_extensions = []
@ -221,14 +225,6 @@ class CuraApplication(QtApplication):
self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
## As of Cura 3.2, the sidebar is controlled by a controller.
# This functionality was added to allow plugins registering custom sidebar views.
self._sidebar_controller = SidebarController(self)
## Register the default settings sidebar manually
settings_sidebar_view = SettingsSidebarView()
self._sidebar_controller.addSidebarView(settings_sidebar_view)
self.setRequiredPlugins([
"CuraEngineBackend",
"UserAgreement",
@ -327,11 +323,6 @@ 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",
@ -737,6 +728,10 @@ class CuraApplication(QtApplication):
if not run_headless:
self.initializeEngine()
# Now that the SidebarViewModel has been created we can set the default sidebar view
# TODO: put this in a more elegant place
self._setDefaultSidebarView()
if run_headless or self._engine.rootObjects:
self.closeSplash()
@ -1324,6 +1319,19 @@ class CuraApplication(QtApplication):
def _addProfileWriter(self, profile_writer):
pass
## Create and register the default sidebar component (settings)
def _setDefaultSidebarView(self):
# Register the default settings sidebar manually
settings_sidebar_view = SettingsSidebarView()
self._sidebar_controller.addSidebarView(settings_sidebar_view)
# Set the default sidebar view depending on user preferences.
preferences = Preferences.getInstance()
preferences.addPreference("cura/active_sidebar_view", settings_sidebar_view.getPluginId())
active_sidebar_view = preferences.getValue("cura/active_sidebar_view")
self._sidebar_controller.setActiveSidebarView(active_sidebar_view)
@pyqtSlot("QSize")
def setMinimumWindowSize(self, size):
self.getMainWindow().setMinimumSize(size)

View file

@ -1,8 +1,8 @@
# Copyright (c) 2017 Ultimaker B.V.
import os.path
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtCore import QObject
from UM.i18n import i18nCatalog
from cura.Sidebar.SidebarView import SidebarView
i18n_catalog = i18nCatalog("cura")
@ -19,11 +19,10 @@ class SettingsSidebarView(QObject, SidebarView):
def getMetaData(self):
return {
"sidebar_view": {
"name": i18n_catalog.i18nc("", "Print settings"),
"name": i18n_catalog.i18nc("@item:inmenu", "Print settings"),
"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")
def getComponent(self):
return None

View file

@ -1,5 +1,6 @@
# Copyright (c) 2017 Ultimaker B.V.
from UM.Logger import Logger
from UM.Preferences import Preferences
from UM.Signal import Signal
from UM.PluginRegistry import PluginRegistry
@ -52,5 +53,7 @@ class SidebarController:
## Change the active sidebar view to one of the registered views.
def setActiveSidebarView(self, sidebar_view_id: str):
self._active_sidebar_view = self._sidebar_views[sidebar_view_id]
self.activeSidebarViewChanged.emit()
if sidebar_view_id in self._sidebar_views:
self._active_sidebar_view = self._sidebar_views[sidebar_view_id]
Preferences.getInstance().setValue("cura/active_sidebar_view", sidebar_view_id)
self.activeSidebarViewChanged.emit()

View file

@ -4,33 +4,41 @@ from UM.Application import Application
## The sidebar controller proxy acts a proxy between the sidebar controller and the QMl context of the controller.
from UM.Logger import Logger
class SidebarControllerProxy(QObject):
def __init__(self, parent = None):
super().__init__(parent)
self._controller = Application.getInstance().getSidebarController()
self._controller.activeSidebarViewChanged.connect(self._onActiveSidebarComponentChanged)
self._controller.activeSidebarViewChanged.connect(self._onActiveSidebarViewChanged)
## 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(str, notify = activeSidebarViewChanged)
def activeSidebarId(self):
if self._controller.getActiveSidebarView() is not None:
return self._controller.getActiveSidebarView().getPluginId()
else:
return "default"
@pyqtProperty(QUrl, notify = activeSidebarViewChanged)
def activeComponentPath(self):
if not self._controller.getActiveSidebarView():
return QUrl()
return self._controller.getActiveSidebarView().getComponentPath()
@pyqtSlot(str)
def setActiveSidebarView(self, sidebar_view_id):
Logger.log("d", "Setting active sidebar view to %s", sidebar_view_id)
self._controller.setActiveSidebarView(sidebar_view_id)
@pyqtSlot(QUrl)
@pyqtSlot(str, result = QObject)
def getSidebarComponent(self, sidebar_id):
return self._controller.getSidebarView(sidebar_id).getComponent()
@pyqtSlot(str, result = QUrl)
def getSidebarComponentPath(self, sidebar_id):
self._controller.getSidebarView(sidebar_id).getComponentPath()
return self._controller.getSidebarView(sidebar_id).getComponentPath()
def _onActiveSidebarComponentChanged(self):
def _onActiveSidebarViewChanged(self):
self.activeSidebarViewChanged.emit()

View file

@ -1,6 +1,7 @@
# Copyright (c) 2017 Ultimaker B.V.
from PyQt5.QtCore import QUrl
import os.path
from UM.Application import Application
from UM.Logger import Logger
from UM.PluginObject import PluginObject
from UM.PluginRegistry import PluginRegistry
@ -14,11 +15,21 @@ class SidebarView(PluginObject):
super().__init__()
self._view = None
def getComponent(self):
if not self._view:
self.createView()
return self._view
def createView(self):
component_path = self.getComponentPath()
self._view = Application.getInstance().createQmlComponent(component_path, {"manager": self})
## Get the path to the component QML file as QUrl
def getComponentPath(self):
try:
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
sidebar_component_file_path = PluginRegistry.getInstance().getMetaData(self.getPluginId())["sidebar_view"]["sidebar_component"]
return QUrl.fromLocalFile(sidebar_component_file_path)
return os.path.join(plugin_path, sidebar_component_file_path)
except KeyError:
Logger.log("w", "Could not find sidebar component QML file for %s", self.getPluginId())
return QUrl()
return ""

View file

@ -26,17 +26,18 @@ class SidebarViewModel(ListModel):
## Update the model when new views are added or another view is made the active view.
def _onSidebarViewsChanged(self):
items = []
current_view_id = None
sidebar_views = self._controller.getAllSidebarViews()
current_view = self._controller.getActiveSidebarView()
if current_view:
current_view_id = current_view.getPluginId()
for sidebar_view_id, sidebar_view in sidebar_views.items():
plugin_metadata = PluginRegistry.getInstance().getMetaData(sidebar_view_id)
if plugin_metadata:
# Check if the registered view came from a plugin and extract the metadata if so.
sidebar_view_metadata = plugin_metadata.get("sidebar_view", {})
if sidebar_view_id != "default":
sidebar_view_metadata = PluginRegistry.getInstance().getMetaData(sidebar_view_id).get("sidebar_view", {})
else:
# Get the meta data directly from the plugin
sidebar_view_metadata = sidebar_view.getMetaData()
sidebar_view_metadata = sidebar_view.getMetaData().get("sidebar_view", {})
# Skip view modes that are marked as not visible
if "visible" in sidebar_view_metadata and not sidebar_view_metadata["visible"]:
@ -48,7 +49,7 @@ class SidebarViewModel(ListModel):
items.append({
"id": sidebar_view_id,
"name": name,
"active": sidebar_view_id == current_view.getPluginId(),
"active": sidebar_view_id == current_view_id,
"weight": weight
})

View file

@ -331,7 +331,7 @@ UM.MainWindow
text: catalog.i18nc("@action:button","Open File");
iconSource: UM.Theme.getIcon("load")
style: UM.Theme.styles.tool_button
tooltip: '';
tooltip: ""
anchors
{
top: topbar.bottom;
@ -366,7 +366,7 @@ UM.MainWindow
onStopMonitoringPrint: base.showPrintMonitor = false
}
Loader
Rectangle
{
id: sidebar
@ -379,11 +379,30 @@ UM.MainWindow
width: UM.Theme.getSize("sidebar").width
// all sidebar components will have access to the show print monitor flag
property bool showPrintMonitor: base.showPrintMonitor
// The sidebarRepeater exposes sidebar views provided by plugins.
// Whenever a plugin sidebar view is active (e.g. not "default"), that sidebar view is shown.
Repeater
{
id: sidebarRepeater
// dynamically get the component from the sidebar controller
source: Cura.SidebarController.activeComponentPath
model: Cura.SidebarViewModel { }
delegate: Loader
{
id: delegate
asynchronous: true
visible: model.active
// dynamically get the component from the sidebar controller or set the default sidebar
sourceComponent: {
if (model.id !== "default") {
return Cura.SidebarController.getSidebarComponent(model.id)
} else {
return defaultSidebar
}
}
}
}
}
Rectangle
@ -434,6 +453,27 @@ UM.MainWindow
}
}
// This is the default sidebar view.
// It is used as sourceComponent for the default sidebar view.
Component
{
id: defaultSidebar
Sidebar
{
// anchors {
// top: parent.top
// bottom: parent.bottom
// left: parent.left
// right: parent.right
// }
//
// width: parent.width
//
// monitoringPrint: base.showPrintMonitor
}
}
UM.PreferencesDialog
{
id: preferences

View file

@ -1,21 +0,0 @@
// 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
}