ProfilesPage.qml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. //Copyright (c) 2022 Ultimaker B.V.
  2. //Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 2.15
  5. import QtQuick.Layouts 1.3
  6. import QtQuick.Dialogs 1.2
  7. import UM 1.5 as UM
  8. import Cura 1.6 as Cura
  9. UM.ManagementPage
  10. {
  11. id: base
  12. property var extrudersModel: CuraApplication.getExtrudersModel()
  13. property var qualityManagementModel: CuraApplication.getQualityManagementModel()
  14. scrollviewCaption: catalog.i18nc("@label", "Profiles compatible with active printer:") + "<b>" + Cura.MachineManager.activeMachine.name + "</b>"
  15. onHamburgeButtonClicked: menu.popup(content_item, content_item.width - menu.width, hamburger_button.height)
  16. property var hasCurrentItem: base.currentItem != null
  17. sectionRole: "section_name"
  18. property var currentItem:
  19. {
  20. var current_index = objectList.currentIndex;
  21. return (current_index == -1) ? null : base.qualityManagementModel.getItem(current_index);
  22. }
  23. property var currentItemName: hasCurrentItem ? base.currentItem.name : ""
  24. property var currentItemDisplayName: hasCurrentItem ? base.qualityManagementModel.getQualityItemDisplayName(base.currentItem) : ""
  25. property var isCurrentItemActivated:
  26. {
  27. if (!base.currentItem)
  28. {
  29. return false;
  30. }
  31. if (base.currentItem.is_read_only)
  32. {
  33. return (base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName) && (base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory);
  34. }
  35. else
  36. {
  37. return base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName;
  38. }
  39. }
  40. property var canCreateProfile:
  41. {
  42. return isCurrentItemActivated && Cura.MachineManager.hasUserSettings;
  43. }
  44. model: qualityManagementModel
  45. buttons: [
  46. Cura.SecondaryButton
  47. {
  48. text: catalog.i18nc("@action:button", "Import")
  49. onClicked:importDialog.open()
  50. },
  51. Cura.SecondaryButton
  52. {
  53. id: createMenuButton
  54. text: catalog.i18nc("@action:button", "Create new")
  55. enabled: !Cura.MachineManager.stacksHaveErrors
  56. visible: base.canCreateProfile
  57. onClicked:
  58. {
  59. createQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name)
  60. createQualityDialog.open()
  61. createQualityDialog.selectText()
  62. }
  63. }
  64. ]
  65. // Click create profile from ... in Profile context menu
  66. signal createProfile()
  67. onCreateProfile:
  68. {
  69. createQualityDialog.object = Cura.ContainerManager.makeUniqueName(Cura.MachineManager.activeQualityOrQualityChangesName);
  70. createQualityDialog.open();
  71. createQualityDialog.selectText();
  72. }
  73. property string newQualityNameToSelect: ""
  74. property bool toActivateNewQuality: false
  75. Item
  76. {
  77. id: content_item
  78. anchors.fill: parent
  79. // This connection makes sure that we will switch to the correct quality after the model gets updated
  80. Connections
  81. {
  82. target: base.qualityManagementModel
  83. function onItemsChanged()
  84. {
  85. var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name;
  86. if (newQualityNameToSelect != "")
  87. {
  88. toSelectItemName = newQualityNameToSelect;
  89. }
  90. var newIdx = -1; // Default to nothing if nothing can be found
  91. if (toSelectItemName != "")
  92. {
  93. // Select the required quality name if given
  94. for (var idx = 0; idx < base.qualityManagementModel.count; ++idx)
  95. {
  96. var item = base.qualityManagementModel.getItem(idx);
  97. if (item && item.name == toSelectItemName)
  98. {
  99. // Switch to the newly created profile if needed
  100. newIdx = idx;
  101. if (base.toActivateNewQuality)
  102. {
  103. // Activate this custom quality if required
  104. if(item.quality_changes_group)
  105. {
  106. Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group);
  107. }
  108. }
  109. break;
  110. }
  111. }
  112. }
  113. objectList.currentIndex = newIdx;
  114. // Reset states
  115. base.newQualityNameToSelect = "";
  116. base.toActivateNewQuality = false;
  117. }
  118. }
  119. Cura.MessageDialog
  120. {
  121. id: messageDialog
  122. standardButtons: Dialog.Ok
  123. }
  124. // Dialog to request a name when creating a new profile
  125. Cura.RenameDialog
  126. {
  127. id: createQualityDialog
  128. title: catalog.i18nc("@title:window", "Create Profile")
  129. object: "<new name>"
  130. explanation: catalog.i18nc("@info", "Please provide a name for this profile.")
  131. onAccepted:
  132. {
  133. base.newQualityNameToSelect = newName; // We want to switch to the new profile once it's created
  134. base.toActivateNewQuality = true;
  135. base.qualityManagementModel.createQualityChanges(newName);
  136. }
  137. }
  138. Cura.Menu
  139. {
  140. id: menu
  141. Cura.MenuItem
  142. {
  143. text: catalog.i18nc("@action:button", "Activate")
  144. enabled: !isCurrentItemActivated && base.currentItem
  145. onTriggered:
  146. {
  147. if(base.currentItem.is_read_only)
  148. {
  149. Cura.IntentManager.selectIntent(base.currentItem.intent_category, base.currentItem.quality_type)
  150. }
  151. else
  152. {
  153. Cura.MachineManager.setQualityChangesGroup(base.currentItem.quality_changes_group)
  154. }
  155. }
  156. }
  157. Cura.MenuItem
  158. {
  159. text: catalog.i18nc("@action:button", "Remove")
  160. enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated
  161. onTriggered:
  162. {
  163. forceActiveFocus()
  164. confirmRemoveQualityDialog.open()
  165. }
  166. }
  167. Cura.MenuItem
  168. {
  169. text: catalog.i18nc("@action:button", "Rename")
  170. enabled: base.hasCurrentItem && !base.currentItem.is_read_only
  171. onTriggered:
  172. {
  173. renameQualityDialog.object = base.currentItem.name
  174. renameQualityDialog.open()
  175. renameQualityDialog.selectText()
  176. }
  177. }
  178. Cura.MenuItem
  179. {
  180. text: catalog.i18nc("@action:button", "Export")
  181. enabled: base.hasCurrentItem && !base.currentItem.is_read_only
  182. onTriggered: exportDialog.open()
  183. }
  184. }
  185. // Dialog for exporting a quality profile
  186. FileDialog
  187. {
  188. id: exportDialog
  189. title: catalog.i18nc("@title:window", "Export Profile")
  190. selectExisting: false
  191. nameFilters: base.qualityManagementModel.getFileNameFilters("profile_writer")
  192. folder: CuraApplication.getDefaultPath("dialog_profile_path")
  193. onAccepted:
  194. {
  195. var result = Cura.ContainerManager.exportQualityChangesGroup(base.currentItem.quality_changes_group,
  196. fileUrl, selectedNameFilter);
  197. if (result && result.status == "error")
  198. {
  199. messageDialog.title = catalog.i18nc("@title:window", "Export Profile")
  200. messageDialog.text = result.message;
  201. messageDialog.open();
  202. }
  203. // else pop-up Message thing from python code
  204. CuraApplication.setDefaultPath("dialog_profile_path", folder);
  205. }
  206. }
  207. // Dialog to request a name when duplicating a new profile
  208. Cura.RenameDialog
  209. {
  210. id: duplicateQualityDialog
  211. title: catalog.i18nc("@title:window", "Duplicate Profile")
  212. object: "<new name>"
  213. onAccepted:
  214. {
  215. base.qualityManagementModel.duplicateQualityChanges(newName, base.currentItem);
  216. }
  217. }
  218. // Confirmation dialog for removing a profile
  219. Cura.MessageDialog
  220. {
  221. id: confirmRemoveQualityDialog
  222. title: catalog.i18nc("@title:window", "Confirm Remove")
  223. text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItemName)
  224. standardButtons: StandardButton.Yes | StandardButton.No
  225. modal: true
  226. onAccepted:
  227. {
  228. base.qualityManagementModel.removeQualityChangesGroup(base.currentItem.quality_changes_group);
  229. // reset current item to the first if available
  230. qualityListView.currentIndex = -1; // Reset selection.
  231. }
  232. }
  233. // Dialog to rename a quality profile
  234. Cura.RenameDialog
  235. {
  236. id: renameQualityDialog
  237. title: catalog.i18nc("@title:window", "Rename Profile")
  238. object: "<new name>"
  239. onAccepted:
  240. {
  241. var actualNewName = base.qualityManagementModel.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName);
  242. base.newQualityNameToSelect = actualNewName; // Select the new name after the model gets updated
  243. }
  244. }
  245. // Dialog for importing a quality profile
  246. FileDialog
  247. {
  248. id: importDialog
  249. title: catalog.i18nc("@title:window", "Import Profile")
  250. selectExisting: true
  251. nameFilters: base.qualityManagementModel.getFileNameFilters("profile_reader")
  252. folder: CuraApplication.getDefaultPath("dialog_profile_path")
  253. onAccepted:
  254. {
  255. var result = Cura.ContainerManager.importProfile(fileUrl);
  256. messageDialog.title = catalog.i18nc("@title:window", "Import Profile")
  257. messageDialog.text = result.message;
  258. messageDialog.open();
  259. CuraApplication.setDefaultPath("dialog_profile_path", folder);
  260. }
  261. }
  262. SystemPalette
  263. {
  264. id: palette
  265. }
  266. Column
  267. {
  268. id: detailsPanelHeaderColumn
  269. anchors
  270. {
  271. left: parent.left
  272. right: parent.right
  273. top: parent.top
  274. }
  275. spacing: UM.Theme.getSize("default_margin").height
  276. visible: base.currentItem != null
  277. UM.Label
  278. {
  279. anchors.left: parent.left
  280. anchors.right: parent.right
  281. text: base.currentItemDisplayName
  282. font: UM.Theme.getFont("large_bold")
  283. elide: Text.ElideRight
  284. }
  285. Flow
  286. {
  287. id: currentSettingsActions
  288. width: parent.width
  289. visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName && base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory
  290. Cura.SecondaryButton
  291. {
  292. text: catalog.i18nc("@action:button", "Update profile with current settings/overrides")
  293. enabled: Cura.MachineManager.hasUserSettings && objectList.currentIndex && !objectList.currentIndex.is_read_only
  294. onClicked: Cura.ContainerManager.updateQualityChanges()
  295. }
  296. Cura.SecondaryButton
  297. {
  298. text: catalog.i18nc("@action:button", "Discard current changes");
  299. enabled: Cura.MachineManager.hasUserSettings
  300. onClicked: Cura.ContainerManager.clearUserContainers();
  301. }
  302. }
  303. UM.Label
  304. {
  305. id: defaultsMessage
  306. visible: false
  307. text: catalog.i18nc("@action:label", "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below.")
  308. width: parent.width
  309. }
  310. UM.Label
  311. {
  312. id: noCurrentSettingsMessage
  313. visible: base.isCurrentItemActivated && !Cura.MachineManager.hasUserSettings
  314. text: catalog.i18nc("@action:label", "Your current settings match the selected profile.")
  315. width: parent.width
  316. }
  317. UM.TabRow
  318. {
  319. id: profileExtruderTabs
  320. UM.TabRowButton //One extra tab for the global settings.
  321. {
  322. text: catalog.i18nc("@title:tab", "Global Settings")
  323. }
  324. Repeater
  325. {
  326. model: base.extrudersModel
  327. UM.TabRowButton
  328. {
  329. text: model.name
  330. }
  331. }
  332. }
  333. }
  334. Rectangle
  335. {
  336. color: UM.Theme.getColor("main_background")
  337. anchors
  338. {
  339. top: detailsPanelHeaderColumn.bottom
  340. topMargin: -UM.Theme.getSize("default_lining").width
  341. left: parent.left
  342. right: parent.right
  343. bottom: parent.bottom
  344. }
  345. border.width: UM.Theme.getSize("default_lining").width
  346. border.color: UM.Theme.getColor("thick_lining")
  347. visible: base.hasCurrentItem
  348. }
  349. Cura.ProfileOverview
  350. {
  351. anchors
  352. {
  353. top: detailsPanelHeaderColumn.bottom
  354. margins: UM.Theme.getSize("default_margin").height
  355. left: parent.left
  356. right: parent.right
  357. bottom: parent.bottom
  358. }
  359. visible: detailsPanelHeaderColumn.visible
  360. qualityItem: base.currentItem
  361. extruderPosition: profileExtruderTabs.currentIndex - 1
  362. }
  363. }
  364. }