PerObjectSettingsPanel.qml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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. containerStack: Cura.MachineManager.activeMachine
  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. // For some reason the model object is updated after removing him from the memory and
  166. // it happens only on Windows. For this reason, set the destroyed value manually.
  167. Component.onDestruction: {
  168. setDestroyed(true);
  169. }
  170. }
  171. delegate: Row
  172. {
  173. spacing: - UM.Theme.getSize("default_margin").width
  174. Loader
  175. {
  176. id: settingLoader
  177. width: UM.Theme.getSize("setting").width
  178. height: UM.Theme.getSize("section").height
  179. property var definition: model
  180. property var settingDefinitionsModel: addedSettingsModel
  181. property var propertyProvider: provider
  182. property var globalPropertyProvider: inheritStackProvider
  183. property var externalResetHandler: false
  184. //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
  185. //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
  186. //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
  187. asynchronous: model.type != "enum" && model.type != "extruder"
  188. onLoaded: {
  189. settingLoader.item.showRevertButton = false
  190. settingLoader.item.showInheritButton = false
  191. settingLoader.item.showLinkedSettingIcon = false
  192. settingLoader.item.doDepthIndentation = false
  193. settingLoader.item.doQualityUserSettingEmphasis = false
  194. }
  195. sourceComponent:
  196. {
  197. switch(model.type)
  198. {
  199. case "int":
  200. return settingTextField
  201. case "[int]":
  202. return settingTextField
  203. case "float":
  204. return settingTextField
  205. case "enum":
  206. return settingComboBox
  207. case "extruder":
  208. return settingExtruder
  209. case "optional_extruder":
  210. return settingOptionalExtruder
  211. case "bool":
  212. return settingCheckBox
  213. case "str":
  214. return settingTextField
  215. case "category":
  216. return settingCategory
  217. default:
  218. return settingUnknown
  219. }
  220. }
  221. }
  222. Button
  223. {
  224. width: Math.round(UM.Theme.getSize("setting").height / 2)
  225. height: UM.Theme.getSize("setting").height
  226. onClicked: addedSettingsModel.setVisible(model.key, false)
  227. style: ButtonStyle
  228. {
  229. background: Item
  230. {
  231. UM.RecolorImage
  232. {
  233. anchors.verticalCenter: parent.verticalCenter
  234. width: parent.width
  235. height: width
  236. sourceSize.height: width
  237. color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
  238. source: UM.Theme.getIcon("minus")
  239. }
  240. }
  241. }
  242. }
  243. // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events
  244. // so we bypass that to make a dedicated provider).
  245. UM.SettingPropertyProvider
  246. {
  247. id: provider
  248. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  249. key: model.key
  250. watchedProperties: [ "value", "enabled", "validationState" ]
  251. storeIndex: 0
  252. removeUnusedValue: false
  253. }
  254. UM.SettingPropertyProvider
  255. {
  256. id: inheritStackProvider
  257. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  258. key: model.key
  259. watchedProperties: [ "limit_to_extruder" ]
  260. }
  261. Connections
  262. {
  263. target: inheritStackProvider
  264. onPropertiesChanged:
  265. {
  266. provider.forcePropertiesChanged();
  267. }
  268. }
  269. Connections
  270. {
  271. target: UM.ActiveTool
  272. onPropertiesChanged:
  273. {
  274. // the values cannot be bound with UM.ActiveTool.properties.getValue() calls,
  275. // so here we connect to the signal and update the those values.
  276. if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
  277. {
  278. const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId");
  279. if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
  280. {
  281. addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId;
  282. }
  283. }
  284. if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
  285. {
  286. const containerId = UM.ActiveTool.properties.getValue("ContainerID");
  287. if (provider.containerStackId != containerId)
  288. {
  289. provider.containerStackId = containerId;
  290. }
  291. if (inheritStackProvider.containerStackId != containerId)
  292. {
  293. inheritStackProvider.containerStackId = containerId;
  294. }
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. }
  302. Button
  303. {
  304. id: customiseSettingsButton;
  305. height: UM.Theme.getSize("setting_control").height;
  306. visible: currentSettings.visible
  307. text: catalog.i18nc("@action:button", "Select settings");
  308. style: ButtonStyle
  309. {
  310. background: Rectangle
  311. {
  312. width: control.width;
  313. height: control.height;
  314. border.width: UM.Theme.getSize("default_lining").width;
  315. border.color: control.pressed ? UM.Theme.getColor("action_button_active_border") :
  316. control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
  317. color: control.pressed ? UM.Theme.getColor("action_button_active") :
  318. control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
  319. }
  320. label: Label
  321. {
  322. text: control.text;
  323. color: UM.Theme.getColor("setting_control_text");
  324. font: UM.Theme.getFont("default")
  325. anchors.centerIn: parent
  326. }
  327. }
  328. onClicked:
  329. {
  330. settingPickDialog.visible = true;
  331. if (meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh")
  332. {
  333. settingPickDialog.additional_excluded_settings = base.all_categories_except_support;
  334. }
  335. else
  336. {
  337. settingPickDialog.additional_excluded_settings = []
  338. }
  339. }
  340. }
  341. }
  342. UM.Dialog {
  343. id: settingPickDialog
  344. title: catalog.i18nc("@title:window", "Select Settings to Customize for this model")
  345. width: screenScaleFactor * 360
  346. property var additional_excluded_settings
  347. onVisibilityChanged:
  348. {
  349. // force updating the model to sync it with addedSettingsModel
  350. if(visible)
  351. {
  352. // Set skip setting, it will prevent from resetting selected mesh_type
  353. contents.model.visibilityHandler.addSkipResetSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type)
  354. listview.model.forceUpdate()
  355. updateFilter()
  356. }
  357. }
  358. function updateFilter()
  359. {
  360. var new_filter = {};
  361. new_filter["settable_per_mesh"] = true;
  362. // Don't filter on "settable_per_meshgroup" any more when `printSequencePropertyProvider.properties.value`
  363. // is set to "one_at_a_time", because the current backend architecture isn't ready for that.
  364. if(filterInput.text != "")
  365. {
  366. new_filter["i18n_label"] = "*" + filterInput.text;
  367. }
  368. listview.model.filter = new_filter;
  369. }
  370. TextField {
  371. id: filterInput
  372. anchors {
  373. top: parent.top
  374. left: parent.left
  375. right: toggleShowAll.left
  376. rightMargin: UM.Theme.getSize("default_margin").width
  377. }
  378. placeholderText: catalog.i18nc("@label:textbox", "Filter...");
  379. onTextChanged: settingPickDialog.updateFilter()
  380. }
  381. CheckBox
  382. {
  383. id: toggleShowAll
  384. anchors {
  385. top: parent.top
  386. right: parent.right
  387. }
  388. text: catalog.i18nc("@label:checkbox", "Show all")
  389. checked: listview.model.showAll
  390. onClicked:
  391. {
  392. listview.model.showAll = checked;
  393. }
  394. }
  395. ScrollView
  396. {
  397. id: scrollView
  398. anchors
  399. {
  400. top: filterInput.bottom;
  401. left: parent.left;
  402. right: parent.right;
  403. bottom: parent.bottom;
  404. }
  405. ListView
  406. {
  407. id:listview
  408. model: UM.SettingDefinitionsModel
  409. {
  410. id: definitionsModel;
  411. containerId: Cura.MachineManager.activeDefinitionId
  412. visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
  413. expanded: [ "*" ]
  414. exclude:
  415. {
  416. var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ];
  417. excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings);
  418. return excluded_settings;
  419. }
  420. }
  421. delegate:Loader
  422. {
  423. id: loader
  424. width: parent.width
  425. height: model.type != undefined ? UM.Theme.getSize("section").height : 0;
  426. property var definition: model
  427. property var settingDefinitionsModel: definitionsModel
  428. asynchronous: true
  429. source:
  430. {
  431. switch(model.type)
  432. {
  433. case "category":
  434. return "PerObjectCategory.qml"
  435. default:
  436. return "PerObjectItem.qml"
  437. }
  438. }
  439. }
  440. Component.onCompleted: settingPickDialog.updateFilter()
  441. }
  442. }
  443. rightButtons: [
  444. Button {
  445. text: catalog.i18nc("@action:button", "Close");
  446. onClicked: {
  447. settingPickDialog.visible = false;
  448. }
  449. }
  450. ]
  451. }
  452. UM.SettingPropertyProvider
  453. {
  454. id: machineExtruderCount
  455. containerStack: Cura.MachineManager.activeMachine
  456. key: "machine_extruder_count"
  457. watchedProperties: [ "value" ]
  458. storeIndex: 0
  459. }
  460. UM.SettingPropertyProvider
  461. {
  462. id: printSequencePropertyProvider
  463. containerStack: Cura.MachineManager.activeMachine
  464. key: "print_sequence"
  465. watchedProperties: [ "value" ]
  466. storeIndex: 0
  467. }
  468. SystemPalette { id: palette; }
  469. Component
  470. {
  471. id: settingTextField;
  472. Cura.SettingTextField { }
  473. }
  474. Component
  475. {
  476. id: settingComboBox;
  477. Cura.SettingComboBox { }
  478. }
  479. Component
  480. {
  481. id: settingExtruder;
  482. Cura.SettingExtruder { }
  483. }
  484. Component
  485. {
  486. id: settingOptionalExtruder
  487. Cura.SettingOptionalExtruder { }
  488. }
  489. Component
  490. {
  491. id: settingCheckBox;
  492. Cura.SettingCheckBox { }
  493. }
  494. Component
  495. {
  496. id: settingCategory;
  497. Cura.SettingCategory { }
  498. }
  499. Component
  500. {
  501. id: settingUnknown;
  502. Cura.SettingUnknown { }
  503. }
  504. }