StatusQ: Add generic LeftJoinModel model mimicking SQL Left Join
Closes: #12502
This commit is contained in:
parent
628d9cdd31
commit
ffadd7522c
|
@ -0,0 +1,283 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
readonly property var colors: [
|
||||
"red", "green", "purple", "orange","gray", "ping", "brown", "blue"
|
||||
]
|
||||
|
||||
ListModel {
|
||||
id: leftModel
|
||||
|
||||
ListElement {
|
||||
title: "Token 1"
|
||||
communityId: "1"
|
||||
}
|
||||
ListElement {
|
||||
title: "Token 2"
|
||||
communityId: "1"
|
||||
}
|
||||
ListElement {
|
||||
title: "Token 3"
|
||||
communityId: "2"
|
||||
}
|
||||
ListElement {
|
||||
title: "Token 4"
|
||||
communityId: "3"
|
||||
}
|
||||
ListElement {
|
||||
title: "Token 5"
|
||||
communityId: ""
|
||||
}
|
||||
ListElement {
|
||||
title: "Token 6"
|
||||
communityId: "1"
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: rightModel
|
||||
|
||||
ListElement {
|
||||
communityId: "1"
|
||||
name: "Community 1"
|
||||
color: "red"
|
||||
|
||||
}
|
||||
ListElement {
|
||||
communityId: "2"
|
||||
name: "Community 2"
|
||||
color: "green"
|
||||
}
|
||||
ListElement {
|
||||
communityId: "3"
|
||||
name: "Community 3"
|
||||
color: "blue"
|
||||
}
|
||||
}
|
||||
|
||||
LeftJoinModel {
|
||||
id: leftJoinModel
|
||||
|
||||
leftModel: leftModel
|
||||
rightModel: rightModel
|
||||
|
||||
joinRole: "communityId"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 40
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
border.color: "gray"
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
|
||||
model: leftModel
|
||||
|
||||
header: Label {
|
||||
height: implicitHeight * 2
|
||||
text: `Left model (${leftModel.count})`
|
||||
|
||||
font.bold: true
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
delegate: Label {
|
||||
width: ListView.view.width
|
||||
|
||||
text: `${model.title}, community id: ${model.communityId || "-"}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
border.color: "gray"
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
|
||||
model: rightModel
|
||||
|
||||
header: Label {
|
||||
height: implicitHeight * 2
|
||||
text: `Right model (${rightModel.count})`
|
||||
|
||||
font.bold: true
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
delegate: RowLayout {
|
||||
width: ListView.view.width - 10
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: `${model.name}, community id: ${model.communityId}`
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: parent.height
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
color: model.color
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
const colorIndex = root.colors.indexOf(
|
||||
model.color)
|
||||
const nextIndex = (colorIndex + 1)
|
||||
% root.colors.length
|
||||
|
||||
rightModel.setProperty(index, "color",
|
||||
root.colors[nextIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
border.color: "gray"
|
||||
|
||||
ListView {
|
||||
id: leftJoinListView
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
model: leftJoinModel
|
||||
|
||||
header: Label {
|
||||
height: implicitHeight * 2
|
||||
text: `Left Join model (${leftJoinListView.count})`
|
||||
|
||||
font.bold: true
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
delegate: RowLayout {
|
||||
id: row
|
||||
|
||||
width: ListView.view.width - 10
|
||||
|
||||
readonly property bool hasCommunity: model.communityId.length
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: model.title + (row.hasCommunity
|
||||
? `, community id: ${model.communityId}, name: ${model.name}`
|
||||
: "")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: parent.height
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
color: model.color || "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Label {
|
||||
text: "Left model count: " + leftModel.count
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Right model count: " + rightModel.count
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "add 100 left model items"
|
||||
|
||||
onClicked: {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
|
||||
const count = leftModel.count
|
||||
|
||||
const entry = {
|
||||
title: "Token " + (count + 1),
|
||||
communityId: (Math.floor(Math.random() * rightModel.count) + 1).toString()
|
||||
}
|
||||
|
||||
leftModel.append(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "add 10 right model items"
|
||||
|
||||
onClicked: {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const count = rightModel.count
|
||||
|
||||
const entry = {
|
||||
communityId: count.toString(),
|
||||
name: "Community " + count,
|
||||
color: root.colors[Math.floor(Math.random() * colors.length)]
|
||||
}
|
||||
|
||||
rightModel.append(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "shuffle"
|
||||
|
||||
onClicked: {
|
||||
const count = leftModel.count
|
||||
const iterations = count / 2
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
leftModel.move(Math.floor(Math.random() * (count - 1)),
|
||||
Math.floor(Math.random() * (count - 1)),
|
||||
Math.floor(Math.random() * 2) + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// category: Models
|
|
@ -89,6 +89,7 @@ endif()
|
|||
add_library(StatusQ SHARED
|
||||
${STATUSQ_QRC_COMPILED}
|
||||
include/StatusQ/QClipboardProxy.h
|
||||
include/StatusQ/leftjoinmodel.h
|
||||
include/StatusQ/modelutilsinternal.h
|
||||
include/StatusQ/permissionutilsinternal.h
|
||||
include/StatusQ/rolesrenamingmodel.h
|
||||
|
@ -97,6 +98,7 @@ add_library(StatusQ SHARED
|
|||
include/StatusQ/statuswindow.h
|
||||
include/StatusQ/stringutilsinternal.h
|
||||
src/QClipboardProxy.cpp
|
||||
src/leftjoinmodel.cpp
|
||||
src/modelutilsinternal.cpp
|
||||
src/permissionutilsinternal.cpp
|
||||
src/plugin.cpp
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include <QIdentityProxyModel>
|
||||
|
||||
class LeftJoinModel : public QIdentityProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QAbstractItemModel* leftModel READ leftModel
|
||||
WRITE setLeftModel NOTIFY leftModelChanged)
|
||||
|
||||
Q_PROPERTY(QAbstractItemModel* rightModel READ rightModel
|
||||
WRITE setRightModel NOTIFY rightModelChanged)
|
||||
|
||||
Q_PROPERTY(QString joinRole READ joinRole
|
||||
WRITE setJoinRole NOTIFY joinRoleChanged)
|
||||
|
||||
public:
|
||||
explicit LeftJoinModel(QObject* parent = nullptr);
|
||||
|
||||
void setLeftModel(QAbstractItemModel* model);
|
||||
QAbstractItemModel* leftModel() const;
|
||||
|
||||
void setRightModel(QAbstractItemModel* model);
|
||||
QAbstractItemModel* rightModel() const;
|
||||
|
||||
void setJoinRole(const QString& joinRole);
|
||||
const QString& joinRole() const;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
void setSourceModel(QAbstractItemModel* newSourceModel) override;
|
||||
|
||||
signals:
|
||||
void leftModelChanged();
|
||||
void rightModelChanged();
|
||||
void joinRoleChanged();
|
||||
|
||||
private:
|
||||
void initializeIfReady();
|
||||
void initialize();
|
||||
|
||||
int m_rightModelRolesOffset = 0;
|
||||
QHash<int, QByteArray> m_roleNames;
|
||||
QVector<int> m_joinedRoles;
|
||||
|
||||
QString m_joinRole;
|
||||
int m_leftModelJoinRole = 0;
|
||||
int m_rightModelJoinRole = 0;
|
||||
|
||||
QAbstractItemModel* m_leftModel = nullptr;
|
||||
QAbstractItemModel* m_rightModel = nullptr;
|
||||
|
||||
bool m_leftModelDestroyed = false;
|
||||
bool m_rightModelDestroyed = false;
|
||||
|
||||
mutable QPersistentModelIndex m_lastUsedRightModelIndex;
|
||||
};
|
|
@ -0,0 +1,240 @@
|
|||
#include "StatusQ/leftjoinmodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
LeftJoinModel::LeftJoinModel(QObject* parent)
|
||||
: QIdentityProxyModel{parent}
|
||||
{
|
||||
}
|
||||
|
||||
void LeftJoinModel::initializeIfReady()
|
||||
{
|
||||
if (m_leftModel && m_rightModel && !m_joinRole.isEmpty()
|
||||
&& !m_leftModel->roleNames().empty()
|
||||
&& !m_rightModel->roleNames().empty())
|
||||
initialize();
|
||||
}
|
||||
|
||||
void LeftJoinModel::initialize()
|
||||
{
|
||||
auto leftRoleNames = m_leftModel->roleNames();
|
||||
auto rightRoleNames = m_rightModel->roleNames();
|
||||
|
||||
if (leftRoleNames.isEmpty() || rightRoleNames.isEmpty()) {
|
||||
qWarning() << "Both left and right models have to contain some roles!";
|
||||
return;
|
||||
}
|
||||
|
||||
auto leftModelJoinRoleList = leftRoleNames.keys(m_joinRole.toUtf8());
|
||||
auto rightModelJoinRoleList = rightRoleNames.keys(m_joinRole.toUtf8());
|
||||
|
||||
if (leftModelJoinRoleList.size() != 1
|
||||
|| rightModelJoinRoleList.size() != 1) {
|
||||
qWarning().noquote() << QString("Both left and right models have to "
|
||||
"contain join role %1!").arg(m_joinRole);
|
||||
return;
|
||||
}
|
||||
|
||||
m_leftModelJoinRole = leftModelJoinRoleList.at(0);
|
||||
m_rightModelJoinRole = rightModelJoinRoleList.at(0);
|
||||
|
||||
auto leftRoles = leftRoleNames.keys();
|
||||
auto maxLeftRole = std::max_element(leftRoles.cbegin(), leftRoles.cend());
|
||||
auto rightRolesOffset = *maxLeftRole + 1;
|
||||
auto roleNames = leftRoleNames;
|
||||
|
||||
auto i = rightRoleNames.constBegin();
|
||||
while (i != rightRoleNames.constEnd()) {
|
||||
if (i.value() != m_joinRole) {
|
||||
auto roleWithOffset = i.key() + rightRolesOffset;
|
||||
roleNames.insert(roleWithOffset, i.value());
|
||||
m_joinedRoles.append(roleWithOffset);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
m_rightModelRolesOffset = rightRolesOffset;
|
||||
m_roleNames = roleNames;
|
||||
|
||||
connect(m_rightModel, &QAbstractItemModel::dataChanged, this,
|
||||
[this](auto& topLeft, auto& bottomRight, auto& roles) {
|
||||
QVector<int> rolesTranslated;
|
||||
|
||||
if (roles.contains(m_rightModelJoinRole)) {
|
||||
rolesTranslated = m_joinedRoles;
|
||||
} else {
|
||||
rolesTranslated = roles;
|
||||
|
||||
for (auto& role : rolesTranslated)
|
||||
role += m_rightModelRolesOffset;
|
||||
}
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, 0), rolesTranslated);
|
||||
});
|
||||
|
||||
disconnect(m_leftModel, &QAbstractItemModel::rowsInserted,
|
||||
this, &LeftJoinModel::initializeIfReady);
|
||||
disconnect(m_rightModel, &QAbstractItemModel::rowsInserted,
|
||||
this, &LeftJoinModel::initializeIfReady);
|
||||
|
||||
auto emitJoinedRolesChanged = [this] {
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, 0), m_joinedRoles);
|
||||
};
|
||||
|
||||
connect(m_rightModel, &QAbstractItemModel::rowsRemoved, this,
|
||||
emitJoinedRolesChanged);
|
||||
connect(m_rightModel, &QAbstractItemModel::rowsInserted, this,
|
||||
emitJoinedRolesChanged);
|
||||
connect(m_rightModel, &QAbstractItemModel::modelReset, this,
|
||||
emitJoinedRolesChanged);
|
||||
connect(m_rightModel, &QAbstractItemModel::layoutChanged, this,
|
||||
emitJoinedRolesChanged);
|
||||
|
||||
connect(this, &QAbstractItemModel::dataChanged, this,
|
||||
[this](auto& topLeft, auto& bottomRight, auto& roles) {
|
||||
if (roles.contains(m_leftModelJoinRole))
|
||||
emit dataChanged(topLeft, bottomRight, m_joinedRoles);
|
||||
});
|
||||
|
||||
QIdentityProxyModel::setSourceModel(m_leftModel);
|
||||
}
|
||||
|
||||
QVariant LeftJoinModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
auto idx = m_leftModel->index(index.row(), index.column());
|
||||
|
||||
if (role < m_rightModelRolesOffset)
|
||||
return m_leftModel->data(idx, role);
|
||||
|
||||
if (m_rightModelDestroyed)
|
||||
return {};
|
||||
|
||||
QVariant joinRoleLeftValue = m_leftModel->data(idx, m_leftModelJoinRole);
|
||||
|
||||
if (m_lastUsedRightModelIndex.isValid()
|
||||
&& m_rightModel->data(m_lastUsedRightModelIndex,
|
||||
m_rightModelJoinRole) == joinRoleLeftValue)
|
||||
{
|
||||
return m_rightModel->data(m_lastUsedRightModelIndex,
|
||||
role - m_rightModelRolesOffset);
|
||||
}
|
||||
|
||||
int rightModelCount = m_rightModel->rowCount();
|
||||
|
||||
for (int i = 0; i < rightModelCount; i++) {
|
||||
auto rightModelIdx = m_rightModel->index(i, 0);
|
||||
auto rightJointRoleValue = m_rightModel->data(rightModelIdx,
|
||||
m_rightModelJoinRole);
|
||||
|
||||
if (joinRoleLeftValue == rightJointRoleValue) {
|
||||
m_lastUsedRightModelIndex = rightModelIdx;
|
||||
|
||||
return m_rightModel->data(rightModelIdx,
|
||||
role - m_rightModelRolesOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void LeftJoinModel::setLeftModel(QAbstractItemModel* model)
|
||||
{
|
||||
if (m_leftModel == model)
|
||||
return;
|
||||
|
||||
if (m_leftModel != nullptr || m_leftModelDestroyed) {
|
||||
qWarning("Changing left model is not supported!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_leftModel = model;
|
||||
|
||||
// Some models may have roles undefined until first row is inserted,
|
||||
// like ListModel, therefore in such cases initialization must be deferred
|
||||
// until first insertion.
|
||||
connect(m_leftModel, &QAbstractItemModel::rowsInserted,
|
||||
this, &LeftJoinModel::initializeIfReady);
|
||||
|
||||
connect(m_leftModel, &QObject::destroyed, this, [this] {
|
||||
this->m_leftModel = nullptr;
|
||||
this->m_leftModelDestroyed = true;
|
||||
});
|
||||
|
||||
emit leftModelChanged();
|
||||
|
||||
initializeIfReady();
|
||||
}
|
||||
|
||||
QAbstractItemModel* LeftJoinModel::leftModel() const
|
||||
{
|
||||
return m_leftModel;
|
||||
}
|
||||
|
||||
void LeftJoinModel::setRightModel(QAbstractItemModel* model)
|
||||
{
|
||||
if (m_rightModel == model)
|
||||
return;
|
||||
|
||||
if (m_rightModel != nullptr || m_rightModelDestroyed) {
|
||||
qWarning("Changing right model is not supported!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_rightModel = model;
|
||||
|
||||
// see: LeftJoinModel::setLeftModel
|
||||
connect(m_rightModel, &QAbstractItemModel::rowsInserted,
|
||||
this, &LeftJoinModel::initializeIfReady);
|
||||
|
||||
connect(m_rightModel, &QObject::destroyed, this, [this] {
|
||||
this->m_rightModel = nullptr;
|
||||
this->m_rightModelDestroyed = true;
|
||||
});
|
||||
|
||||
emit rightModelChanged();
|
||||
|
||||
initializeIfReady();
|
||||
}
|
||||
|
||||
QAbstractItemModel* LeftJoinModel::rightModel() const
|
||||
{
|
||||
return m_rightModel;
|
||||
}
|
||||
|
||||
void LeftJoinModel::setJoinRole(const QString& joinRole)
|
||||
{
|
||||
if (m_joinRole.isEmpty() && joinRole.isEmpty())
|
||||
return;
|
||||
|
||||
if (!m_joinRole.isEmpty()) {
|
||||
qWarning("Changing join role is not supported!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_joinRole = joinRole;
|
||||
|
||||
emit joinRoleChanged();
|
||||
|
||||
initializeIfReady();
|
||||
}
|
||||
|
||||
const QString& LeftJoinModel::joinRole() const
|
||||
{
|
||||
return m_joinRole;
|
||||
}
|
||||
|
||||
void LeftJoinModel::setSourceModel(QAbstractItemModel* newSourceModel)
|
||||
{
|
||||
qWarning() << "Source model is not intended to be set directly on this model."
|
||||
" Use setLeftModel and setRightModel instead!";
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> LeftJoinModel::roleNames() const
|
||||
{
|
||||
return m_roleNames;
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#include <qqmlsortfilterproxymodeltypes.h>
|
||||
|
||||
#include "StatusQ/QClipboardProxy.h"
|
||||
#include "StatusQ/leftjoinmodel.h"
|
||||
#include "StatusQ/modelutilsinternal.h"
|
||||
#include "StatusQ/permissionutilsinternal.h"
|
||||
#include "StatusQ/rolesrenamingmodel.h"
|
||||
|
@ -25,6 +26,7 @@ public:
|
|||
qmlRegisterType<StatusSyntaxHighlighter>("StatusQ", 0, 1, "StatusSyntaxHighlighter");
|
||||
qmlRegisterType<RXValidator>("StatusQ", 0, 1, "RXValidator");
|
||||
|
||||
qmlRegisterType<LeftJoinModel>("StatusQ", 0, 1, "LeftJoinModel");
|
||||
qmlRegisterType<RolesRenamingModel>("StatusQ", 0, 1, "RolesRenamingModel");
|
||||
qmlRegisterType<RoleRename>("StatusQ", 0, 1, "RoleRename");
|
||||
|
||||
|
|
|
@ -44,3 +44,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE
|
|||
add_executable(RolesRenamingModelTest tst_RolesRenamingModel.cpp)
|
||||
target_link_libraries(RolesRenamingModelTest PRIVATE Qt5::Qml Qt5::Test StatusQ)
|
||||
add_test(RolesRenamingModelTest COMMAND RolesRenamingModelTest)
|
||||
|
||||
add_executable(LeftJoinModelTest tst_LeftJoinModel.cpp)
|
||||
target_link_libraries(LeftJoinModelTest PRIVATE Qt5::Test StatusQ)
|
||||
add_test(LeftJoinModelTest COMMAND LeftJoinModelTest)
|
||||
|
|
|
@ -0,0 +1,626 @@
|
|||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <StatusQ/leftjoinmodel.h>
|
||||
|
||||
namespace {
|
||||
|
||||
class TestSourceModel : public QAbstractListModel {
|
||||
|
||||
public:
|
||||
|
||||
explicit TestSourceModel(QList<QPair<QString, QVariantList>> data)
|
||||
: m_data(std::move(data))
|
||||
{
|
||||
m_roles.reserve(m_data.size());
|
||||
|
||||
for (auto i = 0; i < m_data.size(); i++)
|
||||
m_roles.insert(i, m_data.at(i).first.toUtf8());
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex& parent) const override
|
||||
{
|
||||
assert(m_data.size());
|
||||
return m_data.first().second.size();
|
||||
}
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
const auto row = index.row();
|
||||
|
||||
if (role >= m_data.length() || row >= m_data.at(0).second.length())
|
||||
return {};
|
||||
|
||||
return m_data.at(role).second.at(row);
|
||||
}
|
||||
|
||||
void insert(int index, QVariantList row)
|
||||
{
|
||||
beginInsertRows(QModelIndex{}, index, index);
|
||||
|
||||
assert(row.size() == m_data.size());
|
||||
|
||||
for (int i = 0; i < m_data.size(); i++) {
|
||||
auto& roleVariantList = m_data[i].second;
|
||||
assert(index <= roleVariantList.size());
|
||||
roleVariantList.insert(index, row.at(i));
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void update(int index, int role, QVariant value)
|
||||
{
|
||||
assert(role < m_data.size() && index < m_data[role].second.size());
|
||||
m_data[role].second[index].setValue(std::move(value));
|
||||
|
||||
emit dataChanged(this->index(index, 0), this->index(index, 0), { role });
|
||||
}
|
||||
|
||||
void remove(int index)
|
||||
{
|
||||
beginRemoveRows(QModelIndex{}, index, index);
|
||||
|
||||
for (int i = 0; i < m_data.size(); i++) {
|
||||
auto& roleVariantList = m_data[i].second;
|
||||
assert(index < roleVariantList.size());
|
||||
roleVariantList.removeAt(index);
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override
|
||||
{
|
||||
return m_roles;
|
||||
}
|
||||
|
||||
private:
|
||||
QList<QPair<QString, QVariantList>> m_data;
|
||||
QHash<int, QByteArray> m_roles;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class TestLeftJoinModel: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
|
||||
void emptyModelTest() {
|
||||
LeftJoinModel model;
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
}
|
||||
|
||||
void initializationTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
model.setRightModel(&rightModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
|
||||
QHash<int, QByteArray> roles{{0, "title" }, {1, "communityId"}, {2, "name"}};
|
||||
QCOMPARE(model.roleNames(), roles);
|
||||
}
|
||||
|
||||
void setSourceModelDirectlyTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel 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 noJoinRoleTest()
|
||||
{
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
model.setRightModel(&rightModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Both left and right models have to contain "
|
||||
"join role someRole!");
|
||||
|
||||
model.setJoinRole("someRole");
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
}
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
model.setRightModel(&rightModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Both left and right models have to contain "
|
||||
"join role title!");
|
||||
|
||||
model.setJoinRole("title");
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
}
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
model.setRightModel(&rightModel);
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Both left and right models have to contain "
|
||||
"join role name!");
|
||||
|
||||
model.setJoinRole("name");
|
||||
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
}
|
||||
}
|
||||
|
||||
void basicAccesTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
model.setRightModel(&rightModel);
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
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(1, 0), 2), QString("Community 2"));
|
||||
}
|
||||
|
||||
void changesPropagationTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }},
|
||||
{ "color", { "red", "green" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
model.setRightModel(&rightModel);
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
{
|
||||
QSignalSpy dataChangedSpy(&model, &LeftJoinModel::dataChanged);
|
||||
|
||||
rightModel.update(0, 0, "Community 1 Updated");
|
||||
QCOMPARE(dataChangedSpy.count(), 1);
|
||||
|
||||
QCOMPARE(dataChangedSpy.first().at(0), model.index(0, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(1), model.index(model.rowCount() - 1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(2).value<QVector<int>>(), {2});
|
||||
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 1), QString("community_2"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 2), QString("Community 1 Updated"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 2), QString("Community 2"));
|
||||
}
|
||||
{
|
||||
QSignalSpy dataChangedSpy(&model, &LeftJoinModel::dataChanged);
|
||||
|
||||
leftModel.update(1, 0, "Token 2 Updated");
|
||||
QCOMPARE(dataChangedSpy.count(), 1);
|
||||
|
||||
QCOMPARE(dataChangedSpy.first().at(0), model.index(1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(1), model.index(1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(2).value<QVector<int>>(), {0});
|
||||
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2 Updated"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 1), QString("community_2"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 2), QString("Community 1 Updated"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 2), QString("Community 2"));
|
||||
}
|
||||
}
|
||||
|
||||
void rightModelJoinRoleChangesPropagationTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
model.setRightModel(&rightModel);
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QSignalSpy dataChangedSpy(&model, &LeftJoinModel::dataChanged);
|
||||
|
||||
rightModel.update(1, 1, "community_3");
|
||||
QCOMPARE(dataChangedSpy.count(), 1);
|
||||
|
||||
QCOMPARE(dataChangedSpy.first().at(0), model.index(0, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(1), model.index(model.rowCount() - 1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(2).value<QVector<int>>(), {2});
|
||||
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
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(1, 0), 2), {});
|
||||
}
|
||||
|
||||
void rightModelRemovalPropagationTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
model.setRightModel(&rightModel);
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QSignalSpy dataChangedSpy(&model, &LeftJoinModel::dataChanged);
|
||||
|
||||
rightModel.remove(1);
|
||||
QCOMPARE(dataChangedSpy.count(), 1);
|
||||
|
||||
QCOMPARE(dataChangedSpy.first().at(0), model.index(0, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(1), model.index(model.rowCount() - 1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(2).value<QVector<int>>(), {2});
|
||||
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
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(1, 0), 2), {});
|
||||
}
|
||||
|
||||
void rightModelAdditionPropagationTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_3" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
model.setRightModel(&rightModel);
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QSignalSpy dataChangedSpy(&model, &LeftJoinModel::dataChanged);
|
||||
|
||||
rightModel.insert(2, {"Community 3", "community_3"});
|
||||
QCOMPARE(dataChangedSpy.count(), 1);
|
||||
|
||||
QCOMPARE(dataChangedSpy.first().at(0), model.index(0, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(1), model.index(model.rowCount() - 1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(2).value<QVector<int>>(), {2});
|
||||
|
||||
QCOMPARE(model.rowCount(), 3);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2"));
|
||||
QCOMPARE(model.data(model.index(2, 0), 0), QString("Token 3"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 1), QString("community_2"));
|
||||
QCOMPARE(model.data(model.index(2, 0), 1), QString("community_3"));
|
||||
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(2, 0), 2), QString("Community 3"));
|
||||
}
|
||||
|
||||
void leftModelJoinRoleChangesPropagationTest()
|
||||
{
|
||||
TestSourceModel leftModel({
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
TestSourceModel rightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(&leftModel);
|
||||
model.setRightModel(&rightModel);
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QSignalSpy dataChangedSpy(&model, &LeftJoinModel::dataChanged);
|
||||
|
||||
leftModel.update(1, 1, "community_1");
|
||||
QCOMPARE(dataChangedSpy.count(), 2);
|
||||
|
||||
QCOMPARE(dataChangedSpy.first().at(0), model.index(1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(1), model.index(1, 0));
|
||||
QCOMPARE(dataChangedSpy.first().at(2).value<QVector<int>>(), {2});
|
||||
|
||||
QCOMPARE(dataChangedSpy.at(1).at(0), model.index(1, 0));
|
||||
QCOMPARE(dataChangedSpy.at(1).at(1), model.index(1, 0));
|
||||
QCOMPARE(dataChangedSpy.at(1).at(2).value<QVector<int>>(), {1});
|
||||
|
||||
QCOMPARE(model.rowCount(), 3);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), QString("Token 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 0), QString("Token 2"));
|
||||
QCOMPARE(model.data(model.index(2, 0), 0), QString("Token 3"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), QString("community_1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 1), QString("community_1"));
|
||||
QCOMPARE(model.data(model.index(2, 0), 1), QString("community_1"));
|
||||
QCOMPARE(model.data(model.index(0, 0), 2), QString("Community 1"));
|
||||
QCOMPARE(model.data(model.index(1, 0), 2), QString("Community 1"));
|
||||
QCOMPARE(model.data(model.index(2, 0), 2), QString("Community 1"));
|
||||
}
|
||||
|
||||
void modelsDeletedBeforeInitializationTest()
|
||||
{
|
||||
auto leftModel = std::make_unique<TestSourceModel>(
|
||||
QList<QPair<QString, QVariantList>>{
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
auto rightModel = std::make_unique<TestSourceModel>(
|
||||
QList<QPair<QString, QVariantList>>{
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(leftModel.get());
|
||||
model.setRightModel(rightModel.get());
|
||||
|
||||
leftModel.reset();
|
||||
rightModel.reset();
|
||||
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
QCOMPARE(model.roleNames(), {});
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), {});
|
||||
QCOMPARE(model.data(model.index(0, 0), 2), {});
|
||||
|
||||
TestSourceModel newLeftModel({
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
TestSourceModel newRightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Changing left model is not supported!");
|
||||
model.setLeftModel(&newLeftModel);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Changing right model is not supported!");
|
||||
model.setRightModel(&newRightModel);
|
||||
}
|
||||
|
||||
void modelsDeletedAfterInitializationTest()
|
||||
{
|
||||
auto leftModel = std::make_unique<TestSourceModel>(
|
||||
QList<QPair<QString, QVariantList>>{
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
auto rightModel = std::make_unique<TestSourceModel>(
|
||||
QList<QPair<QString, QVariantList>>{
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(leftModel.get());
|
||||
model.setRightModel(rightModel.get());
|
||||
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
leftModel.reset();
|
||||
rightModel.reset();
|
||||
|
||||
QHash<int, QByteArray> roles{{0, "title" }, {1, "communityId"}, {2, "name"}};
|
||||
QCOMPARE(model.roleNames(), roles);
|
||||
QCOMPARE(model.rowCount(), 0);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), {});
|
||||
QCOMPARE(model.data(model.index(0, 0), 2), {});
|
||||
|
||||
TestSourceModel newLeftModel({
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
TestSourceModel newRightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Changing left model is not supported!");
|
||||
model.setLeftModel(&newLeftModel);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Changing right model is not supported!");
|
||||
model.setRightModel(&newRightModel);
|
||||
}
|
||||
|
||||
void rightModelDeletedAfterInitializationTest()
|
||||
{
|
||||
auto leftModel = std::make_unique<TestSourceModel>(
|
||||
QList<QPair<QString, QVariantList>>{
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
auto rightModel = std::make_unique<TestSourceModel>(
|
||||
QList<QPair<QString, QVariantList>>{
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
LeftJoinModel model;
|
||||
model.setLeftModel(leftModel.get());
|
||||
model.setRightModel(rightModel.get());
|
||||
|
||||
model.setJoinRole("communityId");
|
||||
|
||||
rightModel.reset();
|
||||
|
||||
QHash<int, QByteArray> roles{{0, "title" }, {1, "communityId"}, {2, "name"}};
|
||||
QCOMPARE(model.roleNames(), roles);
|
||||
QCOMPARE(model.rowCount(), 3);
|
||||
QCOMPARE(model.data(model.index(0, 0), 0), "Token 1");
|
||||
QCOMPARE(model.data(model.index(0, 0), 1), "community_1");
|
||||
QCOMPARE(model.data(model.index(0, 0), 2), {});
|
||||
|
||||
TestSourceModel newLeftModel({
|
||||
{ "title", { "Token 1", "Token 2", "Token 3"}},
|
||||
{ "communityId", { "community_1", "community_2", "community_1" }}
|
||||
});
|
||||
|
||||
TestSourceModel newRightModel({
|
||||
{ "name", { "Community 1", "Community 2" }},
|
||||
{ "communityId", { "community_1", "community_2" }}
|
||||
});
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Changing left model is not supported!");
|
||||
model.setLeftModel(&newLeftModel);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Changing right model is not supported!");
|
||||
model.setRightModel(&newRightModel);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(TestLeftJoinModel)
|
||||
#include "tst_LeftJoinModel.moc"
|
Loading…
Reference in New Issue