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