PerObjectSettingsPanel.qml 21 KB

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