Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Ha <jackha@gmail.com>2018-03-21 18:55:58 +0300
committerJack Ha <jackha@gmail.com>2018-03-21 18:55:58 +0300
commitd8d226c0d654b3dbfc05e800785a013db8cc1642 (patch)
treeef02946d9320718f901bed495cb2f339eec1f94e /plugins/ModelChecker
parent25bf7a6ababeaee3428924a25bc2f748897db817 (diff)
CURA-4557 it's now a small button next to the job spec when one of the warping materials is selected
Diffstat (limited to 'plugins/ModelChecker')
-rw-r--r--plugins/ModelChecker/ModelChecker.py138
-rw-r--r--plugins/ModelChecker/ModelChecker.qml47
-rw-r--r--plugins/ModelChecker/__init__.py15
-rw-r--r--plugins/ModelChecker/model_checker.svg6
4 files changed, 151 insertions, 55 deletions
diff --git a/plugins/ModelChecker/ModelChecker.py b/plugins/ModelChecker/ModelChecker.py
index afe8a7e47d..285002deda 100644
--- a/plugins/ModelChecker/ModelChecker.py
+++ b/plugins/ModelChecker/ModelChecker.py
@@ -1,13 +1,16 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import QTimer
-from cura.Scene.CuraSceneNode import CuraSceneNode
+import os
+
+from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, pyqtProperty
from UM.Application import Application
-from UM.Tool import Tool
+from UM.Extension import Extension
+from UM.Logger import Logger
from UM.Message import Message
from UM.i18n import i18nCatalog
+from UM.PluginRegistry import PluginRegistry
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
catalog = i18nCatalog("cura")
@@ -17,35 +20,34 @@ SHRINKAGE_THRESHOLD = 0.5
WARNING_SIZE_XY = 150
WARNING_SIZE_Z = 100
+# Use this when actual shrinkage data is not in fdm_materials yet
+MATERIALS_LOOKUP = {
+ "generic_abs": 1,
+ "generic_pc": 1,
+ "generic_pp": 1,
+ "generic_cpe_plus": 1
+}
+
+
+class ModelChecker(QObject, Extension):
+
+ needCheckChanged = pyqtSignal()
-class ModelChecker(Tool):
def __init__(self):
super().__init__()
- self._last_known_tool_id = None
+ self._button_view = None
+ self._need_checks = False
- self._controller.activeToolChanged.connect(self._onActiveToolChanged)
+ Application.getInstance().initializationFinished.connect(self.bindSignals)
- def checkObjects(self, nodes_to_check):
- warning_nodes = []
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack is None:
- return []
- material_shrinkage = {}
- need_check = False
+ def bindSignals(self):
+ Application.getInstance().getMachineManager().rootMaterialChanged.connect(self._onChanged)
- # Get all shrinkage values of materials used
- for extruder_position, extruder in global_container_stack.extruders.items():
- shrinkage = extruder.material.getProperty("material_shrinkage_percentage", "value")
- if shrinkage is None:
- shrinkage = 0
- if shrinkage > SHRINKAGE_THRESHOLD:
- need_check = True
- material_shrinkage[extruder_position] = shrinkage
+ def checkObjectsForShrinkage(self, nodes_to_check):
+ material_shrinkage = self.getMaterialShrinkage()
- # Check if we can bail out fast
- if not need_check:
- return
+ warning_nodes = []
# Check node material shrinkage and bounding box size
for node in nodes_to_check:
@@ -64,7 +66,7 @@ class ModelChecker(Tool):
for node in DepthFirstIterator(scene.getRoot()):
if node.callDecoration("isSliceable"):
nodes_to_check.append(node)
- return self.checkObjects(nodes_to_check)
+ return self.checkObjectsForShrinkage(nodes_to_check)
## Display warning message
def showWarningMessage(self, warning_nodes):
@@ -82,23 +84,77 @@ class ModelChecker(Tool):
def showHappyMessage(self):
happy_message = Message(catalog.i18nc(
"@info:status",
- "The Model Checker did not detect any problems with your model / print setup combination."),
+ "The Model Checker did not detect any problems with your model / chosen materials combination."),
lifetime = 5,
title = catalog.i18nc("@info:title", "Model Checker"))
happy_message.show()
- def _onActiveToolChanged(self):
- active_tool = self.getController().getActiveTool()
- if active_tool is None:
- return
- active_tool_id = active_tool.getPluginId()
- if active_tool_id != self.getPluginId():
- self._last_known_tool_id = active_tool_id
- if active_tool_id == self.getPluginId():
- warning_nodes = self.checkAllSliceableNodes()
- if warning_nodes:
- self.showWarningMessage(warning_nodes)
- else:
- self.showHappyMessage()
- if self._last_known_tool_id is not None:
- self.getController().setActiveTool(self._last_known_tool_id)
+ ## Creates the view used by show popup. The view is saved because of the fairly aggressive garbage collection.
+ def _createView(self):
+ Logger.log("d", "Creating model checker view.")
+
+ # Create the plugin dialog component
+ path = os.path.join(PluginRegistry.getInstance().getPluginPath("ModelChecker"), "ModelChecker.qml")
+ self._button_view = Application.getInstance().createQmlComponent(path, {"manager": self})
+
+ # The qml is only the button
+ Application.getInstance().addAdditionalComponent("jobSpecsButton", self._button_view)
+
+ Logger.log("d", "Model checker view created.")
+
+ def _onChanged(self, *args):
+ if self._button_view is None:
+ self._createView()
+ old_need_checks = self._need_checks
+ self._need_checks = self.calculateNeedCheck()
+ if old_need_checks != self._need_checks:
+ self.needCheckChanged.emit()
+
+ @pyqtSlot()
+ def runChecks(self):
+ warning_nodes = self.checkAllSliceableNodes()
+ if warning_nodes:
+ self.showWarningMessage(warning_nodes)
+ else:
+ self.showHappyMessage()
+
+ # TODO: use this if branch feature_model_check is merged in fdm_materials to master
+ # def getMaterialShrinkage(self):
+ # global_container_stack = Application.getInstance().getGlobalContainerStack()
+ # if global_container_stack is None:
+ # return {}
+ #
+ # material_shrinkage = {}
+ # # Get all shrinkage values of materials used
+ # for extruder_position, extruder in global_container_stack.extruders.items():
+ # shrinkage = extruder.material.getProperty("material_shrinkage_percentage", "value")
+ # if shrinkage is None:
+ # shrinkage = 0
+ # material_shrinkage[extruder_position] = shrinkage
+ # return material_shrinkage
+
+ def getMaterialShrinkage(self):
+ global_container_stack = Application.getInstance().getGlobalContainerStack()
+ if global_container_stack is None:
+ return {}
+
+ material_shrinkage = {}
+ # Get all shrinkage values of materials used
+ for extruder_position, extruder in global_container_stack.extruders.items():
+ base_file = extruder.material.getMetaDataEntry("base_file")
+ shrinkage = MATERIALS_LOOKUP.get(base_file, 0)
+ material_shrinkage[extruder_position] = shrinkage
+ return material_shrinkage
+
+ @pyqtProperty(bool, notify = needCheckChanged)
+ def needCheck(self):
+ return self._need_checks
+
+ def calculateNeedCheck(self):
+ need_check = False
+
+ for shrinkage in self.getMaterialShrinkage().values():
+ if shrinkage > SHRINKAGE_THRESHOLD:
+ need_check = True
+
+ return need_check
diff --git a/plugins/ModelChecker/ModelChecker.qml b/plugins/ModelChecker/ModelChecker.qml
new file mode 100644
index 0000000000..77a483c2c6
--- /dev/null
+++ b/plugins/ModelChecker/ModelChecker.qml
@@ -0,0 +1,47 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 1.1
+import QtQuick.Controls.Styles 1.1
+import QtQuick.Layouts 1.1
+import QtQuick.Dialogs 1.1
+import QtQuick.Window 2.2
+
+import UM 1.2 as UM
+import Cura 1.0 as Cura
+
+
+Button
+{
+ id: modelCheckerButton
+
+ UM.I18nCatalog{id: catalog; name:"cura"}
+
+ visible: manager.needCheck
+ tooltip: catalog.i18nc("@info:tooltip", "Check current setup for known problems.")
+ onClicked: manager.runChecks()
+
+ //anchors.leftMargin: UM.Theme.getSize("default_margin").width
+
+ //anchors.right: parent.right
+ //anchors.verticalCenter: parent.verticalCenter
+ width: UM.Theme.getSize("save_button_specs_icons").width
+ height: UM.Theme.getSize("save_button_specs_icons").height
+
+ style: ButtonStyle
+ {
+ background: Item
+ {
+ UM.RecolorImage
+ {
+ width: UM.Theme.getSize("save_button_specs_icons").width;
+ height: UM.Theme.getSize("save_button_specs_icons").height;
+ sourceSize.width: width;
+ sourceSize.height: width;
+ color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene");
+ source: "model_checker.svg"
+ }
+ }
+ }
+}
diff --git a/plugins/ModelChecker/__init__.py b/plugins/ModelChecker/__init__.py
index b2b8587a7a..5f4d443729 100644
--- a/plugins/ModelChecker/__init__.py
+++ b/plugins/ModelChecker/__init__.py
@@ -1,21 +1,14 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# This example is released under the terms of the AGPLv3 or higher.
from . import ModelChecker
from UM.i18n import i18nCatalog
-i18n_catalog = i18nCatalog("uranium")
+i18n_catalog = i18nCatalog("cura")
def getMetaData():
- return {
- "tool": {
- "name": i18n_catalog.i18nc("@label", "Model Checker"),
- "description": i18n_catalog.i18nc("@info:tooltip", "Checks models and print configuration for possible printing issues and give suggestions."),
- "icon": "model_checker.svg",
- "weight": 10
- }
- }
+ return {}
def register(app):
- return { "tool": ModelChecker.ModelChecker() }
+ return { "extension": ModelChecker.ModelChecker() }
diff --git a/plugins/ModelChecker/model_checker.svg b/plugins/ModelChecker/model_checker.svg
index ca5228155a..5b9dd4d197 100644
--- a/plugins/ModelChecker/model_checker.svg
+++ b/plugins/ModelChecker/model_checker.svg
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="30px" height="30px" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ModelChecker</title>
- <g id="ModelChecker" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <polygon id="Rectangle-3" fill="#000000" points="19 11 30 8 30 24 19 27"></polygon>
+ <g id="ModelChecker" stroke="none" fill="none">
+ <polygon fill="#000000" points="19 11 30 8 30 24 19 27"></polygon>
<path d="M10,19 C5.581722,19 2,15.418278 2,11 C2,6.581722 5.581722,3 10,3 C14.418278,3 18,6.581722 18,11 C18,15.418278 14.418278,19 10,19 Z M10,17 C13.3137085,17 16,14.3137085 16,11 C16,7.6862915 13.3137085,5 10,5 C6.6862915,5 4,7.6862915 4,11 C4,14.3137085 6.6862915,17 10,17 Z" id="Combined-Shape" fill="#000000"></path>
- <polygon id="Polygon" fill="#000000" points="4.2 15 6 16.8 1.8 21 0 19.2"></polygon>
+ <polygon fill="#000000" points="4.2 15 6 16.8 1.8 21 0 19.2"></polygon>
<path d="M18.7333454,8.81666365 C18.2107269,6.71940704 16.9524304,4.91317986 15.248379,3.68790525 L18,3 L30,6 L18.7333454,8.81666365 Z M17,16.6573343 L17,27 L6,24 L6,19.0644804 C7.20495897,19.6632939 8.56315852,20 10,20 C12.8272661,20 15.3500445,18.6963331 17,16.6573343 Z" id="Combined-Shape" fill="#000000"></path>
</g>
</svg>