WorkspaceDialog.qml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. // Copyright (c) 2022 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.10
  4. import QtQuick.Controls 2.3
  5. import QtQuick.Layouts 1.3
  6. import QtQuick.Window 2.2
  7. import UM 1.6 as UM
  8. import Cura 1.1 as Cura
  9. UM.Dialog
  10. {
  11. id: workspaceDialog
  12. title: manager.isUcp? catalog.i18nc("@title:window Don't translate 'Universal Cura Project'", "Open Universal Cura Project (UCP)"): catalog.i18nc("@title:window", "Open Project")
  13. margin: UM.Theme.getSize("default_margin").width
  14. minimumWidth: UM.Theme.getSize("modal_window_minimum").width
  15. minimumHeight: UM.Theme.getSize("modal_window_minimum").height
  16. backgroundColor: UM.Theme.getColor("detail_background")
  17. headerComponent: Rectangle
  18. {
  19. height: childrenRect.height + 2 * UM.Theme.getSize("default_margin").height
  20. color: UM.Theme.getColor("main_background")
  21. ColumnLayout
  22. {
  23. id: headerColumn
  24. anchors.top: parent.top
  25. anchors.left: parent.left
  26. anchors.right: parent.right
  27. anchors.topMargin: UM.Theme.getSize("default_margin").height
  28. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  29. anchors.rightMargin: anchors.leftMargin
  30. RowLayout
  31. {
  32. UM.Label
  33. {
  34. id: titleLabel
  35. text: manager.isUcp? catalog.i18nc("@action:title Don't translate 'Universal Cura Project'", "Summary - Open Universal Cura Project (UCP)"): catalog.i18nc("@action:title", "Summary - Cura Project")
  36. font: UM.Theme.getFont("large")
  37. }
  38. Cura.TertiaryButton
  39. {
  40. id: learnMoreButton
  41. visible: manager.isUcp
  42. text: catalog.i18nc("@button", "Learn more")
  43. iconSource: UM.Theme.getIcon("LinkExternal")
  44. isIconOnRightSide: true
  45. onClicked: Qt.openUrlExternally("https://support.ultimaker.com/s/article/000002979")
  46. }
  47. }
  48. }
  49. }
  50. Rectangle
  51. {
  52. anchors.fill: parent
  53. UM.I18nCatalog { id: catalog; name: "cura" }
  54. color: UM.Theme.getColor("main_background")
  55. Flickable
  56. {
  57. id: dialogSummaryItem
  58. width: parent.width
  59. height: parent.height
  60. clip: true
  61. contentHeight: contentColumn.height
  62. ScrollBar.vertical: UM.ScrollBar { id: scrollbar }
  63. ListModel
  64. {
  65. id: resolveStrategiesModel
  66. // Instead of directly adding the list elements, we add them afterwards.
  67. // This is because it's impossible to use setting function results to be bound to listElement properties directly.
  68. // See http://stackoverflow.com/questions/7659442/listelement-fields-as-properties
  69. Component.onCompleted:
  70. {
  71. append({"key": "override", "label": catalog.i18nc("@action:ComboBox Update/override existing profile", "Update existing")});
  72. append({"key": "new", "label": catalog.i18nc("@action:ComboBox Save settings in a new profile", "Create new")});
  73. }
  74. }
  75. Column
  76. {
  77. id: contentColumn
  78. width: parent.width - scrollbar.width - UM.Theme.getSize("default_margin").width
  79. height: childrenRect.height
  80. spacing: UM.Theme.getSize("default_margin").height
  81. leftPadding: UM.Theme.getSize("default_margin").width
  82. rightPadding: UM.Theme.getSize("default_margin").width
  83. WorkspaceSection
  84. {
  85. id: printerSection
  86. title: catalog.i18nc("@action:label", "Printer settings")
  87. iconSource: UM.Theme.getIcon("Printer")
  88. content: Column
  89. {
  90. spacing: UM.Theme.getSize("default_margin").height
  91. leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
  92. WorkspaceRow
  93. {
  94. leftLabelText: catalog.i18nc("@action:label", "Type")
  95. rightLabelText: manager.machineType
  96. }
  97. WorkspaceRow
  98. {
  99. leftLabelText: catalog.i18nc("@action:label", manager.isPrinterGroup ? "Printer Group" : "Printer Name")
  100. rightLabelText: manager.isUcp? manager.machineType: manager.machineName == catalog.i18nc("@button", "Create new") ? "" : manager.machineName
  101. }
  102. }
  103. comboboxTitle: catalog.i18nc("@action:label", "Open With")
  104. comboboxTooltipText: catalog.i18nc("@info:tooltip", "Printer settings will be updated to match the settings saved with the project.")
  105. comboboxVisible: workspaceDialog.visible && manager.updatableMachinesModel.count > 1
  106. combobox: Cura.MachineSelector
  107. {
  108. id: machineSelector
  109. headerCornerSide: Cura.RoundedRectangle.Direction.All
  110. width: parent.width
  111. height: parent.height
  112. machineListModel: manager.updatableMachinesModel
  113. machineName: manager.machineName
  114. isConnectedCloudPrinter: false
  115. isCloudRegistered: false
  116. isNetworkPrinter: manager.isNetworked
  117. isGroup: manager.isAbstractMachine
  118. connectionStatus: ""
  119. minDropDownWidth: machineSelector.width
  120. Component
  121. {
  122. id: componentNewPrinter
  123. Cura.SecondaryButton
  124. {
  125. id: createNewPrinter
  126. text: catalog.i18nc("@button", "Create new")
  127. fixedWidthMode: true
  128. width: parent.width - leftPadding * 1.5
  129. visible: manager.allowCreateMachine
  130. onClicked:
  131. {
  132. toggleContent()
  133. manager.setResolveStrategy("machine", "new")
  134. machineSelector.machineName = catalog.i18nc("@button", "Create new")
  135. manager.setIsAbstractMachine(false)
  136. manager.setIsNetworkedMachine(false)
  137. }
  138. }
  139. }
  140. buttons: manager.allowCreateMachine ? [componentNewPrinter.createObject()] : []
  141. onSelectPrinter: function(machine)
  142. {
  143. toggleContent();
  144. machineSelector.machineName = machine.name
  145. manager.setResolveStrategy("machine", "override")
  146. manager.setMachineToOverride(machine.id)
  147. manager.setIsAbstractMachine(machine.isAbstractMachine)
  148. manager.setIsNetworkedMachine(machine.isNetworked)
  149. }
  150. }
  151. }
  152. WorkspaceSection
  153. {
  154. id: ucpProfileSection
  155. visible: manager.isUcp
  156. title: catalog.i18nc("@action:label", "Settings Loaded from UCP file")
  157. iconSource: UM.Theme.getIcon("Settings")
  158. content: Column
  159. {
  160. id: ucpProfileSettingsValuesTable
  161. spacing: UM.Theme.getSize("default_margin").height
  162. leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
  163. WorkspaceRow
  164. {
  165. id: numberOfOverrides
  166. leftLabelText: catalog.i18nc("@action:label", "Settings Loaded from UCP file")
  167. rightLabelText: catalog.i18ncp("@action:label", "%1 override", "%1 overrides", manager.exportedSettingModelRowCount).arg(manager.exportedSettingModelRowCount)
  168. buttonText: tableViewSpecificSettings.shouldBeVisible ? catalog.i18nc("@action:button", "Hide settings") : catalog.i18nc("@action:button", "Show settings")
  169. onButtonClicked: tableViewSpecificSettings.shouldBeVisible = !tableViewSpecificSettings.shouldBeVisible
  170. }
  171. Cura.TableView
  172. {
  173. id: tableViewSpecificSettings
  174. width: parent.width - parent.leftPadding - UM.Theme.getSize("default_margin").width
  175. height: UM.Theme.getSize("card").height
  176. visible: shouldBeVisible && manager.isUcp
  177. property bool shouldBeVisible: true
  178. columnHeaders:
  179. [
  180. catalog.i18nc("@title:column", "Applies on"),
  181. catalog.i18nc("@title:column", "Setting"),
  182. catalog.i18nc("@title:column", "Value")
  183. ]
  184. model: UM.TableModel
  185. {
  186. id: tableModel
  187. headers: ["category", "label", "value"]
  188. rows: manager.exportedSettingModelItems
  189. }
  190. Connections
  191. {
  192. target: manager
  193. function onExportedSettingModelChanged()
  194. {
  195. tableModel.clear()
  196. tableModel.rows = manager.exportedSettingModelItems
  197. }
  198. }
  199. }
  200. }
  201. comboboxVisible: manager.qualityChangesConflict
  202. combobox: Cura.ComboBox
  203. {
  204. id: qualityChangesResolveComboBox
  205. model: resolveStrategiesModel
  206. textRole: "label"
  207. visible: manager.qualityChangesConflict && !manager.isUcp
  208. contentLeftPadding: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("narrow_margin").width
  209. textFont: UM.Theme.getFont("medium")
  210. background: Cura.RoundedRectangle
  211. {
  212. border.width: UM.Theme.getSize("default_lining").width
  213. border.color: UM.Theme.getColor("lining")
  214. color: qualityChangesResolveComboBox.hovered ? UM.Theme.getColor("expandable_hover") : UM.Theme.getColor("action_button")
  215. cornerSide: Cura.RoundedRectangle.Direction.All
  216. radius: UM.Theme.getSize("default_radius").width
  217. }
  218. // This is a hack. This will trigger onCurrentIndexChanged and set the index when this component in loaded
  219. currentIndex:
  220. {
  221. currentIndex = 0
  222. }
  223. onCurrentIndexChanged:
  224. {
  225. manager.setResolveStrategy("quality_changes", resolveStrategiesModel.get(currentIndex).key)
  226. }
  227. }
  228. }
  229. WorkspaceSection
  230. {
  231. id: profileSection
  232. title: manager.isUcp? catalog.i18nc("@action:label", "Suggested Profile settings"):catalog.i18nc("@action:label", "Profile settings")
  233. iconSource: UM.Theme.getIcon("Sliders")
  234. content: Column
  235. {
  236. id: profileSettingsValuesTable
  237. spacing: UM.Theme.getSize("default_margin").height
  238. leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
  239. WorkspaceRow
  240. {
  241. leftLabelText: catalog.i18nc("@action:label", "Name")
  242. rightLabelText: manager.qualityName
  243. visible: manager.isCompatibleMachine
  244. }
  245. WorkspaceRow
  246. {
  247. leftLabelText: catalog.i18nc("@action:label", "Intent")
  248. rightLabelText: manager.intentName
  249. visible: manager.isCompatibleMachine
  250. }
  251. WorkspaceRow
  252. {
  253. leftLabelText: catalog.i18nc("@action:label", "Not in profile")
  254. rightLabelText: catalog.i18ncp("@action:label", "%1 override", "%1 overrides", manager.numUserSettings).arg(manager.numUserSettings)
  255. visible: manager.numUserSettings != 0 && !manager.isUcp
  256. }
  257. WorkspaceRow
  258. {
  259. leftLabelText: catalog.i18nc("@action:label", "Derivative from")
  260. rightLabelText: catalog.i18ncp("@action:label", "%1, %2 override", "%1, %2 overrides", manager.numSettingsOverridenByQualityChanges).arg(manager.qualityType).arg(manager.numSettingsOverridenByQualityChanges)
  261. visible: manager.numSettingsOverridenByQualityChanges != 0 && manager.isCompatibleMachine
  262. }
  263. }
  264. }
  265. WorkspaceSection
  266. {
  267. id: materialSection
  268. title: manager.isUcp? catalog.i18nc("@action:label", "Suggested Material settings"): catalog.i18nc("@action:label", "Material settings")
  269. iconSource: UM.Theme.getIcon("Spool")
  270. content: Column
  271. {
  272. spacing: UM.Theme.getSize("default_margin").height
  273. leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
  274. Repeater
  275. {
  276. model: manager.materialLabels
  277. delegate: WorkspaceRow
  278. {
  279. leftLabelText: catalog.i18nc("@action:label", "Name")
  280. rightLabelText: modelData
  281. }
  282. }
  283. }
  284. comboboxVisible: manager.materialConflict
  285. combobox: Cura.ComboBox
  286. {
  287. id: materialResolveComboBox
  288. model: resolveStrategiesModel
  289. textRole: "label"
  290. visible: manager.materialConflict && !manager.isUcp
  291. contentLeftPadding: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("narrow_margin").width
  292. textFont: UM.Theme.getFont("medium")
  293. background: Cura.RoundedRectangle
  294. {
  295. border.width: UM.Theme.getSize("default_lining").width
  296. border.color: UM.Theme.getColor("lining")
  297. color: materialResolveComboBox.hovered ? UM.Theme.getColor("expandable_hover") : UM.Theme.getColor("action_button")
  298. cornerSide: Cura.RoundedRectangle.Direction.All
  299. radius: UM.Theme.getSize("default_radius").width
  300. }
  301. // This is a hack. This will trigger onCurrentIndexChanged and set the index when this component in loaded
  302. currentIndex:
  303. {
  304. currentIndex = 0
  305. }
  306. onCurrentIndexChanged:
  307. {
  308. manager.setResolveStrategy("material", resolveStrategiesModel.get(currentIndex).key)
  309. }
  310. }
  311. }
  312. WorkspaceSection
  313. {
  314. id: visibilitySection
  315. title: catalog.i18nc("@action:label", "Setting visibility")
  316. iconSource: UM.Theme.getIcon("Eye")
  317. visible : !manager.isUcp
  318. content: Column
  319. {
  320. spacing: UM.Theme.getSize("default_margin").height
  321. leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
  322. bottomPadding: UM.Theme.getSize("narrow_margin").height
  323. WorkspaceRow
  324. {
  325. leftLabelText: catalog.i18nc("@action:label", "Mode")
  326. rightLabelText: manager.activeMode
  327. }
  328. WorkspaceRow
  329. {
  330. leftLabelText: catalog.i18nc("@action:label", "%1 out of %2" ).arg(manager.numVisibleSettings).arg(manager.totalNumberOfSettings)
  331. rightLabelText: manager.activeMode
  332. visible: manager.hasVisibleSettingsField
  333. }
  334. }
  335. }
  336. Row
  337. {
  338. id: clearBuildPlateWarning
  339. width: parent.width
  340. height: childrenRect.height
  341. spacing: UM.Theme.getSize("default_margin").width
  342. visible: manager.hasObjectsOnPlate
  343. UM.ColorImage
  344. {
  345. width: warningLabel.height
  346. height: width
  347. source: UM.Theme.getIcon("Information")
  348. color: UM.Theme.getColor("text")
  349. }
  350. UM.Label
  351. {
  352. id: warningLabel
  353. text: catalog.i18nc("@action:warning", "Loading a project will clear all models on the build plate.")
  354. }
  355. }
  356. }
  357. }
  358. }
  359. property bool warning: manager.missingPackages.length > 0
  360. footerComponent: Rectangle
  361. {
  362. color: warning ? UM.Theme.getColor("warning") : "transparent"
  363. anchors.bottom: parent.bottom
  364. width: parent.width
  365. height: childrenRect.height + (warning ? 2 * workspaceDialog.margin : workspaceDialog.margin)
  366. Column
  367. {
  368. height: childrenRect.height
  369. spacing: workspaceDialog.margin
  370. anchors.leftMargin: workspaceDialog.margin
  371. anchors.rightMargin: workspaceDialog.margin
  372. anchors.bottomMargin: workspaceDialog.margin
  373. anchors.topMargin: warning ? workspaceDialog.margin : 0
  374. anchors.left: parent.left
  375. anchors.right: parent.right
  376. anchors.top: parent.top
  377. RowLayout
  378. {
  379. id: warningRow
  380. height: childrenRect.height
  381. visible: warning
  382. spacing: workspaceDialog.margin
  383. UM.ColorImage
  384. {
  385. width: UM.Theme.getSize("extruder_icon").width
  386. height: UM.Theme.getSize("extruder_icon").height
  387. source: UM.Theme.getIcon("Warning")
  388. }
  389. UM.Label
  390. {
  391. id: warningText
  392. text: catalog.i18nc("@label", "This project contains materials or plugins that are currently not installed in Cura.<br/>Install the missing packages and reopen the project.")
  393. }
  394. }
  395. Loader
  396. {
  397. width: parent.width
  398. height: childrenRect.height
  399. sourceComponent: buttonRow
  400. }
  401. }
  402. }
  403. buttonSpacing: UM.Theme.getSize("wide_margin").width
  404. rightButtons: [
  405. Cura.TertiaryButton
  406. {
  407. visible: !warning
  408. text: catalog.i18nc("@action:button", "Cancel")
  409. onClicked: reject()
  410. },
  411. Cura.PrimaryButton
  412. {
  413. visible: !warning
  414. text: catalog.i18nc("@action:button", "Open")
  415. onClicked: accept()
  416. },
  417. Cura.TertiaryButton
  418. {
  419. visible: warning
  420. text: catalog.i18nc("@action:button", "Open project anyway")
  421. onClicked: {
  422. manager.showMissingMaterialsWarning();
  423. accept();
  424. }
  425. },
  426. Cura.PrimaryButton
  427. {
  428. visible: warning
  429. text: catalog.i18nc("@action:button", "Install missing packages")
  430. onClicked: manager.installMissingPackages()
  431. }
  432. ]
  433. onClosing: manager.notifyClosed()
  434. onRejected: manager.onCancelButtonClicked()
  435. onAccepted: manager.onOkButtonClicked()
  436. onVisibleChanged:
  437. {
  438. if (visible)
  439. {
  440. // Force reload the comboboxes
  441. // Since this dialog is only created once the first time you open it, these comboxes need to be reloaded
  442. // each time it is shown after the first time so that the indexes will update correctly.
  443. materialSection.reloadValues()
  444. profileSection.reloadValues()
  445. printerSection.reloadValues()
  446. ucpProfileSection.reloadValues()
  447. }
  448. }
  449. }