3354 lines
141 KiB
C++
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 ¶ms)
|
|
{
|
|
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;
|
|
}
|
|
|