performance(ChannelsSelectionModel): Use LeftJoinModel for ChannelsSelectionModel.qml
Motivation: ChannelsSelectionModel.qml is freezing the app when used with a live channel that's being edited because on each channel change the selection model is re-created. The fix for this is to use the LeftJoinModel to unify the channels selection (a light model containing only keys) and the full channels model containing the channels data. On top of this, the SortFilterProxyModel is added to decorate the model with the roles expected in the UI. Another improvement is by replacing the ExpressionRole with the FastExpressionRole.
This commit is contained in:
parent
29f1bee218
commit
942482fe99
|
@ -3,71 +3,60 @@ import SortFilterProxyModel 0.2
|
|||
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
SortFilterProxyModel {
|
||||
property var channelsModel
|
||||
id: root
|
||||
|
||||
property var selectedChannels
|
||||
property var allChannels
|
||||
|
||||
readonly property QtObject _d: QtObject {
|
||||
id: d
|
||||
|
||||
readonly property ModelChangeTracker tracker: ModelChangeTracker {
|
||||
model: channelsModel
|
||||
|
||||
onRevisionChanged: {
|
||||
const metadata = new Map()
|
||||
const count = channelsModel.rowCount()
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = ModelUtils.get(channelsModel, i)
|
||||
|
||||
const text = "#" + item.name
|
||||
const imageSource = item.icon
|
||||
const emoji = item.emoji
|
||||
const color = !!item.color ? item.color
|
||||
: Theme.palette.userCustomizationColors[item.colorId]
|
||||
metadata.set(item.itemId, { text, imageSource, emoji, color })
|
||||
sourceModel: LeftJoinModel {
|
||||
readonly property var channelsModelAlignedKey: SortFilterProxyModel {
|
||||
sourceModel: root.allChannels
|
||||
proxyRoles: [
|
||||
FastExpressionRole {
|
||||
name: "key"
|
||||
expression: model.itemId ?? ""
|
||||
expectedRoles: ["itemId"]
|
||||
}
|
||||
|
||||
d.metadata = metadata
|
||||
}
|
||||
|
||||
onModelChanged: revisionChanged()
|
||||
}
|
||||
|
||||
property var metadata: new Map()
|
||||
|
||||
function get(key, role) {
|
||||
const item = metadata.get(key)
|
||||
return !!item ? item[role] : ""
|
||||
]
|
||||
}
|
||||
leftModel: root.selectedChannels
|
||||
rightModel: channelsModelAlignedKey
|
||||
joinRole: "key"
|
||||
}
|
||||
|
||||
proxyRoles: [
|
||||
ExpressionRole {
|
||||
FastExpressionRole {
|
||||
name: "text"
|
||||
expression: d.get(model.key, name)
|
||||
expression: "#" + model.name
|
||||
expectedRoles: ["name"]
|
||||
},
|
||||
ExpressionRole {
|
||||
FastExpressionRole {
|
||||
name: "imageSource"
|
||||
expression: d.get(model.key, name)
|
||||
expression: model.icon
|
||||
expectedRoles: ["icon"]
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "emoji"
|
||||
expression: d.get(model.key, name)
|
||||
},
|
||||
ExpressionRole {
|
||||
FastExpressionRole {
|
||||
function getColor(color, colorId) {
|
||||
return !!color ? color
|
||||
: Theme.palette.userCustomizationColors[colorId]
|
||||
}
|
||||
name: "color"
|
||||
expression: d.get(model.key, name)
|
||||
expression: getColor(model.color, model.colorId)
|
||||
expectedRoles: ["color", "colorId"]
|
||||
},
|
||||
ExpressionRole {
|
||||
FastExpressionRole {
|
||||
name: "operator"
|
||||
|
||||
// Direct call for singleton enum is not handled properly by SortFilterProxyModel.
|
||||
readonly property int none: OperatorsUtils.Operators.None
|
||||
|
||||
expression: none
|
||||
expectedRoles: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -513,9 +513,8 @@ StatusScrollView {
|
|||
ChannelsSelectionModel {
|
||||
id: channelsSelectionModel
|
||||
|
||||
sourceModel: d.dirtyValues.selectedChannelsModel
|
||||
|
||||
channelsModel: root.channelsModel
|
||||
selectedChannels: d.dirtyValues.selectedChannelsModel
|
||||
allChannels: root.channelsModel
|
||||
}
|
||||
|
||||
InDropdown {
|
||||
|
|
|
@ -90,8 +90,8 @@ StatusScrollView {
|
|||
ChannelsSelectionModel {
|
||||
id: channelsSelectionModel
|
||||
|
||||
sourceModel: model.channelsListModel ?? null
|
||||
channelsModel: root.channelsModel
|
||||
selectedChannels: model.channelsListModel ?? null
|
||||
allChannels: root.channelsModel
|
||||
}
|
||||
|
||||
channelsListModel: channelsSelectionModel.count
|
||||
|
|
Loading…
Reference in New Issue