PerObjectSettingsPanel.qml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  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.width: width
  237. sourceSize.height: width
  238. color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
  239. source: UM.Theme.getIcon("minus")
  240. }
  241. }
  242. }
  243. }
  244. // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events
  245. // so we bypass that to make a dedicated provider).
  246. UM.SettingPropertyProvider
  247. {
  248. id: provider
  249. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  250. key: model.key
  251. watchedProperties: [ "value", "enabled", "validationState" ]
  252. storeIndex: 0
  253. removeUnusedValue: false
  254. }
  255. UM.SettingPropertyProvider
  256. {
  257. id: inheritStackProvider
  258. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  259. key: model.key
  260. watchedProperties: [ "limit_to_extruder" ]
  261. }
  262. Connections
  263. {
  264. target: inheritStackProvider
  265. onPropertiesChanged:
  266. {
  267. provider.forcePropertiesChanged();
  268. }
  269. }
  270. Connections
  271. {
  272. target: UM.ActiveTool
  273. onPropertiesChanged:
  274. {
  275. // the values cannot be bound with UM.ActiveTool.properties.getValue() calls,
  276. // so here we connect to the signal and update the those values.
  277. if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
  278. {
  279. const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId");
  280. if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
  281. {
  282. addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId;
  283. }
  284. }
  285. if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
  286. {
  287. const containerId = UM.ActiveTool.properties.getValue("ContainerID");
  288. if (provider.containerStackId != containerId)
  289. {
  290. provider.containerStackId = containerId;
  291. }
  292. if (inheritStackProvider.containerStackId != containerId)
  293. {
  294. inheritStackProvider.containerStackId = containerId;
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. }
  302. }
  303. Button
  304. {
  305. id: customiseSettingsButton;
  306. height: UM.Theme.getSize("setting_control").height;
  307. visible: currentSettings.visible
  308. text: catalog.i18nc("@action:button", "Select settings");
  309. style: ButtonStyle
  310. {
  311. background: Rectangle
  312. {
  313. width: control.width;
  314. height: control.height;
  315. border.width: UM.Theme.getSize("default_lining").width;
  316. border.color: control.pressed ? UM.Theme.getColor("action_button_active_border") :
  317. control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
  318. color: control.pressed ? UM.Theme.getColor("action_button_active") :
  319. control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
  320. }
  321. label: Label
  322. {
  323. text: control.text;
  324. color: UM.Theme.getColor("setting_control_text");
  325. font: UM.Theme.getFont("default")
  326. anchors.centerIn: parent
  327. }
  328. }
  329. onClicked:
  330. {
  331. settingPickDialog.visible = true;
  332. if (meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh")
  333. {
  334. settingPickDialog.additional_excluded_settings = base.all_categories_except_support;
  335. }
  336. else
  337. {
  338. settingPickDialog.additional_excluded_settings = []
  339. }
  340. }
  341. }
  342. }
  343. UM.Dialog {
  344. id: settingPickDialog
  345. title: catalog.i18nc("@title:window", "Select Settings to Customize for this model")
  346. width: screenScaleFactor * 360
  347. property var additional_excluded_settings
  348. onVisibilityChanged:
  349. {
  350. // force updating the model to sync it with addedSettingsModel
  351. if(visible)
  352. {
  353. // Set skip setting, it will prevent from resetting selected mesh_type
  354. contents.model.visibilityHandler.addSkipResetSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type)
  355. listview.model.forceUpdate()
  356. updateFilter()
  357. }
  358. }
  359. function updateFilter()
  360. {
  361. var new_filter = {};
  362. if (printSequencePropertyProvider.properties.value == "one_at_a_time")
  363. {
  364. new_filter["settable_per_meshgroup"] = true;
  365. }
  366. else
  367. {
  368. new_filter["settable_per_mesh"] = true;
  369. }
  370. if(filterInput.text != "")
  371. {
  372. new_filter["i18n_label"] = "*" + filterInput.text;
  373. }
  374. listview.model.filter = new_filter;
  375. }
  376. TextField {
  377. id: filterInput
  378. anchors {
  379. top: parent.top
  380. left: parent.left
  381. right: toggleShowAll.left
  382. rightMargin: UM.Theme.getSize("default_margin").width
  383. }
  384. placeholderText: catalog.i18nc("@label:textbox", "Filter...");
  385. onTextChanged: settingPickDialog.updateFilter()
  386. }
  387. CheckBox
  388. {
  389. id: toggleShowAll
  390. anchors {
  391. top: parent.top
  392. right: parent.right
  393. }
  394. text: catalog.i18nc("@label:checkbox", "Show all")
  395. checked: listview.model.showAll
  396. onClicked:
  397. {
  398. listview.model.showAll = checked;
  399. }
  400. }
  401. ScrollView
  402. {
  403. id: scrollView
  404. anchors
  405. {
  406. top: filterInput.bottom;
  407. left: parent.left;
  408. right: parent.right;
  409. bottom: parent.bottom;
  410. }
  411. ListView
  412. {
  413. id:listview
  414. model: UM.SettingDefinitionsModel
  415. {
  416. id: definitionsModel;
  417. containerId: Cura.MachineManager.activeDefinitionId
  418. visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
  419. expanded: [ "*" ]
  420. exclude:
  421. {
  422. var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ];
  423. excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings);
  424. return excluded_settings;
  425. }
  426. }
  427. delegate:Loader
  428. {
  429. id: loader
  430. width: parent.width
  431. height: model.type != undefined ? UM.Theme.getSize("section").height : 0;
  432. property var definition: model
  433. property var settingDefinitionsModel: definitionsModel
  434. asynchronous: true
  435. source:
  436. {
  437. switch(model.type)
  438. {
  439. case "category":
  440. return "PerObjectCategory.qml"
  441. default:
  442. return "PerObjectItem.qml"
  443. }
  444. }
  445. }
  446. Component.onCompleted: settingPickDialog.updateFilter()
  447. }
  448. }
  449. rightButtons: [
  450. Button {
  451. text: catalog.i18nc("@action:button", "Close");
  452. onClicked: {
  453. settingPickDialog.visible = false;
  454. }
  455. }
  456. ]
  457. }
  458. UM.SettingPropertyProvider
  459. {
  460. id: machineExtruderCount
  461. containerStack: Cura.MachineManager.activeMachine
  462. key: "machine_extruder_count"
  463. watchedProperties: [ "value" ]
  464. storeIndex: 0
  465. }
  466. UM.SettingPropertyProvider
  467. {
  468. id: printSequencePropertyProvider
  469. containerStack: Cura.MachineManager.activeMachine
  470. key: "print_sequence"
  471. watchedProperties: [ "value" ]
  472. storeIndex: 0
  473. }
  474. SystemPalette { id: palette; }
  475. Component
  476. {
  477. id: settingTextField;
  478. Cura.SettingTextField { }
  479. }
  480. Component
  481. {
  482. id: settingComboBox;
  483. Cura.SettingComboBox { }
  484. }
  485. Component
  486. {
  487. id: settingExtruder;
  488. Cura.SettingExtruder { }
  489. }
  490. Component
  491. {
  492. id: settingOptionalExtruder
  493. Cura.SettingOptionalExtruder { }
  494. }
  495. Component
  496. {
  497. id: settingCheckBox;
  498. Cura.SettingCheckBox { }
  499. }
  500. Component
  501. {
  502. id: settingCategory;
  503. Cura.SettingCategory { }
  504. }
  505. Component
  506. {
  507. id: settingUnknown;
  508. Cura.SettingUnknown { }
  509. }
  510. }