Files
GostGenerator/controller/specificationcontroller.cpp
T

843 lines
38 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "specificationcontroller.h"
#include "../model/specificationtablemodel.h"
#include "../model/designatormappingmodel.h"
#include "../model/projectsettingsmodel.h"
#include "../model/projectparamtablemodel.h"
#include "../model/pcbmaterialmodel.h"
#include "../controller/maincontroller.h"
#include <QDebug>
#include <QCollator>
SpecificationController::SpecificationController(QObject *parent)
: QObject(parent)
, m_tableModel(new SpecificationTableModel(this))
, m_designatorMappingModel(nullptr)
, m_projectSettingsModel(nullptr)
, m_mainController(nullptr)
, m_pcbMaterialModel(nullptr)
{
// Устанавливаем маппинг по умолчанию для спецификации
m_columnMappings << "Format" << "Zone" << "Position" << "Designation" << "Name" << "Quantity" << "Note";
}
SpecificationController::~SpecificationController()
{
// m_tableModel удалится автоматически, так как он является дочерним объектом
}
void SpecificationController::setDesignatorMappingModel(DesignatorMappingModel *mappingModel)
{
m_designatorMappingModel = mappingModel;
}
void SpecificationController::setModel(SpecificationTableModel *model)
{
if (m_tableModel != model) {
qDebug() << "SpecificationController::setModel: Заменяем модель таблицы";
m_tableModel = model;
// Если модель не пуста, загружаем из неё настройки колонок
if (m_tableModel) {
QStringList columnMappings = m_tableModel->columnMappings();
if (!columnMappings.isEmpty()) {
qDebug() << "SpecificationController::setModel: Загружаем настройки колонок из модели:" << columnMappings;
m_columnMappings = columnMappings;
}
}
}
}
void SpecificationController::setProjectSettingsModel(ProjectSettingsModel *model)
{
m_projectSettingsModel = model;
qDebug() << "SpecificationController::setProjectSettingsModel: Установлена модель настроек проекта";
}
void SpecificationController::setMainController(MainController *controller)
{
m_mainController = controller;
qDebug() << "SpecificationController::setMainController: Установлен главный контроллер";
}
void SpecificationController::setMaterials(const QList<PCBMaterialModel*> &materials)
{
qDebug() << "SpecificationController::setMaterials: Устанавливаем" << materials.size() << "материалов";
m_materials = materials;
// Собираем доступные свойства из материалов
m_propertyNames = collectPropertyNames();
qDebug() << "SpecificationController::setMaterials: Собрано свойств:" << m_propertyNames.size();
qDebug() << "SpecificationController::setMaterials: Свойства:" << m_propertyNames;
}
void SpecificationController::setPCBMaterialModel(PCBMaterialModel* model)
{
qDebug() << "SpecificationController::setPCBMaterialModel: Устанавливаем PCB модель материалов";
m_pcbMaterialModel = model;
if (m_pcbMaterialModel) {
qDebug() << "SpecificationController::setPCBMaterialModel: Материалов в модели:" << m_pcbMaterialModel->getMaterialCount();
}
}
void SpecificationController::generateTableFromMaterials()
{
if (!m_tableModel) {
return;
}
qDebug() << "SpecificationController::generateTableFromMaterials: Начинаем генерацию таблицы";
qDebug() << "SpecificationController::generateTableFromMaterials: Текущие настройки колонок:" << m_columnMappings;
// Очищаем таблицу
m_tableModel->clear();
// Добавляем заголовок таблицы
SpecificationRowData emptyRow;
emptyRow.isEmpty = true;
m_tableModel->addRow(emptyRow);
SpecificationRowData headerRow;
headerRow.isHeader = true;
headerRow.format = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow.zone = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow.position = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow.designation = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow.name = SpecificationCellData("Документаця", 0, 1, true, false, false, 100, true);
headerRow.quantity = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow.note = SpecificationCellData("", 0, 1, true, false, false, 100, true);
m_tableModel->addRow(headerRow);
m_tableModel->addRow(emptyRow);
SpecificationRowData defaultRow1;
defaultRow1.isHeader = false;
defaultRow1.format = SpecificationCellData("A1", 0, 1, false, false, false, 100, false);
defaultRow1.zone = SpecificationCellData("", 0, 1, false, false, false, 100, false);
defaultRow1.position = SpecificationCellData("", 0, 1, false, false, false, 100, false);
defaultRow1.designation = SpecificationCellData(getDecimalNumberBoard() + "Э3 СБ", 0, 1, false, false, false, 100, false);
defaultRow1.name = SpecificationCellData("Сборочный чертеж", 0, 1, false, false, false, 100, false);
defaultRow1.quantity = SpecificationCellData("", 0, 1, false, false, false, 100, false);
defaultRow1.note = SpecificationCellData("", 0, 1, false, false, false, 100, false);
m_tableModel->addRow(defaultRow1);
SpecificationRowData defaultRow2;
defaultRow2.isHeader = false;
defaultRow2.format = SpecificationCellData("*)", 0, 1, false, false, false, 100, false);
defaultRow2.zone = SpecificationCellData("", 0, 1, false, false, false, 100, false);
defaultRow2.position = SpecificationCellData("", 0, 1, false, false, false, 100, false);
defaultRow2.designation = SpecificationCellData(getDecimalNumberBoard() + " Э3 Т5М", 0, 1, false, false, false, 100, false);
defaultRow2.name = SpecificationCellData("Данные проектирования", 0, 1, false, false, false, 100, false);
defaultRow2.quantity = SpecificationCellData("", 0, 1, false, false, false, 100, false);
defaultRow2.note = SpecificationCellData("", 0, 1, false, false, false, 100, false);
m_tableModel->addRow(defaultRow2);
m_tableModel->addRow(emptyRow);
SpecificationRowData headerRow2;
headerRow2.isHeader = true;
headerRow2.format = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow2.zone = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow2.position = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow2.designation = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow2.name = SpecificationCellData("Материалы", 0, 1, true, false, false, 100, true);
headerRow2.quantity = SpecificationCellData("", 0, 1, true, false, false, 100, true);
headerRow2.note = SpecificationCellData("", 0, 1, true, false, false, 100, true);
m_tableModel->addRow(headerRow2);
m_tableModel->addRow(emptyRow);
if (!m_pcbMaterialModel || m_pcbMaterialModel->getMaterialCount() == 0) {
qDebug() << "SpecificationController::generateTableFromMaterials: Нет материалов для генерации";
return;
}
qDebug() << "SpecificationController::generateTableFromMaterials: Материалов для обработки:" << m_pcbMaterialModel->getMaterialCount();
try {
// Получаем список материалов из PCB модели
QList<PCBMaterialData> materials = m_pcbMaterialModel->getMaterials();
// Сортируем материалы по номеру слоя
std::sort(materials.begin(), materials.end(),
[](const PCBMaterialData &a, const PCBMaterialData &b) {
return a.layerNumber < b.layerNumber;
});
// Группируем материалы по названию и типу
QMap<QString, QList<PCBMaterialData>> groupedByName;
for (const PCBMaterialData &material : materials) {
QString materialName = material.name;
groupedByName[materialName].append(material);
}
// Подсчитываем количество ядер (dielType = 1 в модели PCB)
int coreCount = 0;
for (const PCBMaterialData &material : materials) {
if (material.dielType == 1) {
coreCount++;
}
}
// Подсчитываем общее количество слоев
int totalLayers = m_pcbMaterialModel->getLayerCount();
// Рассчитываем количество фольги: (общее количество слоев - количество ядер)
int foilCount = totalLayers - coreCount*2;
// Обрабатываем каждую группу материалов
int pos = 1;
for (auto it = groupedByName.begin(); it != groupedByName.end(); ++it) {
QString materialName = it.key();
QList<PCBMaterialData> materialsInGroup = it.value();
// Определяем тип материала и формируем название
QString displayName;
int quantity = 0;
if (materialName == "DielMaterial") {
// Для диэлектрических материалов группируем по значению
QMap<QString, QList<PCBMaterialData>> groupedByValue;
for (const PCBMaterialData &material : materialsInGroup) {
QString value = material.value;
groupedByValue[value].append(material);
}
// Обрабатываем каждое значение диэлектрика
for (auto valueIt = groupedByValue.begin(); valueIt != groupedByValue.end(); ++valueIt) {
QString value = valueIt.key();
QList<PCBMaterialData> valueMaterials = valueIt.value();
// Определяем тип диэлектрика и формируем название
QString dielTypeName;
if (value == "FR4 PR") {
dielTypeName = "Препрег FR4 PR";
} else if (value == "FR4 Tg150") {
dielTypeName = "Стеклотекстолит FR4 Tg150";
} else if (value == "Solder Resist") {
dielTypeName = "Паяльная маска";
} else {
dielTypeName = value;
}
// Добавляем толщину к названию
if (!valueMaterials.isEmpty()) {
double thickness = valueMaterials.first().height;
displayName = QString("%1 %2 мм").arg(dielTypeName).arg(QString::number(thickness, 'f', 3));
}
quantity = valueMaterials.size();
// Добавляем строку в таблицу
SpecificationRowData row;
row.format = SpecificationCellData("", 0, 1, false, false, false, 100, false);
row.zone = SpecificationCellData("", 0, 1, false, false, false, 100, false);
row.position = SpecificationCellData(QString::number(pos++), 0, 1, false, false, false, 100, false);
row.designation = SpecificationCellData("", 0, 1, false, false, false, 100, false);
row.name = SpecificationCellData(displayName, 0, 1, false, false, false, 100, false);
row.quantity = SpecificationCellData(QString::number(quantity), 0, 1, false, false, false, 100, false);
row.note = SpecificationCellData("", 0, 1, false, false, false, 100, false);
m_tableModel->addRow(row);
}
} else {
// Для других материалов (например, фольга)
displayName = materialName;
quantity = materialsInGroup.size();
// Добавляем строку в таблицу
SpecificationRowData row;
row.format = SpecificationCellData("", 0, 1, false, false, false, 100, false);
row.zone = SpecificationCellData("", 0, 1, false, false, false, 100, false);
row.position = SpecificationCellData(QString::number(pos++), 0, 1, false, false, false, 100, false);
row.designation = SpecificationCellData("", 0, 1, false, false, false, 100, false);
row.name = SpecificationCellData(displayName, 0, 1, false, false, false, 100, false);
row.quantity = SpecificationCellData(QString::number(quantity), 0, 1, false, false, false, 100, false);
row.note = SpecificationCellData("", 0, 1, false, false, false, 100, false);
m_tableModel->addRow(row);
}
}
// Добавляем фольгу в конец, если она есть
if (foilCount > 0) {
SpecificationRowData foilRow;
foilRow.format = SpecificationCellData("", 0, 1, false, false, false, 100, false);
foilRow.zone = SpecificationCellData("", 0, 1, false, false, false, 100, false);
foilRow.position = SpecificationCellData(QString::number(pos++), 0, 1, false, false, false, 100, false);
foilRow.designation = SpecificationCellData("", 0, 1, false, false, false, 100, false);
foilRow.name = SpecificationCellData("Фольга медная толщиной 18 мкм", 0, 1, false, false, false, 100, false);
foilRow.quantity = SpecificationCellData(QString::number(foilCount), 0, 1, false, false, false, 100, false);
foilRow.note = SpecificationCellData("", 0, 1, false, false, false, 100, false);
m_tableModel->addRow(foilRow);
}
qDebug() << "SpecificationController::generateTableFromMaterials: Таблица сгенерирована, строк:" << m_tableModel->rowCount();
// Оптимизируем разрывы страниц после генерации таблицы
m_tableModel->optimizePageBreaks();
} catch (const std::exception &e) {
qDebug() << "SpecificationController::generateTableFromMaterials: Ошибка при генерации:" << e.what();
} catch (...) {
qDebug() << "SpecificationController::generateTableFromMaterials: Неизвестная ошибка при генерации";
}
}
void SpecificationController::updateTableFromMaterials()
{
if (!m_tableModel) {
qDebug() << "SpecificationController::updateTableFromMaterials: m_tableModel is null";
return;
}
qDebug() << "SpecificationController::updateTableFromMaterials: Обновляем таблицу из" << m_materials.size() << "материалов";
if (m_materials.isEmpty()) {
qDebug() << "SpecificationController::updateTableFromMaterials: Нет материалов для обновления";
return;
}
try {
// Метод updateTableFromMaterials больше не используется в новой логике
qDebug() << "SpecificationController::updateTableFromMaterials: Метод устарел";
} catch (const std::exception &e) {
qDebug() << "SpecificationController::updateTableFromMaterials: Ошибка при обновлении:" << e.what();
} catch (...) {
qDebug() << "SpecificationController::updateTableFromMaterials: Неизвестная ошибка при обновлении";
}
}
QString SpecificationController::getMaterialValue(PCBMaterialModel *material, const QString &propertyName)
{
if (!material) {
return "";
}
qDebug() << "SpecificationController::getMaterialValue: propertyName =" << propertyName;
// Получаем значение свойства материала
QString value;
if (propertyName == "Name") {
value = material->getMaterialName(0); // Получаем название первого материала
qDebug() << "SpecificationController::getMaterialValue: Name =" << value;
} else if (propertyName == "Value") {
value = material->getMaterialValue(0);
qDebug() << "SpecificationController::getMaterialValue: Value =" << value;
} else if (propertyName == "Height") {
value = material->formatHeight(material->getMaterialHeight(0));
qDebug() << "SpecificationController::getMaterialValue: Height =" << value;
} else if (propertyName == "DielType") {
value = material->formatDielType(material->getMaterialDielType(0));
qDebug() << "SpecificationController::getMaterialValue: DielType =" << value;
} else if (propertyName == "LayerNumber") {
value = QString::number(material->getMaterialLayerNumber(0));
qDebug() << "SpecificationController::getMaterialValue: LayerNumber =" << value;
} else {
qDebug() << "SpecificationController::getMaterialValue: Неизвестное свойство" << propertyName;
return "";
}
// Проверяем, является ли значение свойства выражением
if (value.startsWith("=")) {
qDebug() << "SpecificationController::getMaterialValue: Значение свойства является выражением:" << value;
return parseExpression(material, value);
}
return value;
}
QString SpecificationController::formatDielType(int dielType)
{
switch (dielType) {
case 0: return "Ядро";
case 1: return "Препрег";
default: return "Неизвестно";
}
}
QString SpecificationController::parseExpression(PCBMaterialModel *material, const QString &expression)
{
if (!material) {
return "";
}
qDebug() << "SpecificationController::parseExpression: Обрабатываем выражение:" << expression;
QString result;
QString expr;
// Определяем, как обрабатывать выражение
if (expression.startsWith("=")) {
expr = expression.mid(1); // Убираем начальный "="
} else if (expression.startsWith("\"") && expression.endsWith("\"")) {
// Если это просто значение в кавычках, возвращаем его без кавычек
return expression.mid(1, expression.length() - 2);
} else {
// Если это не выражение, возвращаем как есть
return expression;
}
// Разбиваем выражение по операторам "+" с учетом кавычек
QStringList parts;
QString currentPart;
bool inDoubleQuotes = false;
bool inSingleQuotes = false;
for (int i = 0; i < expr.length(); ++i) {
QChar ch = expr[i];
if (ch == '"' && !inSingleQuotes) {
inDoubleQuotes = !inDoubleQuotes;
currentPart += ch;
} else if (ch == '\'' && !inDoubleQuotes) {
inSingleQuotes = !inSingleQuotes;
currentPart += ch;
} else if (ch == '+' && !inDoubleQuotes && !inSingleQuotes) {
// Это разделитель "+" вне кавычек
if (!currentPart.trimmed().isEmpty()) {
parts.append(currentPart.trimmed());
}
currentPart.clear();
} else {
currentPart += ch;
}
}
// Добавляем последнюю часть
if (!currentPart.trimmed().isEmpty()) {
parts.append(currentPart.trimmed());
}
qDebug() << "SpecificationController::parseExpression: Части выражения:" << parts;
for (const QString &part : parts) {
QString trimmedPart = part.trimmed();
qDebug() << "SpecificationController::parseExpression: Обрабатываем часть:" << trimmedPart;
// Если это не пустая строка, добавляем к результату
if (!trimmedPart.isEmpty()) {
QString value;
// Проверяем, является ли это литералом в одинарных кавычках
if (trimmedPart.startsWith("'") && trimmedPart.endsWith("'")) {
// Это литерал - убираем кавычки и используем как есть
value = trimmedPart.mid(1, trimmedPart.length() - 2);
qDebug() << "SpecificationController::parseExpression: Найден литерал в одинарных кавычках:" << value;
}
// Проверяем, является ли это именем свойства материала в двойных кавычках
else if (trimmedPart.startsWith("\"") && trimmedPart.endsWith("\"")) {
// Это свойство материала - убираем кавычки и ищем в свойствах
QString propertyName = trimmedPart.mid(1, trimmedPart.length() - 2);
qDebug() << "SpecificationController::parseExpression: Ищем свойство материала:" << propertyName;
value = getMaterialValue(material, propertyName);
qDebug() << "SpecificationController::parseExpression: Найдено свойство" << propertyName << "=" << value;
// Рекурсивно обрабатываем вложенные выражения (getMaterialValue уже обрабатывает первый уровень)
// Но если значение само является выражением, нужно обработать его еще раз
if (value.startsWith("=")) {
qDebug() << "SpecificationController::parseExpression: Значение свойства является вложенным выражением, рекурсивно обрабатываем";
value = parseExpression(material, value);
}
}
// Проверяем, является ли это именем свойства материала без кавычек
else {
// Ищем в свойствах материала
value = getMaterialValue(material, trimmedPart);
qDebug() << "SpecificationController::parseExpression: Ищем свойство" << trimmedPart << "в материале, результат:" << value;
// Рекурсивно обрабатываем вложенные выражения (getMaterialValue уже обрабатывает первый уровень)
// Но если значение само является выражением, нужно обработать его еще раз
if (value.startsWith("=")) {
qDebug() << "SpecificationController::parseExpression: Значение свойства является вложенным выражением, рекурсивно обрабатываем";
value = parseExpression(material, value);
}
}
// Добавляем значение к результату
if (!value.isEmpty()) {
if (!result.isEmpty()) {
result += value;
} else {
result = value;
}
qDebug() << "SpecificationController::parseExpression: Добавили к результату, текущий результат:" << result;
}
}
}
qDebug() << "SpecificationController::parseExpression: Финальный результат:" << result;
return result;
}
QStringList SpecificationController::collectPropertyNames()
{
QStringList propertyNames;
// Добавляем основные свойства материала
propertyNames << "Name" << "Value" << "Height" << "DielType" << "LayerNumber";
// Если дополнительные свойства не найдены в материалах, добавляем стандартные
if (propertyNames.size() <= 5) { // Только базовые свойства
propertyNames << "Format" << "Zone" << "Position" << "Designation" << "Quantity" << "Note";
qDebug() << "SpecificationController: Дополнительные свойства не найдены, используем стандартные:" << propertyNames;
}
// Добавляем специальное свойство для количества материалов в группе
propertyNames << "Quantity" << "Кол.";
return propertyNames;
}
// Методы для работы с децимальными номерами
QString SpecificationController::getDecimalNumberBoard() const
{
QStringList mappings = getColumnMappings();
if (mappings.size() > 7) {
QString fieldName = mappings[7];
if (!fieldName.isEmpty()) {
// Получаем значение из projectparamtable
if (m_mainController) {
ProjectParamTableModel *paramModel = m_mainController->projectParamTableModel();
if (paramModel) {
QMap<QString, QString> params = paramModel->getDataAsMap();
if (params.contains(fieldName)) {
return params[fieldName]; // Возвращаем значение, а не название поля
}
}
}
// Если не удалось получить значение из модели, возвращаем название поля
return fieldName;
}
}
return QString();
}
void SpecificationController::setDecimalNumberBoard(const QString &value)
{
QStringList mappings = getColumnMappings();
while (mappings.size() <= 7) {
mappings.append("");
}
mappings[7] = value;
setColumnMappings(mappings);
}
QString SpecificationController::getDecimalNumberDocument() const
{
QStringList mappings = getColumnMappings();
if (mappings.size() > 8) {
QString fieldName = mappings[8];
if (!fieldName.isEmpty()) {
// Получаем значение из projectparamtable
if (m_mainController) {
ProjectParamTableModel *paramModel = m_mainController->projectParamTableModel();
if (paramModel) {
QMap<QString, QString> params = paramModel->getDataAsMap();
if (params.contains(fieldName)) {
return params[fieldName]; // Возвращаем значение, а не название поля
}
}
}
// Если не удалось получить значение из модели, возвращаем название поля
return fieldName;
}
}
return QString();
}
void SpecificationController::setDecimalNumberDocument(const QString &value)
{
QStringList mappings = getColumnMappings();
while (mappings.size() <= 8) {
mappings.append("");
}
mappings[8] = value;
setColumnMappings(mappings);
}
void SpecificationController::setColumnMappings(const QStringList &mappings)
{
qDebug() << "SpecificationController::setColumnMappings: Устанавливаем новые настройки колонок:" << mappings;
m_columnMappings = mappings;
// Сохраняем настройки в ProjectSettingsModel
if (m_projectSettingsModel) {
for (int i = 0; i < mappings.size(); ++i) {
m_projectSettingsModel->setColumnMapping("Specification", i, mappings[i]);
}
qDebug() << "SpecificationController::setColumnMappings: Настройки сохранены в ProjectSettingsModel";
}
// Обновляем настройки в модели
if (m_tableModel) {
m_tableModel->setColumnMappings(mappings);
qDebug() << "SpecificationController::setColumnMappings: Настройки обновлены в модели";
}
qDebug() << "SpecificationController::setColumnMappings: Настройки колонок обновлены:" << m_columnMappings;
}
QStringList SpecificationController::getColumnMappings() const
{
// Если есть ProjectSettingsModel, читаем настройки из него
if (m_projectSettingsModel) {
QStringList settings = m_projectSettingsModel->getColumnMappings("Specification");
if (!settings.isEmpty()) {
qDebug() << "SpecificationController::getColumnMappings: Получены настройки из ProjectSettingsModel:" << settings;
return settings;
}
}
// Fallback: возвращаем локальные настройки
qDebug() << "SpecificationController::getColumnMappings: Возвращаем локальные настройки:" << m_columnMappings;
return m_columnMappings;
}
QStringList SpecificationController::getAvailableProperties() const
{
QStringList properties = m_propertyNames;
properties.prepend("<Пусто>");
properties.prepend("<Авто>");
return properties;
}
QString SpecificationController::getMaterialType(PCBMaterialModel *material)
{
if (!material) return "";
// Получаем тип материала из свойств
QString type = material->formatDielType(material->getMaterialDielType(0));
if (!type.isEmpty()) {
return type;
}
// Если тип не найден, используем fallback
return "Материал";
}
QPair<QString, QString> SpecificationController::splitDesignator(const QString &designator)
{
if (designator.isEmpty()) {
return QPair<QString, QString>("", "");
}
// Используем регулярное выражение для разделения буквенной и цифровой части
QRegExp regex("([A-Za-z]+)(\\d*)");
if (regex.indexIn(designator) != -1) {
QString letterPart = regex.cap(1);
QString numberPart = regex.cap(2);
return QPair<QString, QString>(letterPart, numberPart);
}
// Fallback: если регулярное выражение не сработало,
// ищем первую цифру и разделяем по ней
for (int i = 0; i < designator.length(); ++i) {
if (designator[i].isDigit()) {
QString letterPart = designator.left(i);
QString numberPart = designator.mid(i);
return QPair<QString, QString>(letterPart, numberPart);
}
}
// Если цифр нет, возвращаем весь десигнатор как буквенную часть
return QPair<QString, QString>(designator, "");
}
// Новые методы для управления строками
void SpecificationController::addEmptyRow()
{
if (m_tableModel) {
m_tableModel->addEmptyRow();
qDebug() << "SpecificationController::addEmptyRow: Добавлена пустая строка";
// Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
// m_tableModel->optimizePageBreaks();
}
}
void SpecificationController::addEmptyRowAt(int position)
{
if (m_tableModel) {
m_tableModel->addEmptyRowAt(position);
qDebug() << "SpecificationController::addEmptyRowAt: Добавлена пустая строка в позицию" << position;
// Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
// m_tableModel->optimizePageBreaks();
}
}
void SpecificationController::insertEmptyRowAt(int position)
{
if (m_tableModel) {
m_tableModel->addEmptyRowAt(position);
qDebug() << "SpecificationController::insertEmptyRowAt: Вставлена пустая строка в позицию" << position;
// Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
// m_tableModel->optimizePageBreaks();
}
}
void SpecificationController::removeRow(int row)
{
if (m_tableModel) {
m_tableModel->removeRow(row);
qDebug() << "SpecificationController::removeRow: Удалена строка" << row;
// Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
// m_tableModel->optimizePageBreaks();
}
}
void SpecificationController::clearTable()
{
if (m_tableModel) {
m_tableModel->clear();
qDebug() << "SpecificationController::clearTable: Таблица очищена";
}
}
void SpecificationController::optimizePageBreaks()
{
if (m_tableModel) {
qDebug() << "SpecificationController::optimizePageBreaks: Оптимизируем разрывы страниц";
m_tableModel->optimizePageBreaks();
}
}
int SpecificationController::getFontSize() const
{
if (m_projectSettingsModel) {
return m_projectSettingsModel->getFontSize("Specification");
}
return 12; // По умолчанию
}
void SpecificationController::setFontSize(int fontSize)
{
if (m_projectSettingsModel) {
m_projectSettingsModel->setFontSize("Specification", fontSize);
}
}
int SpecificationController::getFontStretch() const
{
if (m_projectSettingsModel) {
return m_projectSettingsModel->getFontStretch("Specification");
}
return 100; // По умолчанию (нормальный)
}
void SpecificationController::setFontStretch(int stretch)
{
if (m_projectSettingsModel) {
m_projectSettingsModel->setFontStretch("Specification", stretch);
}
}
QList<QString> SpecificationController::splitLongDesignation(const QString &designation, const QString originalString, PCBMaterialModel *material, int maxLength)
{
QList<QString> result;
if (designation.length() <= maxLength) {
result.append(designation);
return result;
}
qDebug() << "SpecificationController::splitLongDesignation: Разделяем длинное наименование:" << designation;
// Обычный текст - разделяем по пробелам
result = splitBySpaces(designation, maxLength);
qDebug() << "SpecificationController::splitLongDesignation: Результат разделения:" << result;
return result;
}
QList<QString> SpecificationController::splitBySpaces(const QString &text, int maxLength)
{
QList<QString> result;
if (text.length() <= maxLength) {
result.append(text);
return result;
}
// Ищем пробел, ближайший к середине строки
int targetLength = maxLength;
int bestSplitPos = -1;
int minDifference = text.length(); // Минимальная разница с целевой длиной
// Ищем пробелы в тексте
for (int i = 0; i < text.length(); ++i) {
if (text[i] == ' ') {
int leftLength = i;
int rightLength = text.length() - i - 1;
// Вычисляем разницу с целевой длиной
int leftDiff = abs(leftLength - targetLength);
int rightDiff = abs(rightLength - targetLength);
int totalDiff = leftDiff + rightDiff;
// Если эта позиция лучше предыдущей, запоминаем её
if (totalDiff < minDifference) {
minDifference = totalDiff;
bestSplitPos = i;
}
}
}
// Если нашли подходящий пробел, разделяем по нему
if (bestSplitPos != -1) {
QString leftPart = text.left(bestSplitPos).trimmed();
QString rightPart = text.mid(bestSplitPos + 1).trimmed();
// Рекурсивно обрабатываем обе части
if (!leftPart.isEmpty()) {
QList<QString> leftParts = splitBySpaces(leftPart, maxLength);
result.append(leftParts);
}
if (!rightPart.isEmpty()) {
QList<QString> rightParts = splitBySpaces(rightPart, maxLength);
result.append(rightParts);
}
} else {
// Если пробелов нет или не удалось найти подходящий, разбиваем посимвольно
// for (int i = 0; i < text.length(); i += maxLength) {
// result.append(text.mid(i, maxLength));
// }
result.append(text);
}
return result;
}
QString SpecificationController::getMaterialFormat(PCBMaterialModel *material)
{
if (!material) return "";
// Получаем формат из свойств материала
// Для материалов платы обычно используется стандартный формат
return "A4";
}
QString SpecificationController::getMaterialZone(PCBMaterialModel *material)
{
if (!material) return "";
// Получаем зону из свойств материала
// Для материалов платы зона обычно не указывается
return "";
}
QString SpecificationController::getMaterialPosition(PCBMaterialModel *material)
{
if (!material) return "";
// Для спецификации материалов позиция обычно совпадает с номером слоя
return QString::number(material->getMaterialLayerNumber(0));
}