From 0cf46ca48ecab544c0441808fb916406d750de1e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 23 Jun 2018 16:14:50 +0200 Subject: [PATCH 01/10] Changed SettingView to show custom menu items --- resources/qml/Settings/SettingView.qml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 1b3f0cbc20..30160cb5fb 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -561,6 +561,27 @@ Item visible: machineExtruderCount.properties.value > 1 } + Instantiator + { + id: customMenuItems + model: Cura.SidebarCustomMenuItemsModel { } + MenuItem + { + text: model.name + onTriggered: + { + customMenuItems.model.callMenuItemMethod(name, model.actions) + } + } + onObjectAdded: contextMenu.insertItem(index, object) + onObjectRemoved: contextMenu.removeItem(object) + } + + MenuSeparator + { + visible: customMenuItems.count > 0 + } + MenuItem { //: Settings context menu action From 0906e3f1e79d74736b96cd5c0dbd7158c0f70b2f Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 23 Jun 2018 16:16:06 +0200 Subject: [PATCH 02/10] Store custom Menu items in CuraApplication --- cura/CuraApplication.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 08f267d0e1..e5562745de 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -101,6 +101,7 @@ from cura.Settings.UserChangesModel import UserChangesModel from cura.Settings.ExtrudersModel import ExtrudersModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.ContainerManager import ContainerManager +from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel from cura.ObjectsModel import ObjectsModel @@ -219,6 +220,8 @@ class CuraApplication(QtApplication): self._need_to_show_user_agreement = True + self._sidebar_custom_menu_items = [] # type: list # Keeps list of custom menu items for the side bar + # Backups self._auto_save = None self._save_data_enabled = True @@ -943,6 +946,7 @@ class CuraApplication(QtApplication): qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel") qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.getInstance) + qmlRegisterType(SidebarCustomMenuItemsModel, "Cura", 1, 0, "SidebarCustomMenuItemsModel") # 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"))) @@ -1729,3 +1733,10 @@ class CuraApplication(QtApplication): @pyqtSlot() def showMoreInformationDialogForAnonymousDataCollection(self): self._plugin_registry.getPluginObject("SliceInfoPlugin").showMoreInfoDialog() + + + def addSidebarCustomMenuItem(self, menu_item: list) -> None: + self._sidebar_custom_menu_items.append(menu_item) + + def getSidebarCustomMenuItems(self) -> list: + return self._sidebar_custom_menu_items \ No newline at end of file From f577789859952ca1bfcd607268583b0ef650dd6d Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 23 Jun 2018 16:22:33 +0200 Subject: [PATCH 03/10] Added extra SettingsModel for a QML --- cura/Settings/SidebarCustomMenuItemsModel.py | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 cura/Settings/SidebarCustomMenuItemsModel.py diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py new file mode 100644 index 0000000000..71abb0d2ed --- /dev/null +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -0,0 +1,32 @@ +from UM.Qt.ListModel import ListModel +from PyQt5.QtCore import pyqtSlot, Qt + +class SidebarCustomMenuItemsModel(ListModel): + NameRole = Qt.UserRole + 1 + ActionsRole = Qt.UserRole + 2 + MenuItemRole = Qt.UserRole + 3 + + def __init__(self, parent=None): + super().__init__(parent) + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.ActionsRole, "actions") + self.addRoleName(self.MenuItemRole, "menu_item") + self._updateExtensionList() + + def _updateExtensionList(self)-> None: + from cura.CuraApplication import CuraApplication + for menu_item in CuraApplication.getInstance().getSidebarCustomMenuItems(): + + self.appendItem({ + "name": menu_item["name"], + "actions": menu_item["actions"], + "menu_item": menu_item["menu_item"] + }) + + @pyqtSlot(str, "QVariantList") + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list)-> None: + for item in self._items: + if menu_item_name == item["name"]: + for method in menu_item_actions: + getattr(item["menu_item"], method)() + break \ No newline at end of file From c4fa50a8fc1ffd9879b973d61a7ab9dfad7c9405 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 25 Jun 2018 16:51:40 +0200 Subject: [PATCH 04/10] Added icon for custom Menu items --- cura/Settings/SidebarCustomMenuItemsModel.py | 9 ++++++--- resources/qml/Settings/SettingView.qml | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py index 71abb0d2ed..8c82d288bf 100644 --- a/cura/Settings/SidebarCustomMenuItemsModel.py +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -5,12 +5,14 @@ class SidebarCustomMenuItemsModel(ListModel): NameRole = Qt.UserRole + 1 ActionsRole = Qt.UserRole + 2 MenuItemRole = Qt.UserRole + 3 + MenuItemIconNameRole = Qt.UserRole + 5 def __init__(self, parent=None): super().__init__(parent) self.addRoleName(self.NameRole, "name") self.addRoleName(self.ActionsRole, "actions") self.addRoleName(self.MenuItemRole, "menu_item") + self.addRoleName(self.MenuItemIconNameRole, "iconName") self._updateExtensionList() def _updateExtensionList(self)-> None: @@ -19,14 +21,15 @@ class SidebarCustomMenuItemsModel(ListModel): self.appendItem({ "name": menu_item["name"], + "iconName": menu_item["iconName"], "actions": menu_item["actions"], "menu_item": menu_item["menu_item"] }) - @pyqtSlot(str, "QVariantList") - def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list)-> None: + @pyqtSlot(str, "QVariantList", "QVariantMap") + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs)-> None: for item in self._items: if menu_item_name == item["name"]: for method in menu_item_actions: - getattr(item["menu_item"], method)() + getattr(item["menu_item"], method)(kwargs) break \ No newline at end of file diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 30160cb5fb..88876123fe 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -568,9 +568,10 @@ Item MenuItem { text: model.name + iconName: model.iconName onTriggered: { - customMenuItems.model.callMenuItemMethod(name, model.actions) + customMenuItems.model.callMenuItemMethod(name, model.actions, {"key": contextMenu.key}) } } onObjectAdded: contextMenu.insertItem(index, object) From bf219c382170fe8502ba4810d0b9200714d21cbc Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 26 Jul 2018 13:54:35 +0200 Subject: [PATCH 05/10] Added typing CURA-5595 --- cura/Settings/SidebarCustomMenuItemsModel.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py index 8c82d288bf..d2a4d1a2b1 100644 --- a/cura/Settings/SidebarCustomMenuItemsModel.py +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -1,6 +1,12 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import Any + from UM.Qt.ListModel import ListModel from PyQt5.QtCore import pyqtSlot, Qt + class SidebarCustomMenuItemsModel(ListModel): NameRole = Qt.UserRole + 1 ActionsRole = Qt.UserRole + 2 @@ -27,7 +33,7 @@ class SidebarCustomMenuItemsModel(ListModel): }) @pyqtSlot(str, "QVariantList", "QVariantMap") - def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs)-> None: + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs: Any)-> None: for item in self._items: if menu_item_name == item["name"]: for method in menu_item_actions: From 4912073aedc795c2aa51cc1e858190be0cd328a1 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 9 Aug 2018 15:14:55 +0200 Subject: [PATCH 06/10] Add API abstraction layer Contributes to CURA-5595 --- cura/API/SidebarContextMenu.py | 34 ++++++++++++++++++++++++++++++++++ cura/API/__init__.py | 4 ++++ 2 files changed, 38 insertions(+) create mode 100644 cura/API/SidebarContextMenu.py diff --git a/cura/API/SidebarContextMenu.py b/cura/API/SidebarContextMenu.py new file mode 100644 index 0000000000..9c7ad4c4b6 --- /dev/null +++ b/cura/API/SidebarContextMenu.py @@ -0,0 +1,34 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from cura.CuraApplication import CuraApplication + +## The back-ups API provides a version-proof bridge between Cura's +# Sidebar Context Menu and plug-ins that hook into it. +# +# Usage: +# ``from cura.API import CuraAPI +# api = CuraAPI() +# api.sidebar_context_menu.getSidebarMenuItems() +# menu_actions = [] +# menu_actions.append("sidebarMenuItemOnClickHander") +# data = { +# "name": "My Plugin Action", +# "iconName": "my-plugin-icon", +# "actions": menu_actions, +# "menu_item": MyPluginAction(self) +# } +# api.sidebar_context_menu.addSidebarMenuItems([])`` +class SidebarContextMenu: + + _application = CuraApplication.getInstance() # type: CuraApplication + + ## Add items to the sidebar context menu. + # \param menu_item dict containing the menu item to add. + def addSidebarMenuItem(self, menu_items: dict) -> None: + self._application.addSidebarCustomMenuItem(menu_items) + + ## Get all custom items currently added to the sidebar context menu. + # \return List containing all custom context menu items. + def getSidebarMenuItems(self) -> list: + return self._application.getSidebarCustomMenuItems() \ No newline at end of file diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 13f6722336..40c07b8371 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from UM.PluginRegistry import PluginRegistry from cura.API.Backups import Backups +from cura.API.SidebarContextMenu import SidebarContextMenu ## The official Cura API that plug-ins can use to interact with Cura. # @@ -16,3 +17,6 @@ class CuraAPI: # Backups API. backups = Backups() + + # Sidebar Context Menu API + sidebar_context_menu = SidebarContextMenu() From 3217085ebedbdfb0cd763db9c37bca4df2816b07 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 9 Aug 2018 15:20:53 +0200 Subject: [PATCH 07/10] Fix plural Contributes to CURA-5595 --- cura/API/SidebarContextMenu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/API/SidebarContextMenu.py b/cura/API/SidebarContextMenu.py index 9c7ad4c4b6..fdd2d3ed88 100644 --- a/cura/API/SidebarContextMenu.py +++ b/cura/API/SidebarContextMenu.py @@ -25,8 +25,8 @@ class SidebarContextMenu: ## Add items to the sidebar context menu. # \param menu_item dict containing the menu item to add. - def addSidebarMenuItem(self, menu_items: dict) -> None: - self._application.addSidebarCustomMenuItem(menu_items) + def addSidebarMenuItem(self, menu_item: dict) -> None: + self._application.addSidebarCustomMenuItem(menu_item) ## Get all custom items currently added to the sidebar context menu. # \return List containing all custom context menu items. From 88c4240e3b06a64d6c021cb5f9756a66d3e71e2b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 9 Aug 2018 15:21:38 +0200 Subject: [PATCH 08/10] Remove back-ups traces Contributes to CURA-5595 --- cura/API/SidebarContextMenu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/API/SidebarContextMenu.py b/cura/API/SidebarContextMenu.py index fdd2d3ed88..f47b3a062a 100644 --- a/cura/API/SidebarContextMenu.py +++ b/cura/API/SidebarContextMenu.py @@ -3,7 +3,7 @@ from cura.CuraApplication import CuraApplication -## The back-ups API provides a version-proof bridge between Cura's +## The sidebar context menu API provides a version-proof bridge between Cura's # Sidebar Context Menu and plug-ins that hook into it. # # Usage: From 6d237b09e842b9930d377f3b039a869d0de1acd7 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 10 Aug 2018 16:08:54 +0200 Subject: [PATCH 09/10] Proposed improvement on API naming --- cura/API/{SidebarContextMenu.py => Sidebar.py} | 12 ++++++------ cura/API/__init__.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) rename cura/API/{SidebarContextMenu.py => Sidebar.py} (77%) diff --git a/cura/API/SidebarContextMenu.py b/cura/API/Sidebar.py similarity index 77% rename from cura/API/SidebarContextMenu.py rename to cura/API/Sidebar.py index f47b3a062a..dd001739f5 100644 --- a/cura/API/SidebarContextMenu.py +++ b/cura/API/Sidebar.py @@ -9,26 +9,26 @@ from cura.CuraApplication import CuraApplication # Usage: # ``from cura.API import CuraAPI # api = CuraAPI() -# api.sidebar_context_menu.getSidebarMenuItems() +# api.sidebar.getContextMenuItems() # menu_actions = [] -# menu_actions.append("sidebarMenuItemOnClickHander") +# menu_actions.append("sidebarMenuItemOnClickHandler") # data = { # "name": "My Plugin Action", # "iconName": "my-plugin-icon", # "actions": menu_actions, # "menu_item": MyPluginAction(self) # } -# api.sidebar_context_menu.addSidebarMenuItems([])`` -class SidebarContextMenu: +# api.sidebar.addContextMenuItem(data)`` +class Sidebar: _application = CuraApplication.getInstance() # type: CuraApplication ## Add items to the sidebar context menu. # \param menu_item dict containing the menu item to add. - def addSidebarMenuItem(self, menu_item: dict) -> None: + def addContextMenuItem(self, menu_item: dict) -> None: self._application.addSidebarCustomMenuItem(menu_item) ## Get all custom items currently added to the sidebar context menu. # \return List containing all custom context menu items. - def getSidebarMenuItems(self) -> list: + def getContextMenuItems(self) -> list: return self._application.getSidebarCustomMenuItems() \ No newline at end of file diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 40c07b8371..4cd0c9436a 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from UM.PluginRegistry import PluginRegistry from cura.API.Backups import Backups -from cura.API.SidebarContextMenu import SidebarContextMenu +from cura.API.Sidebar import Sidebar ## The official Cura API that plug-ins can use to interact with Cura. # @@ -19,4 +19,4 @@ class CuraAPI: backups = Backups() # Sidebar Context Menu API - sidebar_context_menu = SidebarContextMenu() + sidebar = Sidebar() From 16db29761327adbd9d8463debf3b7bc69d3a0c04 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 10 Aug 2018 16:28:02 +0200 Subject: [PATCH 10/10] Some final tweaks Contributes to CURA-5595 --- cura/API/Backups.py | 1 + .../API/{Sidebar.py => Interface/Settings.py} | 21 ++++++++-------- cura/API/Interface/__init__.py | 24 +++++++++++++++++++ cura/API/__init__.py | 9 +++---- 4 files changed, 40 insertions(+), 15 deletions(-) rename cura/API/{Sidebar.py => Interface/Settings.py} (56%) create mode 100644 cura/API/Interface/__init__.py diff --git a/cura/API/Backups.py b/cura/API/Backups.py index 5964557264..f31933c844 100644 --- a/cura/API/Backups.py +++ b/cura/API/Backups.py @@ -13,6 +13,7 @@ from cura.Backups.BackupsManager import BackupsManager # api = CuraAPI() # api.backups.createBackup() # api.backups.restoreBackup(my_zip_file, {"cura_release": "3.1"})`` + class Backups: manager = BackupsManager() # Re-used instance of the backups manager. diff --git a/cura/API/Sidebar.py b/cura/API/Interface/Settings.py similarity index 56% rename from cura/API/Sidebar.py rename to cura/API/Interface/Settings.py index dd001739f5..2889db7022 100644 --- a/cura/API/Sidebar.py +++ b/cura/API/Interface/Settings.py @@ -3,32 +3,31 @@ from cura.CuraApplication import CuraApplication -## The sidebar context menu API provides a version-proof bridge between Cura's -# Sidebar Context Menu and plug-ins that hook into it. +## The Interface.Settings API provides a version-proof bridge between Cura's +# (currently) sidebar UI and plug-ins that hook into it. # # Usage: # ``from cura.API import CuraAPI # api = CuraAPI() -# api.sidebar.getContextMenuItems() -# menu_actions = [] -# menu_actions.append("sidebarMenuItemOnClickHandler") +# api.interface.settings.getContextMenuItems() # data = { # "name": "My Plugin Action", # "iconName": "my-plugin-icon", -# "actions": menu_actions, +# "actions": my_menu_actions, # "menu_item": MyPluginAction(self) # } -# api.sidebar.addContextMenuItem(data)`` -class Sidebar: +# api.interface.settings.addContextMenuItem(data)`` - _application = CuraApplication.getInstance() # type: CuraApplication +class Settings: + # Re-used instance of Cura: + application = CuraApplication.getInstance() # type: CuraApplication ## Add items to the sidebar context menu. # \param menu_item dict containing the menu item to add. def addContextMenuItem(self, menu_item: dict) -> None: - self._application.addSidebarCustomMenuItem(menu_item) + self.application.addSidebarCustomMenuItem(menu_item) ## Get all custom items currently added to the sidebar context menu. # \return List containing all custom context menu items. def getContextMenuItems(self) -> list: - return self._application.getSidebarCustomMenuItems() \ No newline at end of file + return self.application.getSidebarCustomMenuItems() \ No newline at end of file diff --git a/cura/API/Interface/__init__.py b/cura/API/Interface/__init__.py new file mode 100644 index 0000000000..b38118949b --- /dev/null +++ b/cura/API/Interface/__init__.py @@ -0,0 +1,24 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.PluginRegistry import PluginRegistry +from cura.API.Interface.Settings import Settings + +## The Interface class serves as a common root for the specific API +# methods for each interface element. +# +# Usage: +# ``from cura.API import CuraAPI +# api = CuraAPI() +# api.interface.settings.addContextMenuItem() +# api.interface.viewport.addOverlay() # Not implemented, just a hypothetical +# api.interface.toolbar.getToolButtonCount() # Not implemented, just a hypothetical +# # etc.`` + +class Interface: + + # For now we use the same API version to be consistent. + VERSION = PluginRegistry.APIVersion + + # API methods specific to the settings portion of the UI + settings = Settings() diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 4cd0c9436a..64d636903d 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from UM.PluginRegistry import PluginRegistry from cura.API.Backups import Backups -from cura.API.Sidebar import Sidebar +from cura.API.Interface import Interface ## The official Cura API that plug-ins can use to interact with Cura. # @@ -10,13 +10,14 @@ from cura.API.Sidebar import Sidebar # this API provides a version-safe interface with proper deprecation warnings # etc. Usage of any other methods than the ones provided in this API can cause # plug-ins to be unstable. + class CuraAPI: # For now we use the same API version to be consistent. VERSION = PluginRegistry.APIVersion - # Backups API. + # Backups API backups = Backups() - # Sidebar Context Menu API - sidebar = Sidebar() + # Interface API + interface = Interface()