added ExpresionSorter

This commit is contained in:
oKcerG 2016-10-12 20:28:01 +02:00
parent 0b850c37ec
commit d3bee768f9
2 changed files with 135 additions and 0 deletions

View File

@ -104,9 +104,116 @@ int RoleSorter::compare(const QModelIndex &sourceLeft, const QModelIndex& source
return 0;
}
const QQmlScriptString& ExpressionSorter::expression() const
{
return m_scriptString;
}
void ExpressionSorter::setExpression(const QQmlScriptString& scriptString)
{
if (m_scriptString == scriptString)
return;
m_scriptString = scriptString;
updateExpression();
emit expressionChanged();
emit sorterChanged();
}
bool evaluateBoolExpression(QQmlExpression& expression)
{
QVariant variantResult = expression.evaluate();
if (expression.hasError()) {
qWarning() << expression.error();
return false;
}
if (variantResult.canConvert<bool>()) {
return variantResult.toBool();
} else {
qWarning("%s:%i:%i : Can't convert result to bool",
expression.sourceFile().toUtf8().data(),
expression.lineNumber(),
expression.columnNumber());
return false;
}
}
int ExpressionSorter::compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const
{
if (!m_scriptString.isEmpty()) {
QVariantMap modelLeftMap, modelRightMap;
QHash<int, QByteArray> roles = proxyModel()->roleNames();
QQmlContext context(qmlContext(this));
for (auto it = roles.cbegin(); it != roles.cend(); ++it) {
modelLeftMap.insert(it.value(), proxyModel()->sourceData(sourceLeft, it.key()));
modelRightMap.insert(it.value(), proxyModel()->sourceData(sourceRight, it.key()));
}
modelLeftMap.insert("index", sourceLeft.row());
modelRightMap.insert("index", sourceRight.row());
QQmlExpression expression(m_scriptString, &context);
context.setContextProperty("modelLeft", modelLeftMap);
context.setContextProperty("modelRight", modelRightMap);
if (evaluateBoolExpression(expression))
return -1;
context.setContextProperty("modelLeft", modelRightMap);
context.setContextProperty("modelRight", modelLeftMap);
if (evaluateBoolExpression(expression))
return 1;
}
return 0;
}
void ExpressionSorter::proxyModelCompleted()
{
updateContext();
}
void ExpressionSorter::updateContext()
{
if (!proxyModel())
return;
delete m_context;
m_context = new QQmlContext(qmlContext(this), this);
QVariantMap modelLeftMap, modelRightMap;
// what about roles changes ?
for (const QByteArray& roleName : proxyModel()->roleNames().values()) {
modelLeftMap.insert(roleName, QVariant());
modelRightMap.insert(roleName, QVariant());
}
modelLeftMap.insert("index", -1);
modelRightMap.insert("index", -1);
m_context->setContextProperty("modelLeft", modelLeftMap);
m_context->setContextProperty("modelRight", modelRightMap);
updateExpression();
}
void ExpressionSorter::updateExpression()
{
if (!m_context)
return;
delete m_expression;
m_expression = new QQmlExpression(m_scriptString, m_context, 0, this);
connect(m_expression, &QQmlExpression::valueChanged, this, &Sorter::sorterChanged);
m_expression->setNotifyOnValueChanged(true);
m_expression->evaluate();
}
void registerSorterTypes() {
qmlRegisterUncreatableType<Sorter>("SortFilterProxyModel", 0, 2, "Sorter", "Sorter is an abstract class");
qmlRegisterType<RoleSorter>("SortFilterProxyModel", 0, 2, "RoleSorter");
qmlRegisterType<ExpressionSorter>("SortFilterProxyModel", 0, 2, "ExpressionSorter");
}
Q_COREAPP_STARTUP_FUNCTION(registerSorterTypes)

View File

@ -2,6 +2,7 @@
#define SORTER_H
#include <QObject>
#include <QQmlExpression>
#include "qqmlsortfilterproxymodel.h"
namespace qqsfpm {
@ -69,6 +70,33 @@ private:
QString m_roleName;
};
class ExpressionSorter : public Sorter
{
Q_OBJECT
Q_PROPERTY(QQmlScriptString expression READ expression WRITE setExpression NOTIFY expressionChanged)
public:
using Sorter::Sorter;
const QQmlScriptString& expression() const;
void setExpression(const QQmlScriptString& scriptString);
signals:
void expressionChanged();
protected:
int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override;
void proxyModelCompleted() override;
private:
void updateContext();
void updateExpression();
QQmlScriptString m_scriptString;
QQmlExpression* m_expression = nullptr;
QQmlContext* m_context = nullptr;
};
}
#endif // SORTER_H