SaveButton.qml 17 KB

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