Packages.qml 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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 UM 1.4 as UM
  6. ListView
  7. {
  8. id: packages
  9. width: parent.width
  10. property string pageTitle
  11. property var selectedPackage
  12. property string searchInBrowserUrl
  13. property bool bannerVisible
  14. property var bannerIcon
  15. property string bannerText
  16. property string bannerReadMoreUrl
  17. property var onRemoveBanner
  18. property bool showUpdateButton
  19. property bool showDisableButton
  20. property bool showInstallButton
  21. clip: true
  22. Component.onCompleted: model.updatePackages()
  23. Component.onDestruction: model.cleanUpAPIRequest()
  24. spacing: UM.Theme.getSize("default_margin").height
  25. section.property: "package.sectionTitle"
  26. section.delegate: Rectangle
  27. {
  28. width: packages.width
  29. height: sectionHeaderText.height + UM.Theme.getSize("default_margin").height
  30. color: UM.Theme.getColor("detail_background")
  31. Label
  32. {
  33. id: sectionHeaderText
  34. anchors.verticalCenter: parent.verticalCenter
  35. anchors.left: parent.left
  36. text: section
  37. font: UM.Theme.getFont("large")
  38. color: UM.Theme.getColor("text")
  39. }
  40. }
  41. ScrollBar.vertical: ScrollBar
  42. {
  43. // Vertical ScrollBar, styled similarly to the scrollBar in the settings panel
  44. id: verticalScrollBar
  45. visible: packages.contentHeight > packages.height
  46. anchors.right: parent.right
  47. background: Item {}
  48. contentItem: Rectangle
  49. {
  50. id: scrollViewHandle
  51. implicitWidth: UM.Theme.getSize("scrollbar").width
  52. radius: Math.round(implicitWidth / 2)
  53. color: verticalScrollBar.pressed ? UM.Theme.getColor("scrollbar_handle_down") : verticalScrollBar.hovered ? UM.Theme.getColor("scrollbar_handle_hover") : UM.Theme.getColor("scrollbar_handle")
  54. Behavior on color { ColorAnimation { duration: 50; } }
  55. }
  56. }
  57. delegate: MouseArea
  58. {
  59. id: cardMouseArea
  60. width: parent ? parent.width : 0
  61. height: childrenRect.height
  62. hoverEnabled: true
  63. onClicked:
  64. {
  65. packages.selectedPackage = model.package;
  66. contextStack.push(packageDetailsComponent);
  67. }
  68. PackageCard
  69. {
  70. showUpdateButton: packages.showUpdateButton
  71. showDisableButton: packages.showDisableButton
  72. showInstallButton: packages.showInstallButton
  73. packageData: model.package
  74. width: {
  75. if (verticalScrollBar.visible)
  76. {
  77. return parent.width - UM.Theme.getSize("default_margin").width - UM.Theme.getSize("default_margin").width
  78. }
  79. else
  80. {
  81. return parent.width - UM.Theme.getSize("default_margin").width
  82. }
  83. }
  84. color: cardMouseArea.containsMouse ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("main_background")
  85. }
  86. }
  87. Component
  88. {
  89. id: packageDetailsComponent
  90. PackageDetails
  91. {
  92. packageData: packages.selectedPackage
  93. title: packages.pageTitle
  94. }
  95. }
  96. //Wrapper item to add spacing between content and footer.
  97. footer: Item
  98. {
  99. width: parent.width - UM.Theme.getSize("default_margin").width - UM.Theme.getSize("narrow_margin").width
  100. height: model.hasFooter || packages.model.errorMessage != "" ? UM.Theme.getSize("card").height + packages.spacing : 0
  101. visible: model.hasFooter || packages.model.errorMessage != ""
  102. Button
  103. {
  104. id: loadMoreButton
  105. width: parent.width
  106. height: UM.Theme.getSize("card").height
  107. anchors.bottom: parent.bottom
  108. enabled: packages.model.hasMore && !packages.model.isLoading || packages.model.errorMessage != ""
  109. onClicked: packages.model.updatePackages() //Load next page in plug-in list.
  110. background: Rectangle
  111. {
  112. anchors.fill: parent
  113. radius: UM.Theme.getSize("default_radius").width
  114. color: UM.Theme.getColor("main_background")
  115. }
  116. Row
  117. {
  118. anchors.centerIn: parent
  119. spacing: UM.Theme.getSize("thin_margin").width
  120. states:
  121. [
  122. State
  123. {
  124. name: "Error"
  125. when: packages.model.errorMessage != ""
  126. PropertyChanges
  127. {
  128. target: errorIcon
  129. visible: true
  130. }
  131. PropertyChanges
  132. {
  133. target: loadMoreIcon
  134. visible: false
  135. }
  136. PropertyChanges
  137. {
  138. target: loadMoreLabel
  139. text: catalog.i18nc("@button", "Failed to load packages:") + " " + packages.model.errorMessage + "\n" + catalog.i18nc("@button", "Retry?")
  140. }
  141. },
  142. State
  143. {
  144. name: "Loading"
  145. when: packages.model.isLoading
  146. PropertyChanges
  147. {
  148. target: loadMoreIcon
  149. source: UM.Theme.getIcon("ArrowDoubleCircleRight")
  150. color: UM.Theme.getColor("action_button_disabled_text")
  151. }
  152. PropertyChanges
  153. {
  154. target: loadMoreLabel
  155. text: catalog.i18nc("@button", "Loading")
  156. color: UM.Theme.getColor("action_button_disabled_text")
  157. }
  158. },
  159. State
  160. {
  161. name: "LastPage"
  162. when: !packages.model.hasMore
  163. PropertyChanges
  164. {
  165. target: loadMoreIcon
  166. visible: false
  167. }
  168. PropertyChanges
  169. {
  170. target: loadMoreLabel
  171. text: packages.model.count > 0 ? catalog.i18nc("@message", "No more results to load") : catalog.i18nc("@message", "No results found with current filter")
  172. color: UM.Theme.getColor("action_button_disabled_text")
  173. }
  174. }
  175. ]
  176. Item
  177. {
  178. width: (errorIcon.visible || loadMoreIcon.visible) ? UM.Theme.getSize("small_button_icon").width : 0
  179. height: UM.Theme.getSize("small_button_icon").height
  180. anchors.verticalCenter: loadMoreLabel.verticalCenter
  181. UM.StatusIcon
  182. {
  183. id: errorIcon
  184. anchors.fill: parent
  185. status: UM.StatusIcon.Status.ERROR
  186. visible: false
  187. }
  188. UM.RecolorImage
  189. {
  190. id: loadMoreIcon
  191. anchors.fill: parent
  192. source: UM.Theme.getIcon("ArrowDown")
  193. color: UM.Theme.getColor("secondary_button_text")
  194. RotationAnimator
  195. {
  196. target: loadMoreIcon
  197. from: 0
  198. to: 360
  199. duration: 1000
  200. loops: Animation.Infinite
  201. running: packages.model.isLoading
  202. alwaysRunToEnd: true
  203. }
  204. }
  205. }
  206. Label
  207. {
  208. id: loadMoreLabel
  209. text: catalog.i18nc("@button", "Load more")
  210. font: UM.Theme.getFont("medium_bold")
  211. color: UM.Theme.getColor("secondary_button_text")
  212. }
  213. }
  214. }
  215. }
  216. }