chore(LeftJoinModel): add detection of duplicated roles
This commit is contained in:
parent
cc964508f1
commit
7847cb3b11
|
@ -22,41 +22,56 @@ void LeftJoinModel::initialize()
|
||||||
auto leftRoleNames = m_leftModel->roleNames();
|
auto leftRoleNames = m_leftModel->roleNames();
|
||||||
auto rightRoleNames = m_rightModel->roleNames();
|
auto rightRoleNames = m_rightModel->roleNames();
|
||||||
|
|
||||||
if (leftRoleNames.isEmpty() || rightRoleNames.isEmpty()) {
|
auto leftNames = leftRoleNames.values();
|
||||||
qWarning() << "Both left and right models have to contain some roles!";
|
auto rightNames = rightRoleNames.values();
|
||||||
|
|
||||||
|
QSet<QByteArray> leftNamesSet(leftNames.cbegin(), leftNames.cend());
|
||||||
|
QSet<QByteArray> rightNamesSet(rightNames.cbegin(), rightNames.cend());
|
||||||
|
|
||||||
|
if (leftNames.size() != leftNamesSet.size()
|
||||||
|
|| rightNames.size() != rightNamesSet.size()) {
|
||||||
|
qWarning() << "Each of the source models must have unique role names!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto leftModelJoinRoleList = leftRoleNames.keys(m_joinRole.toUtf8());
|
auto namesIntersection = leftNamesSet.intersect(rightNamesSet);
|
||||||
auto rightModelJoinRoleList = rightRoleNames.keys(m_joinRole.toUtf8());
|
auto hasCommonJoinRole = namesIntersection.remove(m_joinRole.toUtf8());
|
||||||
|
|
||||||
if (leftModelJoinRoleList.size() != 1
|
if (!hasCommonJoinRole) {
|
||||||
|| rightModelJoinRoleList.size() != 1) {
|
|
||||||
qWarning().noquote() << QString("Both left and right models have to "
|
qWarning().noquote() << QString("Both left and right models have to "
|
||||||
"contain join role %1!").arg(m_joinRole);
|
"contain join role %1!").arg(m_joinRole);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_leftModelJoinRole = leftModelJoinRoleList.at(0);
|
if (!namesIntersection.isEmpty()) {
|
||||||
m_rightModelJoinRole = rightModelJoinRoleList.at(0);
|
qWarning().nospace() << "Source models contain conflicting model names: "
|
||||||
|
<< QList(namesIntersection.cbegin(),
|
||||||
|
namesIntersection.cend())
|
||||||
|
<< "!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto leftRoles = leftRoleNames.keys();
|
auto leftRoles = leftRoleNames.keys();
|
||||||
auto maxLeftRole = std::max_element(leftRoles.cbegin(), leftRoles.cend());
|
auto maxLeftRole = std::max_element(leftRoles.cbegin(), leftRoles.cend());
|
||||||
auto rightRolesOffset = *maxLeftRole + 1;
|
auto rightRolesOffset = *maxLeftRole + 1;
|
||||||
auto roleNames = leftRoleNames;
|
auto roleNames = leftRoleNames;
|
||||||
|
QVector<int> joinedRoles;
|
||||||
|
|
||||||
auto i = rightRoleNames.constBegin();
|
auto i = rightRoleNames.constBegin();
|
||||||
while (i != rightRoleNames.constEnd()) {
|
while (i != rightRoleNames.constEnd()) {
|
||||||
if (i.value() != m_joinRole) {
|
if (i.value() != m_joinRole) {
|
||||||
auto roleWithOffset = i.key() + rightRolesOffset;
|
auto roleWithOffset = i.key() + rightRolesOffset;
|
||||||
roleNames.insert(roleWithOffset, i.value());
|
roleNames.insert(roleWithOffset, i.value());
|
||||||
m_joinedRoles.append(roleWithOffset);
|
joinedRoles.append(roleWithOffset);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_roleNames = std::move(roleNames);
|
||||||
|
m_joinedRoles = std::move(joinedRoles);
|
||||||
|
m_leftModelJoinRole = leftRoleNames.key(m_joinRole.toUtf8());
|
||||||
|
m_rightModelJoinRole = rightRoleNames.key(m_joinRole.toUtf8());
|
||||||
m_rightModelRolesOffset = rightRolesOffset;
|
m_rightModelRolesOffset = rightRolesOffset;
|
||||||
m_roleNames = roleNames;
|
|
||||||
|
|
||||||
connect(m_rightModel, &QAbstractItemModel::dataChanged, this,
|
connect(m_rightModel, &QAbstractItemModel::dataChanged, this,
|
||||||
[this](auto& topLeft, auto& bottomRight, auto& roles) {
|
[this](auto& topLeft, auto& bottomRight, auto& roles) {
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace {
|
||||||
class TestSourceModel : public QAbstractListModel {
|
class TestSourceModel : public QAbstractListModel {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit TestSourceModel(QList<QPair<QString, QVariantList>> data)
|
explicit TestSourceModel(QList<QPair<QString, QVariantList>> data)
|
||||||
: m_data(std::move(data))
|
: m_data(std::move(data))
|
||||||
{
|
{
|
||||||
|
@ -86,7 +85,7 @@ private:
|
||||||
QHash<int, QByteArray> m_roles;
|
QHash<int, QByteArray> m_roles;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // anonymous namespace
|
||||||
|
|
||||||
class TestLeftJoinModel: public QObject
|
class TestLeftJoinModel: public QObject
|
||||||
{
|
{
|
||||||
|
@ -102,6 +101,25 @@ private slots:
|
||||||
QCOMPARE(model.roleNames(), {});
|
QCOMPARE(model.roleNames(), {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSourceModelDirectlyTest()
|
||||||
|
{
|
||||||
|
TestSourceModel leftModel({
|
||||||
|
{ "title", { "Token 1", "Token 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
LeftJoinModel model;
|
||||||
|
QAbstractItemModelTester tester(&model);
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"Source model is not intended to be set directly "
|
||||||
|
"on this model. Use setLeftModel and setRightModel instead!");
|
||||||
|
model.setSourceModel(&leftModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
|
|
||||||
void initializationTest()
|
void initializationTest()
|
||||||
{
|
{
|
||||||
TestSourceModel leftModel({
|
TestSourceModel leftModel({
|
||||||
|
@ -135,23 +153,145 @@ private slots:
|
||||||
QCOMPARE(model.roleNames(), roles);
|
QCOMPARE(model.roleNames(), roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSourceModelDirectlyTest()
|
void collidingRolesTest()
|
||||||
{
|
{
|
||||||
TestSourceModel leftModel({
|
TestSourceModel leftModel({
|
||||||
{ "title", { "Token 1", "Token 2" }},
|
{ "name", { "Token 1", "Token 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
TestSourceModel rightModel({
|
||||||
|
{ "name", { "Community 1", "Community 2" }},
|
||||||
{ "communityId", { "community_1", "community_2" }}
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
});
|
});
|
||||||
|
|
||||||
LeftJoinModel model;
|
LeftJoinModel model;
|
||||||
QAbstractItemModelTester tester(&model);
|
QAbstractItemModelTester tester(&model);
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg,
|
model.setLeftModel(&leftModel);
|
||||||
"Source model is not intended to be set directly "
|
|
||||||
"on this model. Use setLeftModel and setRightModel instead!");
|
|
||||||
model.setSourceModel(&leftModel);
|
|
||||||
|
|
||||||
QCOMPARE(model.rowCount(), 0);
|
QCOMPARE(model.rowCount(), 0);
|
||||||
QCOMPARE(model.roleNames(), {});
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
model.setRightModel(&rightModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"Source models contain conflicting model names: "
|
||||||
|
"(\"name\")!");
|
||||||
|
|
||||||
|
model.setJoinRole("communityId");
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void duplicatedRolesTest()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TestSourceModel leftModel({
|
||||||
|
{ "name", { "Token 1", "Token 2" }},
|
||||||
|
{ "name", { "Token 1", "Token 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
TestSourceModel rightModel({
|
||||||
|
{ "title", { "Community 1", "Community 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
LeftJoinModel model;
|
||||||
|
QAbstractItemModelTester tester(&model);
|
||||||
|
|
||||||
|
model.setLeftModel(&leftModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
model.setRightModel(&rightModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"Each of the source models must have unique "
|
||||||
|
"role names!");
|
||||||
|
|
||||||
|
model.setJoinRole("communityId");
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TestSourceModel leftModel({
|
||||||
|
{ "name", { "Token 1", "Token 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
TestSourceModel rightModel({
|
||||||
|
{ "title", { "Community 1", "Community 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
LeftJoinModel model;
|
||||||
|
QAbstractItemModelTester tester(&model);
|
||||||
|
|
||||||
|
model.setLeftModel(&leftModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
model.setRightModel(&rightModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"Each of the source models must have unique "
|
||||||
|
"role names!");
|
||||||
|
|
||||||
|
model.setJoinRole("communityId");
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TestSourceModel leftModel({
|
||||||
|
{ "name", { "Token 1", "Token 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
TestSourceModel rightModel({
|
||||||
|
{ "title", { "Community 1", "Community 2" }},
|
||||||
|
{ "title", { "Community 1", "Community 2" }},
|
||||||
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
|
});
|
||||||
|
|
||||||
|
LeftJoinModel model;
|
||||||
|
QAbstractItemModelTester tester(&model);
|
||||||
|
|
||||||
|
model.setLeftModel(&leftModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
model.setRightModel(&rightModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"Each of the source models must have unique "
|
||||||
|
"role names!");
|
||||||
|
|
||||||
|
model.setJoinRole("communityId");
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void noJoinRoleTest()
|
void noJoinRoleTest()
|
||||||
|
@ -266,6 +406,7 @@ private slots:
|
||||||
|
|
||||||
TestSourceModel rightModel({
|
TestSourceModel rightModel({
|
||||||
{ "name", { "Community 1", "Community 2" }},
|
{ "name", { "Community 1", "Community 2" }},
|
||||||
|
{ "color", { "red", "blue" }},
|
||||||
{ "communityId", { "community_1", "community_2" }}
|
{ "communityId", { "community_1", "community_2" }}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -283,6 +424,8 @@ private slots:
|
||||||
QCOMPARE(model.data(model.index(1, 0), 1), QString("community_2"));
|
QCOMPARE(model.data(model.index(1, 0), 1), QString("community_2"));
|
||||||
QCOMPARE(model.data(model.index(0, 0), 2), QString("Community 1"));
|
QCOMPARE(model.data(model.index(0, 0), 2), QString("Community 1"));
|
||||||
QCOMPARE(model.data(model.index(1, 0), 2), QString("Community 2"));
|
QCOMPARE(model.data(model.index(1, 0), 2), QString("Community 2"));
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), 3), QString("red"));
|
||||||
|
QCOMPARE(model.data(model.index(1, 0), 3), QString("blue"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void changesPropagationTest()
|
void changesPropagationTest()
|
||||||
|
|
Loading…
Reference in New Issue