Window.qml 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. import QtQml 2.12
  2. import QtQml.Models 2.1
  3. import QtQuick 2.15
  4. import QtQuick.Window 2.3
  5. import QtQuick.Controls 2.3
  6. import QtQuick.Layouts 1.2
  7. import QtGraphicalEffects 1.0
  8. import "../"
  9. // Custom qml modules are in /theme (and included by resources.qrc)
  10. import Style 1.0
  11. import com.nextcloud.desktopclient 1.0
  12. Window {
  13. id: trayWindow
  14. title: Systray.windowTitle
  15. // If the main dialog is displayed as a regular window we want it to be quadratic
  16. width: Systray.useNormalWindow ? Style.trayWindowHeight : Style.trayWindowWidth
  17. height: Style.trayWindowHeight
  18. color: "transparent"
  19. flags: Systray.useNormalWindow ? Qt.Window : Qt.Dialog | Qt.FramelessWindowHint
  20. property var fileActivityDialogAbsolutePath: ""
  21. readonly property int maxMenuHeight: Style.trayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth
  22. function openFileActivityDialog(displayPath, absolutePath) {
  23. fileActivityDialogLoader.displayPath = displayPath
  24. fileActivityDialogLoader.absolutePath = absolutePath
  25. fileActivityDialogLoader.refresh()
  26. }
  27. Component.onCompleted: Systray.forceWindowInit(trayWindow)
  28. // Close tray window when focus is lost (e.g. click somewhere else on the screen)
  29. onActiveChanged: {
  30. if (!Systray.useNormalWindow && !active) {
  31. hide();
  32. Systray.setClosed();
  33. }
  34. }
  35. onClosing: {
  36. Systray.setClosed()
  37. }
  38. onVisibleChanged: {
  39. // HACK: reload account Instantiator immediately by restting it - could be done better I guess
  40. // see also id:accountMenu below
  41. userLineInstantiator.active = false;
  42. userLineInstantiator.active = true;
  43. syncStatus.model.load();
  44. }
  45. Connections {
  46. target: UserModel
  47. function onNewUserSelected() {
  48. accountMenu.close();
  49. syncStatus.model.load();
  50. }
  51. }
  52. Connections {
  53. target: Systray
  54. function onShowWindow() {
  55. accountMenu.close();
  56. appsMenu.close();
  57. Systray.positionWindow(trayWindow);
  58. trayWindow.show();
  59. trayWindow.raise();
  60. trayWindow.requestActivate();
  61. Systray.setOpened();
  62. UserModel.fetchCurrentActivityModel();
  63. }
  64. function onHideWindow() {
  65. trayWindow.hide();
  66. Systray.setClosed();
  67. }
  68. function onShowFileActivityDialog(displayPath, absolutePath) {
  69. openFileActivityDialog(displayPath, absolutePath)
  70. }
  71. }
  72. OpacityMask {
  73. anchors.fill: parent
  74. source: ShaderEffectSource {
  75. sourceItem: trayWindowBackground
  76. hideSource: true
  77. }
  78. maskSource: Rectangle {
  79. width: trayWindowBackground.width
  80. height: trayWindowBackground.height
  81. radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius
  82. }
  83. }
  84. Rectangle {
  85. id: trayWindowBackground
  86. property bool isUnifiedSearchActive: unifiedSearchResultsListViewSkeleton.visible
  87. || unifiedSearchResultNothingFound.visible
  88. || unifiedSearchResultsErrorLabel.visible
  89. || unifiedSearchResultsListView.visible
  90. anchors.fill: parent
  91. radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius
  92. border.width: Style.trayWindowBorderWidth
  93. border.color: Style.menuBorder
  94. Accessible.role: Accessible.Grouping
  95. Accessible.name: qsTr("Nextcloud desktop main dialog")
  96. Rectangle {
  97. id: trayWindowHeaderBackground
  98. anchors.left: trayWindowBackground.left
  99. anchors.right: trayWindowBackground.right
  100. anchors.top: trayWindowBackground.top
  101. height: Style.trayWindowHeaderHeight
  102. color: Style.ncBlue
  103. RowLayout {
  104. id: trayWindowHeaderLayout
  105. spacing: 0
  106. anchors.fill: parent
  107. Button {
  108. id: currentAccountButton
  109. Layout.preferredWidth: Style.currentAccountButtonWidth
  110. Layout.preferredHeight: Style.trayWindowHeaderHeight
  111. display: AbstractButton.IconOnly
  112. flat: true
  113. Accessible.role: Accessible.ButtonMenu
  114. Accessible.name: qsTr("Current account")
  115. Accessible.onPressAction: currentAccountButton.clicked()
  116. MouseArea {
  117. id: accountBtnMouseArea
  118. anchors.fill: parent
  119. hoverEnabled: Style.hoverEffectsEnabled
  120. // We call open() instead of popup() because we want to position it
  121. // exactly below the dropdown button, not the mouse
  122. onClicked: {
  123. syncPauseButton.text = Systray.syncIsPaused() ? qsTr("Resume sync for all") : qsTr("Pause sync for all")
  124. if (accountMenu.visible) {
  125. accountMenu.close()
  126. } else {
  127. accountMenu.open()
  128. }
  129. }
  130. Loader {
  131. id: userStatusSelectorDialogLoader
  132. }
  133. Menu {
  134. id: accountMenu
  135. // x coordinate grows towards the right
  136. // y coordinate grows towards the bottom
  137. x: (currentAccountButton.x + 2)
  138. y: (currentAccountButton.y + Style.trayWindowHeaderHeight + 2)
  139. width: (Style.currentAccountButtonWidth - 2)
  140. height: Math.min(implicitHeight, maxMenuHeight)
  141. closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
  142. background: Rectangle {
  143. border.color: Style.menuBorder
  144. radius: Style.currentAccountButtonRadius
  145. }
  146. onClosed: {
  147. // HACK: reload account Instantiator immediately by restting it - could be done better I guess
  148. // see also onVisibleChanged above
  149. userLineInstantiator.active = false;
  150. userLineInstantiator.active = true;
  151. }
  152. Instantiator {
  153. id: userLineInstantiator
  154. model: UserModel
  155. delegate: UserLine {
  156. onShowUserStatusSelectorDialog: {
  157. userStatusSelectorDialogLoader.source = "qrc:/qml/src/gui/UserStatusSelectorDialog.qml"
  158. userStatusSelectorDialogLoader.item.title = qsTr("Set user status")
  159. userStatusSelectorDialogLoader.item.model.load(index)
  160. userStatusSelectorDialogLoader.item.show()
  161. }
  162. }
  163. onObjectAdded: accountMenu.insertItem(index, object)
  164. onObjectRemoved: accountMenu.removeItem(object)
  165. }
  166. MenuItem {
  167. id: addAccountButton
  168. height: Style.addAccountButtonHeight
  169. hoverEnabled: true
  170. background: Item {
  171. height: parent.height
  172. width: parent.menu.width
  173. Rectangle {
  174. anchors.fill: parent
  175. anchors.margins: 1
  176. color: parent.parent.hovered ? Style.lightHover : "transparent"
  177. }
  178. }
  179. RowLayout {
  180. anchors.fill: parent
  181. spacing: 0
  182. Image {
  183. Layout.leftMargin: 12
  184. verticalAlignment: Qt.AlignCenter
  185. source: "qrc:///client/theme/black/add.svg"
  186. sourceSize.width: Style.headerButtonIconSize
  187. sourceSize.height: Style.headerButtonIconSize
  188. }
  189. Label {
  190. Layout.leftMargin: 14
  191. text: qsTr("Add account")
  192. color: "black"
  193. font.pixelSize: Style.topLinePixelSize
  194. }
  195. // Filler on the right
  196. Item {
  197. Layout.fillWidth: true
  198. Layout.fillHeight: true
  199. }
  200. }
  201. onClicked: UserModel.addAccount()
  202. Accessible.role: Accessible.MenuItem
  203. Accessible.name: qsTr("Add new account")
  204. Accessible.onPressAction: addAccountButton.clicked()
  205. }
  206. MenuSeparator {
  207. contentItem: Rectangle {
  208. implicitHeight: 1
  209. color: Style.menuBorder
  210. }
  211. }
  212. MenuItem {
  213. id: syncPauseButton
  214. font.pixelSize: Style.topLinePixelSize
  215. hoverEnabled: true
  216. onClicked: Systray.pauseResumeSync()
  217. background: Item {
  218. height: parent.height
  219. width: parent.menu.width
  220. Rectangle {
  221. anchors.fill: parent
  222. anchors.margins: 1
  223. color: parent.parent.hovered ? Style.lightHover : "transparent"
  224. }
  225. }
  226. Accessible.role: Accessible.MenuItem
  227. Accessible.name: Systray.syncIsPaused() ? qsTr("Resume sync for all") : qsTr("Pause sync for all")
  228. Accessible.onPressAction: syncPauseButton.clicked()
  229. }
  230. MenuItem {
  231. id: settingsButton
  232. text: qsTr("Settings")
  233. font.pixelSize: Style.topLinePixelSize
  234. hoverEnabled: true
  235. onClicked: Systray.openSettings()
  236. background: Item {
  237. height: parent.height
  238. width: parent.menu.width
  239. Rectangle {
  240. anchors.fill: parent
  241. anchors.margins: 1
  242. color: parent.parent.hovered ? Style.lightHover : "transparent"
  243. }
  244. }
  245. Accessible.role: Accessible.MenuItem
  246. Accessible.name: text
  247. Accessible.onPressAction: settingsButton.clicked()
  248. }
  249. MenuItem {
  250. id: exitButton
  251. text: qsTr("Exit");
  252. font.pixelSize: Style.topLinePixelSize
  253. hoverEnabled: true
  254. onClicked: Systray.shutdown()
  255. background: Item {
  256. height: parent.height
  257. width: parent.menu.width
  258. Rectangle {
  259. anchors.fill: parent
  260. anchors.margins: 1
  261. color: parent.parent.hovered ? Style.lightHover : "transparent"
  262. }
  263. }
  264. Accessible.role: Accessible.MenuItem
  265. Accessible.name: text
  266. Accessible.onPressAction: exitButton.clicked()
  267. }
  268. }
  269. }
  270. background: Rectangle {
  271. color: accountBtnMouseArea.containsMouse ? "white" : "transparent"
  272. opacity: 0.2
  273. }
  274. RowLayout {
  275. id: accountControlRowLayout
  276. height: Style.trayWindowHeaderHeight
  277. width: Style.currentAccountButtonWidth
  278. spacing: 0
  279. Image {
  280. id: currentAccountAvatar
  281. Layout.leftMargin: 8
  282. verticalAlignment: Qt.AlignCenter
  283. cache: false
  284. source: UserModel.currentUser.avatar != "" ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite"
  285. Layout.preferredHeight: Style.accountAvatarSize
  286. Layout.preferredWidth: Style.accountAvatarSize
  287. Accessible.role: Accessible.Graphic
  288. Accessible.name: qsTr("Current user avatar")
  289. Rectangle {
  290. id: currentAccountStatusIndicatorBackground
  291. visible: UserModel.currentUser.isConnected
  292. && UserModel.currentUser.serverHasUserStatus
  293. width: Style.accountAvatarStateIndicatorSize + 2
  294. height: width
  295. anchors.bottom: currentAccountAvatar.bottom
  296. anchors.right: currentAccountAvatar.right
  297. color: Style.ncBlue
  298. radius: width*0.5
  299. }
  300. Rectangle {
  301. id: currentAccountStatusIndicatorMouseHover
  302. visible: UserModel.currentUser.isConnected
  303. && UserModel.currentUser.serverHasUserStatus
  304. width: Style.accountAvatarStateIndicatorSize + 2
  305. height: width
  306. anchors.bottom: currentAccountAvatar.bottom
  307. anchors.right: currentAccountAvatar.right
  308. color: accountBtnMouseArea.containsMouse ? "white" : "transparent"
  309. opacity: 0.2
  310. radius: width*0.5
  311. }
  312. Image {
  313. id: currentAccountStatusIndicator
  314. visible: UserModel.currentUser.isConnected
  315. && UserModel.currentUser.serverHasUserStatus
  316. source: UserModel.currentUser.statusIcon
  317. cache: false
  318. x: currentAccountStatusIndicatorBackground.x + 1
  319. y: currentAccountStatusIndicatorBackground.y + 1
  320. sourceSize.width: Style.accountAvatarStateIndicatorSize
  321. sourceSize.height: Style.accountAvatarStateIndicatorSize
  322. Accessible.role: Accessible.Indicator
  323. Accessible.name: UserModel.desktopNotificationsAllowed ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
  324. }
  325. }
  326. Column {
  327. id: accountLabels
  328. spacing: 0
  329. Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
  330. Layout.leftMargin: Style.userStatusSpacing
  331. Layout.fillWidth: true
  332. Layout.maximumWidth: parent.width
  333. Label {
  334. id: currentAccountUser
  335. Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
  336. width: Style.currentAccountLabelWidth
  337. text: UserModel.currentUser.name
  338. elide: Text.ElideRight
  339. color: Style.ncTextColor
  340. font.pixelSize: Style.topLinePixelSize
  341. font.bold: true
  342. }
  343. RowLayout {
  344. id: currentUserStatus
  345. visible: UserModel.currentUser.isConnected &&
  346. UserModel.currentUser.serverHasUserStatus
  347. spacing: Style.accountLabelsSpacing
  348. width: parent.width
  349. Label {
  350. id: emoji
  351. visible: UserModel.currentUser.statusEmoji !== ""
  352. width: Style.userStatusEmojiSize
  353. text: UserModel.currentUser.statusEmoji
  354. }
  355. Label {
  356. id: message
  357. Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
  358. Layout.fillWidth: true
  359. visible: UserModel.currentUser.statusMessage !== ""
  360. width: Style.currentAccountLabelWidth
  361. text: UserModel.currentUser.statusMessage !== ""
  362. ? UserModel.currentUser.statusMessage
  363. : UserModel.currentUser.server
  364. elide: Text.ElideRight
  365. color: Style.ncTextColor
  366. font.pixelSize: Style.subLinePixelSize
  367. }
  368. }
  369. }
  370. ColorOverlay {
  371. cached: true
  372. color: Style.ncTextColor
  373. width: source.width
  374. height: source.height
  375. source: Image {
  376. Layout.alignment: Qt.AlignRight
  377. verticalAlignment: Qt.AlignCenter
  378. Layout.margins: Style.accountDropDownCaretMargin
  379. source: "qrc:///client/theme/white/caret-down.svg"
  380. sourceSize.width: Style.accountDropDownCaretSize
  381. sourceSize.height: Style.accountDropDownCaretSize
  382. Accessible.role: Accessible.PopupMenu
  383. Accessible.name: qsTr("Account switcher and settings menu")
  384. }
  385. }
  386. }
  387. }
  388. // Add space between items
  389. Item {
  390. Layout.fillWidth: true
  391. }
  392. RowLayout {
  393. id: openLocalFolderRowLayout
  394. spacing: 0
  395. Layout.preferredWidth: Style.trayWindowHeaderHeight
  396. Layout.preferredHeight: Style.trayWindowHeaderHeight
  397. Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
  398. HeaderButton {
  399. id: openLocalFolderButton
  400. visible: UserModel.currentUser.hasLocalFolder
  401. icon.source: "qrc:///client/theme/white/folder.svg"
  402. onClicked: UserModel.openCurrentAccountLocalFolder()
  403. Rectangle {
  404. id: folderStateIndicatorBackground
  405. width: Style.folderStateIndicatorSize
  406. height: width
  407. anchors.top: openLocalFolderButton.verticalCenter
  408. anchors.left: openLocalFolderButton.horizontalCenter
  409. color: Style.ncBlue
  410. radius: width*0.5
  411. z: 1
  412. }
  413. Image {
  414. id: folderStateIndicator
  415. visible: UserModel.currentUser.hasLocalFolder
  416. source: UserModel.currentUser.isConnected
  417. ? Style.stateOnlineImageSource
  418. : Style.stateOfflineImageSource
  419. cache: false
  420. anchors.top: openLocalFolderButton.verticalCenter
  421. anchors.left: openLocalFolderButton.horizontalCenter
  422. sourceSize.width: Style.folderStateIndicatorSize
  423. sourceSize.height: Style.folderStateIndicatorSize
  424. Accessible.role: Accessible.Indicator
  425. Accessible.name: UserModel.currentUser.isConnected ? qsTr("Connected") : qsTr("Disconnected")
  426. z: 2
  427. }
  428. }
  429. Accessible.role: Accessible.Button
  430. Accessible.name: qsTr("Open local folder of current account")
  431. }
  432. HeaderButton {
  433. id: trayWindowTalkButton
  434. visible: UserModel.currentUser.serverHasTalk
  435. icon.source: "qrc:///client/theme/white/talk-app.svg"
  436. onClicked: UserModel.openCurrentAccountTalk()
  437. Accessible.role: Accessible.Button
  438. Accessible.name: qsTr("Open Nextcloud Talk in browser")
  439. Accessible.onPressAction: trayWindowTalkButton.clicked()
  440. }
  441. HeaderButton {
  442. id: trayWindowAppsButton
  443. icon.source: "qrc:///client/theme/white/more-apps.svg"
  444. onClicked: {
  445. if(appsMenu.count <= 0) {
  446. UserModel.openCurrentAccountServer()
  447. } else if (appsMenu.visible) {
  448. appsMenu.close()
  449. } else {
  450. appsMenu.open()
  451. }
  452. }
  453. Accessible.role: Accessible.ButtonMenu
  454. Accessible.name: qsTr("More apps")
  455. Accessible.onPressAction: trayWindowAppsButton.clicked()
  456. AutoSizingMenu {
  457. id: appsMenu
  458. y: (trayWindowAppsButton.y + trayWindowAppsButton.height + 2)
  459. readonly property Item listContentItem: contentItem.contentItem
  460. closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
  461. background: Rectangle {
  462. border.color: Style.menuBorder
  463. radius: 2
  464. }
  465. Instantiator {
  466. id: appsMenuInstantiator
  467. model: UserAppsModel
  468. onObjectAdded: appsMenu.insertItem(index, object)
  469. onObjectRemoved: appsMenu.removeItem(object)
  470. delegate: MenuItem {
  471. id: appEntry
  472. text: appName
  473. font.pixelSize: Style.topLinePixelSize
  474. icon.source: appIconUrl
  475. onTriggered: UserAppsModel.openAppUrl(appUrl)
  476. hoverEnabled: true
  477. Accessible.role: Accessible.MenuItem
  478. Accessible.name: qsTr("Open %1 in browser").arg(appName)
  479. Accessible.onPressAction: appEntry.triggered()
  480. }
  481. }
  482. }
  483. }
  484. }
  485. } // Rectangle trayWindowHeaderBackground
  486. UnifiedSearchInputContainer {
  487. id: trayWindowUnifiedSearchInputContainer
  488. height: Style.trayWindowHeaderHeight * 0.65
  489. anchors {
  490. top: trayWindowHeaderBackground.bottom
  491. left: trayWindowBackground.left
  492. right: trayWindowBackground.right
  493. margins: {
  494. top: 10
  495. }
  496. }
  497. text: UserModel.currentUser.unifiedSearchResultsListModel.searchTerm
  498. readOnly: !UserModel.currentUser.isConnected || UserModel.currentUser.unifiedSearchResultsListModel.currentFetchMoreInProgressProviderId
  499. isSearchInProgress: UserModel.currentUser.unifiedSearchResultsListModel.isSearchInProgress
  500. onTextEdited: { UserModel.currentUser.unifiedSearchResultsListModel.searchTerm = trayWindowUnifiedSearchInputContainer.text }
  501. }
  502. ErrorBox {
  503. id: unifiedSearchResultsErrorLabel
  504. visible: UserModel.currentUser.unifiedSearchResultsListModel.errorString && !unifiedSearchResultsListView.visible && ! UserModel.currentUser.unifiedSearchResultsListModel.isSearchInProgress && ! UserModel.currentUser.unifiedSearchResultsListModel.currentFetchMoreInProgressProviderId
  505. text: UserModel.currentUser.unifiedSearchResultsListModel.errorString
  506. color: Style.errorBoxBackgroundColor
  507. backgroundColor: Style.errorBoxTextColor
  508. borderColor: "transparent"
  509. anchors.top: trayWindowUnifiedSearchInputContainer.bottom
  510. anchors.left: trayWindowBackground.left
  511. anchors.right: trayWindowBackground.right
  512. anchors.margins: 10
  513. }
  514. UnifiedSearchResultNothingFound {
  515. id: unifiedSearchResultNothingFound
  516. visible: false
  517. anchors.top: trayWindowUnifiedSearchInputContainer.bottom
  518. anchors.left: trayWindowBackground.left
  519. anchors.right: trayWindowBackground.right
  520. anchors.topMargin: 10
  521. text: UserModel.currentUser.unifiedSearchResultsListModel.searchTerm
  522. property bool isSearchRunning: UserModel.currentUser.unifiedSearchResultsListModel.isSearchInProgress
  523. property bool isSearchResultsEmpty: unifiedSearchResultsListView.count === 0
  524. property bool nothingFound: text && isSearchResultsEmpty && !UserModel.currentUser.unifiedSearchResultsListModel.errorString
  525. onIsSearchRunningChanged: {
  526. if (unifiedSearchResultNothingFound.isSearchRunning) {
  527. visible = false;
  528. } else {
  529. if (nothingFound) {
  530. visible = true;
  531. }
  532. }
  533. }
  534. onTextChanged: {
  535. visible = false;
  536. }
  537. onIsSearchResultsEmptyChanged: {
  538. if (!unifiedSearchResultNothingFound.isSearchResultsEmpty) {
  539. visible = false;
  540. }
  541. }
  542. }
  543. UnifiedSearchResultItemSkeletonContainer {
  544. id: unifiedSearchResultsListViewSkeleton
  545. visible: !unifiedSearchResultNothingFound.visible && !unifiedSearchResultsListView.visible && ! UserModel.currentUser.unifiedSearchResultsListModel.errorString && UserModel.currentUser.unifiedSearchResultsListModel.searchTerm
  546. anchors.top: trayWindowUnifiedSearchInputContainer.bottom
  547. anchors.left: trayWindowBackground.left
  548. anchors.right: trayWindowBackground.right
  549. anchors.bottom: trayWindowBackground.bottom
  550. textLeftMargin: trayWindowBackground.Style.unifiedSearchResultTextLeftMargin
  551. textRightMargin: trayWindowBackground.Style.unifiedSearchResultTextRightMargin
  552. iconWidth: trayWindowBackground.Style.unifiedSearchResulIconWidth
  553. iconLeftMargin: trayWindowBackground.Style.unifiedSearchResulIconLeftMargin
  554. itemHeight: trayWindowBackground.Style.unifiedSearchItemHeight
  555. titleFontSize: trayWindowBackground.Style.unifiedSearchResulTitleFontSize
  556. sublineFontSize: trayWindowBackground.Style.unifiedSearchResulSublineFontSize
  557. titleColor: trayWindowBackground.Style.unifiedSearchResulTitleColor
  558. sublineColor: trayWindowBackground.Style.unifiedSearchResulSublineColor
  559. iconColor: "#afafaf"
  560. }
  561. ListView {
  562. id: unifiedSearchResultsListView
  563. anchors.top: trayWindowUnifiedSearchInputContainer.bottom
  564. anchors.left: trayWindowBackground.left
  565. anchors.right: trayWindowBackground.right
  566. anchors.bottom: trayWindowBackground.bottom
  567. spacing: 4
  568. visible: count > 0
  569. clip: true
  570. ScrollBar.vertical: ScrollBar {
  571. id: unifiedSearchResultsListViewScrollbar
  572. }
  573. keyNavigationEnabled: true
  574. reuseItems: true
  575. Accessible.role: Accessible.List
  576. Accessible.name: qsTr("Unified search results list")
  577. model: UserModel.currentUser.unifiedSearchResultsListModel
  578. delegate: UnifiedSearchResultListItem {
  579. width: unifiedSearchResultsListView.width
  580. height: trayWindowBackground.Style.unifiedSearchItemHeight
  581. isSearchInProgress: unifiedSearchResultsListView.model.isSearchInProgress
  582. textLeftMargin: trayWindowBackground.Style.unifiedSearchResultTextLeftMargin
  583. textRightMargin: trayWindowBackground.Style.unifiedSearchResultTextRightMargin
  584. iconWidth: trayWindowBackground.Style.unifiedSearchResulIconWidth
  585. iconLeftMargin: trayWindowBackground.Style.unifiedSearchResulIconLeftMargin
  586. titleFontSize: trayWindowBackground.Style.unifiedSearchResulTitleFontSize
  587. sublineFontSize: trayWindowBackground.Style.unifiedSearchResulSublineFontSize
  588. titleColor: trayWindowBackground.Style.unifiedSearchResulTitleColor
  589. sublineColor: trayWindowBackground.Style.unifiedSearchResulSublineColor
  590. currentFetchMoreInProgressProviderId: unifiedSearchResultsListView.model.currentFetchMoreInProgressProviderId
  591. fetchMoreTriggerClicked: unifiedSearchResultsListView.model.fetchMoreTriggerClicked
  592. resultClicked: unifiedSearchResultsListView.model.resultClicked
  593. ListView.onPooled: isPooled = true
  594. ListView.onReused: isPooled = false
  595. }
  596. section.property: "providerName"
  597. section.criteria: ViewSection.FullString
  598. section.delegate: UnifiedSearchResultSectionItem {
  599. width: unifiedSearchResultsListView.width
  600. }
  601. }
  602. SyncStatus {
  603. id: syncStatus
  604. visible: !trayWindowBackground.isUnifiedSearchActive
  605. anchors.top: trayWindowUnifiedSearchInputContainer.bottom
  606. anchors.left: trayWindowBackground.left
  607. anchors.right: trayWindowBackground.right
  608. }
  609. ActivityList {
  610. visible: !trayWindowBackground.isUnifiedSearchActive
  611. anchors.top: syncStatus.bottom
  612. anchors.left: trayWindowBackground.left
  613. anchors.right: trayWindowBackground.right
  614. anchors.bottom: trayWindowBackground.bottom
  615. model: activityModel
  616. onShowFileActivity: {
  617. openFileActivityDialog(displayPath, absolutePath)
  618. }
  619. onActivityItemClicked: {
  620. model.triggerDefaultAction(index)
  621. }
  622. }
  623. Loader {
  624. id: fileActivityDialogLoader
  625. property string displayPath: ""
  626. property string absolutePath: ""
  627. function refresh() {
  628. active = true
  629. item.model.load(activityModel.accountState, absolutePath)
  630. item.show()
  631. }
  632. active: false
  633. sourceComponent: FileActivityDialog {
  634. title: qsTr("%1 - File activity").arg(fileActivityDialogLoader.displayPath)
  635. onClosing: fileActivityDialogLoader.active = false
  636. }
  637. onLoaded: refresh()
  638. }
  639. } // Rectangle trayWindowBackground
  640. }