yubioath-flutter/qml/SortedListModel.qml
Dag Heyman 94edf799b6 New UI based on Quick Controls 2
- New design based on Material Style
- Light mode and Dark mode
- Add support for custom CCID readers
- New tray functionality
- Support for favorite credentials

Co-authored-by: Rikard <rikard@yubico.com>
2019-09-11 10:30:37 +02:00

128 lines
4.1 KiB
QML

// Heavyliy based on: https://gist.github.com/stephenquan/fcad6ecd4b28051c61cf48853e39c9e4
// Implements a convenient ListModel that contains sorted items.
// properties:
// sortKey: specifies one or more key to sort on with an optional "-" prefix to set descending order
// compareFunc: allows you to replace the default compare function with your own
// methods:
// insertSorted(obj) - uses binary search insertion sort, duplicates aren't allowed, last in wins.
// sort() - leverages from Array.prototype.sort() to rapidly sort all items to a new compareFunc
// load() - load from another model
import QtQuick 2.9
ListModel {
id: sortedListModel
property var compareFunc: null
onCompareFuncChanged: sort()
function internalCompareFunc(obj1, obj2) {
return compareFunc(obj1, obj2)
}
function sort() {
listModelSort(sortedListModel, compareFunc)
}
function insertSorted(item) {
listModelInsertSorted(sortedListModel, compareFunc, item)
}
function listModelSort(listModel, compareFunc) {
var indexes = new Array(listModel.count)
for (var i = 0; i < listModel.count; i++)
indexes[i] = i
indexes.sort(function (indexA, indexB) {
return compareFunc(get(indexA), get(indexB))
})
var sorted = 0
while (sorted < indexes.length && sorted === indexes[sorted])
sorted++
if (sorted === indexes.length)
return
for (i = sorted; i < indexes.length; i++) {
var idx = indexes[i]
listModel.move(idx, listModel.count - 1, 1)
listModel.insert(idx, {
})
}
listModel.remove(sorted, indexes.length - sorted)
}
function listModelIndexOf(listModel, startIndex, endIndex, item, compareFunc) {
if (startIndex > endIndex)
return startIndex
var startItem = listModel.get(startIndex)
var startCmp = compareFunc(item, startItem)
if (startCmp <= 0)
return startIndex
if (endIndex <= startIndex)
return startIndex + 1
var endItem = listModel.get(endIndex)
var endCmp = compareFunc(item, endItem)
if (endCmp === 0)
return endIndex
if (endCmp > 0)
return endIndex + 1
while (endIndex > startIndex + 1) {
var midIndex = (startIndex + endIndex) >> 1
var midItem = listModel.get(midIndex)
var midCmp = compareFunc(item, midItem)
if (midCmp === 0)
return midIndex
if (midCmp > 0)
endIndex = midIndex
else
startIndex = midIndex
}
return endIndex
}
function listModelInsertSorted(listModel, compareFunc, item) {
if (Array.isArray(item)) {
listModelInsertSortedArray(listModel, compareFunc, item)
return
}
try {
if (item instanceof ListModel) {
listModelInsertedSortedListModel(item)
return
}
} catch (err) {
}
if (listModel.count === 0) {
listModel.append(item)
return
}
var index = listModelIndexOf(listModel, 0, listModel.count - 1, item,
compareFunc)
if (index >= listModel.count) {
listModel.append(item)
return
}
var cmp = compareFunc(item, listModel.get(index))
if (cmp === 0) {
if (options && options.unique) {
listModel.set(index, item)
return
}
}
listModel.insert(index, item)
}
function listModelInsertSortedArray(listModel, compareFunc, arr) {
for (var i = 0; i < arr.length; i++)
listModelInsertSorted(listModel, compareFunc, arr[i])
}
function listModelInsertSortedListModel(listModel, compareFunc, model) {
for (var i = 0; i < model.count; i++)
listModelInsertSorted(listModel, compareFunc, model.get(i))
}
}