1// Copyright (c) 2018 Ultimaker B.V. 2// Cura is released under the terms of the LGPLv3 or higher. 3 4import QtQuick 2.7 5import QtQuick.Controls 2.3 6 7import UM 1.2 as UM 8import Cura 1.1 as Cura 9 10Cura.ExpandablePopup 11{ 12 id: machineSelector 13 14 property bool isNetworkPrinter: Cura.MachineManager.activeMachineHasNetworkConnection 15 property bool isConnectedCloudPrinter: Cura.MachineManager.activeMachineHasCloudConnection 16 property bool isCloudRegistered: Cura.MachineManager.activeMachineHasCloudRegistration 17 property bool isGroup: Cura.MachineManager.activeMachineIsGroup 18 19 readonly property string connectionStatus: { 20 if (isNetworkPrinter) 21 { 22 return "printer_connected" 23 } 24 else if (isConnectedCloudPrinter && Cura.API.connectionStatus.isInternetReachable) 25 { 26 return "printer_cloud_connected" 27 } 28 else if (isCloudRegistered) 29 { 30 return "printer_cloud_not_available" 31 } 32 else 33 { 34 return "" 35 } 36 } 37 38 function getConnectionStatusMessage() { 39 if (connectionStatus == "printer_cloud_not_available") 40 { 41 if(Cura.API.connectionStatus.isInternetReachable) 42 { 43 if (Cura.API.account.isLoggedIn) 44 { 45 if (Cura.MachineManager.activeMachineIsLinkedToCurrentAccount) 46 { 47 return catalog.i18nc("@status", "The cloud printer is offline. Please check if the printer is turned on and connected to the internet.") 48 } 49 else 50 { 51 return catalog.i18nc("@status", "This printer is not linked to your account. Please visit the Ultimaker Digital Factory to establish a connection.") 52 } 53 } 54 else 55 { 56 return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please sign in to connect to the cloud printer.") 57 } 58 } else 59 { 60 return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please check your internet connection.") 61 } 62 } 63 else 64 { 65 return "" 66 } 67 } 68 69 contentPadding: UM.Theme.getSize("default_lining").width 70 contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft 71 72 UM.I18nCatalog 73 { 74 id: catalog 75 name: "cura" 76 } 77 78 headerItem: Cura.IconWithText 79 { 80 text: 81 { 82 if (isNetworkPrinter && Cura.MachineManager.activeMachineNetworkGroupName != "") 83 { 84 return Cura.MachineManager.activeMachineNetworkGroupName 85 } 86 if(Cura.MachineManager.activeMachine != null) 87 { 88 return Cura.MachineManager.activeMachine.name 89 } 90 return "" 91 } 92 source: 93 { 94 if (isGroup) 95 { 96 return UM.Theme.getIcon("printer_group") 97 } 98 else if (isNetworkPrinter || isCloudRegistered) 99 { 100 return UM.Theme.getIcon("printer_single") 101 } 102 else 103 { 104 return "" 105 } 106 } 107 font: UM.Theme.getFont("medium") 108 iconColor: UM.Theme.getColor("machine_selector_printer_icon") 109 iconSize: source != "" ? UM.Theme.getSize("machine_selector_icon").width: 0 110 111 UM.RecolorImage 112 { 113 id: connectionStatusImage 114 anchors 115 { 116 bottom: parent.bottom 117 left: parent.left 118 leftMargin: UM.Theme.getSize("thick_margin").width 119 } 120 121 source: UM.Theme.getIcon(connectionStatus) 122 123 width: UM.Theme.getSize("printer_status_icon").width 124 height: UM.Theme.getSize("printer_status_icon").height 125 126 color: connectionStatus == "printer_cloud_not_available" ? UM.Theme.getColor("cloud_unavailable") : UM.Theme.getColor("primary") 127 128 visible: isNetworkPrinter || isCloudRegistered 129 130 // Make a themable circle in the background so we can change it in other themes 131 Rectangle 132 { 133 id: iconBackground 134 anchors.centerIn: parent 135 // Make it a bit bigger so there is an outline 136 width: parent.width + 2 * UM.Theme.getSize("default_lining").width 137 height: parent.height + 2 * UM.Theme.getSize("default_lining").height 138 radius: Math.round(width / 2) 139 color: UM.Theme.getColor("main_background") 140 z: parent.z - 1 141 } 142 143 } 144 145 MouseArea // Connection status tooltip hover area 146 { 147 id: connectionStatusTooltipHoverArea 148 anchors.fill: parent 149 hoverEnabled: getConnectionStatusMessage() !== "" 150 acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks 151 152 onEntered: 153 { 154 machineSelector.mouseArea.entered() // we want both this and the outer area to be entered 155 tooltip.tooltipText = getConnectionStatusMessage() 156 tooltip.show() 157 } 158 onExited: { tooltip.hide() } 159 } 160 161 Cura.ToolTip 162 { 163 id: tooltip 164 165 width: 250 * screenScaleFactor 166 tooltipText: getConnectionStatusMessage() 167 arrowSize: UM.Theme.getSize("button_tooltip_arrow").width 168 x: connectionStatusImage.x - UM.Theme.getSize("narrow_margin").width 169 y: connectionStatusImage.y + connectionStatusImage.height + UM.Theme.getSize("narrow_margin").height 170 z: popup.z + 1 171 targetPoint: Qt.point( 172 connectionStatusImage.x + Math.round(connectionStatusImage.width / 2), 173 connectionStatusImage.y 174 ) 175 } 176 } 177 178 contentItem: Item 179 { 180 id: popup 181 width: UM.Theme.getSize("machine_selector_widget_content").width 182 183 ScrollView 184 { 185 id: scroll 186 width: parent.width 187 clip: true 188 leftPadding: UM.Theme.getSize("default_lining").width 189 rightPadding: UM.Theme.getSize("default_lining").width 190 191 MachineSelectorList 192 { 193 id: machineSelectorList 194 // Can't use parent.width since the parent is the flickable component and not the ScrollView 195 width: scroll.width - scroll.leftPadding - scroll.rightPadding 196 property real maximumHeight: UM.Theme.getSize("machine_selector_widget_content").height - buttonRow.height 197 198 // We use an extra property here, since we only want to to be informed about the content size changes. 199 onContentHeightChanged: 200 { 201 scroll.height = Math.min(contentHeight, maximumHeight) 202 popup.height = scroll.height + buttonRow.height 203 } 204 205 Component.onCompleted: 206 { 207 scroll.height = Math.min(contentHeight, maximumHeight) 208 popup.height = scroll.height + buttonRow.height 209 } 210 } 211 } 212 213 Rectangle 214 { 215 id: separator 216 217 anchors.top: scroll.bottom 218 width: parent.width 219 height: UM.Theme.getSize("default_lining").height 220 color: UM.Theme.getColor("lining") 221 } 222 223 Row 224 { 225 id: buttonRow 226 227 // The separator is inside the buttonRow. This is to avoid some weird behaviours with the scroll bar. 228 anchors.top: separator.top 229 anchors.horizontalCenter: parent.horizontalCenter 230 padding: UM.Theme.getSize("default_margin").width 231 spacing: UM.Theme.getSize("default_margin").width 232 233 Cura.SecondaryButton 234 { 235 id: addPrinterButton 236 leftPadding: UM.Theme.getSize("default_margin").width 237 rightPadding: UM.Theme.getSize("default_margin").width 238 text: catalog.i18nc("@button", "Add printer") 239 // The maximum width of the button is half of the total space, minus the padding of the parent, the left 240 // padding of the component and half the spacing because of the space between buttons. 241 fixedWidthMode: true 242 width: UM.Theme.getSize("machine_selector_widget_content").width / 2 - leftPadding 243 onClicked: 244 { 245 toggleContent() 246 Cura.Actions.addMachine.trigger() 247 } 248 } 249 250 Cura.SecondaryButton 251 { 252 id: managePrinterButton 253 leftPadding: UM.Theme.getSize("default_margin").width 254 rightPadding: UM.Theme.getSize("default_margin").width 255 text: catalog.i18nc("@button", "Manage printers") 256 fixedWidthMode: true 257 // The maximum width of the button is half of the total space, minus the padding of the parent, the right 258 // padding of the component and half the spacing because of the space between buttons. 259 width: UM.Theme.getSize("machine_selector_widget_content").width / 2 - leftPadding 260 onClicked: 261 { 262 toggleContent() 263 Cura.Actions.configureMachines.trigger() 264 } 265 } 266 } 267 } 268} 269