SelectProjectPage.qml 8.6 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.10
  4. import QtQuick.Window 2.2
  5. import QtQuick.Controls 2.2 as OldControls // TableView doesn't exist in the QtQuick Controls 2.x in 5.10, so use the old one
  6. import QtQuick.Controls 2.3
  7. import QtQuick.Controls.Styles 2.2
  8. import QtQuick.Layouts 1.1
  9. import UM 1.2 as UM
  10. import Cura 1.6 as Cura
  11. import DigitalFactory 1.0 as DF
  12. Item
  13. {
  14. id: base
  15. width: parent.width
  16. height: parent.height
  17. property bool createNewProjectButtonVisible: true
  18. anchors
  19. {
  20. top: parent.top
  21. bottom: parent.bottom
  22. left: parent.left
  23. right: parent.right
  24. margins: UM.Theme.getSize("default_margin").width
  25. }
  26. RowLayout
  27. {
  28. id: headerRow
  29. anchors
  30. {
  31. top: parent.top
  32. left: parent.left
  33. right: parent.right
  34. }
  35. height: childrenRect.height
  36. spacing: UM.Theme.getSize("default_margin").width
  37. Cura.TextField
  38. {
  39. id: searchBar
  40. Layout.fillWidth: true
  41. implicitHeight: createNewProjectButton.height
  42. leftPadding: searchIcon.width + UM.Theme.getSize("default_margin").width * 2
  43. onTextEdited: manager.projectFilter = text //Update the search filter when editing this text field.
  44. placeholderText: "Search"
  45. UM.RecolorImage
  46. {
  47. id: searchIcon
  48. anchors
  49. {
  50. verticalCenter: parent.verticalCenter
  51. left: parent.left
  52. leftMargin: UM.Theme.getSize("default_margin").width
  53. }
  54. source: UM.Theme.getIcon("search")
  55. height: UM.Theme.getSize("small_button_icon").height
  56. width: height
  57. color: UM.Theme.getColor("text")
  58. }
  59. }
  60. Cura.SecondaryButton
  61. {
  62. id: createNewProjectButton
  63. text: "New Library project"
  64. visible: createNewProjectButtonVisible && manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed)
  65. onClicked:
  66. {
  67. createNewProjectPopup.open()
  68. }
  69. busy: manager.creatingNewProjectStatus == DF.RetrievalStatus.InProgress
  70. }
  71. Cura.SecondaryButton
  72. {
  73. id: upgradePlanButton
  74. text: "Upgrade plan"
  75. iconSource: UM.Theme.getIcon("external_link")
  76. visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed)
  77. tooltip: "Maximum number of projects reached. Please upgrade your subscription to create more projects."
  78. onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software?utm_source=cura&utm_medium=software&utm_campaign=MaxProjLink")
  79. }
  80. }
  81. Item
  82. {
  83. id: noLibraryProjectsContainer
  84. anchors
  85. {
  86. top: parent.top
  87. bottom: parent.bottom
  88. left: parent.left
  89. right: parent.right
  90. }
  91. visible: manager.digitalFactoryProjectModel.count == 0 && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed)
  92. Column
  93. {
  94. anchors.centerIn: parent
  95. spacing: UM.Theme.getSize("thin_margin").height
  96. Image
  97. {
  98. id: digitalFactoryImage
  99. anchors.horizontalCenter: parent.horizontalCenter
  100. source: searchBar.text === "" ? "../images/digital_factory.svg" : "../images/projects_not_found.svg"
  101. fillMode: Image.PreserveAspectFit
  102. width: parent.width - 2 * UM.Theme.getSize("thick_margin").width
  103. }
  104. Label
  105. {
  106. id: noLibraryProjectsLabel
  107. anchors.horizontalCenter: parent.horizontalCenter
  108. text: searchBar.text === "" ? "It appears that you don't have any projects in the Library yet." : "No projects found that match the search query."
  109. font: UM.Theme.getFont("medium")
  110. color: UM.Theme.getColor("text")
  111. }
  112. Cura.TertiaryButton
  113. {
  114. id: visitDigitalLibraryButton
  115. anchors.horizontalCenter: parent.horizontalCenter
  116. text: "Visit Digital Library"
  117. onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "/app/library?utm_source=cura&utm_medium=software&utm_campaign=empty-library")
  118. visible: searchBar.text === "" //Show the link to Digital Library when there are no projects in the user's Library.
  119. }
  120. }
  121. }
  122. Item
  123. {
  124. id: projectListContainer
  125. anchors
  126. {
  127. top: headerRow.bottom
  128. topMargin: UM.Theme.getSize("default_margin").height
  129. bottom: parent.bottom
  130. left: parent.left
  131. right: parent.right
  132. }
  133. visible: manager.digitalFactoryProjectModel.count > 0
  134. // Use a flickable and a column with a repeater instead of a ListView in a ScrollView, because the ScrollView cannot
  135. // have additional children (aside from the view inside it), which wouldn't allow us to add the LoadMoreProjectsCard
  136. // in it.
  137. Flickable
  138. {
  139. id: flickableView
  140. clip: true
  141. contentWidth: parent.width
  142. contentHeight: projectsListView.implicitHeight
  143. anchors.fill: parent
  144. ScrollBar.vertical: ScrollBar
  145. {
  146. // Vertical ScrollBar, styled similarly to the scrollBar in the settings panel
  147. id: verticalScrollBar
  148. visible: flickableView.contentHeight > flickableView.height
  149. background: Rectangle
  150. {
  151. implicitWidth: UM.Theme.getSize("scrollbar").width
  152. radius: Math.round(implicitWidth / 2)
  153. color: UM.Theme.getColor("scrollbar_background")
  154. }
  155. contentItem: Rectangle
  156. {
  157. id: scrollViewHandle
  158. implicitWidth: UM.Theme.getSize("scrollbar").width
  159. radius: Math.round(implicitWidth / 2)
  160. color: verticalScrollBar.pressed ? UM.Theme.getColor("scrollbar_handle_down") : verticalScrollBar.hovered ? UM.Theme.getColor("scrollbar_handle_hover") : UM.Theme.getColor("scrollbar_handle")
  161. Behavior on color { ColorAnimation { duration: 50; } }
  162. }
  163. }
  164. Column
  165. {
  166. id: projectsListView
  167. width: verticalScrollBar.visible ? parent.width - verticalScrollBar.width - UM.Theme.getSize("default_margin").width : parent.width
  168. anchors.top: parent.top
  169. spacing: UM.Theme.getSize("narrow_margin").width
  170. Repeater
  171. {
  172. model: manager.digitalFactoryProjectModel
  173. delegate: ProjectSummaryCard
  174. {
  175. id: projectSummaryCard
  176. imageSource: model.thumbnailUrl || "../images/placeholder.svg"
  177. projectNameText: model.displayName
  178. projectUsernameText: model.username
  179. projectLastUpdatedText: "Last updated: " + model.lastUpdated
  180. onClicked:
  181. {
  182. manager.selectedProjectIndex = index
  183. }
  184. }
  185. }
  186. LoadMoreProjectsCard
  187. {
  188. id: loadMoreProjectsCard
  189. height: UM.Theme.getSize("toolbox_thumbnail_small").height
  190. width: parent.width
  191. visible: manager.digitalFactoryProjectModel.count > 0
  192. hasMoreProjectsToLoad: manager.hasMoreProjectsToLoad
  193. onClicked:
  194. {
  195. manager.loadMoreProjects()
  196. }
  197. }
  198. }
  199. }
  200. }
  201. CreateNewProjectPopup
  202. {
  203. id: createNewProjectPopup
  204. width: 400 * screenScaleFactor
  205. height: 220 * screenScaleFactor
  206. x: Math.round((parent.width - width) / 2)
  207. y: Math.round((parent.height - height) / 2)
  208. }
  209. }