import QtQuick 2.13 import QtQuick.Controls 2.15 as Controls import QtQuick.Layouts 1.15 import Qt.labs.platform 1.1 as Labs import QtQuick.Pdf 5.15 import QtQml.Models 2.15 import org.kde.kirigami 2.13 as Kirigami import "./" as Presenter import org.presenter 1.0 ColumnLayout { id: root property var proxyModel property var innerModel property string libraryType property string headerLabel property string itemLabel property string itemSubtitle property string itemIcon property string count property var newItemFunction property var deleteItemFunction property ListView libraryList: libraryList states: [ State { name: "deselected" when: (selectedLibrary !== libraryType) PropertyChanges { target: root Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 } }, State { name: "selected" when: (selectedLibrary == libraryType) PropertyChanges { target: root } } ] transitions: Transition { to: "*" NumberAnimation { target: root properties: "preferredHeight" easing.type: Easing.OutCubic duration: 300 } } Rectangle { id: libraryPanel Layout.preferredHeight: 40 Layout.fillWidth: true Layout.alignment: Qt.AlignTop z: 2 color: Kirigami.Theme.backgroundColor Controls.Label { id: libraryLabel /* anchors.centerIn: parent */ anchors.left: parent.left anchors.leftMargin: 15 anchors.verticalCenter: parent.verticalCenter elide: Text.ElideLeft text: headerLabel color: libraryMouseArea.containsMouse ? Kirigami.Theme.focusColor : Kirigami.Theme.textColor } Controls.Label { id: countLabel anchors {left: libraryLabel.right verticalCenter: libraryLabel.verticalCenter leftMargin: 15} text: count font.pointSize: 9 color: libraryMouseArea.containsMouse ? Kirigami.Theme.focusColor : Kirigami.Theme.textColor } Kirigami.Icon { id: drawerArrow anchors {right: parent.right verticalCenter: libraryLabel.verticalCenter rightMargin: 10} source: "arrow-down" rotation: selectedLibrary == libraryType ? 0 : 180 color: libraryMouseArea.containsMouse ? Kirigami.Theme.focusColor : Kirigami.Theme.textColor Behavior on rotation { NumberAnimation { easing.type: Easing.OutCubic duration: 300 } } } MouseArea { id: libraryMouseArea anchors.fill: parent hoverEnabled: true onClicked: { if (selectedLibrary == libraryType) selectedLibrary = "" else selectedLibrary = libraryType /* console.log(selectedLibrary) */ } } } Rectangle { id: libraryHeader z: 2 Layout.preferredHeight: 40 Layout.fillWidth: true Layout.alignment: Qt.AlignTop /* width: parent.width */ color: Kirigami.Theme.backgroundColor opacity: 1 state: "selected" states: [ State { name: "deselected" when: (selectedLibrary !== libraryType) PropertyChanges { target: libraryHeader Layout.preferredHeight: 0 } }, State { name: "selected" when: (selectedLibrary == libraryType) PropertyChanges { target: libraryHeader } } ] Kirigami.ActionToolBar { height: parent.height width: parent.width display: Controls.Button.IconOnly visible: selectedLibrary == libraryType rightPadding: 5 actions: [ Kirigami.Action { icon.name: "document-new" text: "New " + libraryType tooltip: "Add a new " + libraryType onTriggered: newItemFunction() }, Kirigami.Action { id: searchField displayComponent: Kirigami.SearchField { id: searchField height: parent.height width: parent.width - 40 onAccepted: { innerModel.search(text); } background: Presenter.TextBackground { control: searchField } } } ] Behavior on height { NumberAnimation { easing.type: Easing.OutCubic duration: 300 } } } } ListView { Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignTop id: libraryList model: innerModel clip: true ItemSelectionModel { id: selectionModel model: innerModel onSelectionChanged: { /* showPassiveNotification("deslected: " + deselected); */ /* showPassiveNotification("selected: " + selected); */ /* console.log(selected); */ } } delegate: libraryDelegate state: "selected" states: [ State { name: "deselected" when: (selectedLibrary !== libraryType) PropertyChanges { target: libraryList Layout.preferredHeight: 0 } }, State { name: "selected" when: (selectedLibrary == libraryType) PropertyChanges { target: libraryList } } ] transitions: Transition { to: "*" NumberAnimation { target: libraryList properties: "preferredHeight" easing.type: Easing.OutCubic duration: 300 } } Component { id: libraryDelegate Item { implicitWidth: ListView.view.width height: selectedLibrary == libraryType ? 50 : 0 property bool rightMenu: false property bool selected: selectionModel.hasSelection && selectionModel.currentIndex == innerModel.index(index, 0) property bool fileValidation: { if (filePath) fileHelper.validate(filePath) else false } Rectangle { id: itemBackground color: Kirigami.Theme.backgroundColor anchors.fill: parent Binding on color { when: dragHandler.containsMouse || selected value: Kirigami.Theme.highlightColor } } Controls.ItemDelegate { id: listItem implicitWidth: libraryList.width height: selectedLibrary == libraryType ? 50 : 0 text: title /* subtitle: { */ /* if (libraryType == "song") */ /* author */ /* else if (fileValidation) */ /* filePath; */ /* else */ /* "file is missing" */ /* } */ icon.source: itemIcon icon.width: Kirigami.Units.gridUnit icon.height: Kirigami.Units.gridUnit /* supportsMouseEvents: false */ /* textColor: { */ /* if (selectedLibrary == "song") */ /* Kirigami.Theme.textColor; */ /* else if (fileValidation) { */ /* Kirigami.Theme.textColor; */ /* } */ /* else */ /* "red" */ /* } */ /* Binding on textColor { */ /* when: dragHandler.containsMouse || */ /* (selectionModel.hasSelection && */ /* selectionModel.isSelected(proxyModel.idx(index))) */ /* value: Kirigami.Theme.highlightedTextColor */ /* } */ Behavior on height { NumberAnimation { easing.type: Easing.OutCubic duration: 300 } } Drag.active: dragHandler.drag.active Drag.hotSpot.x: width / 2 Drag.hotSpot.y: height / 2 Drag.keys: [ "library" ] states: State { name: "dragged" when: listItem.Drag.active PropertyChanges { target: listItem x: x y: y width: width height: height } ParentChange { target: listItem parent: rootApp.overlay } } } MouseArea { id: dragHandler anchors.fill: parent hoverEnabled: true Controls.ToolTip { text: { if (libraryType == "song") title + "\n" + author else if (fileValidation) title + "\n" + filePath; else "file is missing" } } drag { target: listItem onActiveChanged: { if (dragHandler.drag.active) { dragItemIndex = index; dragItemType = libraryType; draggedLibraryItem = self; } else { listItem.Drag.drop(); dragHighlightLine.visible = false; } } filterChildren: true threshold: 10 /* onDropped: dragHighlightLine.visible = false; */ } MouseArea { id: clickHandler anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: { if (mouse.button === Qt.RightButton) { if(selectionModel.selectedIndexes.length <= 1) selectionModel.select(innerModel.index(index), ItemSelectionModel.ClearAndSelect); rightClickMenu.popup() } else if ((mouse.button === Qt.LeftButton) && (mouse.modifiers === Qt.ShiftModifier)) { if (libraryList.currentIndex < index) { for (let i = libraryList.currentIndex; i <= index; i++) { selectionModel.select(innerModel.index(i), ItemSelectionModel.Select); } } else { for (let i = index; i <= libraryList.currentIndex; i++) { selectionModel.select(innerModel.index(i), ItemSelectionModel.Select); } } console.log(selectionModel.selectedIndexes); } else { selectionModel.select(innerModel.index(index), ItemSelectionModel.ClearAndSelect); libraryList.currentIndex = index; } } onDoubleClicked: { libraryList.currentIndex = index; if (!editMode) editMode = true; editSwitch(index, libraryType); } } } Controls.Menu { id: rightClickMenu x: clickHandler.mouseX y: clickHandler.mouseY + 10 Kirigami.Action { text: "delete" onTriggered: { var selection = []; var length = selectionModel.selectedIndexes.length; for (let i = 0; i < length; i++) { selection.push(selectionModel.selectedIndexes[i].row); } root.deleteItemFunction(selection); } } } } } Kirigami.WheelHandler { id: wheelHandler target: libraryList filterMouseEvents: true keyNavigationEnabled: true } Controls.ScrollBar.vertical: Controls.ScrollBar { active: hovered || pressed } function selectItems(row) { let currentRow = selectionModel.selectedIndexes[0].row; if (row === currentRow) return; if (row > currentRow) { for (var i = currentRow; i <= row; i++) { let idx = innerModel.idx(i); selectionModel.select(idx, ItemSelectionModel.Select); } } else { for (var i = row; i <= currentRow; i++) { let idx = innerModel.idx(i); selectionModel.select(idx, ItemSelectionModel.Select); } } } } }