PerObjectSettingsPanel.qml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. // Copyright (c) 2017 Ultimaker B.V.
  2. // Uranium is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 1.2
  5. import QtQuick.Controls.Styles 1.2
  6. import QtQuick.Window 2.2
  7. import UM 1.2 as UM
  8. import Cura 1.0 as Cura
  9. import ".."
  10. Item {
  11. id: base;
  12. UM.I18nCatalog { id: catalog; name: "cura"; }
  13. width: childrenRect.width;
  14. height: childrenRect.height;
  15. property var all_categories_except_support: [ "machine_settings", "resolution", "shell", "infill", "material", "speed",
  16. "travel", "cooling", "platform_adhesion", "dual", "meshfix", "blackmagic", "experimental"]
  17. Column
  18. {
  19. id: items
  20. anchors.top: parent.top;
  21. anchors.left: parent.left;
  22. spacing: UM.Theme.getSize("default_margin").height
  23. Row
  24. {
  25. spacing: UM.Theme.getSize("default_margin").width
  26. Label
  27. {
  28. text: catalog.i18nc("@label","Mesh Type")
  29. font: UM.Theme.getFont("default")
  30. color: UM.Theme.getColor("text")
  31. height: UM.Theme.getSize("setting").height
  32. verticalAlignment: Text.AlignVCenter
  33. }
  34. UM.SettingPropertyProvider
  35. {
  36. id: meshTypePropertyProvider
  37. containerStackId: Cura.MachineManager.activeMachineId
  38. watchedProperties: [ "enabled" ]
  39. }
  40. ComboBox
  41. {
  42. id: meshTypeSelection
  43. style: UM.Theme.styles.combobox
  44. onActivated: {
  45. UM.ActiveTool.setProperty("MeshType", model.get(index).type)
  46. }
  47. model: ListModel
  48. {
  49. id: meshTypeModel
  50. Component.onCompleted: meshTypeSelection.populateModel()
  51. }
  52. function populateModel()
  53. {
  54. meshTypeModel.append({
  55. type: "",
  56. text: catalog.i18nc("@label", "Normal model")
  57. });
  58. meshTypePropertyProvider.key = "support_mesh";
  59. if(meshTypePropertyProvider.properties.enabled == "True")
  60. {
  61. meshTypeModel.append({
  62. type: "support_mesh",
  63. text: catalog.i18nc("@label", "Print as support")
  64. });
  65. }
  66. meshTypePropertyProvider.key = "anti_overhang_mesh";
  67. if(meshTypePropertyProvider.properties.enabled == "True")
  68. {
  69. meshTypeModel.append({
  70. type: "anti_overhang_mesh",
  71. text: catalog.i18nc("@label", "Don't support overlap with other models")
  72. });
  73. }
  74. meshTypePropertyProvider.key = "cutting_mesh";
  75. if(meshTypePropertyProvider.properties.enabled == "True")
  76. {
  77. meshTypeModel.append({
  78. type: "cutting_mesh",
  79. text: catalog.i18nc("@label", "Modify settings for overlap with other models")
  80. });
  81. }
  82. meshTypePropertyProvider.key = "infill_mesh";
  83. if(meshTypePropertyProvider.properties.enabled == "True")
  84. {
  85. meshTypeModel.append({
  86. type: "infill_mesh",
  87. text: catalog.i18nc("@label", "Modify settings for infill of other models")
  88. });
  89. }
  90. meshTypeSelection.updateCurrentIndex();
  91. }
  92. function updateCurrentIndex()
  93. {
  94. var mesh_type = UM.ActiveTool.properties.getValue("MeshType");
  95. meshTypeSelection.currentIndex = -1;
  96. for(var index=0; index < meshTypeSelection.model.count; index++)
  97. {
  98. if(meshTypeSelection.model.get(index).type == mesh_type)
  99. {
  100. meshTypeSelection.currentIndex = index;
  101. return;
  102. }
  103. }
  104. meshTypeSelection.currentIndex = 0;
  105. }
  106. }
  107. Connections
  108. {
  109. target: Cura.MachineManager
  110. onGlobalContainerChanged:
  111. {
  112. meshTypeSelection.model.clear();
  113. meshTypeSelection.populateModel();
  114. }
  115. }
  116. Connections
  117. {
  118. target: UM.Selection
  119. onSelectionChanged: meshTypeSelection.updateCurrentIndex()
  120. }
  121. }
  122. Column
  123. {
  124. // This is to ensure that the panel is first increasing in size up to 200 and then shows a scrollbar.
  125. // It kinda looks ugly otherwise (big panel, no content on it)
  126. id: currentSettings
  127. property int maximumHeight: 200 * screenScaleFactor
  128. height: Math.min(contents.count * (UM.Theme.getSize("section").height + UM.Theme.getSize("default_lining").height), maximumHeight)
  129. visible: meshTypeSelection.model.get(meshTypeSelection.currentIndex).type != "anti_overhang_mesh"
  130. ScrollView
  131. {
  132. height: parent.height
  133. width: UM.Theme.getSize("setting").width + UM.Theme.getSize("default_margin").width
  134. style: UM.Theme.styles.scrollview
  135. ListView
  136. {
  137. id: contents
  138. spacing: UM.Theme.getSize("default_lining").height
  139. model: UM.SettingDefinitionsModel
  140. {
  141. id: addedSettingsModel;
  142. containerId: Cura.MachineManager.activeDefinitionId
  143. expanded: [ "*" ]
  144. filter:
  145. {
  146. if (printSequencePropertyProvider.properties.value == "one_at_a_time")
  147. {
  148. return {"settable_per_meshgroup": true};
  149. }
  150. return {"settable_per_mesh": true};
  151. }
  152. exclude:
  153. {
  154. var excluded_settings = [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ];
  155. if(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh")
  156. {
  157. excluded_settings = excluded_settings.concat(base.all_categories_except_support);
  158. }
  159. return excluded_settings;
  160. }
  161. visibilityHandler: Cura.PerObjectSettingVisibilityHandler
  162. {
  163. selectedObjectId: UM.ActiveTool.properties.getValue("SelectedObjectId")
  164. }
  165. }
  166. delegate: Row
  167. {
  168. spacing: - UM.Theme.getSize("default_margin").width
  169. Loader
  170. {
  171. id: settingLoader
  172. width: UM.Theme.getSize("setting").width
  173. height: UM.Theme.getSize("section").height
  174. property var definition: model
  175. property var settingDefinitionsModel: addedSettingsModel
  176. property var propertyProvider: provider
  177. property var globalPropertyProvider: inheritStackProvider
  178. property var externalResetHandler: false
  179. //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
  180. //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
  181. //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
  182. asynchronous: model.type != "enum" && model.type != "extruder"
  183. onLoaded: {
  184. settingLoader.item.showRevertButton = false
  185. settingLoader.item.showInheritButton = false
  186. settingLoader.item.showLinkedSettingIcon = false
  187. settingLoader.item.doDepthIndentation = false
  188. settingLoader.item.doQualityUserSettingEmphasis = false
  189. }
  190. sourceComponent:
  191. {
  192. switch(model.type)
  193. {
  194. case "int":
  195. return settingTextField
  196. case "[int]":
  197. return settingTextField
  198. case "float":
  199. return settingTextField
  200. case "enum":
  201. return settingComboBox
  202. case "extruder":
  203. return settingExtruder
  204. case "optional_extruder":
  205. return settingOptionalExtruder
  206. case "bool":
  207. return settingCheckBox
  208. case "str":
  209. return settingTextField
  210. case "category":
  211. return settingCategory
  212. default:
  213. return settingUnknown
  214. }
  215. }
  216. }
  217. Button
  218. {
  219. width: Math.round(UM.Theme.getSize("setting").height / 2)
  220. height: UM.Theme.getSize("setting").height
  221. onClicked: addedSettingsModel.setVisible(model.key, false)
  222. style: ButtonStyle
  223. {
  224. background: Item
  225. {
  226. UM.RecolorImage
  227. {
  228. anchors.verticalCenter: parent.verticalCenter
  229. width: parent.width
  230. height: width
  231. sourceSize.width: width
  232. sourceSize.height: width
  233. color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
  234. source: UM.Theme.getIcon("minus")
  235. }
  236. }
  237. }
  238. }
  239. // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events
  240. // so we bypass that to make a dedicated provider).
  241. UM.SettingPropertyProvider
  242. {
  243. id: provider
  244. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  245. key: model.key
  246. watchedProperties: [ "value", "enabled", "validationState" ]
  247. storeIndex: 0
  248. removeUnusedValue: false
  249. }
  250. UM.SettingPropertyProvider
  251. {
  252. id: inheritStackProvider
  253. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  254. key: model.key
  255. watchedProperties: [ "limit_to_extruder" ]
  256. }
  257. Connections
  258. {
  259. target: inheritStackProvider
  260. onPropertiesChanged:
  261. {
  262. provider.forcePropertiesChanged();
  263. }
  264. }
  265. Connections
  266. {
  267. target: UM.ActiveTool
  268. onPropertiesChanged:
  269. {
  270. // the values cannot be bound with UM.ActiveTool.properties.getValue() calls,
  271. // so here we connect to the signal and update the those values.
  272. if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
  273. {
  274. const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId");
  275. if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
  276. {
  277. addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId;
  278. }
  279. }
  280. if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
  281. {
  282. const containerId = UM.ActiveTool.properties.getValue("ContainerID");
  283. if (provider.containerStackId != containerId)
  284. {
  285. provider.containerStackId = containerId;
  286. }
  287. if (inheritStackProvider.containerStackId != containerId)
  288. {
  289. inheritStackProvider.containerStackId = containerId;
  290. }
  291. }
  292. }
  293. }
  294. }
  295. }
  296. }
  297. }
  298. Button
  299. {
  300. id: customiseSettingsButton;
  301. height: UM.Theme.getSize("setting_control").height;
  302. visible: currentSettings.visible
  303. text: catalog.i18nc("@action:button", "Select settings");
  304. style: ButtonStyle
  305. {
  306. background: Rectangle
  307. {
  308. width: control.width;
  309. height: control.height;
  310. border.width: UM.Theme.getSize("default_lining").width;
  311. border.color: control.pressed ? UM.Theme.getColor("action_button_active_border") :
  312. control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
  313. color: control.pressed ? UM.Theme.getColor("action_button_active") :
  314. control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
  315. }
  316. label: Label
  317. {
  318. text: control.text;
  319. color: UM.Theme.getColor("setting_control_text");
  320. font: UM.Theme.getFont("default")
  321. anchors.centerIn: parent
  322. }
  323. }
  324. onClicked:
  325. {
  326. settingPickDialog.visible = true;
  327. if (meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh")
  328. {
  329. settingPickDialog.additional_excluded_settings = base.all_categories_except_support;
  330. }
  331. else
  332. {
  333. settingPickDialog.additional_excluded_settings = []
  334. }
  335. }
  336. }
  337. }
  338. UM.Dialog {
  339. id: settingPickDialog
  340. title: catalog.i18nc("@title:window", "Select Settings to Customize for this model")
  341. width: screenScaleFactor * 360
  342. property var additional_excluded_settings
  343. onVisibilityChanged:
  344. {
  345. // force updating the model to sync it with addedSettingsModel
  346. if(visible)
  347. {
  348. // Set skip setting, it will prevent from resetting selected mesh_type
  349. contents.model.visibilityHandler.addSkipResetSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type)
  350. listview.model.forceUpdate()
  351. updateFilter()
  352. }
  353. }
  354. function updateFilter()
  355. {
  356. var new_filter = {};
  357. if (printSequencePropertyProvider.properties.value == "one_at_a_time")
  358. {
  359. new_filter["settable_per_meshgroup"] = true;
  360. }
  361. else
  362. {
  363. new_filter["settable_per_mesh"] = true;
  364. }
  365. if(filterInput.text != "")
  366. {
  367. new_filter["i18n_label"] = "*" + filterInput.text;
  368. }
  369. listview.model.filter = new_filter;
  370. }
  371. TextField {
  372. id: filterInput
  373. anchors {
  374. top: parent.top
  375. left: parent.left
  376. right: toggleShowAll.left
  377. rightMargin: UM.Theme.getSize("default_margin").width
  378. }
  379. placeholderText: catalog.i18nc("@label:textbox", "Filter...");
  380. onTextChanged: settingPickDialog.updateFilter()
  381. }
  382. CheckBox
  383. {
  384. id: toggleShowAll
  385. anchors {
  386. top: parent.top
  387. right: parent.right
  388. }
  389. text: catalog.i18nc("@label:checkbox", "Show all")
  390. checked: listview.model.showAll
  391. onClicked:
  392. {
  393. listview.model.showAll = checked;
  394. }
  395. }
  396. ScrollView
  397. {
  398. id: scrollView
  399. anchors
  400. {
  401. top: filterInput.bottom;
  402. left: parent.left;
  403. right: parent.right;
  404. bottom: parent.bottom;
  405. }
  406. ListView
  407. {
  408. id:listview
  409. model: UM.SettingDefinitionsModel
  410. {
  411. id: definitionsModel;
  412. containerId: Cura.MachineManager.activeDefinitionId
  413. visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
  414. expanded: [ "*" ]
  415. exclude:
  416. {
  417. var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ];
  418. excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings);
  419. return excluded_settings;
  420. }
  421. }
  422. delegate:Loader
  423. {
  424. id: loader
  425. width: parent.width
  426. height: model.type != undefined ? UM.Theme.getSize("section").height : 0;
  427. property var definition: model
  428. property var settingDefinitionsModel: definitionsModel
  429. asynchronous: true
  430. source:
  431. {
  432. switch(model.type)
  433. {
  434. case "category":
  435. return "PerObjectCategory.qml"
  436. default:
  437. return "PerObjectItem.qml"
  438. }
  439. }
  440. }
  441. Component.onCompleted: settingPickDialog.updateFilter()
  442. }
  443. }
  444. rightButtons: [
  445. Button {
  446. text: catalog.i18nc("@action:button", "Close");
  447. onClicked: {
  448. settingPickDialog.visible = false;
  449. }
  450. }
  451. ]
  452. }
  453. UM.SettingPropertyProvider
  454. {
  455. id: machineExtruderCount
  456. containerStackId: Cura.MachineManager.activeMachineId
  457. key: "machine_extruder_count"
  458. watchedProperties: [ "value" ]
  459. storeIndex: 0
  460. }
  461. UM.SettingPropertyProvider
  462. {
  463. id: printSequencePropertyProvider
  464. containerStackId: Cura.MachineManager.activeMachineId
  465. key: "print_sequence"
  466. watchedProperties: [ "value" ]
  467. storeIndex: 0
  468. }
  469. SystemPalette { id: palette; }
  470. Component
  471. {
  472. id: settingTextField;
  473. Cura.SettingTextField { }
  474. }
  475. Component
  476. {
  477. id: settingComboBox;
  478. Cura.SettingComboBox { }
  479. }
  480. Component
  481. {
  482. id: settingExtruder;
  483. Cura.SettingExtruder { }
  484. }
  485. Component
  486. {
  487. id: settingOptionalExtruder
  488. Cura.SettingOptionalExtruder { }
  489. }
  490. Component
  491. {
  492. id: settingCheckBox;
  493. Cura.SettingCheckBox { }
  494. }
  495. Component
  496. {
  497. id: settingCategory;
  498. Cura.SettingCategory { }
  499. }
  500. Component
  501. {
  502. id: settingUnknown;
  503. Cura.SettingUnknown { }
  504. }
  505. }