Merge branch 'feature/print-with-qpainter' into develop
This commit is contained in:
commit
938e607366
@ -78,6 +78,7 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
CheckableItem
|
CheckableItem
|
||||||
CheckableTest
|
CheckableTest
|
||||||
CheckableTestModel
|
CheckableTestModel
|
||||||
|
PrintableModel
|
||||||
MetaData
|
MetaData
|
||||||
VerbEnd
|
VerbEnd
|
||||||
Plural
|
Plural
|
||||||
@ -95,6 +96,7 @@ add_subdirectory(Age)
|
|||||||
add_subdirectory(CheckableItem)
|
add_subdirectory(CheckableItem)
|
||||||
add_subdirectory(CheckableTest)
|
add_subdirectory(CheckableTest)
|
||||||
add_subdirectory(CheckableTestModel)
|
add_subdirectory(CheckableTestModel)
|
||||||
|
add_subdirectory(PrintableModel)
|
||||||
|
|
||||||
add_subdirectory(MetaData)
|
add_subdirectory(MetaData)
|
||||||
add_subdirectory(SubTests)
|
add_subdirectory(SubTests)
|
||||||
|
@ -34,24 +34,3 @@ unsigned int CheckableItem::points() const
|
|||||||
{
|
{
|
||||||
return m_checked ? m_value : 0;
|
return m_checked ? m_value : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableItem::write(QJsonObject &json) const
|
|
||||||
{
|
|
||||||
json["text"] = m_text.c_str();
|
|
||||||
json["checked"] = m_checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckableItem::read(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
const auto &text = json["text"];
|
|
||||||
if (text.isString())
|
|
||||||
{
|
|
||||||
m_text = text.toString().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &checked = json["checked"];
|
|
||||||
if (checked.isBool())
|
|
||||||
{
|
|
||||||
m_checked = checked.toBool();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -24,7 +24,4 @@ public:
|
|||||||
void setValue(unsigned int value);
|
void setValue(unsigned int value);
|
||||||
|
|
||||||
unsigned int points() const;
|
unsigned int points() const;
|
||||||
|
|
||||||
void write(QJsonObject &json) const;
|
|
||||||
void read(const QJsonObject &json);
|
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
CheckableItems::CheckableItems(std::initializer_list<std::string> itemNames)
|
CheckableItems::CheckableItems(std::initializer_list<std::string> itemNames)
|
||||||
{
|
{
|
||||||
for (const auto &itemName : itemNames)
|
for (const auto &itemName : itemNames)
|
||||||
@ -10,27 +12,9 @@ CheckableItems::CheckableItems(std::initializer_list<std::string> itemNames)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableItems::write(QJsonArray &json) const
|
unsigned int CheckableItems::getPoints() const
|
||||||
{
|
{
|
||||||
for (const auto &item : *this)
|
return std::accumulate(begin(), end(), 0, [](int base, const CheckableItem &item) {
|
||||||
{
|
return base + item.points();
|
||||||
QJsonObject itemObject;
|
});
|
||||||
item.write(itemObject);
|
|
||||||
json.append(itemObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckableItems::read(const QJsonArray &json)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
|
|
||||||
for (const auto &itemObject : json)
|
|
||||||
{
|
|
||||||
if (itemObject.isObject())
|
|
||||||
{
|
|
||||||
CheckableItem item;
|
|
||||||
item.read(itemObject.toObject());
|
|
||||||
emplace_back(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,5 @@ class CheckableItems : public std::vector<CheckableItem>
|
|||||||
public:
|
public:
|
||||||
CheckableItems(std::initializer_list<std::string> itemNames);
|
CheckableItems(std::initializer_list<std::string> itemNames);
|
||||||
|
|
||||||
void write(QJsonArray &json) const;
|
unsigned int getPoints() const;
|
||||||
void read(const QJsonArray &json);
|
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "CheckableTest.h"
|
#include "CheckableTest.h"
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
CheckableTest::CheckableTest(
|
CheckableTest::CheckableTest(
|
||||||
const char *name, std::initializer_list<std::string> items)
|
const char *name, std::initializer_list<std::string> items)
|
||||||
: m_name(name)
|
: m_name(name)
|
||||||
@ -26,3 +28,8 @@ CheckableItems &CheckableTest::items()
|
|||||||
{
|
{
|
||||||
return m_items;
|
return m_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int CheckableTest::getPoints() const
|
||||||
|
{
|
||||||
|
return m_items.getPoints();
|
||||||
|
}
|
||||||
|
@ -17,6 +17,8 @@ public:
|
|||||||
const QString &name() const;
|
const QString &name() const;
|
||||||
const CheckableItems &items() const;
|
const CheckableItems &items() const;
|
||||||
CheckableItems &items();
|
CheckableItems &items();
|
||||||
|
|
||||||
|
unsigned int getPoints() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CheckableTests = std::vector<CheckableTest>;
|
using CheckableTests = std::vector<CheckableTest>;
|
||||||
|
@ -18,8 +18,9 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PUBLIC
|
||||||
CheckableItem
|
CheckableItem
|
||||||
CheckableTest
|
CheckableTest
|
||||||
|
PRIVATE
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
)
|
)
|
||||||
|
@ -121,30 +121,6 @@ QVariant CheckableTestModel::headerData(int section, Qt::Orientation orientation
|
|||||||
return QAbstractTableModel::headerData(section, orientation, role);
|
return QAbstractTableModel::headerData(section, orientation, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckableTestModel::isValidIndex(const QModelIndex &index) const
|
bool CheckableTestModel::isValidIndex(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.row() < m_tests.size())
|
if (index.row() < m_tests.size())
|
||||||
@ -211,3 +187,8 @@ unsigned int CheckableTestModel::getPoints() const
|
|||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CheckableTestModel::getTitle() const
|
||||||
|
{
|
||||||
|
return m_title;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ class CheckableTestModel : public QAbstractTableModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QString m_title;
|
||||||
CheckableTests m_tests;
|
CheckableTests m_tests;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -16,20 +17,17 @@ public:
|
|||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QVariant data(
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value,
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
int role = Qt::EditRole) override;
|
|
||||||
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation,
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
int role = Qt::DisplayRole) const override;
|
int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
void write(QJsonObject &json) const;
|
|
||||||
void read(const QJsonObject &json);
|
|
||||||
|
|
||||||
unsigned int getPoints() const;
|
unsigned int getPoints() const;
|
||||||
|
|
||||||
|
QString getTitle() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool isValidIndex(const QModelIndex &index) const;
|
virtual bool isValidIndex(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
@ -100,27 +100,43 @@ void DataModel::read(const QString &filename)
|
|||||||
m_passiv.read(dataModel.lateskillspassiv());
|
m_passiv.read(dataModel.lateskillspassiv());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DataModel::toHtml() const
|
void DataModel::printTo(QPrinter &printer) const
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
QPainter painter;
|
||||||
|
painter.begin(&printer);
|
||||||
|
|
||||||
out << "<html>" << std::endl;
|
painter.setFont(PrintableModel::h1Font());
|
||||||
out << "<head>" << std::endl;
|
painter.drawText(0, painter.fontMetrics().lineSpacing(), "ESGRAF 4-8 Auswertungsbogen");
|
||||||
out << "<style>" << std::endl;
|
painter.translate(0, 3 * painter.fontMetrics().lineSpacing());
|
||||||
out << "body {" << std::endl;
|
|
||||||
out << "font-family:sans-serif;" << std::endl;
|
|
||||||
out << "}" << std::endl;
|
|
||||||
out << "</style>" << std::endl;
|
|
||||||
out << "</head>" << std::endl;
|
|
||||||
out << "<body>" << std::endl;
|
|
||||||
out << "<h2>ESGRAF 4-8 Auswertungsbogen</h2>" << std::endl;
|
|
||||||
out << "<p>" << std::endl;
|
|
||||||
out << m_metaData.toHtml();
|
|
||||||
out << "</p>" << std::endl;
|
|
||||||
out << "</body>" << std::endl;
|
|
||||||
out << "</html>" << std::endl;
|
|
||||||
|
|
||||||
return out.str();
|
m_metaData.printTo(painter);
|
||||||
|
|
||||||
|
m_wfModel.printTo(painter);
|
||||||
|
m_otModel.printTo(painter);
|
||||||
|
m_tPrModel.printTo(painter);
|
||||||
|
m_tPeModel.printTo(painter);
|
||||||
|
V2SvkModel::printSummary(painter,
|
||||||
|
m_wfModel.getV2Points() + m_otModel.getV2Points()
|
||||||
|
+ m_tPrModel.getV2Points() + m_tPeModel.getV2Points(),
|
||||||
|
m_wfModel.getSvkPoints() + m_otModel.getSvkPoints()
|
||||||
|
+ m_tPrModel.getSvkPoints() + m_tPeModel.getSvkPoints());
|
||||||
|
|
||||||
|
m_verbEnd.printTo(painter);
|
||||||
|
m_genus.printTo(painter);
|
||||||
|
|
||||||
|
printer.newPage();
|
||||||
|
painter.resetTransform();
|
||||||
|
|
||||||
|
m_akkusativ.printTo(painter);
|
||||||
|
m_dativ.printTo(painter);
|
||||||
|
m_plural.printTo(painter);
|
||||||
|
|
||||||
|
m_passiv.printTo(painter);
|
||||||
|
m_genitiv.printTo(painter);
|
||||||
|
|
||||||
|
m_results.printTo(painter);
|
||||||
|
|
||||||
|
painter.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataModel::pluralModelChanged()
|
void DataModel::pluralModelChanged()
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "PrintableModel.h"
|
||||||
|
|
||||||
#include "MetaData/MetaDataModel.h"
|
#include "MetaData/MetaDataModel.h"
|
||||||
#include "GenusModel.h"
|
#include "GenusModel.h"
|
||||||
#include "VerbEndModel.h"
|
#include "VerbEndModel.h"
|
||||||
@ -17,7 +19,7 @@
|
|||||||
|
|
||||||
#include "ResultModel.h"
|
#include "ResultModel.h"
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QPrinter>
|
||||||
|
|
||||||
class DataModel : public QObject
|
class DataModel : public QObject
|
||||||
{
|
{
|
||||||
@ -44,35 +46,14 @@ public:
|
|||||||
public:
|
public:
|
||||||
DataModel(QObject *parent);
|
DataModel(QObject *parent);
|
||||||
|
|
||||||
std::string toHtml() const;
|
|
||||||
|
|
||||||
void write(const QString &filename) const;
|
void write(const QString &filename) const;
|
||||||
void read(const QString &filename);
|
void read(const QString &filename);
|
||||||
|
|
||||||
|
void printTo(QPrinter &printer) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void modelChanged();
|
void modelChanged();
|
||||||
|
|
||||||
private:
|
|
||||||
template <class ModelType>
|
|
||||||
void write(
|
|
||||||
const ModelType &model, QJsonObject &target, const char *name) const
|
|
||||||
{
|
|
||||||
QJsonObject jsonObject;
|
|
||||||
model.write(jsonObject);
|
|
||||||
target[name] = jsonObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ModelType>
|
|
||||||
void read(
|
|
||||||
ModelType &model, const QJsonObject &source, const char *name) const
|
|
||||||
{
|
|
||||||
const auto &jsonObject = source[name];
|
|
||||||
if (jsonObject.isObject())
|
|
||||||
{
|
|
||||||
model.read(jsonObject.toObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void pluralModelChanged();
|
void pluralModelChanged();
|
||||||
void metaDataChanged();
|
void metaDataChanged();
|
||||||
|
@ -42,6 +42,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Age
|
Age
|
||||||
|
PrintableModel
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
MetaDataModel::MetaDataModel(QObject *parent)
|
MetaDataModel::MetaDataModel(QObject *parent)
|
||||||
: QAbstractTableModel(parent)
|
: PrintableModel(parent)
|
||||||
{
|
{
|
||||||
m_dateOfBirth = QDate::currentDate().addYears(-9);
|
m_dateOfBirth = QDate::currentDate().addYears(-9);
|
||||||
m_dateOfTest = QDate::currentDate();
|
m_dateOfTest = QDate::currentDate();
|
||||||
@ -130,41 +130,41 @@ void MetaDataModel::write(ESGRAF48::MetaDataModel &model) const
|
|||||||
model.set_remarks(m_remarks.toStdString());
|
model.set_remarks(m_remarks.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MetaDataModel::toHtml() const
|
void MetaDataModel::printTo(QPainter &painter) const
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
painter.setFont(tableFont());
|
||||||
|
|
||||||
out << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" frame=\"box\" rules=\"all\">"
|
auto width = painter.device()->width();
|
||||||
<< std::endl;
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
out << "<tr>" << std::endl;
|
|
||||||
out << "<td width=\"25%\">Name, Vorname</td>" << std::endl;
|
|
||||||
out << "<td width=\"25%\">" << m_participant.toHtmlEscaped().toStdString() << "</td>"
|
|
||||||
<< std::endl;
|
|
||||||
out << "<td width=\"25%\">Untersucher(in)</td>" << std::endl;
|
|
||||||
out << "<td width=\"25%\">" << m_instructor.toHtmlEscaped().toStdString() << "</td>"
|
|
||||||
<< std::endl;
|
|
||||||
out << "</tr>" << std::endl;
|
|
||||||
out << "<tr>" << std::endl;
|
|
||||||
out << "<td>Geburtsdatum</td>" << std::endl;
|
|
||||||
out << "<td>" << m_dateOfBirth.toString("dd.MM.yyyy").toHtmlEscaped().toStdString() << "</td>"
|
|
||||||
<< std::endl;
|
|
||||||
out << "<td colspan=\"2\">Bemerkungen</td>" << std::endl;
|
|
||||||
out << "</tr>" << std::endl;
|
|
||||||
out << "<tr>" << std::endl;
|
|
||||||
out << "<td>Untersuchungsdatum</td>" << std::endl;
|
|
||||||
out << "<td>" << m_dateOfTest.toString("dd.MM.yyyy").toHtmlEscaped().toStdString() << "</td>"
|
|
||||||
<< std::endl;
|
|
||||||
out << "<td colspan=\"2\" rowspan=\"2\">"
|
|
||||||
<< m_remarks.trimmed().toHtmlEscaped().replace("\n", "<br>").toStdString() << "</td>"
|
|
||||||
<< std::endl;
|
|
||||||
out << "</tr>" << std::endl;
|
|
||||||
out << "<tr>" << std::endl;
|
|
||||||
out << "<td>Alter am Testtag</td>" << std::endl;
|
|
||||||
out << "<td>" << getAge().toString() << "</td>" << std::endl;
|
|
||||||
out << "</tr>" << std::endl;
|
|
||||||
out << "</table>" << std::endl;
|
|
||||||
|
|
||||||
return out.str();
|
auto hasRemarks = !m_remarks.trimmed().isEmpty();
|
||||||
|
|
||||||
|
painter.drawText(0, 0, "Name, Vorname");
|
||||||
|
painter.drawText(0.25 * width, 0, m_participant);
|
||||||
|
painter.drawText(0.5 * width, 0, "Untersucher(in)");
|
||||||
|
painter.drawText(0.75 * width, 0, m_instructor);
|
||||||
|
|
||||||
|
painter.translate(0, height);
|
||||||
|
|
||||||
|
painter.drawText(0, 0, "Geburtsdatum");
|
||||||
|
painter.drawText(0.25 * width, 0, m_dateOfBirth.toString("dd.MM.yyyy"));
|
||||||
|
if (hasRemarks)
|
||||||
|
{
|
||||||
|
painter.drawText(0.5 * width, 0, "Bemerkungen:");
|
||||||
|
painter.drawText(QRect(0.5 * width, 0.5 * height, width, 2 * height), m_remarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.translate(0, height);
|
||||||
|
|
||||||
|
painter.drawText(0, 0, "Untersuchungsdatum");
|
||||||
|
painter.drawText(0.25 * width, 0, m_dateOfTest.toString("dd.MM.yyyy"));
|
||||||
|
|
||||||
|
painter.translate(0, height);
|
||||||
|
|
||||||
|
painter.drawText(0, 0, "Alter am Testtag");
|
||||||
|
painter.drawText(0.25 * width, 0, getAge().toString().c_str());
|
||||||
|
|
||||||
|
painter.translate(0, 2 * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Age MetaDataModel::getAge() const
|
Age MetaDataModel::getAge() const
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "PrintableModel.h"
|
||||||
|
|
||||||
#include "Age.h"
|
#include "Age.h"
|
||||||
|
|
||||||
#include "MetaDataModel.pb.h"
|
#include "MetaDataModel.pb.h"
|
||||||
@ -7,9 +9,8 @@
|
|||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDate>
|
#include <QDate>
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
class MetaDataModel : public QAbstractTableModel
|
class MetaDataModel : public PrintableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ public:
|
|||||||
void read(const ESGRAF48::MetaDataModel &model);
|
void read(const ESGRAF48::MetaDataModel &model);
|
||||||
void write(ESGRAF48::MetaDataModel &model) const;
|
void write(ESGRAF48::MetaDataModel &model) const;
|
||||||
|
|
||||||
std::string toHtml() const;
|
void printTo(QPainter &painter) const override;
|
||||||
|
|
||||||
Age getAge() const;
|
Age getAge() const;
|
||||||
};
|
};
|
||||||
|
27
source/PrintableModel/CMakeLists.txt
Normal file
27
source/PrintableModel/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.6)
|
||||||
|
|
||||||
|
project(PrintableModel LANGUAGES CXX)
|
||||||
|
|
||||||
|
find_package(Qt5Core REQUIRED)
|
||||||
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME}
|
||||||
|
PrintableModel.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}
|
||||||
|
PUBLIC
|
||||||
|
CheckableTestModel
|
||||||
|
PRIVATE
|
||||||
|
Qt5::Core
|
||||||
|
Qt5::Widgets
|
||||||
|
)
|
184
source/PrintableModel/PrintableModel.cpp
Normal file
184
source/PrintableModel/PrintableModel.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#include "PrintableModel.h"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
PrintableModel::PrintableModel(QObject *parent)
|
||||||
|
: CheckableTestModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::printTo(QPainter &painter) const
|
||||||
|
{
|
||||||
|
printHeader(painter);
|
||||||
|
printTests(painter);
|
||||||
|
printSummary(painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont PrintableModel::h1Font()
|
||||||
|
{
|
||||||
|
return QFont("Helvetica", 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont PrintableModel::h2Font()
|
||||||
|
{
|
||||||
|
return QFont("Helvetica", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont PrintableModel::tableFont()
|
||||||
|
{
|
||||||
|
return QFont("Helvetica", 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen PrintableModel::tablePen()
|
||||||
|
{
|
||||||
|
return QPen(Qt::black, 1, Qt::SolidLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen PrintableModel::resultPen()
|
||||||
|
{
|
||||||
|
return QPen(Qt::black, 2, Qt::SolidLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
double PrintableModel::headerWidthFactor()
|
||||||
|
{
|
||||||
|
return 0.17;
|
||||||
|
}
|
||||||
|
|
||||||
|
double PrintableModel::cellWidthFactor()
|
||||||
|
{
|
||||||
|
return headerWidthFactor() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::drawTextSquare(QPainter &painter, const QRectF &cell, const QString &text)
|
||||||
|
{
|
||||||
|
auto prevPen = painter.pen();
|
||||||
|
painter.setPen(tablePen());
|
||||||
|
|
||||||
|
painter.drawText(cell, Qt::AlignCenter, text);
|
||||||
|
|
||||||
|
painter.drawLine(cell.topLeft(), cell.topRight());
|
||||||
|
painter.drawLine(cell.topRight(), cell.bottomRight());
|
||||||
|
painter.drawLine(cell.bottomRight(), cell.bottomLeft());
|
||||||
|
painter.drawLine(cell.bottomLeft(), cell.topLeft());
|
||||||
|
|
||||||
|
painter.setPen(prevPen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::drawNumberSquare(QPainter &painter, double x, double y, int number)
|
||||||
|
{
|
||||||
|
QRectF cell = {x, y, 0.03 * painter.device()->width(),
|
||||||
|
1.5 * painter.fontMetrics().lineSpacing()};
|
||||||
|
|
||||||
|
painter.drawText(cell, Qt::AlignCenter, QString::number(number));
|
||||||
|
|
||||||
|
painter.drawLine(cell.topLeft(), cell.topRight());
|
||||||
|
painter.drawLine(cell.topRight(), cell.bottomRight());
|
||||||
|
painter.drawLine(cell.bottomRight(), cell.bottomLeft());
|
||||||
|
painter.drawLine(cell.bottomLeft(), cell.topLeft());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::PrintableModel::drawCheckSquare(QPainter &painter, const QRectF &cell,
|
||||||
|
bool checked)
|
||||||
|
{
|
||||||
|
drawTextSquare(painter, cell, checked ? "\u2612" : "\u2610");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::drawResultSquare(QPainter &painter, double y, bool rightCell,
|
||||||
|
unsigned int value)
|
||||||
|
{
|
||||||
|
double pageWidth = painter.device()->width();
|
||||||
|
double cellWidth = 0.03 * pageWidth;
|
||||||
|
double cellHeight = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
double x = pageWidth - cellWidth - (rightCell ? 0 : 0.04 * pageWidth);
|
||||||
|
|
||||||
|
drawTextSquare(painter, {x, y, cellWidth, cellHeight}, QString::number(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::drawGreySquare(QPainter &painter, const QRectF &cell)
|
||||||
|
{
|
||||||
|
auto prevBrush = painter.brush();
|
||||||
|
auto prevPen = painter.pen();
|
||||||
|
|
||||||
|
painter.setBrush(QBrush(QColor(224, 224, 224)));
|
||||||
|
painter.setPen(QPen(Qt::NoPen));
|
||||||
|
QPointF points[4] = {cell.topLeft(), cell.topRight(), cell.bottomRight(), cell.bottomLeft()};
|
||||||
|
painter.drawPolygon(points, 4);
|
||||||
|
|
||||||
|
painter.setPen(tablePen());
|
||||||
|
painter.drawLine(cell.topLeft(), cell.topRight());
|
||||||
|
painter.drawLine(cell.topRight(), cell.bottomRight());
|
||||||
|
painter.drawLine(cell.bottomRight(), cell.bottomLeft());
|
||||||
|
painter.drawLine(cell.bottomLeft(), cell.topLeft());
|
||||||
|
|
||||||
|
painter.setBrush(prevBrush);
|
||||||
|
painter.setPen(prevPen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::drawHeader2(QPainter &painter, const QString &text)
|
||||||
|
{
|
||||||
|
painter.setFont(h2Font());
|
||||||
|
painter.drawText(0, 0, text);
|
||||||
|
painter.translate(0, 0.5 * painter.fontMetrics().lineSpacing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::printHeader(QPainter &painter) const
|
||||||
|
{
|
||||||
|
auto title = getTitle();
|
||||||
|
if (!title.isEmpty())
|
||||||
|
{
|
||||||
|
drawHeader2(painter, getTitle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::printTests(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.setFont(tableFont());
|
||||||
|
painter.setPen(tablePen());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
double headerWidth = headerWidthFactor() * width;
|
||||||
|
double cellWidth = cellWidthFactor() * width;
|
||||||
|
double rowHeight = height;
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
for (const auto &test : m_tests)
|
||||||
|
{
|
||||||
|
QString testName = QString::fromStdString(
|
||||||
|
std::regex_replace(test.name().toStdString(), std::regex("\\s"), "\n"));
|
||||||
|
|
||||||
|
drawTextSquare(painter, {0, y, headerWidth, 2 * rowHeight}, testName);
|
||||||
|
x = headerWidth;
|
||||||
|
|
||||||
|
for (const auto &item : test.items())
|
||||||
|
{
|
||||||
|
drawTextSquare(painter, {x, y, cellWidth, rowHeight}, item.getText().c_str());
|
||||||
|
drawCheckSquare(painter, {x, y + rowHeight, cellWidth, rowHeight}, item.isChecked());
|
||||||
|
|
||||||
|
x += cellWidth;
|
||||||
|
}
|
||||||
|
y += rowHeight;
|
||||||
|
|
||||||
|
drawResultSquare(painter, y, true, test.getPoints());
|
||||||
|
y += rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.translate(0, y + rowHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintableModel::printSummary(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.setFont(tableFont());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
painter.drawText(0, 0, 0.95 * width, height, Qt::AlignRight | Qt::AlignVCenter,
|
||||||
|
"Rohwertpunkte Total:");
|
||||||
|
painter.setPen(resultPen());
|
||||||
|
drawNumberSquare(painter, 0.97 * width, 0, getPoints());
|
||||||
|
|
||||||
|
painter.translate(0, 3 * height);
|
||||||
|
}
|
42
source/PrintableModel/PrintableModel.h
Normal file
42
source/PrintableModel/PrintableModel.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CheckableTestModel.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QPen>
|
||||||
|
#include <QRect>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class PrintableModel : public CheckableTestModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrintableModel(QObject *parent);
|
||||||
|
|
||||||
|
virtual void printTo(QPainter &painter) const;
|
||||||
|
|
||||||
|
static QFont h1Font();
|
||||||
|
static QFont h2Font();
|
||||||
|
static QFont tableFont();
|
||||||
|
|
||||||
|
static QPen tablePen();
|
||||||
|
static QPen resultPen();
|
||||||
|
|
||||||
|
static double headerWidthFactor();
|
||||||
|
static double cellWidthFactor();
|
||||||
|
|
||||||
|
static void drawTextSquare(QPainter &painter, const QRectF &cell, const QString &text);
|
||||||
|
static void drawNumberSquare(QPainter &painter, double x, double y, int number);
|
||||||
|
static void drawCheckSquare(QPainter &painter, const QRectF &cell, bool checked);
|
||||||
|
static void drawResultSquare(QPainter &painter, double y, bool rightCell, unsigned int value);
|
||||||
|
static void drawGreySquare(QPainter &painter, const QRectF &cell);
|
||||||
|
|
||||||
|
static void drawHeader2(QPainter &painter, const QString &text);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void printHeader(QPainter &painter) const;
|
||||||
|
virtual void printTests(QPainter &painter) const;
|
||||||
|
virtual void printSummary(QPainter &painter) const;
|
||||||
|
};
|
@ -30,6 +30,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
PrintableModel
|
||||||
Age
|
Age
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
)
|
)
|
||||||
|
@ -10,13 +10,14 @@
|
|||||||
#include "PassivPR.h"
|
#include "PassivPR.h"
|
||||||
#include "GenitivPR.h"
|
#include "GenitivPR.h"
|
||||||
|
|
||||||
|
#include "PrintableModel.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
ResultModel::ResultModel(QObject *parent)
|
ResultModel::ResultModel(QObject *parent)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
{
|
{
|
||||||
m_results = { { "V2", "SVK", "VE", "Passiv", "Genus", "Akkusativ", "Dativ",
|
m_results = {{"V2", "SVK", "VE", "Passiv", "Genus", "Akkusativ", "Dativ", "Genitiv", "Plural"}};
|
||||||
"Genitiv", "Plural" } };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResultModel::rowCount(const QModelIndex &parent) const
|
int ResultModel::rowCount(const QModelIndex &parent) const
|
||||||
@ -81,8 +82,7 @@ QVariant ResultModel::data(const QModelIndex &index, int role) const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ResultModel::headerData(
|
QVariant ResultModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
int section, Qt::Orientation orientation, int role) const
|
|
||||||
{
|
{
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
{
|
{
|
||||||
@ -170,7 +170,7 @@ void ResultModel::setDativResult(unsigned int points)
|
|||||||
emit dataChanged(index(0, 6), index(4, 6));
|
emit dataChanged(index(0, 6), index(4, 6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResultModel::setV2Result(unsigned int points)
|
void ResultModel::setV2Result(unsigned int points)
|
||||||
{
|
{
|
||||||
if (m_results[0].points() != points)
|
if (m_results[0].points() != points)
|
||||||
@ -193,20 +193,66 @@ void ResultModel::setSvkResult(unsigned int points)
|
|||||||
|
|
||||||
void ResultModel::setPassivResult(unsigned int points)
|
void ResultModel::setPassivResult(unsigned int points)
|
||||||
{
|
{
|
||||||
if (m_results[3].points() != points)
|
if (m_results[3].points() != points)
|
||||||
{
|
{
|
||||||
m_results[3].setPoints(points);
|
m_results[3].setPoints(points);
|
||||||
m_results[3].setPR(PassivPR().lookup(m_age, points));
|
m_results[3].setPR(PassivPR().lookup(m_age, points));
|
||||||
emit dataChanged(index(0, 3), index(4, 3));
|
emit dataChanged(index(0, 3), index(4, 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResultModel::setGenitivResult(unsigned int points)
|
void ResultModel::setGenitivResult(unsigned int points)
|
||||||
{
|
{
|
||||||
if (m_results[7].points() != points)
|
if (m_results[7].points() != points)
|
||||||
{
|
{
|
||||||
m_results[7].setPoints(points);
|
m_results[7].setPoints(points);
|
||||||
m_results[7].setPR(GenitivPR().lookup(m_age, points));
|
m_results[7].setPR(GenitivPR().lookup(m_age, points));
|
||||||
emit dataChanged(index(0, 7), index(4, 7));
|
emit dataChanged(index(0, 7), index(4, 7));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResultModel::printTo(QPainter &painter) const
|
||||||
|
{
|
||||||
|
PrintableModel::drawHeader2(painter, "Prozentränge (PR)");
|
||||||
|
|
||||||
|
painter.setFont(PrintableModel::tableFont());
|
||||||
|
painter.setPen(PrintableModel::tablePen());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
double cellWidth = width / (m_results.size() + 1);
|
||||||
|
double rowHeight = 2 * height;
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 0 * rowHeight, cellWidth, rowHeight}, "");
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 1 * rowHeight, cellWidth, rowHeight},
|
||||||
|
"\u2265 PR 84");
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 2 * rowHeight, cellWidth, rowHeight},
|
||||||
|
"< PR 84");
|
||||||
|
|
||||||
|
PrintableModel::drawGreySquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight});
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight},
|
||||||
|
"\u2264 PR 16");
|
||||||
|
|
||||||
|
x += cellWidth;
|
||||||
|
for (const auto &result : m_results)
|
||||||
|
{
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 0 * rowHeight, cellWidth, rowHeight},
|
||||||
|
result.name());
|
||||||
|
const auto pr = result.pr();
|
||||||
|
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 1 * rowHeight, cellWidth, rowHeight},
|
||||||
|
pr >= 84 ? QString::number(pr) : "-");
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 2 * rowHeight, cellWidth, rowHeight},
|
||||||
|
pr < 84 && pr > 16 ? QString::number(pr) : "-");
|
||||||
|
|
||||||
|
PrintableModel::drawGreySquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight});
|
||||||
|
PrintableModel::drawTextSquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight},
|
||||||
|
pr <= 16 ? QString::number(pr) : "-");
|
||||||
|
|
||||||
|
x += cellWidth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Age.h"
|
#include "Age.h"
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
class TestResult
|
class TestResult
|
||||||
{
|
{
|
||||||
@ -72,4 +74,6 @@ public:
|
|||||||
void setSvkResult(unsigned int points);
|
void setSvkResult(unsigned int points);
|
||||||
void setPassivResult(unsigned int points);
|
void setPassivResult(unsigned int points);
|
||||||
void setGenitivResult(unsigned int points);
|
void setGenitivResult(unsigned int points);
|
||||||
|
|
||||||
|
void printTo(QPainter &painter) const;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "AkkusativModel.h"
|
#include "AkkusativModel.h"
|
||||||
|
|
||||||
AkkusativModel::AkkusativModel(QObject *parent)
|
AkkusativModel::AkkusativModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: PrintableModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {{"Akkusativ Nominalphrase",
|
m_tests = {{"Akkusativ Nominalphrase",
|
||||||
{"Tiger", "Katze", "Affe", "Gans", "Bär", "Pferd", "Hund", "Elefant"}},
|
{"Tiger", "Katze", "Affe", "Gans", "Bär", "Pferd", "Hund", "Elefant"}},
|
||||||
@ -105,3 +105,8 @@ void AkkusativModel::write(ESGRAF48::AkkusativModel &model) const
|
|||||||
futterModel->set_zucker(testItems[7].isChecked());
|
futterModel->set_zucker(testItems[7].isChecked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AkkusativModel::printHeader(QPainter &painter) const
|
||||||
|
{
|
||||||
|
drawHeader2(painter, "Subtest 4: Akkusativ und Dativ");
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "PrintableModel.h"
|
||||||
#include "AkkusativModel.pb.h"
|
#include "AkkusativModel.pb.h"
|
||||||
|
|
||||||
class AkkusativModel : public CheckableTestModel
|
class AkkusativModel : public PrintableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -12,4 +12,7 @@ public:
|
|||||||
|
|
||||||
void read(const ESGRAF48::AkkusativModel &model);
|
void read(const ESGRAF48::AkkusativModel &model);
|
||||||
void write(ESGRAF48::AkkusativModel &model) const;
|
void write(ESGRAF48::AkkusativModel &model) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &painter) const override;
|
||||||
};
|
};
|
||||||
|
@ -43,9 +43,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
CheckableItem
|
PrintableModel
|
||||||
CheckableTest
|
|
||||||
CheckableTestModel
|
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "DativModel.h"
|
#include "DativModel.h"
|
||||||
|
|
||||||
DativModel::DativModel(QObject *parent)
|
DativModel::DativModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: PrintableModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {{"Dativ Nominalphrase",
|
m_tests = {{"Dativ Nominalphrase",
|
||||||
{"Affe", "Gans", "Tiger", "Hund", "Elefant", "Pferd", "Bär", "Katze"}},
|
{"Affe", "Gans", "Tiger", "Hund", "Elefant", "Pferd", "Bär", "Katze"}},
|
||||||
@ -105,3 +105,8 @@ void DativModel::write(ESGRAF48::DativModel &model) const
|
|||||||
nomTiereModel->set_katze(testItems[7].isChecked());
|
nomTiereModel->set_katze(testItems[7].isChecked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DativModel::printHeader(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.translate(0, -1.5 * painter.fontMetrics().lineSpacing());
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "PrintableModel.h"
|
||||||
#include "DativModel.pb.h"
|
#include "DativModel.pb.h"
|
||||||
|
|
||||||
class DativModel : public CheckableTestModel
|
class DativModel : public PrintableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -12,4 +12,7 @@ public:
|
|||||||
|
|
||||||
void read(const ESGRAF48::DativModel &model);
|
void read(const ESGRAF48::DativModel &model);
|
||||||
void write(ESGRAF48::DativModel &model) const;
|
void write(ESGRAF48::DativModel &model) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &painter) const override;
|
||||||
};
|
};
|
||||||
|
@ -39,9 +39,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
CheckableItem
|
PrintableModel
|
||||||
CheckableTest
|
|
||||||
CheckableTestModel
|
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include "GenusModel.h"
|
#include "GenusModel.h"
|
||||||
|
|
||||||
GenusModel::GenusModel(QObject *parent)
|
GenusModel::GenusModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: PrintableModel(parent)
|
||||||
{
|
{
|
||||||
|
m_title = "Subtest 3: Genus";
|
||||||
|
|
||||||
m_tests = {{"Tiere", {"Tiger", "Bär", "Katze", "Pferd", "Gans", "Elefant", "Affe", "Hund"}},
|
m_tests = {{"Tiere", {"Tiger", "Bär", "Katze", "Pferd", "Gans", "Elefant", "Affe", "Hund"}},
|
||||||
{"Futter",
|
{"Futter",
|
||||||
{"Salat", "Fleisch", "Knochen", "Banane", "Apfel", "Karotte", "Honig", "Zucker"}},
|
{"Salat", "Fleisch", "Knochen", "Banane", "Apfel", "Karotte", "Honig", "Zucker"}},
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "PrintableModel.h"
|
||||||
#include "GenusModel.pb.h"
|
#include "GenusModel.pb.h"
|
||||||
|
|
||||||
class GenusModel : public CheckableTestModel
|
class GenusModel : public PrintableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ protobuf_generate_cpp(LateSkills_PROTO_SRCS LateSkills_PROTO_HDRS
|
|||||||
|
|
||||||
add_library(${PROJECT_NAME}
|
add_library(${PROJECT_NAME}
|
||||||
LateSkillsWidget.cpp
|
LateSkillsWidget.cpp
|
||||||
|
LateSkillsModel.cpp
|
||||||
PassivModel.cpp
|
PassivModel.cpp
|
||||||
GenitivModel.cpp
|
GenitivModel.cpp
|
||||||
${UI_HEADERS}
|
${UI_HEADERS}
|
||||||
@ -43,9 +44,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
CheckableItem
|
PrintableModel
|
||||||
CheckableTest
|
|
||||||
CheckableTestModel
|
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "GenitivModel.h"
|
#include "GenitivModel.h"
|
||||||
|
|
||||||
GenitivModel::GenitivModel(QObject *parent)
|
GenitivModel::GenitivModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: LateSkillsModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {
|
m_tests = {
|
||||||
{"Genitiv Präpositionen",
|
{"Genitiv Präpositionen",
|
||||||
@ -107,3 +107,8 @@ void GenitivModel::write(ESGRAF48::LateSkillsGenitivModel &model) const
|
|||||||
attributierungModel->set_guertel2(testItems[9].isChecked());
|
attributierungModel->set_guertel2(testItems[9].isChecked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenitivModel::printHeader(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.translate(0, -1.5 * painter.fontMetrics().lineSpacing());
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "LateSkillsModel.h"
|
||||||
#include "LateSkillsGenitivModel.pb.h"
|
#include "LateSkillsGenitivModel.pb.h"
|
||||||
|
|
||||||
class GenitivModel : public CheckableTestModel
|
class GenitivModel : public LateSkillsModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -14,4 +14,7 @@ public:
|
|||||||
|
|
||||||
void read(const ESGRAF48::LateSkillsGenitivModel &model);
|
void read(const ESGRAF48::LateSkillsGenitivModel &model);
|
||||||
void write(ESGRAF48::LateSkillsGenitivModel &model) const;
|
void write(ESGRAF48::LateSkillsGenitivModel &model) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &painter) const override;
|
||||||
};
|
};
|
||||||
|
64
source/SubTests/LateSkills/LateSkillsModel.cpp
Normal file
64
source/SubTests/LateSkills/LateSkillsModel.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "LateSkillsModel.h"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
LateSkillsModel::LateSkillsModel(QObject *parent)
|
||||||
|
: PrintableModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void LateSkillsModel::printTests(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.setFont(tableFont());
|
||||||
|
painter.setPen(tablePen());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
double headerWidth = headerWidthFactor() * width;
|
||||||
|
double cellHeaderWidth = cellWidthFactor() * width;
|
||||||
|
double cellWidth = 0.5 * cellHeaderWidth;
|
||||||
|
double rowHeight = height;
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
for (const auto &test : m_tests)
|
||||||
|
{
|
||||||
|
QString testName = QString::fromStdString(
|
||||||
|
std::regex_replace(test.name().toStdString(), std::regex("\\s"), "\n"));
|
||||||
|
|
||||||
|
drawTextSquare(painter, {0, y, headerWidth, 3 * rowHeight}, testName);
|
||||||
|
|
||||||
|
const auto &items = test.items();
|
||||||
|
|
||||||
|
x = headerWidth;
|
||||||
|
for (unsigned int i = 0; i < items.size(); i += 2)
|
||||||
|
{
|
||||||
|
const auto &item = test.items().at(i);
|
||||||
|
QString itemText = QString::fromStdString(item.getText()).split(" ").at(0);
|
||||||
|
|
||||||
|
drawTextSquare(painter, {x, y, cellHeaderWidth, rowHeight}, itemText);
|
||||||
|
|
||||||
|
x += cellHeaderWidth;
|
||||||
|
}
|
||||||
|
y += rowHeight;
|
||||||
|
|
||||||
|
x = headerWidth;
|
||||||
|
for (const auto &item : items)
|
||||||
|
{
|
||||||
|
drawTextSquare(painter, {x, y, cellWidth, rowHeight}, QString::number(item.value()));
|
||||||
|
drawCheckSquare(painter, {x, y + rowHeight, cellWidth, rowHeight}, item.isChecked());
|
||||||
|
|
||||||
|
x += cellWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_tests.size() > 1)
|
||||||
|
{
|
||||||
|
drawResultSquare(painter, y + rowHeight, true, test.getPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
y += 2 * rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.translate(0, y + rowHeight);
|
||||||
|
}
|
15
source/SubTests/LateSkills/LateSkillsModel.h
Normal file
15
source/SubTests/LateSkills/LateSkillsModel.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PrintableModel.h"
|
||||||
|
#include "LateSkillsPassivModel.pb.h"
|
||||||
|
|
||||||
|
class LateSkillsModel : public PrintableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LateSkillsModel(QObject *parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printTests(QPainter &painter) const override;
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
#include "PassivModel.h"
|
#include "PassivModel.h"
|
||||||
|
|
||||||
PassivModel::PassivModel(QObject *parent)
|
PassivModel::PassivModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: LateSkillsModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {{"Passiv",
|
m_tests = {{"Passiv",
|
||||||
{"Elefant (1)", "Elefant (2)", "Pferde (1)", "Pferde (2)", "Bälle (1)", "Bälle (2)",
|
{"Elefant (1)", "Elefant (2)", "Pferde (1)", "Pferde (2)", "Bälle (1)", "Bälle (2)",
|
||||||
@ -65,3 +65,8 @@ void PassivModel::write(ESGRAF48::LateSkillsPassivModel &model) const
|
|||||||
model.set_fleisch1(testItems[8].isChecked());
|
model.set_fleisch1(testItems[8].isChecked());
|
||||||
model.set_fleisch2(testItems[9].isChecked());
|
model.set_fleisch2(testItems[9].isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PassivModel::printHeader(QPainter &painter) const
|
||||||
|
{
|
||||||
|
drawHeader2(painter, "Subtest 6: Späte Fähigkeiten (7;0-8;11)");
|
||||||
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "LateSkillsModel.h"
|
||||||
#include "LateSkillsPassivModel.pb.h"
|
#include "LateSkillsPassivModel.pb.h"
|
||||||
|
|
||||||
class PassivModel : public CheckableTestModel
|
class PassivModel : public LateSkillsModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PassivModel(QObject *parent);
|
PassivModel(QObject *parent);
|
||||||
bool setData(const QModelIndex &index, const QVariant &value,
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
int role = Qt::EditRole) override;
|
|
||||||
|
|
||||||
void read(const ESGRAF48::LateSkillsPassivModel &model);
|
void read(const ESGRAF48::LateSkillsPassivModel &model);
|
||||||
void write(ESGRAF48::LateSkillsPassivModel &model) const;
|
void write(ESGRAF48::LateSkillsPassivModel &model) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &painter) const override;
|
||||||
};
|
};
|
||||||
|
@ -39,9 +39,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
CheckableItem
|
PrintableModel
|
||||||
CheckableTest
|
|
||||||
CheckableTestModel
|
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
PluralModel::PluralModel(QObject *parent)
|
PluralModel::PluralModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: PrintableModel(parent)
|
||||||
{
|
{
|
||||||
|
m_title = "Subtest 5: Plural";
|
||||||
|
|
||||||
m_tests = {{"Plural",
|
m_tests = {{"Plural",
|
||||||
{"Fisch /-e/", "Banane /-n/", "Bonbon /-s/", "Ei /-er/", "Eimer /-ø/",
|
{"Fisch /-e/", "Banane /-n/", "Bonbon /-s/", "Ei /-er/", "Eimer /-ø/",
|
||||||
"Korn UML+/-er/", "Nuss UML+/-e/", "Bär /-en/", "Apfel UML"}}};
|
"Korn UML+/-er/", "Nuss UML+/-e/", "Bär /-en/", "Apfel UML"}}};
|
||||||
@ -41,3 +45,39 @@ void PluralModel::write(ESGRAF48::PluralModel &model) const
|
|||||||
model.set_baer(testItems[7].isChecked());
|
model.set_baer(testItems[7].isChecked());
|
||||||
model.set_apfel(testItems[8].isChecked());
|
model.set_apfel(testItems[8].isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PluralModel::printTests(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.setFont(tableFont());
|
||||||
|
painter.setPen(tablePen());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
double headerWidth = headerWidthFactor() * width;
|
||||||
|
double cellWidth = cellWidthFactor() * width;
|
||||||
|
double rowHeight = height;
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
for (const auto &test : m_tests)
|
||||||
|
{
|
||||||
|
drawTextSquare(painter, {0, y, headerWidth, 3 * rowHeight}, test.name());
|
||||||
|
x = headerWidth;
|
||||||
|
|
||||||
|
for (const auto &item : test.items())
|
||||||
|
{
|
||||||
|
QString itemText =
|
||||||
|
QString::fromStdString(std::regex_replace(item.getText(), std::regex("\\s"), "\n"));
|
||||||
|
|
||||||
|
drawTextSquare(painter, {x, y, cellWidth, 2 * rowHeight}, itemText);
|
||||||
|
drawCheckSquare(painter, {x, y + 2 * rowHeight, cellWidth, rowHeight},
|
||||||
|
item.isChecked());
|
||||||
|
|
||||||
|
x += cellWidth;
|
||||||
|
}
|
||||||
|
y += 2 * rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.translate(0, y + 2 * rowHeight);
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "PrintableModel.h"
|
||||||
#include "PluralModel.pb.h"
|
#include "PluralModel.pb.h"
|
||||||
|
|
||||||
class PluralModel : public CheckableTestModel
|
class PluralModel : public PrintableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -12,4 +12,7 @@ public:
|
|||||||
|
|
||||||
void read(const ESGRAF48::PluralModel &model);
|
void read(const ESGRAF48::PluralModel &model);
|
||||||
void write(ESGRAF48::PluralModel &model) const;
|
void write(ESGRAF48::PluralModel &model) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void printTests(QPainter &painter) const;
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,7 @@ protobuf_generate_cpp(V2Svk_PROTO_SRCS V2Svk_PROTO_HDRS ${V2Svk_PROTO_FILES})
|
|||||||
|
|
||||||
add_library(${PROJECT_NAME}
|
add_library(${PROJECT_NAME}
|
||||||
V2SvkWidget.cpp
|
V2SvkWidget.cpp
|
||||||
|
V2SvkModel.cpp
|
||||||
WFModel.cpp
|
WFModel.cpp
|
||||||
OTModel.cpp
|
OTModel.cpp
|
||||||
TPrModel.cpp
|
TPrModel.cpp
|
||||||
@ -42,9 +43,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
CheckableItem
|
PrintableModel
|
||||||
CheckableTest
|
|
||||||
CheckableTestModel
|
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "OTModel.h"
|
#include "OTModel.h"
|
||||||
|
|
||||||
OTModel::OTModel(QObject *parent)
|
OTModel::OTModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: V2SvkModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {
|
m_tests = {
|
||||||
{"Objekt-Topikalisierung",
|
{"Objekt-Topikalisierung",
|
||||||
@ -13,7 +13,7 @@ OTModel::OTModel(QObject *parent)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int OTModel::getV2Points()
|
unsigned int OTModel::getV2Points() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ unsigned int OTModel::getV2Points()
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int OTModel::getSvkPoints()
|
unsigned int OTModel::getSvkPoints() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -103,3 +103,13 @@ void OTModel::read(const ESGRAF48::V2SvkModel &model)
|
|||||||
|
|
||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<int> OTModel::v2Tests() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<int> OTModel::svkTests() const
|
||||||
|
{
|
||||||
|
return {1};
|
||||||
|
};
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "V2SvkModel.h"
|
||||||
#include "V2SvkModel.pb.h"
|
#include "V2SvkModel.pb.h"
|
||||||
|
|
||||||
class OTModel : public CheckableTestModel
|
class OTModel : public V2SvkModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OTModel(QObject *parent);
|
OTModel(QObject *parent);
|
||||||
|
|
||||||
unsigned int getV2Points();
|
unsigned int getV2Points() const override;
|
||||||
unsigned int getSvkPoints();
|
unsigned int getSvkPoints() const override;
|
||||||
|
|
||||||
void write(ESGRAF48::V2SvkModel &model) const;
|
void write(ESGRAF48::V2SvkModel &model) const override;
|
||||||
void read(const ESGRAF48::V2SvkModel &model);
|
void read(const ESGRAF48::V2SvkModel &model) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &) const override {};
|
||||||
|
|
||||||
|
std::set<int> v2Tests() const override;
|
||||||
|
std::set<int> svkTests() const override;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "TPeModel.h"
|
#include "TPeModel.h"
|
||||||
|
|
||||||
TPeModel::TPeModel(QObject *parent)
|
TPeModel::TPeModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: V2SvkModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {
|
m_tests = {
|
||||||
{"Temporaladverb Perfekt", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
|
{"Temporaladverb Perfekt", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
|
||||||
@ -11,7 +11,7 @@ TPeModel::TPeModel(QObject *parent)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TPeModel::getV2Points()
|
unsigned int TPeModel::getV2Points() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ unsigned int TPeModel::getV2Points()
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TPeModel::getSvkPoints()
|
unsigned int TPeModel::getSvkPoints() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -93,3 +93,13 @@ void TPeModel::read(const ESGRAF48::V2SvkModel &model)
|
|||||||
|
|
||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<int> TPeModel::v2Tests() const
|
||||||
|
{
|
||||||
|
return {0, 1};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<int> TPeModel::svkTests() const
|
||||||
|
{
|
||||||
|
return {2, 3};
|
||||||
|
};
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "V2SvkModel.h"
|
||||||
#include "V2SvkModel.pb.h"
|
#include "V2SvkModel.pb.h"
|
||||||
|
|
||||||
class TPeModel : public CheckableTestModel
|
class TPeModel : public V2SvkModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TPeModel(QObject *parent);
|
TPeModel(QObject *parent);
|
||||||
|
|
||||||
unsigned int getV2Points();
|
unsigned int getV2Points() const override;
|
||||||
unsigned int getSvkPoints();
|
unsigned int getSvkPoints() const override;
|
||||||
|
|
||||||
void write(ESGRAF48::V2SvkModel &model) const;
|
void write(ESGRAF48::V2SvkModel &model) const override;
|
||||||
void read(const ESGRAF48::V2SvkModel &model);
|
void read(const ESGRAF48::V2SvkModel &model) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &) const override {};
|
||||||
|
|
||||||
|
std::set<int> v2Tests() const override;
|
||||||
|
std::set<int> svkTests() const override;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "TPrModel.h"
|
#include "TPrModel.h"
|
||||||
|
|
||||||
TPrModel::TPrModel(QObject *parent)
|
TPrModel::TPrModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: V2SvkModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = {
|
m_tests = {
|
||||||
{"Temporaladverb Präsens", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
|
{"Temporaladverb Präsens", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
|
||||||
@ -9,7 +9,7 @@ TPrModel::TPrModel(QObject *parent)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TPrModel::getV2Points()
|
unsigned int TPrModel::getV2Points() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ unsigned int TPrModel::getV2Points()
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TPrModel::getSvkPoints()
|
unsigned int TPrModel::getSvkPoints() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -87,3 +87,13 @@ void TPrModel::read(const ESGRAF48::V2SvkModel &model)
|
|||||||
|
|
||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<int> TPrModel::v2Tests() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<int> TPrModel::svkTests() const
|
||||||
|
{
|
||||||
|
return {1};
|
||||||
|
};
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "V2SvkModel.h"
|
||||||
#include "V2SvkModel.pb.h"
|
#include "V2SvkModel.pb.h"
|
||||||
|
|
||||||
class TPrModel : public CheckableTestModel
|
class TPrModel : public V2SvkModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TPrModel(QObject *parent);
|
TPrModel(QObject *parent);
|
||||||
|
|
||||||
unsigned int getV2Points();
|
unsigned int getV2Points() const override;
|
||||||
unsigned int getSvkPoints();
|
unsigned int getSvkPoints() const override;
|
||||||
|
|
||||||
void write(ESGRAF48::V2SvkModel &model) const;
|
void write(ESGRAF48::V2SvkModel &model) const override;
|
||||||
void read(const ESGRAF48::V2SvkModel &model);
|
void read(const ESGRAF48::V2SvkModel &model) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printHeader(QPainter &) const override{};
|
||||||
|
|
||||||
|
std::set<int> v2Tests() const override;
|
||||||
|
std::set<int> svkTests() const override;
|
||||||
};
|
};
|
||||||
|
137
source/SubTests/V2Svk/V2SvkModel.cpp
Normal file
137
source/SubTests/V2Svk/V2SvkModel.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include "V2SvkModel.h"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
V2SvkModel::V2SvkModel(QObject *parent)
|
||||||
|
: PrintableModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2SvkModel::printTests(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.setFont(tableFont());
|
||||||
|
painter.setPen(tablePen());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
auto v2TestIndices = v2Tests();
|
||||||
|
auto svkTestIndices = svkTests();
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
auto testIndex = 0;
|
||||||
|
for (const auto &test : m_tests)
|
||||||
|
{
|
||||||
|
double rowHeaderWidth = headerWidthFactor() * width;
|
||||||
|
double resultCellWidth = (test.size() > 8 ? 0.5 : 1) * cellWidthFactor() * width;
|
||||||
|
double rowHeight = height;
|
||||||
|
|
||||||
|
QString testName = test.name();
|
||||||
|
if (testName.length() > 20)
|
||||||
|
{
|
||||||
|
testName = QString::fromStdString(
|
||||||
|
std::regex_replace(testName.toStdString(), std::regex("[\\s-]"), "\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testIndex == 0)
|
||||||
|
{
|
||||||
|
drawTextSquare(painter, {x, y, rowHeaderWidth, 2 * rowHeight}, testName);
|
||||||
|
x += rowHeaderWidth;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, unsigned int>> columnHeaders;
|
||||||
|
for (const auto &item : test.items())
|
||||||
|
{
|
||||||
|
const auto &itemText = item.getText();
|
||||||
|
if (!columnHeaders.empty() && columnHeaders.back().first == itemText)
|
||||||
|
{
|
||||||
|
columnHeaders.back().second++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
columnHeaders.emplace_back(itemText, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &columnHeader : columnHeaders)
|
||||||
|
{
|
||||||
|
double cellWidth = columnHeader.second * resultCellWidth;
|
||||||
|
drawTextSquare(painter, {x, y, cellWidth, rowHeight}, columnHeader.first.c_str());
|
||||||
|
x += cellWidth;
|
||||||
|
}
|
||||||
|
x = rowHeaderWidth;
|
||||||
|
y += rowHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drawTextSquare(painter, {x, y, rowHeaderWidth, rowHeight}, testName);
|
||||||
|
x += rowHeaderWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int emptyItemsStack = 0;
|
||||||
|
for (const auto &item : test.items())
|
||||||
|
{
|
||||||
|
if (item.getText().empty())
|
||||||
|
{
|
||||||
|
emptyItemsStack++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (emptyItemsStack > 0)
|
||||||
|
{
|
||||||
|
drawGreySquare(painter, {x - emptyItemsStack * resultCellWidth, y,
|
||||||
|
emptyItemsStack * resultCellWidth, rowHeight});
|
||||||
|
emptyItemsStack = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCheckSquare(painter, {x, y, resultCellWidth, rowHeight}, item.isChecked());
|
||||||
|
}
|
||||||
|
x += resultCellWidth;
|
||||||
|
}
|
||||||
|
if (emptyItemsStack > 0)
|
||||||
|
{
|
||||||
|
drawGreySquare(painter, {x - emptyItemsStack * resultCellWidth, y,
|
||||||
|
emptyItemsStack * resultCellWidth, rowHeight});
|
||||||
|
emptyItemsStack = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v2TestIndices.find(testIndex) != v2TestIndices.end())
|
||||||
|
{
|
||||||
|
drawResultSquare(painter, y, false, test.getPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (svkTestIndices.find(testIndex) != svkTestIndices.end())
|
||||||
|
{
|
||||||
|
drawResultSquare(painter, y, true, test.getPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y += rowHeight;
|
||||||
|
|
||||||
|
testIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y += height;
|
||||||
|
|
||||||
|
painter.translate(0, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2SvkModel::printSummary(QPainter &painter, unsigned int v2Points, unsigned int svkPoints)
|
||||||
|
{
|
||||||
|
painter.setFont(PrintableModel::tableFont());
|
||||||
|
painter.setPen(PrintableModel::tablePen());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
painter.drawText(0, 0, 0.91 * width, height, Qt::AlignRight | Qt::AlignVCenter,
|
||||||
|
"Rohwertpunkte Total:");
|
||||||
|
|
||||||
|
painter.setPen(resultPen());
|
||||||
|
drawNumberSquare(painter, 0.93 * width, 0, v2Points);
|
||||||
|
drawNumberSquare(painter, 0.97 * width, 0, svkPoints);
|
||||||
|
|
||||||
|
painter.translate(0, 3 * height);
|
||||||
|
}
|
||||||
|
|
27
source/SubTests/V2Svk/V2SvkModel.h
Normal file
27
source/SubTests/V2Svk/V2SvkModel.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PrintableModel.h"
|
||||||
|
#include "V2SvkModel.pb.h"
|
||||||
|
|
||||||
|
class V2SvkModel : public PrintableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
V2SvkModel(QObject *parent);
|
||||||
|
|
||||||
|
virtual unsigned int getV2Points() const = 0;
|
||||||
|
virtual unsigned int getSvkPoints() const = 0;
|
||||||
|
|
||||||
|
virtual void write(ESGRAF48::V2SvkModel &model) const = 0;
|
||||||
|
virtual void read(const ESGRAF48::V2SvkModel &model) = 0;
|
||||||
|
|
||||||
|
static void printSummary(QPainter &painter, unsigned int v2Points, unsigned int svkPoints);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printTests(QPainter &painter) const override;
|
||||||
|
void printSummary(QPainter &painter) const override {};
|
||||||
|
|
||||||
|
virtual std::set<int> v2Tests() const = 0;
|
||||||
|
virtual std::set<int> svkTests() const = 0;
|
||||||
|
};
|
@ -1,8 +1,10 @@
|
|||||||
#include "WFModel.h"
|
#include "WFModel.h"
|
||||||
|
|
||||||
WFModel::WFModel(QObject *parent)
|
WFModel::WFModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: V2SvkModel(parent)
|
||||||
{
|
{
|
||||||
|
m_title = "Subtest 1: Verbzweitstellungsregel (V2) und Subjekt-Verb-Kontrollregel (SVK)";
|
||||||
|
|
||||||
m_tests = {
|
m_tests = {
|
||||||
{"W-Frage",
|
{"W-Frage",
|
||||||
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
|
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
|
||||||
@ -14,7 +16,7 @@ WFModel::WFModel(QObject *parent)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WFModel::getV2Points()
|
unsigned int WFModel::getV2Points() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ unsigned int WFModel::getV2Points()
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WFModel::getSvkPoints()
|
unsigned int WFModel::getSvkPoints() const
|
||||||
{
|
{
|
||||||
unsigned int points = 0;
|
unsigned int points = 0;
|
||||||
|
|
||||||
@ -133,3 +135,13 @@ void WFModel::read(const ESGRAF48::V2SvkModel &model)
|
|||||||
|
|
||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<int> WFModel::v2Tests() const
|
||||||
|
{
|
||||||
|
return {0, 1};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<int> WFModel::svkTests() const
|
||||||
|
{
|
||||||
|
return {2};
|
||||||
|
};
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "V2SvkModel.h"
|
||||||
#include "V2SvkModel.pb.h"
|
#include "V2SvkModel.pb.h"
|
||||||
|
|
||||||
class WFModel : public CheckableTestModel
|
class WFModel : public V2SvkModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WFModel(QObject *parent);
|
WFModel(QObject *parent);
|
||||||
|
|
||||||
unsigned int getV2Points();
|
unsigned int getV2Points() const override;
|
||||||
unsigned int getSvkPoints();
|
unsigned int getSvkPoints() const override;
|
||||||
|
|
||||||
void write(ESGRAF48::V2SvkModel &model) const;
|
void write(ESGRAF48::V2SvkModel &model) const override;
|
||||||
void read(const ESGRAF48::V2SvkModel &model);
|
void read(const ESGRAF48::V2SvkModel &model) override;
|
||||||
|
|
||||||
bool isValidIndex(const QModelIndex &index) const;
|
protected:
|
||||||
|
std::set<int> v2Tests() const override;
|
||||||
|
std::set<int> svkTests() const override;
|
||||||
|
|
||||||
|
bool isValidIndex(const QModelIndex &index) const override;
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,7 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
CheckableItem
|
CheckableItem
|
||||||
CheckableTest
|
CheckableTest
|
||||||
CheckableTestModel
|
CheckableTestModel
|
||||||
|
PrintableModel
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
${Protobuf_LIBRARIES}
|
${Protobuf_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
#include "VerbEndModel.h"
|
#include "VerbEndModel.h"
|
||||||
|
|
||||||
VerbEndModel::VerbEndModel(QObject *parent)
|
VerbEndModel::VerbEndModel(QObject *parent)
|
||||||
: CheckableTestModel(parent)
|
: PrintableModel(parent)
|
||||||
{
|
{
|
||||||
m_tests = { { "Telefonat",
|
m_title = "Subtest 2: Verbendstellungsregel (VE)";
|
||||||
{ "Kausal", "Kausal", "Relativ", "Kausal",
|
|
||||||
"Final", "Temporal", "Temporal" } },
|
m_tests = {
|
||||||
{ "Zaubertrick", { "Relativ", "Final", "Kausal", "Final",
|
{"Telefonat", {"Kausal", "Kausal", "Relativ", "Kausal", "Final", "Temporal", "Temporal"}},
|
||||||
"Temporal", "Kausal", "Temporal" } },
|
{"Zaubertrick", {"Relativ", "Final", "Kausal", "Final", "Temporal", "Kausal", "Temporal"}},
|
||||||
{ "Zauberregel", { "Temporal", "Kausal", "Final", "Relativ",
|
{"Zauberregel", {"Temporal", "Kausal", "Final", "Relativ", "Temporal", "Relativ"}}};
|
||||||
"Temporal", "Relativ" } } };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerbEndModel::write(ESGRAF48::VerbEndModel &model) const
|
void VerbEndModel::write(ESGRAF48::VerbEndModel &model) const
|
||||||
@ -98,3 +97,32 @@ void VerbEndModel::read(const ESGRAF48::VerbEndModel &model)
|
|||||||
|
|
||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int VerbEndModel::getKausalPoints() const
|
||||||
|
{
|
||||||
|
auto points = [&](unsigned int testId, unsigned int itemId) {
|
||||||
|
return m_tests.at(testId).items().at(itemId).points();
|
||||||
|
};
|
||||||
|
|
||||||
|
return points(0, 0) + points(0, 1) + points(0, 3) + points(1, 2) + points(1, 5) + points(2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbEndModel::printSummary(QPainter &painter) const
|
||||||
|
{
|
||||||
|
painter.setFont(tableFont());
|
||||||
|
|
||||||
|
auto width = painter.device()->width();
|
||||||
|
auto height = 1.5 * painter.fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
painter.drawText(0, 0, 0.71 * width, height, Qt::AlignRight | Qt::AlignVCenter,
|
||||||
|
"Rohwertpunkte Kausalsätze:");
|
||||||
|
painter.drawText(0, 0, 0.95 * width, height, Qt::AlignRight | Qt::AlignVCenter,
|
||||||
|
"Rohwertpunkte Total:");
|
||||||
|
|
||||||
|
drawNumberSquare(painter, 0.73 * width, 0, getKausalPoints());
|
||||||
|
|
||||||
|
painter.setPen(resultPen());
|
||||||
|
drawNumberSquare(painter, 0.97 * width, 0, getKausalPoints());
|
||||||
|
|
||||||
|
painter.translate(0, 3 * height);
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CheckableTestModel.h"
|
#include "PrintableModel.h"
|
||||||
#include "VerbEndModel.pb.h"
|
#include "VerbEndModel.pb.h"
|
||||||
|
|
||||||
class VerbEndModel : public CheckableTestModel
|
class VerbEndModel : public PrintableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -12,4 +12,9 @@ public:
|
|||||||
|
|
||||||
void write(ESGRAF48::VerbEndModel &model) const;
|
void write(ESGRAF48::VerbEndModel &model) const;
|
||||||
void read(const ESGRAF48::VerbEndModel &model);
|
void read(const ESGRAF48::VerbEndModel &model);
|
||||||
|
|
||||||
|
unsigned int getKausalPoints() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void printSummary(QPainter &painter) const override;
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <QtPrintSupport/QPrinter>
|
#include <QtPrintSupport/QPrinter>
|
||||||
#include <QtPrintSupport/QPrintDialog>
|
#include <QtPrintSupport/QPrintDialog>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
@ -167,10 +168,9 @@ void MainWindow::closeFile()
|
|||||||
|
|
||||||
void MainWindow::print() const
|
void MainWindow::print() const
|
||||||
{
|
{
|
||||||
//std::ofstream htmlfile("print.html");
|
|
||||||
//htmlfile << m_dataModel.toHtml();
|
|
||||||
|
|
||||||
QPrinter printer;
|
QPrinter printer;
|
||||||
|
printer.setPaperSize(QPrinter::A4);
|
||||||
|
printer.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
|
||||||
|
|
||||||
QPrintDialog dialog(&printer);
|
QPrintDialog dialog(&printer);
|
||||||
if (dialog.exec() != QDialog::Accepted)
|
if (dialog.exec() != QDialog::Accepted)
|
||||||
@ -178,10 +178,7 @@ void MainWindow::print() const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextDocument printDoc;
|
m_dataModel.printTo(printer);
|
||||||
printDoc.setHtml(QString::fromStdString(m_dataModel.toHtml()));
|
|
||||||
|
|
||||||
printDoc.print(&printer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::dataModelChanged()
|
void MainWindow::dataModelChanged()
|
||||||
@ -237,12 +234,10 @@ void MainWindow::savePdf(const QString &filename)
|
|||||||
QPrinter printer;
|
QPrinter printer;
|
||||||
printer.setOutputFormat(QPrinter::PdfFormat);
|
printer.setOutputFormat(QPrinter::PdfFormat);
|
||||||
printer.setPaperSize(QPrinter::A4);
|
printer.setPaperSize(QPrinter::A4);
|
||||||
|
printer.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
|
||||||
printer.setOutputFileName(filename);
|
printer.setOutputFileName(filename);
|
||||||
|
|
||||||
QTextDocument printDoc;
|
m_dataModel.printTo(printer);
|
||||||
printDoc.setHtml(QString::fromStdString(m_dataModel.toHtml()));
|
|
||||||
|
|
||||||
printDoc.print(&printer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::aboutDialog()
|
void MainWindow::aboutDialog()
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
|
|
||||||
class DataModel;
|
class DataModel;
|
||||||
|
Reference in New Issue
Block a user