PostProcessingPlugin.qml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. // Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V.
  2. // The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 1.1
  5. import QtQuick.Controls.Styles 1.1
  6. import QtQuick.Layouts 1.1
  7. import QtQuick.Dialogs 1.1
  8. import QtQuick.Window 2.2
  9. import UM 1.2 as UM
  10. import Cura 1.0 as Cura
  11. UM.Dialog
  12. {
  13. id: dialog
  14. title: catalog.i18nc("@title:window", "Post Processing Plugin")
  15. width: 700 * screenScaleFactor;
  16. height: 500 * screenScaleFactor;
  17. minimumWidth: 400 * screenScaleFactor;
  18. minimumHeight: 250 * screenScaleFactor;
  19. onVisibleChanged:
  20. {
  21. if(!visible) //Whenever the window is closed (either via the "Close" button or the X on the window frame), we want to update it in the stack.
  22. {
  23. manager.writeScriptsToStack();
  24. }
  25. }
  26. Item
  27. {
  28. UM.I18nCatalog{id: catalog; name: "cura"}
  29. id: base
  30. property int columnWidth: Math.round((base.width / 2) - UM.Theme.getSize("default_margin").width)
  31. property int textMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
  32. property string activeScriptName
  33. SystemPalette{ id: palette }
  34. SystemPalette{ id: disabledPalette; colorGroup: SystemPalette.Disabled }
  35. anchors.fill: parent
  36. ExclusiveGroup
  37. {
  38. id: selectedScriptGroup
  39. }
  40. Item
  41. {
  42. id: activeScripts
  43. anchors.left: parent.left
  44. width: base.columnWidth
  45. height: parent.height
  46. Label
  47. {
  48. id: activeScriptsHeader
  49. text: catalog.i18nc("@label", "Post Processing Scripts")
  50. anchors.top: parent.top
  51. anchors.topMargin: base.textMargin
  52. anchors.left: parent.left
  53. anchors.leftMargin: base.textMargin
  54. anchors.right: parent.right
  55. anchors.rightMargin: base.textMargin
  56. font: UM.Theme.getFont("large")
  57. elide: Text.ElideRight
  58. }
  59. ListView
  60. {
  61. id: activeScriptsList
  62. anchors.top: activeScriptsHeader.bottom
  63. anchors.topMargin: base.textMargin
  64. anchors.left: parent.left
  65. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  66. anchors.right: parent.right
  67. anchors.rightMargin: base.textMargin
  68. height: childrenRect.height
  69. model: manager.scriptList
  70. delegate: Item
  71. {
  72. width: parent.width
  73. height: activeScriptButton.height
  74. Button
  75. {
  76. id: activeScriptButton
  77. text: manager.getScriptLabelByKey(modelData.toString())
  78. exclusiveGroup: selectedScriptGroup
  79. checkable: true
  80. checked: {
  81. if (manager.selectedScriptIndex == index)
  82. {
  83. base.activeScriptName = manager.getScriptLabelByKey(modelData.toString())
  84. return true
  85. }
  86. else
  87. {
  88. return false
  89. }
  90. }
  91. onClicked:
  92. {
  93. forceActiveFocus()
  94. manager.setSelectedScriptIndex(index)
  95. base.activeScriptName = manager.getScriptLabelByKey(modelData.toString())
  96. }
  97. width: parent.width
  98. height: UM.Theme.getSize("setting").height
  99. style: ButtonStyle
  100. {
  101. background: Rectangle
  102. {
  103. color: activeScriptButton.checked ? palette.highlight : "transparent"
  104. width: parent.width
  105. height: parent.height
  106. }
  107. label: Label
  108. {
  109. wrapMode: Text.Wrap
  110. text: control.text
  111. elide: Text.ElideRight
  112. color: activeScriptButton.checked ? palette.highlightedText : palette.text
  113. }
  114. }
  115. }
  116. Button
  117. {
  118. id: removeButton
  119. text: "x"
  120. width: 20 * screenScaleFactor
  121. height: 20 * screenScaleFactor
  122. anchors.right:parent.right
  123. anchors.rightMargin: base.textMargin
  124. anchors.verticalCenter: parent.verticalCenter
  125. onClicked: manager.removeScriptByIndex(index)
  126. style: ButtonStyle
  127. {
  128. label: Item
  129. {
  130. UM.RecolorImage
  131. {
  132. anchors.verticalCenter: parent.verticalCenter
  133. anchors.horizontalCenter: parent.horizontalCenter
  134. width: Math.round(control.width / 2.7)
  135. height: Math.round(control.height / 2.7)
  136. sourceSize.width: width
  137. sourceSize.height: width
  138. color: palette.text
  139. source: UM.Theme.getIcon("cross1")
  140. }
  141. }
  142. }
  143. }
  144. Button
  145. {
  146. id: downButton
  147. text: ""
  148. anchors.right: removeButton.left
  149. anchors.verticalCenter: parent.verticalCenter
  150. enabled: index != manager.scriptList.length - 1
  151. width: 20 * screenScaleFactor
  152. height: 20 * screenScaleFactor
  153. onClicked:
  154. {
  155. if (manager.selectedScriptIndex == index)
  156. {
  157. manager.setSelectedScriptIndex(index + 1)
  158. }
  159. return manager.moveScript(index, index + 1)
  160. }
  161. style: ButtonStyle
  162. {
  163. label: Item
  164. {
  165. UM.RecolorImage
  166. {
  167. anchors.verticalCenter: parent.verticalCenter
  168. anchors.horizontalCenter: parent.horizontalCenter
  169. width: Math.round(control.width / 2.5)
  170. height: Math.round(control.height / 2.5)
  171. sourceSize.width: width
  172. sourceSize.height: width
  173. color: control.enabled ? palette.text : disabledPalette.text
  174. source: UM.Theme.getIcon("arrow_bottom")
  175. }
  176. }
  177. }
  178. }
  179. Button
  180. {
  181. id: upButton
  182. text: ""
  183. enabled: index != 0
  184. width: 20 * screenScaleFactor
  185. height: 20 * screenScaleFactor
  186. anchors.right: downButton.left
  187. anchors.verticalCenter: parent.verticalCenter
  188. onClicked:
  189. {
  190. if (manager.selectedScriptIndex == index)
  191. {
  192. manager.setSelectedScriptIndex(index - 1)
  193. }
  194. return manager.moveScript(index, index - 1)
  195. }
  196. style: ButtonStyle
  197. {
  198. label: Item
  199. {
  200. UM.RecolorImage
  201. {
  202. anchors.verticalCenter: parent.verticalCenter
  203. anchors.horizontalCenter: parent.horizontalCenter
  204. width: Math.round(control.width / 2.5)
  205. height: Math.round(control.height / 2.5)
  206. sourceSize.width: width
  207. sourceSize.height: width
  208. color: control.enabled ? palette.text : disabledPalette.text
  209. source: UM.Theme.getIcon("arrow_top")
  210. }
  211. }
  212. }
  213. }
  214. }
  215. }
  216. Button
  217. {
  218. id: addButton
  219. text: catalog.i18nc("@action", "Add a script")
  220. anchors.left: parent.left
  221. anchors.leftMargin: base.textMargin
  222. anchors.top: activeScriptsList.bottom
  223. anchors.topMargin: base.textMargin
  224. menu: scriptsMenu
  225. style: ButtonStyle
  226. {
  227. label: Label
  228. {
  229. text: control.text
  230. }
  231. }
  232. }
  233. Menu
  234. {
  235. id: scriptsMenu
  236. Instantiator
  237. {
  238. model: manager.loadedScriptList
  239. MenuItem
  240. {
  241. text: manager.getScriptLabelByKey(modelData.toString())
  242. onTriggered: manager.addScriptToList(modelData.toString())
  243. }
  244. onObjectAdded: scriptsMenu.insertItem(index, object);
  245. onObjectRemoved: scriptsMenu.removeItem(object);
  246. }
  247. }
  248. }
  249. Rectangle
  250. {
  251. color: UM.Theme.getColor("main_background")
  252. anchors.left: activeScripts.right
  253. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  254. anchors.right: parent.right
  255. height: parent.height
  256. id: settingsPanel
  257. Label
  258. {
  259. id: scriptSpecsHeader
  260. text: manager.selectedScriptIndex == -1 ? catalog.i18nc("@label", "Settings") : base.activeScriptName
  261. anchors.top: parent.top
  262. anchors.topMargin: base.textMargin
  263. anchors.left: parent.left
  264. anchors.leftMargin: base.textMargin
  265. anchors.right: parent.right
  266. anchors.rightMargin: base.textMargin
  267. elide: Text.ElideRight
  268. height: 20 * screenScaleFactor
  269. font: UM.Theme.getFont("large")
  270. color: UM.Theme.getColor("text")
  271. }
  272. ScrollView
  273. {
  274. id: scrollView
  275. anchors.top: scriptSpecsHeader.bottom
  276. anchors.topMargin: settingsPanel.textMargin
  277. anchors.left: parent.left
  278. anchors.right: parent.right
  279. anchors.bottom: parent.bottom
  280. visible: manager.selectedScriptDefinitionId != ""
  281. style: UM.Theme.styles.scrollview;
  282. ListView
  283. {
  284. id: listview
  285. spacing: UM.Theme.getSize("default_lining").height
  286. model: UM.SettingDefinitionsModel
  287. {
  288. id: definitionsModel;
  289. containerId: manager.selectedScriptDefinitionId
  290. showAll: true
  291. }
  292. delegate:Loader
  293. {
  294. id: settingLoader
  295. width: parent.width
  296. height:
  297. {
  298. if(provider.properties.enabled == "True")
  299. {
  300. if(model.type != undefined)
  301. {
  302. return UM.Theme.getSize("section").height;
  303. }
  304. else
  305. {
  306. return 0;
  307. }
  308. }
  309. else
  310. {
  311. return 0;
  312. }
  313. }
  314. Behavior on height { NumberAnimation { duration: 100 } }
  315. opacity: provider.properties.enabled == "True" ? 1 : 0
  316. Behavior on opacity { NumberAnimation { duration: 100 } }
  317. enabled: opacity > 0
  318. property var definition: model
  319. property var settingDefinitionsModel: definitionsModel
  320. property var propertyProvider: provider
  321. property var globalPropertyProvider: inheritStackProvider
  322. //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
  323. //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
  324. //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
  325. asynchronous: model.type != "enum" && model.type != "extruder"
  326. onLoaded: {
  327. settingLoader.item.showRevertButton = false
  328. settingLoader.item.showInheritButton = false
  329. settingLoader.item.showLinkedSettingIcon = false
  330. settingLoader.item.doDepthIndentation = true
  331. settingLoader.item.doQualityUserSettingEmphasis = false
  332. }
  333. sourceComponent:
  334. {
  335. switch(model.type)
  336. {
  337. case "int":
  338. return settingTextField
  339. case "float":
  340. return settingTextField
  341. case "enum":
  342. return settingComboBox
  343. case "extruder":
  344. return settingExtruder
  345. case "bool":
  346. return settingCheckBox
  347. case "str":
  348. return settingTextField
  349. case "category":
  350. return settingCategory
  351. default:
  352. return settingUnknown
  353. }
  354. }
  355. UM.SettingPropertyProvider
  356. {
  357. id: provider
  358. containerStackId: manager.selectedScriptStackId
  359. key: model.key ? model.key : "None"
  360. watchedProperties: [ "value", "enabled", "state", "validationState" ]
  361. storeIndex: 0
  362. }
  363. // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events
  364. // so we bypass that to make a dedicated provider).
  365. UM.SettingPropertyProvider
  366. {
  367. id: inheritStackProvider
  368. containerStack: Cura.MachineManager.activeMachine
  369. key: model.key ? model.key : "None"
  370. watchedProperties: [ "limit_to_extruder" ]
  371. }
  372. Connections
  373. {
  374. target: item
  375. onShowTooltip:
  376. {
  377. tooltip.text = text;
  378. var position = settingLoader.mapToItem(settingsPanel, settingsPanel.x, 0);
  379. tooltip.show(position);
  380. tooltip.target.x = position.x + 1
  381. }
  382. onHideTooltip:
  383. {
  384. tooltip.hide();
  385. }
  386. }
  387. }
  388. }
  389. }
  390. }
  391. Cura.SidebarTooltip
  392. {
  393. id: tooltip
  394. }
  395. Component
  396. {
  397. id: settingTextField;
  398. Cura.SettingTextField { }
  399. }
  400. Component
  401. {
  402. id: settingComboBox;
  403. Cura.SettingComboBox { }
  404. }
  405. Component
  406. {
  407. id: settingExtruder;
  408. Cura.SettingExtruder { }
  409. }
  410. Component
  411. {
  412. id: settingCheckBox;
  413. Cura.SettingCheckBox { }
  414. }
  415. Component
  416. {
  417. id: settingCategory;
  418. Cura.SettingCategory { }
  419. }
  420. Component
  421. {
  422. id: settingUnknown;
  423. Cura.SettingUnknown { }
  424. }
  425. }
  426. rightButtons: Button
  427. {
  428. text: catalog.i18nc("@action:button", "Close")
  429. iconName: "dialog-close"
  430. onClicked: dialog.accept()
  431. }
  432. Button {
  433. objectName: "postProcessingSaveAreaButton"
  434. visible: activeScriptsList.count > 0
  435. height: UM.Theme.getSize("save_button_save_to_button").height
  436. width: height
  437. tooltip: catalog.i18nc("@info:tooltip", "Change active post-processing scripts")
  438. onClicked: dialog.show()
  439. style: ButtonStyle {
  440. background: Rectangle {
  441. id: deviceSelectionIcon
  442. border.width: UM.Theme.getSize("default_lining").width
  443. border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") :
  444. control.pressed ? UM.Theme.getColor("action_button_active_border") :
  445. control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
  446. color: !control.enabled ? UM.Theme.getColor("action_button_disabled") :
  447. control.pressed ? UM.Theme.getColor("action_button_active") :
  448. control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
  449. Behavior on color { ColorAnimation { duration: 50; } }
  450. anchors.left: parent.left
  451. anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2);
  452. width: parent.height
  453. height: parent.height
  454. UM.RecolorImage {
  455. anchors.verticalCenter: parent.verticalCenter
  456. anchors.horizontalCenter: parent.horizontalCenter
  457. width: Math.round(parent.width / 2)
  458. height: Math.round(parent.height / 2)
  459. sourceSize.width: width
  460. sourceSize.height: height
  461. color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
  462. control.pressed ? UM.Theme.getColor("action_button_active_text") :
  463. control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text");
  464. source: "postprocessing.svg"
  465. }
  466. }
  467. label: Label{ }
  468. }
  469. }
  470. }