diff --git a/README.md b/README.md index 70466e9c22..93abcc0c61 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ Dependencies ------------ * [Uranium](https://github.com/Ultimaker/Uranium) Cura is built on top of the Uranium framework. * [CuraEngine](https://github.com/Ultimaker/CuraEngine) This will be needed at runtime to perform the actual slicing. +* [fdm_materials](https://github.com/Ultimaker/fdm_materials) Required to load a printer that has swappable material profiles. * [PySerial](https://github.com/pyserial/pyserial) Only required for USB printing support. -* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers +* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers. Build scripts ------------- diff --git a/cura.desktop.in b/cura.desktop.in index fbe8b30fed..b0195015a5 100644 --- a/cura.desktop.in +++ b/cura.desktop.in @@ -13,6 +13,6 @@ TryExec=@CMAKE_INSTALL_FULL_BINDIR@/cura Icon=cura-icon Terminal=false Type=Application -MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;image/bmp;image/gif;image/jpeg;image/png;model/x3d+xml; +MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;image/bmp;image/gif;image/jpeg;image/png;model/x3d+xml;text/x-gcode; Categories=Graphics; Keywords=3D;Printing;Slicer; diff --git a/cura.sharedmimeinfo b/cura.sharedmimeinfo index 23d38795eb..ed9099d425 100644 --- a/cura.sharedmimeinfo +++ b/cura.sharedmimeinfo @@ -19,4 +19,12 @@ + + + Gcode file + + + + + \ No newline at end of file diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index 897d5fa979..714d6527fe 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -46,12 +46,13 @@ class Backup: # We copy the preferences file to the user data directory in Linux as it's in a different location there. # When restoring a backup on Linux, we move it back. - if Platform.isLinux(): + if Platform.isLinux(): #TODO: This should check for the config directory not being the same as the data directory, rather than hard-coding that to Linux systems. preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) - Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file) - shutil.copyfile(preferences_file, backup_preferences_file) + if os.path.exists(preferences_file) and (not os.path.exists(backup_preferences_file) or not os.path.samefile(preferences_file, backup_preferences_file)): + Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file) + shutil.copyfile(preferences_file, backup_preferences_file) # Create an empty buffer and write the archive to it. buffer = io.BytesIO() diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml index 437a2ef351..0c04dc2bab 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml @@ -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 diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 9c070f2de2..daea696cd1 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -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 UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin @@ -325,13 +325,12 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): ## Handler for zeroConf detection. # Return True or False indicating if the process succeeded. - # Note that this function can take over 3 seconds to complete. Be carefull calling it from the main thread. + # Note that this function can take over 3 seconds to complete. Be careful + # calling it from the main thread. def _onServiceChanged(self, zero_conf, service_type, name, state_change): if state_change == ServiceStateChange.Added: - Logger.log("d", "Bonjour service added: %s" % name) - # First try getting info from zero-conf cache - info = ServiceInfo(service_type, name, properties={}) + info = ServiceInfo(service_type, name, properties = {}) for record in zero_conf.cache.entries_with_name(name.lower()): info.update_record(zero_conf, time(), record) diff --git a/resources/qml/Account/GeneralOperations.qml b/resources/qml/Account/GeneralOperations.qml index 4614c4ba88..b9f1025d5e 100644 --- a/resources/qml/Account/GeneralOperations.qml +++ b/resources/qml/Account/GeneralOperations.qml @@ -11,20 +11,16 @@ Row { spacing: UM.Theme.getSize("default_margin").width - Cura.ActionButton + Cura.SecondaryButton { width: UM.Theme.getSize("account_button").width height: UM.Theme.getSize("account_button").height text: catalog.i18nc("@button", "Create account") - color: UM.Theme.getColor("secondary") - hoverColor: UM.Theme.getColor("secondary") - textColor: UM.Theme.getColor("main_window_header_button_text_active") - textHoverColor: UM.Theme.getColor("main_window_header_button_text_active") onClicked: Qt.openUrlExternally("https://account.ultimaker.com/app/create") fixedWidthMode: true } - Cura.ActionButton + Cura.PrimaryButton { width: UM.Theme.getSize("account_button").width height: UM.Theme.getSize("account_button").height diff --git a/resources/qml/Account/UserOperations.qml b/resources/qml/Account/UserOperations.qml index c167813425..b9ffa395d6 100644 --- a/resources/qml/Account/UserOperations.qml +++ b/resources/qml/Account/UserOperations.qml @@ -11,20 +11,16 @@ Row { spacing: UM.Theme.getSize("default_margin").width - Cura.ActionButton + Cura.SecondaryButton { width: UM.Theme.getSize("account_button").width height: UM.Theme.getSize("account_button").height text: catalog.i18nc("@button", "Manage account") - color: UM.Theme.getColor("secondary") - hoverColor: UM.Theme.getColor("secondary") - textColor: UM.Theme.getColor("main_window_header_button_text_active") - textHoverColor: UM.Theme.getColor("main_window_header_button_text_active") onClicked: Qt.openUrlExternally("https://account.ultimaker.com") fixedWidthMode: true } - Cura.ActionButton + Cura.PrimaryButton { width: UM.Theme.getSize("account_button").width height: UM.Theme.getSize("account_button").height diff --git a/resources/qml/ActionButton.qml b/resources/qml/ActionButton.qml index ff8ee4b149..b9a04f3b46 100644 --- a/resources/qml/ActionButton.qml +++ b/resources/qml/ActionButton.qml @@ -4,25 +4,33 @@ import QtQuick 2.7 import QtQuick.Controls 2.1 +import QtGraphicalEffects 1.0 // For the dropshadow + import UM 1.1 as UM Button { id: button - property alias cursorShape: mouseArea.cursorShape property alias iconSource: buttonIcon.source property alias textFont: buttonText.font property alias cornerRadius: backgroundRect.radius property alias tooltip: tooltip.text - property var color: UM.Theme.getColor("primary") - property var hoverColor: UM.Theme.getColor("primary_hover") - property var disabledColor: color - property var textColor: UM.Theme.getColor("button_text") - property var textHoverColor: UM.Theme.getColor("button_text_hover") - property var textDisabledColor: textColor - property var outlineColor: color - property var outlineHoverColor: hoverColor - property var outlineDisabledColor: outlineColor + + 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 + + hoverEnabled: true + + 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. @@ -67,6 +75,19 @@ Button 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 @@ -74,12 +95,4 @@ Button delay: 500 visible: text != "" && button.hovered } - - MouseArea - { - id: mouseArea - anchors.fill: parent - onPressed: mouse.accepted = false - hoverEnabled: true - } } diff --git a/resources/qml/ActionPanel/OutputDevicesActionButton.qml b/resources/qml/ActionPanel/OutputDevicesActionButton.qml index be79a1893e..2111038cfc 100644 --- a/resources/qml/ActionPanel/OutputDevicesActionButton.qml +++ b/resources/qml/ActionPanel/OutputDevicesActionButton.qml @@ -12,7 +12,7 @@ Item { id: widget - Cura.ActionButton + Cura.PrimaryButton { id: saveToButton height: parent.height @@ -42,6 +42,9 @@ Item id: deviceSelectionMenu height: parent.height + shadowEnabled: true + shadowColor: UM.Theme.getColor("primary_shadow") + anchors { top: parent.top @@ -65,7 +68,7 @@ Item closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent - contentItem: Column + contentItem: ColumnLayout { Repeater { @@ -77,7 +80,7 @@ Item color: "transparent" cornerRadius: 0 hoverColor: UM.Theme.getColor("primary") - + Layout.fillWidth: true onClicked: { UM.OutputDeviceManager.setActiveDevice(model.id) @@ -91,10 +94,7 @@ Item { opacity: visible ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 100 } } - radius: UM.Theme.getSize("default_radius").width color: UM.Theme.getColor("action_panel_secondary") - border.color: UM.Theme.getColor("lining") - border.width: UM.Theme.getSize("default_lining").width } } } diff --git a/resources/qml/ActionPanel/OutputProcessWidget.qml b/resources/qml/ActionPanel/OutputProcessWidget.qml index 3c4386f079..ddbe709a84 100644 --- a/resources/qml/ActionPanel/OutputProcessWidget.qml +++ b/resources/qml/ActionPanel/OutputProcessWidget.qml @@ -101,20 +101,18 @@ Column spacing: UM.Theme.getSize("default_margin").width width: parent.width - Cura.ActionButton + Cura.SecondaryButton { id: previewStageShortcut - leftPadding: UM.Theme.getSize("default_margin").width - rightPadding: UM.Theme.getSize("default_margin").width height: UM.Theme.getSize("action_panel_button").height text: catalog.i18nc("@button", "Preview") - color: UM.Theme.getColor("secondary") - hoverColor: UM.Theme.getColor("secondary") - textColor: UM.Theme.getColor("primary") - textHoverColor: UM.Theme.getColor("text") + 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 diff --git a/resources/qml/ActionPanel/SliceProcessWidget.qml b/resources/qml/ActionPanel/SliceProcessWidget.qml index 2d4a7b6b89..3329ac4b23 100644 --- a/resources/qml/ActionPanel/SliceProcessWidget.qml +++ b/resources/qml/ActionPanel/SliceProcessWidget.qml @@ -40,9 +40,21 @@ Column } } + Label + { + id: autoSlicingLabel + width: parent.width + visible: prepareButtons.autoSlice && widget.backendState == UM.Backend.Processing + + text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...") + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("very_small") + renderType: Text.NativeRendering + } + Cura.IconLabel { - id: message + id: unableToSliceMessage width: parent.width visible: widget.backendState == UM.Backend.Error @@ -81,38 +93,41 @@ Column } } - Cura.ActionButton - { - id: prepareButton - width: parent.width - height: UM.Theme.getSize("action_panel_button").height - fixedWidthMode: true - text: - { - if ([UM.Backend.NotStarted, UM.Backend.Error].indexOf(widget.backendState) != -1) - { - return catalog.i18nc("@button", "Slice") - } - if (autoSlice) - { - return catalog.i18nc("@button", "Auto slicing...") - } - return catalog.i18nc("@button", "Cancel") - } - enabled: !autoSlice && !disabledSlice + Item + { + id: prepareButtons // Get the current value from the preferences property bool autoSlice: UM.Preferences.getValue("general/auto_slice") // Disable the slice process when - property bool disabledSlice: [UM.Backend.Done, UM.Backend.Error].indexOf(widget.backendState) != -1 - disabledColor: disabledSlice ? UM.Theme.getColor("action_button_disabled") : "transparent" - textDisabledColor: disabledSlice ? UM.Theme.getColor("action_button_disabled_text") : UM.Theme.getColor("primary") - outlineDisabledColor: disabledSlice ? UM.Theme.getColor("action_button_disabled_border") : "transparent" + width: parent.width + height: UM.Theme.getSize("action_panel_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() + } - 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 { @@ -120,7 +135,7 @@ Column onPreferenceChanged: { var autoSlice = UM.Preferences.getValue("general/auto_slice") - prepareButton.autoSlice = autoSlice + prepareButtons.autoSlice = autoSlice } } diff --git a/resources/qml/MainWindow/MainWindowHeader.qml b/resources/qml/MainWindow/MainWindowHeader.qml index 59ec542e6b..a24af7ee45 100644 --- a/resources/qml/MainWindow/MainWindowHeader.qml +++ b/resources/qml/MainWindow/MainWindowHeader.qml @@ -2,6 +2,7 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 +import QtQuick.Controls 2.0 as Controls2 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.1 @@ -73,25 +74,37 @@ Rectangle } // Shortcut button to quick access the Toolbox - Cura.ActionButton + Controls2.Button { + id: marketplaceButton + text: catalog.i18nc("@action:button", "Marketplace") + height: Math.round(0.5 * UM.Theme.getSize("main_window_header").height) + onClicked: Cura.Actions.browsePackages.trigger() + + hoverEnabled: true + + background: Rectangle + { + radius: UM.Theme.getSize("action_button_radius").width + color: marketplaceButton.hovered ? UM.Theme.getColor("primary_text") : UM.Theme.getColor("main_window_header_background") + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("primary_text") + } + + contentItem: Label + { + id: label + text: marketplaceButton.text + color: marketplaceButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text") + width: contentWidth + } + anchors { right: accountWidget.left rightMargin: UM.Theme.getSize("default_margin").width verticalCenter: parent.verticalCenter } - leftPadding: UM.Theme.getSize("default_margin").width - rightPadding: UM.Theme.getSize("default_margin").width - text: catalog.i18nc("@action:button", "Marketplace") - height: Math.round(0.5 * UM.Theme.getSize("main_window_header").height) - color: UM.Theme.getColor("main_window_header_secondary_button_background_active") - hoverColor: UM.Theme.getColor("main_window_header_secondary_button_background_hovered") - outlineColor: UM.Theme.getColor("main_window_header_secondary_button_outline_active") - outlineHoverColor: UM.Theme.getColor("main_window_header_secondary_button_outline_hovered") - textColor: UM.Theme.getColor("main_window_header_secondary_button_text_active") - textHoverColor: UM.Theme.getColor("main_window_header_secondary_button_text_hovered") - onClicked: Cura.Actions.browsePackages.trigger() } AccountWidget diff --git a/resources/qml/PrimaryButton.qml b/resources/qml/PrimaryButton.qml new file mode 100644 index 0000000000..fca63d2cdb --- /dev/null +++ b/resources/qml/PrimaryButton.qml @@ -0,0 +1,20 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 + +import UM 1.4 as UM +import Cura 1.1 as Cura + + +Cura.ActionButton +{ + shadowEnabled: true + shadowColor: enabled ? UM.Theme.getColor("primary_button_shadow"): UM.Theme.getColor("action_button_disabled_shadow") + color: UM.Theme.getColor("primary_button") + textColor: UM.Theme.getColor("primary_button_text") + outlineColor: "transparent" + disabledColor: UM.Theme.getColor("action_button_disabled") + textDisabledColor: UM.Theme.getColor("action_button_disabled_text") + hoverColor: UM.Theme.getColor("primary_button_hover") +} \ No newline at end of file diff --git a/resources/qml/SecondaryButton.qml b/resources/qml/SecondaryButton.qml new file mode 100644 index 0000000000..f03d8acdfa --- /dev/null +++ b/resources/qml/SecondaryButton.qml @@ -0,0 +1,20 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 + +import UM 1.4 as UM +import Cura 1.1 as Cura + + +Cura.ActionButton +{ + shadowEnabled: true + shadowColor: enabled ? UM.Theme.getColor("secondary_button_shadow"): UM.Theme.getColor("action_button_disabled_shadow") + color: UM.Theme.getColor("secondary_button") + textColor: UM.Theme.getColor("secondary_button_text") + outlineColor: "transparent" + disabledColor: UM.Theme.getColor("action_button_disabled") + textDisabledColor: UM.Theme.getColor("action_button_disabled_text") + hoverColor: UM.Theme.getColor("secondary_button_hover") +} \ No newline at end of file diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 23b1ffcada..6755d91cc7 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -82,10 +82,22 @@ "viewport_overlay": [0, 0, 0, 192], "primary": [50, 130, 255, 255], + "primary_shadow": [64, 47, 205, 255], "primary_hover": [48, 182, 231, 255], "primary_text": [255, 255, 255, 255], "border": [127, 127, 127, 255], "secondary": [245, 245, 245, 255], + "secondary_shadow": [228, 228, 228, 255], + + "primary_button": [38, 113, 231, 255], + "primary_button_shadow": [27, 95, 202, 255], + "primary_button_hover": [81, 145, 247, 255], + "primary_button_text": [255, 255, 255, 255], + + "secondary_button": [240, 240, 240, 255], + "secondary_button_shadow": [228, 228, 228, 255], + "secondary_button_hover": [228, 228, 228, 255], + "secondary_button_text": [30, 102, 215, 255], "main_window_header_background": [10, 8, 80, 255], "main_window_header_button_text_active": [10, 8, 80, 255], @@ -95,13 +107,6 @@ "main_window_header_button_background_inactive": [255, 255, 255, 0], "main_window_header_button_background_hovered": [255, 255, 255, 102], - "main_window_header_secondary_button_text_active": [255, 255, 255, 255], - "main_window_header_secondary_button_text_hovered": [10, 8, 80, 255], - "main_window_header_secondary_button_background_active": [255, 255, 255, 0], - "main_window_header_secondary_button_background_hovered": [255, 255, 255, 255], - "main_window_header_secondary_button_outline_active": [255, 255, 255, 255], - "main_window_header_secondary_button_outline_hovered": [255, 255, 255, 255], - "account_widget_outline_active": [70, 66, 126, 255], "machine_selector_bar": [31, 36, 39, 255], @@ -174,14 +179,8 @@ "action_button_disabled": [245, 245, 245, 255], "action_button_disabled_text": [127, 127, 127, 255], "action_button_disabled_border": [245, 245, 245, 255], - - "print_button_ready": [50, 130, 255, 255], - "print_button_ready_border": [50, 130, 255, 255], - "print_button_ready_text": [255, 255, 255, 255], - "print_button_ready_hovered": [30, 186, 245, 243], - "print_button_ready_hovered_border": [30, 186, 245, 243], - "print_button_ready_pressed": [30, 186, 245, 243], - "print_button_ready_pressed_border": [30, 186, 245, 243], + "action_button_shadow": [64, 47, 205, 255], + "action_button_disabled_shadow": [228, 228, 228, 255], "scrollbar_background": [255, 255, 255, 255], "scrollbar_handle": [31, 36, 39, 255],