chore(StatusChatList): Keep sync with underlying model after reordering (#825)
This commit is contained in:
parent
b64f2394cd
commit
abd8ea2195
|
@ -9,7 +9,7 @@ import StatusQ.Components 0.1
|
|||
import StatusQ.Controls 0.1
|
||||
|
||||
Column {
|
||||
id: statusChatList
|
||||
id: root
|
||||
|
||||
spacing: 4
|
||||
width: 288
|
||||
|
@ -33,13 +33,33 @@ Column {
|
|||
}
|
||||
}
|
||||
|
||||
onDraggableItemsChanged: delegateModel.items.setGroups(0, delegateModel.items.count, "unsorted")
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property int destinationPosition: -1
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: delegateModel
|
||||
model: statusChatList.model
|
||||
model: root.model
|
||||
|
||||
items.includeByDefault: !root.draggableItems
|
||||
|
||||
groups: DelegateModelGroup {
|
||||
id: unsortedItems
|
||||
|
||||
name: "unsorted"
|
||||
includeByDefault: root.draggableItems
|
||||
onChanged: Utils.delegateModelSort(unsortedItems, delegateModel.items,
|
||||
(a, b) => a.position < b.position)
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
id: draggable
|
||||
objectName: model.name
|
||||
width: statusChatList.width
|
||||
width: root.width
|
||||
height: statusChatListItem.height
|
||||
property alias chatListItem: statusChatListItem
|
||||
|
||||
|
@ -50,7 +70,7 @@ Column {
|
|||
cursorShape: active ? Qt.ClosedHandCursor : Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
pressAndHoldInterval: 150
|
||||
enabled: statusChatList.draggableItems
|
||||
enabled: root.draggableItems
|
||||
|
||||
property bool active: false
|
||||
property real startY: 0
|
||||
|
@ -66,8 +86,8 @@ Column {
|
|||
}
|
||||
onPressAndHold: active = true
|
||||
onReleased: {
|
||||
if (active) {
|
||||
statusChatList.chatItemReordered(statusChatListItem.chatId, statusChatListItem.originalOrder, statusChatListItem.originalOrder)
|
||||
if (active && d.destinationPosition !== -1 && statusChatListItem.originalOrder !== d.destinationPosition) {
|
||||
root.chatItemReordered(statusChatListItem.chatId, statusChatListItem.originalOrder, d.destinationPosition)
|
||||
}
|
||||
active = false
|
||||
}
|
||||
|
@ -81,6 +101,7 @@ Column {
|
|||
active = true
|
||||
}
|
||||
}
|
||||
onActiveChanged: d.destinationPosition = -1
|
||||
|
||||
StatusChatListItem {
|
||||
id: statusChatListItem
|
||||
|
@ -96,7 +117,7 @@ Column {
|
|||
hasUnreadMessages: model.hasUnreadMessages
|
||||
notificationsCount: model.notificationsCount
|
||||
highlightWhenCreated: !!model.highlight
|
||||
selected: (model.active && statusChatList.highlightItem)
|
||||
selected: (model.active && root.highlightItem)
|
||||
|
||||
icon.emoji: model.emoji
|
||||
icon.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
|
||||
|
@ -105,10 +126,26 @@ Column {
|
|||
ringSettings.ringSpecModel: model.colorHash
|
||||
|
||||
sensor.cursorShape: dragSensor.cursorShape
|
||||
|
||||
Connections {
|
||||
target: statusChatListItem
|
||||
enabled: root.draggableItems
|
||||
|
||||
function onOriginalOrderChanged() {
|
||||
Qt.callLater(() => {
|
||||
if (!delegateModel)
|
||||
return
|
||||
|
||||
delegateModel.items.setGroups(0, delegateModel.items.count, "unsorted")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
highlightWhenCreated = false
|
||||
|
||||
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
|
||||
if (mouse.button === Qt.RightButton && !!root.popupMenu) {
|
||||
statusChatListItem.highlighted = true
|
||||
|
||||
let originalOpenHandler = popupMenuSlot.item.openHandler
|
||||
|
@ -136,10 +173,10 @@ Column {
|
|||
return
|
||||
}
|
||||
if (!statusChatListItem.selected) {
|
||||
statusChatList.chatItemSelected(model.parentItemId, model.itemId)
|
||||
root.chatItemSelected(model.parentItemId, model.itemId)
|
||||
}
|
||||
}
|
||||
onUnmute: statusChatList.chatItemUnmuted(model.itemId)
|
||||
onUnmute: root.chatItemUnmuted(model.itemId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +187,6 @@ Column {
|
|||
keys: ["chat-item-category-" + statusChatListItem.categoryId]
|
||||
|
||||
onEntered: reorderDelay.start()
|
||||
onDropped: statusChatList.chatItemReordered(statusChatListItem.chatId, drag.source.originalOrder, statusChatListItem.DelegateModel.itemsIndex)
|
||||
|
||||
Timer {
|
||||
id: reorderDelay
|
||||
|
@ -158,7 +194,7 @@ Column {
|
|||
repeat: false
|
||||
onTriggered: {
|
||||
if (dropArea.containsDrag) {
|
||||
dropArea.drag.source.chatListItem.originalOrder = statusChatListItem.originalOrder
|
||||
d.destinationPosition = delegateModel.model.get(draggable.DelegateModel.itemsIndex).position
|
||||
delegateModel.items.move(dropArea.drag.source.DelegateModel.itemsIndex, draggable.DelegateModel.itemsIndex)
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +244,6 @@ Column {
|
|||
|
||||
Loader {
|
||||
id: popupMenuSlot
|
||||
active: !!statusChatList.popupMenu
|
||||
active: !!root.popupMenu
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import StatusQ.Core 0.1
|
|||
import SortFilterProxyModel 0.2
|
||||
|
||||
Item {
|
||||
id: statusChatListAndCategories
|
||||
id: root
|
||||
|
||||
implicitHeight: chatListsAndCategories.height
|
||||
implicitWidth: chatListsAndCategories.width
|
||||
|
@ -53,11 +53,11 @@ Item {
|
|||
MouseArea {
|
||||
id: sensor
|
||||
anchors.top: parent.top
|
||||
width: statusChatListAndCategories.width
|
||||
height: statusChatListAndCategories.height
|
||||
width: root.width
|
||||
height: root.height
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: {
|
||||
if (mouse.button === Qt.RightButton && showPopupMenu && !!statusChatListAndCategories.popupMenu) {
|
||||
if (mouse.button === Qt.RightButton && showPopupMenu && !!root.popupMenu) {
|
||||
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6)
|
||||
return
|
||||
}
|
||||
|
@ -73,31 +73,44 @@ Item {
|
|||
StatusChatList {
|
||||
id: statusChatList
|
||||
visible: statusChatList.model.count > 0
|
||||
onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
|
||||
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
|
||||
onChatItemReordered: statusChatListAndCategories.chatItemReordered(categoryId, id, from, to)
|
||||
draggableItems: statusChatListAndCategories.draggableItems
|
||||
onChatItemSelected: root.chatItemSelected(categoryId, id)
|
||||
onChatItemUnmuted: root.chatItemUnmuted(id)
|
||||
onChatItemReordered: root.chatItemReordered(categoryId, id, from, to)
|
||||
draggableItems: root.draggableItems
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: statusChatListAndCategories.model
|
||||
sourceModel: root.model
|
||||
|
||||
filters: ValueFilter { roleName: "isCategory"; value: false }
|
||||
sorters: RoleSorter { roleName: "position" }
|
||||
}
|
||||
|
||||
popupMenu: statusChatListAndCategories.chatListPopupMenu
|
||||
popupMenu: root.chatListPopupMenu
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: delegateModel
|
||||
|
||||
property int destinationPosition: -1
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: statusChatListAndCategories.model
|
||||
sourceModel: root.model
|
||||
|
||||
filters: ValueFilter { roleName: "isCategory"; value: true }
|
||||
sorters: RoleSorter { roleName: "position" }
|
||||
}
|
||||
|
||||
items.includeByDefault: false
|
||||
|
||||
groups: DelegateModelGroup {
|
||||
id: unsortedItems
|
||||
|
||||
name: "unsorted"
|
||||
includeByDefault: true
|
||||
onChanged: Utils.delegateModelSort(unsortedItems, delegateModel.items,
|
||||
(a, b) => a.position < b.position)
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
id: draggable
|
||||
width: statusChatListCategory.width
|
||||
|
@ -117,13 +130,13 @@ Item {
|
|||
dragSensor.drag.threshold: 0.1
|
||||
dragSensor.drag.filterChildren: true
|
||||
dragSensor.onPressAndHold: {
|
||||
if (statusChatListAndCategories.draggableCategories) {
|
||||
if (root.draggableCategories) {
|
||||
dragActive = true
|
||||
}
|
||||
}
|
||||
dragSensor.onReleased: {
|
||||
if (dragActive) {
|
||||
statusChatListAndCategories.chatListCategoryReordered(statusChatListCategory.categoryId, statusChatListCategory.originalOrder, statusChatListCategory.originalOrder)
|
||||
if (dragActive && delegateModel.destinationPosition !== -1 && statusChatListCategory.originalOrder !== delegateModel.destinationPosition) {
|
||||
root.chatListCategoryReordered(statusChatListCategory.categoryId, statusChatListCategory.originalOrder, delegateModel.destinationPosition)
|
||||
}
|
||||
dragActive = false
|
||||
}
|
||||
|
@ -133,42 +146,44 @@ Item {
|
|||
startX = dragSensor.mouseX
|
||||
}
|
||||
dragSensor.onMouseYChanged: {
|
||||
if (statusChatListAndCategories.draggableCategories && (Math.abs(startY - dragSensor.mouseY) > 1) && dragSensor.pressed) {
|
||||
if (root.draggableCategories && (Math.abs(startY - dragSensor.mouseY) > 1) && dragSensor.pressed) {
|
||||
dragActive = true
|
||||
}
|
||||
}
|
||||
dragSensor.onMouseXChanged: {
|
||||
if (statusChatListAndCategories.draggableCategories && (Math.abs(startX - dragSensor.mouseX) > 1) && dragSensor.pressed) {
|
||||
if (root.draggableCategories && (Math.abs(startX - dragSensor.mouseX) > 1) && dragSensor.pressed) {
|
||||
dragActive = true
|
||||
}
|
||||
}
|
||||
onDragActiveChanged: delegateModel.destinationPosition = -1
|
||||
|
||||
addButton.tooltip: statusChatListAndCategories.categoryAddButtonToolTip
|
||||
menuButton.tooltip: statusChatListAndCategories.categoryMenuButtonToolTip
|
||||
addButton.tooltip: root.categoryAddButtonToolTip
|
||||
menuButton.tooltip: root.categoryMenuButtonToolTip
|
||||
|
||||
originalOrder: model.position
|
||||
categoryId: model.itemId
|
||||
name: model.name
|
||||
showActionButtons: statusChatListAndCategories.showCategoryActionButtons
|
||||
addButton.onClicked: statusChatListAndCategories.categoryAddButtonClicked(model.itemId)
|
||||
|
||||
showActionButtons: root.showCategoryActionButtons
|
||||
addButton.onClicked: root.categoryAddButtonClicked(model.itemId)
|
||||
|
||||
chatList.model: SortFilterProxyModel {
|
||||
sourceModel: model.subItems
|
||||
sorters: RoleSorter { roleName: "position" }
|
||||
}
|
||||
|
||||
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
|
||||
chatList.onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
|
||||
chatList.onChatItemReordered: statusChatListAndCategories.chatItemReordered(model.itemId, id, from, to)
|
||||
chatList.draggableItems: statusChatListAndCategories.draggableItems
|
||||
chatList.onChatItemSelected: root.chatItemSelected(categoryId, id)
|
||||
chatList.onChatItemUnmuted: root.chatItemUnmuted(id)
|
||||
chatList.onChatItemReordered: root.chatItemReordered(model.itemId, id, from, to)
|
||||
chatList.draggableItems: root.draggableItems
|
||||
|
||||
popupMenu: statusChatListAndCategories.categoryPopupMenu
|
||||
chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu
|
||||
popupMenu: root.categoryPopupMenu
|
||||
chatListPopupMenu: root.chatListPopupMenu
|
||||
|
||||
// Used to set the initial value of "opened" when the
|
||||
// model is bound/changed.
|
||||
opened: {
|
||||
let openedState = statusChatListAndCategories.openedCategoryState[model.itemId]
|
||||
let openedState = root.openedCategoryState[model.itemId]
|
||||
return openedState !== undefined ? openedState : true // defaults to open
|
||||
}
|
||||
|
||||
|
@ -177,7 +192,18 @@ Item {
|
|||
// as the state would be lost each time the model is
|
||||
// changed.
|
||||
onOpenedChanged: {
|
||||
statusChatListAndCategories.openedCategoryState[model.itemId] = statusChatListCategory.opened
|
||||
root.openedCategoryState[model.itemId] = statusChatListCategory.opened
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onOriginalOrderChanged() {
|
||||
Qt.callLater(() => {
|
||||
if (!delegateModel)
|
||||
return
|
||||
|
||||
delegateModel.items.setGroups(0, delegateModel.items.count, "unsorted")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +214,6 @@ Item {
|
|||
keys: ["chat-category"]
|
||||
|
||||
onEntered: reorderDelay.start()
|
||||
onDropped: statusChatListAndCategories.chatListCategoryReordered(statusChatListCategory.categoryId, drag.source.originalOrder, statusChatListCategory.DelegateModel.itemsIndex)
|
||||
|
||||
Timer {
|
||||
id: reorderDelay
|
||||
|
@ -196,7 +221,7 @@ Item {
|
|||
repeat: false
|
||||
onTriggered: {
|
||||
if (dropArea.containsDrag) {
|
||||
dropArea.drag.source.chatListCategory.originalOrder = statusChatListCategory.originalOrder
|
||||
delegateModel.destinationPosition = delegateModel.model.get(draggable.DelegateModel.itemsIndex).position
|
||||
delegateModel.items.move(dropArea.drag.source.DelegateModel.itemsIndex, draggable.DelegateModel.itemsIndex)
|
||||
}
|
||||
}
|
||||
|
@ -242,6 +267,6 @@ Item {
|
|||
|
||||
Loader {
|
||||
id: popupMenuSlot
|
||||
active: !!statusChatListAndCategories.popupMenu
|
||||
active: !!root.popupMenu
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,6 +150,29 @@ QtObject {
|
|||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
function delegateModelSort(srcGroup, dstGroup, lessThan) {
|
||||
const insertPosition = (lessThan, item) => {
|
||||
let lower = 0
|
||||
let upper = dstGroup.count
|
||||
while (lower < upper) {
|
||||
const middle = Math.floor(lower + (upper - lower) / 2)
|
||||
const result = lessThan(item.model, dstGroup.get(middle).model);
|
||||
if (result)
|
||||
upper = middle
|
||||
else
|
||||
lower = middle + 1
|
||||
}
|
||||
return lower
|
||||
}
|
||||
|
||||
while (srcGroup.count > 0) {
|
||||
const item = srcGroup.get(0)
|
||||
const index = insertPosition(lessThan, item)
|
||||
item.groups = dstGroup.name
|
||||
dstGroup.move(item.itemsIndex, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue