SaveButton.qml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  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. forceActiveFocus();
  227. UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, { "filter_by_machine": true, "preferred_mimetype":Printer.preferredOutputMimetype });
  228. }
  229. style: ButtonStyle {
  230. background: Rectangle
  231. {
  232. border.width: UM.Theme.getSize("default_lining").width
  233. border.color:
  234. {
  235. if(!control.enabled)
  236. return UM.Theme.getColor("action_button_disabled_border");
  237. else if(control.pressed)
  238. return UM.Theme.getColor("print_button_ready_pressed_border");
  239. else if(control.hovered)
  240. return UM.Theme.getColor("print_button_ready_hovered_border");
  241. else
  242. return UM.Theme.getColor("print_button_ready_border");
  243. }
  244. color:
  245. {
  246. if(!control.enabled)
  247. return UM.Theme.getColor("action_button_disabled");
  248. else if(control.pressed)
  249. return UM.Theme.getColor("print_button_ready_pressed");
  250. else if(control.hovered)
  251. return UM.Theme.getColor("print_button_ready_hovered");
  252. else
  253. return UM.Theme.getColor("print_button_ready");
  254. }
  255. Behavior on color { ColorAnimation { duration: 50; } }
  256. implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("sidebar_margin").width * 2)
  257. Label {
  258. id: actualLabel
  259. anchors.centerIn: parent
  260. color:
  261. {
  262. if(!control.enabled)
  263. return UM.Theme.getColor("action_button_disabled_text");
  264. else if(control.pressed)
  265. return UM.Theme.getColor("print_button_ready_text");
  266. else if(control.hovered)
  267. return UM.Theme.getColor("print_button_ready_text");
  268. else
  269. return UM.Theme.getColor("print_button_ready_text");
  270. }
  271. font: UM.Theme.getFont("action_button")
  272. text: control.text;
  273. }
  274. }
  275. label: Item { }
  276. }
  277. }
  278. Button {
  279. id: deviceSelectionMenu
  280. tooltip: catalog.i18nc("@info:tooltip","Select the active output device");
  281. anchors.top: parent.top
  282. anchors.right: parent.right
  283. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  284. width: UM.Theme.getSize("save_button_save_to_button").height
  285. height: UM.Theme.getSize("save_button_save_to_button").height
  286. // 3 = Done, 5 = Disabled
  287. enabled: base.backendState != "undefined" && (base.backendState == 3 || base.backendState == 5) && base.activity == true
  288. visible: base.backendState != "undefined" && (devicesModel.deviceCount > 1) && (base.backendState == 3 || base.backendState == 5) && base.activity == true
  289. style: ButtonStyle {
  290. background: Rectangle {
  291. id: deviceSelectionIcon
  292. border.width: UM.Theme.getSize("default_lining").width
  293. border.color:
  294. {
  295. if(!control.enabled)
  296. return UM.Theme.getColor("action_button_disabled_border");
  297. else if(control.pressed)
  298. return UM.Theme.getColor("print_button_ready_pressed_border");
  299. else if(control.hovered)
  300. return UM.Theme.getColor("print_button_ready_hovered_border");
  301. else
  302. return UM.Theme.getColor("print_button_ready_border");
  303. }
  304. color:
  305. {
  306. if(!control.enabled)
  307. return UM.Theme.getColor("action_button_disabled");
  308. else if(control.pressed)
  309. return UM.Theme.getColor("print_button_ready_pressed");
  310. else if(control.hovered)
  311. return UM.Theme.getColor("print_button_ready_hovered");
  312. else
  313. return UM.Theme.getColor("print_button_ready");
  314. }
  315. Behavior on color { ColorAnimation { duration: 50; } }
  316. anchors.left: parent.left
  317. anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2);
  318. width: parent.height
  319. height: parent.height
  320. UM.RecolorImage {
  321. anchors.verticalCenter: parent.verticalCenter
  322. anchors.horizontalCenter: parent.horizontalCenter
  323. width: UM.Theme.getSize("standard_arrow").width
  324. height: UM.Theme.getSize("standard_arrow").height
  325. sourceSize.width: width
  326. sourceSize.height: height
  327. color:
  328. {
  329. if(!control.enabled)
  330. return UM.Theme.getColor("action_button_disabled_text");
  331. else if(control.pressed)
  332. return UM.Theme.getColor("print_button_ready_text");
  333. else if(control.hovered)
  334. return UM.Theme.getColor("print_button_ready_text");
  335. else
  336. return UM.Theme.getColor("print_button_ready_text");
  337. }
  338. source: UM.Theme.getIcon("arrow_bottom");
  339. }
  340. }
  341. label: Label{ }
  342. }
  343. menu: Menu {
  344. id: devicesMenu;
  345. Instantiator {
  346. model: devicesModel;
  347. MenuItem {
  348. text: model.description
  349. checkable: true;
  350. checked: model.id == UM.OutputDeviceManager.activeDevice;
  351. exclusiveGroup: devicesMenuGroup;
  352. onTriggered: {
  353. UM.OutputDeviceManager.setActiveDevice(model.id);
  354. }
  355. }
  356. onObjectAdded: devicesMenu.insertItem(index, object)
  357. onObjectRemoved: devicesMenu.removeItem(object)
  358. }
  359. ExclusiveGroup { id: devicesMenuGroup; }
  360. }
  361. }
  362. UM.OutputDevicesModel { id: devicesModel; }
  363. }
  364. }