refactored common test-model functions to base class

This commit is contained in:
mandlm 2018-05-24 20:35:16 +02:00
parent 3ad5d3bd57
commit 8f170eb83b
14 changed files with 353 additions and 480 deletions

View File

@ -36,6 +36,8 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
CheckableItem CheckableItem
CheckableTest
CheckableTestModel
MetaData MetaData
VerbEnd VerbEnd
Genus Genus
@ -43,6 +45,8 @@ target_link_libraries(${PROJECT_NAME}
) )
add_subdirectory(CheckableItem) add_subdirectory(CheckableItem)
add_subdirectory(CheckableTest)
add_subdirectory(CheckableTestModel)
add_subdirectory(MetaData) add_subdirectory(MetaData)
add_subdirectory(VerbEnd) add_subdirectory(VerbEnd)

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.6)
project(CheckableTest LANGUAGES CXX)
find_package(Qt5Core REQUIRED)
add_library(${PROJECT_NAME}
CheckableTest.cpp
)
set_target_properties(${PROJECT_NAME}
PROPERTIES CXX_STANDARD 14
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
CheckableItem
Qt5::Core
)

View File

@ -0,0 +1,28 @@
#include "CheckableTest.h"
CheckableTest::CheckableTest(
const char *name, std::initializer_list<std::string> items)
: m_name(name)
, m_items(items)
{
}
size_t CheckableTest::size() const
{
return m_items.size();
}
const QString &CheckableTest::name() const
{
return m_name;
}
const CheckableItems &CheckableTest::items() const
{
return m_items;
}
CheckableItems &CheckableTest::items()
{
return m_items;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "CheckableItems.h"
#include <QString>
class CheckableTest
{
private:
CheckableItems m_items;
QString m_name;
public:
CheckableTest(const char *name, std::initializer_list<std::string> items);
size_t size() const;
const QString &name() const;
const CheckableItems &items() const;
CheckableItems &items();
};
using CheckableTests = std::vector<CheckableTest>;

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.6)
project(CheckableTestModel LANGUAGES CXX)
find_package(Qt5Core REQUIRED)
add_library(${PROJECT_NAME}
CheckableTestModel.cpp
)
set_target_properties(${PROJECT_NAME}
PROPERTIES CXX_STANDARD 14
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
CheckableItem
CheckableTest
Qt5::Core
)

View File

@ -0,0 +1,179 @@
#include "CheckableTestModel.h"
#include <QJsonArray>
#include <QDebug>
CheckableTestModel::CheckableTestModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
int CheckableTestModel::rowCount(const QModelIndex &parent) const
{
return m_tests.size();
}
int CheckableTestModel::columnCount(const QModelIndex &parent) const
{
int columnCount = 0;
for (const auto &test : m_tests)
{
columnCount = std::max<int>(columnCount, test.size());
}
return columnCount;
}
QVariant CheckableTestModel::data(const QModelIndex &index, int role) const
{
if (!isValidIndex(index))
{
return {};
}
try
{
auto &item = getItem(index);
if (role == Qt::DisplayRole)
{
return item.getText().c_str();
}
if (role == Qt::CheckStateRole)
{
return item.isChecked() ? Qt::Checked : Qt::Unchecked;
}
}
catch (std::runtime_error &e)
{
qDebug() << "CheckableTestModel::data" << index << e.what();
}
return {};
}
Qt::ItemFlags CheckableTestModel::flags(const QModelIndex &index) const
{
if (isValidIndex(index))
{
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
return Qt::NoItemFlags;
}
bool CheckableTestModel::setData(
const QModelIndex &index, const QVariant &value, int role)
{
if (!isValidIndex(index))
{
return false;
}
try
{
if (role == Qt::CheckStateRole)
{
auto &item = getItem(index);
item.setState(value.toBool());
return true;
}
}
catch (std::runtime_error &e)
{
qDebug() << "CheckableTestModel::setData" << index << e.what();
}
return false;
}
QVariant CheckableTestModel::headerData(
int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Vertical)
{
if (section < m_tests.size())
{
return m_tests.at(section).name();
}
}
return {};
}
void CheckableTestModel::write(QJsonObject &json) const
{
for (const auto &test : m_tests)
{
QJsonArray testData;
test.items().write(testData);
json[test.name()] = testData;
}
}
void CheckableTestModel::read(const QJsonObject &json)
{
for (auto &test : m_tests)
{
auto testData = json[test.name()];
if (testData.isArray())
{
test.items().read(testData.toArray());
}
}
}
bool CheckableTestModel::isValidIndex(const QModelIndex &index) const
{
if (index.row() < m_tests.size())
{
return index.column() < m_tests.at(index.row()).size();
}
return false;
}
CheckableItems &CheckableTestModel::getItems(const QModelIndex &index)
{
if (index.row() < m_tests.size())
{
return m_tests.at(index.row()).items();
}
throw std::runtime_error("invalid index");
}
const CheckableItems &CheckableTestModel::getItems(
const QModelIndex &index) const
{
if (index.row() < m_tests.size())
{
return m_tests.at(index.row()).items();
}
throw std::runtime_error("invalid index");
}
CheckableItem &CheckableTestModel::getItem(const QModelIndex &index)
{
auto &items = getItems(index);
if (index.column() < items.size())
{
return items.at(index.column());
}
throw std::runtime_error("invalid index");
}
const CheckableItem &CheckableTestModel::getItem(const QModelIndex &index) const
{
auto &items = getItems(index);
if (index.column() < items.size())
{
return items.at(index.column());
}
throw std::runtime_error("invalid index");
}

View File

@ -0,0 +1,40 @@
#pragma once
#include "CheckableTest.h"
#include <QAbstractTableModel>
class CheckableTestModel : public QAbstractTableModel
{
Q_OBJECT
protected:
CheckableTests m_tests;
public:
CheckableTestModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(
const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
void write(QJsonObject &json) const;
void read(const QJsonObject &json);
private:
bool isValidIndex(const QModelIndex &index) const;
CheckableItems &getItems(const QModelIndex &index);
const CheckableItems &getItems(const QModelIndex &index) const;
CheckableItem &getItem(const QModelIndex &index);
const CheckableItem &getItem(const QModelIndex &index) const;
};

View File

@ -28,5 +28,7 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
CheckableItem CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
) )

View File

@ -1,208 +1,11 @@
#include "GenusModel.h" #include "GenusModel.h"
#include <QJsonArray>
#include <QDebug>
GenusModel::GenusModel(QObject *parent) GenusModel::GenusModel(QObject *parent)
: QAbstractTableModel(parent) : CheckableTestModel(parent)
{ {
} m_tests = { { "Tiere", { "Tiger", "Bär", "Katze", "Pferd", "Gans",
"Elefant", "Katze", "Hund" } },
int GenusModel::rowCount(const QModelIndex &parent) const { "Futter", { "Salat", "Fleisch", "Knocken", "Banane", "Apfel", "Möhre",
{ "Honig", "Zucker" } },
return 3; { "Zirkus", { "Kiste", "Holz", "Vorhang", "Baum" } } };
}
int GenusModel::columnCount(const QModelIndex &parent) const
{
return 8;
}
QVariant GenusModel::data(const QModelIndex &index, int role) const
{
if (!isValidIndex(index))
{
return {};
}
try
{
auto &item = getItem(index);
if (role == Qt::DisplayRole)
{
return item.getText().c_str();
}
if (role == Qt::CheckStateRole)
{
return item.isChecked() ? Qt::Checked : Qt::Unchecked;
}
}
catch (std::runtime_error &e)
{
qDebug() << "GenusModel::data" << index << e.what();
}
return {};
}
Qt::ItemFlags GenusModel::flags(const QModelIndex &index) const
{
if (isValidIndex(index))
{
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
return Qt::NoItemFlags;
}
bool GenusModel::setData(
const QModelIndex &index, const QVariant &value, int role)
{
if (!isValidIndex(index))
{
return false;
}
try
{
if (role == Qt::CheckStateRole)
{
auto &item = getItem(index);
item.setState(value.toBool());
return true;
}
}
catch (std::runtime_error &e)
{
qDebug() << "GenusModel::setData" << index << e.what();
}
return false;
}
QVariant GenusModel::headerData(
int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Vertical)
{
switch (section)
{
case 0:
return "Tiere";
case 1:
return "Futter";
case 2:
return "Zirkus";
default:
return {};
}
}
return {};
}
void GenusModel::write(QJsonObject &json) const
{
QJsonArray tiere;
m_tiere.write(tiere);
json["Tiere"] = tiere;
QJsonArray futter;
m_futter.write(futter);
json["Futter"] = futter;
QJsonArray zirkus;
m_zirkus.write(zirkus);
json["Zirkus"] = zirkus;
}
void GenusModel::read(const QJsonObject &json)
{
if (json["Tiere"].isArray())
{
m_tiere.read(json["Tiere"].toArray());
}
if (json["Futter"].isArray())
{
m_futter.read(json["Futter"].toArray());
}
if (json["Zirkus"].isArray())
{
m_zirkus.read(json["Zirkus"].toArray());
}
}
bool GenusModel::isValidIndex(const QModelIndex &index) const
{
switch (index.row())
{
case 0:
return index.column() < m_tiere.size();
case 1:
return index.column() < m_futter.size();
case 2:
return index.column() < m_zirkus.size();
default:
return false;
}
}
CheckableItems &GenusModel::getItems(const QModelIndex &index)
{
switch (index.row())
{
case 0:
return m_tiere;
case 1:
return m_futter;
case 2:
return m_zirkus;
default:
break;
}
throw std::runtime_error("invalid index");
}
const CheckableItems &GenusModel::getItems(const QModelIndex &index) const
{
switch (index.row())
{
case 0:
return m_tiere;
case 1:
return m_futter;
case 2:
return m_zirkus;
default:
break;
}
throw std::runtime_error("invalid index");
}
CheckableItem &GenusModel::getItem(const QModelIndex &index)
{
auto &items = getItems(index);
if (index.column() < items.size())
{
return items.at(index.column());
}
throw std::runtime_error("invalid index");
}
const CheckableItem &GenusModel::getItem(const QModelIndex &index) const
{
auto &items = getItems(index);
if (index.column() < items.size())
{
return items.at(index.column());
}
throw std::runtime_error("invalid index");
} }

View File

@ -1,43 +1,11 @@
#pragma once #pragma once
#include "CheckableItem.h" #include "CheckableTestModel.h"
#include "CheckableItems.h"
#include <QAbstractTableModel> class GenusModel : public CheckableTestModel
class GenusModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
private:
CheckableItems m_tiere = { "Tiger", "Bär", "Katze", "Pferd", "Gans",
"Elefant", "Katze", "Hund" };
CheckableItems m_futter = { "Salat", "Fleisch", "Knocken", "Banane",
"Apfel", "Möhre", "Honig", "Zucker" };
CheckableItems m_zirkus = { "Kiste", "Holz", "Vorhang", "Baum" };
public: public:
GenusModel(QObject *parent); GenusModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(
const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
void write(QJsonObject &json) const;
void read(const QJsonObject &json);
private:
bool isValidIndex(const QModelIndex &index) const;
CheckableItems &getItems(const QModelIndex &index);
const CheckableItems &getItems(const QModelIndex &index) const;
CheckableItem &getItem(const QModelIndex &index);
const CheckableItem &getItem(const QModelIndex &index) const;
}; };

View File

@ -28,5 +28,7 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
CheckableItem CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
) )

View File

@ -1,208 +1,13 @@
#include "VerbEndModel.h" #include "VerbEndModel.h"
#include <QJsonArray>
#include <QDebug>
VerbEndModel::VerbEndModel(QObject *parent) VerbEndModel::VerbEndModel(QObject *parent)
: QAbstractTableModel(parent) : CheckableTestModel(parent)
{ {
} m_tests = { { "Telefonat",
{ "Kausal (1)", "Kausal (2)", "Relativ", "Kausal (3)",
int VerbEndModel::rowCount(const QModelIndex &parent) const "Final", "Temporal (1)", "Temporal (2)" } },
{ { "Zaubertrick", { "Relativ", "Final (1)", "Kausal (1)", "Final (2)",
return 3; "Temporal (1)", "Kausal (2)", "Temporal (2)" } },
} { "Zauberregel", { "Temporal (1)", "Kausal", "Final", "Relativ (1)",
"Temporal (2)", "Relativ (2)" } } };
int VerbEndModel::columnCount(const QModelIndex &parent) const
{
return 7;
}
QVariant VerbEndModel::data(const QModelIndex &index, int role) const
{
if (!isValidIndex(index))
{
return {};
}
try
{
auto &item = getItem(index);
if (role == Qt::DisplayRole)
{
return item.getText().c_str();
}
if (role == Qt::CheckStateRole)
{
return item.isChecked() ? Qt::Checked : Qt::Unchecked;
}
}
catch (std::runtime_error &e)
{
qDebug() << "VerbEndModel::data" << index << e.what();
}
return {};
}
Qt::ItemFlags VerbEndModel::flags(const QModelIndex &index) const
{
if (isValidIndex(index))
{
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
return Qt::NoItemFlags;
}
bool VerbEndModel::setData(
const QModelIndex &index, const QVariant &value, int role)
{
if (!isValidIndex(index))
{
return false;
}
try
{
if (role == Qt::CheckStateRole)
{
auto &item = getItem(index);
item.setState(value.toBool());
return true;
}
}
catch (std::runtime_error &e)
{
qDebug() << "VerbEndModel::setData" << index << e.what();
}
return false;
}
QVariant VerbEndModel::headerData(
int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Vertical)
{
switch (section)
{
case 0:
return "Telefonat";
case 1:
return "Zaubertrick";
case 2:
return "Zauberregel";
default:
return {};
}
}
return {};
}
void VerbEndModel::write(QJsonObject &json) const
{
QJsonArray telefonat;
m_telefonat.write(telefonat);
json["Telefonat"] = telefonat;
QJsonArray zaubertrick;
m_zaubertrick.write(zaubertrick);
json["Zaubertrick"] = zaubertrick;
QJsonArray zauberregel;
m_zauberregel.write(zauberregel);
json["Zauberregel"] = zauberregel;
}
void VerbEndModel::read(const QJsonObject &json)
{
if (json["Telefonat"].isArray())
{
m_telefonat.read(json["Telefonat"].toArray());
}
if (json["Zaubertrick"].isArray())
{
m_zaubertrick.read(json["Zaubertrick"].toArray());
}
if (json["Zauberregel"].isArray())
{
m_zauberregel.read(json["Zauberregel"].toArray());
}
}
bool VerbEndModel::isValidIndex(const QModelIndex &index) const
{
switch (index.row())
{
case 0:
return index.column() < m_telefonat.size();
case 1:
return index.column() < m_zaubertrick.size();
case 2:
return index.column() < m_zauberregel.size();
default:
return false;
}
}
CheckableItems &VerbEndModel::getItems(const QModelIndex &index)
{
switch (index.row())
{
case 0:
return m_telefonat;
case 1:
return m_zaubertrick;
case 2:
return m_zauberregel;
default:
break;
}
throw std::runtime_error("invalid index");
}
const CheckableItems &VerbEndModel::getItems(const QModelIndex &index) const
{
switch (index.row())
{
case 0:
return m_telefonat;
case 1:
return m_zaubertrick;
case 2:
return m_zauberregel;
default:
break;
}
throw std::runtime_error("invalid index");
}
CheckableItem &VerbEndModel::getItem(const QModelIndex &index)
{
auto &items = getItems(index);
if (index.column() < items.size())
{
return items.at(index.column());
}
throw std::runtime_error("invalid index");
}
const CheckableItem &VerbEndModel::getItem(const QModelIndex &index) const
{
auto &items = getItems(index);
if (index.column() < items.size())
{
return items.at(index.column());
}
throw std::runtime_error("invalid index");
} }

View File

@ -1,44 +1,11 @@
#pragma once #pragma once
#include "CheckableItem.h" #include "CheckableTestModel.h"
#include "CheckableItems.h"
#include <QAbstractTableModel> class VerbEndModel : public CheckableTestModel
class VerbEndModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
private:
CheckableItems m_telefonat = { "Kausal (1)", "Kausal (2)", "Relativ",
"Kausal (3)", "Final", "Temporal (1)", "Temporal (2)" };
CheckableItems m_zaubertrick = { "Relativ", "Final (1)", "Kausal (1)",
"Final (2)", "Temporal (1)", "Kausal (2)", "Temporal (2)" };
CheckableItems m_zauberregel = { "Temporal (1)", "Kausal", "Final",
"Relativ (1)", "Temporal (2)", "Relativ (2)" };
public: public:
VerbEndModel(QObject *parent); VerbEndModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(
const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
void write(QJsonObject &json) const;
void read(const QJsonObject &json);
private:
bool isValidIndex(const QModelIndex &index) const;
CheckableItems &getItems(const QModelIndex &index);
const CheckableItems &getItems(const QModelIndex &index) const;
CheckableItem &getItem(const QModelIndex &index);
const CheckableItem &getItem(const QModelIndex &index) const;
}; };

View File

@ -18,7 +18,7 @@
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>2</number>
</property> </property>
<widget class="QWidget" name="MetaDataTab"> <widget class="QWidget" name="MetaDataTab">
<attribute name="title"> <attribute name="title">
@ -60,7 +60,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>905</width> <width>905</width>
<height>17</height> <height>19</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -101,6 +101,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Save as...</string> <string>Save as...</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action> </action>
<action name="actionOpen"> <action name="actionOpen">
<property name="icon"> <property name="icon">