mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-06 21:44:01 -06:00
Merge branch 'master' of https://github.com/Ultimaker/Cura
This commit is contained in:
commit
7f15505f01
48 changed files with 783 additions and 314 deletions
|
@ -39,7 +39,8 @@ Please checkout [cura-build](https://github.com/Ultimaker/cura-build)
|
|||
|
||||
Third party plugins
|
||||
-------------
|
||||
[Print time calculator](https://github.com/nallath/PrintCostCalculator)
|
||||
* [Print time calculator](https://github.com/nallath/PrintCostCalculator)
|
||||
* [Post processing plugin](https://github.com/nallath/PostProcessingPlugin)
|
||||
|
||||
Making profiles for other printers
|
||||
----------------------------------
|
||||
|
|
|
@ -79,11 +79,13 @@ class CuraApplication(QtApplication):
|
|||
self._platform_activity = False
|
||||
|
||||
self.activeMachineChanged.connect(self._onActiveMachineChanged)
|
||||
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
|
||||
|
||||
Preferences.getInstance().addPreference("cura/active_machine", "")
|
||||
Preferences.getInstance().addPreference("cura/active_mode", "simple")
|
||||
Preferences.getInstance().addPreference("cura/recent_files", "")
|
||||
Preferences.getInstance().addPreference("cura/categories_expanded", "")
|
||||
Preferences.getInstance().addPreference("view/center_on_select", True)
|
||||
|
||||
JobQueue.getInstance().jobFinished.connect(self._onJobFinished)
|
||||
|
||||
|
@ -115,6 +117,11 @@ class CuraApplication(QtApplication):
|
|||
def run(self):
|
||||
self._i18n_catalog = i18nCatalog("cura");
|
||||
|
||||
i18nCatalog.setTagReplacements({
|
||||
"filename": "font color=\"black\"",
|
||||
"message": "font color=UM.Theme.colors.message_text;",
|
||||
})
|
||||
|
||||
self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Setting up scene..."))
|
||||
|
||||
controller = self.getController()
|
||||
|
@ -196,10 +203,10 @@ class CuraApplication(QtApplication):
|
|||
self._previous_active_tool = None
|
||||
else:
|
||||
self.getController().setActiveTool("TranslateTool")
|
||||
|
||||
self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
|
||||
self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
|
||||
self._camera_animation.start()
|
||||
if Preferences.getInstance().getValue("view/center_on_select"):
|
||||
self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
|
||||
self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
|
||||
self._camera_animation.start()
|
||||
else:
|
||||
if self.getController().getActiveTool():
|
||||
self._previous_active_tool = self.getController().getActiveTool().getPluginId()
|
||||
|
@ -214,24 +221,15 @@ class CuraApplication(QtApplication):
|
|||
def getPlatformActivity(self):
|
||||
return self._platform_activity
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def setPlatformActivity(self, activity):
|
||||
##Sets the _platform_activity variable on true or false depending on whether there is a mesh on the platform
|
||||
if activity == True:
|
||||
self._platform_activity = activity
|
||||
elif activity == False:
|
||||
nodes = []
|
||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||
if type(node) is not SceneNode or not node.getMeshData():
|
||||
continue
|
||||
nodes.append(node)
|
||||
i = 0
|
||||
for node in nodes:
|
||||
if not node.getMeshData():
|
||||
continue
|
||||
i += 1
|
||||
if i <= 1: ## i == 0 when the meshes are removed using the deleteAll function; i == 1 when the last remaining mesh is removed using the deleteObject function
|
||||
self._platform_activity = activity
|
||||
def updatePlatformActivity(self, node = None):
|
||||
count = 0
|
||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||
if type(node) is not SceneNode or not node.getMeshData():
|
||||
continue
|
||||
|
||||
count += 1
|
||||
|
||||
self._platform_activity = True if count > 0 else False
|
||||
self.activityChanged.emit()
|
||||
|
||||
## Remove an object from the scene
|
||||
|
@ -252,8 +250,7 @@ class CuraApplication(QtApplication):
|
|||
group_node = group_node.getParent()
|
||||
op = RemoveSceneNodeOperation(group_node)
|
||||
op.push()
|
||||
self.setPlatformActivity(False)
|
||||
|
||||
|
||||
## Create a number of copies of existing object.
|
||||
@pyqtSlot("quint64", int)
|
||||
def multiplyObject(self, object_id, count):
|
||||
|
@ -300,8 +297,7 @@ class CuraApplication(QtApplication):
|
|||
op.addOperation(RemoveSceneNodeOperation(node))
|
||||
|
||||
op.push()
|
||||
self.setPlatformActivity(False)
|
||||
|
||||
|
||||
## Reset all translation on nodes with mesh data.
|
||||
@pyqtSlot()
|
||||
def resetAllTranslation(self):
|
||||
|
|
|
@ -12,6 +12,8 @@ from UM.Math.Vector import Vector
|
|||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||
from UM.Application import Application
|
||||
from UM.Scene.Selection import Selection
|
||||
from UM.Preferences import Preferences
|
||||
|
||||
from cura.ConvexHullDecorator import ConvexHullDecorator
|
||||
|
||||
from . import PlatformPhysicsOperation
|
||||
|
@ -37,6 +39,8 @@ class PlatformPhysics:
|
|||
self._change_timer.setSingleShot(True)
|
||||
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
||||
|
||||
Preferences.getInstance().addPreference("physics/automatic_push_free", True)
|
||||
|
||||
def _onSceneChanged(self, source):
|
||||
self._change_timer.start()
|
||||
|
||||
|
@ -82,7 +86,7 @@ class PlatformPhysics:
|
|||
|
||||
elif Selection.isSelected(node):
|
||||
pass
|
||||
else:
|
||||
elif Preferences.getInstance().getValue("physics/automatic_push_free"):
|
||||
# Check for collisions between convex hulls
|
||||
for other_node in BreadthFirstIterator(root):
|
||||
# Ignore root, ourselves and anything that is not a normal SceneNode.
|
||||
|
|
|
@ -15,16 +15,21 @@ import os
|
|||
import struct
|
||||
import math
|
||||
from os import listdir
|
||||
import untangle
|
||||
import zipfile
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
|
||||
class ThreeMFReader(MeshReader):
|
||||
def __init__(self):
|
||||
super(ThreeMFReader, self).__init__()
|
||||
self._supported_extension = ".3mf"
|
||||
|
||||
|
||||
self._namespaces = {
|
||||
"3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
|
||||
"cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
|
||||
}
|
||||
|
||||
def read(self, file_name):
|
||||
result = None
|
||||
extension = os.path.splitext(file_name)[1]
|
||||
|
@ -33,32 +38,39 @@ class ThreeMFReader(MeshReader):
|
|||
# The base object of 3mf is a zipped archive.
|
||||
archive = zipfile.ZipFile(file_name, 'r')
|
||||
try:
|
||||
# The model is always stored in this place.
|
||||
root = untangle.parse(archive.read("3D/3dmodel.model").decode("utf-8"))
|
||||
for object in root.model.resources.object: # There can be multiple objects, try to load all of them.
|
||||
root = ET.parse(archive.open("3D/3dmodel.model"))
|
||||
|
||||
# There can be multiple objects, try to load all of them.
|
||||
objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
|
||||
for object in objects:
|
||||
mesh = MeshData()
|
||||
node = SceneNode()
|
||||
vertex_list = []
|
||||
for vertex in object.mesh.vertices.vertex:
|
||||
vertex_list.append([vertex['x'],vertex['y'],vertex['z']])
|
||||
#for vertex in object.mesh.vertices.vertex:
|
||||
for vertex in object.findall(".//3mf:vertex", self._namespaces):
|
||||
vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
|
||||
|
||||
triangles = object.findall(".//3mf:triangle", self._namespaces)
|
||||
|
||||
mesh.reserveFaceCount(len(triangles))
|
||||
|
||||
mesh.reserveFaceCount(len(object.mesh.triangles.triangle))
|
||||
|
||||
for triangle in object.mesh.triangles.triangle:
|
||||
v1 = int(triangle["v1"])
|
||||
v2 = int(triangle["v2"])
|
||||
v3 = int(triangle["v3"])
|
||||
#for triangle in object.mesh.triangles.triangle:
|
||||
for triangle in triangles:
|
||||
v1 = int(triangle.get("v1"))
|
||||
v2 = int(triangle.get("v2"))
|
||||
v3 = int(triangle.get("v3"))
|
||||
mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2])
|
||||
#TODO: We currently do not check for normals and simply recalculate them.
|
||||
mesh.calculateNormals()
|
||||
node.setMeshData(mesh)
|
||||
node.setSelectable(True)
|
||||
|
||||
# Magical python comprehension; looks for the matching transformation
|
||||
transformation = next((x for x in root.model.build.item if x["objectid"] == object["id"]), None)
|
||||
|
||||
if transformation["transform"]:
|
||||
splitted_transformation = transformation["transform"].split()
|
||||
transformation = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(object.get("id")), self._namespaces)
|
||||
if transformation:
|
||||
transformation = transformation[0]
|
||||
|
||||
if transformation.get("transform"):
|
||||
splitted_transformation = transformation.get("transform").split()
|
||||
## Transformation is saved as:
|
||||
## M00 M01 M02 0.0
|
||||
## M10 M11 M12 0.0
|
||||
|
@ -99,10 +111,10 @@ class ThreeMFReader(MeshReader):
|
|||
rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
|
||||
node.rotate(rotation)
|
||||
result.addChild(node)
|
||||
|
||||
# If there is more then one object, group them.
|
||||
|
||||
#If there is more then one object, group them.
|
||||
try:
|
||||
if len(root.model.resources.object) > 1:
|
||||
if len(objects) > 1:
|
||||
group_decorator = GroupDecorator()
|
||||
result.addDecorator(group_decorator)
|
||||
except:
|
||||
|
|
|
@ -130,6 +130,7 @@ class CuraEngineBackend(Backend):
|
|||
if not getattr(node, "_outside_buildarea", False):
|
||||
temp_list.append(node)
|
||||
if len(temp_list) == 0:
|
||||
self.processingProgress.emit(0.0)
|
||||
return
|
||||
object_groups.append(temp_list)
|
||||
#for node in DepthFirstIterator(self._scene.getRoot()):
|
||||
|
@ -241,6 +242,10 @@ class CuraEngineBackend(Backend):
|
|||
self._socket.registerMessageType(6, Cura_pb2.SettingList)
|
||||
self._socket.registerMessageType(7, Cura_pb2.GCodePrefix)
|
||||
|
||||
## Manually triggers a reslice
|
||||
def forceSlice(self):
|
||||
self._change_timer.start()
|
||||
|
||||
def _onChanged(self):
|
||||
if not self._settings:
|
||||
return
|
||||
|
|
|
@ -28,7 +28,8 @@ class LayerData(MeshData):
|
|||
self._layers[layer].polygons.append(p)
|
||||
|
||||
def getLayer(self, layer):
|
||||
return self._layers[layer]
|
||||
if layer in self._layers:
|
||||
return self._layers[layer]
|
||||
|
||||
def getLayers(self):
|
||||
return self._layers
|
||||
|
|
|
@ -17,8 +17,8 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||
super().__init__(device_id)
|
||||
|
||||
self.setName(device_name)
|
||||
self.setShortDescription(catalog.i18nc("", "Save to Removable Drive"))
|
||||
self.setDescription(catalog.i18nc("", "Save to Removable Drive {0}").format(device_name))
|
||||
self.setShortDescription(catalog.i18nc("@action:button", "Save to Removable Drive"))
|
||||
self.setDescription(catalog.i18nc("@info:tooltip", "Save to Removable Drive {0}").format(device_name))
|
||||
self.setIconName("save_sd")
|
||||
self.setPriority(1)
|
||||
|
||||
|
@ -49,7 +49,7 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||
job.progress.connect(self._onProgress)
|
||||
job.finished.connect(self._onFinished)
|
||||
|
||||
message = Message(catalog.i18nc("", "Saving to Removable Drive {0}").format(self.getName()), 0, False, -1)
|
||||
message = Message(catalog.i18nc("@info:status", "Saving to Removable Drive <filename>{0}</filename>").format(self.getName()), 0, False, -1)
|
||||
message.show()
|
||||
|
||||
job._message = message
|
||||
|
|
|
@ -22,7 +22,7 @@ UM.Dialog
|
|||
Column
|
||||
{
|
||||
anchors.fill: parent;
|
||||
|
||||
|
||||
Text
|
||||
{
|
||||
anchors {
|
||||
|
|
|
@ -44,6 +44,9 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
self._connect_thread = threading.Thread(target = self._connect)
|
||||
self._connect_thread.daemon = True
|
||||
|
||||
self._end_stop_thread = threading.Thread(target = self._pollEndStop)
|
||||
self._end_stop_thread.deamon = True
|
||||
|
||||
# Printer is connected
|
||||
self._is_connected = False
|
||||
|
||||
|
@ -52,7 +55,7 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
|
||||
# The baud checking is done by sending a number of m105 commands to the printer and waiting for a readable
|
||||
# response. If the baudrate is correct, this should make sense, else we get giberish.
|
||||
self._required_responses_auto_baud = 10
|
||||
self._required_responses_auto_baud = 3
|
||||
|
||||
self._progress = 0
|
||||
|
||||
|
@ -60,8 +63,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
self._listen_thread.daemon = True
|
||||
|
||||
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
|
||||
self._update_firmware_thread.demon = True
|
||||
|
||||
self._update_firmware_thread.deamon = True
|
||||
|
||||
self._heatup_wait_start_time = time.time()
|
||||
|
||||
## Queue for commands that need to be send. Used when command is sent when a print is active.
|
||||
|
@ -97,6 +100,14 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
# Current Z stage location
|
||||
self._current_z = 0
|
||||
|
||||
self._x_min_endstop_pressed = False
|
||||
self._y_min_endstop_pressed = False
|
||||
self._z_min_endstop_pressed = False
|
||||
|
||||
self._x_max_endstop_pressed = False
|
||||
self._y_max_endstop_pressed = False
|
||||
self._z_max_endstop_pressed = False
|
||||
|
||||
# In order to keep the connection alive we request the temperature every so often from a different extruder.
|
||||
# This index is the extruder we requested data from the last time.
|
||||
self._temperature_requested_extruder_index = 0
|
||||
|
@ -112,6 +123,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
extruderTemperatureChanged = pyqtSignal()
|
||||
bedTemperatureChanged = pyqtSignal()
|
||||
|
||||
endstopStateChanged = pyqtSignal(str ,bool, arguments = ["key","state"])
|
||||
|
||||
@pyqtProperty(float, notify = progressChanged)
|
||||
def progress(self):
|
||||
return self._progress
|
||||
|
@ -209,6 +222,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
|
||||
self.setProgress(100, 100)
|
||||
|
||||
self.firmwareUpdateComplete.emit()
|
||||
|
||||
## Upload new firmware to machine
|
||||
# \param filename full path of firmware file to be uploaded
|
||||
def updateFirmware(self, file_name):
|
||||
|
@ -216,6 +231,20 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
self._firmware_file_name = file_name
|
||||
self._update_firmware_thread.start()
|
||||
|
||||
@pyqtSlot()
|
||||
def startPollEndstop(self):
|
||||
self._poll_endstop = True
|
||||
self._end_stop_thread.start()
|
||||
|
||||
@pyqtSlot()
|
||||
def stopPollEndstop(self):
|
||||
self._poll_endstop = False
|
||||
|
||||
def _pollEndStop(self):
|
||||
while self._is_connected and self._poll_endstop:
|
||||
self.sendCommand("M119")
|
||||
time.sleep(0.5)
|
||||
|
||||
## Private connect function run by thread. Can be started by calling connect.
|
||||
def _connect(self):
|
||||
Logger.log("d", "Attempting to connect to %s", self._serial_port)
|
||||
|
@ -255,9 +284,9 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
if line is None:
|
||||
self.setIsConnected(False) # Something went wrong with reading, could be that close was called.
|
||||
return
|
||||
|
||||
if b"T:" in line:
|
||||
self._serial.timeout = 0.5
|
||||
self._sendCommand("M105")
|
||||
sucesfull_responses += 1
|
||||
if sucesfull_responses >= self._required_responses_auto_baud:
|
||||
self._serial.timeout = 2 #Reset serial timeout
|
||||
|
@ -265,6 +294,8 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
|
||||
return
|
||||
|
||||
self._sendCommand("M105") # Send M105 as long as we are listening, otherwise we end up in an undefined state
|
||||
|
||||
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
|
||||
self.close() # Unable to connect, wrap up.
|
||||
self.setIsConnected(False)
|
||||
|
@ -297,6 +328,9 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
except Exception as e:
|
||||
pass # This should work, but it does fail sometimes for some reason
|
||||
|
||||
self._connect_thread = threading.Thread(target=self._connect)
|
||||
self._connect_thread.daemon = True
|
||||
|
||||
if self._serial is not None:
|
||||
self.setIsConnected(False)
|
||||
try:
|
||||
|
@ -305,11 +339,30 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
pass
|
||||
self._serial.close()
|
||||
|
||||
self._listen_thread = threading.Thread(target=self._listen)
|
||||
self._listen_thread.daemon = True
|
||||
self._serial = None
|
||||
|
||||
def isConnected(self):
|
||||
return self._is_connected
|
||||
|
||||
@pyqtSlot(int)
|
||||
def heatupNozzle(self, temperature):
|
||||
self._sendCommand("M104 S%s" % temperature)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def heatupBed(self, temperature):
|
||||
self._sendCommand("M140 S%s" % temperature)
|
||||
|
||||
@pyqtSlot("long", "long","long")
|
||||
def moveHead(self, x, y, z):
|
||||
print("Moving head" , x , " ", y , " " , z)
|
||||
self._sendCommand("G0 X%s Y%s Z%s"%(x,y,z))
|
||||
|
||||
@pyqtSlot()
|
||||
def homeHead(self):
|
||||
self._sendCommand("G28")
|
||||
|
||||
## Directly send the command, withouth checking connection state (eg; printing).
|
||||
# \param cmd string with g-code
|
||||
def _sendCommand(self, cmd):
|
||||
|
@ -402,6 +455,20 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
def requestWrite(self, node):
|
||||
self.showControlInterface()
|
||||
|
||||
def _setEndstopState(self, endstop_key, value):
|
||||
if endstop_key == b'x_min':
|
||||
if self._x_min_endstop_pressed != value:
|
||||
self.endstopStateChanged.emit('x_min', value)
|
||||
self._x_min_endstop_pressed = value
|
||||
elif endstop_key == b'y_min':
|
||||
if self._y_min_endstop_pressed != value:
|
||||
self.endstopStateChanged.emit('y_min', value)
|
||||
self._y_min_endstop_pressed = value
|
||||
elif endstop_key == b'z_min':
|
||||
if self._z_min_endstop_pressed != value:
|
||||
self.endstopStateChanged.emit('z_min', value)
|
||||
self._z_min_endstop_pressed = value
|
||||
|
||||
## Listen thread function.
|
||||
def _listen(self):
|
||||
Logger.log("i", "Printer connection listen thread started for %s" % self._serial_port)
|
||||
|
@ -413,6 +480,14 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
if line is None:
|
||||
break # None is only returned when something went wrong. Stop listening
|
||||
|
||||
if time.time() > temperature_request_timeout:
|
||||
if self._extruder_count > 0:
|
||||
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._extruder_count
|
||||
self.sendCommand("M105 T%d" % (self._temperature_requested_extruder_index))
|
||||
else:
|
||||
self.sendCommand("M105")
|
||||
temperature_request_timeout = time.time() + 5
|
||||
|
||||
if line.startswith(b"Error:"):
|
||||
# Oh YEAH, consistency.
|
||||
# Marlin reports an MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
||||
|
@ -437,16 +512,11 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
except Exception as e:
|
||||
pass
|
||||
#TODO: temperature changed callback
|
||||
elif b"_min" in line or b"_max" in line:
|
||||
tag, value = line.split(b':', 1)
|
||||
self._setEndstopState(tag,(b'H' in value or b'TRIGGERED' in value))
|
||||
|
||||
if self._is_printing:
|
||||
if time.time() > temperature_request_timeout: # When printing, request temperature every 5 seconds.
|
||||
if self._extruder_count > 0:
|
||||
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._extruder_count
|
||||
self.sendCommand("M105 T%d" % (self._temperature_requested_extruder_index))
|
||||
else:
|
||||
self.sendCommand("M105")
|
||||
temperature_request_timeout = time.time() + 5
|
||||
|
||||
if line == b"" and time.time() > ok_timeout:
|
||||
line = b"ok" # Force a timeout (basicly, send next command)
|
||||
|
||||
|
@ -540,3 +610,10 @@ class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
|||
def _getBaudrateList(self):
|
||||
ret = [250000, 230400, 115200, 57600, 38400, 19200, 9600]
|
||||
return ret
|
||||
|
||||
def _onFirmwareUpdateComplete(self):
|
||||
self._update_firmware_thread.join()
|
||||
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
|
||||
self._update_firmware_thread.deamon = True
|
||||
|
||||
self.connect()
|
||||
|
|
|
@ -10,6 +10,7 @@ from UM.Resources import Resources
|
|||
from UM.Logger import Logger
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
||||
from UM.Qt.ListModel import ListModel
|
||||
|
||||
import threading
|
||||
import platform
|
||||
|
@ -35,6 +36,7 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|||
Extension.__init__(self)
|
||||
self._serial_port_list = []
|
||||
self._printer_connections = {}
|
||||
self._printer_connections_model = None
|
||||
self._update_thread = threading.Thread(target = self._updateThread)
|
||||
self._update_thread.setDaemon(True)
|
||||
|
||||
|
@ -49,6 +51,7 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|||
self.addConnectionSignal.connect(self.addConnection) #Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
||||
|
||||
addConnectionSignal = Signal()
|
||||
printerConnectionStateChanged = pyqtSignal()
|
||||
|
||||
def start(self):
|
||||
self._check_updates = True
|
||||
|
@ -84,15 +87,31 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|||
self.spawnFirmwareInterface("")
|
||||
for printer_connection in self._printer_connections:
|
||||
try:
|
||||
printer_connection.updateFirmware(Resources.getPath(Resources.FirmwareLocation, self._getDefaultFirmwareName()))
|
||||
self._printer_connections[printer_connection].updateFirmware(Resources.getPath(Resources.FirmwareLocation, self._getDefaultFirmwareName()))
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
|
||||
@pyqtSlot(str, result = bool)
|
||||
def updateFirmwareBySerial(self, serial_port):
|
||||
printer_connection = self.getConnectionByPort(serial_port)
|
||||
if printer_connection is not None:
|
||||
self.spawnFirmwareInterface(printer_connection.getSerialPort())
|
||||
printer_connection.updateFirmware(Resources.getPath(Resources.FirmwareLocation, self._getDefaultFirmwareName()))
|
||||
if serial_port in self._printer_connections:
|
||||
self.spawnFirmwareInterface(self._printer_connections[serial_port].getSerialPort())
|
||||
try:
|
||||
self._printer_connections[serial_port].updateFirmware(Resources.getPath(Resources.FirmwareLocation, self._getDefaultFirmwareName()))
|
||||
except FileNotFoundError:
|
||||
self._firmware_view.close()
|
||||
Logger.log("e", "Could not find firmware required for this machine")
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
## Return the singleton instance of the USBPrinterManager
|
||||
@classmethod
|
||||
def getInstance(cls, engine = None, script_engine = None):
|
||||
# Note: Explicit use of class name to prevent issues with inheritance.
|
||||
if USBPrinterManager._instance is None:
|
||||
USBPrinterManager._instance = cls()
|
||||
|
||||
return USBPrinterManager._instance
|
||||
|
||||
def _getDefaultFirmwareName(self):
|
||||
machine_type = Application.getInstance().getActiveMachine().getTypeID()
|
||||
|
@ -140,6 +159,17 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|||
self.getOutputDeviceManager().addOutputDevice(self._printer_connections[serial_port])
|
||||
else:
|
||||
self.getOutputDeviceManager().removeOutputDevice(serial_port)
|
||||
self.printerConnectionStateChanged.emit()
|
||||
|
||||
@pyqtProperty(QObject , notify = printerConnectionStateChanged)
|
||||
def connectedPrinterList(self):
|
||||
self._printer_connections_model = ListModel()
|
||||
self._printer_connections_model.addRoleName(Qt.UserRole + 1,"name")
|
||||
self._printer_connections_model.addRoleName(Qt.UserRole + 2, "printer")
|
||||
for connection in self._printer_connections:
|
||||
if self._printer_connections[connection].isConnected():
|
||||
self._printer_connections_model.appendItem({"name":connection, "printer": self._printer_connections[connection]})
|
||||
return self._printer_connections_model
|
||||
|
||||
## Create a list of serial ports on the system.
|
||||
# \param only_list_usb If true, only usb ports are listed
|
||||
|
@ -163,4 +193,6 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|||
base_list = filter(lambda s: "Bluetooth" not in s, base_list) # Filter because mac sometimes puts them in the list
|
||||
else:
|
||||
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/rfcomm*") + glob.glob("/dev/serial/by-id/*")
|
||||
return list(base_list)
|
||||
return list(base_list)
|
||||
|
||||
_instance = None
|
|
@ -2,7 +2,7 @@
|
|||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import USBPrinterManager
|
||||
|
||||
from PyQt5.QtQml import qmlRegisterType, qmlRegisterSingletonType
|
||||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
@ -19,4 +19,5 @@ def getMetaData():
|
|||
}
|
||||
|
||||
def register(app):
|
||||
return {"extension":USBPrinterManager.USBPrinterManager(),"output_device": USBPrinterManager.USBPrinterManager() }
|
||||
qmlRegisterSingletonType(USBPrinterManager.USBPrinterManager, "UM", 1, 0, "USBPrinterManager", USBPrinterManager.USBPrinterManager.getInstance)
|
||||
return {"extension":USBPrinterManager.USBPrinterManager.getInstance(),"output_device": USBPrinterManager.USBPrinterManager.getInstance() }
|
||||
|
|
|
@ -40,10 +40,18 @@ Item {
|
|||
property alias reportBug: reportBugAction;
|
||||
property alias about: aboutAction;
|
||||
|
||||
property alias toggleFullScreen: toggleFullScreenAction;
|
||||
|
||||
Action
|
||||
{
|
||||
id:toggleFullScreenAction
|
||||
shortcut: StandardKey.FullScreen;
|
||||
}
|
||||
|
||||
Action {
|
||||
id: undoAction;
|
||||
//: Undo action
|
||||
text: qsTr("&Undo");
|
||||
text: qsTr("Undo");
|
||||
iconName: "edit-undo";
|
||||
shortcut: StandardKey.Undo;
|
||||
}
|
||||
|
@ -51,7 +59,7 @@ Item {
|
|||
Action {
|
||||
id: redoAction;
|
||||
//: Redo action
|
||||
text: qsTr("&Redo");
|
||||
text: qsTr("Redo");
|
||||
iconName: "edit-redo";
|
||||
shortcut: StandardKey.Redo;
|
||||
}
|
||||
|
@ -59,7 +67,7 @@ Item {
|
|||
Action {
|
||||
id: quitAction;
|
||||
//: Quit action
|
||||
text: qsTr("&Quit");
|
||||
text: qsTr("Quit");
|
||||
iconName: "application-exit";
|
||||
shortcut: StandardKey.Quit;
|
||||
}
|
||||
|
@ -67,20 +75,20 @@ Item {
|
|||
Action {
|
||||
id: preferencesAction;
|
||||
//: Preferences action
|
||||
text: qsTr("&Preferences...");
|
||||
text: qsTr("Preferences...");
|
||||
iconName: "configure";
|
||||
}
|
||||
|
||||
Action {
|
||||
id: addMachineAction;
|
||||
//: Add Printer action
|
||||
text: qsTr("&Add Printer...");
|
||||
text: qsTr("Add Printer...");
|
||||
}
|
||||
|
||||
Action {
|
||||
id: settingsAction;
|
||||
//: Configure Printers action
|
||||
text: qsTr("&Configure Printers");
|
||||
text: qsTr("Configure Printers");
|
||||
iconName: "configure";
|
||||
}
|
||||
|
||||
|
@ -102,7 +110,7 @@ Item {
|
|||
Action {
|
||||
id: aboutAction;
|
||||
//: About action
|
||||
text: qsTr("&About...");
|
||||
text: qsTr("About...");
|
||||
iconName: "help-about";
|
||||
}
|
||||
|
||||
|
@ -190,7 +198,7 @@ Item {
|
|||
Action {
|
||||
id: openAction;
|
||||
//: Open file action
|
||||
text: qsTr("&Open...");
|
||||
text: qsTr("Load file");
|
||||
iconName: "document-open";
|
||||
shortcut: StandardKey.Open;
|
||||
}
|
||||
|
@ -198,7 +206,7 @@ Item {
|
|||
Action {
|
||||
id: saveAction;
|
||||
//: Save file action
|
||||
text: qsTr("&Save...");
|
||||
text: qsTr("Save...");
|
||||
iconName: "document-save";
|
||||
shortcut: StandardKey.Save;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import UM 1.1 as UM
|
|||
UM.MainWindow {
|
||||
id: base
|
||||
visible: true
|
||||
|
||||
//: Cura application window title
|
||||
title: qsTr("Cura");
|
||||
|
||||
|
@ -212,10 +211,8 @@ UM.MainWindow {
|
|||
|
||||
UM.MessageStack {
|
||||
anchors {
|
||||
left: toolbar.right;
|
||||
leftMargin: UM.Theme.sizes.window_margin.width;
|
||||
right: sidebar.left;
|
||||
rightMargin: UM.Theme.sizes.window_margin.width;
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
horizontalCenterOffset: -(UM.Theme.sizes.logo.width/ 2)
|
||||
top: parent.verticalCenter;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
|
@ -242,17 +239,15 @@ UM.MainWindow {
|
|||
|
||||
Button {
|
||||
id: openFileButton;
|
||||
|
||||
iconSource: UM.Theme.icons.open;
|
||||
style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button;
|
||||
//style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button;
|
||||
style: UM.Theme.styles.open_file_button
|
||||
tooltip: '';
|
||||
anchors {
|
||||
top: parent.top;
|
||||
topMargin: UM.Theme.sizes.window_margin.height;
|
||||
topMargin: UM.Theme.sizes.loadfile_margin.height
|
||||
left: parent.left;
|
||||
leftMargin: UM.Theme.sizes.window_margin.width;
|
||||
leftMargin: UM.Theme.sizes.loadfile_margin.width
|
||||
}
|
||||
|
||||
action: actions.open;
|
||||
}
|
||||
|
||||
|
@ -349,8 +344,15 @@ UM.MainWindow {
|
|||
id: preferences
|
||||
|
||||
Component.onCompleted: {
|
||||
//; Remove & re-add the general page as we want to use our own instead of uranium standard.
|
||||
removePage(0);
|
||||
insertPage(0, qsTr("General") , "" , Qt.resolvedUrl("./GeneralPage.qml"));
|
||||
|
||||
//: View preferences page title
|
||||
insertPage(1, qsTr("View"), "view-preview", Qt.resolvedUrl("./ViewPage.qml"));
|
||||
|
||||
//Force refresh
|
||||
setPage(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,6 +425,8 @@ UM.MainWindow {
|
|||
reportBug.onTriggered: CuraActions.openBugReportPage();
|
||||
showEngineLog.onTriggered: engineLog.visible = true;
|
||||
about.onTriggered: aboutDialog.visible = true;
|
||||
toggleFullScreen.onTriggered: base.toggleFullscreen()
|
||||
|
||||
}
|
||||
|
||||
Menu {
|
||||
|
@ -481,7 +485,6 @@ UM.MainWindow {
|
|||
onAccepted:
|
||||
{
|
||||
UM.MeshFileHandler.readLocalFile(fileUrl)
|
||||
Printer.setPlatformActivity(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
130
resources/qml/GeneralPage.qml
Normal file
130
resources/qml/GeneralPage.qml
Normal file
|
@ -0,0 +1,130 @@
|
|||
// Copyright (c) 2015 Ultimaker B.V.
|
||||
// Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
|
||||
import UM 1.0 as UM
|
||||
|
||||
UM.PreferencesPage
|
||||
{
|
||||
//: General configuration page title
|
||||
title: qsTr("General");
|
||||
|
||||
function reset()
|
||||
{
|
||||
UM.Preferences.resetPreference("general/language")
|
||||
UM.Preferences.resetPreference("physics/automatic_push_free")
|
||||
}
|
||||
GridLayout
|
||||
{
|
||||
columns: 2;
|
||||
//: Language selection label
|
||||
Label
|
||||
{
|
||||
id: languageLabel
|
||||
text: qsTr("Language")
|
||||
}
|
||||
|
||||
ComboBox
|
||||
{
|
||||
id: languageComboBox
|
||||
model: ListModel
|
||||
{
|
||||
id: languageList
|
||||
//: English language combo box option
|
||||
ListElement { text: QT_TR_NOOP("English"); code: "en" }
|
||||
//: German language combo box option
|
||||
ListElement { text: QT_TR_NOOP("German"); code: "de" }
|
||||
//: French language combo box option
|
||||
// ListElement { text: QT_TR_NOOP("French"); code: "fr" }
|
||||
//: Spanish language combo box option
|
||||
ListElement { text: QT_TR_NOOP("Spanish"); code: "es" }
|
||||
//: Italian language combo box option
|
||||
// ListElement { text: QT_TR_NOOP("Italian"); code: "it" }
|
||||
//: Finnish language combo box option
|
||||
ListElement { text: QT_TR_NOOP("Finnish"); code: "fi" }
|
||||
//: Russian language combo box option
|
||||
ListElement { text: QT_TR_NOOP("Russian"); code: "ru" }
|
||||
}
|
||||
|
||||
currentIndex:
|
||||
{
|
||||
var code = UM.Preferences.getValue("general/language");
|
||||
for(var i = 0; i < languageList.count; ++i)
|
||||
{
|
||||
if(model.get(i).code == code)
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: UM.Preferences.setValue("general/language", model.get(index).code)
|
||||
|
||||
anchors.left: languageLabel.right
|
||||
anchors.top: languageLabel.top
|
||||
anchors.leftMargin: 20
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
// Because ListModel is stupid and does not allow using qsTr() for values.
|
||||
for(var i = 0; i < languageList.count; ++i)
|
||||
{
|
||||
languageList.setProperty(i, "text", qsTr(languageList.get(i).text));
|
||||
}
|
||||
|
||||
// Glorious hack time. ComboBox does not update the text properly after changing the
|
||||
// model. So change the indices around to force it to update.
|
||||
currentIndex += 1;
|
||||
currentIndex -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: languageCaption;
|
||||
Layout.columnSpan: 2
|
||||
|
||||
//: Language change warning
|
||||
text: qsTr("You will need to restart the application for language changes to have effect.")
|
||||
wrapMode: Text.WordWrap
|
||||
font.italic: true
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: pushFreeCheckbox
|
||||
checked: UM.Preferences.getValue("physics/automatic_push_free")
|
||||
onCheckedChanged: UM.Preferences.setValue("physics/automatic_push_free", checked)
|
||||
}
|
||||
Button
|
||||
{
|
||||
id: pushFreeText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||
|
||||
//: Display Overhang preference checkbox
|
||||
text: qsTr("Automatic push free");
|
||||
onClicked: pushFreeCheckbox.checked = !pushFreeCheckbox.checked
|
||||
|
||||
//: Display Overhang preference tooltip
|
||||
tooltip: "Are objects on the platform automatically moved so they no longer intersect"
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
border.width: 0
|
||||
color: "transparent"
|
||||
}
|
||||
label: Text
|
||||
{
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: control.text
|
||||
}
|
||||
}
|
||||
}
|
||||
Item { Layout.fillHeight: true; Layout.columnSpan: 2 }
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ Item {
|
|||
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
spacing: 1
|
||||
spacing: UM.Theme.sizes.default_lining.width
|
||||
|
||||
Repeater {
|
||||
id: repeat
|
||||
|
@ -67,6 +67,8 @@ Item {
|
|||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
|
||||
color: UM.Theme.colors.tool_panel_background;
|
||||
border.width: UM.Theme.sizes.default_lining.width
|
||||
border.color: UM.Theme.colors.button_lining
|
||||
|
||||
Loader {
|
||||
id: panel
|
||||
|
|
|
@ -8,7 +8,8 @@ import QtQuick.Controls.Styles 1.1
|
|||
|
||||
import UM 1.0 as UM
|
||||
|
||||
UM.PreferencesPage {
|
||||
UM.PreferencesPage
|
||||
{
|
||||
id: preferencesPage
|
||||
|
||||
//: View configuration page title
|
||||
|
@ -17,22 +18,26 @@ UM.PreferencesPage {
|
|||
function reset()
|
||||
{
|
||||
UM.Preferences.resetPreference("view/show_overhang");
|
||||
UM.Preferences.resetPreferences("view/center_on_select");
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
GridLayout
|
||||
{
|
||||
columns: 2;
|
||||
|
||||
CheckBox {
|
||||
id: viewCheckbox
|
||||
CheckBox
|
||||
{
|
||||
id: overhangCheckbox
|
||||
checked: UM.Preferences.getValue("view/show_overhang")
|
||||
onCheckedChanged: UM.Preferences.setValue("view/show_overhang", checked)
|
||||
}
|
||||
Button {
|
||||
Button
|
||||
{
|
||||
id: viewText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||
|
||||
//: Display Overhang preference checkbox
|
||||
text: qsTr("Display Overhang");
|
||||
onClicked: viewCheckbox.checked = !viewCheckbox.checked
|
||||
onClicked: overhangCheckbox.checked = !overhangCheckbox.checked
|
||||
|
||||
//: Display Overhang preference tooltip
|
||||
tooltip: "Highlight unsupported areas of the model in red. Without support these areas will nog print properly."
|
||||
|
@ -49,6 +54,39 @@ UM.PreferencesPage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: centerCheckbox
|
||||
checked: UM.Preferences.getValue("view/center_on_select")
|
||||
onCheckedChanged: UM.Preferences.setValue("view/center_on_select", checked)
|
||||
}
|
||||
Button
|
||||
{
|
||||
id: centerText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||
|
||||
//: Display Overhang preference checkbox
|
||||
text: qsTr("Center camera when item is selected");
|
||||
onClicked: centerCheckbox.checked = !centerCheckbox.checked
|
||||
|
||||
//: Display Overhang preference tooltip
|
||||
tooltip: "Moves the camera so the object is in the center of the view when an object is selected"
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
border.width: 0
|
||||
color: "transparent"
|
||||
}
|
||||
label: Text
|
||||
{
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: control.text
|
||||
}
|
||||
}
|
||||
}
|
||||
Item { Layout.fillHeight: true; Layout.columnSpan: 2 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -252,6 +252,10 @@ ColumnLayout
|
|||
UM.Models.availableMachinesModel.createMachine(machineList.currentIndex, machineName.text)
|
||||
var pages = UM.Models.availableMachinesModel.getItem(machineList.currentIndex).pages
|
||||
var old_page_count = elementRoot.getPageCount()
|
||||
for(var i = 0; i < UM.Models.count; i++)
|
||||
{
|
||||
print(UM.Models.getItem(i))
|
||||
}
|
||||
// Delete old pages (if any)
|
||||
for (var i = old_page_count - 1; i > 0; i--)
|
||||
{
|
||||
|
|
|
@ -8,62 +8,47 @@ import QtQuick.Window 2.1
|
|||
|
||||
import UM 1.0 as UM
|
||||
|
||||
ColumnLayout {
|
||||
Column
|
||||
{
|
||||
id: wizardPage
|
||||
property string title
|
||||
property int pageWidth
|
||||
property int pageHeight
|
||||
|
||||
SystemPalette{id: palette}
|
||||
//signal openFile(string fileName)
|
||||
//signal closeWizard()
|
||||
|
||||
width: wizardPage.pageWidth
|
||||
height: wizardPage.pageHeight
|
||||
|
||||
Connections {
|
||||
target: elementRoot
|
||||
onResize: {
|
||||
wizardPage.width = pageWidth
|
||||
wizardPage.height = pageHeight
|
||||
}
|
||||
property int leveling_state: 0
|
||||
property bool three_point_leveling: true
|
||||
property int platform_width: UM.Models.settingsModel.getMachineSetting("machine_width")
|
||||
property int platform_height: UM.Models.settingsModel.getMachineSetting("machine_depth")
|
||||
anchors.fill: parent;
|
||||
property variant printer_connection: UM.USBPrinterManager.connectedPrinterList.getItem(0).printer
|
||||
Component.onCompleted: printer_connection.homeHead()
|
||||
Label
|
||||
{
|
||||
text: ""
|
||||
//Component.onCompleted:console.log(UM.Models.settingsModel.getMachineSetting("machine_width"))
|
||||
}
|
||||
|
||||
Label {
|
||||
text: parent.title
|
||||
font.pointSize: 18;
|
||||
}
|
||||
|
||||
Label {
|
||||
//: Add Printer wizard page description
|
||||
text: qsTr("Please select the type of printer:");
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
Layout.fillWidth: true;
|
||||
|
||||
ListView {
|
||||
id: machineList;
|
||||
model: UM.Models.availableMachinesModel
|
||||
delegate: RadioButton {
|
||||
exclusiveGroup: printerGroup;
|
||||
text: model.name;
|
||||
onClicked: {
|
||||
ListView.view.currentIndex = index;
|
||||
|
||||
}
|
||||
Button
|
||||
{
|
||||
text: "Move to next position"
|
||||
onClicked:
|
||||
{
|
||||
if(wizardPage.leveling_state == 0)
|
||||
{
|
||||
printer_connection.moveHead(platform_width /2 , platform_height,0)
|
||||
}
|
||||
if(wizardPage.leveling_state == 1)
|
||||
{
|
||||
printer_connection.moveHead(platform_width , 0,0)
|
||||
}
|
||||
if(wizardPage.leveling_state == 2)
|
||||
{
|
||||
printer_connection.moveHead(0, 0 ,0)
|
||||
}
|
||||
|
||||
wizardPage.leveling_state++
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
//: Add Printer wizard field label
|
||||
text: qsTr("Printer Name:");
|
||||
function threePointLeveling(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
TextField { id: machineName; Layout.fillWidth: true; text: machineList.model.getItem(machineList.currentIndex).name }
|
||||
|
||||
Item { Layout.fillWidth: true; Layout.fillHeight: true; }
|
||||
|
||||
ExclusiveGroup { id: printerGroup; }
|
||||
}
|
|
@ -13,6 +13,16 @@ Column
|
|||
id: wizardPage
|
||||
property string title
|
||||
anchors.fill: parent;
|
||||
property bool x_min_pressed: false
|
||||
property bool y_min_pressed: false
|
||||
property bool z_min_pressed: false
|
||||
property bool heater_works: false
|
||||
property int extruder_target_temp: 0
|
||||
property int bed_target_temp: 0
|
||||
property variant printer_connection: UM.USBPrinterManager.connectedPrinterList.getItem(0).printer
|
||||
|
||||
Component.onCompleted: printer_connection.startPollEndstop()
|
||||
Component.onDestruction: printer_connection.stopPollEndstop()
|
||||
|
||||
Label
|
||||
{
|
||||
|
@ -23,44 +33,144 @@ Column
|
|||
Label
|
||||
{
|
||||
//: Add Printer wizard page description
|
||||
text: qsTr("Please select the type of printer:");
|
||||
text: qsTr("It's a good idea to do a few sanity checks on your Ultimaker. \n You can skip these if you know your machine is functional");
|
||||
}
|
||||
|
||||
ScrollView
|
||||
Row
|
||||
{
|
||||
height: parent.height - 50
|
||||
width: parent.width
|
||||
ListView
|
||||
Label
|
||||
{
|
||||
id: machineList;
|
||||
model: UM.Models.availableMachinesModel
|
||||
delegate: RadioButton
|
||||
{
|
||||
exclusiveGroup: printerGroup;
|
||||
text: model.name;
|
||||
onClicked:
|
||||
{
|
||||
ListView.view.currentIndex = index;
|
||||
}
|
||||
}
|
||||
text: qsTr("Connection: ")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: UM.USBPrinterManager.connectedPrinterList.count ? "Done":"Incomplete"
|
||||
}
|
||||
}
|
||||
Row
|
||||
{
|
||||
Label
|
||||
{
|
||||
text: qsTr("Min endstop X: ")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: x_min_pressed ? qsTr("Works") : qsTr("Not checked")
|
||||
}
|
||||
}
|
||||
Row
|
||||
{
|
||||
Label
|
||||
{
|
||||
text: qsTr("Min endstop Y: ")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: y_min_pressed ? qsTr("Works") : qsTr("Not checked")
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
Row
|
||||
{
|
||||
//: Add Printer wizard field label
|
||||
text: qsTr("Printer Name:");
|
||||
Label
|
||||
{
|
||||
text: qsTr("Min endstop Z: ")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: z_min_pressed ? qsTr("Works") : qsTr("Not checked")
|
||||
}
|
||||
}
|
||||
|
||||
TextField
|
||||
Row
|
||||
{
|
||||
id: machineName; Layout.fillWidth: true; text: machineList.model.getItem(machineList.currentIndex).name
|
||||
Label
|
||||
{
|
||||
text: qsTr("Nozzle temperature check: ")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: printer_connection.extruderTemperature
|
||||
}
|
||||
Button
|
||||
{
|
||||
text: "Start heating"
|
||||
onClicked:
|
||||
{
|
||||
heater_status_label.text = qsTr("Checking")
|
||||
printer_connection.heatupNozzle(190)
|
||||
wizardPage.extruder_target_temp = 190
|
||||
}
|
||||
}
|
||||
Label
|
||||
{
|
||||
id: heater_status_label
|
||||
text: qsTr("Not checked")
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
Row
|
||||
{
|
||||
Layout.fillWidth: true;
|
||||
Layout.fillHeight: true;
|
||||
Label
|
||||
{
|
||||
text: qsTr("bed temperature check: ")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: printer_connection.bedTemperature
|
||||
}
|
||||
Button
|
||||
{
|
||||
text: "Start heating"
|
||||
onClicked:
|
||||
{
|
||||
bed_status_label.text = qsTr("Checking")
|
||||
printer_connection.printer.heatupBed(60)
|
||||
wizardPage.bed_target_temp = 60
|
||||
}
|
||||
}
|
||||
Label
|
||||
{
|
||||
id: bed_status_label
|
||||
text: qsTr("Not checked")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Connections
|
||||
{
|
||||
target: printer_connection
|
||||
onEndstopStateChanged:
|
||||
{
|
||||
if(key == "x_min")
|
||||
{
|
||||
x_min_pressed = true
|
||||
}
|
||||
if(key == "y_min")
|
||||
{
|
||||
y_min_pressed = true
|
||||
}
|
||||
if(key == "z_min")
|
||||
{
|
||||
z_min_pressed = true
|
||||
}
|
||||
}
|
||||
onExtruderTemperatureChanged:
|
||||
{
|
||||
if(printer_connection.extruderTemperature > wizardPage.extruder_target_temp - 10 && printer_connection.extruderTemperature < wizardPage.extruder_target_temp + 10)
|
||||
{
|
||||
heater_status_label.text = qsTr("Works")
|
||||
printer_connection.heatupNozzle(0)
|
||||
}
|
||||
}
|
||||
onBedTemperatureChanged:
|
||||
{
|
||||
if(printer_connection.bedTemperature > wizardPage.bed_target_temp - 5 && printer_connection.bedTemperature < wizardPage.bed_target_temp + 5)
|
||||
{
|
||||
bed_status_label.text = qsTr("Works")
|
||||
printer_connection.heatupBed(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExclusiveGroup
|
||||
|
|
|
@ -13,19 +13,12 @@ Column
|
|||
id: wizardPage
|
||||
property string title
|
||||
anchors.fill: parent;
|
||||
|
||||
Label
|
||||
{
|
||||
text: parent.title
|
||||
font.pointSize: 18;
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
//: Add Printer wizard page description
|
||||
text: qsTr("Please select the type of printer:");
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
height: parent.height - 50
|
||||
|
@ -33,14 +26,26 @@ Column
|
|||
ListView
|
||||
{
|
||||
id: machineList;
|
||||
model: UM.Models.availableMachinesModel
|
||||
delegate: RadioButton
|
||||
model: UM.USBPrinterManager.connectedPrinterList
|
||||
|
||||
delegate:Row
|
||||
{
|
||||
exclusiveGroup: printerGroup;
|
||||
text: model.name;
|
||||
onClicked:
|
||||
id: derp
|
||||
Text
|
||||
{
|
||||
ListView.view.currentIndex = index;
|
||||
id: text_area
|
||||
text: model.name
|
||||
}
|
||||
Button
|
||||
{
|
||||
text: "Update";
|
||||
onClicked:
|
||||
{
|
||||
if(!UM.USBPrinterManager.updateFirmwareBySerial(text_area.text))
|
||||
{
|
||||
status_text.text = "ERROR"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,15 +53,10 @@ Column
|
|||
|
||||
Label
|
||||
{
|
||||
//: Add Printer wizard field label
|
||||
text: qsTr("Printer Name:");
|
||||
id: status_text
|
||||
text: ""
|
||||
}
|
||||
|
||||
TextField
|
||||
{
|
||||
id: machineName; Layout.fillWidth: true; text: machineList.model.getItem(machineList.currentIndex).name
|
||||
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
|
@ -64,8 +64,5 @@ Column
|
|||
Layout.fillHeight: true;
|
||||
}
|
||||
|
||||
ExclusiveGroup
|
||||
{
|
||||
id: printerGroup;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,21 +28,6 @@
|
|||
"machine_center_is_zero": {
|
||||
"default": false
|
||||
},
|
||||
"machine_head_shape_min_x": {
|
||||
"default": 40
|
||||
},
|
||||
"machine_head_shape_min_y": {
|
||||
"default": 10
|
||||
},
|
||||
"machine_head_shape_max_x": {
|
||||
"default": 60
|
||||
},
|
||||
"machine_head_shape_max_y": {
|
||||
"default": 30
|
||||
},
|
||||
"machine_nozzle_gantry_distance": {
|
||||
"default": 55
|
||||
},
|
||||
"machine_extruder_count": {
|
||||
"default": 1
|
||||
},
|
||||
|
@ -67,20 +52,20 @@
|
|||
"machine_head_polygon": {
|
||||
"default": [
|
||||
[
|
||||
-10,
|
||||
10
|
||||
-1,
|
||||
1
|
||||
],
|
||||
[
|
||||
10,
|
||||
10
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
[
|
||||
10,
|
||||
-10
|
||||
1,
|
||||
-1
|
||||
],
|
||||
[
|
||||
-10,
|
||||
-10
|
||||
1,
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
|
|
|
@ -38,14 +38,30 @@
|
|||
"machine_height": { "default": 205 },
|
||||
"machine_heated_bed": { "default": true },
|
||||
|
||||
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"default": [
|
||||
[
|
||||
-40,
|
||||
30
|
||||
],
|
||||
[
|
||||
-40,
|
||||
-10
|
||||
],
|
||||
[
|
||||
60,
|
||||
-10
|
||||
],
|
||||
[
|
||||
60,
|
||||
30
|
||||
]
|
||||
]
|
||||
},
|
||||
"machine_center_is_zero": { "default": false },
|
||||
"machine_nozzle_size": { "default": 0.4 },
|
||||
"machine_head_shape_min_x": { "default": 40 },
|
||||
"machine_head_shape_min_y": { "default": 10 },
|
||||
"machine_head_shape_max_x": { "default": 60 },
|
||||
"machine_head_shape_max_y": { "default": 30 },
|
||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
||||
"gantry_height": { "default": 55 },
|
||||
"machine_use_extruder_offset_to_offset_coords": { "default": true },
|
||||
"machine_gcode_flavor": { "default": "UltiGCode" },
|
||||
"machine_disallowed_areas": { "default": [
|
||||
|
|
|
@ -41,11 +41,28 @@
|
|||
"machine_depth": { "default": 205 },
|
||||
"machine_center_is_zero": { "default": false },
|
||||
"machine_nozzle_size": { "default": 0.4 },
|
||||
"machine_head_shape_min_x": { "default": 75 },
|
||||
"machine_head_shape_min_y": { "default": 18 },
|
||||
"machine_head_shape_max_x": { "default": 18 },
|
||||
"machine_head_shape_max_y": { "default": 35 },
|
||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"default": [
|
||||
[
|
||||
-75,
|
||||
35
|
||||
],
|
||||
[
|
||||
-75,
|
||||
-18
|
||||
],
|
||||
[
|
||||
18,
|
||||
35
|
||||
],
|
||||
[
|
||||
18,
|
||||
-18
|
||||
]
|
||||
]
|
||||
},
|
||||
"gantry_height": { "default": 55 },
|
||||
"machine_use_extruder_offset_to_offset_coords": { "default": true },
|
||||
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||
|
||||
|
|
BIN
resources/themes/cura/fonts/ProximaNova-Black.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-Black.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-Bold.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-Bold.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-BoldIt.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-BoldIt.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-Extrabold.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-Extrabold.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-Light.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-Light.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-LightItalic.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-LightItalic.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-Regular.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-Regular.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNova-RegularItalic.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNova-RegularItalic.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNovaCond-Light.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNovaCond-Light.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNovaCond-LightIt.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNovaCond-LightIt.otf
Normal file
Binary file not shown.
BIN
resources/themes/cura/fonts/ProximaNovaCond-Regular.otf
Normal file
BIN
resources/themes/cura/fonts/ProximaNovaCond-Regular.otf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -35,54 +35,26 @@ QtObject {
|
|||
}
|
||||
}
|
||||
|
||||
property Component open_file_button: Component {
|
||||
property Component open_file_button: Component {
|
||||
ButtonStyle {
|
||||
background: Item {
|
||||
implicitWidth: UM.Theme.sizes.button.width;
|
||||
implicitHeight: UM.Theme.sizes.button.height;
|
||||
|
||||
background: Item{
|
||||
implicitWidth: UM.Theme.sizes.loadfile_button.width
|
||||
implicitHeight: UM.Theme.sizes.loadfile_button.height
|
||||
Rectangle {
|
||||
anchors.bottom: parent.verticalCenter;
|
||||
width: parent.width;
|
||||
height: control.hovered ? parent.height / 2 + label.height : 0;
|
||||
Behavior on height { NumberAnimation { duration: 100; } }
|
||||
|
||||
opacity: control.hovered ? 1.0 : 0.0;
|
||||
Behavior on opacity { NumberAnimation { duration: 100; } }
|
||||
|
||||
Label {
|
||||
id: label;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
text: control.text.replace("&", "");
|
||||
font: UM.Theme.fonts.button_tooltip;
|
||||
color: UM.Theme.colors.button_tooltip_text;
|
||||
}
|
||||
}
|
||||
|
||||
UM.AngledCornerRectangle {
|
||||
anchors.fill: parent;
|
||||
color: {
|
||||
if(control.hovered) {
|
||||
return UM.Theme.colors.button_active_hover;
|
||||
} else {
|
||||
return UM.Theme.colors.button_active;
|
||||
}
|
||||
}
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: control.hovered ? UM.Theme.colors.load_save_button_hover : UM.Theme.colors.load_save_button
|
||||
Behavior on color { ColorAnimation { duration: 50; } }
|
||||
cornerSize: UM.Theme.sizes.default_margin.width;
|
||||
}
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
text: control.text
|
||||
color: UM.Theme.colors.load_save_button_text
|
||||
font: UM.Theme.fonts.default
|
||||
}
|
||||
}
|
||||
|
||||
label: Item {
|
||||
Image {
|
||||
anchors.centerIn: parent;
|
||||
|
||||
source: control.iconSource;
|
||||
width: UM.Theme.sizes.button_icon.width;
|
||||
height: UM.Theme.sizes.button_icon.height;
|
||||
|
||||
sourceSize: UM.Theme.sizes.button_icon;
|
||||
}
|
||||
label: Label{
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +62,6 @@ QtObject {
|
|||
property Component tool_button: Component {
|
||||
ButtonStyle {
|
||||
background: Item {
|
||||
///////////TODO CHANGE SIZES!!
|
||||
implicitWidth: UM.Theme.sizes.button.width;
|
||||
implicitHeight: UM.Theme.sizes.button.height;
|
||||
|
||||
|
@ -99,7 +70,6 @@ QtObject {
|
|||
anchors.top: parent.verticalCenter;
|
||||
|
||||
width: parent.width;
|
||||
///////////TODO CHANGE LABELHEIGHT!!
|
||||
height: control.hovered ? parent.height / 2 + label.height : 0;
|
||||
Behavior on height { NumberAnimation { duration: 100; } }
|
||||
|
||||
|
@ -109,7 +79,7 @@ QtObject {
|
|||
Label {
|
||||
id: label
|
||||
anchors.bottom: parent.bottom
|
||||
text: control.text.replace("&", "");
|
||||
text: control.text
|
||||
font: UM.Theme.fonts.button_tooltip;
|
||||
color: UM.Theme.colors.button_tooltip_text;
|
||||
}
|
||||
|
@ -138,13 +108,14 @@ QtObject {
|
|||
Behavior on color { ColorAnimation { duration: 50; } }
|
||||
|
||||
Label {
|
||||
id: tool_button_arrow
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width / 2;
|
||||
anchors.rightMargin: (UM.Theme.sizes.button.width - UM.Theme.sizes.button_icon.width - tool_button_arrow.width) / 2
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
text: "▼";
|
||||
font: UM.Theme.fonts.small;
|
||||
visible: control.menu != null;
|
||||
color: "white";
|
||||
color: UM.Theme.colors.button_text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,34 +133,98 @@ QtObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
property Component tool_button_panel: Component {
|
||||
ButtonStyle {
|
||||
background: Item {
|
||||
implicitWidth: UM.Theme.sizes.button.width;
|
||||
implicitHeight: UM.Theme.sizes.button.height;
|
||||
|
||||
Rectangle {
|
||||
id: tool_button_background
|
||||
anchors.top: parent.verticalCenter;
|
||||
|
||||
width: parent.width;
|
||||
height: control.hovered ? parent.height / 2 + label.height : 0;
|
||||
Behavior on height { NumberAnimation { duration: 100; } }
|
||||
|
||||
opacity: control.hovered ? 1.0 : 0.0;
|
||||
Behavior on opacity { NumberAnimation { duration: 100; } }
|
||||
|
||||
Label {
|
||||
id: label
|
||||
anchors.bottom: parent.bottom
|
||||
text: control.text
|
||||
width: UM.Theme.sizes.button.width;
|
||||
wrapMode: Text.WordWrap
|
||||
font: UM.Theme.fonts.button_tooltip;
|
||||
color: UM.Theme.colors.button_tooltip_text;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonFace;
|
||||
|
||||
anchors.fill: parent;
|
||||
|
||||
property bool down: control.pressed || (control.checkable && control.checked);
|
||||
|
||||
color: {
|
||||
if(!control.enabled) {
|
||||
return UM.Theme.colors.button_disabled;
|
||||
} else if(control.checkable && control.checked && control.hovered) {
|
||||
return UM.Theme.colors.button_active_hover;
|
||||
} else if(control.pressed || (control.checkable && control.checked)) {
|
||||
return UM.Theme.colors.button_active;
|
||||
} else if(control.hovered) {
|
||||
return UM.Theme.colors.button_hover;
|
||||
} else {
|
||||
return UM.Theme.colors.button;
|
||||
}
|
||||
}
|
||||
Behavior on color { ColorAnimation { duration: 50; } }
|
||||
}
|
||||
}
|
||||
|
||||
label: Item {
|
||||
Image {
|
||||
anchors.centerIn: parent;
|
||||
|
||||
source: control.iconSource;
|
||||
width: UM.Theme.sizes.button_icon.width;
|
||||
height: UM.Theme.sizes.button_icon.height;
|
||||
|
||||
sourceSize: UM.Theme.sizes.button_icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
property Component progressbar: Component{
|
||||
ProgressBarStyle {
|
||||
background: UM.AngledCornerRectangle {
|
||||
cornerSize: UM.Theme.sizes.progressbar_control.height
|
||||
implicitWidth: UM.Theme.sizes.progressbar.width
|
||||
background:Rectangle {
|
||||
implicitWidth: UM.Theme.sizes.message.width - (UM.Theme.sizes.default_margin.width * 2)
|
||||
implicitHeight: UM.Theme.sizes.progressbar.height
|
||||
x: UM.Theme.sizes.default_margin.width
|
||||
color: UM.Theme.colors.progressbar_background
|
||||
}
|
||||
progress: UM.AngledCornerRectangle {
|
||||
cornerSize: UM.Theme.sizes.progressbar_control.height
|
||||
progress: Rectangle {
|
||||
color: control.indeterminate ? "transparent" : UM.Theme.colors.progressbar_control
|
||||
|
||||
UM.AngledCornerRectangle {
|
||||
cornerSize: UM.Theme.sizes.progressbar_control.height
|
||||
Rectangle{
|
||||
color: UM.Theme.colors.progressbar_control
|
||||
width: UM.Theme.sizes.progressbar_control.width
|
||||
height: UM.Theme.sizes.progressbar_control.height
|
||||
x: UM.Theme.sizes.default_margin.width
|
||||
visible: control.indeterminate
|
||||
|
||||
SequentialAnimation on x {
|
||||
id: xAnim
|
||||
property int animEndPoint: UM.Theme.sizes.progressbar.width - UM.Theme.sizes.progressbar_control.width
|
||||
property int animEndPoint: UM.Theme.sizes.message.width - UM.Theme.sizes.default_margin.width - UM.Theme.sizes.progressbar_control.width
|
||||
running: control.indeterminate
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { from: 0; to: xAnim.animEndPoint; duration: 2000;}
|
||||
NumberAnimation { from: xAnim.animEndPoint; to: 0; duration: 2000;}
|
||||
NumberAnimation { from: UM.Theme.sizes.default_margin.width; to: xAnim.animEndPoint; duration: 2000;}
|
||||
NumberAnimation { from: xAnim.animEndPoint; to: UM.Theme.sizes.default_margin.width; duration: 2000;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,52 +3,52 @@
|
|||
"large": {
|
||||
"size": 1.5,
|
||||
"bold": true,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"default": {
|
||||
"size": 1,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"default_allcaps": {
|
||||
"size": 1,
|
||||
"capitalize": true,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"small": {
|
||||
"size": 0.75,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"tiny": {
|
||||
"size": 0.5,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"caption": {
|
||||
"size": 0.75,
|
||||
"italic": true,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"sidebar_header": {
|
||||
"size": 0.75,
|
||||
"capitalize": true,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"sidebar_save_to": {
|
||||
"size": 1.0,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"timeslider_time": {
|
||||
"size": 1.0,
|
||||
"bold": true,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"button_tooltip": {
|
||||
"size": 0.75,
|
||||
"capitalize": true,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
},
|
||||
"setting_category": {
|
||||
"size": 1.5,
|
||||
"family": "Roboto"
|
||||
"family": "ProximaNova"
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -66,15 +66,20 @@
|
|||
"text_hover": [35, 35, 35, 255],
|
||||
"text_pressed": [12, 169, 227, 255],
|
||||
|
||||
"button": [160, 163, 171, 255],
|
||||
"button_hover": [140, 144, 154, 255],
|
||||
"button": [139, 143, 153, 255],
|
||||
"button_hover": [116, 120, 127, 255],
|
||||
"button_active": [12, 169, 227, 255],
|
||||
"button_active_hover": [34, 150, 199, 255],
|
||||
"button_lining": [140, 144, 154, 255],
|
||||
"button_active_hover": [77, 184, 226, 255],
|
||||
"button_lining": [208, 210, 211, 255],
|
||||
"button_text": [255, 255, 255, 255],
|
||||
"button_disabled": [245, 245, 245, 255],
|
||||
"button_tooltip_text": [35, 35, 35, 255],
|
||||
|
||||
"load_save_button": [0, 0, 0, 255],
|
||||
"load_save_button_text": [255, 255, 255, 255],
|
||||
"load_save_button_hover": [43, 45, 46, 255],
|
||||
"load_save_button_active": [43, 45, 46, 255],
|
||||
|
||||
"scrollbar_background": [245, 245, 245, 255],
|
||||
"scrollbar_handle": [205, 202, 201, 255],
|
||||
"scrollbar_handle_hover": [174, 174, 174, 255],
|
||||
|
@ -98,7 +103,7 @@
|
|||
"setting_validation_warning": [255, 186, 15, 255],
|
||||
"setting_validation_ok": [255, 255, 255, 255],
|
||||
|
||||
"progressbar_background": [245, 245, 245, 255],
|
||||
"progressbar_background": [208, 210, 211, 255],
|
||||
"progressbar_control": [12, 169, 227, 255],
|
||||
|
||||
"slider_groove": [245, 245, 245, 255],
|
||||
|
@ -126,8 +131,8 @@
|
|||
"save_button_printtime_text": [12, 169, 227, 255],
|
||||
"save_button_background": [249, 249, 249, 255],
|
||||
|
||||
"message": [160, 163, 171, 255],
|
||||
"message_text": [35, 35, 35, 255],
|
||||
"message_background": [255, 255, 255, 255],
|
||||
"message_text": [12, 169, 227, 255],
|
||||
|
||||
"tool_panel_background": [255, 255, 255, 255]
|
||||
},
|
||||
|
@ -135,11 +140,15 @@
|
|||
"sizes": {
|
||||
"window_margin": [2.0, 2.0],
|
||||
"default_margin": [1.0, 1.0],
|
||||
"default_lining": [0.1, 0.1],
|
||||
"panel": [22.0, 10.0],
|
||||
"logo": [9.5, 2.0],
|
||||
"toolbar_button": [2.0, 2.0],
|
||||
"toolbar_spacing": [1.0, 1.0],
|
||||
|
||||
"loadfile_button": [11.0, 2.4],
|
||||
"loadfile_margin": [0.8, 0.4],
|
||||
|
||||
"section": [22.0, 3.0],
|
||||
"section_icon": [2.14, 2.14],
|
||||
"section_text_margin": [0.33, 0.33],
|
||||
|
@ -153,11 +162,11 @@
|
|||
"standard_list_lineheight": [1.5, 1.5],
|
||||
"standard_list_input": [20.0, 25.0],
|
||||
|
||||
"button": [4.25, 4.25],
|
||||
"button_icon": [2.9, 2.9],
|
||||
"button": [3.2, 3.2],
|
||||
"button_icon": [2.5, 2.5],
|
||||
|
||||
"progressbar": [26.0, 0.5],
|
||||
"progressbar_control": [8.0, 0.5],
|
||||
"progressbar": [26.0, 0.8],
|
||||
"progressbar_control": [8.0, 0.8],
|
||||
"progressbar_padding": [0.0, 1.0],
|
||||
|
||||
"scrollbar": [0.5, 0.5],
|
||||
|
@ -184,6 +193,7 @@
|
|||
"wizard_progress": [10.0, 0.0],
|
||||
|
||||
"message": [30.0, 5.0],
|
||||
"message_close": [1.25, 1.25]
|
||||
"message_close": [1.25, 1.25],
|
||||
"message_button": [6.0, 1.8]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue