SaveButton.qml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. // Copyright (c) 2018 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 1.1
  5. import QtQuick.Controls.Styles 1.1
  6. import QtQuick.Layouts 1.1
  7. import UM 1.1 as UM
  8. Item {
  9. id: base;
  10. UM.I18nCatalog { id: catalog; name:"cura"}
  11. property real progress: UM.Backend.progress
  12. property int backendState: UM.Backend.state
  13. property bool activity: CuraApplication.platformActivity
  14. property alias buttonRowWidth: saveRow.width
  15. property string fileBaseName
  16. property string statusText:
  17. {
  18. if(!activity)
  19. {
  20. return catalog.i18nc("@label:PrintjobStatus", "Please load a 3D model");
  21. }
  22. if (base.backendState == "undefined") {
  23. return ""
  24. }
  25. switch(base.backendState)
  26. {
  27. case 1:
  28. return catalog.i18nc("@label:PrintjobStatus", "Ready to slice");
  29. case 2:
  30. return catalog.i18nc("@label:PrintjobStatus", "Slicing...");
  31. case 3:
  32. return catalog.i18nc("@label:PrintjobStatus %1 is target operation","Ready to %1").arg(UM.OutputDeviceManager.activeDeviceShortDescription);
  33. case 4:
  34. return catalog.i18nc("@label:PrintjobStatus", "Unable to Slice");
  35. case 5:
  36. return catalog.i18nc("@label:PrintjobStatus", "Slicing unavailable");
  37. default:
  38. return "";
  39. }
  40. }
  41. function sliceOrStopSlicing() {
  42. try {
  43. if ([1, 5].indexOf(base.backendState) != -1) {
  44. CuraApplication.backend.forceSlice();
  45. } else {
  46. CuraApplication.backend.stopSlicing();
  47. }
  48. } catch (e) {
  49. console.log('Could not start or stop slicing', e)
  50. }
  51. }
  52. Label {
  53. id: statusLabel
  54. width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width
  55. anchors.top: parent.top
  56. anchors.left: parent.left
  57. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  58. color: UM.Theme.getColor("text")
  59. font: UM.Theme.getFont("default_bold")
  60. text: statusText;
  61. }
  62. Rectangle {
  63. id: progressBar
  64. width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width
  65. height: UM.Theme.getSize("progressbar").height
  66. anchors.top: statusLabel.bottom
  67. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 4)
  68. anchors.left: parent.left
  69. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  70. radius: UM.Theme.getSize("progressbar_radius").width
  71. color: UM.Theme.getColor("progressbar_background")
  72. Rectangle {
  73. width: Math.max(parent.width * base.progress)
  74. height: parent.height
  75. color: UM.Theme.getColor("progressbar_control")
  76. radius: UM.Theme.getSize("progressbar_radius").width
  77. visible: (base.backendState != "undefined" && base.backendState == 2) ? true : false
  78. }
  79. }
  80. // Shortcut for "save as/print/..."
  81. Action {
  82. shortcut: "Ctrl+P"
  83. onTriggered:
  84. {
  85. // only work when the button is enabled
  86. if (saveToButton.enabled) {
  87. saveToButton.clicked();
  88. }
  89. // prepare button
  90. if (prepareButton.enabled) {
  91. sliceOrStopSlicing();
  92. }
  93. }
  94. }
  95. Item {
  96. id: saveRow
  97. width: {
  98. // using childrenRect.width directly causes a binding loop, because setting the width affects the childrenRect
  99. var children_width = UM.Theme.getSize("default_margin").width;
  100. for (var index in children)
  101. {
  102. var child = children[index];
  103. if(child.visible)
  104. {
  105. children_width += child.width + child.anchors.rightMargin;
  106. }
  107. }
  108. return Math.min(children_width, base.width - UM.Theme.getSize("sidebar_margin").width);
  109. }
  110. height: saveToButton.height
  111. anchors.bottom: parent.bottom
  112. anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height
  113. anchors.right: parent.right
  114. clip: true
  115. Row {
  116. id: additionalComponentsRow
  117. anchors.top: parent.top
  118. anchors.right: saveToButton.visible ? saveToButton.left : (prepareButton.visible ? prepareButton.left : parent.right)
  119. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  120. spacing: UM.Theme.getSize("default_margin").width
  121. }
  122. Component.onCompleted: {
  123. saveRow.addAdditionalComponents("saveButton")
  124. }
  125. Connections {
  126. target: CuraApplication
  127. onAdditionalComponentsChanged: saveRow.addAdditionalComponents("saveButton")
  128. }
  129. function addAdditionalComponents (areaId) {
  130. if(areaId == "saveButton") {
  131. for (var component in CuraApplication.additionalComponents["saveButton"]) {
  132. CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
  133. }
  134. }
  135. }
  136. Connections {
  137. target: UM.Preferences
  138. onPreferenceChanged:
  139. {
  140. var autoSlice = UM.Preferences.getValue("general/auto_slice");
  141. prepareButton.autoSlice = autoSlice;
  142. saveToButton.autoSlice = autoSlice;
  143. }
  144. }
  145. // Prepare button, only shows if auto_slice is off
  146. Button {
  147. id: prepareButton
  148. tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process")
  149. // 1 = not started, 2 = Processing
  150. enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity
  151. visible: base.backendState != "undefined" && !autoSlice && ([1, 2, 4].indexOf(base.backendState) != -1) && base.activity
  152. property bool autoSlice
  153. height: UM.Theme.getSize("save_button_save_to_button").height
  154. anchors.top: parent.top
  155. anchors.right: parent.right
  156. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  157. // 1 = not started, 4 = error, 5 = disabled
  158. text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel")
  159. onClicked:
  160. {
  161. sliceOrStopSlicing();
  162. }
  163. style: ButtonStyle {
  164. background: Rectangle
  165. {
  166. border.width: UM.Theme.getSize("default_lining").width
  167. border.color:
  168. {
  169. if(!control.enabled)
  170. return UM.Theme.getColor("action_button_disabled_border");
  171. else if(control.pressed)
  172. return UM.Theme.getColor("action_button_active_border");
  173. else if(control.hovered)
  174. return UM.Theme.getColor("action_button_hovered_border");
  175. else
  176. return UM.Theme.getColor("action_button_border");
  177. }
  178. color:
  179. {
  180. if(!control.enabled)
  181. return UM.Theme.getColor("action_button_disabled");
  182. else if(control.pressed)
  183. return UM.Theme.getColor("action_button_active");
  184. else if(control.hovered)
  185. return UM.Theme.getColor("action_button_hovered");
  186. else
  187. return UM.Theme.getColor("action_button");
  188. }
  189. Behavior on color { ColorAnimation { duration: 50; } }
  190. implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("sidebar_margin").width * 2)
  191. Label {
  192. id: actualLabel
  193. anchors.centerIn: parent
  194. color:
  195. {
  196. if(!control.enabled)
  197. return UM.Theme.getColor("action_button_disabled_text");
  198. else if(control.pressed)
  199. return UM.Theme.getColor("action_button_active_text");
  200. else if(control.hovered)
  201. return UM.Theme.getColor("action_button_hovered_text");
  202. else
  203. return UM.Theme.getColor("action_button_text");
  204. }
  205. font: UM.Theme.getFont("action_button")
  206. text: control.text;
  207. }
  208. }
  209. label: Item { }
  210. }
  211. }
  212. Button {
  213. id: saveToButton
  214. tooltip: UM.OutputDeviceManager.activeDeviceDescription;
  215. // 3 = done, 5 = disabled
  216. enabled: base.backendState != "undefined" && (base.backendState == 3 || base.backendState == 5) && base.activity == true
  217. visible: base.backendState != "undefined" && autoSlice || ((base.backendState == 3 || base.backendState == 5) && base.activity == true)
  218. property bool autoSlice
  219. height: UM.Theme.getSize("save_button_save_to_button").height
  220. anchors.top: parent.top
  221. anchors.right: deviceSelectionMenu.visible ? deviceSelectionMenu.left : parent.right
  222. anchors.rightMargin: deviceSelectionMenu.visible ? -3 * UM.Theme.getSize("default_lining").width : UM.Theme.getSize("sidebar_margin").width
  223. text: UM.OutputDeviceManager.activeDeviceShortDescription
  224. onClicked:
  225. {
  226. UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, { "filter_by_machine": true, "preferred_mimetype":Printer.preferredOutputMimetype })
  227. }
  228. style: ButtonStyle {
  229. background: Rectangle
  230. {
  231. border.width: UM.Theme.getSize("default_lining").width
  232. border.color:
  233. {
  234. if(!control.enabled)
  235. return UM.Theme.getColor("action_button_disabled_border");
  236. else if(control.pressed)
  237. return UM.Theme.getColor("print_button_ready_pressed_border");
  238. else if(control.hovered)
  239. return UM.Theme.getColor("print_button_ready_hovered_border");
  240. else
  241. return UM.Theme.getColor("print_button_ready_border");
  242. }
  243. color:
  244. {
  245. if(!control.enabled)
  246. return UM.Theme.getColor("action_button_disabled");
  247. else if(control.pressed)
  248. return UM.Theme.getColor("print_button_ready_pressed");
  249. else if(control.hovered)
  250. return UM.Theme.getColor("print_button_ready_hovered");
  251. else
  252. return UM.Theme.getColor("print_button_ready");
  253. }
  254. Behavior on color { ColorAnimation { duration: 50; } }
  255. implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("sidebar_margin").width * 2)
  256. Label {
  257. id: actualLabel
  258. anchors.centerIn: parent
  259. color:
  260. {
  261. if(!control.enabled)
  262. return UM.Theme.getColor("action_button_disabled_text");
  263. else if(control.pressed)
  264. return UM.Theme.getColor("print_button_ready_text");
  265. else if(control.hovered)
  266. return UM.Theme.getColor("print_button_ready_text");
  267. else
  268. return UM.Theme.getColor("print_button_ready_text");
  269. }
  270. font: UM.Theme.getFont("action_button")
  271. text: control.text;
  272. }
  273. }
  274. label: Item { }
  275. }
  276. }
  277. Button {
  278. id: deviceSelectionMenu
  279. tooltip: catalog.i18nc("@info:tooltip","Select the active output device");
  280. anchors.top: parent.top
  281. anchors.right: parent.right
  282. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  283. width: UM.Theme.getSize("save_button_save_to_button").height
  284. height: UM.Theme.getSize("save_button_save_to_button").height
  285. // 3 = Done, 5 = Disabled
  286. enabled: base.backendState != "undefined" && (base.backendState == 3 || base.backendState == 5) && base.activity == true
  287. visible: base.backendState != "undefined" && (devicesModel.deviceCount > 1) && (base.backendState == 3 || base.backendState == 5) && base.activity == true
  288. style: ButtonStyle {
  289. background: Rectangle {
  290. id: deviceSelectionIcon
  291. border.width: UM.Theme.getSize("default_lining").width
  292. border.color:
  293. {
  294. if(!control.enabled)
  295. return UM.Theme.getColor("action_button_disabled_border");
  296. else if(control.pressed)
  297. return UM.Theme.getColor("print_button_ready_pressed_border");
  298. else if(control.hovered)
  299. return UM.Theme.getColor("print_button_ready_hovered_border");
  300. else
  301. return UM.Theme.getColor("print_button_ready_border");
  302. }
  303. color:
  304. {
  305. if(!control.enabled)
  306. return UM.Theme.getColor("action_button_disabled");
  307. else if(control.pressed)
  308. return UM.Theme.getColor("print_button_ready_pressed");
  309. else if(control.hovered)
  310. return UM.Theme.getColor("print_button_ready_hovered");
  311. else
  312. return UM.Theme.getColor("print_button_ready");
  313. }
  314. Behavior on color { ColorAnimation { duration: 50; } }
  315. anchors.left: parent.left
  316. anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2);
  317. width: parent.height
  318. height: parent.height
  319. UM.RecolorImage {
  320. anchors.verticalCenter: parent.verticalCenter
  321. anchors.horizontalCenter: parent.horizontalCenter
  322. width: UM.Theme.getSize("standard_arrow").width
  323. height: UM.Theme.getSize("standard_arrow").height
  324. sourceSize.width: width
  325. sourceSize.height: height
  326. color:
  327. {
  328. if(!control.enabled)
  329. return UM.Theme.getColor("action_button_disabled_text");
  330. else if(control.pressed)
  331. return UM.Theme.getColor("print_button_ready_text");
  332. else if(control.hovered)
  333. return UM.Theme.getColor("print_button_ready_text");
  334. else
  335. return UM.Theme.getColor("print_button_ready_text");
  336. }
  337. source: UM.Theme.getIcon("arrow_bottom");
  338. }
  339. }
  340. label: Label{ }
  341. }
  342. menu: Menu {
  343. id: devicesMenu;
  344. Instantiator {
  345. model: devicesModel;
  346. MenuItem {
  347. text: model.description
  348. checkable: true;
  349. checked: model.id == UM.OutputDeviceManager.activeDevice;
  350. exclusiveGroup: devicesMenuGroup;
  351. onTriggered: {
  352. UM.OutputDeviceManager.setActiveDevice(model.id);
  353. }
  354. }
  355. onObjectAdded: devicesMenu.insertItem(index, object)
  356. onObjectRemoved: devicesMenu.removeItem(object)
  357. }
  358. ExclusiveGroup { id: devicesMenuGroup; }
  359. }
  360. }
  361. UM.OutputDevicesModel { id: devicesModel; }
  362. }
  363. }