379 lines
11 KiB
C++
379 lines
11 KiB
C++
#include "simplelisttablemodel.h"
|
|
#include "componentmodel.h"
|
|
#include <QDebug>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonArray>
|
|
|
|
// Регистрируем структуры для работы с QVariant
|
|
Q_DECLARE_METATYPE(SimpleListCellData)
|
|
Q_DECLARE_METATYPE(SimpleListRowData)
|
|
|
|
// Статические константы
|
|
const QStringList SimpleListTableModel::DEFAULT_HEADERS = QStringList() << "Поз.обозначение" << "Наименование" << "Кол.";
|
|
|
|
SimpleListTableModel::SimpleListTableModel(QObject *parent)
|
|
: QAbstractTableModel(parent)
|
|
, m_techReservePercent(10)
|
|
{
|
|
qDebug() << "SimpleListTableModel::SimpleListTableModel: Создана модель";
|
|
}
|
|
|
|
int SimpleListTableModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
if (parent.isValid())
|
|
return 0;
|
|
return m_rows.size();
|
|
}
|
|
|
|
int SimpleListTableModel::columnCount(const QModelIndex &parent) const
|
|
{
|
|
if (parent.isValid())
|
|
return 0;
|
|
return COLUMN_COUNT;
|
|
}
|
|
|
|
QVariant SimpleListTableModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid() || index.row() >= m_rows.size())
|
|
return QVariant();
|
|
|
|
const SimpleListRowData &row = m_rows[index.row()];
|
|
|
|
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
|
switch (index.column()) {
|
|
case 0: return row.designator.value;
|
|
case 1: return row.name.value;
|
|
case 2: return row.quantity.value;
|
|
default: return QVariant();
|
|
}
|
|
} else if (role == Qt::UserRole) {
|
|
// Возвращаем структуру ячейки для дополнительной информации
|
|
switch (index.column()) {
|
|
case 0: return QVariant::fromValue(row.designator);
|
|
case 1: return QVariant::fromValue(row.name);
|
|
case 2: return QVariant::fromValue(row.quantity);
|
|
default: return QVariant();
|
|
}
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant SimpleListTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (role != Qt::DisplayRole)
|
|
return QVariant();
|
|
|
|
if (orientation == Qt::Horizontal) {
|
|
if (section < DEFAULT_HEADERS.size()) {
|
|
QString header = DEFAULT_HEADERS[section];
|
|
// Для столбца "Кол." (индекс 2) добавляем процент тех запаса
|
|
if (section == 2) {
|
|
header = QString("Кол-во (+%1%)").arg(m_techReservePercent);
|
|
}
|
|
return header;
|
|
}
|
|
} else {
|
|
return section + 1;
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
bool SimpleListTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
|
{
|
|
if (!index.isValid() || index.row() >= m_rows.size() || role != Qt::EditRole)
|
|
return false;
|
|
|
|
if (!canEditRow(index.row())) {
|
|
qDebug() << "SimpleListTableModel::setData: Строка" << index.row() << "не может быть отредактирована";
|
|
return false;
|
|
}
|
|
|
|
SimpleListRowData &row = m_rows[index.row()];
|
|
QString newValue = value.toString();
|
|
|
|
switch (index.column()) {
|
|
case 0:
|
|
row.designator.value = newValue;
|
|
row.designator.isAutoGenerated = false;
|
|
row.designator.isEmpty = newValue.isEmpty();
|
|
break;
|
|
case 1:
|
|
row.name.value = newValue;
|
|
row.name.isAutoGenerated = false;
|
|
row.name.isEmpty = newValue.isEmpty();
|
|
break;
|
|
case 2:
|
|
row.quantity.value = newValue;
|
|
row.quantity.isAutoGenerated = false;
|
|
row.quantity.isEmpty = newValue.isEmpty();
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
// Обновляем флаг isEmpty для строки
|
|
updateRowEmptyStatus(index.row());
|
|
|
|
emit dataChanged(index, index, QVector<int>() << role);
|
|
return true;
|
|
}
|
|
|
|
Qt::ItemFlags SimpleListTableModel::flags(const QModelIndex &index) const
|
|
{
|
|
if (!index.isValid())
|
|
return Qt::NoItemFlags;
|
|
|
|
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
|
|
// Разрешаем редактирование только для редактируемых строк
|
|
if (canEditRow(index.row())) {
|
|
flags |= Qt::ItemIsEditable;
|
|
}
|
|
|
|
return flags;
|
|
}
|
|
|
|
void SimpleListTableModel::addRow(const SimpleListRowData &rowData)
|
|
{
|
|
beginInsertRows(QModelIndex(), m_rows.size(), m_rows.size());
|
|
m_rows.append(rowData);
|
|
endInsertRows();
|
|
emit modelDataChanged();
|
|
}
|
|
|
|
void SimpleListTableModel::insertRow(int position, const SimpleListRowData &rowData)
|
|
{
|
|
if (position < 0 || position > m_rows.size())
|
|
return;
|
|
|
|
beginInsertRows(QModelIndex(), position, position);
|
|
m_rows.insert(position, rowData);
|
|
endInsertRows();
|
|
emit modelDataChanged();
|
|
}
|
|
|
|
void SimpleListTableModel::removeRow(int row)
|
|
{
|
|
if (row < 0 || row >= m_rows.size())
|
|
return;
|
|
|
|
beginRemoveRows(QModelIndex(), row, row);
|
|
m_rows.removeAt(row);
|
|
endRemoveRows();
|
|
emit modelDataChanged();
|
|
}
|
|
|
|
void SimpleListTableModel::clear()
|
|
{
|
|
qDebug() << "SimpleListTableModel::clear: Очищаем таблицу, строк:" << m_rows.size();
|
|
|
|
if (m_rows.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
beginResetModel();
|
|
m_rows.clear();
|
|
endResetModel();
|
|
|
|
emit modelDataChanged();
|
|
}
|
|
|
|
void SimpleListTableModel::setComponents(const QList<ComponentModel*> &components)
|
|
{
|
|
qDebug() << "SimpleListTableModel::setComponents: Получено" << components.size() << "компонентов";
|
|
|
|
// Проверяем компоненты на null
|
|
QList<ComponentModel*> validComponents;
|
|
for (ComponentModel *component : components) {
|
|
if (component) {
|
|
validComponents.append(component);
|
|
}
|
|
}
|
|
|
|
m_components = validComponents;
|
|
qDebug() << "SimpleListTableModel::setComponents: Сохранено" << m_components.size() << "валидных компонентов";
|
|
}
|
|
|
|
QByteArray SimpleListTableModel::saveToDatabase() const
|
|
{
|
|
qDebug() << "SimpleListTableModel::saveToDatabase: Начинаем сохранение в БД";
|
|
qDebug() << "SimpleListTableModel::saveToDatabase: Количество строк:" << m_rows.size();
|
|
|
|
QJsonObject root;
|
|
QJsonArray rowsArray;
|
|
|
|
for (const SimpleListRowData &row : m_rows) {
|
|
QJsonObject rowObj;
|
|
|
|
// Сохраняем данные ячеек
|
|
QJsonObject designatorObj;
|
|
designatorObj["value"] = row.designator.value;
|
|
designatorObj["isAutoGenerated"] = row.designator.isAutoGenerated;
|
|
designatorObj["isEmpty"] = row.designator.isEmpty;
|
|
rowObj["designator"] = designatorObj;
|
|
|
|
QJsonObject nameObj;
|
|
nameObj["value"] = row.name.value;
|
|
nameObj["isAutoGenerated"] = row.name.isAutoGenerated;
|
|
nameObj["isEmpty"] = row.name.isEmpty;
|
|
rowObj["name"] = nameObj;
|
|
|
|
QJsonObject quantityObj;
|
|
quantityObj["value"] = row.quantity.value;
|
|
quantityObj["isAutoGenerated"] = row.quantity.isAutoGenerated;
|
|
quantityObj["isEmpty"] = row.quantity.isEmpty;
|
|
rowObj["quantity"] = quantityObj;
|
|
|
|
rowObj["isEmpty"] = row.isEmpty;
|
|
|
|
rowsArray.append(rowObj);
|
|
}
|
|
|
|
root["rows"] = rowsArray;
|
|
|
|
QJsonDocument doc(root);
|
|
QByteArray result = doc.toJson();
|
|
|
|
qDebug() << "SimpleListTableModel::saveToDatabase: Сохранение завершено, размер данных:" << result.size() << "байт";
|
|
return result;
|
|
}
|
|
|
|
void SimpleListTableModel::loadFromDatabase(const QByteArray &data)
|
|
{
|
|
qDebug() << "SimpleListTableModel::loadFromDatabase: Начинаем загрузку из БД, размер данных:" << data.size();
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
if (!doc.isObject()) {
|
|
qDebug() << "SimpleListTableModel::loadFromDatabase: Ошибка парсинга JSON";
|
|
return;
|
|
}
|
|
|
|
QJsonObject root = doc.object();
|
|
|
|
// Загружаем строки
|
|
clear();
|
|
if (root.contains("rows")) {
|
|
QJsonArray rowsArray = root["rows"].toArray();
|
|
for (const QJsonValue &value : rowsArray) {
|
|
QJsonObject rowObj = value.toObject();
|
|
SimpleListRowData row;
|
|
|
|
if (rowObj.contains("designator")) {
|
|
QJsonObject desObj = rowObj["designator"].toObject();
|
|
row.designator = SimpleListCellData(
|
|
desObj["value"].toString(),
|
|
desObj["isAutoGenerated"].toBool(),
|
|
desObj["isEmpty"].toBool()
|
|
);
|
|
}
|
|
|
|
if (rowObj.contains("name")) {
|
|
QJsonObject nameObj = rowObj["name"].toObject();
|
|
row.name = SimpleListCellData(
|
|
nameObj["value"].toString(),
|
|
nameObj["isAutoGenerated"].toBool(),
|
|
nameObj["isEmpty"].toBool()
|
|
);
|
|
}
|
|
|
|
if (rowObj.contains("quantity")) {
|
|
QJsonObject qtyObj = rowObj["quantity"].toObject();
|
|
row.quantity = SimpleListCellData(
|
|
qtyObj["value"].toString(),
|
|
qtyObj["isAutoGenerated"].toBool(),
|
|
qtyObj["isEmpty"].toBool()
|
|
);
|
|
}
|
|
|
|
row.isEmpty = rowObj["isEmpty"].toBool();
|
|
|
|
addRow(row);
|
|
}
|
|
}
|
|
|
|
qDebug() << "SimpleListTableModel::loadFromDatabase: Загружено строк:" << m_rows.size();
|
|
}
|
|
|
|
QString SimpleListTableModel::getDocumentTitle() const
|
|
{
|
|
return "Список элементов";
|
|
}
|
|
|
|
QString SimpleListTableModel::getDocumentType() const
|
|
{
|
|
return "SimpleList";
|
|
}
|
|
|
|
void SimpleListTableModel::addEmptyRow()
|
|
{
|
|
SimpleListRowData emptyRow = createEmptyRow();
|
|
addRow(emptyRow);
|
|
}
|
|
|
|
void SimpleListTableModel::addEmptyRowAt(int position)
|
|
{
|
|
SimpleListRowData emptyRow = createEmptyRow();
|
|
insertRow(position, emptyRow);
|
|
}
|
|
|
|
SimpleListRowData SimpleListTableModel::createEmptyRow() const
|
|
{
|
|
SimpleListRowData row;
|
|
row.isEmpty = false;
|
|
|
|
row.designator = SimpleListCellData("", false, true);
|
|
row.name = SimpleListCellData("", false, true);
|
|
row.quantity = SimpleListCellData("", false, true);
|
|
|
|
return row;
|
|
}
|
|
|
|
bool SimpleListTableModel::canEditRow(int row) const
|
|
{
|
|
if (row < 0 || row >= m_rows.size())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void SimpleListTableModel::updateRowEmptyStatus(int row)
|
|
{
|
|
if (row < 0 || row >= m_rows.size())
|
|
return;
|
|
|
|
SimpleListRowData &rowData = m_rows[row];
|
|
|
|
// Проверяем, пустые ли все ячейки
|
|
bool allEmpty = rowData.designator.value.isEmpty() &&
|
|
rowData.name.value.isEmpty() &&
|
|
rowData.quantity.value.isEmpty();
|
|
|
|
// Обновляем флаг isEmpty для строки
|
|
if (rowData.isEmpty != allEmpty) {
|
|
rowData.isEmpty = allEmpty;
|
|
}
|
|
}
|
|
|
|
SimpleListCellData SimpleListTableModel::createCellData(const QString &value, bool isAuto, bool isEmpty)
|
|
{
|
|
return SimpleListCellData(value, isAuto, isEmpty);
|
|
}
|
|
|
|
void SimpleListTableModel::setTechReservePercent(int percent)
|
|
{
|
|
if (m_techReservePercent != percent) {
|
|
m_techReservePercent = percent;
|
|
// Обновляем заголовок столбца количества
|
|
emit headerDataChanged(Qt::Horizontal, 2, 2);
|
|
}
|
|
}
|
|
|
|
int SimpleListTableModel::getTechReservePercent() const
|
|
{
|
|
return m_techReservePercent;
|
|
}
|
|
|