StatusQ: Add generic proxy model for roles renaming
This commit is contained in:
parent
a3239d9e2b
commit
628d9cdd31
|
@ -0,0 +1,156 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
RolesRenamingModel {
|
||||||
|
id: renamedModel
|
||||||
|
|
||||||
|
sourceModel: sourceModel
|
||||||
|
|
||||||
|
mapping: [
|
||||||
|
RoleRename {
|
||||||
|
from: "tokenId"
|
||||||
|
to: "id"
|
||||||
|
},
|
||||||
|
RoleRename {
|
||||||
|
from: "title"
|
||||||
|
to: "name"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: sourceModel
|
||||||
|
|
||||||
|
ListElement {
|
||||||
|
tokenId: "1"
|
||||||
|
title: "Token 1"
|
||||||
|
communityId: "1"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
tokenId: "2"
|
||||||
|
title: "Token 2"
|
||||||
|
communityId: "1"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
tokenId: "3"
|
||||||
|
title: "Token 3"
|
||||||
|
communityId: "2"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
tokenId: "4"
|
||||||
|
title: "Token 4"
|
||||||
|
communityId: "3"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
tokenId: "5"
|
||||||
|
title: "Token 5"
|
||||||
|
communityId: ""
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
tokenId: "6"
|
||||||
|
title: "Token 6"
|
||||||
|
communityId: "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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: sourceModel
|
||||||
|
|
||||||
|
header: Label {
|
||||||
|
height: implicitHeight * 2
|
||||||
|
text: `Left model (${sourceModel.count})`
|
||||||
|
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {}
|
||||||
|
|
||||||
|
delegate: Label {
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
text: `token id: ${model.tokenId}, ${model.title}, community id: ${model.communityId || "-"}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
border.color: "gray"
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: renamedListView
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
model: renamedModel
|
||||||
|
|
||||||
|
header: Label {
|
||||||
|
height: implicitHeight * 2
|
||||||
|
text: `Renamed model (${renamedListView.count})`
|
||||||
|
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {}
|
||||||
|
|
||||||
|
delegate: Label {
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
text: `id: ${model.id}, ${model.name}, community id: ${model.communityId || "-"}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "shuffle"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
const count = sourceModel.count
|
||||||
|
const iterations = count / 2
|
||||||
|
|
||||||
|
for (let i = 0; i < iterations; i++) {
|
||||||
|
sourceModel.move(Math.floor(Math.random() * (count - 1)),
|
||||||
|
Math.floor(Math.random() * (count - 1)),
|
||||||
|
Math.floor(Math.random() * 2) + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// category: Models
|
|
@ -13,8 +13,8 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
# Although SHARED libraries set this to ON by default,
|
# Although SHARED libraries set this to ON by default,
|
||||||
# all static libraries, that are built into this SHARED,
|
# all static libraries, that are built into this SHARED,
|
||||||
# (which is qzxing in our case) should also be build with -fPIC.
|
# (which is qzxing in our case) should also be build with -fPIC.
|
||||||
# This fixes it.
|
# This fixes it.
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ add_library(StatusQ SHARED
|
||||||
include/StatusQ/QClipboardProxy.h
|
include/StatusQ/QClipboardProxy.h
|
||||||
include/StatusQ/modelutilsinternal.h
|
include/StatusQ/modelutilsinternal.h
|
||||||
include/StatusQ/permissionutilsinternal.h
|
include/StatusQ/permissionutilsinternal.h
|
||||||
|
include/StatusQ/rolesrenamingmodel.h
|
||||||
include/StatusQ/rxvalidator.h
|
include/StatusQ/rxvalidator.h
|
||||||
include/StatusQ/statussyntaxhighlighter.h
|
include/StatusQ/statussyntaxhighlighter.h
|
||||||
include/StatusQ/statuswindow.h
|
include/StatusQ/statuswindow.h
|
||||||
|
@ -99,13 +100,14 @@ add_library(StatusQ SHARED
|
||||||
src/modelutilsinternal.cpp
|
src/modelutilsinternal.cpp
|
||||||
src/permissionutilsinternal.cpp
|
src/permissionutilsinternal.cpp
|
||||||
src/plugin.cpp
|
src/plugin.cpp
|
||||||
|
src/rolesrenamingmodel.cpp
|
||||||
src/rxvalidator.cpp
|
src/rxvalidator.cpp
|
||||||
src/statussyntaxhighlighter.cpp
|
src/statussyntaxhighlighter.cpp
|
||||||
src/statuswindow.cpp
|
src/statuswindow.cpp
|
||||||
src/stringutilsinternal.cpp
|
src/stringutilsinternal.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(StatusQ PROPERTIES
|
set_target_properties(StatusQ PROPERTIES
|
||||||
ADDITIONAL_CLEAN_FILES bin/StatusQ/qmldir
|
ADDITIONAL_CLEAN_FILES bin/StatusQ/qmldir
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${STATUSQ_MODULE_PATH}
|
RUNTIME_OUTPUT_DIRECTORY ${STATUSQ_MODULE_PATH}
|
||||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${STATUSQ_MODULE_PATH}
|
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${STATUSQ_MODULE_PATH}
|
||||||
|
@ -144,7 +146,7 @@ target_link_libraries(StatusQ PRIVATE
|
||||||
qzxing
|
qzxing
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(StatusQ PRIVATE include)
|
target_include_directories(StatusQ PUBLIC include)
|
||||||
|
|
||||||
install(TARGETS StatusQ
|
install(TARGETS StatusQ
|
||||||
RUNTIME DESTINATION StatusQ
|
RUNTIME DESTINATION StatusQ
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QIdentityProxyModel>
|
||||||
|
#include <QQmlListProperty>
|
||||||
|
|
||||||
|
class RoleRename : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString from READ from WRITE setFrom NOTIFY fromChanged)
|
||||||
|
Q_PROPERTY(QString to READ to WRITE setTo NOTIFY toChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RoleRename(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
void setFrom(const QString& from);
|
||||||
|
const QString& from() const;
|
||||||
|
|
||||||
|
void setTo(const QString& to);
|
||||||
|
const QString& to() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fromChanged();
|
||||||
|
void toChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_from;
|
||||||
|
QString m_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RolesRenamingModel : public QIdentityProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QQmlListProperty<RoleRename> mapping READ mapping CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RolesRenamingModel(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> mapping();
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable bool m_rolesFetched = false;
|
||||||
|
QList<RoleRename*> m_mapping;
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
#include "StatusQ/QClipboardProxy.h"
|
#include "StatusQ/QClipboardProxy.h"
|
||||||
#include "StatusQ/modelutilsinternal.h"
|
#include "StatusQ/modelutilsinternal.h"
|
||||||
#include "StatusQ/permissionutilsinternal.h"
|
#include "StatusQ/permissionutilsinternal.h"
|
||||||
|
#include "StatusQ/rolesrenamingmodel.h"
|
||||||
#include "StatusQ/rxvalidator.h"
|
#include "StatusQ/rxvalidator.h"
|
||||||
#include "StatusQ/statussyntaxhighlighter.h"
|
#include "StatusQ/statussyntaxhighlighter.h"
|
||||||
#include "StatusQ/statuswindow.h"
|
#include "StatusQ/statuswindow.h"
|
||||||
|
@ -24,6 +25,9 @@ public:
|
||||||
qmlRegisterType<StatusSyntaxHighlighter>("StatusQ", 0, 1, "StatusSyntaxHighlighter");
|
qmlRegisterType<StatusSyntaxHighlighter>("StatusQ", 0, 1, "StatusSyntaxHighlighter");
|
||||||
qmlRegisterType<RXValidator>("StatusQ", 0, 1, "RXValidator");
|
qmlRegisterType<RXValidator>("StatusQ", 0, 1, "RXValidator");
|
||||||
|
|
||||||
|
qmlRegisterType<RolesRenamingModel>("StatusQ", 0, 1, "RolesRenamingModel");
|
||||||
|
qmlRegisterType<RoleRename>("StatusQ", 0, 1, "RoleRename");
|
||||||
|
|
||||||
qmlRegisterSingletonType<QClipboardProxy>("StatusQ", 0, 1, "QClipboardProxy", &QClipboardProxy::qmlInstance);
|
qmlRegisterSingletonType<QClipboardProxy>("StatusQ", 0, 1, "QClipboardProxy", &QClipboardProxy::qmlInstance);
|
||||||
|
|
||||||
qmlRegisterSingletonType<ModelUtilsInternal>(
|
qmlRegisterSingletonType<ModelUtilsInternal>(
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
#include "StatusQ/rolesrenamingmodel.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
RoleRename::RoleRename(QObject* parent)
|
||||||
|
: QObject{parent}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoleRename::setFrom(const QString& from)
|
||||||
|
{
|
||||||
|
if (m_from == from)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_from.isEmpty()) {
|
||||||
|
qWarning() << "RoleRename: property \"from\" is inteded to be initialized once and not changed!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_from = from;
|
||||||
|
emit fromChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& RoleRename::from() const
|
||||||
|
{
|
||||||
|
return m_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoleRename::setTo(const QString& to)
|
||||||
|
{
|
||||||
|
if (m_to == to)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_to.isEmpty()) {
|
||||||
|
qWarning() << "RoleRename: property \"to\" is inteded to be initialized once and not changed!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_to = to;
|
||||||
|
emit toChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& RoleRename::to() const
|
||||||
|
{
|
||||||
|
return m_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
RolesRenamingModel::RolesRenamingModel(QObject* parent)
|
||||||
|
: QIdentityProxyModel{parent}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> RolesRenamingModel::mapping()
|
||||||
|
{
|
||||||
|
QQmlListProperty<RoleRename> list(this, &m_mapping);
|
||||||
|
|
||||||
|
list.replace = nullptr;
|
||||||
|
list.clear = nullptr;
|
||||||
|
list.removeLast = nullptr;
|
||||||
|
|
||||||
|
list.append = [](auto listProperty, auto element) {
|
||||||
|
RolesRenamingModel* model = qobject_cast<RolesRenamingModel*>(
|
||||||
|
listProperty->object);
|
||||||
|
|
||||||
|
if (model->m_rolesFetched) {
|
||||||
|
qWarning() << "RolesRenamingModel: role names mapping cannot be modified after fetching role names!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
model->m_mapping.append(element);
|
||||||
|
};
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> RolesRenamingModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles = sourceModel()
|
||||||
|
? sourceModel()->roleNames()
|
||||||
|
: QHash<int, QByteArray>{};
|
||||||
|
|
||||||
|
if (roles.empty())
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
QHash<QString, RoleRename*> renameMap;
|
||||||
|
|
||||||
|
for (const auto rename : m_mapping)
|
||||||
|
renameMap.insert(rename->from(), rename);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> remapped;
|
||||||
|
remapped.reserve(roles.size());
|
||||||
|
|
||||||
|
QSet<QByteArray> roleNamesSet;
|
||||||
|
roleNamesSet.reserve(roles.size());
|
||||||
|
|
||||||
|
for (auto i = roles.cbegin(), end = roles.cend(); i != end; ++i) {
|
||||||
|
RoleRename* rename = renameMap.take(i.value());
|
||||||
|
QByteArray roleName = rename ? rename->to().toUtf8() : i.value();
|
||||||
|
|
||||||
|
remapped.insert(i.key(), roleName);
|
||||||
|
roleNamesSet.insert(roleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roles.size() != roleNamesSet.size()) {
|
||||||
|
qWarning() << "RolesRenamingModel: model cannot contain duplicated role names!";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renameMap.size()) {
|
||||||
|
qWarning().nospace()
|
||||||
|
<< "RolesRenamingModel: specified source roles not found: "
|
||||||
|
<< renameMap.keys() << "!";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rolesFetched = true;
|
||||||
|
return remapped;
|
||||||
|
}
|
|
@ -16,7 +16,9 @@ add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} main.cpp)
|
add_executable(${PROJECT_NAME} main.cpp)
|
||||||
|
|
||||||
add_test(NAME ${PROJECT_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} -input "${CMAKE_CURRENT_SOURCE_DIR}")
|
add_test(NAME ${PROJECT_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} -input "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
add_custom_target("Run_${PROJECT_NAME}" COMMAND ${CMAKE_CTEST_COMMAND} --test-dir "${CMAKE_CURRENT_BINARY_DIR}")
|
add_custom_target("Run_${PROJECT_NAME}" COMMAND ${CMAKE_CTEST_COMMAND} --test-dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
add_dependencies("Run_${PROJECT_NAME}" ${PROJECT_NAME})
|
add_dependencies("Run_${PROJECT_NAME}" ${PROJECT_NAME})
|
||||||
|
|
||||||
|
@ -38,3 +40,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
STATUSQ_MODULE_PATH="${STATUSQ_MODULE_PATH}"
|
STATUSQ_MODULE_PATH="${STATUSQ_MODULE_PATH}"
|
||||||
STATUSQ_MODULE_IMPORT_PATH="${STATUSQ_MODULE_IMPORT_PATH}"
|
STATUSQ_MODULE_IMPORT_PATH="${STATUSQ_MODULE_IMPORT_PATH}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(RolesRenamingModelTest tst_RolesRenamingModel.cpp)
|
||||||
|
target_link_libraries(RolesRenamingModelTest PRIVATE Qt5::Qml Qt5::Test StatusQ)
|
||||||
|
add_test(RolesRenamingModelTest COMMAND RolesRenamingModelTest)
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <StatusQ/rolesrenamingmodel.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class TestSourceModel : public QAbstractListModel {
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TestSourceModel(QList<QString> roles)
|
||||||
|
: m_roles(std::move(roles))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& index, int role) const override
|
||||||
|
{
|
||||||
|
if(!index.isValid() || index.row() >= capacity)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& parent) const override
|
||||||
|
{
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const override
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.remove(m_roles.size());
|
||||||
|
|
||||||
|
for (auto i = 0; i < m_roles.size(); i++)
|
||||||
|
roles.insert(i, m_roles.at(i).toUtf8());
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr auto capacity = 5;
|
||||||
|
QList<QString> m_roles;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestRolesRenamingModel: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initializationTest()
|
||||||
|
{
|
||||||
|
RolesRenamingModel model;
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> mapping = model.mapping();
|
||||||
|
|
||||||
|
RoleRename rename;
|
||||||
|
rename.setFrom("someIdFrom");
|
||||||
|
rename.setTo("someIdTo");
|
||||||
|
|
||||||
|
mapping.append(&mapping, &rename);
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "RolesRenamingModel: specified source roles not found: (\"someIdFrom\")!");
|
||||||
|
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void remappingTest()
|
||||||
|
{
|
||||||
|
TestSourceModel sourceModel({"id", "name", "color"});
|
||||||
|
RolesRenamingModel model;
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> mapping = model.mapping();
|
||||||
|
|
||||||
|
RoleRename rename_1;
|
||||||
|
rename_1.setFrom("id");
|
||||||
|
rename_1.setTo("tokenId");
|
||||||
|
mapping.append(&mapping, &rename_1);
|
||||||
|
|
||||||
|
RoleRename rename_2;
|
||||||
|
rename_2.setFrom("name");
|
||||||
|
rename_2.setTo("tokenName");
|
||||||
|
mapping.append(&mapping, &rename_2);
|
||||||
|
|
||||||
|
model.setSourceModel(&sourceModel);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> expectedRoles = {{0, "tokenId"}, {1, "tokenName"}, {2, "color"}};
|
||||||
|
QCOMPARE(model.roleNames(), expectedRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addMappingAfterFetchingRoleNamesTest()
|
||||||
|
{
|
||||||
|
TestSourceModel sourceModel({"id", "name", "color"});
|
||||||
|
RolesRenamingModel model;
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> mapping = model.mapping();
|
||||||
|
|
||||||
|
RoleRename rename_1;
|
||||||
|
rename_1.setFrom("id");
|
||||||
|
rename_1.setTo("tokenId");
|
||||||
|
mapping.append(&mapping, &rename_1);
|
||||||
|
|
||||||
|
model.setSourceModel(&sourceModel);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> expectedRoles = {{0, "tokenId"}, {1, "name"}, {2, "color"}};
|
||||||
|
QCOMPARE(model.roleNames(), expectedRoles);
|
||||||
|
|
||||||
|
RoleRename rename_2;
|
||||||
|
rename_2.setFrom("name");
|
||||||
|
rename_2.setTo("tokenName");
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "RolesRenamingModel: role names mapping cannot be modified after fetching role names!");
|
||||||
|
mapping.append(&mapping, &rename_2);
|
||||||
|
|
||||||
|
QCOMPARE(model.roleNames(), expectedRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
void duplicatedNamesTest()
|
||||||
|
{
|
||||||
|
TestSourceModel sourceModel({"id", "name", "color"});
|
||||||
|
RolesRenamingModel model;
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> mapping = model.mapping();
|
||||||
|
|
||||||
|
RoleRename rename_1;
|
||||||
|
rename_1.setFrom("id");
|
||||||
|
rename_1.setTo("name");
|
||||||
|
mapping.append(&mapping, &rename_1);
|
||||||
|
|
||||||
|
model.setSourceModel(&sourceModel);
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "RolesRenamingModel: model cannot contain duplicated role names!");
|
||||||
|
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void resettingFromToPropertiesTest()
|
||||||
|
{
|
||||||
|
RoleRename rename;
|
||||||
|
|
||||||
|
rename.setFrom("id");
|
||||||
|
QCOMPARE(rename.from(), "id");
|
||||||
|
QCOMPARE(rename.to(), "");
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"RoleRename: property \"from\" is inteded to be initialized once and not changed!");
|
||||||
|
rename.setFrom("id2");
|
||||||
|
QCOMPARE(rename.from(), "id");
|
||||||
|
QCOMPARE(rename.to(), "");
|
||||||
|
|
||||||
|
rename.setTo("myId");
|
||||||
|
QCOMPARE(rename.from(), "id");
|
||||||
|
QCOMPARE(rename.to(), "myId");
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "RoleRename: property \"to\" is inteded to be initialized once and not changed!");
|
||||||
|
rename.setTo("myId2");
|
||||||
|
QCOMPARE(rename.from(), "id");
|
||||||
|
QCOMPARE(rename.to(), "myId");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sourceModelDeletedTest()
|
||||||
|
{
|
||||||
|
auto sourceModel = std::make_unique<TestSourceModel>(
|
||||||
|
QList<QString>{"id", "name", "color"});
|
||||||
|
RolesRenamingModel model;
|
||||||
|
|
||||||
|
QQmlListProperty<RoleRename> mapping = model.mapping();
|
||||||
|
|
||||||
|
RoleRename rename_1;
|
||||||
|
rename_1.setFrom("id");
|
||||||
|
rename_1.setTo("tokenId");
|
||||||
|
mapping.append(&mapping, &rename_1);
|
||||||
|
|
||||||
|
RoleRename rename_2;
|
||||||
|
rename_2.setFrom("name");
|
||||||
|
rename_2.setTo("tokenName");
|
||||||
|
mapping.append(&mapping, &rename_2);
|
||||||
|
|
||||||
|
model.setSourceModel(sourceModel.get());
|
||||||
|
|
||||||
|
QHash<int, QByteArray> expectedRoles = {
|
||||||
|
{0, "tokenId"}, {1, "tokenName"}, {2, "color"}
|
||||||
|
};
|
||||||
|
QCOMPARE(model.roleNames(), expectedRoles);
|
||||||
|
QCOMPARE(model.rowCount(), 5);
|
||||||
|
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), 0), 42);
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), 1), 42);
|
||||||
|
QCOMPARE(model.data(model.index(5, 0), 0), {});
|
||||||
|
QCOMPARE(model.data(model.index(5, 0), 1), {});
|
||||||
|
|
||||||
|
QSignalSpy destroyedSpy(sourceModel.get(), &QObject::destroyed);
|
||||||
|
sourceModel.reset();
|
||||||
|
|
||||||
|
QCOMPARE(destroyedSpy.size(), 1);
|
||||||
|
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
|
||||||
|
QCOMPARE(model.roleNames(), {});
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), 0), {});
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), 1), {});
|
||||||
|
QCOMPARE(model.data(model.index(5, 0), 0), {});
|
||||||
|
QCOMPARE(model.data(model.index(5, 0), 1), {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(TestRolesRenamingModel)
|
||||||
|
#include "tst_RolesRenamingModel.moc"
|
Loading…
Reference in New Issue