Marketplace.qml 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright (c) 2021 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.15
  4. import QtQuick.Controls 2.15
  5. import QtQuick.Layouts 1.15
  6. import QtQuick.Window 2.2
  7. import UM 1.5 as UM
  8. import Cura 1.6 as Cura
  9. Window
  10. {
  11. id: marketplaceDialog
  12. property variant catalog: UM.I18nCatalog { name: "cura" }
  13. signal searchStringChanged(string new_search)
  14. minimumWidth: UM.Theme.getSize("modal_window_minimum").width
  15. minimumHeight: UM.Theme.getSize("modal_window_minimum").height
  16. width: minimumWidth
  17. height: minimumHeight
  18. onVisibleChanged:
  19. {
  20. while(contextStack.depth > 1)
  21. {
  22. contextStack.pop(); //Do NOT use the StackView.Immediate transition here, since it causes the window to stay empty. Seemingly a Qt bug: https://bugreports.qt.io/browse/QTBUG-60670?
  23. }
  24. }
  25. Connections
  26. {
  27. target: Cura.API.account
  28. function onLoginStateChanged()
  29. {
  30. close();
  31. }
  32. }
  33. title: "Marketplace" //Seen by Ultimaker as a brand name, so this doesn't get translated.
  34. modality: Qt.NonModal
  35. // Background color
  36. Rectangle
  37. {
  38. anchors.fill: parent
  39. color: UM.Theme.getColor("main_background")
  40. }
  41. //The Marketplace can have a page in front of everything with package details. The stack view controls its visibility.
  42. StackView
  43. {
  44. id: contextStack
  45. anchors.fill: parent
  46. initialItem: packageBrowse
  47. ColumnLayout
  48. {
  49. id: packageBrowse
  50. spacing: UM.Theme.getSize("narrow_margin").height
  51. // Page title.
  52. Item
  53. {
  54. Layout.preferredWidth: parent.width
  55. Layout.preferredHeight: childrenRect.height + UM.Theme.getSize("default_margin").height
  56. UM.Label
  57. {
  58. id: pageTitle
  59. anchors
  60. {
  61. left: parent.left
  62. leftMargin: UM.Theme.getSize("default_margin").width
  63. right: parent.right
  64. rightMargin: UM.Theme.getSize("default_margin").width
  65. bottom: parent.bottom
  66. }
  67. font: UM.Theme.getFont("large")
  68. text: content.item ? content.item.pageTitle: catalog.i18nc("@title", "Loading...")
  69. }
  70. }
  71. OnboardBanner
  72. {
  73. visible: content.item && content.item.bannerVisible
  74. text: content.item && content.item.bannerText
  75. icon: content.item && content.item.bannerIcon
  76. onRemove: content.item && content.item.onRemoveBanner
  77. readMoreUrl: content.item && content.item.bannerReadMoreUrl
  78. Layout.fillWidth: true
  79. Layout.leftMargin: UM.Theme.getSize("default_margin").width
  80. Layout.rightMargin: UM.Theme.getSize("default_margin").width
  81. }
  82. // Search & Top-Level Tabs
  83. Item
  84. {
  85. implicitHeight: childrenRect.height
  86. implicitWidth: parent.width - 2 * UM.Theme.getSize("default_margin").width
  87. Layout.alignment: Qt.AlignHCenter
  88. RowLayout
  89. {
  90. width: parent.width
  91. height: UM.Theme.getSize("button_icon").height + UM.Theme.getSize("default_margin").height
  92. spacing: UM.Theme.getSize("thin_margin").width
  93. Cura.SearchBar
  94. {
  95. id: searchBar
  96. implicitHeight: UM.Theme.getSize("button_icon").height
  97. Layout.fillWidth: true
  98. onTextEdited: searchStringChanged(text)
  99. }
  100. // Page selection.
  101. TabBar
  102. {
  103. id: pageSelectionTabBar
  104. Layout.alignment: Qt.AlignRight
  105. height: UM.Theme.getSize("button_icon").height
  106. spacing: 0
  107. background: Rectangle { color: "transparent" }
  108. currentIndex: manager.tabShown
  109. onCurrentIndexChanged:
  110. {
  111. manager.tabShown = currentIndex
  112. searchBar.text = "";
  113. searchBar.visible = currentItem.hasSearch;
  114. content.source = currentItem.sourcePage;
  115. }
  116. PackageTypeTab
  117. {
  118. id: pluginTabText
  119. width: implicitWidth
  120. text: catalog.i18nc("@button", "Plugins")
  121. property string sourcePage: "Plugins.qml"
  122. property bool hasSearch: true
  123. }
  124. PackageTypeTab
  125. {
  126. id: materialsTabText
  127. width: implicitWidth
  128. text: catalog.i18nc("@button", "Materials")
  129. property string sourcePage: "Materials.qml"
  130. property bool hasSearch: true
  131. }
  132. ManagePackagesButton
  133. {
  134. property string sourcePage: "ManagedPackages.qml"
  135. property bool hasSearch: false
  136. Cura.NotificationIcon
  137. {
  138. anchors
  139. {
  140. horizontalCenter: parent.right
  141. verticalCenter: parent.top
  142. }
  143. visible: CuraApplication.getPackageManager().packagesWithUpdate.length > 0
  144. labelText:
  145. {
  146. const itemCount = CuraApplication.getPackageManager().packagesWithUpdate.length
  147. return itemCount > 9 ? "9+" : itemCount
  148. }
  149. }
  150. }
  151. }
  152. }
  153. }
  154. FontMetrics
  155. {
  156. id: fontMetrics
  157. font: UM.Theme.getFont("default")
  158. }
  159. Cura.TertiaryButton
  160. {
  161. text: catalog.i18nc("@info", "Search in the browser")
  162. iconSource: UM.Theme.getIcon("LinkExternal")
  163. visible: pageSelectionTabBar.currentItem.hasSearch
  164. isIconOnRightSide: true
  165. height: fontMetrics.height
  166. textFont: fontMetrics.font
  167. textColor: UM.Theme.getColor("text")
  168. onClicked: content.item && Qt.openUrlExternally(content.item.searchInBrowserUrl)
  169. }
  170. // Page contents.
  171. Rectangle
  172. {
  173. Layout.preferredWidth: parent.width
  174. Layout.fillHeight: true
  175. color: UM.Theme.getColor("detail_background")
  176. // Page contents.
  177. Loader
  178. {
  179. id: content
  180. anchors.fill: parent
  181. anchors.margins: UM.Theme.getSize("default_margin").width
  182. source: "Plugins.qml"
  183. Connections
  184. {
  185. target: content
  186. function onLoaded()
  187. {
  188. pageTitle.text = content.item.pageTitle
  189. searchStringChanged.connect(handleSearchStringChanged)
  190. }
  191. function handleSearchStringChanged(new_search)
  192. {
  193. content.item.model.searchString = new_search
  194. }
  195. }
  196. }
  197. }
  198. }
  199. }
  200. Rectangle
  201. {
  202. height: quitButton.height + 2 * UM.Theme.getSize("default_margin").width
  203. color: UM.Theme.getColor("primary")
  204. visible: manager.showRestartNotification
  205. anchors
  206. {
  207. left: parent.left
  208. right: parent.right
  209. bottom: parent.bottom
  210. }
  211. RowLayout
  212. {
  213. anchors
  214. {
  215. left: parent.left
  216. right: parent.right
  217. verticalCenter: parent.verticalCenter
  218. margins: UM.Theme.getSize("default_margin").width
  219. }
  220. spacing: UM.Theme.getSize("default_margin").width
  221. UM.ColorImage
  222. {
  223. id: bannerIcon
  224. source: UM.Theme.getIcon("Plugin")
  225. color: UM.Theme.getColor("primary_button_text")
  226. implicitWidth: UM.Theme.getSize("banner_icon_size").width
  227. implicitHeight: UM.Theme.getSize("banner_icon_size").height
  228. }
  229. Text
  230. {
  231. color: UM.Theme.getColor("primary_button_text")
  232. text: catalog.i18nc("@button", "In order to use the package you will need to restart Cura")
  233. font: UM.Theme.getFont("default")
  234. renderType: Text.NativeRendering
  235. Layout.fillWidth: true
  236. }
  237. Cura.SecondaryButton
  238. {
  239. id: quitButton
  240. text: catalog.i18nc("@info:button, %1 is the application name", "Quit %1").arg(CuraApplication.applicationDisplayName)
  241. onClicked:
  242. {
  243. marketplaceDialog.hide();
  244. CuraApplication.closeApplication();
  245. }
  246. }
  247. }
  248. }
  249. }