mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-23 22:54:01 -06:00
Merge pull request #4967 from Ultimaker/ui_rework_4_0
Merge the entire UI rework planned for the new redesign of Cura 4.0
This commit is contained in:
commit
4c82f8b74f
204 changed files with 11335 additions and 8853 deletions
|
@ -38,12 +38,13 @@ class Account(QObject):
|
|||
|
||||
self._callback_port = 32118
|
||||
self._oauth_root = "https://account.ultimaker.com"
|
||||
self._cloud_api_root = "https://api.ultimaker.com"
|
||||
|
||||
self._oauth_settings = OAuth2Settings(
|
||||
OAUTH_SERVER_URL= self._oauth_root,
|
||||
CALLBACK_PORT=self._callback_port,
|
||||
CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port),
|
||||
CLIENT_ID="um----------------------------ultimaker_cura",
|
||||
CLIENT_ID="um---------------ultimaker_cura_drive_plugin",
|
||||
CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download packages.rating.read packages.rating.write",
|
||||
AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data",
|
||||
AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root),
|
||||
|
|
|
@ -441,6 +441,7 @@ class CuraApplication(QtApplication):
|
|||
"XmlMaterialProfile", #Cura crashes without this one.
|
||||
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
|
||||
"PrepareStage", #Cura is useless without this one since you can't load models.
|
||||
"PreviewStage", #This shows the list of the plugin views that are installed in Cura.
|
||||
"MonitorStage", #Major part of Cura's functionality.
|
||||
"LocalFileOutputDevice", #Major part of Cura's functionality.
|
||||
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
|
||||
|
@ -633,9 +634,7 @@ class CuraApplication(QtApplication):
|
|||
self._message_box_callback(button, *self._message_box_callback_arguments)
|
||||
self._message_box_callback = None
|
||||
self._message_box_callback_arguments = []
|
||||
|
||||
showPrintMonitor = pyqtSignal(bool, arguments = ["show"])
|
||||
|
||||
|
||||
def setSaveDataEnabled(self, enabled: bool) -> None:
|
||||
self._save_data_enabled = enabled
|
||||
|
||||
|
@ -1666,7 +1665,9 @@ class CuraApplication(QtApplication):
|
|||
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions
|
||||
|
||||
if is_non_sliceable:
|
||||
self.callLater(lambda: self.getController().setActiveView("SimulationView"))
|
||||
# Need to switch first to the preview stage and then to layer view
|
||||
self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"),
|
||||
self.getController().setActiveView("SimulationView")))
|
||||
|
||||
block_slicing_decorator = BlockSlicingDecorator()
|
||||
node.addDecorator(block_slicing_decorator)
|
||||
|
|
24
cura/CuraView.py
Normal file
24
cura/CuraView.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import pyqtProperty, QUrl
|
||||
|
||||
from UM.View.View import View
|
||||
|
||||
|
||||
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
|
||||
# to indicate this.
|
||||
# MainComponent works in the same way the MainComponent of a stage.
|
||||
# the stageMenuComponent returns an item that should be used somehwere in the stage menu. It's up to the active stage
|
||||
# to actually do something with this.
|
||||
class CuraView(View):
|
||||
def __init__(self, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
@pyqtProperty(QUrl, constant = True)
|
||||
def mainComponent(self) -> QUrl:
|
||||
return self.getDisplayComponent("main")
|
||||
|
||||
@pyqtProperty(QUrl, constant = True)
|
||||
def stageMenuComponent(self) -> QUrl:
|
||||
return self.getDisplayComponent("menu")
|
|
@ -1,4 +1,6 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
|
|
|
@ -394,21 +394,7 @@ class PrintInformation(QObject):
|
|||
return
|
||||
active_machine_type_name = global_container_stack.definition.getName()
|
||||
|
||||
abbr_machine = ""
|
||||
for word in re.findall(r"[\w']+", active_machine_type_name):
|
||||
if word.lower() == "ultimaker":
|
||||
abbr_machine += "UM"
|
||||
elif word.isdigit():
|
||||
abbr_machine += word
|
||||
else:
|
||||
stripped_word = self._stripAccents(word.upper())
|
||||
# - use only the first character if the word is too long (> 3 characters)
|
||||
# - use the whole word if it's not too long (<= 3 characters)
|
||||
if len(stripped_word) > 3:
|
||||
stripped_word = stripped_word[0]
|
||||
abbr_machine += stripped_word
|
||||
|
||||
self._abbr_machine = abbr_machine
|
||||
self._abbr_machine = self._application.getMachineManager().getAbbreviatedMachineName(active_machine_type_name)
|
||||
|
||||
## Utility method that strips accents from characters (eg: â -> a)
|
||||
def _stripAccents(self, to_strip: str) -> str:
|
||||
|
|
|
@ -211,6 +211,11 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
|||
self._unique_configurations.sort(key = lambda k: k.printerType)
|
||||
self.uniqueConfigurationsChanged.emit()
|
||||
|
||||
# Returns the unique configurations of the printers within this output device
|
||||
@pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
|
||||
def uniquePrinterTypes(self) -> List[str]:
|
||||
return list(set([configuration.printerType for configuration in self._unique_configurations]))
|
||||
|
||||
def _onPrintersChanged(self) -> None:
|
||||
for printer in self._printers:
|
||||
printer.configurationChanged.connect(self._updateUniqueConfigurations)
|
||||
|
@ -238,4 +243,4 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
|||
if not self._firmware_updater:
|
||||
return
|
||||
|
||||
self._firmware_updater.updateFirmware(firmware_file)
|
||||
self._firmware_updater.updateFirmware(firmware_file)
|
||||
|
|
|
@ -63,7 +63,7 @@ class ExtruderManager(QObject):
|
|||
if not self._application.getGlobalContainerStack():
|
||||
return None # No active machine, so no active extruder.
|
||||
try:
|
||||
return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId()
|
||||
return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self.activeExtruderIndex)].getId()
|
||||
except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong.
|
||||
return None
|
||||
|
||||
|
@ -144,7 +144,7 @@ class ExtruderManager(QObject):
|
|||
|
||||
@pyqtSlot(result = QObject)
|
||||
def getActiveExtruderStack(self) -> Optional["ExtruderStack"]:
|
||||
return self.getExtruderStack(self._active_extruder_index)
|
||||
return self.getExtruderStack(self.activeExtruderIndex)
|
||||
|
||||
## Get an extruder stack by index
|
||||
def getExtruderStack(self, index) -> Optional["ExtruderStack"]:
|
||||
|
|
|
@ -52,8 +52,8 @@ class ExtruderStack(CuraContainerStack):
|
|||
return super().getNextStack()
|
||||
|
||||
def setEnabled(self, enabled: bool) -> None:
|
||||
if "enabled" not in self._metadata:
|
||||
self.setMetaDataEntry("enabled", "True")
|
||||
if self.getMetaDataEntry("enabled", True) == enabled: # No change.
|
||||
return # Don't emit a signal then.
|
||||
self.setMetaDataEntry("enabled", str(enabled))
|
||||
self.enabledChanged.emit()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
|
||||
|
@ -24,8 +24,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
|
||||
## Human-readable name of the extruder.
|
||||
NameRole = Qt.UserRole + 2
|
||||
## Is the extruder enabled?
|
||||
EnabledRole = Qt.UserRole + 9
|
||||
|
||||
## Colour of the material loaded in the extruder.
|
||||
ColorRole = Qt.UserRole + 3
|
||||
|
@ -47,6 +45,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
VariantRole = Qt.UserRole + 7
|
||||
StackRole = Qt.UserRole + 8
|
||||
|
||||
MaterialBrandRole = Qt.UserRole + 9
|
||||
ColorNameRole = Qt.UserRole + 10
|
||||
|
||||
## Is the extruder enabled?
|
||||
EnabledRole = Qt.UserRole + 11
|
||||
|
||||
## List of colours to display if there is no material or the material has no known
|
||||
# colour.
|
||||
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
|
||||
|
@ -67,7 +71,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
self.addRoleName(self.MaterialRole, "material")
|
||||
self.addRoleName(self.VariantRole, "variant")
|
||||
self.addRoleName(self.StackRole, "stack")
|
||||
|
||||
self.addRoleName(self.MaterialBrandRole, "material_brand")
|
||||
self.addRoleName(self.ColorNameRole, "color_name")
|
||||
self._update_extruder_timer = QTimer()
|
||||
self._update_extruder_timer.setInterval(100)
|
||||
self._update_extruder_timer.setSingleShot(True)
|
||||
|
@ -160,7 +165,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
def __updateExtruders(self):
|
||||
extruders_changed = False
|
||||
|
||||
if self.rowCount() != 0:
|
||||
if self.count != 0:
|
||||
extruders_changed = True
|
||||
|
||||
items = []
|
||||
|
@ -172,7 +177,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
|
||||
|
||||
for extruder in Application.getInstance().getExtruderManager().getActiveExtruderStacks():
|
||||
position = extruder.getMetaDataEntry("position", default = "0") # Get the position
|
||||
position = extruder.getMetaDataEntry("position", default = "0")
|
||||
try:
|
||||
position = int(position)
|
||||
except ValueError:
|
||||
|
@ -183,7 +188,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
|
||||
default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0]
|
||||
color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color
|
||||
|
||||
material_brand = extruder.material.getMetaDataEntry("brand", default = "generic")
|
||||
color_name = extruder.material.getMetaDataEntry("color_name")
|
||||
# construct an item with only the relevant information
|
||||
item = {
|
||||
"id": extruder.getId(),
|
||||
|
@ -195,6 +201,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
"material": extruder.material.getName() if extruder.material else "",
|
||||
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
|
||||
"stack": extruder,
|
||||
"material_brand": material_brand,
|
||||
"color_name": color_name
|
||||
}
|
||||
|
||||
items.append(item)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
import collections
|
||||
import time
|
||||
import re
|
||||
import unicodedata
|
||||
from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast
|
||||
|
||||
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||
|
@ -872,7 +874,7 @@ class MachineManager(QObject):
|
|||
caution_message = Message(catalog.i18nc(
|
||||
"@info:generic",
|
||||
"Settings have been changed to match the current availability of extruders: [%s]" % ", ".join(add_user_changes)),
|
||||
lifetime=0,
|
||||
lifetime = 0,
|
||||
title = catalog.i18nc("@info:title", "Settings updated"))
|
||||
caution_message.show()
|
||||
|
||||
|
@ -1534,9 +1536,32 @@ class MachineManager(QObject):
|
|||
name = self._current_quality_group.name
|
||||
return name
|
||||
|
||||
@pyqtProperty(bool, notify = activeQualityGroupChanged)
|
||||
def hasNotSupportedQuality(self) -> bool:
|
||||
return self._current_quality_group is None and self._current_quality_changes_group is None
|
||||
|
||||
def _updateUponMaterialMetadataChange(self) -> None:
|
||||
if self._global_container_stack is None:
|
||||
return
|
||||
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||
self.updateMaterialWithVariant(None)
|
||||
self._updateQualityWithMaterial()
|
||||
|
||||
## This function will translate any printer type name to an abbreviated printer type name
|
||||
@pyqtSlot(str, result = str)
|
||||
def getAbbreviatedMachineName(self, machine_type_name: str) -> str:
|
||||
abbr_machine = ""
|
||||
for word in re.findall(r"[\w']+", machine_type_name):
|
||||
if word.lower() == "ultimaker":
|
||||
abbr_machine += "UM"
|
||||
elif word.isdigit():
|
||||
abbr_machine += word
|
||||
else:
|
||||
stripped_word = "".join(char for char in unicodedata.normalize("NFD", word.upper()) if unicodedata.category(char) != "Mn")
|
||||
# - use only the first character if the word is too long (> 3 characters)
|
||||
# - use the whole word if it's not too long (<= 3 characters)
|
||||
if len(stripped_word) > 3:
|
||||
stripped_word = stripped_word[0]
|
||||
abbr_machine += stripped_word
|
||||
|
||||
return abbr_machine
|
||||
|
|
|
@ -1,23 +1,33 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import pyqtProperty, QUrl
|
||||
|
||||
from UM.Stage import Stage
|
||||
|
||||
|
||||
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
|
||||
# to indicate this.
|
||||
# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
|
||||
# buttons and elements. This component will be drawn over the bar & main component.
|
||||
# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
|
||||
# of the screen.
|
||||
class CuraStage(Stage):
|
||||
|
||||
def __init__(self, parent = None):
|
||||
def __init__(self, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
@pyqtProperty(str, constant = True)
|
||||
def stageId(self):
|
||||
def stageId(self) -> str:
|
||||
return self.getPluginId()
|
||||
|
||||
@pyqtProperty(QUrl, constant = True)
|
||||
def mainComponent(self):
|
||||
def mainComponent(self) -> QUrl:
|
||||
return self.getDisplayComponent("main")
|
||||
|
||||
@pyqtProperty(QUrl, constant = True)
|
||||
def sidebarComponent(self):
|
||||
def sidebarComponent(self) -> QUrl:
|
||||
return self.getDisplayComponent("sidebar")
|
||||
|
||||
@pyqtProperty(QUrl, constant = True)
|
||||
def stageMenuComponent(self) -> QUrl:
|
||||
return self.getDisplayComponent("menu")
|
|
@ -195,7 +195,7 @@ class ProcessSlicedLayersJob(Job):
|
|||
if extruders:
|
||||
material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32)
|
||||
for extruder in extruders:
|
||||
position = int(extruder.getMetaDataEntry("position", default="0")) # Get the position
|
||||
position = int(extruder.getMetaDataEntry("position", default = "0"))
|
||||
try:
|
||||
default_color = ExtrudersModel.defaultColors[position]
|
||||
except IndexError:
|
||||
|
|
|
@ -22,7 +22,7 @@ Cura.MachineAction
|
|||
{
|
||||
id: firmwareUpdaterMachineAction
|
||||
anchors.fill: parent;
|
||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||
UM.I18nCatalog { id: catalog; name: "cura"}
|
||||
spacing: UM.Theme.getSize("default_margin").height
|
||||
|
||||
Label
|
||||
|
|
|
@ -20,7 +20,7 @@ UM.Dialog
|
|||
|
||||
GridLayout
|
||||
{
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||
anchors.fill: parent;
|
||||
Layout.fillWidth: true
|
||||
columnSpacing: 16 * screenScaleFactor
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
|
@ -23,7 +23,7 @@ Cura.MachineAction
|
|||
target: base.extrudersModel
|
||||
onModelChanged:
|
||||
{
|
||||
var extruderCount = base.extrudersModel.rowCount();
|
||||
var extruderCount = base.extrudersModel.count;
|
||||
base.extruderTabsCount = extruderCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
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"}
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
visible: manager.hasWarnings
|
||||
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
|
||||
|
@ -25,6 +25,8 @@ Button
|
|||
width: UM.Theme.getSize("save_button_specs_icons").width
|
||||
height: UM.Theme.getSize("save_button_specs_icons").height
|
||||
|
||||
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Item
|
||||
|
@ -33,7 +35,6 @@ Button
|
|||
{
|
||||
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"
|
||||
|
|
|
@ -1,45 +1,40 @@
|
|||
// Copyright (c) 2017 Ultimaker B.V.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
// parent could be undefined as this component is not visible at all times
|
||||
width: parent ? parent.width : 0
|
||||
height: parent ? parent.height : 0
|
||||
|
||||
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
|
||||
Rectangle
|
||||
{
|
||||
id: viewportOverlay
|
||||
|
||||
color: UM.Theme.getColor("viewport_overlay")
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onWheel: wheel.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
id: monitorViewComponent
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
property real maximumWidth: parent.width
|
||||
property real maximumHeight: parent.height
|
||||
|
||||
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
|
||||
visible: sourceComponent != null
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2017 Ultimaker B.V.
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
Item
|
||||
{
|
||||
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
|
||||
Rectangle
|
||||
{
|
||||
id: viewportOverlay
|
||||
|
||||
color: UM.Theme.getColor("viewport_overlay")
|
||||
anchors.fill: parent
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onWheel: wheel.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
id: monitorViewComponent
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
height: parent.height
|
||||
|
||||
property real maximumWidth: parent.width
|
||||
property real maximumHeight: parent.height
|
||||
|
||||
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
|
||||
}
|
||||
}
|
23
plugins/MonitorStage/MonitorMenu.qml
Normal file
23
plugins/MonitorStage/MonitorMenu.qml
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
signal showTooltip(Item item, point location, string text)
|
||||
signal hideTooltip()
|
||||
|
||||
Cura.MachineSelector
|
||||
{
|
||||
id: machineSelection
|
||||
headerCornerSide: Cura.RoundedRectangle.Direction.All
|
||||
width: UM.Theme.getSize("machine_selector_widget").width
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
|
@ -65,15 +65,10 @@ class MonitorStage(CuraStage):
|
|||
# We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early)
|
||||
Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
|
||||
self._onOutputDevicesChanged()
|
||||
self._updateMainOverlay()
|
||||
self._updateSidebar()
|
||||
|
||||
def _updateMainOverlay(self):
|
||||
main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("MonitorStage"),
|
||||
"MonitorMainView.qml")
|
||||
self.addDisplayComponent("main", main_component_path)
|
||||
|
||||
def _updateSidebar(self):
|
||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
||||
"MonitorSidebar.qml")
|
||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
||||
plugin_path = Application.getInstance().getPluginRegistry().getPluginPath(self.getPluginId())
|
||||
if plugin_path is not None:
|
||||
menu_component_path = os.path.join(plugin_path, "MonitorMenu.qml")
|
||||
main_component_path = os.path.join(plugin_path, "MonitorMain.qml")
|
||||
self.addDisplayComponent("menu", menu_component_path)
|
||||
self.addDisplayComponent("main", main_component_path)
|
||||
|
|
|
@ -7,14 +7,16 @@ from . import MonitorStage
|
|||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"stage": {
|
||||
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def register(app):
|
||||
return {
|
||||
"stage": MonitorStage.MonitorStage()
|
||||
|
|
|
@ -265,7 +265,6 @@ Item {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width
|
||||
height: width
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
|
||||
source: UM.Theme.getIcon("minus")
|
||||
|
|
|
@ -31,7 +31,7 @@ UM.Dialog
|
|||
|
||||
Item
|
||||
{
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||
id: base
|
||||
property int columnWidth: Math.round((base.width / 2) - UM.Theme.getSize("default_margin").width)
|
||||
property int textMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||
|
@ -141,7 +141,6 @@ UM.Dialog
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Math.round(control.width / 2.7)
|
||||
height: Math.round(control.height / 2.7)
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: palette.text
|
||||
source: UM.Theme.getIcon("cross1")
|
||||
|
@ -176,7 +175,6 @@ UM.Dialog
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Math.round(control.width / 2.5)
|
||||
height: Math.round(control.height / 2.5)
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: control.enabled ? palette.text : disabledPalette.text
|
||||
source: UM.Theme.getIcon("arrow_bottom")
|
||||
|
@ -211,7 +209,6 @@ UM.Dialog
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Math.round(control.width / 2.5)
|
||||
height: Math.round(control.height / 2.5)
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: control.enabled ? palette.text : disabledPalette.text
|
||||
source: UM.Theme.getIcon("arrow_top")
|
||||
|
@ -260,7 +257,7 @@ UM.Dialog
|
|||
|
||||
Rectangle
|
||||
{
|
||||
color: UM.Theme.getColor("sidebar")
|
||||
color: UM.Theme.getColor("main_background")
|
||||
anchors.left: activeScripts.right
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
anchors.right: parent.right
|
||||
|
@ -415,7 +412,7 @@ UM.Dialog
|
|||
}
|
||||
}
|
||||
|
||||
Cura.SidebarTooltip
|
||||
Cura.PrintSetupTooltip
|
||||
{
|
||||
id: tooltip
|
||||
}
|
||||
|
@ -498,7 +495,6 @@ UM.Dialog
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Math.round(parent.width / 2)
|
||||
height: Math.round(parent.height / 2)
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
|
||||
control.pressed ? UM.Theme.getColor("action_button_active_text") :
|
||||
|
|
134
plugins/PrepareStage/PrepareMenu.qml
Normal file
134
plugins/PrepareStage/PrepareMenu.qml
Normal file
|
@ -0,0 +1,134 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||
|
||||
Item
|
||||
{
|
||||
id: prepareMenu
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
// Item to ensure that all of the buttons are nicely centered.
|
||||
Item
|
||||
{
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: openFileButton.width + itemRow.width + UM.Theme.getSize("default_margin").width
|
||||
height: parent.height
|
||||
|
||||
RowLayout
|
||||
{
|
||||
id: itemRow
|
||||
|
||||
anchors.left: openFileButton.right
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
|
||||
width: Math.round(0.9 * prepareMenu.width)
|
||||
height: parent.height
|
||||
spacing: 0
|
||||
|
||||
Cura.MachineSelector
|
||||
{
|
||||
id: machineSelection
|
||||
headerCornerSide: Cura.RoundedRectangle.Direction.Left
|
||||
Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width
|
||||
Layout.maximumWidth: UM.Theme.getSize("machine_selector_widget").width
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
// Separator line
|
||||
Rectangle
|
||||
{
|
||||
height: parent.height
|
||||
width: UM.Theme.getSize("default_lining").width
|
||||
color: UM.Theme.getColor("lining")
|
||||
}
|
||||
|
||||
Cura.ConfigurationMenu
|
||||
{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: itemRow.width - machineSelection.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width
|
||||
}
|
||||
|
||||
// Separator line
|
||||
Rectangle
|
||||
{
|
||||
height: parent.height
|
||||
width: UM.Theme.getSize("default_lining").width
|
||||
color: UM.Theme.getColor("lining")
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: printSetupSelectorItem
|
||||
// This is a work around to prevent the printSetupSelector from having to be re-loaded every time
|
||||
// a stage switch is done.
|
||||
children: [printSetupSelector]
|
||||
height: childrenRect.height
|
||||
width: childrenRect.width
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
id: openFileButton
|
||||
height: UM.Theme.getSize("stage_menu").height
|
||||
width: UM.Theme.getSize("stage_menu").height
|
||||
onClicked: Cura.Actions.open.trigger()
|
||||
hoverEnabled: true
|
||||
|
||||
contentItem: Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: buttonIcon
|
||||
anchors.centerIn: parent
|
||||
source: UM.Theme.getIcon("load")
|
||||
width: UM.Theme.getSize("button_icon").width
|
||||
height: UM.Theme.getSize("button_icon").height
|
||||
color: UM.Theme.getColor("toolbar_button_text")
|
||||
|
||||
sourceSize.height: height
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle
|
||||
{
|
||||
id: background
|
||||
height: UM.Theme.getSize("stage_menu").height
|
||||
width: UM.Theme.getSize("stage_menu").height
|
||||
|
||||
radius: UM.Theme.getSize("default_radius").width
|
||||
color: openFileButton.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
|
||||
}
|
||||
|
||||
DropShadow
|
||||
{
|
||||
id: shadow
|
||||
// Don't blur the shadow
|
||||
radius: 0
|
||||
anchors.fill: background
|
||||
source: background
|
||||
verticalOffset: 2
|
||||
visible: true
|
||||
color: UM.Theme.getColor("action_button_shadow")
|
||||
// Should always be drawn behind the background.
|
||||
z: background.z - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,13 +2,14 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import os.path
|
||||
from UM.Application import Application
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Resources import Resources
|
||||
from cura.Stages.CuraStage import CuraStage
|
||||
|
||||
|
||||
|
||||
## Stage for preparing model (slicing).
|
||||
class PrepareStage(CuraStage):
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
||||
|
@ -16,4 +17,7 @@ class PrepareStage(CuraStage):
|
|||
def _engineCreated(self):
|
||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
||||
"PrepareSidebar.qml")
|
||||
|
||||
menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
|
||||
self.addDisplayComponent("menu", menu_component_path)
|
||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
||||
|
|
18
plugins/PreviewStage/PreviewMain.qml
Normal file
18
plugins/PreviewStage/PreviewMain.qml
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
|
||||
import UM 1.0 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
Loader
|
||||
{
|
||||
id: previewMain
|
||||
|
||||
source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : ""
|
||||
}
|
74
plugins/PreviewStage/PreviewMenu.qml
Normal file
74
plugins/PreviewStage/PreviewMenu.qml
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
id: previewMenu
|
||||
|
||||
property real itemHeight: height - 2 * UM.Theme.getSize("default_lining").width
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
|
||||
Row
|
||||
{
|
||||
id: stageMenuRow
|
||||
anchors.centerIn: parent
|
||||
height: parent.height
|
||||
|
||||
Cura.ViewsSelector
|
||||
{
|
||||
id: viewsSelector
|
||||
height: parent.height
|
||||
width: UM.Theme.getSize("views_selector").width
|
||||
headerCornerSide: Cura.RoundedRectangle.Direction.Left
|
||||
}
|
||||
|
||||
// Separator line
|
||||
Rectangle
|
||||
{
|
||||
height: parent.height
|
||||
// If there is no viewPanel, we only need a single spacer, so hide this one.
|
||||
visible: viewPanel.source != ""
|
||||
width: visible ? UM.Theme.getSize("default_lining").width : 0
|
||||
|
||||
color: UM.Theme.getColor("lining")
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
id: viewPanel
|
||||
height: parent.height
|
||||
width: childrenRect.width
|
||||
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
|
||||
}
|
||||
|
||||
// Separator line
|
||||
Rectangle
|
||||
{
|
||||
height: parent.height
|
||||
width: UM.Theme.getSize("default_lining").width
|
||||
color: UM.Theme.getColor("lining")
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: printSetupSelectorItem
|
||||
// This is a work around to prevent the printSetupSelector from having to be re-loaded every time
|
||||
// a stage switch is done.
|
||||
children: [printSetupSelector]
|
||||
height: childrenRect.height
|
||||
width: childrenRect.width
|
||||
}
|
||||
}
|
||||
}
|
51
plugins/PreviewStage/PreviewStage.py
Normal file
51
plugins/PreviewStage/PreviewStage.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import os.path
|
||||
|
||||
from UM.Qt.QtApplication import QtApplication
|
||||
from cura.Stages.CuraStage import CuraStage
|
||||
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from UM.View.View import View
|
||||
|
||||
|
||||
## Displays a preview of what you're about to print.
|
||||
#
|
||||
# The Python component of this stage just loads PreviewMain.qml for display
|
||||
# when the stage is selected, and makes sure that it reverts to the previous
|
||||
# view when the previous stage is activated.
|
||||
class PreviewStage(CuraStage):
|
||||
def __init__(self, application: QtApplication, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
self._application = application
|
||||
self._application.engineCreatedSignal.connect(self._engineCreated)
|
||||
self._previously_active_view = None # type: Optional[View]
|
||||
|
||||
## When selecting the stage, remember which was the previous view so that
|
||||
# we can revert to that view when we go out of the stage later.
|
||||
def onStageSelected(self) -> None:
|
||||
self._previously_active_view = self._application.getController().getActiveView()
|
||||
|
||||
## Called when going to a different stage (away from the Preview Stage).
|
||||
#
|
||||
# When going to a different stage, the view should be reverted to what it
|
||||
# was before. Normally, that just reverts it to solid view.
|
||||
def onStageDeselected(self) -> None:
|
||||
if self._previously_active_view is not None:
|
||||
self._application.getController().setActiveView(self._previously_active_view.getPluginId())
|
||||
self._previously_active_view = None
|
||||
|
||||
## Delayed load of the QML files.
|
||||
#
|
||||
# We need to make sure that the QML engine is running before we can load
|
||||
# these.
|
||||
def _engineCreated(self) -> None:
|
||||
plugin_path = self._application.getPluginRegistry().getPluginPath(self.getPluginId())
|
||||
if plugin_path is not None:
|
||||
menu_component_path = os.path.join(plugin_path, "PreviewMenu.qml")
|
||||
main_component_path = os.path.join(plugin_path, "PreviewMain.qml")
|
||||
self.addDisplayComponent("menu", menu_component_path)
|
||||
self.addDisplayComponent("main", main_component_path)
|
22
plugins/PreviewStage/__init__.py
Normal file
22
plugins/PreviewStage/__init__.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from . import PreviewStage
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"stage": {
|
||||
"name": i18n_catalog.i18nc("@item:inmenu", "Preview"),
|
||||
"weight": 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def register(app):
|
||||
return {
|
||||
"stage": PreviewStage.PreviewStage(app)
|
||||
}
|
8
plugins/PreviewStage/plugin.json
Normal file
8
plugins/PreviewStage/plugin.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Preview Stage",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"description": "Provides a preview stage in Cura.",
|
||||
"api": 5,
|
||||
"i18n-catalog": "cura"
|
||||
}
|
|
@ -13,23 +13,20 @@ Item
|
|||
{
|
||||
id: sliderRoot
|
||||
|
||||
// handle properties
|
||||
property real handleSize: 10
|
||||
// Handle properties
|
||||
property real handleSize: UM.Theme.getSize("slider_handle").width
|
||||
property real handleRadius: handleSize / 2
|
||||
property real minimumRangeHandleSize: handleSize / 2
|
||||
property color upperHandleColor: "black"
|
||||
property color lowerHandleColor: "black"
|
||||
property color rangeHandleColor: "black"
|
||||
property color handleActiveColor: "white"
|
||||
property real handleLabelWidth: width
|
||||
property color upperHandleColor: UM.Theme.getColor("slider_handle")
|
||||
property color lowerHandleColor: UM.Theme.getColor("slider_handle")
|
||||
property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
|
||||
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||
property var activeHandle: upperHandle
|
||||
|
||||
// track properties
|
||||
property real trackThickness: 4 // width of the slider track
|
||||
property real trackRadius: trackThickness / 2
|
||||
property color trackColor: "white"
|
||||
property real trackBorderWidth: 1 // width of the slider track border
|
||||
property color trackBorderColor: "black"
|
||||
// Track properties
|
||||
property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track
|
||||
property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
|
||||
property color trackColor: UM.Theme.getColor("slider_groove")
|
||||
|
||||
// value properties
|
||||
property real maximumValue: 100
|
||||
|
@ -80,7 +77,7 @@ Item
|
|||
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
|
||||
}
|
||||
|
||||
// slider track
|
||||
// Slider track
|
||||
Rectangle
|
||||
{
|
||||
id: track
|
||||
|
@ -90,8 +87,6 @@ Item
|
|||
radius: sliderRoot.trackRadius
|
||||
anchors.centerIn: sliderRoot
|
||||
color: sliderRoot.trackColor
|
||||
border.width: sliderRoot.trackBorderWidth
|
||||
border.color: sliderRoot.trackBorderColor
|
||||
visible: sliderRoot.layersVisible
|
||||
}
|
||||
|
||||
|
@ -106,7 +101,7 @@ Item
|
|||
anchors.horizontalCenter: sliderRoot.horizontalCenter
|
||||
visible: sliderRoot.layersVisible
|
||||
|
||||
// set the new value when dragging
|
||||
// Set the new value when dragging
|
||||
function onHandleDragged()
|
||||
{
|
||||
sliderRoot.manuallyChanged = true
|
||||
|
@ -140,9 +135,10 @@ Item
|
|||
|
||||
Rectangle
|
||||
{
|
||||
width: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
|
||||
width: sliderRoot.trackThickness
|
||||
height: parent.height + sliderRoot.handleSize
|
||||
anchors.centerIn: parent
|
||||
radius: sliderRoot.trackRadius
|
||||
color: sliderRoot.rangeHandleColor
|
||||
}
|
||||
|
||||
|
@ -167,9 +163,9 @@ Item
|
|||
id: rangleHandleLabel
|
||||
|
||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
||||
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
||||
target: Qt.point(sliderRoot.width + width, y + height / 2)
|
||||
visible: sliderRoot.activeHandle == parent
|
||||
|
||||
// custom properties
|
||||
|
@ -275,7 +271,7 @@ Item
|
|||
id: upperHandleLabel
|
||||
|
||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
||||
x: parent.x - parent.width - width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
||||
visible: sliderRoot.activeHandle == parent
|
||||
|
@ -385,9 +381,9 @@ Item
|
|||
id: lowerHandleLabel
|
||||
|
||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
||||
x: parent.x - parent.width - width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
||||
target: Qt.point(sliderRoot.width + width, y + height / 2)
|
||||
visible: sliderRoot.activeHandle == parent
|
||||
|
||||
// custom properties
|
||||
|
|
|
@ -14,19 +14,17 @@ Item
|
|||
id: sliderRoot
|
||||
|
||||
// handle properties
|
||||
property real handleSize: 10
|
||||
property real handleSize: UM.Theme.getSize("slider_handle").width
|
||||
property real handleRadius: handleSize / 2
|
||||
property color handleColor: "black"
|
||||
property color handleActiveColor: "white"
|
||||
property color rangeColor: "black"
|
||||
property color handleColor: UM.Theme.getColor("slider_handle")
|
||||
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||
property color rangeColor: UM.Theme.getColor("slider_groove_fill")
|
||||
property real handleLabelWidth: width
|
||||
|
||||
// track properties
|
||||
property real trackThickness: 4 // width of the slider track
|
||||
property real trackRadius: trackThickness / 2
|
||||
property color trackColor: "white"
|
||||
property real trackBorderWidth: 1 // width of the slider track border
|
||||
property color trackBorderColor: "black"
|
||||
property real trackThickness: UM.Theme.getSize("slider_groove").width
|
||||
property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
|
||||
property color trackColor: UM.Theme.getColor("slider_groove")
|
||||
|
||||
// value properties
|
||||
property real maximumValue: 100
|
||||
|
@ -68,8 +66,6 @@ Item
|
|||
radius: sliderRoot.trackRadius
|
||||
anchors.centerIn: sliderRoot
|
||||
color: sliderRoot.trackColor
|
||||
border.width: sliderRoot.trackBorderWidth
|
||||
border.color: sliderRoot.trackBorderColor
|
||||
visible: sliderRoot.pathsVisible
|
||||
}
|
||||
|
||||
|
@ -86,9 +82,10 @@ Item
|
|||
|
||||
Rectangle
|
||||
{
|
||||
height: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
|
||||
height: sliderRoot.trackThickness
|
||||
width: parent.width + sliderRoot.handleSize
|
||||
anchors.centerIn: parent
|
||||
radius: sliderRoot.trackRadius
|
||||
color: sliderRoot.rangeColor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
|
|||
from UM.Message import Message
|
||||
from UM.Platform import Platform
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Qt.QtApplication import QtApplication
|
||||
from UM.Resources import Resources
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
|
||||
|
@ -26,8 +27,8 @@ from UM.View.GL.OpenGL import OpenGL
|
|||
from UM.View.GL.OpenGLContext import OpenGLContext
|
||||
from UM.View.GL.ShaderProgram import ShaderProgram
|
||||
|
||||
from UM.View.View import View
|
||||
from UM.i18n import i18nCatalog
|
||||
from cura.CuraView import CuraView
|
||||
from cura.Scene.ConvexHullNode import ConvexHullNode
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
|
@ -48,15 +49,15 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
|
||||
## View used to display g-code paths.
|
||||
class SimulationView(View):
|
||||
class SimulationView(CuraView):
|
||||
# Must match SimulationView.qml
|
||||
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
|
||||
LAYER_VIEW_TYPE_LINE_TYPE = 1
|
||||
LAYER_VIEW_TYPE_FEEDRATE = 2
|
||||
LAYER_VIEW_TYPE_THICKNESS = 3
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
def __init__(self, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
self._max_layers = 0
|
||||
self._current_layer_num = 0
|
||||
|
@ -113,6 +114,16 @@ class SimulationView(View):
|
|||
self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"),
|
||||
title = catalog.i18nc("@info:title", "Simulation View"))
|
||||
|
||||
QtApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
|
||||
|
||||
def _onEngineCreated(self) -> None:
|
||||
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
|
||||
if plugin_path:
|
||||
self.addDisplayComponent("main", os.path.join(plugin_path, "SimulationViewMainComponent.qml"))
|
||||
self.addDisplayComponent("menu", os.path.join(plugin_path, "SimulationViewMenuComponent.qml"))
|
||||
else:
|
||||
Logger.log("e", "Unable to find the path for %s", self.getPluginId())
|
||||
|
||||
def _evaluateCompatibilityMode(self) -> bool:
|
||||
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
|
||||
|
||||
|
|
|
@ -1,808 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
|
||||
import UM 1.0 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
width:
|
||||
{
|
||||
if (UM.SimulationView.compatibilityMode)
|
||||
{
|
||||
return UM.Theme.getSize("layerview_menu_size_compatibility").width;
|
||||
}
|
||||
else
|
||||
{
|
||||
return UM.Theme.getSize("layerview_menu_size").width;
|
||||
}
|
||||
}
|
||||
height: {
|
||||
if (viewSettings.collapsed)
|
||||
{
|
||||
if (UM.SimulationView.compatibilityMode)
|
||||
{
|
||||
return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height;
|
||||
}
|
||||
return UM.Theme.getSize("layerview_menu_size_collapsed").height;
|
||||
}
|
||||
else if (UM.SimulationView.compatibilityMode)
|
||||
{
|
||||
return UM.Theme.getSize("layerview_menu_size_compatibility").height;
|
||||
}
|
||||
else if (UM.Preferences.getValue("layerview/layer_view_type") == 0)
|
||||
{
|
||||
return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
|
||||
}
|
||||
else
|
||||
{
|
||||
return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
|
||||
}
|
||||
}
|
||||
Behavior on height { NumberAnimation { duration: 100 } }
|
||||
|
||||
property var buttonTarget:
|
||||
{
|
||||
if(parent != null)
|
||||
{
|
||||
var force_binding = parent.y; // ensure this gets reevaluated when the panel moves
|
||||
return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y)
|
||||
}
|
||||
return Qt.point(0,0)
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: layerViewMenu
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
clip: true
|
||||
z: layerSlider.z - 1
|
||||
color: UM.Theme.getColor("tool_panel_background")
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
|
||||
Button {
|
||||
id: collapseButton
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Math.round(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2)
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||
|
||||
width: UM.Theme.getSize("standard_arrow").width
|
||||
height: UM.Theme.getSize("standard_arrow").height
|
||||
|
||||
onClicked: viewSettings.collapsed = !viewSettings.collapsed
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: UM.RecolorImage
|
||||
{
|
||||
width: control.width
|
||||
height: control.height
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
|
||||
}
|
||||
label: Label{ }
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout
|
||||
{
|
||||
id: viewSettings
|
||||
|
||||
property bool collapsed: false
|
||||
property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
|
||||
property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
|
||||
property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
|
||||
property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
|
||||
property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
|
||||
// if we are in compatibility mode, we only show the "line type"
|
||||
property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
|
||||
property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
|
||||
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
|
||||
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
|
||||
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
|
||||
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||
spacing: UM.Theme.getSize("layerview_row_spacing").height
|
||||
|
||||
Label
|
||||
{
|
||||
id: layerViewTypesLabel
|
||||
anchors.left: parent.left
|
||||
text: catalog.i18nc("@label","Color scheme")
|
||||
font: UM.Theme.getFont("default");
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
Layout.fillWidth: true
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
}
|
||||
|
||||
ListModel // matches SimulationView.py
|
||||
{
|
||||
id: layerViewTypes
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Material Color"),
|
||||
type_id: 0
|
||||
})
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Line Type"),
|
||||
type_id: 1
|
||||
})
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Feedrate"),
|
||||
type_id: 2
|
||||
})
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Layer thickness"),
|
||||
type_id: 3 // these ids match the switching in the shader
|
||||
})
|
||||
}
|
||||
|
||||
ComboBox
|
||||
{
|
||||
id: layerTypeCombobox
|
||||
anchors.left: parent.left
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
||||
model: layerViewTypes
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
style: UM.Theme.styles.combobox
|
||||
anchors.right: parent.right
|
||||
|
||||
onActivated:
|
||||
{
|
||||
UM.Preferences.setValue("layerview/layer_view_type", index);
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
|
||||
updateLegends(currentIndex);
|
||||
}
|
||||
|
||||
function updateLegends(type_id)
|
||||
{
|
||||
// update visibility of legends
|
||||
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
|
||||
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
|
||||
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
|
||||
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: compatibilityModeLabel
|
||||
anchors.left: parent.left
|
||||
text: catalog.i18nc("@label","Compatibility Mode")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
visible: UM.SimulationView.compatibilityMode
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
|
||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||
width: width
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: UM.Preferences
|
||||
onPreferenceChanged:
|
||||
{
|
||||
layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
|
||||
layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex);
|
||||
playButton.pauseSimulation();
|
||||
viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|");
|
||||
viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves");
|
||||
viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers");
|
||||
viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin");
|
||||
viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill");
|
||||
viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers");
|
||||
viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count");
|
||||
}
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
model: Cura.ExtrudersModel{}
|
||||
CheckBox
|
||||
{
|
||||
id: extrudersModelCheckBox
|
||||
checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
|
||||
onClicked:
|
||||
{
|
||||
viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
|
||||
UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
|
||||
}
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
enabled: index + 1 <= 4
|
||||
Rectangle
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: extrudersModelCheckBox.right
|
||||
width: UM.Theme.getSize("layerview_legend_size").width
|
||||
height: UM.Theme.getSize("layerview_legend_size").height
|
||||
color: model.color
|
||||
radius: Math.round(width / 2)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
visible: !viewSettings.show_legend & !viewSettings.show_gradient
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
||||
style: UM.Theme.styles.checkbox
|
||||
Label
|
||||
{
|
||||
text: model.name
|
||||
elide: Text.ElideRight
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: extrudersModelCheckBox.left;
|
||||
anchors.right: extrudersModelCheckBox.right;
|
||||
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
|
||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
model: ListModel
|
||||
{
|
||||
id: typesLegendModel
|
||||
Component.onCompleted:
|
||||
{
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Travels"),
|
||||
initialValue: viewSettings.show_travel_moves,
|
||||
preference: "layerview/show_travel_moves",
|
||||
colorId: "layerview_move_combing"
|
||||
});
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Helpers"),
|
||||
initialValue: viewSettings.show_helpers,
|
||||
preference: "layerview/show_helpers",
|
||||
colorId: "layerview_support"
|
||||
});
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Shell"),
|
||||
initialValue: viewSettings.show_skin,
|
||||
preference: "layerview/show_skin",
|
||||
colorId: "layerview_inset_0"
|
||||
});
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Infill"),
|
||||
initialValue: viewSettings.show_infill,
|
||||
preference: "layerview/show_infill",
|
||||
colorId: "layerview_infill"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: legendModelCheckBox
|
||||
checked: model.initialValue
|
||||
onClicked:
|
||||
{
|
||||
UM.Preferences.setValue(model.preference, checked);
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: legendModelCheckBox.right
|
||||
width: UM.Theme.getSize("layerview_legend_size").width
|
||||
height: UM.Theme.getSize("layerview_legend_size").height
|
||||
color: UM.Theme.getColor(model.colorId)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
visible: viewSettings.show_legend
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
||||
style: UM.Theme.styles.checkbox
|
||||
Label
|
||||
{
|
||||
text: label
|
||||
font: UM.Theme.getFont("default")
|
||||
elide: Text.ElideRight
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: legendModelCheckBox.left;
|
||||
anchors.right: legendModelCheckBox.right;
|
||||
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
|
||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
checked: viewSettings.only_show_top_layers
|
||||
onClicked:
|
||||
{
|
||||
UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0);
|
||||
}
|
||||
text: catalog.i18nc("@label", "Only Show Top Layers")
|
||||
visible: UM.SimulationView.compatibilityMode
|
||||
style: UM.Theme.styles.checkbox
|
||||
}
|
||||
CheckBox
|
||||
{
|
||||
checked: viewSettings.top_layer_count == 5
|
||||
onClicked:
|
||||
{
|
||||
UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1);
|
||||
}
|
||||
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
|
||||
visible: UM.SimulationView.compatibilityMode
|
||||
style: UM.Theme.styles.checkbox
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
model: ListModel
|
||||
{
|
||||
id: typesLegendModelNoCheck
|
||||
Component.onCompleted:
|
||||
{
|
||||
typesLegendModelNoCheck.append({
|
||||
label: catalog.i18nc("@label", "Top / Bottom"),
|
||||
colorId: "layerview_skin",
|
||||
});
|
||||
typesLegendModelNoCheck.append({
|
||||
label: catalog.i18nc("@label", "Inner Wall"),
|
||||
colorId: "layerview_inset_x",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: label
|
||||
visible: viewSettings.show_legend
|
||||
id: typesLegendModelLabel
|
||||
Rectangle
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: typesLegendModelLabel.right
|
||||
width: UM.Theme.getSize("layerview_legend_size").width
|
||||
height: UM.Theme.getSize("layerview_legend_size").height
|
||||
color: UM.Theme.getColor(model.colorId)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
visible: viewSettings.show_legend
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
||||
|
||||
// Text for the minimum, maximum and units for the feedrates and layer thickness
|
||||
Item
|
||||
{
|
||||
id: gradientLegend
|
||||
visible: viewSettings.show_gradient
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("layerview_row").height
|
||||
anchors
|
||||
{
|
||||
topMargin: UM.Theme.getSize("slider_layerview_margin").height
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: minText()
|
||||
anchors.left: parent.left
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
|
||||
function minText()
|
||||
{
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
|
||||
}
|
||||
// Layer thickness selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
|
||||
}
|
||||
}
|
||||
return catalog.i18nc("@label","min")
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: unitsText()
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
|
||||
function unitsText()
|
||||
{
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||
{
|
||||
return "mm/s"
|
||||
}
|
||||
// Layer thickness selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||
{
|
||||
return "mm"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: maxText()
|
||||
anchors.right: parent.right
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
|
||||
function maxText()
|
||||
{
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
|
||||
}
|
||||
// Layer thickness selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
|
||||
}
|
||||
}
|
||||
return catalog.i18nc("@label","max")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient colors for feedrate
|
||||
Rectangle
|
||||
{ // In QML 5.9 can be changed by LinearGradient
|
||||
// Invert values because then the bar is rotated 90 degrees
|
||||
id: feedrateGradient
|
||||
visible: viewSettings.show_feedrate_gradient
|
||||
anchors.left: parent.right
|
||||
height: parent.width
|
||||
width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
|
||||
gradient: Gradient
|
||||
{
|
||||
GradientStop
|
||||
{
|
||||
position: 0.000
|
||||
color: Qt.rgba(1, 0.5, 0, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.625
|
||||
color: Qt.rgba(0.375, 0.5, 0, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.75
|
||||
color: Qt.rgba(0.25, 1, 0, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 1.0
|
||||
color: Qt.rgba(0, 0, 1, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient colors for layer thickness (similar to parula colormap)
|
||||
Rectangle // In QML 5.9 can be changed by LinearGradient
|
||||
{
|
||||
// Invert values because then the bar is rotated 90 degrees
|
||||
id: thicknessGradient
|
||||
visible: viewSettings.show_thickness_gradient
|
||||
anchors.left: parent.right
|
||||
height: parent.width
|
||||
width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
|
||||
gradient: Gradient
|
||||
{
|
||||
GradientStop
|
||||
{
|
||||
position: 0.000
|
||||
color: Qt.rgba(1, 1, 0, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.25
|
||||
color: Qt.rgba(1, 0.75, 0.25, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.5
|
||||
color: Qt.rgba(0, 0.75, 0.5, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.75
|
||||
color: Qt.rgba(0, 0.375, 0.75, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 1.0
|
||||
color: Qt.rgba(0, 0, 0.5, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: slidersBox
|
||||
|
||||
width: parent.width
|
||||
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
|
||||
|
||||
anchors
|
||||
{
|
||||
top: parent.bottom
|
||||
topMargin: UM.Theme.getSize("slider_layerview_margin").height
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
PathSlider
|
||||
{
|
||||
id: pathSlider
|
||||
|
||||
height: UM.Theme.getSize("slider_handle").width
|
||||
anchors.left: playButton.right
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
anchors.right: parent.right
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
|
||||
// custom properties
|
||||
handleValue: UM.SimulationView.currentPath
|
||||
maximumValue: UM.SimulationView.numPaths
|
||||
handleSize: UM.Theme.getSize("slider_handle").width
|
||||
trackThickness: UM.Theme.getSize("slider_groove").width
|
||||
trackColor: UM.Theme.getColor("slider_groove")
|
||||
trackBorderColor: UM.Theme.getColor("slider_groove_border")
|
||||
handleColor: UM.Theme.getColor("slider_handle")
|
||||
handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||
rangeColor: UM.Theme.getColor("slider_groove_fill")
|
||||
|
||||
// update values when layer data changes
|
||||
Connections
|
||||
{
|
||||
target: UM.SimulationView
|
||||
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||
onCurrentPathChanged:
|
||||
{
|
||||
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
||||
if (pathSlider.manuallyChanged)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the slider handlers show the correct value after switching views
|
||||
Component.onCompleted:
|
||||
{
|
||||
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||
}
|
||||
}
|
||||
|
||||
LayerSlider
|
||||
{
|
||||
id: layerSlider
|
||||
|
||||
width: UM.Theme.getSize("slider_handle").width
|
||||
height: UM.Theme.getSize("layerview_menu_size").height
|
||||
|
||||
anchors
|
||||
{
|
||||
top: !UM.SimulationView.compatibilityMode ? pathSlider.bottom : parent.top
|
||||
topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("slider_layerview_margin").width
|
||||
}
|
||||
|
||||
// custom properties
|
||||
upperValue: UM.SimulationView.currentLayer
|
||||
lowerValue: UM.SimulationView.minimumLayer
|
||||
maximumValue: UM.SimulationView.numLayers
|
||||
handleSize: UM.Theme.getSize("slider_handle").width
|
||||
trackThickness: UM.Theme.getSize("slider_groove").width
|
||||
trackColor: UM.Theme.getColor("slider_groove")
|
||||
trackBorderColor: UM.Theme.getColor("slider_groove_border")
|
||||
upperHandleColor: UM.Theme.getColor("slider_handle")
|
||||
lowerHandleColor: UM.Theme.getColor("slider_handle")
|
||||
rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
|
||||
handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||
handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width
|
||||
|
||||
// update values when layer data changes
|
||||
Connections
|
||||
{
|
||||
target: UM.SimulationView
|
||||
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
||||
onCurrentLayerChanged:
|
||||
{
|
||||
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
||||
if (layerSlider.manuallyChanged)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the slider handlers show the correct value after switching views
|
||||
Component.onCompleted:
|
||||
{
|
||||
layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
||||
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||
}
|
||||
}
|
||||
|
||||
// Play simulation button
|
||||
Button
|
||||
{
|
||||
id: playButton
|
||||
iconSource: "./resources/simulation_resume.svg"
|
||||
style: UM.Theme.styles.small_tool_button
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
anchors
|
||||
{
|
||||
verticalCenter: pathSlider.verticalCenter
|
||||
}
|
||||
|
||||
property var status: 0 // indicates if it's stopped (0) or playing (1)
|
||||
|
||||
onClicked:
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
resumeSimulation()
|
||||
break
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
pauseSimulation()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pauseSimulation()
|
||||
{
|
||||
UM.SimulationView.setSimulationRunning(false)
|
||||
iconSource = "./resources/simulation_resume.svg"
|
||||
simulationTimer.stop()
|
||||
status = 0
|
||||
layerSlider.manuallyChanged = true
|
||||
pathSlider.manuallyChanged = true
|
||||
}
|
||||
|
||||
function resumeSimulation()
|
||||
{
|
||||
UM.SimulationView.setSimulationRunning(true)
|
||||
iconSource = "./resources/simulation_pause.svg"
|
||||
simulationTimer.start()
|
||||
layerSlider.manuallyChanged = false
|
||||
pathSlider.manuallyChanged = false
|
||||
}
|
||||
}
|
||||
|
||||
Timer
|
||||
{
|
||||
id: simulationTimer
|
||||
interval: 100
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered:
|
||||
{
|
||||
var currentPath = UM.SimulationView.currentPath
|
||||
var numPaths = UM.SimulationView.numPaths
|
||||
var currentLayer = UM.SimulationView.currentLayer
|
||||
var numLayers = UM.SimulationView.numLayers
|
||||
// When the user plays the simulation, if the path slider is at the end of this layer, we start
|
||||
// the simulation at the beginning of the current layer.
|
||||
if (playButton.status == 0)
|
||||
{
|
||||
if (currentPath >= numPaths)
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(0)
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(currentPath+1)
|
||||
}
|
||||
}
|
||||
// If the simulation is already playing and we reach the end of a layer, then it automatically
|
||||
// starts at the beginning of the next layer.
|
||||
else
|
||||
{
|
||||
if (currentPath >= numPaths)
|
||||
{
|
||||
// At the end of the model, the simulation stops
|
||||
if (currentLayer >= numLayers)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentLayer(currentLayer+1)
|
||||
UM.SimulationView.setCurrentPath(0)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(currentPath+1)
|
||||
}
|
||||
}
|
||||
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
|
||||
// correctly, because part of the logic is in this trigger function.
|
||||
playButton.status = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontMetrics
|
||||
{
|
||||
id: fontMetrics
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
211
plugins/SimulationView/SimulationViewMainComponent.qml
Normal file
211
plugins/SimulationView/SimulationViewMainComponent.qml
Normal file
|
@ -0,0 +1,211 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
|
||||
import UM 1.4 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
property bool is_simulation_playing: false
|
||||
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
|
||||
|
||||
PathSlider
|
||||
{
|
||||
id: pathSlider
|
||||
height: UM.Theme.getSize("slider_handle").width
|
||||
width: UM.Theme.getSize("slider_layerview_size").height
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
|
||||
// Custom properties
|
||||
handleValue: UM.SimulationView.currentPath
|
||||
maximumValue: UM.SimulationView.numPaths
|
||||
|
||||
// Update values when layer data changes.
|
||||
Connections
|
||||
{
|
||||
target: UM.SimulationView
|
||||
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||
onCurrentPathChanged:
|
||||
{
|
||||
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
||||
if (pathSlider.manuallyChanged)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the slider handlers show the correct value after switching views.
|
||||
Component.onCompleted:
|
||||
{
|
||||
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UM.SimpleButton
|
||||
{
|
||||
id: playButton
|
||||
iconSource: !is_simulation_playing ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
|
||||
width: UM.Theme.getSize("small_button").width
|
||||
height: UM.Theme.getSize("small_button").height
|
||||
hoverColor: UM.Theme.getColor("slider_handle_active")
|
||||
color: UM.Theme.getColor("slider_handle")
|
||||
iconMargin: UM.Theme.getSize("thick_lining").width
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
|
||||
Connections
|
||||
{
|
||||
target: UM.Preferences
|
||||
onPreferenceChanged:
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
}
|
||||
|
||||
anchors
|
||||
{
|
||||
right: pathSlider.left
|
||||
verticalCenter: pathSlider.verticalCenter
|
||||
}
|
||||
|
||||
onClicked:
|
||||
{
|
||||
if(is_simulation_playing)
|
||||
{
|
||||
pauseSimulation()
|
||||
}
|
||||
else
|
||||
{
|
||||
resumeSimulation()
|
||||
}
|
||||
}
|
||||
|
||||
function pauseSimulation()
|
||||
{
|
||||
UM.SimulationView.setSimulationRunning(false)
|
||||
simulationTimer.stop()
|
||||
is_simulation_playing = false
|
||||
layerSlider.manuallyChanged = true
|
||||
pathSlider.manuallyChanged = true
|
||||
}
|
||||
|
||||
function resumeSimulation()
|
||||
{
|
||||
UM.SimulationView.setSimulationRunning(true)
|
||||
simulationTimer.start()
|
||||
layerSlider.manuallyChanged = false
|
||||
pathSlider.manuallyChanged = false
|
||||
}
|
||||
}
|
||||
|
||||
Timer
|
||||
{
|
||||
id: simulationTimer
|
||||
interval: 100
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered:
|
||||
{
|
||||
var currentPath = UM.SimulationView.currentPath
|
||||
var numPaths = UM.SimulationView.numPaths
|
||||
var currentLayer = UM.SimulationView.currentLayer
|
||||
var numLayers = UM.SimulationView.numLayers
|
||||
|
||||
// When the user plays the simulation, if the path slider is at the end of this layer, we start
|
||||
// the simulation at the beginning of the current layer.
|
||||
if (!is_simulation_playing)
|
||||
{
|
||||
if (currentPath >= numPaths)
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(0)
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(currentPath + 1)
|
||||
}
|
||||
}
|
||||
// If the simulation is already playing and we reach the end of a layer, then it automatically
|
||||
// starts at the beginning of the next layer.
|
||||
else
|
||||
{
|
||||
if (currentPath >= numPaths)
|
||||
{
|
||||
// At the end of the model, the simulation stops
|
||||
if (currentLayer >= numLayers)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentLayer(currentLayer + 1)
|
||||
UM.SimulationView.setCurrentPath(0)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(currentPath + 1)
|
||||
}
|
||||
}
|
||||
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
|
||||
// correctly, because part of the logic is in this trigger function.
|
||||
is_simulation_playing = true
|
||||
}
|
||||
}
|
||||
|
||||
LayerSlider
|
||||
{
|
||||
id: layerSlider
|
||||
|
||||
width: UM.Theme.getSize("slider_handle").width
|
||||
height: UM.Theme.getSize("slider_layerview_size").height
|
||||
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
rightMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
|
||||
// Custom properties
|
||||
upperValue: UM.SimulationView.currentLayer
|
||||
lowerValue: UM.SimulationView.minimumLayer
|
||||
maximumValue: UM.SimulationView.numLayers
|
||||
|
||||
// Update values when layer data changes
|
||||
Connections
|
||||
{
|
||||
target: UM.SimulationView
|
||||
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
||||
onCurrentLayerChanged:
|
||||
{
|
||||
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
||||
if (layerSlider.manuallyChanged)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the slider handlers show the correct value after switching views
|
||||
Component.onCompleted:
|
||||
{
|
||||
layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
||||
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||
}
|
||||
}
|
||||
}
|
530
plugins/SimulationView/SimulationViewMenuComponent.qml
Normal file
530
plugins/SimulationView/SimulationViewMenuComponent.qml
Normal file
|
@ -0,0 +1,530 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import UM 1.0 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
Cura.ExpandableComponent
|
||||
{
|
||||
id: base
|
||||
|
||||
width: UM.Theme.getSize("layerview_menu_size").width
|
||||
contentHeaderTitle: catalog.i18nc("@label", "Color scheme")
|
||||
|
||||
Connections
|
||||
{
|
||||
target: UM.Preferences
|
||||
onPreferenceChanged:
|
||||
{
|
||||
layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type")
|
||||
layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex)
|
||||
viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|")
|
||||
viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves")
|
||||
viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers")
|
||||
viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin")
|
||||
viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill")
|
||||
viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers")
|
||||
viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count")
|
||||
}
|
||||
}
|
||||
|
||||
headerItem: Label
|
||||
{
|
||||
id: layerViewTypesLabel
|
||||
text: catalog.i18nc("@label", "Color scheme")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
height: base.height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
contentItem: Column
|
||||
{
|
||||
id: viewSettings
|
||||
|
||||
property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
|
||||
property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
|
||||
property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
|
||||
property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
|
||||
property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
|
||||
|
||||
// If we are in compatibility mode, we only show the "line type"
|
||||
property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
|
||||
property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
|
||||
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
|
||||
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
|
||||
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
|
||||
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
|
||||
|
||||
width: UM.Theme.getSize("layerview_menu_size").width - 2 * UM.Theme.getSize("default_margin").width
|
||||
height: implicitHeight
|
||||
|
||||
spacing: UM.Theme.getSize("layerview_row_spacing").height
|
||||
|
||||
ListModel // matches SimulationView.py
|
||||
{
|
||||
id: layerViewTypes
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Material Color"),
|
||||
type_id: 0
|
||||
})
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Line Type"),
|
||||
type_id: 1
|
||||
})
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Feedrate"),
|
||||
type_id: 2
|
||||
})
|
||||
layerViewTypes.append({
|
||||
text: catalog.i18nc("@label:listbox", "Layer thickness"),
|
||||
type_id: 3 // these ids match the switching in the shader
|
||||
})
|
||||
}
|
||||
|
||||
ComboBox
|
||||
{
|
||||
id: layerTypeCombobox
|
||||
width: parent.width
|
||||
model: layerViewTypes
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
style: UM.Theme.styles.combobox
|
||||
|
||||
onActivated:
|
||||
{
|
||||
UM.Preferences.setValue("layerview/layer_view_type", index);
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
|
||||
updateLegends(currentIndex);
|
||||
}
|
||||
|
||||
function updateLegends(type_id)
|
||||
{
|
||||
// Update the visibility of the legends.
|
||||
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
|
||||
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
|
||||
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
|
||||
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: compatibilityModeLabel
|
||||
text: catalog.i18nc("@label","Compatibility Mode")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
visible: UM.SimulationView.compatibilityMode
|
||||
height: UM.Theme.getSize("layerview_row").height
|
||||
width: parent.width
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Item // Spacer
|
||||
{
|
||||
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||
width: width
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
model: Cura.ExtrudersModel{}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: extrudersModelCheckBox
|
||||
checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
|
||||
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||
width: parent.width
|
||||
visible: !UM.SimulationView.compatibilityMode
|
||||
enabled: index < 4
|
||||
|
||||
onClicked:
|
||||
{
|
||||
viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
|
||||
UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
|
||||
}
|
||||
|
||||
style: UM.Theme.styles.checkbox
|
||||
|
||||
Rectangle
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: extrudersModelCheckBox.right
|
||||
width: UM.Theme.getSize("layerview_legend_size").width
|
||||
height: UM.Theme.getSize("layerview_legend_size").height
|
||||
color: model.color
|
||||
radius: Math.round(width / 2)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
visible: !viewSettings.show_legend && !viewSettings.show_gradient
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: model.name
|
||||
elide: Text.ElideRight
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
anchors
|
||||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: extrudersModelCheckBox.left
|
||||
right: extrudersModelCheckBox.right
|
||||
leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||
rightMargin: UM.Theme.getSize("default_margin").width * 2
|
||||
}
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
model: ListModel
|
||||
{
|
||||
id: typesLegendModel
|
||||
Component.onCompleted:
|
||||
{
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Travels"),
|
||||
initialValue: viewSettings.show_travel_moves,
|
||||
preference: "layerview/show_travel_moves",
|
||||
colorId: "layerview_move_combing"
|
||||
});
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Helpers"),
|
||||
initialValue: viewSettings.show_helpers,
|
||||
preference: "layerview/show_helpers",
|
||||
colorId: "layerview_support"
|
||||
});
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Shell"),
|
||||
initialValue: viewSettings.show_skin,
|
||||
preference: "layerview/show_skin",
|
||||
colorId: "layerview_inset_0"
|
||||
});
|
||||
typesLegendModel.append({
|
||||
label: catalog.i18nc("@label", "Show Infill"),
|
||||
initialValue: viewSettings.show_infill,
|
||||
preference: "layerview/show_infill",
|
||||
colorId: "layerview_infill"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: legendModelCheckBox
|
||||
checked: model.initialValue
|
||||
onClicked: UM.Preferences.setValue(model.preference, checked)
|
||||
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||
width: parent.width
|
||||
|
||||
style: UM.Theme.styles.checkbox
|
||||
|
||||
Rectangle
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: legendModelCheckBox.right
|
||||
width: UM.Theme.getSize("layerview_legend_size").width
|
||||
height: UM.Theme.getSize("layerview_legend_size").height
|
||||
color: UM.Theme.getColor(model.colorId)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
visible: viewSettings.show_legend
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: label
|
||||
font: UM.Theme.getFont("default")
|
||||
elide: Text.ElideRight
|
||||
renderType: Text.NativeRendering
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: legendModelCheckBox.left
|
||||
anchors.right: legendModelCheckBox.right
|
||||
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
checked: viewSettings.only_show_top_layers
|
||||
onClicked: UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0)
|
||||
text: catalog.i18nc("@label", "Only Show Top Layers")
|
||||
visible: UM.SimulationView.compatibilityMode
|
||||
style: UM.Theme.styles.checkbox
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
checked: viewSettings.top_layer_count == 5
|
||||
onClicked: UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1)
|
||||
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
|
||||
width: parent.width
|
||||
visible: UM.SimulationView.compatibilityMode
|
||||
style: UM.Theme.styles.checkbox
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
model: ListModel
|
||||
{
|
||||
id: typesLegendModelNoCheck
|
||||
Component.onCompleted:
|
||||
{
|
||||
typesLegendModelNoCheck.append({
|
||||
label: catalog.i18nc("@label", "Top / Bottom"),
|
||||
colorId: "layerview_skin",
|
||||
});
|
||||
typesLegendModelNoCheck.append({
|
||||
label: catalog.i18nc("@label", "Inner Wall"),
|
||||
colorId: "layerview_inset_x",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: label
|
||||
visible: viewSettings.show_legend
|
||||
id: typesLegendModelLabel
|
||||
|
||||
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||
width: parent.width
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
Rectangle
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: typesLegendModelLabel.right
|
||||
|
||||
width: UM.Theme.getSize("layerview_legend_size").width
|
||||
height: UM.Theme.getSize("layerview_legend_size").height
|
||||
|
||||
color: UM.Theme.getColor(model.colorId)
|
||||
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text for the minimum, maximum and units for the feedrates and layer thickness
|
||||
Item
|
||||
{
|
||||
id: gradientLegend
|
||||
visible: viewSettings.show_gradient
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("layerview_row").height
|
||||
|
||||
Label
|
||||
{
|
||||
text:
|
||||
{
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
|
||||
}
|
||||
// Layer thickness selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
|
||||
}
|
||||
}
|
||||
return catalog.i18nc("@label","min")
|
||||
}
|
||||
anchors.left: parent.left
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: {
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||
{
|
||||
return "mm/s"
|
||||
}
|
||||
// Layer thickness selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||
{
|
||||
return "mm"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: {
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
|
||||
}
|
||||
// Layer thickness selected
|
||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||
{
|
||||
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
|
||||
}
|
||||
}
|
||||
return catalog.i18nc("@label","max")
|
||||
}
|
||||
|
||||
anchors.right: parent.right
|
||||
color: UM.Theme.getColor("setting_control_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient colors for feedrate
|
||||
Rectangle
|
||||
{
|
||||
id: feedrateGradient
|
||||
visible: viewSettings.show_feedrate_gradient
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
|
||||
LinearGradient
|
||||
{
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("default_lining").width
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("default_lining").width
|
||||
top: parent.top
|
||||
topMargin: UM.Theme.getSize("default_lining").width
|
||||
bottom: parent.bottom
|
||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
||||
}
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(parent.width, 0)
|
||||
gradient: Gradient
|
||||
{
|
||||
GradientStop
|
||||
{
|
||||
position: 0.000
|
||||
color: Qt.rgba(0, 0, 1, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.25
|
||||
color: Qt.rgba(0.25, 1, 0, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.375
|
||||
color: Qt.rgba(0.375, 0.5, 0, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 1.0
|
||||
color: Qt.rgba(1, 0.5, 0, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient colors for layer thickness (similar to parula colormap)
|
||||
Rectangle
|
||||
{
|
||||
id: thicknessGradient
|
||||
visible: viewSettings.show_thickness_gradient
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
|
||||
LinearGradient
|
||||
{
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("default_lining").width
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("default_lining").width
|
||||
top: parent.top
|
||||
topMargin: UM.Theme.getSize("default_lining").width
|
||||
bottom: parent.bottom
|
||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
||||
}
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(parent.width, 0)
|
||||
gradient: Gradient
|
||||
{
|
||||
GradientStop
|
||||
{
|
||||
position: 0.000
|
||||
color: Qt.rgba(0, 0, 0.5, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.25
|
||||
color: Qt.rgba(0, 0.375, 0.75, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.5
|
||||
color: Qt.rgba(0, 0.75, 0.5, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.75
|
||||
color: Qt.rgba(1, 0.75, 0.25, 1)
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 1.0
|
||||
color: Qt.rgba(1, 1, 0, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontMetrics
|
||||
{
|
||||
id: fontMetrics
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
|
@ -8,19 +8,21 @@ from . import SimulationViewProxy, SimulationView
|
|||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"view": {
|
||||
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
|
||||
"view_panel": "SimulationView.qml",
|
||||
"weight": 2
|
||||
"weight": 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def createSimulationViewProxy(engine, script_engine):
|
||||
return SimulationViewProxy.SimulationViewProxy()
|
||||
|
||||
|
||||
def register(app):
|
||||
simulation_view = SimulationView.SimulationView()
|
||||
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
|
||||
return { "view": SimulationView.SimulationView()}
|
||||
return { "view": simulation_view}
|
||||
|
|
|
@ -10,7 +10,8 @@ def getMetaData():
|
|||
return {
|
||||
"view": {
|
||||
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
|
||||
"weight": 0
|
||||
"weight": 0,
|
||||
"visible": False
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ Window
|
|||
maximumWidth: minimumWidth
|
||||
minimumHeight: height
|
||||
maximumHeight: minimumHeight
|
||||
color: UM.Theme.getColor("sidebar")
|
||||
color: UM.Theme.getColor("main_background")
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name:"cura"
|
||||
name: "cura"
|
||||
}
|
||||
Item
|
||||
{
|
||||
|
|
|
@ -86,13 +86,13 @@ Item
|
|||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Website") + ":"
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Email") + ":"
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ Item
|
|||
}
|
||||
return ""
|
||||
}
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
linkColor: UM.Theme.getColor("text_link")
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
|
@ -134,7 +134,7 @@ Item
|
|||
}
|
||||
return ""
|
||||
}
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
linkColor: UM.Theme.getColor("text_link")
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
|
|
|
@ -90,7 +90,7 @@ Item
|
|||
model: packageData.supported_configs
|
||||
headerDelegate: Rectangle
|
||||
{
|
||||
color: UM.Theme.getColor("sidebar")
|
||||
color: UM.Theme.getColor("main_background")
|
||||
height: UM.Theme.getSize("toolbox_chart_row").height
|
||||
Label
|
||||
{
|
||||
|
@ -228,7 +228,7 @@ Item
|
|||
|
||||
return result
|
||||
}
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
linkColor: UM.Theme.getColor("text_link")
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
|
|
|
@ -37,7 +37,7 @@ Item
|
|||
leftMargin: UM.Theme.getSize("wide_margin").width
|
||||
topMargin: UM.Theme.getSize("wide_margin").height
|
||||
}
|
||||
color: white //Always a white background for image (regardless of theme).
|
||||
color: "white" //Always a white background for image (regardless of theme).
|
||||
Image
|
||||
{
|
||||
anchors.fill: parent
|
||||
|
@ -82,25 +82,25 @@ Item
|
|||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Version") + ":"
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Last updated") + ":"
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Author") + ":"
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Downloads") + ":"
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ Item
|
|||
Label
|
||||
{
|
||||
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
Label
|
||||
|
@ -133,7 +133,7 @@ Item
|
|||
var date = new Date(details.last_updated)
|
||||
return date.toLocaleString(UM.Preferences.getValue("general/language"))
|
||||
}
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
Label
|
||||
|
@ -149,7 +149,7 @@ Item
|
|||
return "<a href=\"" + details.website + "\">" + details.author_name + "</a>"
|
||||
}
|
||||
}
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
linkColor: UM.Theme.getColor("text_link")
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
|
@ -157,7 +157,7 @@ Item
|
|||
Label
|
||||
{
|
||||
text: details === null ? "" : (details.download_count || catalog.i18nc("@label", "Unknown"))
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ Item
|
|||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
visible: installedPackages != 0
|
||||
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
||||
|
@ -81,7 +80,7 @@ Item
|
|||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ Rectangle
|
|||
right: parent.right
|
||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
||||
}
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
visible: installedPackages != 0
|
||||
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
||||
source: "../images/installed_check.svg"
|
||||
|
|
|
@ -19,10 +19,10 @@ Button
|
|||
Rectangle
|
||||
{
|
||||
visible: control.active
|
||||
color: UM.Theme.getColor("sidebar_header_highlight_hover")
|
||||
color: UM.Theme.getColor("toolbox_header_highlight_hover")
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("sidebar_header_highlight").height
|
||||
height: UM.Theme.getSize("toolbox_header_highlight").height
|
||||
}
|
||||
}
|
||||
label: Label
|
||||
|
@ -32,15 +32,15 @@ Button
|
|||
{
|
||||
if(control.hovered)
|
||||
{
|
||||
return UM.Theme.getColor("topbar_button_text_hovered");
|
||||
return UM.Theme.getColor("toolbox_header_button_text_hovered");
|
||||
}
|
||||
if(control.active)
|
||||
{
|
||||
return UM.Theme.getColor("topbar_button_text_active");
|
||||
return UM.Theme.getColor("toolbox_header_button_text_active");
|
||||
}
|
||||
else
|
||||
{
|
||||
return UM.Theme.getColor("topbar_button_text_inactive");
|
||||
return UM.Theme.getColor("toolbox_header_button_text_inactive");
|
||||
}
|
||||
}
|
||||
font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Component {
|
||||
Rectangle {
|
||||
id: base;
|
||||
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
|
||||
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width;
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("sidebar");
|
||||
visible: OutputDevice != null;
|
||||
|
||||
UM.I18nCatalog {
|
||||
id: catalog;
|
||||
name: "cura";
|
||||
}
|
||||
|
||||
Label {
|
||||
id: printingLabel;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
leftMargin: 4 * UM.Theme.getSize("default_margin").width;
|
||||
margins: 2 * UM.Theme.getSize("default_margin").width;
|
||||
right: parent.right;
|
||||
top: parent.top;
|
||||
}
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("large");
|
||||
text: catalog.i18nc("@label", "Printing");
|
||||
}
|
||||
|
||||
Label {
|
||||
id: managePrintersLabel;
|
||||
anchors {
|
||||
bottom: printingLabel.bottom;
|
||||
right: printerScrollView.right;
|
||||
rightMargin: 4 * UM.Theme.getSize("default_margin").width;
|
||||
}
|
||||
color: UM.Theme.getColor("primary"); // "Cura Blue"
|
||||
font: UM.Theme.getFont("default");
|
||||
linkColor: UM.Theme.getColor("primary"); // "Cura Blue"
|
||||
text: catalog.i18nc("@label link to connect manager", "Manage printers");
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: managePrintersLabel;
|
||||
hoverEnabled: true;
|
||||
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel();
|
||||
onEntered: managePrintersLabel.font.underline = true;
|
||||
onExited: managePrintersLabel.font.underline = false;
|
||||
}
|
||||
|
||||
// Skeleton loading
|
||||
Column {
|
||||
id: skeletonLoader;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
leftMargin: UM.Theme.getSize("wide_margin").width;
|
||||
right: parent.right;
|
||||
rightMargin: UM.Theme.getSize("wide_margin").width;
|
||||
top: printingLabel.bottom;
|
||||
topMargin: UM.Theme.getSize("default_margin").height;
|
||||
}
|
||||
spacing: UM.Theme.getSize("default_margin").height - 10;
|
||||
visible: printerList.count === 0;
|
||||
|
||||
PrinterCard {
|
||||
printer: null;
|
||||
}
|
||||
PrinterCard {
|
||||
printer: null;
|
||||
}
|
||||
}
|
||||
|
||||
// Actual content
|
||||
ScrollView {
|
||||
id: printerScrollView;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
top: printingLabel.bottom;
|
||||
topMargin: UM.Theme.getSize("default_margin").height;
|
||||
}
|
||||
style: UM.Theme.styles.scrollview;
|
||||
|
||||
ListView {
|
||||
id: printerList;
|
||||
property var currentIndex: -1;
|
||||
anchors {
|
||||
fill: parent;
|
||||
leftMargin: UM.Theme.getSize("wide_margin").width;
|
||||
rightMargin: UM.Theme.getSize("wide_margin").width;
|
||||
}
|
||||
delegate: PrinterCard {
|
||||
printer: modelData;
|
||||
}
|
||||
model: OutputDevice.printers;
|
||||
spacing: UM.Theme.getSize("default_margin").height - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,6 +64,7 @@ Cura.MachineAction
|
|||
width: parent.width
|
||||
text: catalog.i18nc("@title:window", "Connect to Networked Printer")
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
font.pointSize: 18
|
||||
}
|
||||
|
||||
|
@ -72,6 +73,7 @@ Cura.MachineAction
|
|||
id: pageDescription
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: catalog.i18nc("@label", "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n\nSelect your printer from the list below:")
|
||||
}
|
||||
|
||||
|
@ -182,6 +184,7 @@ Cura.MachineAction
|
|||
text: listview.model[index].name
|
||||
color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text
|
||||
elide: Text.ElideRight
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
MouseArea
|
||||
|
@ -204,6 +207,7 @@ Cura.MachineAction
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://ultimaker.com/en/troubleshooting");
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
}
|
||||
|
@ -221,6 +225,7 @@ Cura.MachineAction
|
|||
text: base.selectedDevice ? base.selectedDevice.name : ""
|
||||
font: UM.Theme.getFont("large")
|
||||
elide: Text.ElideRight
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
Grid
|
||||
{
|
||||
|
@ -231,12 +236,14 @@ Cura.MachineAction
|
|||
{
|
||||
width: Math.round(parent.width * 0.5)
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: catalog.i18nc("@label", "Type")
|
||||
}
|
||||
Label
|
||||
{
|
||||
width: Math.round(parent.width * 0.5)
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text:
|
||||
{
|
||||
if(base.selectedDevice)
|
||||
|
@ -268,24 +275,28 @@ Cura.MachineAction
|
|||
{
|
||||
width: Math.round(parent.width * 0.5)
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: catalog.i18nc("@label", "Firmware version")
|
||||
}
|
||||
Label
|
||||
{
|
||||
width: Math.round(parent.width * 0.5)
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: base.selectedDevice ? base.selectedDevice.firmwareVersion : ""
|
||||
}
|
||||
Label
|
||||
{
|
||||
width: Math.round(parent.width * 0.5)
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: catalog.i18nc("@label", "Address")
|
||||
}
|
||||
Label
|
||||
{
|
||||
width: Math.round(parent.width * 0.5)
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text: base.selectedDevice ? base.selectedDevice.ipAddress : ""
|
||||
}
|
||||
}
|
||||
|
@ -294,6 +305,7 @@ Cura.MachineAction
|
|||
{
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
text:{
|
||||
// The property cluster size does not exist for older UM3 devices.
|
||||
if(!base.selectedDevice || base.selectedDevice.clusterSize == null || base.selectedDevice.clusterSize == 1)
|
||||
|
@ -315,6 +327,7 @@ Cura.MachineAction
|
|||
{
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
visible: base.selectedDevice != null && !base.completeProperties
|
||||
text: catalog.i18nc("@label", "The printer at this address has not yet responded." )
|
||||
}
|
||||
|
@ -358,9 +371,10 @@ Cura.MachineAction
|
|||
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@alabel","Enter the IP address or hostname of your printer on the network.")
|
||||
text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.")
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
TextField
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 2.0
|
||||
import UM 1.3 as UM
|
||||
|
||||
Rectangle {
|
||||
color: UM.Theme.getColor("monitor_lining_light"); // TODO: Maybe theme separately? Maybe not.
|
||||
height: UM.Theme.getSize("default_lining").height;
|
||||
width: parent.width;
|
||||
}
|
|
@ -27,7 +27,7 @@ Item
|
|||
Row
|
||||
{
|
||||
height: parent.height
|
||||
spacing: 12 * screenScaleFactor // TODO: Theme! (Should be same as extruder spacing)
|
||||
spacing: UM.Theme.getSize("print_setup_slider_handle").width // TODO: Theme! (Should be same as extruder spacing)
|
||||
|
||||
// This wrapper ensures that the buildplate icon is located centered
|
||||
// below an extruder icon.
|
||||
|
@ -52,7 +52,7 @@ Item
|
|||
id: buildplateLabel
|
||||
color: "#191919" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("very_small") // 12pt, regular
|
||||
font: UM.Theme.getFont("default") // 12pt, regular
|
||||
text: ""
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Dialogs 1.2
|
||||
import UM 1.3 as UM
|
||||
|
||||
UM.Dialog
|
||||
{
|
||||
id: overrideConfirmationDialog
|
||||
|
||||
property var printer: null
|
||||
|
||||
minimumWidth: screenScaleFactor * 640;
|
||||
minimumHeight: screenScaleFactor * 320;
|
||||
width: minimumWidth
|
||||
height: minimumHeight
|
||||
title: catalog.i18nc("@title:window", "Configuration Changes")
|
||||
rightButtons:
|
||||
[
|
||||
Button
|
||||
{
|
||||
id: overrideButton
|
||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||
text: catalog.i18nc("@action:button", "Override")
|
||||
onClicked:
|
||||
{
|
||||
OutputDevice.forceSendJob(printer.activePrintJob.key)
|
||||
overrideConfirmationDialog.close()
|
||||
}
|
||||
},
|
||||
Button
|
||||
{
|
||||
id: cancelButton
|
||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||
text: catalog.i18nc("@action:button", "Cancel")
|
||||
onClicked:
|
||||
{
|
||||
overrideConfirmationDialog.reject()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Label
|
||||
{
|
||||
anchors
|
||||
{
|
||||
fill: parent
|
||||
margins: 36 * screenScaleFactor // TODO: Theme!
|
||||
bottomMargin: 56 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
wrapMode: Text.WordWrap
|
||||
text:
|
||||
{
|
||||
if (!printer.activePrintJob)
|
||||
{
|
||||
return ""
|
||||
}
|
||||
var topLine
|
||||
if (materialsAreKnown(printer.activePrintJob))
|
||||
{
|
||||
topLine = catalog.i18ncp("@label", "The assigned printer, %1, requires the following configuration change:", "The assigned printer, %1, requires the following configuration changes:", printer.activePrintJob.configurationChanges.length).arg(printer.name)
|
||||
}
|
||||
else
|
||||
{
|
||||
topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printer.name)
|
||||
}
|
||||
var result = "<p>" + topLine +"</p>\n\n"
|
||||
for (var i = 0; i < printer.activePrintJob.configurationChanges.length; i++)
|
||||
{
|
||||
var change = printer.activePrintJob.configurationChanges[i]
|
||||
var text
|
||||
switch (change.typeOfChange)
|
||||
{
|
||||
case "material_change":
|
||||
text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName)
|
||||
break
|
||||
case "material_insert":
|
||||
text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName)
|
||||
break
|
||||
case "print_core_change":
|
||||
text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName)
|
||||
break
|
||||
case "buildplate_change":
|
||||
text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name))
|
||||
break
|
||||
default:
|
||||
text = "unknown"
|
||||
}
|
||||
result += "<p><b>" + text + "</b></p>\n\n"
|
||||
}
|
||||
var bottomLine = catalog.i18nc("@label", "Override will use the specified settings with the existing printer configuration. This may result in a failed print.")
|
||||
result += "<p>" + bottomLine + "</p>\n\n"
|
||||
return result
|
||||
}
|
||||
}
|
||||
// Utils
|
||||
function formatPrintJobName(name)
|
||||
{
|
||||
var extensions = [ ".gcode.gz", ".gz", ".gcode", ".ufp" ]
|
||||
for (var i = 0; i < extensions.length; i++)
|
||||
{
|
||||
var extension = extensions[i]
|
||||
if (name.slice(-extension.length) === extension)
|
||||
{
|
||||
name = name.substring(0, name.length - extension.length)
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
function materialsAreKnown(job)
|
||||
{
|
||||
var conf0 = job.configuration[0]
|
||||
if (conf0 && !conf0.material.material)
|
||||
{
|
||||
return false
|
||||
}
|
||||
var conf1 = job.configuration[1]
|
||||
if (conf1 && !conf1.material.material)
|
||||
{
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
function formatBuildPlateType(buildPlateType)
|
||||
{
|
||||
var translationText = ""
|
||||
switch (buildPlateType) {
|
||||
case "glass":
|
||||
translationText = catalog.i18nc("@label", "Glass")
|
||||
break
|
||||
case "aluminum":
|
||||
translationText = catalog.i18nc("@label", "Aluminum")
|
||||
break
|
||||
default:
|
||||
translationText = null
|
||||
}
|
||||
return translationText
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ Item
|
|||
}
|
||||
color: "#191919" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("very_small") // 12pt, regular
|
||||
font: UM.Theme.getFont("default") // 12pt, regular
|
||||
text: ""
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
|
@ -66,7 +66,7 @@ Item
|
|||
}
|
||||
color: "#191919" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("small") // 12pt, bold
|
||||
font: UM.Theme.getFont("default_bold") // 12pt, bold
|
||||
text: ""
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
|
|
|
@ -26,6 +26,7 @@ Item
|
|||
|
||||
ExpandableCard
|
||||
{
|
||||
borderColor: printJob.configurationChanges.length !== 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme!
|
||||
headerItem: Row
|
||||
{
|
||||
height: 48 * screenScaleFactor // TODO: Theme!
|
||||
|
|
|
@ -23,7 +23,7 @@ Item
|
|||
anchors.fill: parent
|
||||
opacity:
|
||||
{
|
||||
if (printJob && (printJob.state == "error" || !printJob.isActive))
|
||||
if (printJob && (printJob.state == "error" || printJob.configurationChanges.length > 0 || !printJob.isActive))
|
||||
{
|
||||
return 0.5
|
||||
}
|
||||
|
@ -60,6 +60,14 @@ Item
|
|||
height: 0.5 * printJobPreview.height
|
||||
source:
|
||||
{
|
||||
if (!printJob)
|
||||
{
|
||||
return ""
|
||||
}
|
||||
if (printJob.configurationChanges.length > 0)
|
||||
{
|
||||
return "../svg/warning-icon.svg"
|
||||
}
|
||||
switch(printJob.state)
|
||||
{
|
||||
case "error":
|
||||
|
@ -75,6 +83,7 @@ Item
|
|||
default:
|
||||
return ""
|
||||
}
|
||||
return ""
|
||||
}
|
||||
sourceSize
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ Item
|
|||
left: progressBar.right
|
||||
leftMargin: 18 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
text: Math.round(printJob.progress * 100) + "%"
|
||||
text: printJob ? Math.round(printJob.progress * 100) + "%" : "0%"
|
||||
color: printJob && printJob.isActive ? "#374355" : "#babac1" // TODO: Theme!
|
||||
width: contentWidth
|
||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||
|
@ -88,6 +88,8 @@ Item
|
|||
return catalog.i18nc("@label:status", "Aborted")
|
||||
}
|
||||
return catalog.i18nc("@label:status", "Finished")
|
||||
case "finished":
|
||||
return catalog.i18nc("@label:status", "Finished")
|
||||
case "sent_to_printer":
|
||||
return catalog.i18nc("@label:status", "Preparing...")
|
||||
case "pre_print":
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Dialogs 1.1
|
||||
import UM 1.3 as UM
|
||||
|
||||
/**
|
||||
|
@ -66,7 +67,7 @@ Item
|
|||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: 216 * screenScaleFactor // TODO: Theme!
|
||||
width: 180 * screenScaleFactor // TODO: Theme!
|
||||
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
|
||||
|
||||
Label
|
||||
|
@ -150,7 +151,7 @@ Item
|
|||
}
|
||||
border
|
||||
{
|
||||
color: "#EAEAEC" // TODO: Theme!
|
||||
color: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme!
|
||||
width: borderSize // TODO: Remove once themed
|
||||
}
|
||||
color: "white" // TODO: Theme!
|
||||
|
@ -185,14 +186,15 @@ Item
|
|||
}
|
||||
if (printer && printer.state == "unreachable")
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Unreachable")
|
||||
return catalog.i18nc("@label:status", "Unavailable")
|
||||
}
|
||||
if (printer && printer.state == "idle")
|
||||
if (printer && !printer.activePrintJob && printer.state == "idle")
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Idle")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
Item
|
||||
|
@ -218,7 +220,7 @@ Item
|
|||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: 216 * screenScaleFactor // TODO: Theme!
|
||||
width: 180 * screenScaleFactor // TODO: Theme!
|
||||
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
|
||||
visible: printer.activePrintJob
|
||||
|
||||
|
@ -247,7 +249,7 @@ Item
|
|||
}
|
||||
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("very_small") // 12pt, regular
|
||||
font: UM.Theme.getFont("default") // 12pt, regular
|
||||
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
|
||||
width: parent.width
|
||||
|
||||
|
@ -264,8 +266,67 @@ Item
|
|||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
printJob: printer.activePrintJob
|
||||
visible: printer.activePrintJob
|
||||
visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length === 0
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
anchors
|
||||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
font: UM.Theme.getFont("default")
|
||||
text: "Requires configuration changes"
|
||||
visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
height: 18 * screenScaleFactor // TODO: Theme!
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
id: detailsButton
|
||||
anchors
|
||||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 18 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
background: Rectangle
|
||||
{
|
||||
color: "#d8d8d8" // TODO: Theme!
|
||||
radius: 2 * screenScaleFactor // Todo: Theme!
|
||||
Rectangle
|
||||
{
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
|
||||
color: detailsButton.hovered ? "#e4e4e4" : "#f0f0f0" // TODO: Theme!
|
||||
radius: 2 * screenScaleFactor // Todo: Theme!
|
||||
}
|
||||
}
|
||||
contentItem: Label
|
||||
{
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
|
||||
color: "#1e66d7" // TODO: Theme!
|
||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||
text: "Details" // TODO: I18NC!
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
height: 18 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
implicitHeight: 32 * screenScaleFactor // TODO: Theme!
|
||||
implicitWidth: 96 * screenScaleFactor // TODO: Theme!
|
||||
visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0
|
||||
onClicked: overrideConfirmationDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
MonitorConfigOverrideDialog
|
||||
{
|
||||
id: overrideConfirmationDialog
|
||||
printer: base.printer
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import UM 1.3 as UM
|
|||
import Cura 1.0 as Cura
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
// Root component for the monitor tab (stage)
|
||||
Component
|
||||
{
|
||||
Item
|
||||
|
@ -130,7 +131,7 @@ Component
|
|||
verticalCenter: externalLinkIcon.verticalCenter
|
||||
}
|
||||
color: UM.Theme.getColor("primary")
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("default") // 12pt, regular
|
||||
linkColor: UM.Theme.getColor("primary")
|
||||
text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect")
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
// 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.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import UM 1.2 as UM
|
||||
|
||||
Item {
|
||||
id: extruderInfo;
|
||||
property var printCoreConfiguration: null;
|
||||
height: childrenRect.height;
|
||||
width: Math.round(parent.width / 2);
|
||||
|
||||
// Extruder circle
|
||||
Item {
|
||||
id: extruderCircle;
|
||||
height: UM.Theme.getSize("monitor_extruder_circle").height;
|
||||
width: UM.Theme.getSize("monitor_extruder_circle").width;
|
||||
|
||||
// Loading skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
radius: Math.round(width / 2);
|
||||
visible: !printCoreConfiguration;
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
border.width: UM.Theme.getSize("monitor_thick_lining").width;
|
||||
border.color: UM.Theme.getColor("monitor_lining_heavy");
|
||||
color: "transparent";
|
||||
opacity: {
|
||||
if (printCoreConfiguration == null || printCoreConfiguration.activeMaterial == null || printCoreConfiguration.hotendID == null) {
|
||||
return 0.5;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
radius: Math.round(width / 2);
|
||||
visible: printCoreConfiguration;
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent;
|
||||
color: UM.Theme.getColor("text");
|
||||
font: UM.Theme.getFont("default_bold");
|
||||
text: printCoreConfiguration ? printCoreConfiguration.position + 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print core and material labels
|
||||
Item {
|
||||
id: materialLabel
|
||||
anchors {
|
||||
left: extruderCircle.right;
|
||||
leftMargin: UM.Theme.getSize("default_margin").width;
|
||||
right: parent.right;
|
||||
top: parent.top;
|
||||
}
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
|
||||
// Loading skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
visible: !extruderInfo.printCoreConfiguration;
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
elide: Text.ElideRight;
|
||||
color: UM.Theme.getColor("text");
|
||||
font: UM.Theme.getFont("default");
|
||||
text: {
|
||||
if (printCoreConfiguration && printCoreConfiguration.activeMaterial != undefined) {
|
||||
return printCoreConfiguration.activeMaterial.name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
visible: extruderInfo.printCoreConfiguration;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: printCoreLabel;
|
||||
anchors {
|
||||
left: extruderCircle.right;
|
||||
leftMargin: UM.Theme.getSize("default_margin").width;
|
||||
right: parent.right;
|
||||
top: materialLabel.bottom;
|
||||
topMargin: Math.floor(UM.Theme.getSize("default_margin").height/4);
|
||||
}
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
|
||||
// Loading skeleton
|
||||
Rectangle {
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
height: parent.height;
|
||||
visible: !extruderInfo.printCoreConfiguration;
|
||||
width: Math.round(parent.width / 3);
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Label {
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default");
|
||||
opacity: 0.6;
|
||||
text: {
|
||||
if (printCoreConfiguration != undefined && printCoreConfiguration.hotendID != undefined) {
|
||||
return printCoreConfiguration.hotendID;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
visible: extruderInfo.printCoreConfiguration;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -182,7 +182,7 @@ Item {
|
|||
abortConfirmationDialog.visible = true;
|
||||
popup.close();
|
||||
}
|
||||
text: printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
|
||||
text: printJob && printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
|
||||
visible: {
|
||||
if (!printJob) {
|
||||
return false;
|
||||
|
|
|
@ -1,505 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Dialogs 1.1
|
||||
import UM 1.3 as UM
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
|
||||
property var shadowOffset: 2 * screenScaleFactor;
|
||||
property var debug: false;
|
||||
property var printJob: null;
|
||||
width: parent.width; // Bubbles downward
|
||||
height: childrenRect.height + shadowRadius * 2; // Bubbles upward
|
||||
|
||||
UM.I18nCatalog {
|
||||
id: catalog;
|
||||
name: "cura";
|
||||
}
|
||||
|
||||
// The actual card (white block)
|
||||
Rectangle {
|
||||
// 5px margin, but shifted 2px vertically because of the shadow
|
||||
anchors {
|
||||
bottomMargin: root.shadowRadius + root.shadowOffset;
|
||||
leftMargin: root.shadowRadius;
|
||||
rightMargin: root.shadowRadius;
|
||||
topMargin: root.shadowRadius - root.shadowOffset;
|
||||
}
|
||||
color: UM.Theme.getColor("monitor_card_background");
|
||||
height: childrenRect.height;
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
radius: root.shadowRadius
|
||||
verticalOffset: 2 * screenScaleFactor
|
||||
color: "#3F000000" // 25% shadow
|
||||
}
|
||||
width: parent.width - shadowRadius * 2;
|
||||
|
||||
Column {
|
||||
height: childrenRect.height;
|
||||
width: parent.width;
|
||||
|
||||
// Main content
|
||||
Item {
|
||||
id: mainContent;
|
||||
height: 200 * screenScaleFactor; // TODO: Theme!
|
||||
width: parent.width;
|
||||
|
||||
// Left content
|
||||
Item {
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
margins: UM.Theme.getSize("wide_margin").width;
|
||||
right: parent.horizontalCenter;
|
||||
top: parent.top;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: printJobName;
|
||||
width: parent.width;
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
|
||||
Rectangle {
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
height: parent.height;
|
||||
visible: !printJob;
|
||||
width: Math.round(parent.width / 3);
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default_bold");
|
||||
text: printJob && printJob.name ? printJob.name : ""; // Supress QML warnings
|
||||
visible: printJob;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: printJobOwnerName;
|
||||
anchors {
|
||||
top: printJobName.bottom;
|
||||
topMargin: Math.floor(UM.Theme.getSize("default_margin").height / 2);
|
||||
}
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
width: parent.width;
|
||||
|
||||
Rectangle {
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
height: parent.height;
|
||||
visible: !printJob;
|
||||
width: Math.round(parent.width / 2);
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default");
|
||||
text: printJob ? printJob.owner : ""; // Supress QML warnings
|
||||
visible: printJob;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: printJobPreview;
|
||||
property var useUltibot: false;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
horizontalCenter: parent.horizontalCenter;
|
||||
top: printJobOwnerName.bottom;
|
||||
topMargin: UM.Theme.getSize("default_margin").height;
|
||||
}
|
||||
width: height;
|
||||
|
||||
// Skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
radius: UM.Theme.getSize("default_margin").width;
|
||||
visible: !printJob;
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Image {
|
||||
id: previewImage;
|
||||
anchors.fill: parent;
|
||||
opacity: printJob && printJob.state == "error" ? 0.5 : 1.0;
|
||||
source: printJob ? printJob.previewImageUrl : "";
|
||||
visible: printJob;
|
||||
}
|
||||
|
||||
UM.RecolorImage {
|
||||
id: ultiBotImage;
|
||||
|
||||
anchors.centerIn: printJobPreview;
|
||||
color: UM.Theme.getColor("monitor_placeholder_image");
|
||||
height: printJobPreview.height;
|
||||
source: "../svg/ultibot.svg";
|
||||
sourceSize {
|
||||
height: height;
|
||||
width: width;
|
||||
}
|
||||
/* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or
|
||||
not in order to determine if we show the placeholder (ultibot) image instead. */
|
||||
visible: printJob && previewImage.status == Image.Error;
|
||||
width: printJobPreview.width;
|
||||
}
|
||||
|
||||
UM.RecolorImage {
|
||||
id: statusImage;
|
||||
anchors.centerIn: printJobPreview;
|
||||
color: UM.Theme.getColor("monitor_image_overlay");
|
||||
height: 0.5 * printJobPreview.height;
|
||||
source: printJob && printJob.state == "error" ? "../svg/aborted-icon.svg" : "";
|
||||
sourceSize {
|
||||
height: height;
|
||||
width: width;
|
||||
}
|
||||
visible: source != "";
|
||||
width: 0.5 * printJobPreview.width;
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: totalTimeLabel;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
right: parent.right;
|
||||
}
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default");
|
||||
text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : "";
|
||||
}
|
||||
}
|
||||
|
||||
// Divider
|
||||
Rectangle {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter;
|
||||
verticalCenter: parent.verticalCenter;
|
||||
}
|
||||
color: !printJob ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_lining_light");
|
||||
height: parent.height - 2 * UM.Theme.getSize("default_margin").height;
|
||||
width: UM.Theme.getSize("default_lining").width;
|
||||
}
|
||||
|
||||
// Right content
|
||||
Item {
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.horizontalCenter;
|
||||
margins: UM.Theme.getSize("wide_margin").width;
|
||||
right: parent.right;
|
||||
top: parent.top;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: targetPrinterLabel;
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
width: parent.width;
|
||||
|
||||
Rectangle {
|
||||
visible: !printJob;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
anchors.fill: parent;
|
||||
}
|
||||
|
||||
Label {
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default_bold");
|
||||
text: {
|
||||
if (printJob !== null) {
|
||||
if (printJob.assignedPrinter == null) {
|
||||
if (printJob.state == "error") {
|
||||
return catalog.i18nc("@label", "Waiting for: Unavailable printer");
|
||||
}
|
||||
return catalog.i18nc("@label", "Waiting for: First available");
|
||||
} else {
|
||||
return catalog.i18nc("@label", "Waiting for: ") + printJob.assignedPrinter.name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
visible: printJob;
|
||||
}
|
||||
}
|
||||
|
||||
PrinterInfoBlock {
|
||||
anchors.bottom: parent.bottom;
|
||||
printer: root.printJon && root.printJob.assignedPrinter;
|
||||
printJob: root.printJob;
|
||||
}
|
||||
}
|
||||
|
||||
PrintJobContextMenu {
|
||||
id: contextButton;
|
||||
anchors {
|
||||
right: mainContent.right;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width * 3 + root.shadowRadius;
|
||||
top: mainContent.top;
|
||||
topMargin: UM.Theme.getSize("default_margin").height;
|
||||
}
|
||||
printJob: root.printJob;
|
||||
visible: root.printJob;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: configChangesBox;
|
||||
height: childrenRect.height;
|
||||
visible: printJob && printJob.configurationChanges.length !== 0;
|
||||
width: parent.width;
|
||||
|
||||
// Config change toggle
|
||||
Rectangle {
|
||||
id: configChangeToggle;
|
||||
color: {
|
||||
if (configChangeToggleArea.containsMouse) {
|
||||
return UM.Theme.getColor("viewport_background"); // TODO: Theme!
|
||||
} else {
|
||||
return "transparent";
|
||||
}
|
||||
}
|
||||
width: parent.width;
|
||||
height: UM.Theme.getSize("default_margin").height * 4; // TODO: Theme!
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
top: parent.top;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: !printJob ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_lining_light");
|
||||
height: UM.Theme.getSize("default_lining").height;
|
||||
width: parent.width;
|
||||
}
|
||||
|
||||
UM.RecolorImage {
|
||||
anchors {
|
||||
right: configChangeToggleLabel.left;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
||||
verticalCenter: parent.verticalCenter;
|
||||
}
|
||||
color: UM.Theme.getColor("text");
|
||||
height: 23 * screenScaleFactor; // TODO: Theme!
|
||||
source: "../svg/warning-icon.svg";
|
||||
sourceSize {
|
||||
height: height;
|
||||
width: width;
|
||||
}
|
||||
width: 23 * screenScaleFactor; // TODO: Theme!
|
||||
}
|
||||
|
||||
Label {
|
||||
id: configChangeToggleLabel;
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter;
|
||||
verticalCenter: parent.verticalCenter;
|
||||
}
|
||||
color: UM.Theme.getColor("text");
|
||||
font: UM.Theme.getFont("default");
|
||||
text: catalog.i18nc("@label", "Configuration change");
|
||||
}
|
||||
|
||||
UM.RecolorImage {
|
||||
anchors {
|
||||
left: configChangeToggleLabel.right;
|
||||
leftMargin: UM.Theme.getSize("default_margin").width;
|
||||
verticalCenter: parent.verticalCenter;
|
||||
}
|
||||
color: UM.Theme.getColor("text");
|
||||
height: 15 * screenScaleFactor; // TODO: Theme!
|
||||
source: {
|
||||
if (configChangeDetails.visible) {
|
||||
return UM.Theme.getIcon("arrow_top");
|
||||
} else {
|
||||
return UM.Theme.getIcon("arrow_bottom");
|
||||
}
|
||||
}
|
||||
sourceSize {
|
||||
width: width;
|
||||
height: height;
|
||||
}
|
||||
width: 15 * screenScaleFactor; // TODO: Theme!
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: configChangeToggleArea;
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
onClicked: {
|
||||
configChangeDetails.visible = !configChangeDetails.visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Config change details
|
||||
Item {
|
||||
id: configChangeDetails;
|
||||
anchors.top: configChangeToggle.bottom;
|
||||
Behavior on height { NumberAnimation { duration: 100 } }
|
||||
// In case of really massive multi-line configuration changes
|
||||
height: visible ? Math.max(UM.Theme.getSize("monitor_config_override_box").height, childrenRect.height) : 0;
|
||||
visible: false;
|
||||
width: parent.width;
|
||||
|
||||
Item {
|
||||
anchors {
|
||||
bottomMargin: UM.Theme.getSize("wide_margin").height;
|
||||
fill: parent;
|
||||
leftMargin: UM.Theme.getSize("wide_margin").height * 4;
|
||||
rightMargin: UM.Theme.getSize("wide_margin").height * 4;
|
||||
topMargin: UM.Theme.getSize("wide_margin").height;
|
||||
}
|
||||
clip: true;
|
||||
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
elide: Text.ElideRight;
|
||||
color: UM.Theme.getColor("text");
|
||||
font: UM.Theme.getFont("default");
|
||||
text: {
|
||||
if (!printJob || printJob.configurationChanges.length === 0) {
|
||||
return "";
|
||||
}
|
||||
var topLine;
|
||||
if (materialsAreKnown(printJob)) {
|
||||
topLine = catalog.i18nc("@label", "The assigned printer, %1, requires the following configuration change(s):").arg(printJob.assignedPrinter.name);
|
||||
} else {
|
||||
topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printJob.assignedPrinter.name);
|
||||
}
|
||||
var result = "<p>" + topLine +"</p>";
|
||||
for (var i = 0; i < printJob.configurationChanges.length; i++) {
|
||||
var change = printJob.configurationChanges[i];
|
||||
var text;
|
||||
switch (change.typeOfChange) {
|
||||
case "material_change":
|
||||
text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName);
|
||||
break;
|
||||
case "material_insert":
|
||||
text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName);
|
||||
break;
|
||||
case "print_core_change":
|
||||
text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName);
|
||||
break;
|
||||
case "buildplate_change":
|
||||
text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name));
|
||||
break;
|
||||
default:
|
||||
text = "";
|
||||
}
|
||||
result += "<p><b>" + text + "</b></p>";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
wrapMode: Text.WordWrap;
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
}
|
||||
background: Rectangle {
|
||||
border {
|
||||
color: UM.Theme.getColor("monitor_lining_heavy");
|
||||
width: UM.Theme.getSize("default_lining").width;
|
||||
}
|
||||
color: parent.hovered ? UM.Theme.getColor("monitor_card_background_inactive") : UM.Theme.getColor("monitor_card_background");
|
||||
implicitHeight: UM.Theme.getSize("default_margin").height * 3;
|
||||
implicitWidth: UM.Theme.getSize("default_margin").height * 8;
|
||||
}
|
||||
contentItem: Label {
|
||||
color: UM.Theme.getColor("text");
|
||||
font: UM.Theme.getFont("medium");
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
text: parent.text;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
onClicked: {
|
||||
overrideConfirmationDialog.visible = true;
|
||||
}
|
||||
text: catalog.i18nc("@label", "Override");
|
||||
visible: {
|
||||
if (printJob && printJob.configurationChanges) {
|
||||
var length = printJob.configurationChanges.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var typeOfChange = printJob.configurationChanges[i].typeOfChange;
|
||||
if (typeOfChange === "material_insert" || typeOfChange === "buildplate_change") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: overrideConfirmationDialog;
|
||||
Component.onCompleted: visible = false;
|
||||
icon: StandardIcon.Warning;
|
||||
onYes: OutputDevice.forceSendJob(printJob.key);
|
||||
standardButtons: StandardButton.Yes | StandardButton.No;
|
||||
text: {
|
||||
if (!printJob) {
|
||||
return "";
|
||||
}
|
||||
var printJobName = formatPrintJobName(printJob.name);
|
||||
var confirmText = catalog.i18nc("@label", "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?").arg(printJobName);
|
||||
return confirmText;
|
||||
}
|
||||
title: catalog.i18nc("@window:title", "Override configuration configuration and start print");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Utils
|
||||
function formatPrintJobName(name) {
|
||||
var extensions = [ ".gz", ".gcode", ".ufp" ];
|
||||
for (var i = 0; i < extensions.length; i++) {
|
||||
var extension = extensions[i];
|
||||
if (name.slice(-extension.length) === extension) {
|
||||
name = name.substring(0, name.length - extension.length);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
function materialsAreKnown(job) {
|
||||
var conf0 = job.configuration[0];
|
||||
if (conf0 && !conf0.material.material) {
|
||||
return false;
|
||||
}
|
||||
var conf1 = job.configuration[1];
|
||||
if (conf1 && !conf1.material.material) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function formatBuildPlateType(buildPlateType) {
|
||||
var translationText = "";
|
||||
switch (buildPlateType) {
|
||||
case "glass":
|
||||
translationText = catalog.i18nc("@label", "Glass");
|
||||
break;
|
||||
case "aluminum":
|
||||
translationText = catalog.i18nc("@label", "Aluminum");
|
||||
break;
|
||||
default:
|
||||
translationText = null;
|
||||
}
|
||||
return translationText;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls 1.4 as LegacyControls
|
||||
import UM 1.3 as UM
|
||||
|
||||
// Includes print job name, owner, and preview
|
||||
|
||||
Item {
|
||||
property var job: null;
|
||||
property var useUltibot: false;
|
||||
height: 100 * screenScaleFactor;
|
||||
width: height;
|
||||
|
||||
// Skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
radius: UM.Theme.getSize("default_margin").width;
|
||||
visible: !job;
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Image {
|
||||
id: previewImage;
|
||||
visible: job;
|
||||
source: job ? job.previewImageUrl : "";
|
||||
opacity: {
|
||||
if (job == null) {
|
||||
return 1.0;
|
||||
}
|
||||
var states = ["wait_cleanup", "wait_user_action", "error", "paused"];
|
||||
if (states.indexOf(job.state) !== -1) {
|
||||
return 0.5;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
anchors.fill: parent;
|
||||
}
|
||||
|
||||
UM.RecolorImage {
|
||||
id: ultibotImage;
|
||||
anchors.centerIn: parent;
|
||||
color: UM.Theme.getColor("monitor_placeholder_image"); // TODO: Theme!
|
||||
height: parent.height;
|
||||
source: "../svg/ultibot.svg";
|
||||
sourceSize {
|
||||
height: height;
|
||||
width: width;
|
||||
}
|
||||
/* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or
|
||||
not in order to determine if we show the placeholder (ultibot) image instead. */
|
||||
visible: job && previewImage.status == Image.Error;
|
||||
width: parent.width;
|
||||
}
|
||||
|
||||
UM.RecolorImage {
|
||||
id: statusImage;
|
||||
anchors.centerIn: parent;
|
||||
color: "black"; // TODO: Theme!
|
||||
height: Math.round(0.5 * parent.height);
|
||||
source: job && job.state == "error" ? "../svg/aborted-icon.svg" : "";
|
||||
sourceSize {
|
||||
height: height;
|
||||
width: width;
|
||||
}
|
||||
visible: source != "";
|
||||
width: Math.round(0.5 * parent.width);
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 2.0
|
||||
import UM 1.3 as UM
|
||||
|
||||
Column {
|
||||
property var job: null;
|
||||
height: childrenRect.height;
|
||||
spacing: Math.floor( UM.Theme.getSize("default_margin").height / 2); // TODO: Use explicit theme size
|
||||
width: parent.width;
|
||||
|
||||
Item {
|
||||
id: jobName;
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
width: parent.width;
|
||||
|
||||
// Skeleton loading
|
||||
Rectangle {
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
height: parent.height;
|
||||
visible: !job;
|
||||
width: Math.round(parent.width / 3);
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default_bold");
|
||||
text: job && job.name ? job.name : "";
|
||||
visible: job;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: ownerName;
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
width: parent.width;
|
||||
|
||||
// Skeleton loading
|
||||
Rectangle {
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill");
|
||||
height: parent.height;
|
||||
visible: !job;
|
||||
width: Math.round(parent.width / 2);
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("text")
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default");
|
||||
text: job ? job.owner : "";
|
||||
visible: job;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,241 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import UM 1.3 as UM
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
|
||||
property var shadowOffset: UM.Theme.getSize("monitor_shadow_offset").width;
|
||||
property var printer: null;
|
||||
property var collapsed: true;
|
||||
height: childrenRect.height + shadowRadius * 2; // Bubbles upward
|
||||
width: parent.width; // Bubbles downward
|
||||
|
||||
// The actual card (white block)
|
||||
Rectangle {
|
||||
// 5px margin, but shifted 2px vertically because of the shadow
|
||||
anchors {
|
||||
bottomMargin: root.shadowRadius + root.shadowOffset;
|
||||
leftMargin: root.shadowRadius;
|
||||
rightMargin: root.shadowRadius;
|
||||
topMargin: root.shadowRadius - root.shadowOffset;
|
||||
}
|
||||
color: {
|
||||
if (!printer) {
|
||||
return UM.Theme.getColor("monitor_card_background_inactive");
|
||||
}
|
||||
if (printer.state == "disabled") {
|
||||
return UM.Theme.getColor("monitor_card_background_inactive");
|
||||
} else {
|
||||
return UM.Theme.getColor("monitor_card_background");
|
||||
}
|
||||
}
|
||||
height: childrenRect.height;
|
||||
layer.effect: DropShadow {
|
||||
radius: root.shadowRadius;
|
||||
verticalOffset: root.shadowOffset;
|
||||
color: "#3F000000"; // 25% shadow
|
||||
}
|
||||
layer.enabled: true
|
||||
width: parent.width - 2 * shadowRadius;
|
||||
|
||||
Column {
|
||||
id: cardContents;
|
||||
height: childrenRect.height;
|
||||
width: parent.width;
|
||||
|
||||
// Main card
|
||||
Item {
|
||||
id: mainCard;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
leftMargin: UM.Theme.getSize("default_margin").width;
|
||||
right: parent.right;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
||||
}
|
||||
height: 60 * screenScaleFactor + 2 * UM.Theme.getSize("default_margin").height;
|
||||
width: parent.width;
|
||||
|
||||
// Machine icon
|
||||
Item {
|
||||
id: machineIcon;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
height: parent.height - 2 * UM.Theme.getSize("default_margin").width;
|
||||
width: height;
|
||||
|
||||
// Skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill_dark");
|
||||
radius: UM.Theme.getSize("default_margin").width;
|
||||
visible: !printer;
|
||||
}
|
||||
|
||||
// Content
|
||||
UM.RecolorImage {
|
||||
anchors.centerIn: parent;
|
||||
color: {
|
||||
if (printer && printer.activePrintJob != undefined) {
|
||||
return UM.Theme.getColor("monitor_printer_icon");
|
||||
}
|
||||
return UM.Theme.getColor("monitor_printer_icon_inactive");
|
||||
}
|
||||
height: sourceSize.height;
|
||||
source: {
|
||||
if (!printer) {
|
||||
return "";
|
||||
}
|
||||
switch(printer.type) {
|
||||
case "Ultimaker 3":
|
||||
return "../svg/UM3-icon.svg";
|
||||
case "Ultimaker 3 Extended":
|
||||
return "../svg/UM3x-icon.svg";
|
||||
case "Ultimaker S5":
|
||||
return "../svg/UMs5-icon.svg";
|
||||
}
|
||||
}
|
||||
visible: printer;
|
||||
width: sourceSize.width;
|
||||
}
|
||||
}
|
||||
|
||||
// Printer info
|
||||
Item {
|
||||
id: printerInfo;
|
||||
anchors {
|
||||
left: machineIcon.right;
|
||||
leftMargin: UM.Theme.getSize("wide_margin").width;
|
||||
right: collapseIcon.left;
|
||||
verticalCenter: machineIcon.verticalCenter;
|
||||
}
|
||||
height: childrenRect.height;
|
||||
|
||||
// Machine name
|
||||
Item {
|
||||
id: machineNameLabel;
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
width: {
|
||||
var percent = printer ? 0.75 : 0.3;
|
||||
return Math.round(parent.width * percent);
|
||||
}
|
||||
|
||||
// Skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill_dark");
|
||||
visible: !printer;
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("text");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default_bold");
|
||||
text: printer ? printer.name : "";
|
||||
visible: printer;
|
||||
width: parent.width;
|
||||
}
|
||||
}
|
||||
|
||||
// Job name
|
||||
Item {
|
||||
id: activeJobLabel;
|
||||
anchors {
|
||||
top: machineNameLabel.bottom;
|
||||
topMargin: Math.round(UM.Theme.getSize("default_margin").height / 2);
|
||||
}
|
||||
height: UM.Theme.getSize("monitor_text_line").height;
|
||||
width: Math.round(parent.width * 0.75);
|
||||
|
||||
// Skeleton
|
||||
Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_skeleton_fill_dark");
|
||||
visible: !printer;
|
||||
}
|
||||
|
||||
// Actual content
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
color: UM.Theme.getColor("monitor_text_inactive");
|
||||
elide: Text.ElideRight;
|
||||
font: UM.Theme.getFont("default");
|
||||
text: {
|
||||
if (!printer) {
|
||||
return "";
|
||||
}
|
||||
if (printer.state == "disabled") {
|
||||
return catalog.i18nc("@label", "Not available");
|
||||
} else if (printer.state == "unreachable") {
|
||||
return catalog.i18nc("@label", "Unreachable");
|
||||
}
|
||||
if (printer.activePrintJob != null && printer.activePrintJob.name) {
|
||||
return printer.activePrintJob.name;
|
||||
}
|
||||
return catalog.i18nc("@label", "Available");
|
||||
}
|
||||
visible: printer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collapse icon
|
||||
UM.RecolorImage {
|
||||
id: collapseIcon;
|
||||
anchors {
|
||||
right: parent.right;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
||||
verticalCenter: parent.verticalCenter;
|
||||
}
|
||||
color: UM.Theme.getColor("text");
|
||||
height: 15 * screenScaleFactor; // TODO: Theme!
|
||||
source: root.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom");
|
||||
sourceSize {
|
||||
height: height;
|
||||
width: width;
|
||||
}
|
||||
visible: printer;
|
||||
width: 15 * screenScaleFactor; // TODO: Theme!
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
enabled: printer;
|
||||
onClicked: {
|
||||
if (model && root.collapsed) {
|
||||
printerList.currentIndex = model.index;
|
||||
} else {
|
||||
printerList.currentIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: printerList;
|
||||
onCurrentIndexChanged: {
|
||||
root.collapsed = printerList.currentIndex != model.index;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Detailed card
|
||||
PrinterCardDetails {
|
||||
collapsed: root.collapsed;
|
||||
printer: root.printer;
|
||||
visible: root.printer;
|
||||
}
|
||||
|
||||
// Progress bar
|
||||
PrinterCardProgressBar {
|
||||
visible: printer && printer.activePrintJob != null;
|
||||
width: parent.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls 1.4 as LegacyControls
|
||||
import UM 1.3 as UM
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
property var printer: null;
|
||||
property var printJob: printer ? printer.activePrintJob : null;
|
||||
property var collapsed: true;
|
||||
Behavior on height { NumberAnimation { duration: 100 } }
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
height: collapsed ? 0 : childrenRect.height;
|
||||
opacity: collapsed ? 0 : 1;
|
||||
width: parent.width;
|
||||
|
||||
Column {
|
||||
id: contentColumn;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
leftMargin: UM.Theme.getSize("default_margin").width;
|
||||
right: parent.right;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
||||
}
|
||||
height: childrenRect.height + UM.Theme.getSize("default_margin").height;
|
||||
spacing: UM.Theme.getSize("default_margin").height;
|
||||
width: parent.width;
|
||||
|
||||
HorizontalLine {}
|
||||
|
||||
PrinterInfoBlock {
|
||||
printer: root.printer;
|
||||
printJob: root.printer ? root.printer.activePrintJob : null;
|
||||
}
|
||||
|
||||
HorizontalLine {}
|
||||
|
||||
Row {
|
||||
height: childrenRect.height;
|
||||
visible: root.printJob;
|
||||
width: parent.width;
|
||||
|
||||
PrintJobTitle {
|
||||
job: root.printer ? root.printer.activePrintJob : null;
|
||||
}
|
||||
PrintJobContextMenu {
|
||||
id: contextButton;
|
||||
anchors {
|
||||
right: parent.right;
|
||||
rightMargin: UM.Theme.getSize("wide_margin").width;
|
||||
}
|
||||
printJob: root.printer ? root.printer.activePrintJob : null;
|
||||
visible: printJob;
|
||||
}
|
||||
}
|
||||
|
||||
PrintJobPreview {
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
job: root.printer && root.printer.activePrintJob ? root.printer.activePrintJob : null;
|
||||
visible: root.printJob;
|
||||
}
|
||||
|
||||
CameraButton {
|
||||
id: showCameraButton;
|
||||
iconSource: "../svg/camera-icon.svg";
|
||||
visible: root.printer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtQuick.Controls 1.4
|
||||
import UM 1.3 as UM
|
||||
|
||||
ProgressBar {
|
||||
property var progress: {
|
||||
if (!printer || printer.activePrintJob == null) {
|
||||
return 0;
|
||||
}
|
||||
var result = printer.activePrintJob.timeElapsed / printer.activePrintJob.timeTotal;
|
||||
if (result > 1.0) {
|
||||
result = 1.0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
style: ProgressBarStyle {
|
||||
property var remainingTime: {
|
||||
if (!printer || printer.activePrintJob == null) {
|
||||
return 0;
|
||||
}
|
||||
/* Sometimes total minus elapsed is less than 0. Use Math.max() to prevent remaining
|
||||
time from ever being less than 0. Negative durations cause strange behavior such
|
||||
as displaying "-1h -1m". */
|
||||
return Math.max(printer.activePrintJob.timeTotal - printer.activePrintJob.timeElapsed, 0);
|
||||
}
|
||||
property var progressText: {
|
||||
if (printer === null ) {
|
||||
return "";
|
||||
}
|
||||
switch (printer.activePrintJob.state) {
|
||||
case "wait_cleanup":
|
||||
if (printer.activePrintJob.timeTotal > printer.activePrintJob.timeElapsed) {
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
}
|
||||
return catalog.i18nc("@label:status", "Finished");
|
||||
case "pre_print":
|
||||
case "sent_to_printer":
|
||||
return catalog.i18nc("@label:status", "Preparing");
|
||||
case "aborted":
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
case "wait_user_action":
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
case "pausing":
|
||||
return catalog.i18nc("@label:status", "Pausing");
|
||||
case "paused":
|
||||
return OutputDevice.formatDuration( remainingTime );
|
||||
case "resuming":
|
||||
return catalog.i18nc("@label:status", "Resuming");
|
||||
case "queued":
|
||||
return catalog.i18nc("@label:status", "Action required");
|
||||
default:
|
||||
return OutputDevice.formatDuration( remainingTime );
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
color: UM.Theme.getColor("monitor_progress_background");
|
||||
implicitHeight: visible ? 24 : 0;
|
||||
implicitWidth: 100;
|
||||
}
|
||||
progress: Rectangle {
|
||||
id: progressItem;
|
||||
color: {
|
||||
if (! printer || !printer.activePrintJob) {
|
||||
return "black";
|
||||
}
|
||||
var state = printer.activePrintJob.state
|
||||
var inactiveStates = [
|
||||
"pausing",
|
||||
"paused",
|
||||
"resuming",
|
||||
"wait_cleanup"
|
||||
];
|
||||
if (inactiveStates.indexOf(state) > -1 && remainingTime > 0) {
|
||||
return UM.Theme.getColor("monitor_progress_fill_inactive");
|
||||
} else {
|
||||
return UM.Theme.getColor("monitor_progress_fill");
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: progressLabel;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
leftMargin: getTextOffset();
|
||||
}
|
||||
text: progressText;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
color: progressItem.width + progressLabel.width < control.width ? UM.Theme.getColor("text") : UM.Theme.getColor("monitor_progress_fill_text");
|
||||
width: contentWidth;
|
||||
font: UM.Theme.getFont("default");
|
||||
}
|
||||
|
||||
function getTextOffset() {
|
||||
if (progressItem.width + progressLabel.width + 16 < control.width) {
|
||||
return progressItem.width + UM.Theme.getSize("default_margin").width;
|
||||
} else {
|
||||
return progressItem.width - progressLabel.width - UM.Theme.getSize("default_margin").width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
value: progress;
|
||||
width: parent.width;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// 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.4
|
||||
import UM 1.2 as UM
|
||||
|
||||
Item {
|
||||
property alias text: familyNameLabel.text;
|
||||
property var padding: 3 * screenScaleFactor; // TODO: Theme!
|
||||
implicitHeight: familyNameLabel.contentHeight + 2 * padding; // Apply the padding to top and bottom.
|
||||
implicitWidth: Math.max(48 * screenScaleFactor, familyNameLabel.contentWidth + implicitHeight); // The extra height is added to ensure the radius doesn't cut something off.
|
||||
|
||||
Rectangle {
|
||||
id: background;
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter;
|
||||
right: parent.right;
|
||||
}
|
||||
color: familyNameLabel.text.length < 1 ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_pill_background");
|
||||
height: parent.height;
|
||||
radius: 0.5 * height;
|
||||
width: parent.width;
|
||||
}
|
||||
|
||||
Label {
|
||||
id: familyNameLabel;
|
||||
anchors.centerIn: parent;
|
||||
color: UM.Theme.getColor("text");
|
||||
text: "";
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls 1.4 as LegacyControls
|
||||
import UM 1.3 as UM
|
||||
|
||||
// Includes printer type pill and extuder configurations
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
property var printer: null;
|
||||
property var printJob: null;
|
||||
width: parent.width;
|
||||
height: childrenRect.height;
|
||||
|
||||
// Printer family pills
|
||||
Row {
|
||||
id: printerFamilyPills;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
}
|
||||
height: childrenRect.height;
|
||||
spacing: Math.round(0.5 * UM.Theme.getSize("default_margin").width);
|
||||
width: parent.width;
|
||||
|
||||
Repeater {
|
||||
id: compatiblePills;
|
||||
delegate: PrinterFamilyPill {
|
||||
text: modelData;
|
||||
}
|
||||
model: printJob ? printJob.compatibleMachineFamilies : [];
|
||||
visible: printJob;
|
||||
|
||||
}
|
||||
|
||||
PrinterFamilyPill {
|
||||
text: printer ? printer.type : "";
|
||||
visible: !compatiblePills.visible && printer;
|
||||
}
|
||||
}
|
||||
|
||||
// Extruder info
|
||||
Row {
|
||||
id: extrudersInfo;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
||||
top: printerFamilyPills.bottom;
|
||||
topMargin: UM.Theme.getSize("default_margin").height;
|
||||
}
|
||||
height: childrenRect.height;
|
||||
spacing: UM.Theme.getSize("default_margin").width;
|
||||
width: parent.width;
|
||||
|
||||
PrintCoreConfiguration {
|
||||
width: Math.round(parent.width / 2) * screenScaleFactor;
|
||||
printCoreConfiguration: getExtruderConfig(0);
|
||||
}
|
||||
|
||||
PrintCoreConfiguration {
|
||||
width: Math.round(parent.width / 2) * screenScaleFactor;
|
||||
printCoreConfiguration: getExtruderConfig(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getExtruderConfig( i ) {
|
||||
if (root.printJob) {
|
||||
// Use more-specific print job if possible
|
||||
return root.printJob.configuration.extruderConfigurations[i];
|
||||
}
|
||||
if (root.printer) {
|
||||
return root.printer.printerConfiguration.extruderConfigurations[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ Item {
|
|||
Button {
|
||||
height: UM.Theme.getSize("save_button_save_to_button").height;
|
||||
onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication();
|
||||
style: UM.Theme.styles.sidebar_action_button;
|
||||
style: UM.Theme.styles.print_setup_action_button;
|
||||
text: catalog.i18nc("@action:button", "Request Access");
|
||||
tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer");
|
||||
visible: printerConnected && !printerAcceptsCommands && !authenticationRequested;
|
||||
|
@ -38,7 +38,7 @@ Item {
|
|||
Button {
|
||||
height: UM.Theme.getSize("save_button_save_to_button").height;
|
||||
onClicked: connectActionDialog.show();
|
||||
style: UM.Theme.styles.sidebar_action_button;
|
||||
style: UM.Theme.styles.print_setup_action_button;
|
||||
text: catalog.i18nc("@action:button", "Connect");
|
||||
tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer");
|
||||
visible: !printerConnected;
|
||||
|
|
|
@ -64,7 +64,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
|
||||
self._received_print_jobs = False # type: bool
|
||||
|
||||
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml")
|
||||
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/MonitorStage.qml")
|
||||
|
||||
# See comments about this hack with the clusterPrintersChanged signal
|
||||
self.printersChanged.connect(self.clusterPrintersChanged)
|
||||
|
@ -607,17 +607,24 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
|
||||
def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel":
|
||||
material_manager = CuraApplication.getInstance().getMaterialManager()
|
||||
material_group_list = material_manager.getMaterialGroupListByGUID(material_data["guid"])
|
||||
# This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the
|
||||
# material is unknown to Cura, so we should return an "empty" or "unknown" material model.
|
||||
material_group_list = None
|
||||
|
||||
# Avoid crashing if there is no "guid" field in the metadata
|
||||
material_guid = material_data.get("guid")
|
||||
if material_guid:
|
||||
material_group_list = material_manager.getMaterialGroupListByGUID(material_guid)
|
||||
|
||||
# This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the
|
||||
# material is unknown to Cura, so we should return an "empty" or "unknown" material model.
|
||||
if material_group_list is None:
|
||||
material_name = "Empty" if len(material_data["guid"]) == 0 else "Unknown"
|
||||
return MaterialOutputModel(guid = material_data["guid"],
|
||||
type = material_data.get("type", ""),
|
||||
color = material_data.get("color", ""),
|
||||
brand = material_data.get("brand", ""),
|
||||
name = material_data.get("name", material_name)
|
||||
)
|
||||
material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
|
||||
else i18n_catalog.i18nc("@label:material", "Unknown")
|
||||
return MaterialOutputModel(guid = material_data.get("guid", ""),
|
||||
type = material_data.get("type", ""),
|
||||
color = material_data.get("color", ""),
|
||||
brand = material_data.get("brand", ""),
|
||||
name = material_data.get("name", material_name)
|
||||
)
|
||||
|
||||
# Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
|
||||
read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
|
||||
|
@ -643,9 +650,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
color = material_data["color"]
|
||||
brand = material_data["brand"]
|
||||
material_type = material_data["material"]
|
||||
name = "Empty" if material_data["material"] == "empty" else "Unknown"
|
||||
return MaterialOutputModel(guid=material_data["guid"], type=material_type,
|
||||
brand=brand, color=color, name=name)
|
||||
name = i18n_catalog.i18nc("@label:material", "Empty") if material_data["material"] == "empty" \
|
||||
else i18n_catalog.i18nc("@label:material", "Unknown")
|
||||
return MaterialOutputModel(guid = material_data["guid"], type = material_type,
|
||||
brand = brand, color = color, name = name)
|
||||
|
||||
def _updatePrinter(self, printer: PrinterOutputModel, data: Dict[str, Any]) -> None:
|
||||
# For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer.
|
||||
|
|
46
plugins/USBPrinting/MonitorItem.qml
Normal file
46
plugins/USBPrinting/MonitorItem.qml
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
Component
|
||||
{
|
||||
Item
|
||||
{
|
||||
Rectangle
|
||||
{
|
||||
anchors.right: parent.right
|
||||
width: parent.width * 0.3
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
Cura.PrintMonitor
|
||||
{
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: footerSeparator
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("wide_lining").height
|
||||
color: UM.Theme.getColor("wide_lining")
|
||||
anchors.bottom: monitorButton.top
|
||||
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
|
||||
}
|
||||
|
||||
// MonitorButton is actually the bottom footer panel.
|
||||
Cura.MonitorButton
|
||||
{
|
||||
id: monitorButton
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import os
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.i18n import i18nCatalog
|
||||
|
@ -64,7 +65,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
self._accepts_commands = True
|
||||
|
||||
self._paused = False
|
||||
self._printer_busy = False # when printer is preheating and waiting (M190/M109), or when waiting for action on the printer
|
||||
self._printer_busy = False # When printer is preheating and waiting (M190/M109), or when waiting for action on the printer
|
||||
|
||||
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
||||
|
||||
|
@ -77,6 +78,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
self._firmware_name_requested = False
|
||||
self._firmware_updater = AvrFirmwareUpdater(self)
|
||||
|
||||
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "MonitorItem.qml")
|
||||
|
||||
CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit)
|
||||
|
||||
# This is a callback function that checks if there is any printing in progress via USB when the application tries
|
||||
|
|
|
@ -19,7 +19,7 @@ Cura.MachineAction
|
|||
property bool heatupBedStarted: false
|
||||
property bool printerConnected: Cura.MachineManager.printerConnected
|
||||
|
||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||
UM.I18nCatalog { id: catalog; name: "cura"}
|
||||
Label
|
||||
{
|
||||
id: pageTitle
|
||||
|
|
|
@ -36,7 +36,7 @@ UM.Dialog
|
|||
width: parent.width
|
||||
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
||||
|
||||
UM.I18nCatalog { id: catalog; name:"cura" }
|
||||
UM.I18nCatalog { id: catalog; name: "cura" }
|
||||
|
||||
Button
|
||||
{
|
||||
|
|
|
@ -356,6 +356,23 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"PreviewStage": {
|
||||
"package_info": {
|
||||
"package_id": "PreviewStage",
|
||||
"package_type": "plugin",
|
||||
"display_name": "Preview Stage",
|
||||
"description": "Provides a preview stage in Cura.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": 5,
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
"display_name": "Ultimaker B.V.",
|
||||
"email": "plugins@ultimaker.com",
|
||||
"website": "https://ultimaker.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RemovableDriveOutputDevice": {
|
||||
"package_info": {
|
||||
"package_id": "RemovableDriveOutputDevice",
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
// Copyright (c) 2015 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.Window 2.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
|
||||
UM.Dialog
|
||||
{
|
||||
id: base
|
||||
|
||||
//: About dialog title
|
||||
title: catalog.i18nc("@title:window","About Cura")
|
||||
|
||||
minimumWidth: 500 * screenScaleFactor
|
||||
minimumHeight: 650 * screenScaleFactor
|
||||
width: minimumWidth
|
||||
height: minimumHeight
|
||||
|
||||
Rectangle
|
||||
{
|
||||
width: parent.width + 2 * margin // margin from Dialog.qml
|
||||
height: version.y + version.height + margin
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: - margin
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
color: UM.Theme.getColor("viewport_background")
|
||||
}
|
||||
|
||||
Image
|
||||
{
|
||||
id: logo
|
||||
width: (base.minimumWidth * 0.85) | 0
|
||||
height: (width * (1/4.25)) | 0
|
||||
|
||||
source: UM.Theme.getImage("logo")
|
||||
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: ((base.minimumWidth - width) / 2) | 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: version
|
||||
|
||||
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
|
||||
font: UM.Theme.getFont("large")
|
||||
color: UM.Theme.getColor("text")
|
||||
anchors.right : logo.right
|
||||
anchors.top: logo.bottom
|
||||
anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: description
|
||||
width: parent.width
|
||||
|
||||
//: About dialog application description
|
||||
text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
|
||||
font: UM.Theme.getFont("system")
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: version.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: creditsNotes
|
||||
width: parent.width
|
||||
|
||||
//: About dialog application author note
|
||||
text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:")
|
||||
font: UM.Theme.getFont("system")
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: description.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
id: credits
|
||||
anchors.top: creditsNotes.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
|
||||
width: parent.width
|
||||
height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
|
||||
|
||||
ListView
|
||||
{
|
||||
id: projectsList
|
||||
|
||||
width: parent.width
|
||||
|
||||
delegate: Row
|
||||
{
|
||||
Label
|
||||
{
|
||||
text: "<a href='%1' title='%2'>%2</a>".arg(model.url).arg(model.name)
|
||||
width: (projectsList.width * 0.25) | 0
|
||||
elide: Text.ElideRight
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: model.description
|
||||
elide: Text.ElideRight
|
||||
width: (projectsList.width * 0.6) | 0
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: model.license
|
||||
elide: Text.ElideRight
|
||||
width: (projectsList.width * 0.15) | 0
|
||||
}
|
||||
}
|
||||
model: ListModel
|
||||
{
|
||||
id: projectsModel
|
||||
}
|
||||
Component.onCompleted:
|
||||
{
|
||||
projectsModel.append({ name:"Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
|
||||
projectsModel.append({ name:"Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
|
||||
projectsModel.append({ name:"CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
|
||||
projectsModel.append({ name:"libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
|
||||
|
||||
projectsModel.append({ name:"Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" });
|
||||
projectsModel.append({ name:"Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
|
||||
projectsModel.append({ name:"PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
|
||||
projectsModel.append({ name:"SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
|
||||
projectsModel.append({ name:"Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
|
||||
projectsModel.append({ name:"SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
|
||||
projectsModel.append({ name:"NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
|
||||
projectsModel.append({ name:"NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
|
||||
projectsModel.append({ name:"Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" });
|
||||
projectsModel.append({ name:"Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
|
||||
projectsModel.append({ name:"NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" });
|
||||
projectsModel.append({ name:"libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
|
||||
projectsModel.append({ name:"libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
|
||||
projectsModel.append({ name:"PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
|
||||
projectsModel.append({ name:"python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
|
||||
projectsModel.append({ name:"Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
|
||||
projectsModel.append({ name:"Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" });
|
||||
|
||||
projectsModel.append({ name:"Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
|
||||
projectsModel.append({ name:"Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" });
|
||||
projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightButtons: Button
|
||||
{
|
||||
//: Close about dialog button
|
||||
id: closeButton
|
||||
text: catalog.i18nc("@action:button","Close");
|
||||
|
||||
onClicked: base.visible = false;
|
||||
}
|
||||
}
|
69
resources/qml/Account/AccountDetails.qml
Normal file
69
resources/qml/Account/AccountDetails.qml
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
import UM 1.4 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Column
|
||||
{
|
||||
property var profile: null
|
||||
property var loggedIn: false
|
||||
property var profileImage: ""
|
||||
|
||||
padding: UM.Theme.getSize("wide_margin").height
|
||||
spacing: UM.Theme.getSize("wide_margin").height
|
||||
|
||||
AvatarImage
|
||||
{
|
||||
id: avatar
|
||||
width: UM.Theme.getSize("avatar_image").width
|
||||
height: UM.Theme.getSize("avatar_image").height
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
source:
|
||||
{
|
||||
if(loggedIn)
|
||||
{
|
||||
if(profileImage)
|
||||
{
|
||||
return profileImage
|
||||
}
|
||||
return UM.Theme.getImage("avatar_no_user")
|
||||
}
|
||||
return UM.Theme.getImage("avatar_no_user")
|
||||
}
|
||||
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: information
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
renderType: Text.NativeRendering
|
||||
text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.")
|
||||
font: loggedIn ? UM.Theme.getFont("large") : UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
id: accountOperations
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
sourceComponent: loggedIn ? userOperations : generalOperations
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: userOperations
|
||||
UserOperations { }
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: generalOperations
|
||||
GeneralOperations { }
|
||||
}
|
||||
}
|
76
resources/qml/Account/AccountWidget.qml
Normal file
76
resources/qml/Account/AccountWidget.qml
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
import UM 1.4 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Button
|
||||
{
|
||||
id: accountWidget
|
||||
property var profile: Cura.API.account.userProfile
|
||||
property var loggedIn: Cura.API.account.isLoggedIn
|
||||
|
||||
implicitHeight: UM.Theme.getSize("main_window_header").height
|
||||
implicitWidth: UM.Theme.getSize("main_window_header").height
|
||||
|
||||
background: AvatarImage
|
||||
{
|
||||
id: avatar
|
||||
|
||||
width: Math.round(0.8 * accountWidget.width)
|
||||
height: Math.round(0.8 * accountWidget.height)
|
||||
anchors.verticalCenter: accountWidget.verticalCenter
|
||||
anchors.horizontalCenter: accountWidget.horizontalCenter
|
||||
|
||||
source:
|
||||
{
|
||||
if(loggedIn)
|
||||
{
|
||||
if(profile["profile_image_url"])
|
||||
{
|
||||
return profile["profile_image_url"]
|
||||
}
|
||||
return UM.Theme.getImage("avatar_no_user")
|
||||
}
|
||||
return UM.Theme.getImage("avatar_no_user")
|
||||
}
|
||||
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
|
||||
}
|
||||
|
||||
onClicked: popup.opened ? popup.close() : popup.open()
|
||||
|
||||
Popup
|
||||
{
|
||||
id: popup
|
||||
|
||||
y: parent.height + UM.Theme.getSize("default_arrow").height
|
||||
x: parent.width - width
|
||||
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
|
||||
opacity: opened ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
|
||||
contentItem: AccountDetails
|
||||
{
|
||||
id: panel
|
||||
profile: Cura.API.account.userProfile
|
||||
loggedIn: Cura.API.account.isLoggedIn
|
||||
profileImage: Cura.API.account.profileImageUrl
|
||||
}
|
||||
|
||||
background: UM.PointingRectangle
|
||||
{
|
||||
color: UM.Theme.getColor("tool_panel_background")
|
||||
borderColor: UM.Theme.getColor("lining")
|
||||
borderWidth: UM.Theme.getSize("default_lining").width
|
||||
|
||||
target: Qt.point(width - (accountWidget.width / 2), -10)
|
||||
|
||||
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||
}
|
||||
}
|
||||
}
|
56
resources/qml/Account/AvatarImage.qml
Normal file
56
resources/qml/Account/AvatarImage.qml
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import UM 1.4 as UM
|
||||
|
||||
Item
|
||||
{
|
||||
// This item shows the provided image while applying a round mask to it.
|
||||
// It also shows a round border around it. The color is defined by the outlineColor property.
|
||||
|
||||
id: avatar
|
||||
|
||||
property alias source: profileImage.source
|
||||
property alias outlineColor: profileImageOutline.color
|
||||
|
||||
Image
|
||||
{
|
||||
id: profileImage
|
||||
anchors.fill: parent
|
||||
source: UM.Theme.getImage("avatar_default")
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: false
|
||||
mipmap: true
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: profileImageMask
|
||||
anchors.fill: parent
|
||||
radius: width
|
||||
}
|
||||
|
||||
OpacityMask
|
||||
{
|
||||
anchors.fill: parent
|
||||
source: profileImage
|
||||
maskSource: profileImageMask
|
||||
cached: true
|
||||
}
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: profileImageOutline
|
||||
anchors.centerIn: parent
|
||||
// Make it a bit bigger than it has to, otherwise it sometimes shows a white border.
|
||||
width: parent.width + 2
|
||||
height: parent.height + 2
|
||||
source: UM.Theme.getIcon("circle_outline")
|
||||
sourceSize: Qt.size(parent.width, parent.height)
|
||||
color: UM.Theme.getColor("account_widget_ouline_active")
|
||||
}
|
||||
}
|
31
resources/qml/Account/GeneralOperations.qml
Normal file
31
resources/qml/Account/GeneralOperations.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
// 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 UM 1.4 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Row
|
||||
{
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Cura.SecondaryButton
|
||||
{
|
||||
width: UM.Theme.getSize("account_button").width
|
||||
height: UM.Theme.getSize("account_button").height
|
||||
text: catalog.i18nc("@button", "Create account")
|
||||
onClicked: Qt.openUrlExternally("https://account.ultimaker.com/app/create")
|
||||
fixedWidthMode: true
|
||||
}
|
||||
|
||||
Cura.PrimaryButton
|
||||
{
|
||||
width: UM.Theme.getSize("account_button").width
|
||||
height: UM.Theme.getSize("account_button").height
|
||||
text: catalog.i18nc("@button", "Login")
|
||||
onClicked: Cura.API.account.login()
|
||||
fixedWidthMode: true
|
||||
}
|
||||
}
|
31
resources/qml/Account/UserOperations.qml
Normal file
31
resources/qml/Account/UserOperations.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
// 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 UM 1.4 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Row
|
||||
{
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Cura.SecondaryButton
|
||||
{
|
||||
width: UM.Theme.getSize("account_button").width
|
||||
height: UM.Theme.getSize("account_button").height
|
||||
text: catalog.i18nc("@button", "Manage account")
|
||||
onClicked: Qt.openUrlExternally("https://account.ultimaker.com")
|
||||
fixedWidthMode: true
|
||||
}
|
||||
|
||||
Cura.PrimaryButton
|
||||
{
|
||||
width: UM.Theme.getSize("account_button").width
|
||||
height: UM.Theme.getSize("account_button").height
|
||||
text: catalog.i18nc("@button", "Logout")
|
||||
onClicked: Cura.API.account.logout()
|
||||
fixedWidthMode: true
|
||||
}
|
||||
}
|
119
resources/qml/ActionButton.qml
Normal file
119
resources/qml/ActionButton.qml
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||
import UM 1.1 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
Button
|
||||
{
|
||||
id: button
|
||||
property bool isIconOnRightSide: false
|
||||
|
||||
property alias iconSource: buttonIconLeft.source
|
||||
property alias textFont: buttonText.font
|
||||
property alias cornerRadius: backgroundRect.radius
|
||||
property alias tooltip: tooltip.text
|
||||
property alias cornerSide: backgroundRect.cornerSide
|
||||
|
||||
property color color: UM.Theme.getColor("primary")
|
||||
property color hoverColor: UM.Theme.getColor("primary_hover")
|
||||
property color disabledColor: color
|
||||
property color textColor: UM.Theme.getColor("button_text")
|
||||
property color textHoverColor: textColor
|
||||
property color textDisabledColor: textColor
|
||||
property color outlineColor: color
|
||||
property color outlineHoverColor: hoverColor
|
||||
property color outlineDisabledColor: outlineColor
|
||||
property alias shadowColor: shadow.color
|
||||
property alias shadowEnabled: shadow.visible
|
||||
|
||||
// This property is used to indicate whether the button has a fixed width or the width would depend on the contents
|
||||
// Be careful when using fixedWidthMode, the translated texts can be too long that they won't fit. In any case,
|
||||
// we elide the text to the right so the text will be cut off with the three dots at the end.
|
||||
property var fixedWidthMode: false
|
||||
|
||||
leftPadding: UM.Theme.getSize("default_margin").width
|
||||
rightPadding: UM.Theme.getSize("default_margin").width
|
||||
height: UM.Theme.getSize("action_button").height
|
||||
hoverEnabled: true
|
||||
|
||||
contentItem: Row
|
||||
{
|
||||
//Left side icon. Only displayed if !isIconOnRightSide.
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: buttonIconLeft
|
||||
source: ""
|
||||
height: buttonText.height
|
||||
width: visible ? height : 0
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
color: button.hovered ? button.textHoverColor : button.textColor
|
||||
visible: source != "" && !button.isIconOnRightSide
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: buttonText
|
||||
text: button.text
|
||||
color: button.enabled ? (button.hovered ? button.textHoverColor : button.textColor): button.textDisabledColor
|
||||
font: UM.Theme.getFont("action_button")
|
||||
visible: text != ""
|
||||
renderType: Text.NativeRendering
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: fixedWidthMode ? button.width - button.leftPadding - button.rightPadding : undefined
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
//Right side icon. Only displayed if isIconOnRightSide.
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: buttonIconRight
|
||||
source: buttonIconLeft.source
|
||||
height: buttonText.height
|
||||
width: visible ? height : 0
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
color: buttonIconLeft.color
|
||||
visible: source != "" && button.isIconOnRightSide
|
||||
anchors.verticalCenter: buttonIconLeft.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
background: Cura.RoundedRectangle
|
||||
{
|
||||
id: backgroundRect
|
||||
cornerSide: Cura.RoundedRectangle.Direction.All
|
||||
color: button.enabled ? (button.hovered ? button.hoverColor : button.color) : button.disabledColor
|
||||
radius: UM.Theme.getSize("action_button_radius").width
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: button.enabled ? (button.hovered ? button.outlineHoverColor : button.outlineColor) : button.outlineDisabledColor
|
||||
}
|
||||
|
||||
DropShadow
|
||||
{
|
||||
id: shadow
|
||||
// Don't blur the shadow
|
||||
radius: 0
|
||||
anchors.fill: backgroundRect
|
||||
source: backgroundRect
|
||||
verticalOffset: 2
|
||||
visible: false
|
||||
// Should always be drawn behind the background.
|
||||
z: backgroundRect.z - 1
|
||||
}
|
||||
|
||||
ToolTip
|
||||
{
|
||||
id: tooltip
|
||||
text: ""
|
||||
delay: 500
|
||||
visible: text != "" && button.hovered
|
||||
}
|
||||
}
|
55
resources/qml/ActionPanel/ActionPanelWidget.qml
Normal file
55
resources/qml/ActionPanel/ActionPanelWidget.qml
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
// This element hold all the elements needed for the user to trigger the slicing process, and later
|
||||
// to get information about the printing times, material consumption and the output process (such as
|
||||
// saving to a file, printing over network, ...
|
||||
Rectangle
|
||||
{
|
||||
id: actionPanelWidget
|
||||
|
||||
width: UM.Theme.getSize("action_panel_widget").width
|
||||
height: childrenRect.height + 2 * UM.Theme.getSize("thick_margin").height
|
||||
|
||||
color: UM.Theme.getColor("main_background")
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
radius: UM.Theme.getSize("default_radius").width
|
||||
|
||||
property bool outputAvailable: UM.Backend.state == UM.Backend.Done || UM.Backend.state == UM.Backend.Disabled
|
||||
|
||||
Loader
|
||||
{
|
||||
id: loader
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
topMargin: UM.Theme.getSize("thick_margin").height
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("thick_margin").width
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("thick_margin").width
|
||||
}
|
||||
sourceComponent: outputAvailable ? outputProcessWidget : sliceProcessWidget
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: sliceProcessWidget
|
||||
SliceProcessWidget { }
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: outputProcessWidget
|
||||
OutputProcessWidget { }
|
||||
}
|
||||
}
|
107
resources/qml/ActionPanel/OutputDevicesActionButton.qml
Normal file
107
resources/qml/ActionPanel/OutputDevicesActionButton.qml
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import UM 1.1 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
id: widget
|
||||
|
||||
Cura.PrimaryButton
|
||||
{
|
||||
id: saveToButton
|
||||
height: parent.height
|
||||
fixedWidthMode: true
|
||||
cornerSide: deviceSelectionMenu.visible ? Cura.RoundedRectangle.Direction.Left : Cura.RoundedRectangle.Direction.All
|
||||
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: deviceSelectionMenu.visible ? deviceSelectionMenu.left : parent.right
|
||||
}
|
||||
|
||||
tooltip: UM.OutputDeviceManager.activeDeviceDescription
|
||||
|
||||
text: UM.OutputDeviceManager.activeDeviceShortDescription
|
||||
|
||||
onClicked:
|
||||
{
|
||||
forceActiveFocus();
|
||||
UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName,
|
||||
{ "filter_by_machine": true, "preferred_mimetypes": Cura.MachineManager.activeMachine.preferred_output_file_formats });
|
||||
}
|
||||
}
|
||||
|
||||
Cura.ActionButton
|
||||
{
|
||||
id: deviceSelectionMenu
|
||||
height: parent.height
|
||||
|
||||
shadowEnabled: true
|
||||
shadowColor: UM.Theme.getColor("primary_shadow")
|
||||
cornerSide: Cura.RoundedRectangle.Direction.Right
|
||||
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
leftPadding: UM.Theme.getSize("narrow_margin").width //Need more space than usual here for wide text.
|
||||
rightPadding: UM.Theme.getSize("narrow_margin").width
|
||||
tooltip: popup.opened ? "" : catalog.i18nc("@info:tooltip", "Select the active output device")
|
||||
iconSource: popup.opened ? UM.Theme.getIcon("arrow_top") : UM.Theme.getIcon("arrow_bottom")
|
||||
color: UM.Theme.getColor("action_panel_secondary")
|
||||
visible: (devicesModel.deviceCount > 1)
|
||||
|
||||
onClicked: popup.opened ? popup.close() : popup.open()
|
||||
|
||||
Popup
|
||||
{
|
||||
id: popup
|
||||
padding: 0
|
||||
|
||||
y: -height
|
||||
x: parent.width - width
|
||||
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
|
||||
contentItem: ColumnLayout
|
||||
{
|
||||
Repeater
|
||||
{
|
||||
model: devicesModel
|
||||
|
||||
delegate: Cura.ActionButton
|
||||
{
|
||||
text: model.description
|
||||
color: "transparent"
|
||||
cornerRadius: 0
|
||||
hoverColor: UM.Theme.getColor("primary")
|
||||
Layout.fillWidth: true
|
||||
onClicked:
|
||||
{
|
||||
UM.OutputDeviceManager.setActiveDevice(model.id)
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle
|
||||
{
|
||||
opacity: visible ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
color: UM.Theme.getColor("action_panel_secondary")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.OutputDevicesModel { id: devicesModel }
|
||||
}
|
142
resources/qml/ActionPanel/OutputProcessWidget.qml
Normal file
142
resources/qml/ActionPanel/OutputProcessWidget.qml
Normal file
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import UM 1.1 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
// This element contains all the elements the user needs to visualize the data
|
||||
// that is gather after the slicing process, such as printint time, material usage, ...
|
||||
// There are also two buttons: one to previsualize the output layers, and the other to
|
||||
// select what to do with it (such as print over network, save to file, ...)
|
||||
Column
|
||||
{
|
||||
id: widget
|
||||
|
||||
spacing: UM.Theme.getSize("thin_margin").height
|
||||
property bool preSlicedData: PrintInformation.preSliced
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: information
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
Column
|
||||
{
|
||||
id: timeAndCostsInformation
|
||||
spacing: UM.Theme.getSize("thin_margin").height
|
||||
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: printInformationPanel.left
|
||||
rightMargin: UM.Theme.getSize("thin_margin").height
|
||||
}
|
||||
|
||||
Cura.IconWithText
|
||||
{
|
||||
id: estimatedTime
|
||||
width: parent.width
|
||||
|
||||
text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long)
|
||||
source: UM.Theme.getIcon("clock")
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
}
|
||||
|
||||
Cura.IconWithText
|
||||
{
|
||||
id: estimatedCosts
|
||||
width: parent.width
|
||||
|
||||
property var printMaterialLengths: PrintInformation.materialLengths
|
||||
property var printMaterialWeights: PrintInformation.materialWeights
|
||||
|
||||
text:
|
||||
{
|
||||
if (preSlicedData)
|
||||
{
|
||||
return catalog.i18nc("@label", "No cost estimation available")
|
||||
}
|
||||
var totalLengths = 0
|
||||
var totalWeights = 0
|
||||
if (printMaterialLengths)
|
||||
{
|
||||
for(var index = 0; index < printMaterialLengths.length; index++)
|
||||
{
|
||||
if(printMaterialLengths[index] > 0)
|
||||
{
|
||||
totalLengths += printMaterialLengths[index]
|
||||
totalWeights += Math.round(printMaterialWeights[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
return totalWeights + "g · " + totalLengths.toFixed(2) + "m"
|
||||
}
|
||||
source: UM.Theme.getIcon("spool")
|
||||
}
|
||||
}
|
||||
|
||||
PrintInformationWidget
|
||||
{
|
||||
id: printInformationPanel
|
||||
visible: !preSlicedData
|
||||
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
verticalCenter: timeAndCostsInformation.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: buttonRow
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
height: UM.Theme.getSize("action_button").height
|
||||
|
||||
Cura.SecondaryButton
|
||||
{
|
||||
id: previewStageShortcut
|
||||
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: outputDevicesButton.left
|
||||
rightMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
|
||||
height: UM.Theme.getSize("action_button").height
|
||||
leftPadding: UM.Theme.getSize("default_margin").width
|
||||
rightPadding: UM.Theme.getSize("default_margin").width
|
||||
text: catalog.i18nc("@button", "Preview")
|
||||
|
||||
onClicked: UM.Controller.setActiveStage("PreviewStage")
|
||||
visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage"
|
||||
|
||||
shadowEnabled: true
|
||||
shadowColor: UM.Theme.getColor("action_button_disabled_shadow")
|
||||
}
|
||||
|
||||
Cura.OutputDevicesActionButton
|
||||
{
|
||||
id: outputDevicesButton
|
||||
|
||||
anchors.right: parent.right
|
||||
width: previewStageShortcut.visible ? UM.Theme.getSize("action_button").width : parent.width
|
||||
height: UM.Theme.getSize("action_button").height
|
||||
}
|
||||
}
|
||||
}
|
58
resources/qml/ActionPanel/PrintInformationWidget.qml
Normal file
58
resources/qml/ActionPanel/PrintInformationWidget.qml
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: widget
|
||||
|
||||
source: UM.Theme.getIcon("info")
|
||||
width: UM.Theme.getSize("section_icon").width
|
||||
height: UM.Theme.getSize("section_icon").height
|
||||
|
||||
color: popup.opened ? UM.Theme.getColor("primary") : UM.Theme.getColor("text_medium")
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: popup.open()
|
||||
onExited: popup.close()
|
||||
}
|
||||
|
||||
Popup
|
||||
{
|
||||
id: popup
|
||||
|
||||
y: -(height + UM.Theme.getSize("default_arrow").height + UM.Theme.getSize("thin_margin").height)
|
||||
x: parent.width - width + UM.Theme.getSize("thin_margin").width
|
||||
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
|
||||
opacity: opened ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
|
||||
contentItem: PrintJobInformation
|
||||
{
|
||||
id: printJobInformation
|
||||
width: UM.Theme.getSize("action_panel_information_widget").width
|
||||
}
|
||||
|
||||
background: UM.PointingRectangle
|
||||
{
|
||||
color: UM.Theme.getColor("tool_panel_background")
|
||||
borderColor: UM.Theme.getColor("lining")
|
||||
borderWidth: UM.Theme.getSize("default_lining").width
|
||||
|
||||
target: Qt.point(width - (widget.width / 2) - UM.Theme.getSize("thin_margin").width,
|
||||
height + UM.Theme.getSize("default_arrow").height - UM.Theme.getSize("thin_margin").height)
|
||||
|
||||
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||
}
|
||||
}
|
||||
}
|
159
resources/qml/ActionPanel/PrintJobInformation.qml
Normal file
159
resources/qml/ActionPanel/PrintJobInformation.qml
Normal file
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Column
|
||||
{
|
||||
id: base
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
Column
|
||||
{
|
||||
id: timeSpecification
|
||||
width: parent.width
|
||||
topPadding: UM.Theme.getSize("default_margin").height
|
||||
leftPadding: UM.Theme.getSize("default_margin").width
|
||||
rightPadding: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Time specification").toUpperCase()
|
||||
color: UM.Theme.getColor("primary")
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
property var printDuration: PrintInformation.currentPrintTime
|
||||
|
||||
text:
|
||||
{
|
||||
// All the time information for the different features is achieved
|
||||
var printTime = PrintInformation.getFeaturePrintTimes()
|
||||
var totalSeconds = parseInt(printDuration.getDisplayString(UM.DurationFormat.Seconds))
|
||||
|
||||
// A message is created and displayed when the user hover the time label
|
||||
var text = "<table width=\"100%\">"
|
||||
for(var feature in printTime)
|
||||
{
|
||||
if(!printTime[feature].isTotalDurationZero)
|
||||
{
|
||||
text += "<tr><td>" + feature + ":</td>" +
|
||||
"<td align=\"right\" valign=\"bottom\"> %1</td>".arg(printTime[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) +
|
||||
"<td align=\"right\" valign=\"bottom\"> %1%</td>".arg(Math.round(100 * parseInt(printTime[feature].getDisplayString(UM.DurationFormat.Seconds)) / totalSeconds)) +
|
||||
"</tr>"
|
||||
}
|
||||
}
|
||||
text += "</table>"
|
||||
return text
|
||||
}
|
||||
width: parent.width - 2 * UM.Theme.getSize("default_margin").width
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
|
||||
Column
|
||||
{
|
||||
id: materialSpecification
|
||||
width: parent.width
|
||||
bottomPadding: UM.Theme.getSize("default_margin").height
|
||||
leftPadding: UM.Theme.getSize("default_margin").width
|
||||
rightPadding: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Material specification").toUpperCase()
|
||||
color: UM.Theme.getColor("primary")
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
property var printMaterialLengths: PrintInformation.materialLengths
|
||||
property var printMaterialWeights: PrintInformation.materialWeights
|
||||
property var printMaterialCosts: PrintInformation.materialCosts
|
||||
property var printMaterialNames: PrintInformation.materialNames
|
||||
|
||||
function formatRow(items)
|
||||
{
|
||||
var rowHTML = "<tr>"
|
||||
for(var item = 0; item < items.length; item++)
|
||||
{
|
||||
if (item == 0)
|
||||
{
|
||||
rowHTML += "<td valign=\"bottom\">%1</td>".arg(items[item])
|
||||
}
|
||||
else
|
||||
{
|
||||
rowHTML += "<td align=\"right\" valign=\"bottom\"> %1</td>".arg(items[item])
|
||||
}
|
||||
}
|
||||
rowHTML += "</tr>"
|
||||
return rowHTML
|
||||
}
|
||||
|
||||
text:
|
||||
{
|
||||
var lengths = []
|
||||
var weights = []
|
||||
var costs = []
|
||||
var names = []
|
||||
if(printMaterialLengths)
|
||||
{
|
||||
for(var index = 0; index < printMaterialLengths.length; index++)
|
||||
{
|
||||
if(printMaterialLengths[index] > 0)
|
||||
{
|
||||
names.push(printMaterialNames[index])
|
||||
lengths.push(printMaterialLengths[index].toFixed(2))
|
||||
weights.push(String(Math.round(printMaterialWeights[index])))
|
||||
var cost = printMaterialCosts[index] == undefined ? 0 : printMaterialCosts[index].toFixed(2)
|
||||
costs.push(cost)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(lengths.length == 0)
|
||||
{
|
||||
lengths = ["0.00"]
|
||||
weights = ["0"]
|
||||
costs = ["0.00"]
|
||||
}
|
||||
|
||||
var text = "<table width=\"100%\">"
|
||||
for(var index = 0; index < lengths.length; index++)
|
||||
{
|
||||
text += formatRow([
|
||||
"%1:".arg(names[index]),
|
||||
catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]),
|
||||
catalog.i18nc("@label g for grams", "%1g").arg(weights[index]),
|
||||
"%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]),
|
||||
])
|
||||
}
|
||||
text += "</table>"
|
||||
|
||||
return text
|
||||
}
|
||||
width: parent.width - 2 * UM.Theme.getSize("default_margin").width
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
}
|
157
resources/qml/ActionPanel/SliceProcessWidget.qml
Normal file
157
resources/qml/ActionPanel/SliceProcessWidget.qml
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 1.4 as Controls1
|
||||
|
||||
import UM 1.1 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
|
||||
// This element contains all the elements the user needs to create a printjob from the
|
||||
// model(s) that is(are) on the buildplate. Mainly the button to start/stop the slicing
|
||||
// process and a progress bar to see the progress of the process.
|
||||
Column
|
||||
{
|
||||
id: widget
|
||||
|
||||
spacing: UM.Theme.getSize("thin_margin").height
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
property real progress: UM.Backend.progress
|
||||
property int backendState: UM.Backend.state
|
||||
|
||||
function sliceOrStopSlicing()
|
||||
{
|
||||
if (widget.backendState == UM.Backend.NotStarted)
|
||||
{
|
||||
CuraApplication.backend.forceSlice()
|
||||
}
|
||||
else
|
||||
{
|
||||
CuraApplication.backend.stopSlicing()
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: autoSlicingLabel
|
||||
width: parent.width
|
||||
visible: prepareButtons.autoSlice && (widget.backendState == UM.Backend.Processing || widget.backendState == UM.Backend.NotStarted)
|
||||
|
||||
text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...")
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Cura.IconWithText
|
||||
{
|
||||
id: unableToSliceMessage
|
||||
width: parent.width
|
||||
visible: widget.backendState == UM.Backend.Error
|
||||
|
||||
text: catalog.i18nc("@label:PrintjobStatus", "Unable to Slice")
|
||||
source: UM.Theme.getIcon("warning")
|
||||
color: UM.Theme.getColor("warning")
|
||||
}
|
||||
|
||||
// Progress bar, only visible when the backend is in the process of slice the printjob
|
||||
ProgressBar
|
||||
{
|
||||
id: progressBar
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("progressbar").height
|
||||
value: progress
|
||||
indeterminate: widget.backendState == UM.Backend.NotStarted
|
||||
visible: (widget.backendState == UM.Backend.Processing || (prepareButtons.autoSlice && widget.backendState == UM.Backend.NotStarted))
|
||||
|
||||
background: Rectangle
|
||||
{
|
||||
anchors.fill: parent
|
||||
radius: UM.Theme.getSize("progressbar_radius").width
|
||||
color: UM.Theme.getColor("progressbar_background")
|
||||
}
|
||||
|
||||
contentItem: Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
Rectangle
|
||||
{
|
||||
width: progressBar.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: UM.Theme.getSize("progressbar_radius").width
|
||||
color: UM.Theme.getColor("progressbar_control")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: prepareButtons
|
||||
// Get the current value from the preferences
|
||||
property bool autoSlice: UM.Preferences.getValue("general/auto_slice")
|
||||
// Disable the slice process when
|
||||
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("action_button").height
|
||||
visible: !autoSlice
|
||||
Cura.PrimaryButton
|
||||
{
|
||||
id: sliceButton
|
||||
fixedWidthMode: true
|
||||
anchors.fill: parent
|
||||
text: catalog.i18nc("@button", "Slice")
|
||||
enabled: widget.backendState != UM.Backend.Error
|
||||
visible: widget.backendState == UM.Backend.NotStarted || widget.backendState == UM.Backend.Error
|
||||
onClicked: sliceOrStopSlicing()
|
||||
}
|
||||
|
||||
Cura.SecondaryButton
|
||||
{
|
||||
id: cancelButton
|
||||
fixedWidthMode: true
|
||||
anchors.fill: parent
|
||||
text: catalog.i18nc("@button", "Cancel")
|
||||
enabled: sliceButton.enabled
|
||||
visible: !sliceButton.visible
|
||||
onClicked: sliceOrStopSlicing()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// React when the user changes the preference of having the auto slice enabled
|
||||
Connections
|
||||
{
|
||||
target: UM.Preferences
|
||||
onPreferenceChanged:
|
||||
{
|
||||
var autoSlice = UM.Preferences.getValue("general/auto_slice")
|
||||
prepareButtons.autoSlice = autoSlice
|
||||
if(autoSlice)
|
||||
{
|
||||
CuraApplication.backend.forceSlice()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcut for "slice/stop"
|
||||
Controls1.Action
|
||||
{
|
||||
shortcut: "Ctrl+P"
|
||||
onTriggered:
|
||||
{
|
||||
if (prepareButton.enabled)
|
||||
{
|
||||
sliceOrStopSlicing()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2015 Ultimaker B.V.
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
pragma Singleton
|
||||
|
@ -23,8 +23,6 @@ Item
|
|||
property alias viewLeftSideCamera: viewLeftSideCameraAction;
|
||||
property alias viewRightSideCamera: viewRightSideCameraAction;
|
||||
|
||||
property alias expandSidebar: expandSidebarAction;
|
||||
|
||||
property alias deleteSelection: deleteSelectionAction;
|
||||
property alias centerSelection: centerSelectionAction;
|
||||
property alias multiplySelection: multiplySelectionAction;
|
||||
|
@ -58,7 +56,6 @@ Item
|
|||
|
||||
property alias preferences: preferencesAction;
|
||||
|
||||
property alias showEngineLog: showEngineLogAction;
|
||||
property alias showProfileFolder: showProfileFolderAction;
|
||||
property alias documentation: documentationAction;
|
||||
property alias reportBug: reportBugAction;
|
||||
|
@ -70,7 +67,7 @@ Item
|
|||
|
||||
property alias browsePackages: browsePackagesAction
|
||||
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||
|
||||
Action
|
||||
{
|
||||
|
@ -398,14 +395,6 @@ Item
|
|||
shortcut: StandardKey.New
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: showEngineLogAction;
|
||||
text: catalog.i18nc("@action:inmenu menubar:help","Show Engine &Log...");
|
||||
iconName: "view-list-text";
|
||||
shortcut: StandardKey.WhatsThis;
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: showProfileFolderAction;
|
||||
|
@ -426,11 +415,4 @@ Item
|
|||
text: catalog.i18nc("@action:menu", "&Marketplace")
|
||||
iconName: "plugins_browse"
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: expandSidebarAction;
|
||||
text: catalog.i18nc("@action:inmenu menubar:view","Expand/Collapse Sidebar");
|
||||
shortcut: "Ctrl+E";
|
||||
}
|
||||
}
|
||||
|
|
10
resources/qml/BorderGroup.qml
Normal file
10
resources/qml/BorderGroup.qml
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
QtObject
|
||||
{
|
||||
property real width: 0
|
||||
property color color: "black"
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017 Ultimaker B.V.
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
|
@ -6,53 +6,42 @@ import QtQuick.Controls 1.4
|
|||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
import "Dialogs"
|
||||
import "Menus"
|
||||
import "MainWindow"
|
||||
|
||||
UM.MainWindow
|
||||
{
|
||||
id: base
|
||||
//: Cura application window title
|
||||
title: catalog.i18nc("@title:window","Ultimaker Cura");
|
||||
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
|
||||
property bool showPrintMonitor: false
|
||||
|
||||
// Cura application window title
|
||||
title: catalog.i18nc("@title:window", "Ultimaker Cura")
|
||||
backgroundColor: UM.Theme.getColor("viewport_background")
|
||||
// This connection is here to support legacy printer output devices that use the showPrintMonitor signal on Application to switch to the monitor stage
|
||||
// It should be phased out in newer plugin versions.
|
||||
Connections
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
target: CuraApplication
|
||||
onShowPrintMonitor: {
|
||||
if (show) {
|
||||
UM.Controller.setActiveStage("MonitorStage")
|
||||
} else {
|
||||
UM.Controller.setActiveStage("PrepareStage")
|
||||
}
|
||||
}
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
onWidthChanged:
|
||||
function showTooltip(item, position, text)
|
||||
{
|
||||
// If slidebar is collapsed then it should be invisible
|
||||
// otherwise after the main_window resize the sidebar will be fully re-drawn
|
||||
if (sidebar.collapsed){
|
||||
if (sidebar.visible == true){
|
||||
sidebar.visible = false
|
||||
sidebar.initialWidth = 0
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (sidebar.visible == false){
|
||||
sidebar.visible = true
|
||||
sidebar.initialWidth = UM.Theme.getSize("sidebar").width
|
||||
}
|
||||
}
|
||||
tooltip.text = text;
|
||||
position = item.mapToItem(backgroundItem, position.x - UM.Theme.getSize("default_arrow").width, position.y);
|
||||
tooltip.show(position);
|
||||
}
|
||||
|
||||
function hideTooltip()
|
||||
{
|
||||
tooltip.hide();
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size"))
|
||||
|
@ -72,12 +61,12 @@ UM.MainWindow
|
|||
|
||||
Item
|
||||
{
|
||||
id: backgroundItem;
|
||||
anchors.fill: parent;
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
id: backgroundItem
|
||||
anchors.fill: parent
|
||||
|
||||
signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml
|
||||
function getMeshName(path){
|
||||
function getMeshName(path)
|
||||
{
|
||||
//takes the path the complete path of the meshname and returns only the filebase
|
||||
var fileName = path.slice(path.lastIndexOf("/") + 1)
|
||||
var fileBase = fileName.slice(0, fileName.indexOf("."))
|
||||
|
@ -85,253 +74,86 @@ UM.MainWindow
|
|||
}
|
||||
|
||||
//DeleteSelection on the keypress backspace event
|
||||
Keys.onPressed: {
|
||||
Keys.onPressed:
|
||||
{
|
||||
if (event.key == Qt.Key_Backspace)
|
||||
{
|
||||
Cura.Actions.deleteSelection.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
UM.ApplicationMenu
|
||||
ApplicationMenu
|
||||
{
|
||||
id: menu
|
||||
id: applicationMenu
|
||||
window: base
|
||||
|
||||
Menu
|
||||
{
|
||||
id: fileMenu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&File");
|
||||
MenuItem
|
||||
{
|
||||
id: newProjectMenu
|
||||
action: Cura.Actions.newProject;
|
||||
}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
id: openMenu
|
||||
action: Cura.Actions.open;
|
||||
}
|
||||
|
||||
RecentFilesMenu { }
|
||||
|
||||
MenuItem
|
||||
{
|
||||
id: saveWorkspaceMenu
|
||||
text: catalog.i18nc("@title:menu menubar:file","&Save...")
|
||||
onTriggered:
|
||||
{
|
||||
var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" };
|
||||
if(UM.Preferences.getValue("cura/dialog_on_project_save"))
|
||||
{
|
||||
saveWorkspaceDialog.args = args;
|
||||
saveWorkspaceDialog.open()
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem
|
||||
{
|
||||
id: saveAsMenu
|
||||
text: catalog.i18nc("@title:menu menubar:file", "&Export...")
|
||||
onTriggered:
|
||||
{
|
||||
var localDeviceId = "local_file";
|
||||
UM.OutputDeviceManager.requestWriteToDevice(localDeviceId, PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"});
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
id: exportSelectionMenu
|
||||
text: catalog.i18nc("@action:inmenu menubar:file", "Export Selection...");
|
||||
enabled: UM.Selection.hasSelection;
|
||||
iconName: "document-save-as";
|
||||
onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"});
|
||||
}
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem
|
||||
{
|
||||
id: reloadAllMenu
|
||||
action: Cura.Actions.reloadAll;
|
||||
}
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem { action: Cura.Actions.quit; }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Edit");
|
||||
|
||||
MenuItem { action: Cura.Actions.undo; }
|
||||
MenuItem { action: Cura.Actions.redo; }
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.selectAll; }
|
||||
MenuItem { action: Cura.Actions.arrangeAll; }
|
||||
MenuItem { action: Cura.Actions.deleteSelection; }
|
||||
MenuItem { action: Cura.Actions.deleteAll; }
|
||||
MenuItem { action: Cura.Actions.resetAllTranslation; }
|
||||
MenuItem { action: Cura.Actions.resetAll; }
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.groupObjects;}
|
||||
MenuItem { action: Cura.Actions.mergeObjects;}
|
||||
MenuItem { action: Cura.Actions.unGroupObjects;}
|
||||
}
|
||||
|
||||
ViewMenu { title: catalog.i18nc("@title:menu", "&View") }
|
||||
|
||||
Menu
|
||||
{
|
||||
id: settingsMenu
|
||||
title: catalog.i18nc("@title:menu", "&Settings")
|
||||
|
||||
PrinterMenu { title: catalog.i18nc("@title:menu menubar:settings", "&Printer") }
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: Cura.ExtrudersModel { simpleNames: true }
|
||||
Menu {
|
||||
title: model.name
|
||||
|
||||
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index }
|
||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index }
|
||||
|
||||
MenuSeparator
|
||||
{
|
||||
visible: Cura.MachineManager.hasVariants || Cura.MachineManager.hasMaterials
|
||||
}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: catalog.i18nc("@action:inmenu", "Set as Active Extruder")
|
||||
onTriggered: Cura.MachineManager.setExtruderIndex(model.index)
|
||||
}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: catalog.i18nc("@action:inmenu", "Enable Extruder")
|
||||
onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, true)
|
||||
visible: !Cura.MachineManager.getExtruder(model.index).isEnabled
|
||||
}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: catalog.i18nc("@action:inmenu", "Disable Extruder")
|
||||
onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, false)
|
||||
visible: Cura.MachineManager.getExtruder(model.index).isEnabled
|
||||
enabled: Cura.MachineManager.numberExtrudersEnabled > 1
|
||||
}
|
||||
|
||||
}
|
||||
onObjectAdded: settingsMenu.insertItem(index, object)
|
||||
onObjectRemoved: settingsMenu.removeItem(object)
|
||||
}
|
||||
|
||||
// TODO Only show in dev mode. Remove check when feature ready
|
||||
BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: CuraSDKVersion == "dev" ? Cura.MachineManager.hasVariantBuildplates : false }
|
||||
ProfileMenu { title: catalog.i18nc("@title:settings", "&Profile"); }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem { action: Cura.Actions.configureSettingVisibility }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: extension_menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","E&xtensions");
|
||||
|
||||
Instantiator
|
||||
{
|
||||
id: extensions
|
||||
model: UM.ExtensionModel { }
|
||||
|
||||
Menu
|
||||
{
|
||||
id: sub_menu
|
||||
title: model.name;
|
||||
visible: actions != null
|
||||
enabled: actions != null
|
||||
Instantiator
|
||||
{
|
||||
model: actions
|
||||
MenuItem
|
||||
{
|
||||
text: model.text
|
||||
onTriggered: extensions.model.subMenuTriggered(name, model.text)
|
||||
}
|
||||
onObjectAdded: sub_menu.insertItem(index, object)
|
||||
onObjectRemoved: sub_menu.removeItem(object)
|
||||
}
|
||||
}
|
||||
|
||||
onObjectAdded: extension_menu.insertItem(index, object)
|
||||
onObjectRemoved: extension_menu.removeItem(object)
|
||||
}
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: plugin_menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace")
|
||||
|
||||
MenuItem { action: Cura.Actions.browsePackages }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: preferencesMenu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","P&references");
|
||||
|
||||
MenuItem { action: Cura.Actions.preferences; }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: helpMenu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Help");
|
||||
|
||||
MenuItem { action: Cura.Actions.showProfileFolder; }
|
||||
MenuItem { action: Cura.Actions.documentation; }
|
||||
MenuItem { action: Cura.Actions.reportBug; }
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.about; }
|
||||
}
|
||||
}
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
id: machineExtruderCount
|
||||
|
||||
containerStack: Cura.MachineManager.activeMachine
|
||||
key: "machine_extruder_count"
|
||||
watchedProperties: [ "value" ]
|
||||
storeIndex: 0
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: contentItem;
|
||||
id: headerBackground
|
||||
anchors
|
||||
{
|
||||
top: applicationMenu.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
height: stageMenu.source != "" ? Math.round(mainWindowHeader.height + stageMenu.height / 2) : mainWindowHeader.height
|
||||
|
||||
y: menu.height
|
||||
width: parent.width;
|
||||
height: parent.height - menu.height;
|
||||
LinearGradient
|
||||
{
|
||||
anchors.fill: parent
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(parent.width, 0)
|
||||
gradient: Gradient
|
||||
{
|
||||
GradientStop
|
||||
{
|
||||
position: 0.0
|
||||
color: UM.Theme.getColor("main_window_header_background")
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 0.5
|
||||
color: UM.Theme.getColor("main_window_header_background_gradient")
|
||||
}
|
||||
GradientStop
|
||||
{
|
||||
position: 1.0
|
||||
color: UM.Theme.getColor("main_window_header_background")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.forwardTo: menu
|
||||
MainWindowHeader
|
||||
{
|
||||
id: mainWindowHeader
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: applicationMenu.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: contentItem
|
||||
|
||||
anchors
|
||||
{
|
||||
top: mainWindowHeader.bottom
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
Keys.forwardTo: applicationMenu
|
||||
|
||||
DropArea
|
||||
{
|
||||
anchors.fill: parent;
|
||||
// The drop area is here to handle files being dropped onto Cura.
|
||||
anchors.fill: parent
|
||||
onDropped:
|
||||
{
|
||||
if (drop.urls.length > 0)
|
||||
|
@ -359,156 +181,110 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
JobSpecs
|
||||
{
|
||||
id: jobSpecs
|
||||
anchors
|
||||
{
|
||||
bottom: parent.bottom;
|
||||
right: sidebar.left;
|
||||
bottomMargin: UM.Theme.getSize("default_margin").height;
|
||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
id: openFileButton;
|
||||
text: catalog.i18nc("@action:button","Open File");
|
||||
iconSource: UM.Theme.getIcon("load")
|
||||
style: UM.Theme.styles.tool_button
|
||||
tooltip: ""
|
||||
anchors
|
||||
{
|
||||
top: topbar.bottom;
|
||||
topMargin: UM.Theme.getSize("default_margin").height;
|
||||
left: parent.left;
|
||||
}
|
||||
action: Cura.Actions.open;
|
||||
}
|
||||
|
||||
Toolbar
|
||||
{
|
||||
id: toolbar;
|
||||
// The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by
|
||||
// plugins)
|
||||
id: toolbar
|
||||
|
||||
property int mouseX: base.mouseX
|
||||
property int mouseY: base.mouseY
|
||||
|
||||
anchors {
|
||||
top: openFileButton.bottom;
|
||||
topMargin: UM.Theme.getSize("window_margin").height;
|
||||
left: parent.left;
|
||||
anchors
|
||||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
}
|
||||
visible: CuraApplication.platformActivity && !PrintInformation.preSliced
|
||||
}
|
||||
|
||||
ObjectsList
|
||||
{
|
||||
id: objectsList;
|
||||
visible: UM.Preferences.getValue("cura/use_multi_build_plate");
|
||||
id: objectsList
|
||||
visible: UM.Preferences.getValue("cura/use_multi_build_plate")
|
||||
anchors
|
||||
{
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
bottom: viewOrientationControls.top
|
||||
left: toolbar.right
|
||||
margins: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Topbar
|
||||
JobSpecs
|
||||
{
|
||||
id: jobSpecs
|
||||
visible: CuraApplication.platformActivity
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
bottom: viewOrientationControls.top
|
||||
margins: UM.Theme.getSize("default_margin").width
|
||||
bottomMargin: UM.Theme.getSize("thin_margin").width
|
||||
}
|
||||
}
|
||||
|
||||
ViewOrientationControls
|
||||
{
|
||||
id: viewOrientationControls
|
||||
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
margins: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
}
|
||||
|
||||
Cura.ActionPanelWidget
|
||||
{
|
||||
id: topbar
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
|
||||
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
|
||||
visible: CuraApplication.platformActivity
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
// A stage can control this area. If nothing is set, it will therefore show the 3D view.
|
||||
id: main
|
||||
|
||||
anchors
|
||||
{
|
||||
top: topbar.bottom
|
||||
bottom: parent.bottom
|
||||
// Align to the top of the stageMenu since the stageMenu may not exist
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: sidebar.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
visible: UM.Controller.activeStage.mainComponent != ""
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onWheel: wheel.accepted = true
|
||||
}
|
||||
|
||||
source: UM.Controller.activeStage.mainComponent
|
||||
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : ""
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
id: sidebar
|
||||
|
||||
property bool collapsed: false;
|
||||
property var initialWidth: UM.Theme.getSize("sidebar").width;
|
||||
|
||||
function callExpandOrCollapse() {
|
||||
if (collapsed) {
|
||||
sidebar.visible = true;
|
||||
sidebar.initialWidth = UM.Theme.getSize("sidebar").width;
|
||||
viewportRect = Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0);
|
||||
expandSidebarAnimation.start();
|
||||
} else {
|
||||
viewportRect = Qt.rect(0, 0, 1, 1.0);
|
||||
collapseSidebarAnimation.start();
|
||||
}
|
||||
collapsed = !collapsed;
|
||||
UM.Preferences.setValue("cura/sidebar_collapsed", collapsed);
|
||||
}
|
||||
// The stage menu is, as the name implies, a menu that is defined by the active stage.
|
||||
// Note that this menu does not need to be set at all! It's perfectly acceptable to have a stage
|
||||
// without this menu!
|
||||
id: stageMenu
|
||||
|
||||
anchors
|
||||
{
|
||||
top: topbar.top
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
|
||||
width: initialWidth
|
||||
x: base.width - sidebar.width
|
||||
source: UM.Controller.activeStage.sidebarComponent
|
||||
height: UM.Theme.getSize("stage_menu").height
|
||||
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : ""
|
||||
|
||||
NumberAnimation {
|
||||
id: collapseSidebarAnimation
|
||||
target: sidebar
|
||||
properties: "x"
|
||||
to: base.width
|
||||
duration: 100
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: expandSidebarAnimation
|
||||
target: sidebar
|
||||
properties: "x"
|
||||
to: base.width - sidebar.width
|
||||
duration: 100
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
// The printSetupSelector is defined here so that the setting list doesn't need to get re-instantiated
|
||||
// Every time the stage is changed.
|
||||
property var printSetupSelector: Cura.PrintSetupSelector
|
||||
{
|
||||
var sidebar_collapsed = UM.Preferences.getValue("cura/sidebar_collapsed");
|
||||
|
||||
if (sidebar_collapsed)
|
||||
{
|
||||
sidebar.collapsed = true;
|
||||
viewportRect = Qt.rect(0, 0, 1, 1.0)
|
||||
collapseSidebarAnimation.start();
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
visible: UM.Controller.activeStage.sidebarComponent != ""
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onWheel: wheel.accepted = true
|
||||
width: UM.Theme.getSize("print_setup_widget").width
|
||||
height: UM.Theme.getSize("stage_menu").height
|
||||
headerCornerSide: RoundedRectangle.Direction.Right
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,20 +293,17 @@ UM.MainWindow
|
|||
anchors
|
||||
{
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
horizontalCenterOffset: -(Math.round(UM.Theme.getSize("sidebar").width / 2))
|
||||
top: parent.verticalCenter;
|
||||
bottom: parent.bottom;
|
||||
top: parent.verticalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expand or collapse sidebar
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.expandSidebar
|
||||
onTriggered: sidebar.callExpandOrCollapse()
|
||||
PrintSetupTooltip
|
||||
{
|
||||
id: tooltip
|
||||
}
|
||||
}
|
||||
|
||||
UM.PreferencesDialog
|
||||
|
@ -567,13 +340,6 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
WorkspaceSummaryDialog
|
||||
{
|
||||
id: saveWorkspaceDialog
|
||||
property var args
|
||||
onYes: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args)
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.preferences
|
||||
|
@ -586,33 +352,6 @@ UM.MainWindow
|
|||
onShowPreferencesWindow: preferences.visible = true
|
||||
}
|
||||
|
||||
MessageDialog
|
||||
{
|
||||
id: newProjectDialog
|
||||
modality: Qt.ApplicationModal
|
||||
title: catalog.i18nc("@title:window", "New project")
|
||||
text: catalog.i18nc("@info:question", "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings.")
|
||||
standardButtons: StandardButton.Yes | StandardButton.No
|
||||
icon: StandardIcon.Question
|
||||
onYes:
|
||||
{
|
||||
CuraApplication.deleteAll();
|
||||
Cura.Actions.resetProfile.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.newProject
|
||||
onTriggered:
|
||||
{
|
||||
if(Printer.platformActivity || Cura.MachineManager.hasUserSettings)
|
||||
{
|
||||
newProjectDialog.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.addProfile
|
||||
|
@ -670,19 +409,6 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
UM.ExtensionModel {
|
||||
id: curaExtensions
|
||||
}
|
||||
|
||||
// show the plugin browser dialog
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.browsePackages
|
||||
onTriggered: {
|
||||
curaExtensions.callExtensionMethod("Toolbox", "browsePackages")
|
||||
}
|
||||
}
|
||||
|
||||
Timer
|
||||
{
|
||||
id: createProfileTimer
|
||||
|
@ -703,7 +429,8 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
ContextMenu {
|
||||
ContextMenu
|
||||
{
|
||||
id: contextMenu
|
||||
}
|
||||
|
||||
|
@ -870,7 +597,8 @@ UM.MainWindow
|
|||
modality: Qt.ApplicationModal
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
MessageDialog
|
||||
{
|
||||
id: infoMultipleFilesWithGcodeDialog
|
||||
title: catalog.i18nc("@title:window", "Open File(s)")
|
||||
icon: StandardIcon.Information
|
||||
|
@ -914,11 +642,6 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
EngineLog
|
||||
{
|
||||
id: engineLog;
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.showProfileFolder
|
||||
|
|
168
resources/qml/Dialogs/AboutDialog.qml
Normal file
168
resources/qml/Dialogs/AboutDialog.qml
Normal file
|
@ -0,0 +1,168 @@
|
|||
// 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.Window 2.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
|
||||
UM.Dialog
|
||||
{
|
||||
id: base
|
||||
|
||||
//: About dialog title
|
||||
title: catalog.i18nc("@title:window","About Cura")
|
||||
|
||||
minimumWidth: 500 * screenScaleFactor
|
||||
minimumHeight: 650 * screenScaleFactor
|
||||
width: minimumWidth
|
||||
height: minimumHeight
|
||||
|
||||
Rectangle
|
||||
{
|
||||
width: parent.width + 2 * margin // margin from Dialog.qml
|
||||
height: version.y + version.height + margin
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: - margin
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
color: UM.Theme.getColor("viewport_background")
|
||||
}
|
||||
|
||||
Image
|
||||
{
|
||||
id: logo
|
||||
width: (base.minimumWidth * 0.85) | 0
|
||||
height: (width * (UM.Theme.getSize("logo").height / UM.Theme.getSize("logo").width)) | 0
|
||||
|
||||
source: UM.Theme.getImage("logo_about")
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: ((base.minimumWidth - width) / 2) | 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: version
|
||||
|
||||
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
|
||||
font: UM.Theme.getFont("large")
|
||||
color: UM.Theme.getColor("text")
|
||||
anchors.right : logo.right
|
||||
anchors.top: logo.bottom
|
||||
anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: description
|
||||
width: parent.width
|
||||
|
||||
//: About dialog application description
|
||||
text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
|
||||
font: UM.Theme.getFont("system")
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: version.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: creditsNotes
|
||||
width: parent.width
|
||||
|
||||
//: About dialog application author note
|
||||
text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:")
|
||||
font: UM.Theme.getFont("system")
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: description.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
id: credits
|
||||
anchors.top: creditsNotes.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
|
||||
width: parent.width
|
||||
height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
|
||||
|
||||
ListView
|
||||
{
|
||||
id: projectsList
|
||||
|
||||
width: parent.width
|
||||
|
||||
delegate: Row
|
||||
{
|
||||
Label
|
||||
{
|
||||
text: "<a href='%1' title='%2'>%2</a>".arg(model.url).arg(model.name)
|
||||
width: (projectsList.width * 0.25) | 0
|
||||
elide: Text.ElideRight
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: model.description
|
||||
elide: Text.ElideRight
|
||||
width: (projectsList.width * 0.6) | 0
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: model.license
|
||||
elide: Text.ElideRight
|
||||
width: (projectsList.width * 0.15) | 0
|
||||
}
|
||||
}
|
||||
model: ListModel
|
||||
{
|
||||
id: projectsModel
|
||||
}
|
||||
Component.onCompleted:
|
||||
{
|
||||
projectsModel.append({ name: "Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
|
||||
projectsModel.append({ name: "Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
|
||||
projectsModel.append({ name: "CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
|
||||
projectsModel.append({ name: "libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
|
||||
|
||||
projectsModel.append({ name: "Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" });
|
||||
projectsModel.append({ name: "Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
|
||||
projectsModel.append({ name: "PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
|
||||
projectsModel.append({ name: "SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
|
||||
projectsModel.append({ name: "Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
|
||||
projectsModel.append({ name: "SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
|
||||
projectsModel.append({ name: "NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
|
||||
projectsModel.append({ name: "NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
|
||||
projectsModel.append({ name: "Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" });
|
||||
projectsModel.append({ name: "Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
|
||||
projectsModel.append({ name: "NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" });
|
||||
projectsModel.append({ name: "libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
|
||||
projectsModel.append({ name: "libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
|
||||
projectsModel.append({ name: "PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
|
||||
projectsModel.append({ name: "python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
|
||||
projectsModel.append({ name: "Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
|
||||
projectsModel.append({ name: "Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" });
|
||||
|
||||
projectsModel.append({ name: "Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
|
||||
projectsModel.append({ name: "Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" });
|
||||
projectsModel.append({ name: "AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightButtons: Button
|
||||
{
|
||||
//: Close about dialog button
|
||||
id: closeButton
|
||||
text: catalog.i18nc("@action:button","Close");
|
||||
|
||||
onClicked: base.visible = false;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017 Ultimaker B.V.
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
|
@ -156,7 +156,6 @@ UM.Dialog
|
|||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||
width: UM.Theme.getSize("standard_arrow").width
|
||||
height: UM.Theme.getSize("standard_arrow").height
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: palette.windowText
|
||||
source: base.activeCategory == section ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_right")
|
||||
|
@ -170,7 +169,7 @@ UM.Dialog
|
|||
if (machineList.model.getItem(machineList.currentIndex).section != section)
|
||||
{
|
||||
// Find the first machine from this section
|
||||
for(var i = 0; i < machineList.model.rowCount(); i++)
|
||||
for(var i = 0; i < machineList.model.count; i++)
|
||||
{
|
||||
var item = machineList.model.getItem(i);
|
||||
if (item.section == section)
|
||||
|
@ -276,7 +275,6 @@ UM.Dialog
|
|||
id: machineName
|
||||
text: getMachineName()
|
||||
width: Math.floor(parent.width * 0.75)
|
||||
implicitWidth: UM.Theme.getSize("standard_list_input").width
|
||||
maximumLength: 40
|
||||
//validator: Cura.MachineNameValidator { } //TODO: Gives a segfault in PyQt5.6. For now, we must use a signal on text changed.
|
||||
validator: RegExpValidator
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright (c) 2015 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.Layouts 1.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
|
||||
UM.Dialog
|
||||
{
|
||||
id: dialog;
|
||||
|
||||
//: Engine Log dialog title
|
||||
title: catalog.i18nc("@title:window","Engine Log");
|
||||
|
||||
modality: Qt.NonModal;
|
||||
|
||||
TextArea
|
||||
{
|
||||
id: textArea
|
||||
anchors.fill: parent;
|
||||
|
||||
Timer
|
||||
{
|
||||
id: updateTimer;
|
||||
interval: 1000;
|
||||
running: false;
|
||||
repeat: true;
|
||||
onTriggered: textArea.text = CuraApplication.getEngineLog();
|
||||
}
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
}
|
||||
|
||||
rightButtons: Button
|
||||
{
|
||||
//: Close engine log button
|
||||
text: catalog.i18nc("@action:button","Close");
|
||||
onClicked: dialog.visible = false;
|
||||
}
|
||||
|
||||
onVisibleChanged:
|
||||
{
|
||||
if(visible)
|
||||
{
|
||||
textArea.text = CuraApplication.getEngineLog();
|
||||
updateTimer.start();
|
||||
} else
|
||||
{
|
||||
updateTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
262
resources/qml/ExpandableComponent.qml
Normal file
262
resources/qml/ExpandableComponent.qml
Normal file
|
@ -0,0 +1,262 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||
|
||||
// The expandable component has 2 major sub components:
|
||||
// * The headerItem; Always visible and should hold some info about what happens if the component is expanded
|
||||
// * The contentItem; The content that needs to be shown if the component is expanded.
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
// Enumeration with the different possible alignments of the content with respect of the headerItem
|
||||
enum ContentAlignment
|
||||
{
|
||||
AlignLeft,
|
||||
AlignRight
|
||||
}
|
||||
|
||||
// The headerItem holds the QML item that is always displayed.
|
||||
property alias headerItem: headerItemLoader.sourceComponent
|
||||
|
||||
// The contentItem holds the QML item that is shown when the "open" button is pressed
|
||||
property alias contentItem: content.contentItem
|
||||
|
||||
property color contentBackgroundColor: UM.Theme.getColor("action_button")
|
||||
|
||||
property color headerBackgroundColor: UM.Theme.getColor("action_button")
|
||||
property color headerActiveColor: UM.Theme.getColor("secondary")
|
||||
property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
|
||||
|
||||
property alias enabled: mouseArea.enabled
|
||||
|
||||
// Text to show when this component is disabled
|
||||
property alias disabledText: disabledLabel.text
|
||||
|
||||
// Defines the alignment of the content with respect of the headerItem, by default to the right
|
||||
property int contentAlignment: ExpandableComponent.ContentAlignment.AlignRight
|
||||
|
||||
// How much spacing is needed around the contentItem
|
||||
property alias contentPadding: content.padding
|
||||
|
||||
// Adds a title to the content item
|
||||
property alias contentHeaderTitle: contentHeader.headerTitle
|
||||
|
||||
// How much spacing is needed for the contentItem by Y coordinate
|
||||
property var contentSpacingY: UM.Theme.getSize("narrow_margin").width
|
||||
|
||||
// How much padding is needed around the header & button
|
||||
property alias headerPadding: background.padding
|
||||
|
||||
// What icon should be displayed on the right.
|
||||
property alias iconSource: collapseButton.source
|
||||
|
||||
property alias iconColor: collapseButton.color
|
||||
|
||||
// The icon size (it's always drawn as a square)
|
||||
property alias iconSize: collapseButton.height
|
||||
|
||||
// Is the "drawer" open?
|
||||
readonly property alias expanded: contentContainer.visible
|
||||
|
||||
// What should the radius of the header be. This is also influenced by the headerCornerSide
|
||||
property alias headerRadius: background.radius
|
||||
|
||||
// On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right.
|
||||
property alias headerCornerSide: background.cornerSide
|
||||
|
||||
property alias headerShadowColor: shadow.color
|
||||
|
||||
property alias enableHeaderShadow: shadow.visible
|
||||
|
||||
property int shadowOffset: 2
|
||||
|
||||
function toggleContent()
|
||||
{
|
||||
contentContainer.visible = !expanded
|
||||
}
|
||||
|
||||
// Add this binding since the background color is not updated otherwise
|
||||
Binding
|
||||
{
|
||||
target: background
|
||||
property: "color"
|
||||
value:
|
||||
{
|
||||
return base.enabled ? (expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
|
||||
}
|
||||
}
|
||||
|
||||
// The panel needs to close when it becomes disabled
|
||||
Connections
|
||||
{
|
||||
target: base
|
||||
onEnabledChanged:
|
||||
{
|
||||
if (!base.enabled && expanded)
|
||||
{
|
||||
toggleContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: 100 * screenScaleFactor
|
||||
implicitWidth: 400 * screenScaleFactor
|
||||
|
||||
RoundedRectangle
|
||||
{
|
||||
id: background
|
||||
property real padding: UM.Theme.getSize("default_margin").width
|
||||
|
||||
color: base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
|
||||
anchors.fill: parent
|
||||
|
||||
Label
|
||||
{
|
||||
id: disabledLabel
|
||||
visible: !base.enabled
|
||||
anchors.fill: parent
|
||||
leftPadding: background.padding
|
||||
rightPadding: background.padding
|
||||
text: ""
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: UM.Theme.getColor("text")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
visible: base.enabled
|
||||
|
||||
Loader
|
||||
{
|
||||
id: headerItemLoader
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: collapseButton.visible ? collapseButton.left : parent.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
margins: background.padding
|
||||
}
|
||||
}
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: collapseButton
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
margins: background.padding
|
||||
}
|
||||
source: UM.Theme.getIcon("pencil")
|
||||
visible: source != ""
|
||||
width: UM.Theme.getSize("standard_arrow").width
|
||||
height: UM.Theme.getSize("standard_arrow").height
|
||||
color: UM.Theme.getColor("small_button_text")
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: toggleContent()
|
||||
hoverEnabled: true
|
||||
onEntered: background.color = headerHoverColor
|
||||
onExited: background.color = base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
|
||||
}
|
||||
}
|
||||
|
||||
DropShadow
|
||||
{
|
||||
id: shadow
|
||||
// Don't blur the shadow
|
||||
radius: 0
|
||||
anchors.fill: background
|
||||
source: background
|
||||
verticalOffset: base.shadowOffset
|
||||
visible: true
|
||||
color: UM.Theme.getColor("action_button_shadow")
|
||||
// Should always be drawn behind the background.
|
||||
z: background.z - 1
|
||||
}
|
||||
|
||||
Cura.RoundedRectangle
|
||||
{
|
||||
id: contentContainer
|
||||
|
||||
visible: false
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
|
||||
// Ensure that the content is located directly below the headerItem
|
||||
y: background.height + base.shadowOffset + base.contentSpacingY
|
||||
|
||||
// Make the content aligned with the rest, using the property contentAlignment to decide whether is right or left.
|
||||
// In case of right alignment, the 3x padding is due to left, right and padding between the button & text.
|
||||
x: contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
|
||||
|
||||
cornerSide: Cura.RoundedRectangle.Direction.All
|
||||
color: contentBackgroundColor
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
radius: UM.Theme.getSize("default_radius").width
|
||||
|
||||
ExpandableComponentHeader
|
||||
{
|
||||
id: contentHeader
|
||||
headerTitle: ""
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Control
|
||||
{
|
||||
id: content
|
||||
|
||||
anchors.top: contentHeader.bottom
|
||||
padding: UM.Theme.getSize("default_margin").width
|
||||
|
||||
contentItem: Item {}
|
||||
|
||||
onContentItemChanged:
|
||||
{
|
||||
// Since we want the size of the content to be set by the size of the content,
|
||||
// we need to do it like this.
|
||||
content.width = contentItem.width + 2 * content.padding
|
||||
content.height = contentItem.height + 2 * content.padding
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.
|
||||
// Apparently the order in which these are handled matters and so the height is correctly updated if this is here.
|
||||
Connections
|
||||
{
|
||||
// Since it could be that the content is dynamically populated, we should also take these changes into account.
|
||||
target: content.contentItem
|
||||
onWidthChanged: content.width = content.contentItem.width + 2 * content.padding
|
||||
onHeightChanged:
|
||||
{
|
||||
content.height = content.contentItem.height + 2 * content.padding
|
||||
contentContainer.height = contentHeader.height + content.height
|
||||
}
|
||||
}
|
||||
}
|
68
resources/qml/ExpandableComponentHeader.qml
Normal file
68
resources/qml/ExpandableComponentHeader.qml
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
// Header of the popup
|
||||
Cura.RoundedRectangle
|
||||
{
|
||||
id: header
|
||||
|
||||
property alias headerTitle: headerLabel.text
|
||||
|
||||
height: UM.Theme.getSize("expandable_component_content_header").height
|
||||
color: UM.Theme.getColor("secondary")
|
||||
cornerSide: Cura.RoundedRectangle.Direction.Up
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
radius: UM.Theme.getSize("default_radius").width
|
||||
|
||||
Label
|
||||
{
|
||||
id: headerLabel
|
||||
text: ""
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: UM.Theme.getColor("small_button_text")
|
||||
height: parent.height
|
||||
|
||||
anchors
|
||||
{
|
||||
topMargin: UM.Theme.getSize("default_margin").height
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
id: closeButton
|
||||
width: UM.Theme.getSize("message_close").width
|
||||
height: UM.Theme.getSize("message_close").height
|
||||
hoverEnabled: true
|
||||
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("default_margin").width
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
contentItem: UM.RecolorImage
|
||||
{
|
||||
anchors.fill: parent
|
||||
sourceSize.width: width
|
||||
color: closeButton.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text")
|
||||
source: UM.Theme.getIcon("cross1")
|
||||
}
|
||||
|
||||
background: Item {}
|
||||
|
||||
onClicked: toggleContent() // Will hide the popup item
|
||||
}
|
||||
}
|
250
resources/qml/ExpandablePopup.qml
Normal file
250
resources/qml/ExpandablePopup.qml
Normal file
|
@ -0,0 +1,250 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||
|
||||
// The expandable component has 2 major sub components:
|
||||
// * The headerItem; Always visible and should hold some info about what happens if the component is expanded
|
||||
// * The contentItem; The content that needs to be shown if the component is expanded.
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
// Enumeration with the different possible alignments of the content with respect of the headerItem
|
||||
enum ContentAlignment
|
||||
{
|
||||
AlignLeft,
|
||||
AlignRight
|
||||
}
|
||||
|
||||
// The headerItem holds the QML item that is always displayed.
|
||||
property alias headerItem: headerItemLoader.sourceComponent
|
||||
|
||||
// The contentItem holds the QML item that is shown when the "open" button is pressed
|
||||
property alias contentItem: content.contentItem
|
||||
|
||||
property color contentBackgroundColor: UM.Theme.getColor("action_button")
|
||||
|
||||
property color headerBackgroundColor: UM.Theme.getColor("action_button")
|
||||
property color headerActiveColor: UM.Theme.getColor("secondary")
|
||||
property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
|
||||
|
||||
property alias enabled: mouseArea.enabled
|
||||
|
||||
// Text to show when this component is disabled
|
||||
property alias disabledText: disabledLabel.text
|
||||
|
||||
// Defines the alignment of the content with respect of the headerItem, by default to the right
|
||||
property int contentAlignment: ExpandablePopup.ContentAlignment.AlignRight
|
||||
|
||||
// How much spacing is needed around the contentItem
|
||||
property alias contentPadding: content.padding
|
||||
|
||||
// How much padding is needed around the header & button
|
||||
property alias headerPadding: background.padding
|
||||
|
||||
// What icon should be displayed on the right.
|
||||
property alias iconSource: collapseButton.source
|
||||
|
||||
property alias iconColor: collapseButton.color
|
||||
|
||||
// The icon size (it's always drawn as a square)
|
||||
property alias iconSize: collapseButton.height
|
||||
|
||||
// Is the "drawer" open?
|
||||
readonly property alias expanded: content.visible
|
||||
|
||||
property alias expandedHighlightColor: expandedHighlight.color
|
||||
|
||||
// What should the radius of the header be. This is also influenced by the headerCornerSide
|
||||
property alias headerRadius: background.radius
|
||||
|
||||
// On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right.
|
||||
property alias headerCornerSide: background.cornerSide
|
||||
|
||||
// Change the contentItem close behaviour
|
||||
property alias contentClosePolicy : content.closePolicy
|
||||
|
||||
property alias headerShadowColor: shadow.color
|
||||
|
||||
property alias enableHeaderShadow: shadow.visible
|
||||
|
||||
property int shadowOffset: 2
|
||||
|
||||
function toggleContent()
|
||||
{
|
||||
if (content.visible)
|
||||
{
|
||||
content.close()
|
||||
}
|
||||
else
|
||||
{
|
||||
content.open()
|
||||
}
|
||||
}
|
||||
|
||||
// Add this binding since the background color is not updated otherwise
|
||||
Binding
|
||||
{
|
||||
target: background
|
||||
property: "color"
|
||||
value: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
|
||||
}
|
||||
|
||||
// The panel needs to close when it becomes disabled
|
||||
Connections
|
||||
{
|
||||
target: base
|
||||
onEnabledChanged:
|
||||
{
|
||||
if (!base.enabled && expanded)
|
||||
{
|
||||
toggleContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: 100 * screenScaleFactor
|
||||
implicitWidth: 400 * screenScaleFactor
|
||||
|
||||
RoundedRectangle
|
||||
{
|
||||
id: background
|
||||
property real padding: UM.Theme.getSize("default_margin").width
|
||||
|
||||
color: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
|
||||
anchors.fill: parent
|
||||
|
||||
Label
|
||||
{
|
||||
id: disabledLabel
|
||||
visible: !base.enabled
|
||||
leftPadding: background.padding
|
||||
text: ""
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: UM.Theme.getColor("text")
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
visible: base.enabled
|
||||
|
||||
Loader
|
||||
{
|
||||
id: headerItemLoader
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: collapseButton.visible ? collapseButton.left : parent.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
margins: background.padding
|
||||
}
|
||||
}
|
||||
|
||||
// A highlight that is shown when the content is expanded
|
||||
Rectangle
|
||||
{
|
||||
id: expandedHighlight
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("thick_lining").height
|
||||
color: UM.Theme.getColor("primary")
|
||||
visible: expanded
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: collapseButton
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
margins: background.padding
|
||||
}
|
||||
source: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")
|
||||
visible: source != ""
|
||||
width: UM.Theme.getSize("standard_arrow").width
|
||||
height: UM.Theme.getSize("standard_arrow").height
|
||||
color: UM.Theme.getColor("small_button_text")
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: toggleContent()
|
||||
hoverEnabled: true
|
||||
onEntered: background.color = headerHoverColor
|
||||
onExited: background.color = base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
|
||||
}
|
||||
}
|
||||
|
||||
DropShadow
|
||||
{
|
||||
id: shadow
|
||||
// Don't blur the shadow
|
||||
radius: 0
|
||||
anchors.fill: background
|
||||
source: background
|
||||
verticalOffset: base.shadowOffset
|
||||
visible: true
|
||||
color: UM.Theme.getColor("action_button_shadow")
|
||||
// Should always be drawn behind the background.
|
||||
z: background.z - 1
|
||||
}
|
||||
|
||||
Popup
|
||||
{
|
||||
id: content
|
||||
|
||||
// Ensure that the content is located directly below the headerItem
|
||||
y: background.height + base.shadowOffset
|
||||
|
||||
// Make the content aligned with the rest, using the property contentAlignment to decide whether is right or left.
|
||||
// In case of right alignment, the 3x padding is due to left, right and padding between the button & text.
|
||||
x: contentAlignment == ExpandablePopup.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
|
||||
padding: UM.Theme.getSize("default_margin").width
|
||||
closePolicy: Popup.CloseOnPressOutsideParent
|
||||
|
||||
background: Cura.RoundedRectangle
|
||||
{
|
||||
cornerSide: Cura.RoundedRectangle.Direction.Down
|
||||
color: contentBackgroundColor
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
radius: UM.Theme.getSize("default_radius").width
|
||||
}
|
||||
|
||||
contentItem: Item {}
|
||||
|
||||
onContentItemChanged:
|
||||
{
|
||||
// Since we want the size of the content to be set by the size of the content,
|
||||
// we need to do it like this.
|
||||
content.width = contentItem.width + 2 * content.padding
|
||||
content.height = contentItem.height + 2 * content.padding
|
||||
}
|
||||
}
|
||||
|
||||
// DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.
|
||||
// Apparently the order in which these are handled matters and so the height is correctly updated if this is here.
|
||||
Connections
|
||||
{
|
||||
// Since it could be that the content is dynamically populated, we should also take these changes into account.
|
||||
target: content.contentItem
|
||||
onWidthChanged: content.width = content.contentItem.width + 2 * content.padding
|
||||
onHeightChanged: content.height = content.contentItem.height + 2 * content.padding
|
||||
}
|
||||
}
|
|
@ -2,80 +2,32 @@
|
|||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Button
|
||||
Cura.ToolbarButton
|
||||
{
|
||||
id: base
|
||||
|
||||
property var extruder;
|
||||
property var extruder
|
||||
|
||||
text: catalog.i18ncp("@label %1 is filled in with the name of an extruder", "Print Selected Model with %1", "Print Selected Models with %1", UM.Selection.selectionCount).arg(extruder.name)
|
||||
|
||||
style: UM.Theme.styles.tool_button;
|
||||
iconSource: UM.Theme.getIcon("extruder_button")
|
||||
|
||||
checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1
|
||||
enabled: UM.Selection.hasSelection && extruder.stack.isEnabled
|
||||
|
||||
property color customColor: base.hovered ? UM.Theme.getColor("button_hover") : UM.Theme.getColor("button");
|
||||
|
||||
Rectangle
|
||||
toolItem: ExtruderIcon
|
||||
{
|
||||
anchors.fill: parent
|
||||
anchors.margins: UM.Theme.getSize("default_lining").width;
|
||||
|
||||
color: "transparent"
|
||||
|
||||
border.width: base.checked ? UM.Theme.getSize("default_lining").width : 0;
|
||||
border.color: UM.Theme.getColor("button_text")
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
anchors.centerIn: parent
|
||||
width: UM.Theme.getSize("default_margin").width
|
||||
height: UM.Theme.getSize("default_margin").height
|
||||
|
||||
Label
|
||||
{
|
||||
anchors.centerIn: parent;
|
||||
text: index + 1;
|
||||
color: parent.enabled ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_disabled_text")
|
||||
font: UM.Theme.getFont("default_bold");
|
||||
}
|
||||
}
|
||||
|
||||
// Material colour circle
|
||||
// Only draw the filling colour of the material inside the SVG border.
|
||||
Rectangle
|
||||
{
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
rightMargin: UM.Theme.getSize("extruder_button_material_margin").width
|
||||
topMargin: UM.Theme.getSize("extruder_button_material_margin").height
|
||||
}
|
||||
|
||||
color: model.color
|
||||
|
||||
width: UM.Theme.getSize("extruder_button_material").width
|
||||
height: UM.Theme.getSize("extruder_button_material").height
|
||||
radius: Math.round(width / 2)
|
||||
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("extruder_button_material_border")
|
||||
|
||||
opacity: !base.enabled ? 0.2 : 1.0
|
||||
materialColor: extruder.color
|
||||
extruderEnabled: extruder.stack.isEnabled
|
||||
property int index: extruder.index
|
||||
}
|
||||
|
||||
onClicked:
|
||||
{
|
||||
forceActiveFocus() //First grab focus, so all the text fields are updated
|
||||
CuraActions.setExtruderForSelection(extruder.id);
|
||||
CuraActions.setExtruderForSelection(extruder.id)
|
||||
}
|
||||
}
|
||||
|
|
71
resources/qml/ExtruderIcon.qml
Normal file
71
resources/qml/ExtruderIcon.qml
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.1
|
||||
import UM 1.2 as UM
|
||||
|
||||
Item
|
||||
{
|
||||
id: extruderIconItem
|
||||
|
||||
implicitWidth: UM.Theme.getSize("extruder_icon").width
|
||||
implicitHeight: UM.Theme.getSize("extruder_icon").height
|
||||
|
||||
property bool checked: true
|
||||
property color materialColor
|
||||
property alias textColor: extruderNumberText.color
|
||||
property bool extruderEnabled: true
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: mainIcon
|
||||
anchors.fill: parent
|
||||
|
||||
source: UM.Theme.getIcon("extruder_button")
|
||||
color: extruderEnabled ? materialColor: UM.Theme.getColor("disabled")
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: extruderNumberCircle
|
||||
|
||||
width: height
|
||||
height: Math.round(parent.height / 2)
|
||||
radius: Math.round(width / 2)
|
||||
color: UM.Theme.getColor("toolbar_background")
|
||||
|
||||
anchors
|
||||
{
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
top: parent.top
|
||||
// The circle needs to be slightly off center (so it sits in the middle of the square bit of the icon)
|
||||
topMargin: (parent.height - height) / 2 - 0.1 * parent.height
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: extruderNumberText
|
||||
anchors.centerIn: parent
|
||||
text: index + 1
|
||||
font: UM.Theme.getFont("very_small")
|
||||
width: contentWidth
|
||||
height: contentHeight
|
||||
visible: extruderEnabled
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: disabledIcon
|
||||
anchors.fill: parent
|
||||
anchors.margins: UM.Theme.getSize("thick_lining").width
|
||||
sourceSize.height: width
|
||||
source: UM.Theme.getIcon("cross1")
|
||||
visible: !extruderEnabled
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue