PostProcessingPlugin.qml 20 KB

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