#include "simplelisttablemodel.h" #include "componentmodel.h" #include #include #include #include // Регистрируем структуры для работы с 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() << 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 &components) { qDebug() << "SimpleListTableModel::setComponents: Получено" << components.size() << "компонентов"; // Проверяем компоненты на null QList 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; }