AddLocalPrinterScrollView.qml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. // Copyright (c) 2023 UltiMaker
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.15
  4. import QtQuick.Controls 2.14
  5. import UM 1.5 as UM
  6. import Cura 1.1 as Cura
  7. //
  8. // This is the scroll view widget for adding a (local) printer. This scroll view shows a list view with printers
  9. // categorized into 3 categories: "Ultimaker", "Custom", and "Other".
  10. //
  11. Item
  12. {
  13. id: base
  14. property bool hasSearchFilter: false
  15. // The currently selected machine item in the local machine list.
  16. property var currentItem: machineList.currentIndex >= 0 ? machineList.model.getItem(machineList.currentIndex) : null
  17. // The currently active (expanded) section/category, where section/category is the grouping of local machine items.
  18. property var currentSections: new Set()
  19. // By default (when this list shows up) we always expand the "Ultimaker" section.
  20. property var preferredCategories: {
  21. "Ultimaker B.V.": -2,
  22. "Custom": -1
  23. }
  24. // User-editable printer name
  25. property alias printerName: printerNameTextField.text
  26. property alias isPrinterNameValid: printerNameTextField.acceptableInput
  27. onCurrentItemChanged:
  28. {
  29. printerName = currentItem && currentItem.name? currentItem.name: ""
  30. }
  31. function updateCurrentItemUponSectionChange(section)
  32. {
  33. // Find the first machine from this section
  34. for (var i = 0; i < machineList.count; i ++)
  35. {
  36. const item = machineList.model.getItem(i);
  37. if (item.section == section)
  38. {
  39. updateCurrentItem(i)
  40. break;
  41. }
  42. }
  43. }
  44. function updateCurrentItem(index)
  45. {
  46. machineList.currentIndex = index;
  47. currentItem = machineList.model.getItem(index);
  48. if (currentItem && currentItem.name)
  49. {
  50. machineName.text = currentItem.name
  51. manufacturer.text = currentItem.metadata["manufacturer"]
  52. author.text = currentItem.metadata["author"]
  53. }
  54. else
  55. {
  56. machineName.text = "No printers Found"
  57. manufacturer.text = ""
  58. author.text = ""
  59. }
  60. }
  61. Component.onCompleted:
  62. {
  63. const initialSection = "Ultimaker B.V.";
  64. base.currentSections.add(initialSection);
  65. updateCurrentItemUponSectionChange(initialSection);
  66. // Trigger update on base.currentSections
  67. base.currentSections = base.currentSections;
  68. }
  69. Row
  70. {
  71. id: localPrinterSelectionItem
  72. anchors.fill: parent
  73. Column
  74. {
  75. id: root
  76. width: Math.floor(parent.width * 0.48)
  77. height: parent.height
  78. Item
  79. {
  80. width: root.width
  81. height: filter.height
  82. Cura.TextField
  83. {
  84. id: filter
  85. width: parent.width
  86. implicitHeight: parent.height
  87. background: Rectangle {
  88. id: background
  89. color: UM.Theme.getColor("main_background")
  90. radius: UM.Theme.getSize("default_radius").width
  91. border.color: UM.Theme.getColor("primary_button")
  92. }
  93. height: UM.Theme.getSize("small_button_icon").height * 2
  94. placeholderText: catalog.i18nc("@label:textbox", "Search Printer")
  95. placeholderTextColor: UM.Theme.getColor("primary_button")
  96. font: UM.Theme.getFont("medium_italic")
  97. leftPadding: searchIcon.width + UM.Theme.getSize("default_margin").width * 2
  98. UM.ColorImage
  99. {
  100. id: searchIcon
  101. source: UM.Theme.getIcon("Magnifier")
  102. anchors
  103. {
  104. verticalCenter: parent.verticalCenter
  105. left: parent.left
  106. leftMargin: UM.Theme.getSize("default_margin").width
  107. }
  108. height: UM.Theme.getSize("small_button_icon").height
  109. width: height
  110. color: UM.Theme.getColor("text")
  111. }
  112. onTextChanged: editingFinished()
  113. onEditingFinished:
  114. {
  115. machineDefinitionsModel.filter = {"name" : "*" + text.toLowerCase() + "*", "visible": true}
  116. base.hasSearchFilter = (text.length > 0)
  117. updateDefinitionModel()
  118. }
  119. Keys.onEscapePressed: filter.text = ""
  120. function updateDefinitionModel()
  121. {
  122. if (base.hasSearchFilter)
  123. {
  124. base.currentSections.clear()
  125. for (var i = 0; i < machineDefinitionsModel.count; i++)
  126. {
  127. var sectionexpanded = machineDefinitionsModel.getItem(i)["section"]
  128. if (!base.currentSections.has(sectionexpanded))
  129. {
  130. base.currentSections.add(sectionexpanded);
  131. }
  132. }
  133. base.updateCurrentItem(0)
  134. // Trigger update on base.currentSections
  135. base.currentSections = base.currentSections;
  136. }
  137. else
  138. {
  139. const initialSection = "Ultimaker B.V.";
  140. base.currentSections.clear();
  141. base.currentSections.add(initialSection);
  142. updateCurrentItemUponSectionChange(initialSection);
  143. updateCurrentItem(0)
  144. // Trigger update on base.currentSections
  145. base.currentSections = base.currentSections;
  146. }
  147. }
  148. }
  149. UM.SimpleButton
  150. {
  151. id: clearFilterButton
  152. iconSource: UM.Theme.getIcon("Cancel")
  153. visible: base.hasSearchFilter
  154. height: Math.round(filter.height * 0.5)
  155. width: visible ? height : 0
  156. anchors.verticalCenter: filter.verticalCenter
  157. anchors.right: filter.right
  158. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  159. color: UM.Theme.getColor("setting_control_button")
  160. hoverColor: UM.Theme.getColor("setting_control_button_hover")
  161. onClicked:
  162. {
  163. filter.text = ""
  164. filter.forceActiveFocus()
  165. }
  166. }
  167. }
  168. //Selecting a local printer to add from this list.
  169. ListView
  170. {
  171. id: machineList
  172. width: root.width
  173. height: root.height - filter.height
  174. clip: true
  175. ScrollBar.vertical: UM.ScrollBar {}
  176. model: UM.DefinitionContainersModel
  177. {
  178. id: machineDefinitionsModel
  179. filter: { "visible": true }
  180. sectionProperty: "manufacturer"
  181. preferredSections: preferredCategories
  182. }
  183. section.property: "section"
  184. section.delegate: Button
  185. {
  186. id: button
  187. width: machineList.width
  188. height: UM.Theme.getSize("action_button").height
  189. text: section
  190. property bool isActive: base.currentSections.has(section)
  191. background: Rectangle
  192. {
  193. anchors.fill: parent
  194. color: isActive ? UM.Theme.getColor("setting_control_highlight") : "transparent"
  195. }
  196. contentItem: Item
  197. {
  198. width: childrenRect.width
  199. height: UM.Theme.getSize("action_button").height
  200. UM.ColorImage
  201. {
  202. id: arrow
  203. anchors.left: parent.left
  204. width: UM.Theme.getSize("standard_arrow").width
  205. height: UM.Theme.getSize("standard_arrow").height
  206. color: UM.Theme.getColor("text")
  207. source: isActive ? UM.Theme.getIcon("ChevronSingleDown") : UM.Theme.getIcon("ChevronSingleRight")
  208. }
  209. UM.Label
  210. {
  211. id: label
  212. anchors.left: arrow.right
  213. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  214. text: button.text
  215. font: UM.Theme.getFont("default_bold")
  216. }
  217. }
  218. onClicked:
  219. {
  220. if (base.currentSections.has(section))
  221. {
  222. base.currentSections.delete(section);
  223. }
  224. else
  225. {
  226. base.currentSections.add(section);
  227. base.updateCurrentItemUponSectionChange(section);
  228. }
  229. // Trigger update on base.currentSections
  230. base.currentSections = base.currentSections;
  231. }
  232. }
  233. delegate: Cura.RadioButton
  234. {
  235. id: radioButton
  236. anchors
  237. {
  238. left: parent !== null ? parent.left : undefined
  239. leftMargin: UM.Theme.getSize("standard_list_lineheight").width
  240. right: parent !== null ? parent.right : undefined
  241. rightMargin: UM.Theme.getSize("default_margin").width
  242. }
  243. height: visible ? UM.Theme.getSize("standard_list_lineheight").height : 0 //This causes the scrollbar to vary in length due to QTBUG-76830.
  244. checked: machineList.currentIndex == index
  245. text: name
  246. visible: base.currentSections.has(section)
  247. onClicked: base.updateCurrentItem(index)
  248. }
  249. }
  250. }
  251. // Vertical line
  252. Rectangle
  253. {
  254. id: verticalLine
  255. anchors.top: parent.top
  256. height: parent.height - UM.Theme.getSize("default_lining").height
  257. width: UM.Theme.getSize("default_lining").height
  258. color: UM.Theme.getColor("lining")
  259. }
  260. // User-editable printer name row
  261. Column
  262. {
  263. width: Math.floor(parent.width * 0.52)
  264. spacing: UM.Theme.getSize("default_margin").width
  265. padding: UM.Theme.getSize("default_margin").width
  266. UM.Label
  267. {
  268. id: machineName
  269. width: parent.width - (2 * UM.Theme.getSize("default_margin").width)
  270. color: UM.Theme.getColor("primary_button")
  271. font: UM.Theme.getFont("huge")
  272. elide: Text.ElideRight
  273. }
  274. Grid
  275. {
  276. width: parent.width
  277. columns: 2
  278. rowSpacing: UM.Theme.getSize("default_lining").height
  279. columnSpacing: UM.Theme.getSize("default_margin").width
  280. verticalItemAlignment: Grid.AlignVCenter
  281. UM.Label
  282. {
  283. id: manufacturerLabel
  284. text: catalog.i18nc("@label", "Manufacturer")
  285. }
  286. UM.Label
  287. {
  288. id: manufacturer
  289. width: parent.width - manufacturerLabel.width
  290. wrapMode: Text.WordWrap
  291. }
  292. UM.Label
  293. {
  294. id: profileAuthorLabel
  295. text: catalog.i18nc("@label", "Profile author")
  296. }
  297. UM.Label
  298. {
  299. id: author
  300. width: parent.width - profileAuthorLabel.width
  301. wrapMode: Text.WordWrap
  302. }
  303. UM.Label
  304. {
  305. id: printerNameLabel
  306. text: catalog.i18nc("@label", "Printer name")
  307. }
  308. Cura.TextField
  309. {
  310. id: printerNameTextField
  311. placeholderText: catalog.i18nc("@text", "Please name your printer")
  312. maximumLength: 40
  313. width: parent.width - (printerNameLabel.width + (3 * UM.Theme.getSize("default_margin").width))
  314. validator: RegularExpressionValidator
  315. {
  316. regularExpression: printerNameTextField.machineNameValidator.machineNameRegex
  317. }
  318. property var machineNameValidator: Cura.MachineNameValidator { }
  319. }
  320. }
  321. }
  322. }
  323. }