DiscoverUM3Action.qml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. // Copyright (c) 2018 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import UM 1.2 as UM
  4. import Cura 1.0 as Cura
  5. import QtQuick 2.2
  6. import QtQuick.Controls 1.1
  7. import QtQuick.Layouts 1.1
  8. import QtQuick.Window 2.1
  9. import QtQuick.Dialogs 1.2
  10. Cura.MachineAction
  11. {
  12. id: base
  13. anchors.fill: parent;
  14. property var selectedDevice: null
  15. property bool completeProperties: true
  16. function connectToPrinter()
  17. {
  18. if(base.selectedDevice && base.completeProperties)
  19. {
  20. var printerKey = base.selectedDevice.key
  21. var printerName = base.selectedDevice.name // TODO To change when the groups have a name
  22. if (manager.getStoredKey() != printerKey)
  23. {
  24. // Check if there is another instance with the same key
  25. if (!manager.existsKey(printerKey))
  26. {
  27. manager.associateActiveMachineWithPrinterDevice(base.selectedDevice)
  28. manager.setGroupName(printerName) // TODO To change when the groups have a name
  29. completed()
  30. }
  31. else
  32. {
  33. existingConnectionDialog.open()
  34. }
  35. }
  36. }
  37. }
  38. MessageDialog
  39. {
  40. id: existingConnectionDialog
  41. title: catalog.i18nc("@window:title", "Existing Connection")
  42. icon: StandardIcon.Information
  43. text: catalog.i18nc("@message:text", "This printer/group is already added to Cura. Please select another printer/group.")
  44. standardButtons: StandardButton.Ok
  45. modality: Qt.ApplicationModal
  46. }
  47. Column
  48. {
  49. anchors.fill: parent;
  50. id: discoverUM3Action
  51. spacing: UM.Theme.getSize("default_margin").height
  52. SystemPalette { id: palette }
  53. UM.I18nCatalog { id: catalog; name:"cura" }
  54. Label
  55. {
  56. id: pageTitle
  57. width: parent.width
  58. text: catalog.i18nc("@title:window", "Connect to Networked Printer")
  59. wrapMode: Text.WordWrap
  60. renderType: Text.NativeRendering
  61. font.pointSize: 18
  62. }
  63. Label
  64. {
  65. id: pageDescription
  66. width: parent.width
  67. wrapMode: Text.WordWrap
  68. renderType: Text.NativeRendering
  69. 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:")
  70. }
  71. Row
  72. {
  73. spacing: UM.Theme.getSize("default_lining").width
  74. Button
  75. {
  76. id: addButton
  77. text: catalog.i18nc("@action:button", "Add");
  78. onClicked:
  79. {
  80. manualPrinterDialog.showDialog("", "");
  81. }
  82. }
  83. Button
  84. {
  85. id: editButton
  86. text: catalog.i18nc("@action:button", "Edit")
  87. enabled: base.selectedDevice != null && base.selectedDevice.getProperty("manual") == "true"
  88. onClicked:
  89. {
  90. manualPrinterDialog.showDialog(base.selectedDevice.key, base.selectedDevice.ipAddress);
  91. }
  92. }
  93. Button
  94. {
  95. id: removeButton
  96. text: catalog.i18nc("@action:button", "Remove")
  97. enabled: base.selectedDevice != null && base.selectedDevice.getProperty("manual") == "true"
  98. onClicked: manager.removeManualDevice(base.selectedDevice.key, base.selectedDevice.ipAddress)
  99. }
  100. Button
  101. {
  102. id: rediscoverButton
  103. text: catalog.i18nc("@action:button", "Refresh")
  104. onClicked: manager.restartDiscovery()
  105. }
  106. }
  107. Row
  108. {
  109. id: contentRow
  110. width: parent.width
  111. spacing: UM.Theme.getSize("default_margin").width
  112. Column
  113. {
  114. width: Math.round(parent.width * 0.5)
  115. spacing: UM.Theme.getSize("default_margin").height
  116. ScrollView
  117. {
  118. id: objectListContainer
  119. frameVisible: true
  120. width: parent.width
  121. height: base.height - contentRow.y - discoveryTip.height
  122. Rectangle
  123. {
  124. parent: viewport
  125. anchors.fill: parent
  126. color: palette.light
  127. }
  128. ListView
  129. {
  130. id: listview
  131. model: manager.foundDevices
  132. onModelChanged:
  133. {
  134. var selectedKey = manager.getLastManualEntryKey()
  135. // If there is no last manual entry key, then we select the stored key (if any)
  136. if (selectedKey == "")
  137. selectedKey = manager.getStoredKey()
  138. for(var i = 0; i < model.length; i++) {
  139. if(model[i].key == selectedKey)
  140. {
  141. currentIndex = i;
  142. return
  143. }
  144. }
  145. currentIndex = -1;
  146. }
  147. width: parent.width
  148. currentIndex: -1
  149. onCurrentIndexChanged:
  150. {
  151. base.selectedDevice = listview.model[currentIndex];
  152. // Only allow connecting if the printer has responded to API query since the last refresh
  153. base.completeProperties = base.selectedDevice != null && base.selectedDevice.getProperty("incomplete") != "true";
  154. }
  155. Component.onCompleted: manager.startDiscovery()
  156. delegate: Rectangle
  157. {
  158. height: childrenRect.height
  159. color: ListView.isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase
  160. width: parent.width
  161. Label
  162. {
  163. anchors.left: parent.left
  164. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  165. anchors.right: parent.right
  166. text: listview.model[index].name
  167. color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text
  168. elide: Text.ElideRight
  169. renderType: Text.NativeRendering
  170. }
  171. MouseArea
  172. {
  173. anchors.fill: parent;
  174. onClicked:
  175. {
  176. if(!parent.ListView.isCurrentItem)
  177. {
  178. parent.ListView.view.currentIndex = index;
  179. }
  180. }
  181. }
  182. }
  183. }
  184. }
  185. Label
  186. {
  187. id: discoveryTip
  188. anchors.left: parent.left
  189. anchors.right: parent.right
  190. wrapMode: Text.WordWrap
  191. renderType: Text.NativeRendering
  192. 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");
  193. onLinkActivated: Qt.openUrlExternally(link)
  194. }
  195. }
  196. Column
  197. {
  198. width: Math.round(parent.width * 0.5)
  199. visible: base.selectedDevice ? true : false
  200. spacing: UM.Theme.getSize("default_margin").height
  201. Label
  202. {
  203. width: parent.width
  204. wrapMode: Text.WordWrap
  205. text: base.selectedDevice ? base.selectedDevice.name : ""
  206. font: UM.Theme.getFont("large_bold")
  207. elide: Text.ElideRight
  208. renderType: Text.NativeRendering
  209. }
  210. Grid
  211. {
  212. visible: base.completeProperties
  213. width: parent.width
  214. columns: 2
  215. Label
  216. {
  217. width: Math.round(parent.width * 0.5)
  218. wrapMode: Text.WordWrap
  219. renderType: Text.NativeRendering
  220. text: catalog.i18nc("@label", "Type")
  221. }
  222. Label
  223. {
  224. width: Math.round(parent.width * 0.5)
  225. wrapMode: Text.WordWrap
  226. renderType: Text.NativeRendering
  227. text:
  228. {
  229. if(base.selectedDevice)
  230. {
  231. if (base.selectedDevice.printerType == "ultimaker3")
  232. {
  233. return "Ultimaker 3";
  234. }
  235. else if (base.selectedDevice.printerType == "ultimaker3_extended")
  236. {
  237. return "Ultimaker 3 Extended";
  238. }
  239. else if (base.selectedDevice.printerType == "ultimaker_s5")
  240. {
  241. return "Ultimaker S5";
  242. }
  243. else
  244. {
  245. return catalog.i18nc("@label", "Unknown") // We have no idea what type it is. Should not happen 'in the field'
  246. }
  247. }
  248. else
  249. {
  250. return ""
  251. }
  252. }
  253. }
  254. Label
  255. {
  256. width: Math.round(parent.width * 0.5)
  257. wrapMode: Text.WordWrap
  258. renderType: Text.NativeRendering
  259. text: catalog.i18nc("@label", "Firmware version")
  260. }
  261. Label
  262. {
  263. width: Math.round(parent.width * 0.5)
  264. wrapMode: Text.WordWrap
  265. renderType: Text.NativeRendering
  266. text: base.selectedDevice ? base.selectedDevice.firmwareVersion : ""
  267. }
  268. Label
  269. {
  270. width: Math.round(parent.width * 0.5)
  271. wrapMode: Text.WordWrap
  272. renderType: Text.NativeRendering
  273. text: catalog.i18nc("@label", "Address")
  274. }
  275. Label
  276. {
  277. width: Math.round(parent.width * 0.5)
  278. wrapMode: Text.WordWrap
  279. renderType: Text.NativeRendering
  280. text: base.selectedDevice ? base.selectedDevice.ipAddress : ""
  281. }
  282. }
  283. Label
  284. {
  285. width: parent.width
  286. wrapMode: Text.WordWrap
  287. renderType: Text.NativeRendering
  288. text:{
  289. // The property cluster size does not exist for older UM3 devices.
  290. if(!base.selectedDevice || base.selectedDevice.clusterSize == null || base.selectedDevice.clusterSize == 1)
  291. {
  292. return "";
  293. }
  294. else if (base.selectedDevice.clusterSize === 0)
  295. {
  296. return catalog.i18nc("@label", "This printer is not set up to host a group of printers.");
  297. }
  298. else
  299. {
  300. return catalog.i18nc("@label", "This printer is the host for a group of %1 printers.".arg(base.selectedDevice.clusterSize));
  301. }
  302. }
  303. }
  304. Label
  305. {
  306. width: parent.width
  307. wrapMode: Text.WordWrap
  308. renderType: Text.NativeRendering
  309. visible: base.selectedDevice != null && !base.completeProperties
  310. text: catalog.i18nc("@label", "The printer at this address has not yet responded." )
  311. }
  312. Button
  313. {
  314. text: catalog.i18nc("@action:button", "Connect")
  315. enabled: (base.selectedDevice && base.completeProperties && base.selectedDevice.clusterSize > 0) ? true : false
  316. onClicked: connectToPrinter()
  317. }
  318. }
  319. }
  320. }
  321. UM.Dialog
  322. {
  323. id: manualPrinterDialog
  324. property string printerKey
  325. property alias addressText: addressField.text
  326. title: catalog.i18nc("@title:window", "Printer Address")
  327. minimumWidth: 400 * screenScaleFactor
  328. minimumHeight: 130 * screenScaleFactor
  329. width: minimumWidth
  330. height: minimumHeight
  331. signal showDialog(string key, string address)
  332. onShowDialog:
  333. {
  334. printerKey = key;
  335. addressText = address;
  336. manualPrinterDialog.show();
  337. addressField.selectAll();
  338. addressField.focus = true;
  339. }
  340. Column {
  341. anchors.fill: parent
  342. spacing: UM.Theme.getSize("default_margin").height
  343. Label
  344. {
  345. text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.")
  346. width: parent.width
  347. wrapMode: Text.WordWrap
  348. renderType: Text.NativeRendering
  349. }
  350. TextField
  351. {
  352. id: addressField
  353. width: parent.width
  354. validator: RegExpValidator
  355. {
  356. regExp: /[a-zA-Z0-9\.\-\_]*/
  357. }
  358. onAccepted: btnOk.clicked()
  359. }
  360. }
  361. rightButtons: [
  362. Button {
  363. text: catalog.i18nc("@action:button","Cancel")
  364. onClicked:
  365. {
  366. manualPrinterDialog.reject()
  367. manualPrinterDialog.hide()
  368. }
  369. },
  370. Button {
  371. id: btnOk
  372. text: catalog.i18nc("@action:button", "OK")
  373. onClicked:
  374. {
  375. manager.setManualDevice(manualPrinterDialog.printerKey, manualPrinterDialog.addressText)
  376. manualPrinterDialog.hide()
  377. }
  378. enabled: manualPrinterDialog.addressText.trim() != ""
  379. isDefault: true
  380. }
  381. ]
  382. }
  383. }