Reworked UI so that it matches 15.04 UI, and made each field in the UI do the same thing that they do in 15.04.

This commit is contained in:
Kurt Loeffler 2016-01-13 20:00:30 -08:00
parent b8cf51349c
commit b28bfc9602
3 changed files with 235 additions and 61 deletions

View file

@ -10,13 +10,13 @@ import UM 1.1 as UM
UM.Dialog
{
width: 250*Screen.devicePixelRatio;
minimumWidth: 250*Screen.devicePixelRatio;
maximumWidth: 250*Screen.devicePixelRatio;
width: 350*Screen.devicePixelRatio;
minimumWidth: 350*Screen.devicePixelRatio;
maximumWidth: 350*Screen.devicePixelRatio;
height: 200*Screen.devicePixelRatio;
minimumHeight: 200*Screen.devicePixelRatio;
maximumHeight: 200*Screen.devicePixelRatio;
height: 220*Screen.devicePixelRatio;
minimumHeight: 220*Screen.devicePixelRatio;
maximumHeight: 220*Screen.devicePixelRatio;
modality: Qt.Modal
@ -30,58 +30,158 @@ UM.Dialog
Layout.fillWidth: true
columnSpacing: 16
rowSpacing: 4
columns: 2
columns: 1
Text {
text: catalog.i18nc("@action:label","Size (mm)")
UM.TooltipArea {
Layout.fillWidth:true
}
TextField {
id: size
focus: true
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 1; top: 500;}
text: "120"
onTextChanged: { manager.onSizeChanged(text) }
height: childrenRect.height
text: catalog.i18nc("@info:tooltip","The maximum distance of each pixel from \"Base.\"")
Row {
width: parent.width
height: childrenRect.height
Text {
text: catalog.i18nc("@action:label","Height (mm)")
width: 150
anchors.verticalCenter: parent.verticalCenter
}
TextField {
id: peak_height
objectName: "Peak_Height"
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: -500; top: 500;}
width: 180
onTextChanged: { manager.onPeakHeightChanged(text) }
}
}
}
Text {
text: catalog.i18nc("@action:label","Base Height (mm)")
UM.TooltipArea {
Layout.fillWidth:true
}
TextField {
id: base_height
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 0; top: 500;}
text: "2"
onTextChanged: { manager.onBaseHeightChanged(text) }
height: childrenRect.height
text: catalog.i18nc("@info:tooltip","The base height from the build plate in millimeters.")
Row {
width: parent.width
height: childrenRect.height
Text {
text: catalog.i18nc("@action:label","Base (mm)")
width: 150
anchors.verticalCenter: parent.verticalCenter
}
TextField {
id: base_height
objectName: "Base_Height"
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 0; top: 500;}
width: 180
onTextChanged: { manager.onBaseHeightChanged(text) }
}
}
}
Text {
text: catalog.i18nc("@action:label","Peak Height (mm)")
UM.TooltipArea {
Layout.fillWidth:true
}
TextField {
id: peak_height
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 0; top: 500;}
text: "12"
onTextChanged: { manager.onPeakHeightChanged(text) }
height: childrenRect.height
text: catalog.i18nc("@info:tooltip","The width in millimeters on the build plate.")
Row {
width: parent.width
height: childrenRect.height
Text {
text: catalog.i18nc("@action:label","Width (mm)")
width: 150
anchors.verticalCenter: parent.verticalCenter
}
TextField {
id: width
objectName: "Width"
focus: true
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 1; top: 500;}
width: 180
onTextChanged: { manager.onWidthChanged(text) }
}
}
}
Text {
text: catalog.i18nc("@action:label","Smoothing")
UM.TooltipArea {
Layout.fillWidth:true
}
Rectangle {
width: 100
height: 20
color: "transparent"
height: childrenRect.height
text: catalog.i18nc("@info:tooltip","The depth in millimeters on the build plate")
Row {
width: parent.width
height: childrenRect.height
Slider {
id: smoothing
maximumValue: 100.0
stepSize: 1.0
value: 1
width: 100
onValueChanged: { manager.onSmoothingChanged(value) }
Text {
text: catalog.i18nc("@action:label","Depth (mm)")
width: 150
anchors.verticalCenter: parent.verticalCenter
}
TextField {
id: depth
objectName: "Depth"
focus: true
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 1; top: 500;}
width: 180
onTextChanged: { manager.onDepthChanged(text) }
}
}
}
UM.TooltipArea {
Layout.fillWidth:true
height: childrenRect.height
text: catalog.i18nc("@info:tooltip","By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh.")
Row {
width: parent.width
height: childrenRect.height
//Empty label so 2 column layout works.
Text {
text: ""
width: 150
anchors.verticalCenter: parent.verticalCenter
}
ComboBox {
id: image_color_invert
objectName: "Image_Color_Invert"
model: [ catalog.i18nc("@action:label","Lighter is higher"), catalog.i18nc("@action:label","Darker is higher") ]
width: 180
onCurrentIndexChanged: { manager.onImageColorInvertChanged(currentIndex) }
}
}
}
UM.TooltipArea {
Layout.fillWidth:true
height: childrenRect.height
text: catalog.i18nc("@info:tooltip","The amount of smoothing to apply to the image.")
Row {
width: parent.width
height: childrenRect.height
Text {
text: catalog.i18nc("@action:label","Smoothing")
width: 150
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: 180
height: 20
Layout.fillWidth:true
color: "transparent"
Slider {
id: smoothing
objectName: "Smoothing"
maximumValue: 100.0
stepSize: 1.0
width: 180
onValueChanged: { manager.onSmoothingChanged(value) }
}
}
}
}
}

View file

@ -23,6 +23,20 @@ class ImageReader(MeshReader):
self._ui = ImageReaderUI(self)
def preRead(self, file_name):
img = QImage(file_name)
if img.isNull():
Logger.log("e", "Image is corrupt.")
return MeshReader.PreReadResult.failed
width = img.width()
depth = img.height()
largest = max(width, depth)
width = width/largest*self._ui.defaultWidth
depth = depth/largest*self._ui.defaultDepth
self._ui.setWidthAndDepth(width, depth)
self._ui.showConfigUI()
self._ui.waitForUIToClose()
@ -31,9 +45,10 @@ class ImageReader(MeshReader):
return MeshReader.PreReadResult.accepted
def read(self, file_name):
return self._generateSceneNode(file_name, self._ui.size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512)
size = max(self._ui.getWidth(), self._ui.getDepth())
return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.image_color_invert)
def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size):
def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, image_color_invert):
mesh = None
scene_node = None
@ -56,9 +71,10 @@ class ImageReader(MeshReader):
img = img.scaled(width, height, Qt.IgnoreAspectRatio)
base_height = max(base_height, 0)
peak_height = max(peak_height, -base_height)
xz_size = max(xz_size, 1)
scale_vector = Vector(xz_size, max(peak_height - base_height, -base_height), xz_size)
scale_vector = Vector(xz_size, peak_height, xz_size)
if width > height:
scale_vector.setZ(scale_vector.z * aspect)
@ -92,6 +108,9 @@ class ImageReader(MeshReader):
Job.yieldThread()
if image_color_invert:
height_data = 1-height_data
for i in range(0, blur_iterations):
copy = numpy.pad(height_data, ((1, 1), (1, 1)), mode='edge')

View file

@ -24,15 +24,32 @@ class ImageReaderUI(QObject):
self._ui_view = None
self.show_config_ui_trigger.connect(self._actualShowConfigUI)
# There are corresponding values for these fields in ConfigUI.qml.
# If you change the values here, consider updating ConfigUI.qml as well.
self.size = 120
self.base_height = 2
self.peak_height = 12
self.defaultWidth = 120
self.defaultDepth = 120
self._aspect = 1
self._width = self.defaultWidth
self._depth = self.defaultDepth
self.base_height = 1
self.peak_height = 10
self.smoothing = 1
self.image_color_invert = False;
self._ui_lock = threading.Lock()
self._cancelled = False
self._disable_size_callbacks = False
def setWidthAndDepth(self, width, depth):
self._aspect = width/depth
self._width = width
self._depth = depth
def getWidth(self):
return self._width
def getDepth(self):
return self._depth
def getCancelled(self):
return self._cancelled
@ -47,10 +64,20 @@ class ImageReaderUI(QObject):
self.show_config_ui_trigger.emit()
def _actualShowConfigUI(self):
self._disable_size_callbacks = True
if self._ui_view is None:
self._createConfigUI()
self._ui_view.show()
self._ui_view.findChild(QObject, "Width").setProperty("text", str(self._width))
self._ui_view.findChild(QObject, "Depth").setProperty("text", str(self._depth))
self._disable_size_callbacks = False
self._ui_view.findChild(QObject, "Base_Height").setProperty("text", str(self.base_height))
self._ui_view.findChild(QObject, "Peak_Height").setProperty("text", str(self.peak_height))
self._ui_view.findChild(QObject, "Smoothing").setProperty("value", self.smoothing)
def _createConfigUI(self):
if self._ui_view is None:
Logger.log("d", "Creating ImageReader config UI")
@ -62,6 +89,8 @@ class ImageReaderUI(QObject):
self._ui_view.setFlags(self._ui_view.flags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowMinimizeButtonHint & ~Qt.WindowMaximizeButtonHint);
self._disable_size_callbacks = False
@pyqtSlot()
def onOkButtonClicked(self):
self._cancelled = False
@ -75,11 +104,30 @@ class ImageReaderUI(QObject):
self._ui_lock.release()
@pyqtSlot(str)
def onSizeChanged(self, value):
if (len(value) > 0):
self.size = float(value)
else:
self.size = 0
def onWidthChanged(self, value):
if self._ui_view and not self._disable_size_callbacks:
if (len(value) > 0):
self._width = float(value)
else:
self._width = 0
self._depth = self._width/self._aspect
self._disable_size_callbacks = True
self._ui_view.findChild(QObject, "Depth").setProperty("text", str(self._depth))
self._disable_size_callbacks = False
@pyqtSlot(str)
def onDepthChanged(self, value):
if self._ui_view and not self._disable_size_callbacks:
if (len(value) > 0):
self._depth = float(value)
else:
self._depth = 0
self._width = self._depth*self._aspect
self._disable_size_callbacks = True
self._ui_view.findChild(QObject, "Width").setProperty("text", str(self._width))
self._disable_size_callbacks = False
@pyqtSlot(str)
def onBaseHeightChanged(self, value):
@ -98,3 +146,10 @@ class ImageReaderUI(QObject):
@pyqtSlot(float)
def onSmoothingChanged(self, value):
self.smoothing = int(value)
@pyqtSlot(int)
def onImageColorInvertChanged(self, value):
if (value == 1):
self.image_color_invert = True
else:
self.image_color_invert = False