Files
GostGenerator/controller/databasecontroller.cpp
T

3354 lines
141 KiB
C++

#include "databasecontroller.h"
#include <QSqlRecord>
#include <QSqlField>
#include <QThread> // Added for QThread::currentThreadId()
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFileInfo> // Added for QFileInfo
// Инициализация статического счетчика
int DataBaseController::s_connectionCounter = 0;
DataBaseController::DataBaseController(QObject *parent)
: QObject(parent)
{
}
DataBaseController::~DataBaseController()
{
if (m_database.isOpen()) {
m_database.close();
}
}
bool DataBaseController::initializeDatabase(const QString &dbPath, const QString &connectionName)
{
// Закрываем предыдущее соединение, если оно открыто
if (m_database.isOpen()) {
m_database.close();
}
// Удаляем предыдущее соединение, если оно существует
if (!connectionName.isEmpty()) {
QSqlDatabase::removeDatabase(connectionName);
}
// Создаем новое соединение с уникальным именем
QString connName = connectionName.isEmpty() ? "default" : connectionName;
m_database = QSqlDatabase::addDatabase("QSQLITE", connName);
m_database.setDatabaseName(dbPath);
if (!m_database.open()) {
setLastError("Не удалось открыть базу данных: " + m_database.lastError().text());
return false;
}
return createTables();
}
bool DataBaseController::createTables()
{
QStringList tables = {
"CREATE TABLE IF NOT EXISTS variants ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" name TEXT UNIQUE NOT NULL"
")",
"CREATE TABLE IF NOT EXISTS components ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" designator TEXT UNIQUE NOT NULL"
")",
"CREATE TABLE IF NOT EXISTS component_properties ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" component_id INTEGER NOT NULL,"
" property_name TEXT NOT NULL,"
" property_value TEXT,"
" FOREIGN KEY(component_id) REFERENCES components(id) ON DELETE CASCADE,"
" UNIQUE(component_id, property_name)"
")",
"CREATE TABLE IF NOT EXISTS component_variants ("
" component_id INTEGER NOT NULL,"
" variant_id INTEGER NOT NULL,"
" is_fitted BOOLEAN DEFAULT 1,"
" PRIMARY KEY(component_id, variant_id),"
" FOREIGN KEY(component_id) REFERENCES components(id) ON DELETE CASCADE,"
" FOREIGN KEY(variant_id) REFERENCES variants(id) ON DELETE CASCADE"
")",
"CREATE TABLE IF NOT EXISTS variant_properties ("
" component_id INTEGER NOT NULL,"
" variant_id INTEGER NOT NULL,"
" property_name TEXT NOT NULL,"
" property_value TEXT,"
" PRIMARY KEY(component_id, variant_id, property_name),"
" FOREIGN KEY(component_id) REFERENCES components(id) ON DELETE CASCADE,"
" FOREIGN KEY(variant_id) REFERENCES variants(id) ON DELETE CASCADE"
")",
"CREATE TABLE IF NOT EXISTS project_params ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" name TEXT UNIQUE NOT NULL,"
" value TEXT"
")",
"CREATE TABLE IF NOT EXISTS project_settings ("
" key TEXT PRIMARY KEY,"
" value TEXT"
")",
"CREATE TABLE IF NOT EXISTS designator_mappings ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" designator TEXT UNIQUE NOT NULL,"
" singular_name TEXT NOT NULL,"
" plural_name TEXT NOT NULL,"
" is_custom BOOLEAN DEFAULT 0"
")",
"CREATE TABLE IF NOT EXISTS title_inscriptions ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" project_name TEXT NOT NULL,"
" field_number INTEGER NOT NULL,"
" field_value TEXT,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" UNIQUE(project_name, field_number)"
")",
"CREATE TABLE IF NOT EXISTS perechen_rows ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" project_name TEXT NOT NULL,"
" row_order INTEGER NOT NULL,"
" position_value TEXT,"
" designation_value TEXT,"
" quantity_value TEXT,"
" note_value TEXT,"
" is_header BOOLEAN DEFAULT 0,"
" is_empty BOOLEAN DEFAULT 0,"
" position_is_auto BOOLEAN DEFAULT 0,"
" designation_is_auto BOOLEAN DEFAULT 0,"
" quantity_is_auto BOOLEAN DEFAULT 0,"
" note_is_auto BOOLEAN DEFAULT 0,"
" cell_stretches TEXT,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP"
")",
"CREATE TABLE IF NOT EXISTS specification_pcb_rows ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" project_name TEXT NOT NULL,"
" row_order INTEGER NOT NULL,"
" format_value TEXT,"
" zone_value TEXT,"
" position_value TEXT,"
" designation_value TEXT,"
" name_value TEXT,"
" quantity_value TEXT,"
" note_value TEXT,"
" is_header BOOLEAN DEFAULT 0,"
" is_empty BOOLEAN DEFAULT 0,"
" format_is_auto BOOLEAN DEFAULT 0,"
" zone_is_auto BOOLEAN DEFAULT 0,"
" position_is_auto BOOLEAN DEFAULT 0,"
" designation_is_auto BOOLEAN DEFAULT 0,"
" name_is_auto BOOLEAN DEFAULT 0,"
" quantity_is_auto BOOLEAN DEFAULT 0,"
" note_is_auto BOOLEAN DEFAULT 0,"
" cell_stretches TEXT,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP"
")",
"CREATE TABLE IF NOT EXISTS specification_rows ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" project_name TEXT NOT NULL,"
" row_order INTEGER NOT NULL,"
" format_value TEXT,"
" zone_value TEXT,"
" position_value TEXT,"
" designation_value TEXT,"
" name_value TEXT,"
" quantity_value TEXT,"
" note_value TEXT,"
" is_header BOOLEAN DEFAULT 0,"
" is_empty BOOLEAN DEFAULT 0,"
" format_is_auto BOOLEAN DEFAULT 0,"
" zone_is_auto BOOLEAN DEFAULT 0,"
" position_is_auto BOOLEAN DEFAULT 0,"
" designation_is_auto BOOLEAN DEFAULT 0,"
" name_is_auto BOOLEAN DEFAULT 0,"
" quantity_is_auto BOOLEAN DEFAULT 0,"
" note_is_auto BOOLEAN DEFAULT 0,"
" cell_stretches TEXT,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP"
")",
"CREATE TABLE IF NOT EXISTS vedomost_rows ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" project_name TEXT NOT NULL,"
" row_order INTEGER NOT NULL,"
" name_value TEXT,"
" product_code_value TEXT,"
" document_code_value TEXT,"
" supplier_value TEXT,"
" where_used_value TEXT,"
" quantity_per_item_value TEXT,"
" quantity_in_set_value TEXT,"
" quantity_for_reg_value TEXT,"
" total_quantity_value TEXT,"
" note_value TEXT,"
" is_header BOOLEAN DEFAULT 0,"
" is_empty BOOLEAN DEFAULT 0,"
" name_is_auto BOOLEAN DEFAULT 0,"
" product_code_is_auto BOOLEAN DEFAULT 0,"
" document_code_is_auto BOOLEAN DEFAULT 0,"
" supplier_is_auto BOOLEAN DEFAULT 0,"
" where_used_is_auto BOOLEAN DEFAULT 0,"
" quantity_per_item_is_auto BOOLEAN DEFAULT 0,"
" quantity_in_set_is_auto BOOLEAN DEFAULT 0,"
" quantity_for_reg_is_auto BOOLEAN DEFAULT 0,"
" total_quantity_is_auto BOOLEAN DEFAULT 0,"
" note_is_auto BOOLEAN DEFAULT 0,"
" row_number INTEGER DEFAULT 0,"
" page_number INTEGER DEFAULT 1,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP"
")",
"CREATE TABLE IF NOT EXISTS pcb_data ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" layer_count INTEGER DEFAULT 0,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP"
")",
"CREATE TABLE IF NOT EXISTS diel_materials ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" pcb_id INTEGER NOT NULL,"
" name TEXT NOT NULL,"
" value TEXT,"
" height REAL DEFAULT 0.0,"
" diel_type INTEGER DEFAULT 0,"
" layer_number INTEGER NOT NULL,"
" created_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,"
" FOREIGN KEY(pcb_id) REFERENCES pcb_data(id) ON DELETE CASCADE,"
" UNIQUE(pcb_id, layer_number)"
")"
};
for (const QString &tableQuery : tables) {
if (!executeQuery(tableQuery)) {
return false;
}
}
// Миграция: добавляем поле cell_stretches в существующие таблицы, если его нет
migrateAddCellStretchesColumn();
return true;
}
void DataBaseController::migrateAddCellStretchesColumn()
{
qDebug() << "DataBaseController::migrateAddCellStretchesColumn: Проверяем наличие поля cell_stretches";
// Список таблиц, в которые нужно добавить поле cell_stretches
QStringList tables = {"perechen_rows", "specification_pcb_rows", "specification_rows", "vedomost_rows"};
for (const QString &tableName : tables) {
// Проверяем, существует ли колонка cell_stretches
QSqlQuery checkQuery = prepareQuery(
QString("PRAGMA table_info(%1)").arg(tableName)
);
bool columnExists = false;
if (checkQuery.exec()) {
while (checkQuery.next()) {
QString columnName = checkQuery.value(1).toString();
if (columnName == "cell_stretches") {
columnExists = true;
break;
}
}
}
if (!columnExists) {
qDebug() << "DataBaseController::migrateAddCellStretchesColumn: Добавляем поле cell_stretches в таблицу" << tableName;
QSqlQuery alterQuery = prepareQuery(
QString("ALTER TABLE %1 ADD COLUMN cell_stretches TEXT").arg(tableName)
);
if (!alterQuery.exec()) {
qDebug() << "DataBaseController::migrateAddCellStretchesColumn: Ошибка добавления колонки в" << tableName << ":" << alterQuery.lastError().text();
} else {
qDebug() << "DataBaseController::migrateAddCellStretchesColumn: Поле cell_stretches успешно добавлено в" << tableName;
}
} else {
qDebug() << "DataBaseController::migrateAddCellStretchesColumn: Поле cell_stretches уже существует в" << tableName;
}
}
}
int DataBaseController::addVariant(const QString &name)
{
QSqlQuery query = prepareQuery("INSERT INTO variants (name) VALUES (?)");
query.addBindValue(name);
if (!query.exec()) {
setLastError("Ошибка добавления варианта: " + query.lastError().text());
return -1;
}
return query.lastInsertId().toInt();
}
bool DataBaseController::removeVariant(int variantId)
{
QSqlQuery query = prepareQuery("DELETE FROM variants WHERE id = ?");
query.addBindValue(variantId);
if (!query.exec()) {
setLastError("Ошибка удаления варианта: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QList<VariantData> DataBaseController::getAllVariants()
{
QList<VariantData> variants;
QSqlQuery query = prepareQuery("SELECT id, name FROM variants");
if (query.exec()) {
while (query.next()) {
VariantData variant;
variant.id = query.value(0).toInt();
variant.name = query.value(1).toString();
variants << variant;
}
}
return variants;
}
int DataBaseController::getVariantId(const QString &name)
{
QSqlQuery query = prepareQuery("SELECT id FROM variants WHERE name = ?");
query.addBindValue(name);
if (query.exec() && query.next()) {
return query.value(0).toInt();
}
return -1;
}
int DataBaseController::addComponent(const QString &designator)
{
QSqlQuery query = prepareQuery("INSERT INTO components (designator) VALUES (?)");
query.addBindValue(designator);
if (!query.exec()) {
setLastError("Ошибка добавления компонента: " + query.lastError().text());
return -1;
}
return query.lastInsertId().toInt();
}
bool DataBaseController::removeComponent(int componentId)
{
QSqlQuery query = prepareQuery("DELETE FROM components WHERE id = ?");
query.addBindValue(componentId);
if (!query.exec()) {
setLastError("Ошибка удаления компонента: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::updateComponentDesignator(int componentId, const QString &designator)
{
QSqlQuery query = prepareQuery("UPDATE components SET designator = ? WHERE id = ?");
query.addBindValue(designator);
query.addBindValue(componentId);
return query.exec();
}
QList<ComponentData> DataBaseController::getAllComponents()
{
QList<ComponentData> components;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return components;
}
QSqlQuery query = prepareQuery("SELECT id, designator FROM components ORDER BY designator");
if (!query.exec()) {
setLastError("Ошибка получения компонентов: " + query.lastError().text());
return components;
}
while (query.next()) {
ComponentData component;
component.id = query.value(0).toInt();
component.designator = query.value(1).toString();
component.baseProperties = getComponentProperties(component.id);
// Получаем варианты для компонента
QSqlQuery variantQuery = prepareQuery(
"SELECT v.id, v.name, cv.is_fitted FROM variants v "
"JOIN component_variants cv ON v.id = cv.variant_id "
"WHERE cv.component_id = ?"
);
variantQuery.addBindValue(component.id);
if (variantQuery.exec()) {
while (variantQuery.next()) {
int variantId = variantQuery.value(0).toInt();
QString variantName = variantQuery.value(1).toString();
bool fitted = variantQuery.value(2).toBool();
component.variantFitted[variantName] = fitted;
// Получаем свойства варианта
QSqlQuery propQuery = prepareQuery(
"SELECT property_name, property_value FROM variant_properties "
"WHERE component_id = ? AND variant_id = ?"
);
propQuery.addBindValue(component.id);
propQuery.addBindValue(variantId);
if (propQuery.exec()) {
QMap<QString, QString> variantProps;
while (propQuery.next()) {
QString propName = propQuery.value(0).toString();
QString propValue = propQuery.value(1).toString();
variantProps[propName] = propValue;
}
component.variantProperties[variantName] = variantProps;
} else {
}
}
} else {
}
components.append(component);
}
return components;
}
ComponentData DataBaseController::getComponent(int componentId)
{
ComponentData component;
QSqlQuery query = prepareQuery("SELECT id, designator FROM components WHERE id = ?");
query.addBindValue(componentId);
if (!query.exec() || !query.next()) {
return component;
}
component.id = query.value(0).toInt();
component.designator = query.value(1).toString();
component.baseProperties = getComponentProperties(componentId);
// Получаем варианты для компонента
QSqlQuery variantQuery = prepareQuery(
"SELECT v.id, v.name, cv.is_fitted FROM variants v "
"JOIN component_variants cv ON v.id = cv.variant_id "
"WHERE cv.component_id = ?"
);
variantQuery.addBindValue(componentId);
if (variantQuery.exec()) {
while (variantQuery.next()) {
int variantId = variantQuery.value(0).toInt();
QString variantName = variantQuery.value(1).toString();
bool fitted = variantQuery.value(2).toBool();
component.variantFitted[variantName] = fitted;
// Получаем свойства варианта
QSqlQuery propQuery = prepareQuery(
"SELECT property_name, property_value FROM variant_properties "
"WHERE component_id = ? AND variant_id = ?"
);
propQuery.addBindValue(componentId);
propQuery.addBindValue(variantId);
if (propQuery.exec()) {
QMap<QString, QString> variantProps;
while (propQuery.next()) {
QString propName = propQuery.value(0).toString();
QString propValue = propQuery.value(1).toString();
variantProps[propName] = propValue;
}
component.variantProperties[variantName] = variantProps;
}
}
}
return component;
}
ComponentData DataBaseController::getComponent(const QString &designator)
{
ComponentData component;
QSqlQuery query = prepareQuery("SELECT id, designator FROM components WHERE designator = ?");
query.addBindValue(designator);
if (!query.exec() || !query.next()) {
return component;
}
component.id = query.value(0).toInt();
component.designator = query.value(1).toString();
component.baseProperties = getComponentProperties(component.id);
// Получаем варианты для компонента
QSqlQuery variantQuery = prepareQuery(
"SELECT v.id, v.name, cv.is_fitted FROM variants v "
"JOIN component_variants cv ON v.id = cv.variant_id "
"WHERE cv.component_id = ?"
);
variantQuery.addBindValue(component.id);
if (variantQuery.exec()) {
while (variantQuery.next()) {
int variantId = variantQuery.value(0).toInt();
QString variantName = variantQuery.value(1).toString();
bool fitted = variantQuery.value(2).toBool();
component.variantFitted[variantName] = fitted;
// Получаем свойства варианта
QSqlQuery propQuery = prepareQuery(
"SELECT property_name, property_value FROM variant_properties "
"WHERE component_id = ? AND variant_id = ?"
);
propQuery.addBindValue(component.id);
propQuery.addBindValue(variantId);
if (propQuery.exec()) {
QMap<QString, QString> variantProps;
while (propQuery.next()) {
QString propName = propQuery.value(0).toString();
QString propValue = propQuery.value(1).toString();
variantProps[propName] = propValue;
}
component.variantProperties[variantName] = variantProps;
}
}
}
return component;
}
bool DataBaseController::saveComponents(const QList<ComponentData> &components)
{
// Очищаем существующие компоненты
if (!executeQuery("DELETE FROM components")) {
return false;
}
// Добавляем новые компоненты
for (const auto& component : components) {
int componentId = addComponent(component.designator);
if (componentId == -1) {
return false;
}
// Сохраняем свойства
for (auto it = component.baseProperties.begin(); it != component.baseProperties.end(); ++it) {
if (!setComponentProperty(componentId, it.key(), it.value())) {
return false;
}
}
// Сохраняем варианты
for (auto it = component.variantFitted.begin(); it != component.variantFitted.end(); ++it) {
int variantId = getVariantId(it.key());
if (variantId != -1) {
setComponentVariantFitted(componentId, variantId, it.value());
}
}
// Сохраняем свойства вариантов
for (auto it = component.variantProperties.begin(); it != component.variantProperties.end(); ++it) {
int variantId = getVariantId(it.key());
if (variantId != -1) {
for (auto propIt = it.value().begin(); propIt != it.value().end(); ++propIt) {
setVariantProperty(componentId, variantId, propIt.key(), propIt.value());
}
}
}
}
return true;
}
QMap<QString, QString> DataBaseController::getComponentProperties(int componentId)
{
QMap<QString, QString> properties;
QSqlQuery query = prepareQuery(
"SELECT property_name, property_value FROM component_properties WHERE component_id = ?"
);
query.addBindValue(componentId);
if (!query.exec()) {
setLastError("Ошибка получения свойств компонента: " + query.lastError().text());
return properties;
}
while (query.next()) {
QString propertyName = query.value(0).toString();
QString propertyValue = query.value(1).toString();
properties[propertyName] = propertyValue;
}
return properties;
}
bool DataBaseController::setComponentProperty(int componentId, const QString &propertyName, const QString &propertyValue)
{
QSqlQuery query = prepareQuery("INSERT OR REPLACE INTO component_properties (component_id, property_name, property_value) VALUES (?, ?, ?)");
query.addBindValue(componentId);
query.addBindValue(propertyName);
query.addBindValue(propertyValue);
return query.exec();
}
bool DataBaseController::removeComponentProperty(int componentId, const QString &propertyName)
{
QSqlQuery query = prepareQuery("DELETE FROM component_properties WHERE component_id = ? AND property_name = ?");
query.addBindValue(componentId);
query.addBindValue(propertyName);
return query.exec();
}
bool DataBaseController::setComponentVariantFitted(int componentId, int variantId, bool fitted)
{
QSqlQuery query = prepareQuery("INSERT OR REPLACE INTO component_variants (component_id, variant_id, is_fitted) VALUES (?, ?, ?)");
query.addBindValue(componentId);
query.addBindValue(variantId);
query.addBindValue(fitted);
return query.exec();
}
bool DataBaseController::setVariantProperty(int componentId, int variantId, const QString &propertyName, const QString &propertyValue)
{
QSqlQuery query = prepareQuery("INSERT OR REPLACE INTO variant_properties (component_id, variant_id, property_name, property_value) VALUES (?, ?, ?, ?)");
query.addBindValue(componentId);
query.addBindValue(variantId);
query.addBindValue(propertyName);
query.addBindValue(propertyValue);
return query.exec();
}
bool DataBaseController::removeVariantProperty(int componentId, int variantId, const QString &propertyName)
{
QSqlQuery query = prepareQuery(
"DELETE FROM variant_properties WHERE component_id = ? AND variant_id = ? AND property_name = ?"
);
query.addBindValue(componentId);
query.addBindValue(variantId);
query.addBindValue(propertyName);
if (!query.exec()) {
setLastError("Ошибка удаления свойства варианта: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QList<ComponentData> DataBaseController::getComponentsForVariant(int variantId)
{
QList<ComponentData> components;
QSqlQuery query = prepareQuery(
"SELECT c.id, c.designator, cv.is_fitted FROM components c "
"JOIN component_variants cv ON c.id = cv.component_id "
"WHERE cv.variant_id = ? "
"ORDER BY c.designator"
);
query.addBindValue(variantId);
if (!query.exec()) {
setLastError("Ошибка получения компонентов для варианта: " + query.lastError().text());
return components;
}
while (query.next()) {
ComponentData component;
component.id = query.value(0).toInt();
component.designator = query.value(1).toString();
bool fitted = query.value(2).toBool();
// Получаем базовые свойства
component.baseProperties = getComponentProperties(component.id);
// Получаем ВСЕ варианты для этого компонента
QSqlQuery allVariantsQuery = prepareQuery(
"SELECT v.id, v.name, cv.is_fitted FROM variants v "
"JOIN component_variants cv ON v.id = cv.variant_id "
"WHERE cv.component_id = ?"
);
allVariantsQuery.addBindValue(component.id);
if (allVariantsQuery.exec()) {
while (allVariantsQuery.next()) {
int currentVariantId = allVariantsQuery.value(0).toInt();
QString currentVariantName = allVariantsQuery.value(1).toString();
bool currentFitted = allVariantsQuery.value(2).toBool();
component.variantFitted[currentVariantName] = currentFitted;
// Получаем свойства для текущего варианта
QSqlQuery propQuery = prepareQuery(
"SELECT property_name, property_value FROM variant_properties "
"WHERE component_id = ? AND variant_id = ?"
);
propQuery.addBindValue(component.id);
propQuery.addBindValue(currentVariantId);
if (propQuery.exec()) {
QMap<QString, QString> variantProps;
while (propQuery.next()) {
QString propName = propQuery.value(0).toString();
QString propValue = propQuery.value(1).toString();
variantProps[propName] = propValue;
}
component.variantProperties[currentVariantName] = variantProps;
}
}
}
components.append(component);
}
return components;
}
QList<ComponentData> DataBaseController::getComponentsForVariant(const QString &variantName)
{
int variantId = getVariantId(variantName);
if (variantId == -1) {
setLastError("Вариант не найден: " + variantName);
return QList<ComponentData>();
}
return getComponentsForVariant(variantId);
}
QStringList DataBaseController::getAllPropertyNames()
{
QStringList propertyNames;
QSqlQuery query = prepareQuery("SELECT DISTINCT property_name FROM component_properties");
if (query.exec()) {
while (query.next()) {
propertyNames << query.value(0).toString();
}
}
return propertyNames;
}
int DataBaseController::addProjectParam(const QString &name, const QString &value)
{
QSqlQuery query = prepareQuery("INSERT INTO project_params (name, value) VALUES (?, ?)");
query.addBindValue(name);
query.addBindValue(value);
if (!query.exec()) {
setLastError("Ошибка добавления параметра проекта: " + query.lastError().text());
return -1;
}
emit dataChanged();
return query.lastInsertId().toInt();
}
bool DataBaseController::updateProjectParam(int paramId, const QString &name, const QString &value)
{
QSqlQuery query = prepareQuery("UPDATE project_params SET name = ?, value = ? WHERE id = ?");
query.addBindValue(name);
query.addBindValue(value);
query.addBindValue(paramId);
if (!query.exec()) {
setLastError("Ошибка обновления параметра проекта: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::removeProjectParam(int paramId)
{
QSqlQuery query = prepareQuery("DELETE FROM project_params WHERE id = ?");
query.addBindValue(paramId);
if (!query.exec()) {
setLastError("Ошибка удаления параметра проекта: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QList<ProjectParamData> DataBaseController::getAllProjectParams()
{
QList<ProjectParamData> params;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
qDebug() << "DataBaseController: База данных не открыта для загрузки параметров проекта";
return params;
}
qDebug() << "DataBaseController: Загружаем параметры проекта из БД";
QSqlQuery query = prepareQuery("SELECT id, name, value FROM project_params ORDER BY name");
if (!query.exec()) {
setLastError("Ошибка получения параметров проекта: " + query.lastError().text());
qDebug() << "DataBaseController: Ошибка запроса параметров проекта:" << query.lastError().text();
return params;
}
while (query.next()) {
ProjectParamData param;
param.id = query.value(0).toInt();
param.name = query.value(1).toString();
param.value = query.value(2).toString();
params.append(param);
qDebug() << "DataBaseController: Загружен параметр проекта:" << param.name << "=" << param.value;
}
qDebug() << "DataBaseController: Всего загружено параметров проекта:" << params.size();
return params;
}
ProjectParamData DataBaseController::getProjectParam(int paramId)
{
ProjectParamData param;
QSqlQuery query = prepareQuery("SELECT id, name, value FROM project_params WHERE id = ?");
query.addBindValue(paramId);
if (!query.exec() || !query.next()) {
return param;
}
param.id = query.value(0).toInt();
param.name = query.value(1).toString();
param.value = query.value(2).toString();
return param;
}
bool DataBaseController::setProjectParam(const QString &name, const QString &value)
{
// Проверяем, существует ли уже параметр с таким именем
QSqlQuery checkQuery = prepareQuery("SELECT id FROM project_params WHERE name = ?");
checkQuery.addBindValue(name);
if (checkQuery.exec() && checkQuery.next()) {
// Обновляем существующий параметр
int paramId = checkQuery.value(0).toInt();
return updateProjectParam(paramId, name, value);
} else {
// Добавляем новый параметр
return addProjectParam(name, value) != -1;
}
}
bool DataBaseController::isDatabaseOpen() const
{
return m_database.isOpen();
}
QString DataBaseController::lastError() const
{
return m_lastError;
}
QString DataBaseController::getDatabasePath() const
{
return m_database.databaseName();
}
bool DataBaseController::executeQuery(const QString &query, const QVariantMap &params)
{
QSqlQuery sqlQuery = prepareQuery(query);
for (auto it = params.begin(); it != params.end(); ++it) {
sqlQuery.addBindValue(it.value());
}
if (!sqlQuery.exec()) {
setLastError("Ошибка выполнения запроса: " + sqlQuery.lastError().text());
return false;
}
return true;
}
QSqlQuery DataBaseController::prepareQuery(const QString &query)
{
QSqlQuery sqlQuery(m_database);
sqlQuery.prepare(query);
return sqlQuery;
}
void DataBaseController::setLastError(const QString &error)
{
m_lastError = error;
emit databaseError(error);
}
void DataBaseController::clearAllData()
{
QSqlQuery query(m_database);
query.exec("DELETE FROM component_properties");
query.exec("DELETE FROM component_variants");
query.exec("DELETE FROM variant_properties");
query.exec("DELETE FROM project_params");
query.exec("DELETE FROM project_settings"); // Added for project settings
query.exec("DELETE FROM diel_materials"); // Added for PCB materials
query.exec("DELETE FROM pcb_data"); // Added for PCB data
query.exec("DELETE FROM components");
query.exec("DELETE FROM variants");
}
// Пакетная вставка компонентов (оптимизация)
bool DataBaseController::beginTransaction()
{
QSqlQuery query(m_database);
return query.exec("BEGIN TRANSACTION");
}
bool DataBaseController::commitTransaction()
{
QSqlQuery query(m_database);
return query.exec("COMMIT");
}
bool DataBaseController::rollbackTransaction()
{
QSqlQuery query(m_database);
return query.exec("ROLLBACK");
}
bool DataBaseController::addComponentBatch(const QString &designator, const QMap<QString, QString> &properties)
{
// Добавляем компонент
QSqlQuery query(m_database);
query.prepare("INSERT INTO components (designator) VALUES (?)");
query.addBindValue(designator);
if (!query.exec()) {
setLastError("Ошибка добавления компонента: " + query.lastError().text());
return false;
}
int componentId = query.lastInsertId().toInt();
// Добавляем свойства пакетно
if (!properties.isEmpty()) {
return addComponentPropertiesBatch(componentId, properties);
}
return true;
}
bool DataBaseController::addComponentPropertiesBatch(int componentId, const QMap<QString, QString> &properties)
{
if (properties.isEmpty()) {
return true;
}
// Подготавливаем пакетный INSERT
QStringList placeholders;
QVariantList values;
for (auto it = properties.begin(); it != properties.end(); ++it) {
placeholders.append("(?, ?, ?)");
values.append(componentId);
values.append(it.key());
values.append(it.value());
}
QString queryStr = QString("INSERT INTO component_properties (component_id, property_name, property_value) VALUES %1")
.arg(placeholders.join(", "));
QSqlQuery query(m_database);
query.prepare(queryStr);
for (const QVariant &value : values) {
query.addBindValue(value);
}
if (!query.exec()) {
setLastError("Ошибка пакетной вставки свойств: " + query.lastError().text());
return false;
}
return true;
}
bool DataBaseController::addComponentVariantsBatch(int componentId, const QStringList &variantNames)
{
if (variantNames.isEmpty()) {
return true;
}
// Получаем ID вариантов
QList<int> variantIds;
for (const QString &variantName : variantNames) {
int variantId = getVariantId(variantName);
if (variantId != -1) {
variantIds.append(variantId);
}
}
if (variantIds.isEmpty()) {
return true;
}
// Подготавливаем пакетный INSERT
QStringList placeholders;
QVariantList values;
for (int variantId : variantIds) {
placeholders.append("(?, ?, 1)");
values.append(componentId);
values.append(variantId);
}
QString queryStr = QString("INSERT INTO component_variants (component_id, variant_id, is_fitted) VALUES %1")
.arg(placeholders.join(", "));
QSqlQuery query(m_database);
query.prepare(queryStr);
for (const QVariant &value : values) {
query.addBindValue(value);
}
if (!query.exec()) {
setLastError("Ошибка пакетной вставки вариантов: " + query.lastError().text());
return false;
}
return true;
}
// Методы для работы с настройками проекта
bool DataBaseController::setProjectSetting(const QString &key, const QString &value)
{
QSqlQuery query = prepareQuery("INSERT OR REPLACE INTO project_settings (key, value) VALUES (?, ?)");
query.addBindValue(key);
query.addBindValue(value);
if (!query.exec()) {
setLastError("Ошибка сохранения настройки проекта: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QString DataBaseController::getProjectSetting(const QString &key, const QString &defaultValue)
{
QSqlQuery query = prepareQuery("SELECT value FROM project_settings WHERE key = ?");
query.addBindValue(key);
if (!query.exec()) {
setLastError("Ошибка получения настройки проекта: " + query.lastError().text());
return defaultValue;
}
if (query.next()) {
return query.value(0).toString();
}
return defaultValue;
}
bool DataBaseController::setProjectSettingList(const QString &key, const QStringList &value)
{
// Сохраняем список как JSON строку
QJsonArray array;
for (const QString &item : value) {
array.append(item);
}
QJsonDocument doc(array);
QString jsonString = doc.toJson(QJsonDocument::Compact);
return setProjectSetting(key, jsonString);
}
QStringList DataBaseController::getProjectSettingList(const QString &key, const QStringList &defaultValue)
{
QString jsonString = getProjectSetting(key, QString());
if (jsonString.isEmpty()) {
return defaultValue;
}
QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8());
if (!doc.isArray()) {
return defaultValue;
}
QStringList result;
QJsonArray array = doc.array();
for (const QJsonValue &value : array) {
result.append(value.toString());
}
return result;
}
// Методы для работы с маппингами дезигнаторов
int DataBaseController::addDesignatorMapping(const QString &designator, const QString &singularName,
const QString &pluralName, bool isCustom)
{
QSqlQuery query = prepareQuery("INSERT INTO designator_mappings (designator, singular_name, plural_name, is_custom) VALUES (?, ?, ?, ?)");
query.addBindValue(designator);
query.addBindValue(singularName);
query.addBindValue(pluralName);
query.addBindValue(isCustom);
if (!query.exec()) {
setLastError("Ошибка добавления маппинга дезигнатора: " + query.lastError().text());
return -1;
}
emit dataChanged();
return query.lastInsertId().toInt();
}
bool DataBaseController::updateDesignatorMapping(int mappingId, const QString &designator,
const QString &singularName, const QString &pluralName, bool isCustom)
{
QSqlQuery query = prepareQuery("UPDATE designator_mappings SET designator = ?, singular_name = ?, plural_name = ?, is_custom = ? WHERE id = ?");
query.addBindValue(designator);
query.addBindValue(singularName);
query.addBindValue(pluralName);
query.addBindValue(isCustom);
query.addBindValue(mappingId);
if (!query.exec()) {
setLastError("Ошибка обновления маппинга дезигнатора: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::removeDesignatorMapping(int mappingId)
{
QSqlQuery query = prepareQuery("DELETE FROM designator_mappings WHERE id = ?");
query.addBindValue(mappingId);
if (!query.exec()) {
setLastError("Ошибка удаления маппинга дезигнатора: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::removeDesignatorMapping(const QString &designator)
{
QSqlQuery query = prepareQuery("DELETE FROM designator_mappings WHERE designator = ?");
query.addBindValue(designator);
if (!query.exec()) {
setLastError("Ошибка удаления маппинга дезигнатора: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QList<DesignatorMappingData> DataBaseController::getAllDesignatorMappings()
{
QList<DesignatorMappingData> mappings;
QSqlQuery query = prepareQuery("SELECT id, designator, singular_name, plural_name, is_custom FROM designator_mappings ORDER BY designator");
if (!query.exec()) {
setLastError("Ошибка получения маппингов дезигнаторов: " + query.lastError().text());
return mappings;
}
while (query.next()) {
DesignatorMappingData mapping;
mapping.id = query.value(0).toInt();
mapping.designator = query.value(1).toString();
mapping.singularName = query.value(2).toString();
mapping.pluralName = query.value(3).toString();
mapping.isCustom = query.value(4).toBool();
mappings.append(mapping);
}
return mappings;
}
DesignatorMappingData DataBaseController::getDesignatorMapping(int mappingId)
{
DesignatorMappingData mapping;
mapping.id = -1;
QSqlQuery query = prepareQuery("SELECT id, designator, singular_name, plural_name, is_custom FROM designator_mappings WHERE id = ?");
query.addBindValue(mappingId);
if (!query.exec()) {
setLastError("Ошибка получения маппинга дезигнатора: " + query.lastError().text());
return mapping;
}
if (query.next()) {
mapping.id = query.value(0).toInt();
mapping.designator = query.value(1).toString();
mapping.singularName = query.value(2).toString();
mapping.pluralName = query.value(3).toString();
mapping.isCustom = query.value(4).toBool();
}
return mapping;
}
DesignatorMappingData DataBaseController::getDesignatorMapping(const QString &designator)
{
DesignatorMappingData mapping;
mapping.id = -1;
QSqlQuery query = prepareQuery("SELECT id, designator, singular_name, plural_name, is_custom FROM designator_mappings WHERE designator = ?");
query.addBindValue(designator);
if (!query.exec()) {
setLastError("Ошибка получения маппинга дезигнатора: " + query.lastError().text());
return mapping;
}
if (query.next()) {
mapping.id = query.value(0).toInt();
mapping.designator = query.value(1).toString();
mapping.singularName = query.value(2).toString();
mapping.pluralName = query.value(3).toString();
mapping.isCustom = query.value(4).toBool();
}
return mapping;
}
bool DataBaseController::saveDesignatorMappings(const QList<DesignatorMappingData> &mappings)
{
// Начинаем транзакцию
if (!beginTransaction()) {
return false;
}
// Очищаем все существующие маппинги
QSqlQuery clearQuery = prepareQuery("DELETE FROM designator_mappings");
if (!clearQuery.exec()) {
setLastError("Ошибка очистки маппингов дезигнаторов: " + clearQuery.lastError().text());
rollbackTransaction();
return false;
}
// Добавляем новые маппинги
for (const auto &mapping : mappings) {
QSqlQuery insertQuery = prepareQuery("INSERT INTO designator_mappings (designator, singular_name, plural_name, is_custom) VALUES (?, ?, ?, ?)");
insertQuery.addBindValue(mapping.designator);
insertQuery.addBindValue(mapping.singularName);
insertQuery.addBindValue(mapping.pluralName);
insertQuery.addBindValue(mapping.isCustom);
if (!insertQuery.exec()) {
setLastError("Ошибка сохранения маппинга дезигнатора: " + insertQuery.lastError().text());
rollbackTransaction();
return false;
}
}
// Подтверждаем транзакцию
if (!commitTransaction()) {
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::clearCustomDesignatorMappings()
{
QSqlQuery query = prepareQuery("DELETE FROM designator_mappings WHERE is_custom = 1");
if (!query.exec()) {
setLastError("Ошибка очистки пользовательских маппингов: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::resetDesignatorMappingsToDefaults()
{
// Сначала очищаем все маппинги
QSqlQuery clearQuery = prepareQuery("DELETE FROM designator_mappings");
if (!clearQuery.exec()) {
setLastError("Ошибка очистки маппингов дезигнаторов: " + clearQuery.lastError().text());
return false;
}
// Добавляем значения по умолчанию
QList<DesignatorMappingData> defaultMappings = {
{1, "A", "Устройство (общее обозначение)", "Устройства (общее обозначение)", false},
{2, "B", "Преобразователи неэлектрических величин в электрические", "Преобразователи неэлектрических величин в электрические", false},
{3, "C", "Конденсаторы", "Конденсаторы", false},
{4, "D", "Схемы интегральные, микросборки", "Схемы интегральные, микросборки", false},
{5, "E", "Элементы разные", "Элементы разные", false},
{6, "F", "Защитные аппараты, предохранители, разрядники", "Защитные аппараты, предохранители, разрядники", false},
{7, "G", "Генераторы, источники питания", "Генераторы, источники питания", false},
{8, "H", "Устройства индикаторные и сигнальные", "Устройства индикаторные и сигнальные", false},
{9, "K", "Реле", "Реле", false},
{10, "L", "Катушки индуктивности, дроссели", "Катушки индуктивности, дроссели", false},
{11, "M", "Двигатели", "Двигатели", false},
{12, "P", "Приборы измерительные", "Приборы измерительные", false},
{13, "Q", "Выключатели и разъединители в силовых цепях", "Выключатели и разъединители в силовых цепях", false},
{14, "R", "Резисторы", "Резисторы", false},
{15, "S", "Устройства коммутационные в цепях управления, сигнализации и измерительных", "Устройства коммутационные в цепях управления, сигнализации и измерительных", false},
{16, "T", "Трансформаторы, автотрансформаторы", "Трансформаторы, автотрансформаторы", false},
{17, "U", "Преобразователи электрических величин в электрические", "Преобразователи электрических величин в электрические", false},
{18, "V", "Приборы электровакуумные и полупроводниковые", "Приборы электровакуумные и полупроводниковые", false},
{19, "W", "Линии и элементы сверхвысоких частот", "Линии и элементы сверхвысоких частот", false},
{20, "X", "Соединения контактные", "Соединения контактные", false},
{21, "Y", "Устройства механические с электромагнитным приводом", "Устройства механические с электромагнитным приводом", false},
{22, "Z", "Ограничители, устройства оконечные, фильтры", "Ограничители, устройства оконечные, фильтры", false},
{23, "BA", "Громкоговорители", "Громкоговорители", false},
{24, "BB", "Преобразователи неэлектрических величин в электрические", "Преобразователи неэлектрических величин в электрические", false},
{25, "BZ", "Преобразователи неэлектрических величин в электрические", "Преобразователи неэлектрических величин в электрические", false}
};
return saveDesignatorMappings(defaultMappings);
}
// Работа с надписями титульного листа
bool DataBaseController::saveTitleInscriptions(const QMap<int, QString> &inscriptions, const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController::saveTitleInscriptions: Сохраняем надписи для проекта:" << projectName;
qDebug() << "DataBaseController::saveTitleInscriptions: Путь к БД:" << m_database.databaseName();
qDebug() << "DataBaseController::saveTitleInscriptions: Количество полей для сохранения:" << inscriptions.size();
// Начинаем транзакцию
if (!beginTransaction()) {
return false;
}
// Удаляем существующие записи для данного проекта
QSqlQuery deleteQuery = prepareQuery("DELETE FROM title_inscriptions WHERE project_name = ?");
deleteQuery.addBindValue(projectName);
if (!deleteQuery.exec()) {
setLastError("Ошибка удаления существующих надписей: " + deleteQuery.lastError().text());
qDebug() << "DataBaseController::saveTitleInscriptions: Ошибка удаления:" << deleteQuery.lastError().text();
rollbackTransaction();
return false;
}
// Добавляем новые записи
int savedCount = 0;
for (auto it = inscriptions.begin(); it != inscriptions.end(); ++it) {
if (!it.value().isEmpty()) { // Сохраняем только непустые значения
QSqlQuery insertQuery = prepareQuery(
"INSERT INTO title_inscriptions (project_name, field_number, field_value) VALUES (?, ?, ?)"
);
insertQuery.addBindValue(projectName);
insertQuery.addBindValue(it.key());
insertQuery.addBindValue(it.value());
if (!insertQuery.exec()) {
setLastError("Ошибка сохранения надписи: " + insertQuery.lastError().text());
qDebug() << "DataBaseController::saveTitleInscriptions: Ошибка сохранения поля" << it.key() << ":" << insertQuery.lastError().text();
rollbackTransaction();
return false;
}
savedCount++;
qDebug() << "DataBaseController::saveTitleInscriptions: Сохранено поле" << it.key() << "=" << it.value();
}
}
// Подтверждаем транзакцию
if (!commitTransaction()) {
return false;
}
qDebug() << "DataBaseController::saveTitleInscriptions: Всего сохранено полей:" << savedCount;
emit dataChanged();
return true;
}
bool DataBaseController::loadTitleInscriptions(QMap<int, QString> &inscriptions, const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
inscriptions.clear();
qDebug() << "DataBaseController::loadTitleInscriptions: Загружаем надписи для проекта:" << projectName;
qDebug() << "DataBaseController::loadTitleInscriptions: Путь к БД:" << m_database.databaseName();
QSqlQuery query = prepareQuery(
"SELECT field_number, field_value FROM title_inscriptions WHERE project_name = ? ORDER BY field_number"
);
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка загрузки надписей: " + query.lastError().text());
qDebug() << "DataBaseController::loadTitleInscriptions: Ошибка выполнения запроса:" << query.lastError().text();
return false;
}
int count = 0;
while (query.next()) {
int fieldNumber = query.value(0).toInt();
QString fieldValue = query.value(1).toString();
inscriptions[fieldNumber] = fieldValue;
count++;
qDebug() << "DataBaseController::loadTitleInscriptions: Загружено поле" << fieldNumber << "=" << fieldValue;
}
qDebug() << "DataBaseController::loadTitleInscriptions: Всего загружено полей:" << count;
return true;
}
bool DataBaseController::deleteTitleInscriptions(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("DELETE FROM title_inscriptions WHERE project_name = ?");
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка удаления надписей: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QStringList DataBaseController::getAvailableTitleInscriptionProjects()
{
QStringList projects;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return projects;
}
QSqlQuery query = prepareQuery("SELECT DISTINCT project_name FROM title_inscriptions ORDER BY project_name");
if (!query.exec()) {
setLastError("Ошибка получения списка проектов: " + query.lastError().text());
return projects;
}
while (query.next()) {
projects << query.value(0).toString();
}
return projects;
}
// Работа с перечнем элементов
bool DataBaseController::savePerechenTable(const QByteArray &tableData, const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController::savePerechenTable: Сохраняем перечень для проекта:" << projectName;
// Начинаем транзакцию
if (!beginTransaction()) {
return false;
}
// Удаляем существующие записи для данного проекта
QSqlQuery deleteQuery = prepareQuery("DELETE FROM perechen_rows WHERE project_name = ?");
deleteQuery.addBindValue(projectName);
if (!deleteQuery.exec()) {
setLastError("Ошибка удаления существующего перечня: " + deleteQuery.lastError().text());
qDebug() << "DataBaseController::savePerechenTable: Ошибка удаления:" << deleteQuery.lastError().text();
rollbackTransaction();
return false;
}
// Парсим JSON данные и сохраняем каждую строку отдельно
QJsonDocument doc = QJsonDocument::fromJson(tableData);
if (!doc.isObject()) {
setLastError("Ошибка парсинга JSON данных перечня");
rollbackTransaction();
return false;
}
QJsonObject root = doc.object();
QJsonArray rowsArray = root["rows"].toArray();
int rowOrder = 0;
for (const QJsonValue &value : rowsArray) {
QJsonObject rowObj = value.toObject();
// Получаем данные ячеек
QJsonObject positionObj = rowObj["position"].toObject();
QJsonObject designationObj = rowObj["designation"].toObject();
QJsonObject quantityObj = rowObj["quantity"].toObject();
QJsonObject noteObj = rowObj["note"].toObject();
// Формируем JSON объект с настройками ячеек (stretch, isHeader, isUnderline)
QJsonObject cellSettingsObj;
QJsonObject positionCellObj;
positionCellObj["stretch"] = positionObj["stretch"].toInt(100);
positionCellObj["isHeader"] = positionObj["isHeader"].toBool(false);
positionCellObj["isUnderline"] = positionObj["isUnderline"].toBool(false);
cellSettingsObj["position"] = positionCellObj;
QJsonObject designationCellObj;
designationCellObj["stretch"] = designationObj["stretch"].toInt(100);
designationCellObj["isHeader"] = designationObj["isHeader"].toBool(false);
designationCellObj["isUnderline"] = designationObj["isUnderline"].toBool(false);
cellSettingsObj["designation"] = designationCellObj;
QJsonObject quantityCellObj;
quantityCellObj["stretch"] = quantityObj["stretch"].toInt(100);
quantityCellObj["isHeader"] = quantityObj["isHeader"].toBool(false);
quantityCellObj["isUnderline"] = quantityObj["isUnderline"].toBool(false);
cellSettingsObj["quantity"] = quantityCellObj;
QJsonObject noteCellObj;
noteCellObj["stretch"] = noteObj["stretch"].toInt(100);
noteCellObj["isHeader"] = noteObj["isHeader"].toBool(false);
noteCellObj["isUnderline"] = noteObj["isUnderline"].toBool(false);
cellSettingsObj["note"] = noteCellObj;
QJsonDocument cellSettingsDoc(cellSettingsObj);
QString cellSettingsJson = cellSettingsDoc.toJson(QJsonDocument::Compact);
// Добавляем строку в БД
QSqlQuery insertQuery = prepareQuery(
"INSERT INTO perechen_rows (project_name, row_order, position_value, designation_value, quantity_value, note_value, "
"is_header, is_empty, position_is_auto, designation_is_auto, quantity_is_auto, note_is_auto, cell_stretches) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
insertQuery.addBindValue(projectName);
insertQuery.addBindValue(rowOrder++);
insertQuery.addBindValue(positionObj["value"].toString());
insertQuery.addBindValue(designationObj["value"].toString());
insertQuery.addBindValue(quantityObj["value"].toString());
insertQuery.addBindValue(noteObj["value"].toString());
insertQuery.addBindValue(rowObj["isHeader"].toBool());
insertQuery.addBindValue(rowObj["isEmpty"].toBool());
insertQuery.addBindValue(positionObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(designationObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(quantityObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(noteObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(cellSettingsJson);
if (!insertQuery.exec()) {
setLastError("Ошибка сохранения строки перечня: " + insertQuery.lastError().text());
qDebug() << "DataBaseController::savePerechenTable: Ошибка сохранения строки" << rowOrder-1 << ":" << insertQuery.lastError().text();
rollbackTransaction();
return false;
}
}
// Подтверждаем транзакцию
if (!commitTransaction()) {
return false;
}
qDebug() << "DataBaseController::savePerechenTable: Перечень успешно сохранен," << rowsArray.size() << "строк";
emit dataChanged();
return true;
}
QByteArray DataBaseController::loadPerechenTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QByteArray();
}
qDebug() << "DataBaseController::loadPerechenTable: Загружаем перечень для проекта:" << projectName;
QSqlQuery query = prepareQuery(
"SELECT row_order, position_value, designation_value, quantity_value, note_value, "
"is_header, is_empty, position_is_auto, designation_is_auto, quantity_is_auto, note_is_auto, cell_stretches "
"FROM perechen_rows WHERE project_name = ? ORDER BY row_order"
);
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка загрузки перечня: " + query.lastError().text());
qDebug() << "DataBaseController::loadPerechenTable: Ошибка выполнения запроса:" << query.lastError().text();
return QByteArray();
}
// Создаем JSON структуру для совместимости с PerechenTableModel
QJsonObject root;
QJsonArray rowsArray;
while (query.next()) {
QJsonObject rowObj;
// Загружаем настройки ячеек (stretch, isHeader, isUnderline) из JSON
QJsonObject cellSettingsObj;
QString cellSettingsJson = query.value(11).toString();
if (!cellSettingsJson.isEmpty()) {
QJsonDocument cellSettingsDoc = QJsonDocument::fromJson(cellSettingsJson.toUtf8());
if (cellSettingsDoc.isObject()) {
cellSettingsObj = cellSettingsDoc.object();
}
}
// Получаем настройки для каждой ячейки (с fallback на старый формат массива)
QJsonObject positionCellObj = cellSettingsObj["position"].toObject();
QJsonObject designationCellObj = cellSettingsObj["designation"].toObject();
QJsonObject quantityCellObj = cellSettingsObj["quantity"].toObject();
QJsonObject noteCellObj = cellSettingsObj["note"].toObject();
// Если старый формат (массив), конвертируем
if (positionCellObj.isEmpty() && cellSettingsJson.startsWith("[")) {
QJsonDocument oldDoc = QJsonDocument::fromJson(cellSettingsJson.toUtf8());
if (oldDoc.isArray()) {
QJsonArray stretchesArray = oldDoc.array();
if (stretchesArray.size() > 0) {
positionCellObj["stretch"] = stretchesArray[0].toInt(100);
positionCellObj["isHeader"] = false;
positionCellObj["isUnderline"] = false;
}
if (stretchesArray.size() > 1) {
designationCellObj["stretch"] = stretchesArray[1].toInt(100);
designationCellObj["isHeader"] = false;
designationCellObj["isUnderline"] = false;
}
if (stretchesArray.size() > 2) {
quantityCellObj["stretch"] = stretchesArray[2].toInt(100);
quantityCellObj["isHeader"] = false;
quantityCellObj["isUnderline"] = false;
}
if (stretchesArray.size() > 3) {
noteCellObj["stretch"] = stretchesArray[3].toInt(100);
noteCellObj["isHeader"] = false;
noteCellObj["isUnderline"] = false;
}
}
}
// Создаем объекты для каждой ячейки
QJsonObject positionObj;
positionObj["value"] = query.value(1).toString();
positionObj["rowNumber"] = query.value(0).toInt();
positionObj["pageNumber"] = 1;
positionObj["isHeader"] = positionCellObj["isHeader"].toBool(query.value(5).toBool());
positionObj["isAutoGenerated"] = query.value(7).toBool();
positionObj["isEmpty"] = query.value(1).toString().isEmpty();
positionObj["stretch"] = positionCellObj["stretch"].toInt(100);
positionObj["isUnderline"] = positionCellObj["isUnderline"].toBool(false);
QJsonObject designationObj;
designationObj["value"] = query.value(2).toString();
designationObj["rowNumber"] = query.value(0).toInt();
designationObj["pageNumber"] = 1;
designationObj["isHeader"] = designationCellObj["isHeader"].toBool(query.value(5).toBool());
designationObj["isAutoGenerated"] = query.value(8).toBool();
designationObj["isEmpty"] = query.value(2).toString().isEmpty();
designationObj["stretch"] = designationCellObj["stretch"].toInt(100);
designationObj["isUnderline"] = designationCellObj["isUnderline"].toBool(false);
QJsonObject quantityObj;
quantityObj["value"] = query.value(3).toString();
quantityObj["rowNumber"] = query.value(0).toInt();
quantityObj["pageNumber"] = 1;
quantityObj["isHeader"] = quantityCellObj["isHeader"].toBool(query.value(5).toBool());
quantityObj["isAutoGenerated"] = query.value(9).toBool();
quantityObj["isEmpty"] = query.value(3).toString().isEmpty();
quantityObj["stretch"] = quantityCellObj["stretch"].toInt(100);
quantityObj["isUnderline"] = quantityCellObj["isUnderline"].toBool(false);
QJsonObject noteObj;
noteObj["value"] = query.value(4).toString();
noteObj["rowNumber"] = query.value(0).toInt();
noteObj["pageNumber"] = 1;
noteObj["isHeader"] = noteCellObj["isHeader"].toBool(query.value(5).toBool());
noteObj["isAutoGenerated"] = query.value(10).toBool();
noteObj["isEmpty"] = query.value(4).toString().isEmpty();
noteObj["stretch"] = noteCellObj["stretch"].toInt(100);
noteObj["isUnderline"] = noteCellObj["isUnderline"].toBool(false);
// Создаем объект строки
rowObj["position"] = positionObj;
rowObj["designation"] = designationObj;
rowObj["quantity"] = quantityObj;
rowObj["note"] = noteObj;
rowObj["isHeader"] = query.value(5).toBool();
rowObj["isEmpty"] = query.value(6).toBool();
rowObj["rowNumber"] = query.value(0).toInt();
rowObj["pageNumber"] = 1;
rowsArray.append(rowObj);
}
root["rows"] = rowsArray;
root["columnMappings"] = QJsonArray::fromStringList(QStringList() << "<Авто>" << "Designator" << "<Пусто>" << "<Пусто>");
root["propertyNames"] = QJsonArray::fromStringList(QStringList() << "Designator");
QJsonDocument doc(root);
QByteArray result = doc.toJson();
qDebug() << "DataBaseController::loadPerechenTable: Загружено" << rowsArray.size() << "строк";
return result;
}
bool DataBaseController::deletePerechenTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("DELETE FROM perechen_rows WHERE project_name = ?");
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка удаления перечня: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QStringList DataBaseController::getAvailablePerechenProjects()
{
QStringList projects;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return projects;
}
QSqlQuery query = prepareQuery("SELECT DISTINCT project_name FROM perechen_rows ORDER BY project_name");
if (!query.exec()) {
setLastError("Ошибка получения списка проектов перечня: " + query.lastError().text());
return projects;
}
while (query.next()) {
projects << query.value(0).toString();
}
return projects;
}
QString DataBaseController::getPerechenTableInfo(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QString();
}
QString actualProjectName = projectName;
if (actualProjectName.isEmpty()) {
actualProjectName = QFileInfo(m_database.databaseName()).baseName();
}
QSqlQuery query = prepareQuery(
"SELECT row_order, position_value, designation_value, quantity_value, note_value, "
"is_header, is_empty, position_is_auto, designation_is_auto, quantity_is_auto, note_is_auto "
"FROM perechen_rows WHERE project_name = ? ORDER BY row_order"
);
query.addBindValue(actualProjectName);
if (!query.exec()) {
setLastError("Ошибка получения информации о перечне: " + query.lastError().text());
return QString();
}
QString info = QString("Информация о перечне для проекта '%1':\n").arg(actualProjectName);
info += QString("Всего строк: %1\n\n").arg(query.size());
while (query.next()) {
int rowOrder = query.value(0).toInt();
QString position = query.value(1).toString();
QString designation = query.value(2).toString();
QString quantity = query.value(3).toString();
QString note = query.value(4).toString();
bool isHeader = query.value(5).toBool();
bool isEmpty = query.value(6).toBool();
bool posAuto = query.value(7).toBool();
bool desAuto = query.value(8).toBool();
bool qtyAuto = query.value(9).toBool();
bool noteAuto = query.value(10).toBool();
info += QString("Строка %1:\n").arg(rowOrder);
info += QString(" Поз.: '%1' (авто: %2)\n").arg(position).arg(posAuto ? "да" : "нет");
info += QString(" Наим.: '%1' (авто: %2)\n").arg(designation).arg(desAuto ? "да" : "нет");
info += QString(" Кол.: '%1' (авто: %2)\n").arg(quantity).arg(qtyAuto ? "да" : "нет");
info += QString(" Прим.: '%1' (авто: %2)\n").arg(note).arg(noteAuto ? "да" : "нет");
info += QString(" Заголовок: %1, Пустая: %2\n\n").arg(isHeader ? "да" : "нет").arg(isEmpty ? "да" : "нет");
}
return info;
}
// Работа со спецификацией платы
bool DataBaseController::saveSpecificationPCBTable(const QByteArray &tableData, const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController::saveSpecificationPCBTable: Сохраняем спецификацию платы для проекта:" << projectName;
// Начинаем транзакцию
if (!beginTransaction()) {
return false;
}
// Удаляем существующие записи для данного проекта
QSqlQuery deleteQuery = prepareQuery("DELETE FROM specification_pcb_rows WHERE project_name = ?");
deleteQuery.addBindValue(projectName);
if (!deleteQuery.exec()) {
setLastError("Ошибка удаления существующей спецификации платы: " + deleteQuery.lastError().text());
qDebug() << "DataBaseController::saveSpecificationPCBTable: Ошибка удаления:" << deleteQuery.lastError().text();
rollbackTransaction();
return false;
}
// Парсим JSON данные и сохраняем каждую строку отдельно
QJsonDocument doc = QJsonDocument::fromJson(tableData);
if (!doc.isObject()) {
setLastError("Ошибка парсинга JSON данных спецификации платы");
rollbackTransaction();
return false;
}
QJsonObject root = doc.object();
QJsonArray rowsArray = root["rows"].toArray();
int rowOrder = 0;
for (const QJsonValue &value : rowsArray) {
QJsonObject rowObj = value.toObject();
// Получаем данные ячеек для 7 столбцов
QJsonObject formatObj = rowObj["format"].toObject();
QJsonObject zoneObj = rowObj["zone"].toObject();
QJsonObject positionObj = rowObj["position"].toObject();
QJsonObject designationObj = rowObj["designation"].toObject();
QJsonObject nameObj = rowObj["name"].toObject();
QJsonObject quantityObj = rowObj["quantity"].toObject();
QJsonObject noteObj = rowObj["note"].toObject();
// Формируем JSON объект с настройками ячеек (stretch, isHeader, isUnderline)
QJsonObject cellSettingsObj;
QJsonObject formatCellObj;
formatCellObj["stretch"] = formatObj["stretch"].toInt(100);
formatCellObj["isHeader"] = formatObj["isHeader"].toBool(false);
formatCellObj["isUnderline"] = formatObj["isUnderline"].toBool(false);
cellSettingsObj["format"] = formatCellObj;
QJsonObject zoneCellObj;
zoneCellObj["stretch"] = zoneObj["stretch"].toInt(100);
zoneCellObj["isHeader"] = zoneObj["isHeader"].toBool(false);
zoneCellObj["isUnderline"] = zoneObj["isUnderline"].toBool(false);
cellSettingsObj["zone"] = zoneCellObj;
QJsonObject positionCellObj;
positionCellObj["stretch"] = positionObj["stretch"].toInt(100);
positionCellObj["isHeader"] = positionObj["isHeader"].toBool(false);
positionCellObj["isUnderline"] = positionObj["isUnderline"].toBool(false);
cellSettingsObj["position"] = positionCellObj;
QJsonObject designationCellObj;
designationCellObj["stretch"] = designationObj["stretch"].toInt(100);
designationCellObj["isHeader"] = designationObj["isHeader"].toBool(false);
designationCellObj["isUnderline"] = designationObj["isUnderline"].toBool(false);
cellSettingsObj["designation"] = designationCellObj;
QJsonObject nameCellObj;
nameCellObj["stretch"] = nameObj["stretch"].toInt(100);
nameCellObj["isHeader"] = nameObj["isHeader"].toBool(false);
nameCellObj["isUnderline"] = nameObj["isUnderline"].toBool(false);
cellSettingsObj["name"] = nameCellObj;
QJsonObject quantityCellObj;
quantityCellObj["stretch"] = quantityObj["stretch"].toInt(100);
quantityCellObj["isHeader"] = quantityObj["isHeader"].toBool(false);
quantityCellObj["isUnderline"] = quantityObj["isUnderline"].toBool(false);
cellSettingsObj["quantity"] = quantityCellObj;
QJsonObject noteCellObj;
noteCellObj["stretch"] = noteObj["stretch"].toInt(100);
noteCellObj["isHeader"] = noteObj["isHeader"].toBool(false);
noteCellObj["isUnderline"] = noteObj["isUnderline"].toBool(false);
cellSettingsObj["note"] = noteCellObj;
QJsonDocument cellSettingsDoc(cellSettingsObj);
QString cellSettingsJson = cellSettingsDoc.toJson(QJsonDocument::Compact);
// Добавляем строку в БД
QSqlQuery insertQuery = prepareQuery(
"INSERT INTO specification_pcb_rows (project_name, row_order, format_value, zone_value, position_value, "
"designation_value, name_value, quantity_value, note_value, is_header, is_empty, "
"format_is_auto, zone_is_auto, position_is_auto, designation_is_auto, name_is_auto, quantity_is_auto, note_is_auto, cell_stretches) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
insertQuery.addBindValue(projectName);
insertQuery.addBindValue(rowOrder++);
insertQuery.addBindValue(formatObj["value"].toString());
insertQuery.addBindValue(zoneObj["value"].toString());
insertQuery.addBindValue(positionObj["value"].toString());
insertQuery.addBindValue(designationObj["value"].toString());
insertQuery.addBindValue(nameObj["value"].toString());
insertQuery.addBindValue(quantityObj["value"].toString());
insertQuery.addBindValue(noteObj["value"].toString());
insertQuery.addBindValue(rowObj["isHeader"].toBool());
insertQuery.addBindValue(rowObj["isEmpty"].toBool());
insertQuery.addBindValue(formatObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(zoneObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(positionObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(designationObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(nameObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(quantityObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(noteObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(cellSettingsJson);
if (!insertQuery.exec()) {
setLastError("Ошибка сохранения строки спецификации платы: " + insertQuery.lastError().text());
qDebug() << "DataBaseController::saveSpecificationPCBTable: Ошибка сохранения строки" << rowOrder-1 << ":" << insertQuery.lastError().text();
rollbackTransaction();
return false;
}
}
// Подтверждаем транзакцию
if (!commitTransaction()) {
return false;
}
qDebug() << "DataBaseController::saveSpecificationPCBTable: Спецификация платы успешно сохранена," << rowsArray.size() << "строк";
emit dataChanged();
return true;
}
QByteArray DataBaseController::loadSpecificationPCBTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QByteArray();
}
qDebug() << "DataBaseController::loadSpecificationPCBTable: Загружаем спецификацию платы для проекта:" << projectName;
QSqlQuery query = prepareQuery(
"SELECT row_order, format_value, zone_value, position_value, designation_value, name_value, quantity_value, note_value, "
"is_header, is_empty, format_is_auto, zone_is_auto, position_is_auto, designation_is_auto, name_is_auto, quantity_is_auto, note_is_auto, cell_stretches "
"FROM specification_pcb_rows WHERE project_name = ? ORDER BY row_order"
);
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка загрузки спецификации платы: " + query.lastError().text());
qDebug() << "DataBaseController::loadSpecificationPCBTable: Ошибка выполнения запроса:" << query.lastError().text();
return QByteArray();
}
// Создаем JSON структуру для совместимости с SpecificationPCBTableModel
QJsonObject root;
QJsonArray rowsArray;
while (query.next()) {
QJsonObject rowObj;
// Загружаем настройки ячеек (stretch, isHeader, isUnderline) из JSON
QJsonObject cellSettingsObj;
QString cellSettingsJson = query.value(17).toString();
if (!cellSettingsJson.isEmpty()) {
QJsonDocument cellSettingsDoc = QJsonDocument::fromJson(cellSettingsJson.toUtf8());
if (cellSettingsDoc.isObject()) {
cellSettingsObj = cellSettingsDoc.object();
}
}
// Получаем настройки для каждой ячейки
QJsonObject formatCellObj = cellSettingsObj["format"].toObject();
QJsonObject zoneCellObj = cellSettingsObj["zone"].toObject();
QJsonObject positionCellObj = cellSettingsObj["position"].toObject();
QJsonObject designationCellObj = cellSettingsObj["designation"].toObject();
QJsonObject nameCellObj = cellSettingsObj["name"].toObject();
QJsonObject quantityCellObj = cellSettingsObj["quantity"].toObject();
QJsonObject noteCellObj = cellSettingsObj["note"].toObject();
// Создаем объекты для каждой ячейки (7 столбцов)
QJsonObject formatObj;
formatObj["value"] = query.value(1).toString();
formatObj["rowNumber"] = query.value(0).toInt();
formatObj["pageNumber"] = 1;
formatObj["isHeader"] = formatCellObj["isHeader"].toBool(query.value(8).toBool());
formatObj["isAutoGenerated"] = query.value(10).toBool();
formatObj["isEmpty"] = query.value(1).toString().isEmpty();
formatObj["stretch"] = formatCellObj["stretch"].toInt(100);
formatObj["isUnderline"] = formatCellObj["isUnderline"].toBool(false);
QJsonObject zoneObj;
zoneObj["value"] = query.value(2).toString();
zoneObj["rowNumber"] = query.value(0).toInt();
zoneObj["pageNumber"] = 1;
zoneObj["isHeader"] = zoneCellObj["isHeader"].toBool(query.value(8).toBool());
zoneObj["isAutoGenerated"] = query.value(11).toBool();
zoneObj["isEmpty"] = query.value(2).toString().isEmpty();
zoneObj["stretch"] = zoneCellObj["stretch"].toInt(100);
zoneObj["isUnderline"] = zoneCellObj["isUnderline"].toBool(false);
QJsonObject positionObj;
positionObj["value"] = query.value(3).toString();
positionObj["rowNumber"] = query.value(0).toInt();
positionObj["pageNumber"] = 1;
positionObj["isHeader"] = positionCellObj["isHeader"].toBool(query.value(8).toBool());
positionObj["isAutoGenerated"] = query.value(12).toBool();
positionObj["isEmpty"] = query.value(3).toString().isEmpty();
positionObj["stretch"] = positionCellObj["stretch"].toInt(100);
positionObj["isUnderline"] = positionCellObj["isUnderline"].toBool(false);
QJsonObject designationObj;
designationObj["value"] = query.value(4).toString();
designationObj["rowNumber"] = query.value(0).toInt();
designationObj["pageNumber"] = 1;
designationObj["isHeader"] = designationCellObj["isHeader"].toBool(query.value(8).toBool());
designationObj["isAutoGenerated"] = query.value(13).toBool();
designationObj["isEmpty"] = query.value(4).toString().isEmpty();
designationObj["stretch"] = designationCellObj["stretch"].toInt(100);
designationObj["isUnderline"] = designationCellObj["isUnderline"].toBool(false);
QJsonObject nameObj;
nameObj["value"] = query.value(5).toString();
nameObj["rowNumber"] = query.value(0).toInt();
nameObj["pageNumber"] = 1;
nameObj["isHeader"] = nameCellObj["isHeader"].toBool(query.value(8).toBool());
nameObj["isAutoGenerated"] = query.value(14).toBool();
nameObj["isEmpty"] = query.value(5).toString().isEmpty();
nameObj["stretch"] = nameCellObj["stretch"].toInt(100);
nameObj["isUnderline"] = nameCellObj["isUnderline"].toBool(false);
QJsonObject quantityObj;
quantityObj["value"] = query.value(6).toString();
quantityObj["rowNumber"] = query.value(0).toInt();
quantityObj["pageNumber"] = 1;
quantityObj["isHeader"] = quantityCellObj["isHeader"].toBool(query.value(8).toBool());
quantityObj["isAutoGenerated"] = query.value(15).toBool();
quantityObj["isEmpty"] = query.value(6).toString().isEmpty();
quantityObj["stretch"] = quantityCellObj["stretch"].toInt(100);
quantityObj["isUnderline"] = quantityCellObj["isUnderline"].toBool(false);
QJsonObject noteObj;
noteObj["value"] = query.value(7).toString();
noteObj["rowNumber"] = query.value(0).toInt();
noteObj["pageNumber"] = 1;
noteObj["isHeader"] = noteCellObj["isHeader"].toBool(query.value(8).toBool());
noteObj["isAutoGenerated"] = query.value(16).toBool();
noteObj["isEmpty"] = query.value(7).toString().isEmpty();
noteObj["stretch"] = noteCellObj["stretch"].toInt(100);
noteObj["isUnderline"] = noteCellObj["isUnderline"].toBool(false);
// Создаем объект строки
rowObj["format"] = formatObj;
rowObj["zone"] = zoneObj;
rowObj["position"] = positionObj;
rowObj["designation"] = designationObj;
rowObj["name"] = nameObj;
rowObj["quantity"] = quantityObj;
rowObj["note"] = noteObj;
rowObj["isHeader"] = query.value(8).toBool();
rowObj["isEmpty"] = query.value(9).toBool();
rowObj["rowNumber"] = query.value(0).toInt();
rowObj["pageNumber"] = 1;
rowsArray.append(rowObj);
}
root["rows"] = rowsArray;
root["columnMappings"] = QJsonArray::fromStringList(QStringList() << "Format" << "Zone" << "Position" << "Designator" << "Name" << "Quantity" << "Note");
root["propertyNames"] = QJsonArray::fromStringList(QStringList() << "Designator" << "Format" << "Zone" << "Position");
QJsonDocument doc(root);
QByteArray result = doc.toJson();
qDebug() << "DataBaseController::loadSpecificationPCBTable: Загружено" << rowsArray.size() << "строк";
return result;
}
bool DataBaseController::deleteSpecificationPCBTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("DELETE FROM specification_pcb_rows WHERE project_name = ?");
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка удаления спецификации платы: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QStringList DataBaseController::getAvailableSpecificationPCBProjects()
{
QStringList projects;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return projects;
}
QSqlQuery query = prepareQuery("SELECT DISTINCT project_name FROM specification_pcb_rows ORDER BY project_name");
if (!query.exec()) {
setLastError("Ошибка получения списка проектов спецификации платы: " + query.lastError().text());
return projects;
}
while (query.next()) {
projects << query.value(0).toString();
}
return projects;
}
QString DataBaseController::getSpecificationPCBTableInfo(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QString();
}
QString actualProjectName = projectName;
if (actualProjectName.isEmpty()) {
actualProjectName = QFileInfo(m_database.databaseName()).baseName();
}
QSqlQuery query = prepareQuery(
"SELECT row_order, format_value, zone_value, position_value, designation_value, name_value, quantity_value, note_value, "
"is_header, is_empty, format_is_auto, zone_is_auto, position_is_auto, designation_is_auto, name_is_auto, quantity_is_auto, note_is_auto "
"FROM specification_pcb_rows WHERE project_name = ? ORDER BY row_order"
);
query.addBindValue(actualProjectName);
if (!query.exec()) {
setLastError("Ошибка получения информации о спецификации платы: " + query.lastError().text());
return QString();
}
QString info = QString("Информация о спецификации платы для проекта '%1':\n").arg(actualProjectName);
info += QString("Всего строк: %1\n\n").arg(query.size());
while (query.next()) {
int rowOrder = query.value(0).toInt();
QString format = query.value(1).toString();
QString zone = query.value(2).toString();
QString position = query.value(3).toString();
QString designation = query.value(4).toString();
QString name = query.value(5).toString();
QString quantity = query.value(6).toString();
QString note = query.value(7).toString();
bool isHeader = query.value(8).toBool();
bool isEmpty = query.value(9).toBool();
bool formatAuto = query.value(10).toBool();
bool zoneAuto = query.value(11).toBool();
bool posAuto = query.value(12).toBool();
bool desAuto = query.value(13).toBool();
bool nameAuto = query.value(14).toBool();
bool qtyAuto = query.value(15).toBool();
bool noteAuto = query.value(16).toBool();
info += QString("Строка %1:\n").arg(rowOrder);
info += QString(" Формат: '%1' (авто: %2)\n").arg(format).arg(formatAuto ? "да" : "нет");
info += QString(" Зона: '%1' (авто: %2)\n").arg(zone).arg(zoneAuto ? "да" : "нет");
info += QString(" Поз.: '%1' (авто: %2)\n").arg(position).arg(posAuto ? "да" : "нет");
info += QString(" Обозн.: '%1' (авто: %2)\n").arg(designation).arg(desAuto ? "да" : "нет");
info += QString(" Наим.: '%1' (авто: %2)\n").arg(name).arg(nameAuto ? "да" : "нет");
info += QString(" Кол.: '%1' (авто: %2)\n").arg(quantity).arg(qtyAuto ? "да" : "нет");
info += QString(" Прим.: '%1' (авто: %2)\n").arg(note).arg(noteAuto ? "да" : "нет");
info += QString(" Заголовок: %1, Пустая: %2\n\n").arg(isHeader ? "да" : "нет").arg(isEmpty ? "да" : "нет");
}
return info;
}
// Работа со спецификацией материалов
bool DataBaseController::saveSpecificationTable(const QByteArray &tableData, const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController::saveSpecificationTable: Сохраняем спецификацию для проекта:" << projectName;
// Начинаем транзакцию
if (!beginTransaction()) {
return false;
}
// Удаляем существующие записи для данного проекта
QSqlQuery deleteQuery = prepareQuery("DELETE FROM specification_rows WHERE project_name = ?");
deleteQuery.addBindValue(projectName);
if (!deleteQuery.exec()) {
setLastError("Ошибка удаления существующей спецификации: " + deleteQuery.lastError().text());
qDebug() << "DataBaseController::saveSpecificationTable: Ошибка удаления:" << deleteQuery.lastError().text();
rollbackTransaction();
return false;
}
// Парсим JSON данные и сохраняем каждую строку отдельно
QJsonDocument doc = QJsonDocument::fromJson(tableData);
if (!doc.isObject()) {
setLastError("Ошибка парсинга JSON данных спецификации");
rollbackTransaction();
return false;
}
QJsonObject root = doc.object();
QJsonArray rowsArray = root["rows"].toArray();
int rowOrder = 0;
for (const QJsonValue &value : rowsArray) {
QJsonObject rowObj = value.toObject();
// Получаем данные ячеек для 7 столбцов
QJsonObject formatObj = rowObj["format"].toObject();
QJsonObject zoneObj = rowObj["zone"].toObject();
QJsonObject positionObj = rowObj["position"].toObject();
QJsonObject designationObj = rowObj["designation"].toObject();
QJsonObject nameObj = rowObj["name"].toObject();
QJsonObject quantityObj = rowObj["quantity"].toObject();
QJsonObject noteObj = rowObj["note"].toObject();
// Формируем JSON объект с настройками ячеек (stretch, isHeader, isUnderline)
QJsonObject cellSettingsObj;
QJsonObject formatCellObj;
formatCellObj["stretch"] = formatObj["stretch"].toInt(100);
formatCellObj["isHeader"] = formatObj["isHeader"].toBool(false);
formatCellObj["isUnderline"] = formatObj["isUnderline"].toBool(false);
cellSettingsObj["format"] = formatCellObj;
QJsonObject zoneCellObj;
zoneCellObj["stretch"] = zoneObj["stretch"].toInt(100);
zoneCellObj["isHeader"] = zoneObj["isHeader"].toBool(false);
zoneCellObj["isUnderline"] = zoneObj["isUnderline"].toBool(false);
cellSettingsObj["zone"] = zoneCellObj;
QJsonObject positionCellObj;
positionCellObj["stretch"] = positionObj["stretch"].toInt(100);
positionCellObj["isHeader"] = positionObj["isHeader"].toBool(false);
positionCellObj["isUnderline"] = positionObj["isUnderline"].toBool(false);
cellSettingsObj["position"] = positionCellObj;
QJsonObject designationCellObj;
designationCellObj["stretch"] = designationObj["stretch"].toInt(100);
designationCellObj["isHeader"] = designationObj["isHeader"].toBool(false);
designationCellObj["isUnderline"] = designationObj["isUnderline"].toBool(false);
cellSettingsObj["designation"] = designationCellObj;
QJsonObject nameCellObj;
nameCellObj["stretch"] = nameObj["stretch"].toInt(100);
nameCellObj["isHeader"] = nameObj["isHeader"].toBool(false);
nameCellObj["isUnderline"] = nameObj["isUnderline"].toBool(false);
cellSettingsObj["name"] = nameCellObj;
QJsonObject quantityCellObj;
quantityCellObj["stretch"] = quantityObj["stretch"].toInt(100);
quantityCellObj["isHeader"] = quantityObj["isHeader"].toBool(false);
quantityCellObj["isUnderline"] = quantityObj["isUnderline"].toBool(false);
cellSettingsObj["quantity"] = quantityCellObj;
QJsonObject noteCellObj;
noteCellObj["stretch"] = noteObj["stretch"].toInt(100);
noteCellObj["isHeader"] = noteObj["isHeader"].toBool(false);
noteCellObj["isUnderline"] = noteObj["isUnderline"].toBool(false);
cellSettingsObj["note"] = noteCellObj;
QJsonDocument cellSettingsDoc(cellSettingsObj);
QString cellSettingsJson = cellSettingsDoc.toJson(QJsonDocument::Compact);
// Добавляем строку в БД
QSqlQuery insertQuery = prepareQuery(
"INSERT INTO specification_rows (project_name, row_order, format_value, zone_value, position_value, "
"designation_value, name_value, quantity_value, note_value, is_header, is_empty, "
"format_is_auto, zone_is_auto, position_is_auto, designation_is_auto, name_is_auto, quantity_is_auto, note_is_auto, cell_stretches) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
insertQuery.addBindValue(projectName);
insertQuery.addBindValue(rowOrder++);
insertQuery.addBindValue(formatObj["value"].toString());
insertQuery.addBindValue(zoneObj["value"].toString());
insertQuery.addBindValue(positionObj["value"].toString());
insertQuery.addBindValue(designationObj["value"].toString());
insertQuery.addBindValue(nameObj["value"].toString());
insertQuery.addBindValue(quantityObj["value"].toString());
insertQuery.addBindValue(noteObj["value"].toString());
insertQuery.addBindValue(rowObj["isHeader"].toBool());
insertQuery.addBindValue(rowObj["isEmpty"].toBool());
insertQuery.addBindValue(formatObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(zoneObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(positionObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(designationObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(nameObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(quantityObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(noteObj["isAutoGenerated"].toBool());
insertQuery.addBindValue(cellSettingsJson);
if (!insertQuery.exec()) {
setLastError("Ошибка сохранения строки спецификации: " + insertQuery.lastError().text());
qDebug() << "DataBaseController::saveSpecificationTable: Ошибка сохранения строки" << rowOrder-1 << ":" << insertQuery.lastError().text();
rollbackTransaction();
return false;
}
}
// Подтверждаем транзакцию
if (!commitTransaction()) {
return false;
}
qDebug() << "DataBaseController::saveSpecificationTable: Спецификация успешно сохранена," << rowsArray.size() << "строк";
emit dataChanged();
return true;
}
QByteArray DataBaseController::loadSpecificationTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QByteArray();
}
qDebug() << "DataBaseController::loadSpecificationTable: Загружаем спецификацию для проекта:" << projectName;
QSqlQuery query = prepareQuery(
"SELECT row_order, format_value, zone_value, position_value, designation_value, name_value, quantity_value, note_value, "
"is_header, is_empty, format_is_auto, zone_is_auto, position_is_auto, designation_is_auto, name_is_auto, quantity_is_auto, note_is_auto, cell_stretches "
"FROM specification_rows WHERE project_name = ? ORDER BY row_order"
);
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка загрузки спецификации: " + query.lastError().text());
qDebug() << "DataBaseController::loadSpecificationTable: Ошибка выполнения запроса:" << query.lastError().text();
return QByteArray();
}
// Создаем JSON структуру для совместимости с SpecificationTableModel
QJsonObject root;
QJsonArray rowsArray;
while (query.next()) {
QJsonObject rowObj;
// Загружаем настройки ячеек (stretch, isHeader, isUnderline) из JSON
QJsonObject cellSettingsObj;
QString cellSettingsJson = query.value(17).toString();
if (!cellSettingsJson.isEmpty()) {
QJsonDocument cellSettingsDoc = QJsonDocument::fromJson(cellSettingsJson.toUtf8());
if (cellSettingsDoc.isObject()) {
cellSettingsObj = cellSettingsDoc.object();
}
}
// Получаем настройки для каждой ячейки
QJsonObject formatCellObj = cellSettingsObj["format"].toObject();
QJsonObject zoneCellObj = cellSettingsObj["zone"].toObject();
QJsonObject positionCellObj = cellSettingsObj["position"].toObject();
QJsonObject designationCellObj = cellSettingsObj["designation"].toObject();
QJsonObject nameCellObj = cellSettingsObj["name"].toObject();
QJsonObject quantityCellObj = cellSettingsObj["quantity"].toObject();
QJsonObject noteCellObj = cellSettingsObj["note"].toObject();
// Создаем объекты для каждой ячейки (7 столбцов)
QJsonObject formatObj;
formatObj["value"] = query.value(1).toString();
formatObj["rowNumber"] = query.value(0).toInt();
formatObj["pageNumber"] = 1;
formatObj["isHeader"] = formatCellObj["isHeader"].toBool(query.value(8).toBool());
formatObj["isAutoGenerated"] = query.value(10).toBool();
formatObj["isEmpty"] = query.value(1).toString().isEmpty();
formatObj["stretch"] = formatCellObj["stretch"].toInt(100);
formatObj["isUnderline"] = formatCellObj["isUnderline"].toBool(false);
QJsonObject zoneObj;
zoneObj["value"] = query.value(2).toString();
zoneObj["rowNumber"] = query.value(0).toInt();
zoneObj["pageNumber"] = 1;
zoneObj["isHeader"] = zoneCellObj["isHeader"].toBool(query.value(8).toBool());
zoneObj["isAutoGenerated"] = query.value(11).toBool();
zoneObj["isEmpty"] = query.value(2).toString().isEmpty();
zoneObj["stretch"] = zoneCellObj["stretch"].toInt(100);
zoneObj["isUnderline"] = zoneCellObj["isUnderline"].toBool(false);
QJsonObject positionObj;
positionObj["value"] = query.value(3).toString();
positionObj["rowNumber"] = query.value(0).toInt();
positionObj["pageNumber"] = 1;
positionObj["isHeader"] = positionCellObj["isHeader"].toBool(query.value(8).toBool());
positionObj["isAutoGenerated"] = query.value(12).toBool();
positionObj["isEmpty"] = query.value(3).toString().isEmpty();
positionObj["stretch"] = positionCellObj["stretch"].toInt(100);
positionObj["isUnderline"] = positionCellObj["isUnderline"].toBool(false);
QJsonObject designationObj;
designationObj["value"] = query.value(4).toString();
designationObj["rowNumber"] = query.value(0).toInt();
designationObj["pageNumber"] = 1;
designationObj["isHeader"] = designationCellObj["isHeader"].toBool(query.value(8).toBool());
designationObj["isAutoGenerated"] = query.value(13).toBool();
designationObj["isEmpty"] = query.value(4).toString().isEmpty();
designationObj["stretch"] = designationCellObj["stretch"].toInt(100);
designationObj["isUnderline"] = designationCellObj["isUnderline"].toBool(false);
QJsonObject nameObj;
nameObj["value"] = query.value(5).toString();
nameObj["rowNumber"] = query.value(0).toInt();
nameObj["pageNumber"] = 1;
nameObj["isHeader"] = nameCellObj["isHeader"].toBool(query.value(8).toBool());
nameObj["isAutoGenerated"] = query.value(14).toBool();
nameObj["isEmpty"] = query.value(5).toString().isEmpty();
nameObj["stretch"] = nameCellObj["stretch"].toInt(100);
nameObj["isUnderline"] = nameCellObj["isUnderline"].toBool(false);
QJsonObject quantityObj;
quantityObj["value"] = query.value(6).toString();
quantityObj["rowNumber"] = query.value(0).toInt();
quantityObj["pageNumber"] = 1;
quantityObj["isHeader"] = quantityCellObj["isHeader"].toBool(query.value(8).toBool());
quantityObj["isAutoGenerated"] = query.value(15).toBool();
quantityObj["isEmpty"] = query.value(6).toString().isEmpty();
quantityObj["stretch"] = quantityCellObj["stretch"].toInt(100);
quantityObj["isUnderline"] = quantityCellObj["isUnderline"].toBool(false);
QJsonObject noteObj;
noteObj["value"] = query.value(7).toString();
noteObj["rowNumber"] = query.value(0).toInt();
noteObj["pageNumber"] = 1;
noteObj["isHeader"] = noteCellObj["isHeader"].toBool(query.value(8).toBool());
noteObj["isAutoGenerated"] = query.value(16).toBool();
noteObj["isEmpty"] = query.value(7).toString().isEmpty();
noteObj["stretch"] = noteCellObj["stretch"].toInt(100);
noteObj["isUnderline"] = noteCellObj["isUnderline"].toBool(false);
// Создаем объект строки
rowObj["format"] = formatObj;
rowObj["zone"] = zoneObj;
rowObj["position"] = positionObj;
rowObj["designation"] = designationObj;
rowObj["name"] = nameObj;
rowObj["quantity"] = quantityObj;
rowObj["note"] = noteObj;
rowObj["isHeader"] = query.value(8).toBool();
rowObj["isEmpty"] = query.value(9).toBool();
rowObj["rowNumber"] = query.value(0).toInt();
rowObj["pageNumber"] = 1;
rowsArray.append(rowObj);
}
root["rows"] = rowsArray;
root["columnMappings"] = QJsonArray::fromStringList(QStringList() << "Format" << "Zone" << "Position" << "Designation" << "Name" << "Quantity" << "Note");
root["propertyNames"] = QJsonArray::fromStringList(QStringList() << "Name" << "Value" << "Height" << "DielType" << "LayerNumber");
QJsonDocument doc(root);
QByteArray result = doc.toJson();
qDebug() << "DataBaseController::loadSpecificationTable: Загружено" << rowsArray.size() << "строк";
return result;
}
bool DataBaseController::deleteSpecificationTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("DELETE FROM specification_rows WHERE project_name = ?");
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка удаления спецификации: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
QStringList DataBaseController::getAvailableSpecificationProjects()
{
QStringList projects;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return projects;
}
QSqlQuery query = prepareQuery("SELECT DISTINCT project_name FROM specification_rows ORDER BY project_name");
if (!query.exec()) {
setLastError("Ошибка получения списка проектов спецификации: " + query.lastError().text());
return projects;
}
while (query.next()) {
projects << query.value(0).toString();
}
return projects;
}
QString DataBaseController::getSpecificationTableInfo(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QString();
}
qDebug() << "DataBaseController::getSpecificationTableInfo: Получаем информацию о спецификации материалов для проекта:" << projectName;
QSqlQuery query = prepareQuery(
"SELECT COUNT(*) as total_rows, "
"SUM(CASE WHEN is_header = 1 THEN 1 ELSE 0 END) as header_rows, "
"SUM(CASE WHEN is_empty = 1 THEN 1 ELSE 0 END) as empty_rows, "
"MIN(row_order) as min_order, "
"MAX(row_order) as max_order "
"FROM specification_rows WHERE project_name = ?"
);
query.addBindValue(projectName);
if (!query.exec() || !query.next()) {
setLastError("Ошибка получения информации о спецификации: " + query.lastError().text());
return QString();
}
int totalRows = query.value(0).toInt();
int headerRows = query.value(1).toInt();
int emptyRows = query.value(2).toInt();
int minOrder = query.value(3).toInt();
int maxOrder = query.value(4).toInt();
QString info = QString("Спецификация для проекта '%1':\n"
"Всего строк: %2\n"
"Заголовков: %3\n"
"Пустых строк: %4\n"
"Диапазон строк: %5-%6")
.arg(projectName)
.arg(totalRows)
.arg(headerRows)
.arg(emptyRows)
.arg(minOrder)
.arg(maxOrder);
qDebug() << "DataBaseController::getSpecificationTableInfo: Информация получена:" << info;
return info;
}
// Работа с ведомостью покупных изделий
bool DataBaseController::saveVedomostTable(const QByteArray &tableData, const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController::saveVedomostTable: Сохраняем ведомость покупных изделий для проекта:" << projectName;
// Начинаем транзакцию
if (!beginTransaction()) {
return false;
}
// Удаляем существующие данные для этого проекта
QSqlQuery deleteQuery = prepareQuery("DELETE FROM vedomost_rows WHERE project_name = ?");
deleteQuery.addBindValue(projectName);
if (!deleteQuery.exec()) {
qDebug() << "DataBaseController::saveVedomostTable: Ошибка удаления:" << deleteQuery.lastError().text();
setLastError("Ошибка удаления существующих данных ведомости: " + deleteQuery.lastError().text());
rollbackTransaction();
return false;
}
// Парсим JSON данные и сохраняем каждую строку отдельно
QJsonDocument doc = QJsonDocument::fromJson(tableData);
if (!doc.isObject()) {
setLastError("Ошибка парсинга JSON данных ведомости");
rollbackTransaction();
return false;
}
QJsonObject root = doc.object();
QJsonArray rowsArray = root["rows"].toArray();
int rowOrder = 0;
for (const QJsonValue &value : rowsArray) {
QJsonObject rowObj = value.toObject();
// Отладочная информация для первых нескольких строк
if (rowOrder < 5) {
qDebug() << "DataBaseController::saveVedomostTable: Обрабатываем строку" << rowOrder << ":";
if (rowObj.contains("name")) {
QJsonObject nameObj = rowObj["name"].toObject();
qDebug() << " name.value:" << nameObj["value"].toString();
}
if (rowObj.contains("productCode")) {
QJsonObject productCodeObj = rowObj["productCode"].toObject();
qDebug() << " productCode.value:" << productCodeObj["value"].toString();
}
qDebug() << " isHeader:" << rowObj["isHeader"].toBool();
qDebug() << " isEmpty:" << rowObj["isEmpty"].toBool();
}
// Получаем данные ячеек
QJsonObject nameObj = rowObj["name"].toObject();
QJsonObject productCodeObj = rowObj["productCode"].toObject();
QJsonObject documentCodeObj = rowObj["documentCode"].toObject();
QJsonObject supplierObj = rowObj["supplier"].toObject();
QJsonObject whereUsedObj = rowObj["whereUsed"].toObject();
QJsonObject quantityPerItemObj = rowObj["quantityPerItem"].toObject();
QJsonObject quantityInSetObj = rowObj["quantityInSet"].toObject();
QJsonObject quantityForRegObj = rowObj["quantityForReg"].toObject();
QJsonObject totalQuantityObj = rowObj["totalQuantity"].toObject();
QJsonObject noteObj = rowObj["note"].toObject();
// Формируем JSON объект с настройками ячеек (stretch, isHeader, isUnderline)
QJsonObject cellSettingsObj;
QJsonObject nameCellObj;
nameCellObj["stretch"] = nameObj["stretch"].toInt(100);
nameCellObj["isHeader"] = nameObj["isHeader"].toBool(false);
nameCellObj["isUnderline"] = nameObj["isUnderline"].toBool(false);
cellSettingsObj["name"] = nameCellObj;
QJsonObject productCodeCellObj;
productCodeCellObj["stretch"] = productCodeObj["stretch"].toInt(100);
productCodeCellObj["isHeader"] = productCodeObj["isHeader"].toBool(false);
productCodeCellObj["isUnderline"] = productCodeObj["isUnderline"].toBool(false);
cellSettingsObj["productCode"] = productCodeCellObj;
QJsonObject documentCodeCellObj;
documentCodeCellObj["stretch"] = documentCodeObj["stretch"].toInt(100);
documentCodeCellObj["isHeader"] = documentCodeObj["isHeader"].toBool(false);
documentCodeCellObj["isUnderline"] = documentCodeObj["isUnderline"].toBool(false);
cellSettingsObj["documentCode"] = documentCodeCellObj;
QJsonObject supplierCellObj;
supplierCellObj["stretch"] = supplierObj["stretch"].toInt(100);
supplierCellObj["isHeader"] = supplierObj["isHeader"].toBool(false);
supplierCellObj["isUnderline"] = supplierObj["isUnderline"].toBool(false);
cellSettingsObj["supplier"] = supplierCellObj;
QJsonObject whereUsedCellObj;
whereUsedCellObj["stretch"] = whereUsedObj["stretch"].toInt(100);
whereUsedCellObj["isHeader"] = whereUsedObj["isHeader"].toBool(false);
whereUsedCellObj["isUnderline"] = whereUsedObj["isUnderline"].toBool(false);
cellSettingsObj["whereUsed"] = whereUsedCellObj;
QJsonObject quantityPerItemCellObj;
quantityPerItemCellObj["stretch"] = quantityPerItemObj["stretch"].toInt(100);
quantityPerItemCellObj["isHeader"] = quantityPerItemObj["isHeader"].toBool(false);
quantityPerItemCellObj["isUnderline"] = quantityPerItemObj["isUnderline"].toBool(false);
cellSettingsObj["quantityPerItem"] = quantityPerItemCellObj;
QJsonObject quantityInSetCellObj;
quantityInSetCellObj["stretch"] = quantityInSetObj["stretch"].toInt(100);
quantityInSetCellObj["isHeader"] = quantityInSetObj["isHeader"].toBool(false);
quantityInSetCellObj["isUnderline"] = quantityInSetObj["isUnderline"].toBool(false);
cellSettingsObj["quantityInSet"] = quantityInSetCellObj;
QJsonObject quantityForRegCellObj;
quantityForRegCellObj["stretch"] = quantityForRegObj["stretch"].toInt(100);
quantityForRegCellObj["isHeader"] = quantityForRegObj["isHeader"].toBool(false);
quantityForRegCellObj["isUnderline"] = quantityForRegObj["isUnderline"].toBool(false);
cellSettingsObj["quantityForReg"] = quantityForRegCellObj;
QJsonObject totalQuantityCellObj;
totalQuantityCellObj["stretch"] = totalQuantityObj["stretch"].toInt(100);
totalQuantityCellObj["isHeader"] = totalQuantityObj["isHeader"].toBool(false);
totalQuantityCellObj["isUnderline"] = totalQuantityObj["isUnderline"].toBool(false);
cellSettingsObj["totalQuantity"] = totalQuantityCellObj;
QJsonObject noteCellObj;
noteCellObj["stretch"] = noteObj["stretch"].toInt(100);
noteCellObj["isHeader"] = noteObj["isHeader"].toBool(false);
noteCellObj["isUnderline"] = noteObj["isUnderline"].toBool(false);
cellSettingsObj["note"] = noteCellObj;
QJsonDocument cellSettingsDoc(cellSettingsObj);
QString cellSettingsJson = cellSettingsDoc.toJson(QJsonDocument::Compact);
// Добавляем строку в БД
QSqlQuery insertQuery = prepareQuery(
"INSERT INTO vedomost_rows (project_name, row_order, name_value, product_code_value, document_code_value, "
"supplier_value, where_used_value, quantity_per_item_value, quantity_in_set_value, quantity_for_reg_value, total_quantity_value, "
"note_value, is_header, is_empty, row_number, page_number, cell_stretches) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
insertQuery.addBindValue(projectName);
insertQuery.addBindValue(rowOrder++);
insertQuery.addBindValue(nameObj["value"].toString());
insertQuery.addBindValue(productCodeObj["value"].toString());
insertQuery.addBindValue(documentCodeObj["value"].toString());
insertQuery.addBindValue(supplierObj["value"].toString());
insertQuery.addBindValue(whereUsedObj["value"].toString());
insertQuery.addBindValue(quantityPerItemObj["value"].toString());
insertQuery.addBindValue(quantityInSetObj["value"].toString());
insertQuery.addBindValue(quantityForRegObj["value"].toString());
insertQuery.addBindValue(totalQuantityObj["value"].toString());
insertQuery.addBindValue(noteObj["value"].toString());
insertQuery.addBindValue(rowObj["isHeader"].toBool());
insertQuery.addBindValue(rowObj["isEmpty"].toBool());
insertQuery.addBindValue(rowObj["rowNumber"].toInt());
insertQuery.addBindValue(rowObj["pageNumber"].toInt());
insertQuery.addBindValue(cellSettingsJson);
if (!insertQuery.exec()) {
qDebug() << "DataBaseController::saveVedomostTable: Ошибка сохранения строки" << rowOrder-1 << ":" << insertQuery.lastError().text();
setLastError("Ошибка сохранения строки ведомости: " + insertQuery.lastError().text());
rollbackTransaction();
return false;
}
}
// Подтверждаем транзакцию
if (!commitTransaction()) {
return false;
}
qDebug() << "DataBaseController::saveVedomostTable: Ведомость успешно сохранена," << rowsArray.size() << "строк";
emit dataChanged();
return true;
}
QByteArray DataBaseController::loadVedomostTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QByteArray();
}
qDebug() << "DataBaseController::loadVedomostTable: Загружаем ведомость покупных изделий для проекта:" << projectName;
QSqlQuery query = prepareQuery(
"SELECT name_value, product_code_value, document_code_value, supplier_value, where_used_value, quantity_per_item_value, "
"quantity_in_set_value, quantity_for_reg_value, total_quantity_value, note_value, is_header, is_empty, row_number, page_number, cell_stretches "
"FROM vedomost_rows WHERE project_name = ? ORDER BY row_order"
);
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка загрузки ведомости покупных изделий: " + query.lastError().text());
return QByteArray();
}
QJsonObject root;
QJsonArray rowsArray;
while (query.next()) {
QJsonObject rowObj;
// Загружаем настройки ячеек (stretch, isHeader, isUnderline) из JSON
QJsonObject cellSettingsObj;
QString cellSettingsJson = query.value(14).toString();
if (!cellSettingsJson.isEmpty()) {
QJsonDocument cellSettingsDoc = QJsonDocument::fromJson(cellSettingsJson.toUtf8());
if (cellSettingsDoc.isObject()) {
cellSettingsObj = cellSettingsDoc.object();
}
}
// Получаем настройки для каждой ячейки
QJsonObject nameCellObj = cellSettingsObj["name"].toObject();
QJsonObject productCodeCellObj = cellSettingsObj["productCode"].toObject();
QJsonObject documentCodeCellObj = cellSettingsObj["documentCode"].toObject();
QJsonObject supplierCellObj = cellSettingsObj["supplier"].toObject();
QJsonObject whereUsedCellObj = cellSettingsObj["whereUsed"].toObject();
QJsonObject quantityPerItemCellObj = cellSettingsObj["quantityPerItem"].toObject();
QJsonObject quantityInSetCellObj = cellSettingsObj["quantityInSet"].toObject();
QJsonObject quantityForRegCellObj = cellSettingsObj["quantityForReg"].toObject();
QJsonObject totalQuantityCellObj = cellSettingsObj["totalQuantity"].toObject();
QJsonObject noteCellObj = cellSettingsObj["note"].toObject();
// Создаем объекты для каждой ячейки
QJsonObject nameObj;
nameObj["value"] = query.value(0).toString();
nameObj["rowNumber"] = query.value(12).toInt();
nameObj["pageNumber"] = query.value(13).toInt();
nameObj["isHeader"] = nameCellObj["isHeader"].toBool(query.value(10).toBool());
nameObj["isAutoGenerated"] = false;
nameObj["isEmpty"] = query.value(11).toBool();
nameObj["stretch"] = nameCellObj["stretch"].toInt(100);
nameObj["isUnderline"] = nameCellObj["isUnderline"].toBool(false);
rowObj["name"] = nameObj;
QJsonObject productCodeObj;
productCodeObj["value"] = query.value(1).toString();
productCodeObj["rowNumber"] = query.value(12).toInt();
productCodeObj["pageNumber"] = query.value(13).toInt();
productCodeObj["isHeader"] = productCodeCellObj["isHeader"].toBool(query.value(10).toBool());
productCodeObj["isAutoGenerated"] = false;
productCodeObj["isEmpty"] = query.value(11).toBool();
productCodeObj["stretch"] = productCodeCellObj["stretch"].toInt(100);
productCodeObj["isUnderline"] = productCodeCellObj["isUnderline"].toBool(false);
rowObj["productCode"] = productCodeObj;
QJsonObject documentCodeObj;
documentCodeObj["value"] = query.value(2).toString();
documentCodeObj["rowNumber"] = query.value(12).toInt();
documentCodeObj["pageNumber"] = query.value(13).toInt();
documentCodeObj["isHeader"] = documentCodeCellObj["isHeader"].toBool(query.value(10).toBool());
documentCodeObj["isAutoGenerated"] = false;
documentCodeObj["isEmpty"] = query.value(11).toBool();
documentCodeObj["stretch"] = documentCodeCellObj["stretch"].toInt(100);
documentCodeObj["isUnderline"] = documentCodeCellObj["isUnderline"].toBool(false);
rowObj["documentCode"] = documentCodeObj;
QJsonObject supplierObj;
supplierObj["value"] = query.value(3).toString();
supplierObj["rowNumber"] = query.value(12).toInt();
supplierObj["pageNumber"] = query.value(13).toInt();
supplierObj["isHeader"] = supplierCellObj["isHeader"].toBool(query.value(10).toBool());
supplierObj["isAutoGenerated"] = false;
supplierObj["isEmpty"] = query.value(11).toBool();
supplierObj["stretch"] = supplierCellObj["stretch"].toInt(100);
supplierObj["isUnderline"] = supplierCellObj["isUnderline"].toBool(false);
rowObj["supplier"] = supplierObj;
QJsonObject whereUsedObj;
whereUsedObj["value"] = query.value(4).toString();
whereUsedObj["rowNumber"] = query.value(12).toInt();
whereUsedObj["pageNumber"] = query.value(13).toInt();
whereUsedObj["isHeader"] = whereUsedCellObj["isHeader"].toBool(query.value(10).toBool());
whereUsedObj["isAutoGenerated"] = false;
whereUsedObj["isEmpty"] = query.value(11).toBool();
whereUsedObj["stretch"] = whereUsedCellObj["stretch"].toInt(100);
whereUsedObj["isUnderline"] = whereUsedCellObj["isUnderline"].toBool(false);
rowObj["whereUsed"] = whereUsedObj;
QJsonObject quantityPerItemObj;
quantityPerItemObj["value"] = query.value(5).toString();
quantityPerItemObj["rowNumber"] = query.value(12).toInt();
quantityPerItemObj["pageNumber"] = query.value(13).toInt();
quantityPerItemObj["isHeader"] = quantityPerItemCellObj["isHeader"].toBool(query.value(10).toBool());
quantityPerItemObj["isAutoGenerated"] = false;
quantityPerItemObj["isEmpty"] = query.value(11).toBool();
quantityPerItemObj["stretch"] = quantityPerItemCellObj["stretch"].toInt(100);
quantityPerItemObj["isUnderline"] = quantityPerItemCellObj["isUnderline"].toBool(false);
rowObj["quantityPerItem"] = quantityPerItemObj;
QJsonObject quantityInSetObj;
quantityInSetObj["value"] = query.value(6).toString();
quantityInSetObj["rowNumber"] = query.value(12).toInt();
quantityInSetObj["pageNumber"] = query.value(13).toInt();
quantityInSetObj["isHeader"] = quantityInSetCellObj["isHeader"].toBool(query.value(10).toBool());
quantityInSetObj["isAutoGenerated"] = false;
quantityInSetObj["isEmpty"] = query.value(11).toBool();
quantityInSetObj["stretch"] = quantityInSetCellObj["stretch"].toInt(100);
quantityInSetObj["isUnderline"] = quantityInSetCellObj["isUnderline"].toBool(false);
rowObj["quantityInSet"] = quantityInSetObj;
QJsonObject quantityForRegObj;
quantityForRegObj["value"] = query.value(7).toString();
quantityForRegObj["rowNumber"] = query.value(12).toInt();
quantityForRegObj["pageNumber"] = query.value(13).toInt();
quantityForRegObj["isHeader"] = quantityForRegCellObj["isHeader"].toBool(query.value(10).toBool());
quantityForRegObj["isAutoGenerated"] = false;
quantityForRegObj["isEmpty"] = query.value(11).toBool();
quantityForRegObj["stretch"] = quantityForRegCellObj["stretch"].toInt(100);
quantityForRegObj["isUnderline"] = quantityForRegCellObj["isUnderline"].toBool(false);
rowObj["quantityForReg"] = quantityForRegObj;
QJsonObject totalQuantityObj;
totalQuantityObj["value"] = query.value(8).toString();
totalQuantityObj["rowNumber"] = query.value(12).toInt();
totalQuantityObj["pageNumber"] = query.value(13).toInt();
totalQuantityObj["isHeader"] = totalQuantityCellObj["isHeader"].toBool(query.value(10).toBool());
totalQuantityObj["isAutoGenerated"] = false;
totalQuantityObj["isEmpty"] = query.value(11).toBool();
totalQuantityObj["stretch"] = totalQuantityCellObj["stretch"].toInt(100);
totalQuantityObj["isUnderline"] = totalQuantityCellObj["isUnderline"].toBool(false);
rowObj["totalQuantity"] = totalQuantityObj;
QJsonObject noteObj;
noteObj["value"] = query.value(9).toString();
noteObj["rowNumber"] = query.value(12).toInt();
noteObj["pageNumber"] = query.value(13).toInt();
noteObj["isHeader"] = noteCellObj["isHeader"].toBool(query.value(10).toBool());
noteObj["isAutoGenerated"] = false;
noteObj["isEmpty"] = query.value(11).toBool();
noteObj["stretch"] = noteCellObj["stretch"].toInt(100);
noteObj["isUnderline"] = noteCellObj["isUnderline"].toBool(false);
rowObj["note"] = noteObj;
rowObj["isHeader"] = query.value(10).toBool();
rowObj["isEmpty"] = query.value(11).toBool();
rowObj["rowNumber"] = query.value(12).toInt();
rowObj["pageNumber"] = query.value(13).toInt();
rowsArray.append(rowObj);
}
root["rows"] = rowsArray;
// Добавляем настройки колонок по умолчанию
QStringList defaultColumnMappings = {"Name", "ProductCode", "DocumentCode", "Supplier", "WhereUsed",
"QuantityPerItem", "QuantityInSet", "QuantityForReg", "TotalQuantity", "Note"};
root["columnMappings"] = QJsonArray::fromStringList(defaultColumnMappings);
// Добавляем свойства по умолчанию
QStringList defaultPropertyNames = {"Name", "ProductCode", "DocumentCode", "Supplier", "WhereUsed",
"QuantityPerItem", "QuantityInSet", "QuantityForReg", "TotalQuantity", "Note"};
root["propertyNames"] = QJsonArray::fromStringList(defaultPropertyNames);
QJsonDocument doc(root);
QByteArray result = doc.toJson();
qDebug() << "DataBaseController::loadVedomostTable: Загружено" << rowsArray.size() << "строк";
return result;
}
bool DataBaseController::deleteVedomostTable(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController::deleteVedomostTable: Удаляем ведомость покупных изделий для проекта:" << projectName;
QSqlQuery query = prepareQuery("DELETE FROM vedomost_rows WHERE project_name = ?");
query.addBindValue(projectName);
if (!query.exec()) {
setLastError("Ошибка удаления ведомости покупных изделий: " + query.lastError().text());
return false;
}
qDebug() << "DataBaseController::deleteVedomostTable: Ведомость успешно удалена";
emit dataChanged();
return true;
}
QStringList DataBaseController::getAvailableVedomostProjects()
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QStringList();
}
qDebug() << "DataBaseController::getAvailableVedomostProjects: Получаем список проектов с ведомостями";
QSqlQuery query = prepareQuery("SELECT DISTINCT project_name FROM vedomost_rows ORDER BY project_name");
if (!query.exec()) {
setLastError("Ошибка получения списка проектов с ведомостями: " + query.lastError().text());
return QStringList();
}
QStringList projects;
while (query.next()) {
projects << query.value(0).toString();
}
return projects;
}
QString DataBaseController::getVedomostTableInfo(const QString &projectName)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return QString();
}
qDebug() << "DataBaseController::getVedomostTableInfo: Получаем информацию о ведомости покупных изделий для проекта:" << projectName;
QSqlQuery query = prepareQuery(
"SELECT COUNT(*) as total_rows, "
"SUM(CASE WHEN is_header = 1 THEN 1 ELSE 0 END) as header_rows, "
"SUM(CASE WHEN is_empty = 1 THEN 1 ELSE 0 END) as empty_rows, "
"MIN(row_order) as min_order, "
"MAX(row_order) as max_order "
"FROM vedomost_rows WHERE project_name = ?"
);
query.addBindValue(projectName);
if (!query.exec() || !query.next()) {
setLastError("Ошибка получения информации о ведомости покупных изделий: " + query.lastError().text());
return QString();
}
int totalRows = query.value(0).toInt();
int headerRows = query.value(1).toInt();
int emptyRows = query.value(2).toInt();
int minOrder = query.value(3).toInt();
int maxOrder = query.value(4).toInt();
QString info = QString("Ведомость покупных изделий для проекта '%1':\n"
"Всего строк: %2\n"
"Заголовков: %3\n"
"Пустых строк: %4\n"
"Диапазон строк: %5-%6")
.arg(projectName)
.arg(totalRows)
.arg(headerRows)
.arg(emptyRows)
.arg(minOrder)
.arg(maxOrder);
qDebug() << "DataBaseController::getVedomostTableInfo: Информация получена:" << info;
return info;
}
// Работа с данными PCB
int DataBaseController::addPCBData(int layerCount)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return -1;
}
QSqlQuery query = prepareQuery("INSERT INTO pcb_data (layer_count) VALUES (?)");
query.addBindValue(layerCount);
if (!query.exec()) {
setLastError("Ошибка добавления данных PCB: " + query.lastError().text());
return -1;
}
return query.lastInsertId().toInt();
}
bool DataBaseController::updatePCBLayerCount(int pcbId, int layerCount)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("UPDATE pcb_data SET layer_count = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?");
query.addBindValue(layerCount);
query.addBindValue(pcbId);
if (!query.exec()) {
setLastError("Ошибка обновления количества слоев PCB: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
bool DataBaseController::addDielMaterial(int pcbId, const QString &name, const QString &value, double height, int dielType, int layerNumber)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
qDebug() << "DataBaseController: Добавляем диэлектрический материал:";
qDebug() << " pcbId:" << pcbId;
qDebug() << " name:" << name;
qDebug() << " value:" << value;
qDebug() << " height:" << height;
qDebug() << " dielType:" << dielType;
qDebug() << " layerNumber:" << layerNumber;
QSqlQuery query = prepareQuery(
"REPLACE INTO diel_materials (pcb_id, name, value, height, diel_type, layer_number) "
"VALUES (?, ?, ?, ?, ?, ?)"
);
query.addBindValue(pcbId);
query.addBindValue(name);
query.addBindValue(value);
query.addBindValue(height);
query.addBindValue(dielType);
query.addBindValue(layerNumber);
if (!query.exec()) {
QString errorText = "Ошибка добавления диэлектрического материала: " + query.lastError().text();
qDebug() << "DataBaseController:" << errorText;
setLastError(errorText);
return false;
}
qDebug() << "DataBaseController: Диэлектрический материал успешно добавлен";
emit dataChanged();
return true;
}
bool DataBaseController::updateDielMaterial(int pcbId, const QString &name, const QString &value, double height, int dielType, int layerNumber)
{
return addDielMaterial(pcbId, name, value, height, dielType, layerNumber); // REPLACE INTO
}
bool DataBaseController::removeDielMaterial(int pcbId, int layerNumber)
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("DELETE FROM diel_materials WHERE pcb_id = ? AND layer_number = ?");
query.addBindValue(pcbId);
query.addBindValue(layerNumber);
if (!query.exec()) {
setLastError("Ошибка удаления диэлектрического материала: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}
PCBData DataBaseController::getPCBData(int pcbId)
{
PCBData pcbData;
pcbData.id = -1;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return pcbData;
}
QSqlQuery query = prepareQuery("SELECT id, layer_count FROM pcb_data WHERE id = ?");
query.addBindValue(pcbId);
if (query.exec() && query.next()) {
pcbData.id = query.value(0).toInt();
pcbData.layerCount = query.value(1).toInt();
pcbData.dielMaterials = getDielMaterials(pcbId);
}
return pcbData;
}
QList<DielProperty> DataBaseController::getDielMaterials(int pcbId)
{
QList<DielProperty> materials;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return materials;
}
QSqlQuery query = prepareQuery("SELECT name, value, height, diel_type, layer_number FROM diel_materials WHERE pcb_id = ? ORDER BY layer_number");
query.addBindValue(pcbId);
if (query.exec()) {
while (query.next()) {
DielProperty material;
material.name = query.value(0).toString();
material.value = query.value(1).toString();
material.height = query.value(2).toDouble();
material.dielType = query.value(3).toInt();
material.layerNumber = query.value(4).toInt();
materials << material;
}
}
return materials;
}
PCBData DataBaseController::getPCBData()
{
PCBData pcbData;
pcbData.id = -1;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return pcbData;
}
// Получаем последнюю запись PCB
QSqlQuery query = prepareQuery("SELECT id, layer_count FROM pcb_data ORDER BY id DESC LIMIT 1");
if (query.exec() && query.next()) {
int pcbId = query.value(0).toInt();
pcbData.id = pcbId;
pcbData.layerCount = query.value(1).toInt();
pcbData.dielMaterials = getDielMaterials(pcbId);
qDebug() << "DataBaseController: Получены данные PCB - ID:" << pcbData.id
<< "слоев:" << pcbData.layerCount << "материалов:" << pcbData.dielMaterials.size();
} else {
qDebug() << "DataBaseController: Данные PCB не найдены в БД";
}
return pcbData;
}
QList<DielProperty> DataBaseController::getDielMaterials()
{
QList<DielProperty> materials;
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return materials;
}
// Получаем материалы для последней записи PCB
QSqlQuery pcbQuery = prepareQuery("SELECT id FROM pcb_data ORDER BY id DESC LIMIT 1");
if (pcbQuery.exec() && pcbQuery.next()) {
int pcbId = pcbQuery.value(0).toInt();
materials = getDielMaterials(pcbId);
qDebug() << "DataBaseController: Получены материалы для PCB ID:" << pcbId
<< "количество:" << materials.size();
} else {
qDebug() << "DataBaseController: Записи PCB не найдены в БД";
}
return materials;
}
bool DataBaseController::savePCBData(const PCBData &pcbData)
{
qDebug() << "DataBaseController: Начинаем сохранение PCB данных:";
qDebug() << " ID:" << pcbData.id;
qDebug() << " LayerCount:" << pcbData.layerCount;
qDebug() << " Materials count:" << pcbData.dielMaterials.size();
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
if (!beginTransaction()) {
qDebug() << "DataBaseController: ОШИБКА: Не удалось начать транзакцию";
return false;
}
int pcbId = pcbData.id;
if (pcbId == -1) {
// Создаем новую запись PCB
qDebug() << "DataBaseController: Создаем новую запись PCB";
pcbId = addPCBData(pcbData.layerCount);
if (pcbId == -1) {
qDebug() << "DataBaseController: ОШИБКА: Не удалось создать запись PCB";
rollbackTransaction();
return false;
}
qDebug() << "DataBaseController: Создана запись PCB с ID:" << pcbId;
} else {
// Обновляем существующую запись
qDebug() << "DataBaseController: Обновляем существующую запись PCB с ID:" << pcbId;
if (!updatePCBLayerCount(pcbId, pcbData.layerCount)) {
qDebug() << "DataBaseController: ОШИБКА: Не удалось обновить запись PCB";
rollbackTransaction();
return false;
}
}
// Сохраняем диэлектрические материалы
qDebug() << "DataBaseController: Сохраняем" << pcbData.dielMaterials.size() << "материалов";
for (int i = 0; i < pcbData.dielMaterials.size(); i++) {
const DielProperty &material = pcbData.dielMaterials[i];
qDebug() << "DataBaseController: Сохраняем материал" << i << ":" << material.name << "=" << material.value << "слой:" << material.layerNumber;
if (!addDielMaterial(pcbId, material.name, material.value, material.height, material.dielType, material.layerNumber)) {
qDebug() << "DataBaseController: ОШИБКА: Не удалось сохранить материал" << i;
rollbackTransaction();
return false;
}
}
if (!commitTransaction()) {
qDebug() << "DataBaseController: ОШИБКА: Не удалось завершить транзакцию";
rollbackTransaction();
return false;
}
qDebug() << "DataBaseController: PCB данные успешно сохранены";
return true;
}
bool DataBaseController::clearPCBData()
{
if (!m_database.isOpen()) {
setLastError("База данных не открыта");
return false;
}
QSqlQuery query = prepareQuery("DELETE FROM pcb_data");
if (!query.exec()) {
setLastError("Ошибка очистки данных PCB: " + query.lastError().text());
return false;
}
emit dataChanged();
return true;
}