2018-05-24 18:35:16 +00:00
|
|
|
#include "CheckableTestModel.h"
|
|
|
|
|
|
|
|
#include <QJsonArray>
|
2018-08-26 12:24:05 +00:00
|
|
|
#include <QSize>
|
2018-12-08 20:02:35 +00:00
|
|
|
#include <QTextTable>
|
2018-05-24 18:35:16 +00:00
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
CheckableTestModel::CheckableTestModel(QObject *parent)
|
2018-12-08 20:02:35 +00:00
|
|
|
: QAbstractTableModel(parent)
|
2018-05-24 18:35:16 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-26 12:24:05 +00:00
|
|
|
int CheckableTestModel::rowCount(const QModelIndex &) const
|
2018-05-24 18:35:16 +00:00
|
|
|
{
|
2018-12-08 20:02:35 +00:00
|
|
|
return static_cast<int>(m_tests.size());
|
2018-05-24 18:35:16 +00:00
|
|
|
}
|
|
|
|
|
2018-08-26 12:24:05 +00:00
|
|
|
int CheckableTestModel::columnCount(const QModelIndex &) const
|
2018-05-24 18:35:16 +00:00
|
|
|
{
|
|
|
|
int columnCount = 0;
|
|
|
|
|
|
|
|
for (const auto &test : m_tests)
|
|
|
|
{
|
2018-12-08 20:02:35 +00:00
|
|
|
columnCount = std::max(columnCount, static_cast<int>(test.size()));
|
2018-05-24 18:35:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return columnCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant CheckableTestModel::data(const QModelIndex &index, int role) const
|
|
|
|
{
|
|
|
|
if (!isValidIndex(index))
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto &item = getItem(index);
|
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
switch (role)
|
|
|
|
{
|
|
|
|
case Qt::DisplayRole:
|
|
|
|
{
|
|
|
|
return item.getText().c_str();
|
|
|
|
}
|
|
|
|
case Qt::CheckStateRole:
|
|
|
|
{
|
|
|
|
return item.isChecked() ? Qt::Checked : Qt::Unchecked;
|
|
|
|
}
|
|
|
|
}
|
2018-05-24 18:35:16 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
bool CheckableTestModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
2018-05-24 18:35:16 +00:00
|
|
|
{
|
|
|
|
if (!isValidIndex(index))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (role == Qt::CheckStateRole)
|
|
|
|
{
|
|
|
|
auto &item = getItem(index);
|
|
|
|
item.setState(value.toBool());
|
2018-06-08 18:25:21 +00:00
|
|
|
emit dataChanged(index, index);
|
2018-05-24 18:35:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::runtime_error &e)
|
|
|
|
{
|
|
|
|
qDebug() << "CheckableTestModel::setData" << index << e.what();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
QVariant CheckableTestModel::headerData(int section, Qt::Orientation orientation, int role) const
|
2018-05-24 18:35:16 +00:00
|
|
|
{
|
|
|
|
if (role == Qt::DisplayRole && orientation == Qt::Vertical)
|
|
|
|
{
|
|
|
|
if (section < m_tests.size())
|
|
|
|
{
|
|
|
|
return m_tests.at(section).name();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
return QAbstractTableModel::headerData(section, orientation, role);
|
2018-05-24 18:35:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CheckableTestModel::isValidIndex(const QModelIndex &index) const
|
|
|
|
{
|
|
|
|
if (index.row() < m_tests.size())
|
|
|
|
{
|
|
|
|
return index.column() < m_tests.at(index.row()).size();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
void CheckableTestModel::printTo(QTextCursor &cursor) const
|
|
|
|
{
|
|
|
|
QTextCharFormat headerFormat;
|
|
|
|
headerFormat.setFontPointSize(10);
|
|
|
|
cursor.insertBlock();
|
|
|
|
cursor.insertText("\n");
|
|
|
|
cursor.insertText(getName().c_str(), headerFormat);
|
|
|
|
|
|
|
|
printTableTo(cursor);
|
|
|
|
cursor.movePosition(QTextCursor::End);
|
|
|
|
cursor.insertBlock();
|
|
|
|
cursor.insertText("\n");
|
|
|
|
printSummaryTo(cursor);
|
|
|
|
cursor.movePosition(QTextCursor::End);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckableTestModel::printTableTo(QTextCursor &cursor) const
|
|
|
|
{
|
|
|
|
QTextTableFormat tableFormat;
|
|
|
|
tableFormat.setCellPadding(2);
|
|
|
|
tableFormat.setCellSpacing(0);
|
|
|
|
|
|
|
|
tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 20),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 9),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 1),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 3),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 1),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 3)});
|
|
|
|
|
|
|
|
QTextTable *table = cursor.insertTable(m_tests.size() * 2, 13, tableFormat);
|
|
|
|
|
|
|
|
int currentRow = 0;
|
|
|
|
for (const auto &test : m_tests)
|
|
|
|
{
|
|
|
|
table->mergeCells(currentRow, 0, 2, 1);
|
|
|
|
|
|
|
|
int currentColumn = 0;
|
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
setCellText(*table, currentRow, currentColumn, test.name());
|
2018-12-08 20:02:35 +00:00
|
|
|
currentColumn++;
|
|
|
|
|
|
|
|
for (const auto &item : test.items())
|
|
|
|
{
|
2018-12-10 20:11:46 +00:00
|
|
|
setCellText(*table, currentRow, currentColumn, item.getText().c_str());
|
|
|
|
setCellChecked(*table, currentRow + 1, currentColumn, item.isChecked());
|
2018-12-08 20:02:35 +00:00
|
|
|
|
|
|
|
currentColumn++;
|
|
|
|
}
|
|
|
|
|
2018-12-10 21:29:49 +00:00
|
|
|
setCellNumber(*table, currentRow + 1, 12, test.getPoints());
|
2018-12-08 20:02:35 +00:00
|
|
|
|
|
|
|
currentRow += 2;
|
|
|
|
}
|
|
|
|
}
|
2018-12-09 10:27:13 +00:00
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
void CheckableTestModel::printSummaryTo(QTextCursor &cursor) const
|
|
|
|
{
|
|
|
|
QTextTableFormat tableFormat;
|
|
|
|
tableFormat.setCellPadding(2);
|
|
|
|
tableFormat.setCellSpacing(0);
|
|
|
|
|
|
|
|
tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 76),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 20),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 1),
|
|
|
|
QTextLength(QTextLength::PercentageLength, 3)});
|
|
|
|
|
|
|
|
QTextTable *table = cursor.insertTable(1, 4, tableFormat);
|
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
setCellText(*table, 0, 1, "Rohwertpunkte Total:");
|
2018-12-10 21:29:49 +00:00
|
|
|
setCellNumber(*table, 0, 3, getPoints());
|
2018-12-10 20:11:46 +00:00
|
|
|
}
|
2018-12-08 20:02:35 +00:00
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
void CheckableTestModel::setCellText(QTextTable &table, int row, int column, const QString &text)
|
|
|
|
{
|
|
|
|
auto cell = table.cellAt(row, column);
|
|
|
|
auto textCursor = cell.firstCursorPosition();
|
2018-12-08 20:02:35 +00:00
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
auto blockFormat = textCursor.blockFormat();
|
|
|
|
blockFormat.setAlignment(Qt::AlignCenter);
|
|
|
|
textCursor.setBlockFormat(blockFormat);
|
2018-12-08 20:02:35 +00:00
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
auto cellFormat = cell.format();
|
|
|
|
cellFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
|
|
|
|
cell.setFormat(cellFormat);
|
2018-12-09 10:27:13 +00:00
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
auto charFormat = textCursor.charFormat();
|
|
|
|
charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
|
|
|
|
charFormat.setFontPointSize(8);
|
|
|
|
textCursor.setCharFormat(charFormat);
|
2018-12-08 20:02:35 +00:00
|
|
|
|
2018-12-10 20:11:46 +00:00
|
|
|
textCursor.insertText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckableTestModel::setCellChecked(QTextTable &table, int row, int column, bool check)
|
|
|
|
{
|
|
|
|
setCellText(table, row, column, check ? "x" : "\u2610");
|
2018-12-08 20:02:35 +00:00
|
|
|
}
|
|
|
|
|
2018-05-24 18:35:16 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:02:35 +00:00
|
|
|
const CheckableItems &CheckableTestModel::getItems(const QModelIndex &index) const
|
2018-05-24 18:35:16 +00:00
|
|
|
{
|
|
|
|
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");
|
|
|
|
}
|
2018-06-15 15:53:43 +00:00
|
|
|
|
|
|
|
unsigned int CheckableTestModel::getPoints() const
|
|
|
|
{
|
2018-12-10 20:11:46 +00:00
|
|
|
return std::accumulate(
|
|
|
|
std::begin(m_tests), std::end(m_tests), 0,
|
|
|
|
[](int base, const CheckableTest &test) { return base + test.getPoints(); });
|
2018-06-15 15:53:43 +00:00
|
|
|
}
|