mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-16 03:07:53 -06:00
Implement switching sidebar views
This commit is contained in:
parent
3c863fc388
commit
caf56587fe
8 changed files with 121 additions and 72 deletions
|
@ -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._currently_loading_files = []
|
||||||
self._non_sliceable_extensions = []
|
self._non_sliceable_extensions = []
|
||||||
|
|
||||||
|
@ -221,14 +225,6 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
|
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([
|
self.setRequiredPlugins([
|
||||||
"CuraEngineBackend",
|
"CuraEngineBackend",
|
||||||
"UserAgreement",
|
"UserAgreement",
|
||||||
|
@ -327,11 +323,6 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
self._need_to_show_user_agreement = not Preferences.getInstance().getValue("general/accepted_user_agreement")
|
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 [
|
for key in [
|
||||||
"dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin
|
"dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin
|
||||||
"dialog_profile_path",
|
"dialog_profile_path",
|
||||||
|
@ -737,6 +728,10 @@ class CuraApplication(QtApplication):
|
||||||
if not run_headless:
|
if not run_headless:
|
||||||
self.initializeEngine()
|
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:
|
if run_headless or self._engine.rootObjects:
|
||||||
self.closeSplash()
|
self.closeSplash()
|
||||||
|
|
||||||
|
@ -1324,6 +1319,19 @@ class CuraApplication(QtApplication):
|
||||||
def _addProfileWriter(self, profile_writer):
|
def _addProfileWriter(self, profile_writer):
|
||||||
pass
|
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")
|
@pyqtSlot("QSize")
|
||||||
def setMinimumWindowSize(self, size):
|
def setMinimumWindowSize(self, size):
|
||||||
self.getMainWindow().setMinimumSize(size)
|
self.getMainWindow().setMinimumSize(size)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
import os.path
|
from PyQt5.QtCore import QObject
|
||||||
from PyQt5.QtCore import QObject, QUrl
|
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
from cura.Sidebar.SidebarView import SidebarView
|
from cura.Sidebar.SidebarView import SidebarView
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -19,11 +19,10 @@ class SettingsSidebarView(QObject, SidebarView):
|
||||||
def getMetaData(self):
|
def getMetaData(self):
|
||||||
return {
|
return {
|
||||||
"sidebar_view": {
|
"sidebar_view": {
|
||||||
"name": i18n_catalog.i18nc("", "Print settings"),
|
"name": i18n_catalog.i18nc("@item:inmenu", "Print settings"),
|
||||||
"weight": 0
|
"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 getComponent(self):
|
||||||
def getComponentPath(self):
|
return None
|
||||||
return QUrl("SidebarSettings.qml")
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.Preferences import Preferences
|
||||||
from UM.Signal import Signal
|
from UM.Signal import Signal
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
|
||||||
|
@ -52,5 +53,7 @@ class SidebarController:
|
||||||
|
|
||||||
## Change the active sidebar view to one of the registered views.
|
## Change the active sidebar view to one of the registered views.
|
||||||
def setActiveSidebarView(self, sidebar_view_id: str):
|
def setActiveSidebarView(self, sidebar_view_id: str):
|
||||||
self._active_sidebar_view = self._sidebar_views[sidebar_view_id]
|
if sidebar_view_id in self._sidebar_views:
|
||||||
self.activeSidebarViewChanged.emit()
|
self._active_sidebar_view = self._sidebar_views[sidebar_view_id]
|
||||||
|
Preferences.getInstance().setValue("cura/active_sidebar_view", sidebar_view_id)
|
||||||
|
self.activeSidebarViewChanged.emit()
|
||||||
|
|
|
@ -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.
|
## 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):
|
class SidebarControllerProxy(QObject):
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._controller = Application.getInstance().getSidebarController()
|
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()
|
activeSidebarViewChanged = pyqtSignal()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def createSidebarControllerProxy(self, engine, script_engine):
|
def createSidebarControllerProxy(self, engine, script_engine):
|
||||||
return SidebarControllerProxy()
|
return SidebarControllerProxy()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtProperty(str, notify = activeSidebarViewChanged)
|
||||||
def setActiveView(self, sidebar_view):
|
def activeSidebarId(self):
|
||||||
self._controller.setActiveSidebarView(sidebar_view)
|
if self._controller.getActiveSidebarView() is not None:
|
||||||
|
return self._controller.getActiveSidebarView().getPluginId()
|
||||||
|
else:
|
||||||
|
return "default"
|
||||||
|
|
||||||
@pyqtProperty(QUrl, notify = activeSidebarViewChanged)
|
@pyqtSlot(str)
|
||||||
def activeComponentPath(self):
|
def setActiveSidebarView(self, sidebar_view_id):
|
||||||
if not self._controller.getActiveSidebarView():
|
Logger.log("d", "Setting active sidebar view to %s", sidebar_view_id)
|
||||||
return QUrl()
|
self._controller.setActiveSidebarView(sidebar_view_id)
|
||||||
return self._controller.getActiveSidebarView().getComponentPath()
|
|
||||||
|
|
||||||
@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):
|
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()
|
self.activeSidebarViewChanged.emit()
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# 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.Logger import Logger
|
||||||
from UM.PluginObject import PluginObject
|
from UM.PluginObject import PluginObject
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
@ -14,11 +15,21 @@ class SidebarView(PluginObject):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._view = None
|
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
|
## Get the path to the component QML file as QUrl
|
||||||
def getComponentPath(self):
|
def getComponentPath(self):
|
||||||
try:
|
try:
|
||||||
|
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
|
||||||
sidebar_component_file_path = PluginRegistry.getInstance().getMetaData(self.getPluginId())["sidebar_view"]["sidebar_component"]
|
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:
|
except KeyError:
|
||||||
Logger.log("w", "Could not find sidebar component QML file for %s", self.getPluginId())
|
Logger.log("w", "Could not find sidebar component QML file for %s", self.getPluginId())
|
||||||
return QUrl()
|
return ""
|
||||||
|
|
|
@ -26,17 +26,18 @@ class SidebarViewModel(ListModel):
|
||||||
## Update the model when new views are added or another view is made the active view.
|
## Update the model when new views are added or another view is made the active view.
|
||||||
def _onSidebarViewsChanged(self):
|
def _onSidebarViewsChanged(self):
|
||||||
items = []
|
items = []
|
||||||
|
current_view_id = None
|
||||||
|
|
||||||
sidebar_views = self._controller.getAllSidebarViews()
|
sidebar_views = self._controller.getAllSidebarViews()
|
||||||
current_view = self._controller.getActiveSidebarView()
|
current_view = self._controller.getActiveSidebarView()
|
||||||
|
if current_view:
|
||||||
|
current_view_id = current_view.getPluginId()
|
||||||
|
|
||||||
for sidebar_view_id, sidebar_view in sidebar_views.items():
|
for sidebar_view_id, sidebar_view in sidebar_views.items():
|
||||||
plugin_metadata = PluginRegistry.getInstance().getMetaData(sidebar_view_id)
|
if sidebar_view_id != "default":
|
||||||
if plugin_metadata:
|
sidebar_view_metadata = PluginRegistry.getInstance().getMetaData(sidebar_view_id).get("sidebar_view", {})
|
||||||
# Check if the registered view came from a plugin and extract the metadata if so.
|
|
||||||
sidebar_view_metadata = plugin_metadata.get("sidebar_view", {})
|
|
||||||
else:
|
else:
|
||||||
# Get the meta data directly from the plugin
|
sidebar_view_metadata = sidebar_view.getMetaData().get("sidebar_view", {})
|
||||||
sidebar_view_metadata = sidebar_view.getMetaData()
|
|
||||||
|
|
||||||
# Skip view modes that are marked as not visible
|
# Skip view modes that are marked as not visible
|
||||||
if "visible" in sidebar_view_metadata and not sidebar_view_metadata["visible"]:
|
if "visible" in sidebar_view_metadata and not sidebar_view_metadata["visible"]:
|
||||||
|
@ -48,7 +49,7 @@ class SidebarViewModel(ListModel):
|
||||||
items.append({
|
items.append({
|
||||||
"id": sidebar_view_id,
|
"id": sidebar_view_id,
|
||||||
"name": name,
|
"name": name,
|
||||||
"active": sidebar_view_id == current_view.getPluginId(),
|
"active": sidebar_view_id == current_view_id,
|
||||||
"weight": weight
|
"weight": weight
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -331,7 +331,7 @@ UM.MainWindow
|
||||||
text: catalog.i18nc("@action:button","Open File");
|
text: catalog.i18nc("@action:button","Open File");
|
||||||
iconSource: UM.Theme.getIcon("load")
|
iconSource: UM.Theme.getIcon("load")
|
||||||
style: UM.Theme.styles.tool_button
|
style: UM.Theme.styles.tool_button
|
||||||
tooltip: '';
|
tooltip: ""
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: topbar.bottom;
|
top: topbar.bottom;
|
||||||
|
@ -366,7 +366,7 @@ UM.MainWindow
|
||||||
onStopMonitoringPrint: base.showPrintMonitor = false
|
onStopMonitoringPrint: base.showPrintMonitor = false
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader
|
Rectangle
|
||||||
{
|
{
|
||||||
id: sidebar
|
id: sidebar
|
||||||
|
|
||||||
|
@ -379,11 +379,30 @@ UM.MainWindow
|
||||||
|
|
||||||
width: UM.Theme.getSize("sidebar").width
|
width: UM.Theme.getSize("sidebar").width
|
||||||
|
|
||||||
// all sidebar components will have access to the show print monitor flag
|
// The sidebarRepeater exposes sidebar views provided by plugins.
|
||||||
property bool showPrintMonitor: base.showPrintMonitor
|
// 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
|
model: Cura.SidebarViewModel { }
|
||||||
source: Cura.SidebarController.activeComponentPath
|
|
||||||
|
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
|
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
|
UM.PreferencesDialog
|
||||||
{
|
{
|
||||||
id: preferences
|
id: preferences
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue