Refactor specification handling in DocumentSettingsDialog and PDFController. Introduced primary application field for document types, updated export messages for consistency, and improved page number handling in specifications. Cleaned up unnecessary code in preview widgets.

This commit is contained in:
2025-12-23 14:12:50 +03:00
parent 129922e392
commit 80e407e6be
12 changed files with 349 additions and 105 deletions
+6
View File
@@ -5,3 +5,9 @@ IDI_ICON1 ICON DISCARDABLE "assets/icon2.ico"
+2 -2
View File
@@ -2585,7 +2585,7 @@ QString DataBaseController::getSpecificationTableInfo(const QString &projectName
query.addBindValue(projectName); query.addBindValue(projectName);
if (!query.exec() || !query.next()) { if (!query.exec() || !query.next()) {
setLastError("Ошибка получения информации о спецификации материалов: " + query.lastError().text()); setLastError("Ошибка получения информации о спецификации: " + query.lastError().text());
return QString(); return QString();
} }
@@ -2595,7 +2595,7 @@ QString DataBaseController::getSpecificationTableInfo(const QString &projectName
int minOrder = query.value(3).toInt(); int minOrder = query.value(3).toInt();
int maxOrder = query.value(4).toInt(); int maxOrder = query.value(4).toInt();
QString info = QString("Спецификация материалов для проекта '%1':\n" QString info = QString("Спецификация для проекта '%1':\n"
"Всего строк: %2\n" "Всего строк: %2\n"
"Заголовков: %3\n" "Заголовков: %3\n"
"Пустых строк: %4\n" "Пустых строк: %4\n"
+15 -3
View File
@@ -113,7 +113,7 @@ bool PDFController::exportPerechenToPdf(const QString &filePath, MainController
int pageNumber = 1; int pageNumber = 1;
// Вычисляем общее количество страниц заранее // Вычисляем общее количество страниц заранее
int totalPages = 2; int totalPages = 1;
int tempRow = 0; int tempRow = 0;
while (tempRow < totalRows) { while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages; int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
@@ -988,7 +988,18 @@ painter.drawText(mainTableRect.left()+165*mmToPixels, mainTableRect.top()+20*mmT
painter.drawText(60*mmToPixels,0, 60*mmToPixels, 5*mmToPixels, Qt::AlignCenter,"Перв. примен."); painter.drawText(60*mmToPixels,0, 60*mmToPixels, 5*mmToPixels, Qt::AlignCenter,"Перв. примен.");
painter.drawText(0,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 24)); painter.drawText(0,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 24));
painter.drawText(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 25)); // Определяем номер поля "Первичное применение" в зависимости от типа документа
int primaryApplicationField = 25; // По умолчанию
if (docType == 1) {
primaryApplicationField = 251; // Перечень
} else if (docType == 2) {
primaryApplicationField = 252; // Спецификация ПП
} else if (docType == 3) {
primaryApplicationField = 253; // Спецификация материалов
} else if (docType == 4) {
primaryApplicationField = 254; // Ведомость
}
painter.drawText(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, primaryApplicationField));
painter.restore(); painter.restore();
@@ -1351,7 +1362,8 @@ bool PDFController::addGostFrameA3FirstPage(QPainter &painter, const QRectF &pag
painter.drawText(60*mmToPixels,0, 60*mmToPixels, 5*mmToPixels, Qt::AlignCenter,"Перв. примен."); painter.drawText(60*mmToPixels,0, 60*mmToPixels, 5*mmToPixels, Qt::AlignCenter,"Перв. примен.");
painter.drawText(0,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 24)); painter.drawText(0,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 24));
painter.drawText(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 25)); // A3 формат используется только для ведомости, поэтому используем поле 254
painter.drawText(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 254));
painter.restore(); painter.restore();
+12 -11
View File
@@ -203,7 +203,17 @@ void SpecificationPCBController::generateTableFromComponents()
m_tableModel->addRow(pcbInfo); m_tableModel->addRow(pcbInfo);
m_tableModel->addRow(emptyRow); m_tableModel->addRow(emptyRow);
SpecificationPCBRowData headerRow2;
headerRow2.isHeader = true;
headerRow2.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.name = SpecificationPCBCellData("Детали", 0, 1, true, false, false, 100, true);
headerRow2.quantity = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
m_tableModel->addRow(headerRow2);
m_tableModel->addRow(emptyRow);
SpecificationPCBRowData headerRow2_1; SpecificationPCBRowData headerRow2_1;
headerRow2_1.isHeader = true; headerRow2_1.isHeader = true;
headerRow2_1.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true); headerRow2_1.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
@@ -215,16 +225,7 @@ void SpecificationPCBController::generateTableFromComponents()
headerRow2_1.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true); headerRow2_1.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
m_tableModel->addRow(headerRow2_1); m_tableModel->addRow(headerRow2_1);
m_tableModel->addRow(emptyRow); m_tableModel->addRow(emptyRow);
SpecificationPCBRowData headerRow2;
headerRow2.isHeader = true;
headerRow2.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.name = SpecificationPCBCellData("Детали", 0, 1, true, false, false, 100, true);
headerRow2.quantity = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
headerRow2.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
m_tableModel->addRow(headerRow2);
SpecificationPCBRowData headerRow3; SpecificationPCBRowData headerRow3;
headerRow3.isHeader = true; headerRow3.isHeader = true;
+30 -4
View File
@@ -1018,10 +1018,14 @@ void SpecificationPCBTableModel::updatePageNumbers()
int currentRow = 0; int currentRow = 0;
int currentPage = 1; int currentPage = 1;
int rowsOnCurrentPage = 0; int rowsOnCurrentPage = 0;
bool pageNumbersChanged = false;
for (int i = 0; i < m_rows.size(); ++i) { for (int i = 0; i < m_rows.size(); ++i) {
SpecificationPCBRowData &row = m_rows[i]; SpecificationPCBRowData &row = m_rows[i];
// Сохраняем старый номер страницы для проверки изменений
int oldPageNumber = row.pageNumber;
// Определяем, сколько строк помещается на текущей странице // Определяем, сколько строк помещается на текущей странице
int maxRowsOnPage = (currentPage == 1) ? ROWS_PER_FIRST_PAGE : ROWS_PER_OTHER_PAGE; int maxRowsOnPage = (currentPage == 1) ? ROWS_PER_FIRST_PAGE : ROWS_PER_OTHER_PAGE;
@@ -1032,6 +1036,11 @@ void SpecificationPCBTableModel::updatePageNumbers()
maxRowsOnPage = ROWS_PER_OTHER_PAGE; // Начиная со второй страницы maxRowsOnPage = ROWS_PER_OTHER_PAGE; // Начиная со второй страницы
} }
// Проверяем, изменился ли номер страницы
if (oldPageNumber != currentPage) {
pageNumbersChanged = true;
}
// Устанавливаем номер страницы для строки // Устанавливаем номер страницы для строки
row.pageNumber = currentPage; row.pageNumber = currentPage;
row.format.pageNumber = currentPage; row.format.pageNumber = currentPage;
@@ -1052,8 +1061,9 @@ void SpecificationPCBTableModel::updatePageNumbers()
qDebug() << "SpecificationPCBTableModel::updatePageNumbers: Обновление завершено, всего страниц:" << currentPage; qDebug() << "SpecificationPCBTableModel::updatePageNumbers: Обновление завершено, всего страниц:" << currentPage;
// Уведомляем UI об изменении данных для обновления отображения страниц // Уведомляем UI об изменении данных ТОЛЬКО если номера страниц действительно изменились
if (!m_rows.isEmpty()) { // Это критично для производительности при редактировании больших таблиц
if (pageNumbersChanged && !m_rows.isEmpty()) {
emit dataChanged(index(0, 0), index(m_rows.size() - 1, COLUMN_COUNT - 1), emit dataChanged(index(0, 0), index(m_rows.size() - 1, COLUMN_COUNT - 1),
QVector<int>() << Qt::BackgroundRole); QVector<int>() << Qt::BackgroundRole);
emit headerDataChanged(Qt::Vertical, 0, m_rows.size() - 1); emit headerDataChanged(Qt::Vertical, 0, m_rows.size() - 1);
@@ -1264,11 +1274,27 @@ void SpecificationPCBTableModel::updatePageDisplay()
{ {
qDebug() << "SpecificationPCBTableModel::updatePageDisplay: Обновляем отображение страниц в UI"; qDebug() << "SpecificationPCBTableModel::updatePageDisplay: Обновляем отображение страниц в UI";
// Сохраняем старые номера страниц для проверки изменений
QList<int> oldPageNumbers;
for (const SpecificationPCBRowData &row : m_rows) {
oldPageNumbers.append(row.pageNumber);
}
// Обновляем номера страниц // Обновляем номера страниц
updatePageNumbers(); updatePageNumbers();
// Уведомляем UI об изменении всех данных для обновления отображения // Проверяем, изменились ли номера страниц
if (!m_rows.isEmpty()) { bool pageNumbersChanged = false;
for (int i = 0; i < m_rows.size() && i < oldPageNumbers.size(); ++i) {
if (m_rows[i].pageNumber != oldPageNumbers[i]) {
pageNumbersChanged = true;
break;
}
}
// Уведомляем UI об изменении данных ТОЛЬКО если номера страниц действительно изменились
// Это критично для производительности при редактировании больших таблиц
if (pageNumbersChanged && !m_rows.isEmpty()) {
emit dataChanged(index(0, 0), index(m_rows.size() - 1, COLUMN_COUNT - 1), emit dataChanged(index(0, 0), index(m_rows.size() - 1, COLUMN_COUNT - 1),
QVector<int>() << Qt::BackgroundRole); QVector<int>() << Qt::BackgroundRole);
+23
View File
@@ -1339,6 +1339,29 @@ void DocumentEditWidget::onRemoveRow()
return; return;
} }
// Проверяем, является ли процессор SpecificationProcessor
SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
if (specProcessor) {
// Проверяем, можно ли удалить эту строку
if (m_controller && m_controller->specificationTableModel()) {
if (!m_controller->specificationTableModel()->canEditRow(row)) {
qDebug() << "DocumentEditWidget::onRemoveRow: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
return;
}
}
qDebug() << "DocumentEditWidget::onRemoveRow: Удаляем строку" << row;
// Получаем контроллер и удаляем строку
if (m_controller && m_controller->specificationController()) {
m_controller->specificationController()->removeRow(row);
qDebug() << "DocumentEditWidget::onRemoveRow: Строка удалена через SpecificationController";
} else {
qDebug() << "DocumentEditWidget::onRemoveRow: SpecificationController недоступен";
}
return;
}
// Проверяем, является ли процессор VedomostProcessor // Проверяем, является ли процессор VedomostProcessor
VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor); VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
if (vedomostProcessor) { if (vedomostProcessor) {
+226 -7
View File
@@ -45,6 +45,10 @@ void DocumentSettingsDialog::initializeFieldData()
s_fieldNames[22] = "Инв. номер дубликата"; s_fieldNames[22] = "Инв. номер дубликата";
s_fieldNames[24] = "Обозначение документа (взамен) / Справ. №"; s_fieldNames[24] = "Обозначение документа (взамен) / Справ. №";
s_fieldNames[25] = "Обозначение соответствующего документа / Перв. примен."; s_fieldNames[25] = "Обозначение соответствующего документа / Перв. примен.";
s_fieldNames[251] = "Первичное применение (Перечень)";
s_fieldNames[252] = "Первичное применение (Спецификация ПП)";
s_fieldNames[253] = "Первичное применение (Спецификация)";
s_fieldNames[254] = "Первичное применение (Ведомость)";
s_fieldNames[301]= "Наименование документа"; s_fieldNames[301]= "Наименование документа";
s_fieldNames[1002] = "Название документа"; s_fieldNames[1002] = "Название документа";
@@ -77,6 +81,8 @@ DocumentSettingsDialog::DocumentSettingsDialog(DocumentType docType, MainControl
, m_controller(controller) , m_controller(controller)
, m_projectParamModel(nullptr) , m_projectParamModel(nullptr)
, m_titleInscriptionsModel(nullptr) , m_titleInscriptionsModel(nullptr)
, m_primaryApplicationComboBox(nullptr)
, m_primaryApplicationFieldNumber(0)
{ {
qDebug() << "DocumentSettingsDialog: Конструктор для типа документа:" << static_cast<int>(docType); qDebug() << "DocumentSettingsDialog: Конструктор для типа документа:" << static_cast<int>(docType);
@@ -118,6 +124,9 @@ void DocumentSettingsDialog::setUp()
loadDecimalNumberSettings(); loadDecimalNumberSettings();
} }
// Загружаем настройки "Первичное применение" для всех типов документов
loadPrimaryApplicationSettings();
qDebug() << "DocumentSettingsDialog::setUp: Настройка диалога завершена"; qDebug() << "DocumentSettingsDialog::setUp: Настройка диалога завершена";
} }
@@ -166,6 +175,9 @@ void DocumentSettingsDialog::createTableSettingsTab()
createDecimalNumberFields(); createDecimalNumberFields();
} }
// Создаем поле "Первичное применение" для всех типов документов
createPrimaryApplicationField();
// Создаем поле "Куда входит" для ведомости // Создаем поле "Куда входит" для ведомости
if (m_documentType == DocumentType::Vedomost) { if (m_documentType == DocumentType::Vedomost) {
createWhereUsedField(); createWhereUsedField();
@@ -551,6 +563,95 @@ void DocumentSettingsDialog::createWhereUsedField()
qDebug() << "DocumentSettingsDialog::createWhereUsedField: Поле 'Куда входит' создано"; qDebug() << "DocumentSettingsDialog::createWhereUsedField: Поле 'Куда входит' создано";
} }
void DocumentSettingsDialog::createPrimaryApplicationField()
{
qDebug() << "DocumentSettingsDialog::createPrimaryApplicationField: Создаем поле 'Первичное применение'";
// Определяем номер поля в зависимости от типа документа
int fieldNumber = 0;
QString fieldLabelText;
switch (m_documentType) {
case DocumentType::Perechen:
fieldNumber = 251;
fieldLabelText = "Первичное применение (Перечень):";
break;
case DocumentType::SpecificationPCB:
fieldNumber = 252;
fieldLabelText = "Первичное применение (Спецификация ПП):";
break;
case DocumentType::Specification:
fieldNumber = 253;
fieldLabelText = "Первичное применение (Спецификация):";
break;
case DocumentType::Vedomost:
fieldNumber = 254;
fieldLabelText = "Первичное применение (Ведомость):";
break;
default:
return;
}
// Создаем группу для поля "Первичное применение"
QGroupBox *primaryAppGroup = new QGroupBox("Первичное применение", m_tableScrollContent);
QGridLayout *primaryAppLayout = new QGridLayout(primaryAppGroup);
// Поле "Первичное применение"
QLabel *primaryAppLabel = new QLabel(fieldLabelText, primaryAppGroup);
primaryAppLayout->addWidget(primaryAppLabel, 0, 0);
QComboBox *primaryAppComboBox = new QComboBox(primaryAppGroup);
primaryAppComboBox->setEditable(true);
primaryAppComboBox->addItem("-- Не выбрано --", "");
// Добавляем параметры проекта в комбобокс
if (m_projectParamModel) {
QMap<QString, QString> projectParams = m_projectParamModel->getDataAsMap();
for (auto it = projectParams.begin(); it != projectParams.end(); ++it) {
QString paramName = it.key();
QString paramValue = it.value();
// Формируем отображаемый текст: "Название (значение)" если значение не пустое
QString displayText = paramName;
if (!paramValue.isEmpty()) {
displayText += QString(" (%1)").arg(paramValue);
}
primaryAppComboBox->addItem(displayText, paramName);
}
}
// Соединяем сигнал изменения
connect(primaryAppComboBox, QOverload<const QString &>::of(&QComboBox::currentTextChanged),
[this, fieldNumber](const QString &value) {
onPrimaryApplicationComboBoxChanged(fieldNumber, value);
});
// Добавляем комбобокс в компоновку
primaryAppLayout->addWidget(primaryAppComboBox, 0, 1);
// Сохраняем ссылку на комбобокс
m_primaryApplicationComboBox = primaryAppComboBox;
m_primaryApplicationFieldNumber = fieldNumber;
// Добавляем группу в основную компоновку таблицы
QGridLayout *mainGridLayout = qobject_cast<QGridLayout*>(m_tableScrollContent->layout());
if (mainGridLayout) {
int row = mainGridLayout->rowCount();
mainGridLayout->addWidget(primaryAppGroup, row, 0, 1, 2);
} else {
// Если основная компоновка не является QGridLayout, создаем новую
QVBoxLayout *mainLayout = qobject_cast<QVBoxLayout*>(m_tableScrollContent->layout());
if (mainLayout) {
mainLayout->addWidget(primaryAppGroup);
} else {
QVBoxLayout *newLayout = new QVBoxLayout(m_tableScrollContent);
newLayout->addWidget(primaryAppGroup);
}
}
qDebug() << "DocumentSettingsDialog::createPrimaryApplicationField: Поле 'Первичное применение' создано для поля" << fieldNumber;
}
void DocumentSettingsDialog::createFontSettingsFields() void DocumentSettingsDialog::createFontSettingsFields()
{ {
qDebug() << "DocumentSettingsDialog::createFontSettingsFields: Создаем поля настроек шрифта"; qDebug() << "DocumentSettingsDialog::createFontSettingsFields: Создаем поля настроек шрифта";
@@ -816,7 +917,8 @@ QStringList DocumentSettingsDialog::getDefaultTableMappings() const
QList<int> DocumentSettingsDialog::getRequiredInscriptionFields() const QList<int> DocumentSettingsDialog::getRequiredInscriptionFields() const
{ {
// Общие обязательные поля для всех документов // Общие обязательные поля для всех документов
return {1, 2, 4, 9, 10, 11, 111, 112, 113, 114, 25}; // Поле 25 (Первичное применение) теперь находится в настройках таблицы как 251-254
return {1, 2, 4, 9, 10, 11, 111, 112, 113, 114};
} }
QList<int> DocumentSettingsDialog::getOptionalInscriptionFields() const QList<int> DocumentSettingsDialog::getOptionalInscriptionFields() const
@@ -1146,22 +1248,24 @@ void DocumentSettingsDialog::saveInscriptionSettings()
qDebug() << "DocumentSettingsDialog::saveInscriptionSettings: Сохраняем настройки надписей"; qDebug() << "DocumentSettingsDialog::saveInscriptionSettings: Сохраняем настройки надписей";
if (m_titleInscriptionsModel) { if (m_titleInscriptionsModel) {
QMap<int, QString> values; // Обновляем только поля из таба основных надписей, не заменяя все поля
// Это важно, чтобы не потерять поля 251-254 (Первичное применение)
for (auto it = m_inscriptionFields.begin(); it != m_inscriptionFields.end(); ++it) { for (auto it = m_inscriptionFields.begin(); it != m_inscriptionFields.end(); ++it) {
int fieldNumber = it.key(); int fieldNumber = it.key();
const TitleInscriptionFieldExtended &field = it.value(); const TitleInscriptionFieldExtended &field = it.value();
if (!field.currentValue.isEmpty()) { if (!field.currentValue.isEmpty()) {
values[fieldNumber] = field.currentValue; m_titleInscriptionsModel->setInscriptionValue(fieldNumber, field.currentValue);
} else {
m_titleInscriptionsModel->setInscriptionValue(fieldNumber, "");
} }
} }
m_titleInscriptionsModel->setAllInscriptions(values);
// Сохраняем в базу данных через контроллер // Сохраняем в базу данных через контроллер
// Сохраняем все надписи из модели, как это делают остальные поля
if (m_controller) { if (m_controller) {
m_controller->saveTitleInscriptionsToDatabase(values); QMap<int, QString> allInscriptions = m_titleInscriptionsModel->getAllInscriptions();
m_controller->saveTitleInscriptionsToDatabase(allInscriptions);
} }
} }
@@ -1264,6 +1368,9 @@ void DocumentSettingsDialog::onAccept()
saveDecimalNumberSettings(); saveDecimalNumberSettings();
} }
// Сохраняем настройки "Первичное применение" для всех типов документов
savePrimaryApplicationSettings();
accept(); accept();
} }
@@ -1617,6 +1724,118 @@ void DocumentSettingsDialog::saveDecimalNumberSettings()
} }
} }
void DocumentSettingsDialog::loadPrimaryApplicationSettings()
{
qDebug() << "DocumentSettingsDialog::loadPrimaryApplicationSettings: Загружаем настройки 'Первичное применение'";
if (!m_primaryApplicationComboBox || m_primaryApplicationFieldNumber == 0) {
qDebug() << "DocumentSettingsDialog::loadPrimaryApplicationSettings: Поле 'Первичное применение' не создано";
return;
}
// Загружаем значение из titleInscriptionsModel
if (m_titleInscriptionsModel) {
QString value = m_titleInscriptionsModel->getInscriptionValue(m_primaryApplicationFieldNumber);
if (!value.isEmpty()) {
// Пытаемся найти значение в списке по itemData (название поля)
int index = m_primaryApplicationComboBox->findData(value);
if (index >= 0) {
m_primaryApplicationComboBox->setCurrentIndex(index);
} else {
// Если не найдено в списке, устанавливаем как кастомный текст
m_primaryApplicationComboBox->setCurrentText(value);
}
qDebug() << "DocumentSettingsDialog::loadPrimaryApplicationSettings: Загружено значение из поля" << m_primaryApplicationFieldNumber << ":" << value;
} else {
// Если значение пустое, устанавливаем "-- Не выбрано --"
m_primaryApplicationComboBox->setCurrentIndex(0);
}
}
}
void DocumentSettingsDialog::savePrimaryApplicationSettings()
{
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Сохраняем настройки 'Первичное применение'";
if (!m_primaryApplicationComboBox || m_primaryApplicationFieldNumber == 0) {
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Поле 'Первичное применение' не создано";
return;
}
QString value = m_primaryApplicationComboBox->currentText();
// Если выбрано "-- Не выбрано --", очищаем поле
if (value == "-- Не выбрано --" || value.isEmpty()) {
if (m_titleInscriptionsModel) {
m_titleInscriptionsModel->setInscriptionValue(m_primaryApplicationFieldNumber, "");
}
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Очищено поле" << m_primaryApplicationFieldNumber;
} else {
// Получаем значение: если это предустановленное значение, берем itemData, иначе текст
int index = m_primaryApplicationComboBox->findText(value);
if (index >= 0) {
QString fieldName = m_primaryApplicationComboBox->itemData(index).toString();
if (!fieldName.isEmpty()) {
// Это предустановленное значение - сохраняем название поля
if (m_titleInscriptionsModel) {
m_titleInscriptionsModel->setInscriptionValue(m_primaryApplicationFieldNumber, fieldName);
}
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Сохранено предустановленное значение в поле" << m_primaryApplicationFieldNumber << ":" << fieldName;
} else {
// Это кастомный ввод - сохраняем текст
if (m_titleInscriptionsModel) {
m_titleInscriptionsModel->setInscriptionValue(m_primaryApplicationFieldNumber, value);
}
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Сохранено кастомное значение в поле" << m_primaryApplicationFieldNumber << ":" << value;
}
} else {
// Кастомный ввод - сохраняем текст
if (m_titleInscriptionsModel) {
m_titleInscriptionsModel->setInscriptionValue(m_primaryApplicationFieldNumber, value);
}
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Сохранено кастомное значение в поле" << m_primaryApplicationFieldNumber << ":" << value;
}
// Сохраняем в базу данных через контроллер
// Сохраняем все надписи из модели, как это делают остальные поля
if (m_controller && m_titleInscriptionsModel) {
QMap<int, QString> allInscriptions = m_titleInscriptionsModel->getAllInscriptions();
m_controller->saveTitleInscriptionsToDatabase(allInscriptions);
qDebug() << "DocumentSettingsDialog::savePrimaryApplicationSettings: Сохранены все надписи из модели, включая поле" << m_primaryApplicationFieldNumber;
}
}
}
void DocumentSettingsDialog::onPrimaryApplicationComboBoxChanged(int fieldNumber, const QString &value)
{
qDebug() << "DocumentSettingsDialog::onPrimaryApplicationComboBoxChanged: Изменено значение поля" << fieldNumber << "на" << value;
// Обновляем значение в модели (но не сохраняем в базу данных до нажатия ОК)
if (m_titleInscriptionsModel) {
if (value == "-- Не выбрано --" || value.isEmpty()) {
m_titleInscriptionsModel->setInscriptionValue(fieldNumber, "");
} else {
// Получаем значение: если это предустановленное значение, берем itemData, иначе текст
if (m_primaryApplicationComboBox) {
int index = m_primaryApplicationComboBox->findText(value);
if (index >= 0) {
QString fieldName = m_primaryApplicationComboBox->itemData(index).toString();
if (!fieldName.isEmpty()) {
// Это предустановленное значение - сохраняем название поля
m_titleInscriptionsModel->setInscriptionValue(fieldNumber, fieldName);
} else {
// Это кастомный ввод - сохраняем текст
m_titleInscriptionsModel->setInscriptionValue(fieldNumber, value);
}
} else {
// Кастомный ввод - сохраняем текст
m_titleInscriptionsModel->setInscriptionValue(fieldNumber, value);
}
}
}
}
}
// Публичные методы // Публичные методы
QStringList DocumentSettingsDialog::getTableColumnMappings() const QStringList DocumentSettingsDialog::getTableColumnMappings() const
{ {
+10
View File
@@ -133,6 +133,10 @@ private:
QMap<QString, QComboBox*> m_decimalNumberComboBoxes; QMap<QString, QComboBox*> m_decimalNumberComboBoxes;
QMap<QString, QString> m_decimalNumberValues; QMap<QString, QString> m_decimalNumberValues;
// Поля для "Первичное применение"
QComboBox *m_primaryApplicationComboBox;
int m_primaryApplicationFieldNumber;
// Статические данные о графах ГОСТ // Статические данные о графах ГОСТ
static QMap<int, QString> s_fieldNames; static QMap<int, QString> s_fieldNames;
static QMap<int, QString> s_fieldDescriptions; static QMap<int, QString> s_fieldDescriptions;
@@ -146,6 +150,12 @@ private:
void onDecimalNumberComboBoxChanged(const QString &fieldName, const QString &value); void onDecimalNumberComboBoxChanged(const QString &fieldName, const QString &value);
void updateDecimalNumberFieldValue(const QString &type, const QString &value); void updateDecimalNumberFieldValue(const QString &type, const QString &value);
// Методы для работы с полем "Первичное применение"
void createPrimaryApplicationField();
void loadPrimaryApplicationSettings();
void savePrimaryApplicationSettings();
void onPrimaryApplicationComboBoxChanged(int fieldNumber, const QString &value);
// Методы для работы с настройками шрифта // Методы для работы с настройками шрифта
void createFontSettingsFields(); void createFontSettingsFields();
void loadFontSettings(); void loadFontSettings();
+1 -1
View File
@@ -140,7 +140,7 @@ void EditPDFWidget::setUpConnections(){
QString documentType; QString documentType;
switch (index) { switch (index) {
case 0: // Спецификация case 0: // Спецификация
documentType = "Спецификация материалов"; documentType = "Спецификация";
break; break;
case 1: // Спецификация ПП case 1: // Спецификация ПП
documentType = "Спецификация PCB"; documentType = "Спецификация PCB";
+11 -11
View File
@@ -752,25 +752,25 @@ void MainWindow::onExportSpecification(){
QString defaultPath = QCoreApplication::applicationDirPath() + "/" + fileNameBase + ".pdf"; QString defaultPath = QCoreApplication::applicationDirPath() + "/" + fileNameBase + ".pdf";
QString fileName = QFileDialog::getSaveFileName( QString fileName = QFileDialog::getSaveFileName(
this, this,
tr("Экспорт спецификации материалов"), tr("Экспорт спецификации"),
defaultPath, defaultPath,
tr("PDF файлы (*.pdf)") tr("PDF файлы (*.pdf)")
); );
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
m_statusBar->showMessage(tr("Экспорт спецификации материалов: %1").arg(fileName)); m_statusBar->showMessage(tr("Экспорт спецификации: %1").arg(fileName));
// Экспортируем в PDF через MainController // Экспортируем в PDF через MainController
if (m_controller->exportSpecificationToPdf(fileName)) { if (m_controller->exportSpecificationToPdf(fileName)) {
m_statusBar->showMessage(tr("Спецификация материалов успешно экспортирована: %1").arg(fileName)); m_statusBar->showMessage(tr("Спецификация успешно экспортирована: %1").arg(fileName));
// Автоматически открываем созданный PDF файл // Автоматически открываем созданный PDF файл
QUrl fileUrl = QUrl::fromLocalFile(fileName); QUrl fileUrl = QUrl::fromLocalFile(fileName);
QDesktopServices::openUrl(fileUrl); QDesktopServices::openUrl(fileUrl);
} else { } else {
m_statusBar->showMessage(tr("Ошибка экспорта спецификации материалов")); m_statusBar->showMessage(tr("Ошибка экспорта спецификации"));
QMessageBox::critical(this, tr("Ошибка"), QMessageBox::critical(this, tr("Ошибка"),
tr("Не удалось экспортировать спецификацию материалов")); tr("Не удалось экспортировать спецификацию"));
} }
} }
} }
@@ -982,23 +982,23 @@ void MainWindow::onExportSpecificationToCsv()
QString defaultPath = QCoreApplication::applicationDirPath() + "/Спецификация.csv"; QString defaultPath = QCoreApplication::applicationDirPath() + "/Спецификация.csv";
QString fileName = QFileDialog::getSaveFileName( QString fileName = QFileDialog::getSaveFileName(
this, this,
tr("Экспорт спецификации материалов в CSV"), tr("Экспорт спецификации в CSV"),
defaultPath, defaultPath,
tr("CSV файлы (*.csv);;Все файлы (*)") tr("CSV файлы (*.csv);;Все файлы (*)")
); );
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
m_statusBar->showMessage(tr("Экспорт спецификации материалов в CSV: %1").arg(fileName)); m_statusBar->showMessage(tr("Экспорт спецификации в CSV: %1").arg(fileName));
// Экспортируем в CSV через MainController // Экспортируем в CSV через MainController
if (m_controller->exportSpecificationToCsv(fileName)) { if (m_controller->exportSpecificationToCsv(fileName)) {
m_statusBar->showMessage(tr("Спецификация материалов успешно экспортирована в CSV: %1").arg(fileName)); m_statusBar->showMessage(tr("Спецификация успешно экспортирована в CSV: %1").arg(fileName));
QMessageBox::information(this, tr("Успех"), QMessageBox::information(this, tr("Успех"),
tr("Спецификация материалов успешно экспортирована в CSV:\n%1").arg(fileName)); tr("Спецификация успешно экспортирована в CSV:\n%1").arg(fileName));
} else { } else {
m_statusBar->showMessage(tr("Ошибка экспорта спецификации материалов в CSV")); m_statusBar->showMessage(tr("Ошибка экспорта спецификации в CSV"));
QMessageBox::critical(this, tr("Ошибка"), QMessageBox::critical(this, tr("Ошибка"),
tr("Не удалось экспортировать спецификацию материалов в CSV")); tr("Не удалось экспортировать спецификацию в CSV"));
} }
} }
} }
+12 -62
View File
@@ -10,11 +10,10 @@
#include <QApplication> #include <QApplication>
#include <QScreen> #include <QScreen>
#include <QDebug> // Added for qDebug #include <QDebug> // Added for qDebug
#include <QTimer>
// Константы // Константы
const int PreviewPdfWidget::ZOOM_LEVELS[] = {25, 50, 75, 100, 125, 150, 200}; const int PreviewPdfWidget::ZOOM_LEVELS[] = {25, 50, 75, 100, 125, 150, 200};
const QStringList PreviewPdfWidget::DOCUMENT_TYPES = {"Перечень элементов", "Спецификация PCB", "Спецификация материалов", "Ведомость покупных изделий"}; const QStringList PreviewPdfWidget::DOCUMENT_TYPES = {"Перечень элементов", "Спецификация PCB", "Спецификация", "Ведомость покупных изделий"};
// Дополнительные константы для мелкого масштабирования // Дополнительные константы для мелкого масштабирования
const int PreviewPdfWidget::FINE_ZOOM_STEP = 5; // Шаг для Ctrl+колесико (5%) const int PreviewPdfWidget::FINE_ZOOM_STEP = 5; // Шаг для Ctrl+колесико (5%)
@@ -44,16 +43,10 @@ PreviewPdfWidget::PreviewPdfWidget(QWidget *parent)
: QWidget{parent} : QWidget{parent}
, m_mainController(nullptr) , m_mainController(nullptr)
, m_pdfController(nullptr) , m_pdfController(nullptr)
, m_updateTimer(new QTimer(this))
, m_currentPage(0) , m_currentPage(0)
, m_currentZoom(100) , m_currentZoom(100)
, m_currentDocumentType("Перечень элементов") , m_currentDocumentType("Перечень элементов")
{ {
// Настраиваем таймер для отложенного обновления (500 мс задержка)
m_updateTimer->setSingleShot(true);
m_updateTimer->setInterval(500);
connect(m_updateTimer, &QTimer::timeout, this, &PreviewPdfWidget::updatePreview);
setUp(); setUp();
} }
@@ -78,6 +71,7 @@ void PreviewPdfWidget::setWidgets(){
m_prevPageBtn = new QPushButton("", this); m_prevPageBtn = new QPushButton("", this);
m_nextPageBtn = new QPushButton("", this); m_nextPageBtn = new QPushButton("", this);
m_refreshBtn = new QPushButton("Обновить", this);
m_pageInfoLabel = new QLabel("Страница 1 из 1", this); m_pageInfoLabel = new QLabel("Страница 1 из 1", this);
// Создаем область прокрутки для страниц // Создаем область прокрутки для страниц
@@ -119,6 +113,9 @@ void PreviewPdfWidget::setUpLayout(){
m_controlsLayout->addWidget(m_nextPageBtn); m_controlsLayout->addWidget(m_nextPageBtn);
m_controlsLayout->addWidget(m_pageInfoLabel); m_controlsLayout->addWidget(m_pageInfoLabel);
m_controlsLayout->addSpacing(20);
m_controlsLayout->addWidget(m_refreshBtn);
m_controlsLayout->addStretch(); m_controlsLayout->addStretch();
// Добавляем все в основной layout // Добавляем все в основной layout
@@ -154,6 +151,7 @@ void PreviewPdfWidget::setUpConnections(){
renderPage(m_currentPage); renderPage(m_currentPage);
} }
}); });
connect(m_refreshBtn, &QPushButton::clicked, this, &PreviewPdfWidget::updatePreview);
// Подключаем сигнал масштабирования от ZoomableScrollArea // Подключаем сигнал масштабирования от ZoomableScrollArea
connect(m_scrollArea, &ZoomableScrollArea::zoomRequested, connect(m_scrollArea, &ZoomableScrollArea::zoomRequested,
@@ -180,59 +178,11 @@ void PreviewPdfWidget::setMainController(MainController *mainController)
if (m_mainController) { if (m_mainController) {
m_pdfController = m_mainController->pdfController(); m_pdfController = m_mainController->pdfController();
qDebug() << "PreviewPdfWidget::setMainController: PDFController получен из MainController:" << m_pdfController; qDebug() << "PreviewPdfWidget::setMainController: PDFController получен из MainController:" << m_pdfController;
// Подключаемся к сигналам изменения данных (используем отложенное обновление)
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->perechenTableModel()), &QAbstractItemModel::dataChanged,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->perechenTableModel()), &QAbstractItemModel::modelReset,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->perechenTableModel()), &QAbstractItemModel::rowsInserted,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->perechenTableModel()), &QAbstractItemModel::rowsRemoved,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationPCBTableModel()), &QAbstractItemModel::dataChanged,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationPCBTableModel()), &QAbstractItemModel::modelReset,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationPCBTableModel()), &QAbstractItemModel::rowsInserted,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationPCBTableModel()), &QAbstractItemModel::rowsRemoved,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationTableModel()), &QAbstractItemModel::dataChanged,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationTableModel()), &QAbstractItemModel::modelReset,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationTableModel()), &QAbstractItemModel::rowsInserted,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->specificationTableModel()), &QAbstractItemModel::rowsRemoved,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->vedomostTableModel()), &QAbstractItemModel::dataChanged,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->vedomostTableModel()), &QAbstractItemModel::modelReset,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->vedomostTableModel()), &QAbstractItemModel::rowsInserted,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->vedomostTableModel()), &QAbstractItemModel::rowsRemoved,
this, [this]() { m_updateTimer->start(); });
// Подключаемся к сигналам изменения данных TitleInscriptionsModel
connect(m_mainController->titleInscriptionsModel(), &TitleInscriptionsModel::dataChanged,
this, [this]() {
qDebug() << "PreviewPdfWidget: Получен сигнал dataChanged от TitleInscriptionsModel";
m_updateTimer->start();
});
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->projectParamTableModel()), &QAbstractItemModel::dataChanged,
this, [this]() { m_updateTimer->start(); });
connect(reinterpret_cast<QAbstractItemModel*>(m_mainController->projectParamTableModel()), &QAbstractItemModel::modelReset,
this, [this]() { m_updateTimer->start(); });
} else { } else {
m_pdfController = nullptr; m_pdfController = nullptr;
} }
// Обновляем превью при первой установке контроллера
updatePreview(); updatePreview();
} }
@@ -261,7 +211,7 @@ void PreviewPdfWidget::updatePreview()
qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в спецификации PCB:" << m_mainController->specificationPCBTableModel()->rowCount(); qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в спецификации PCB:" << m_mainController->specificationPCBTableModel()->rowCount();
} }
if (m_mainController->specificationTableModel()) { if (m_mainController->specificationTableModel()) {
qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в спецификации материалов:" << m_mainController->specificationTableModel()->rowCount(); qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в спецификации:" << m_mainController->specificationTableModel()->rowCount();
} }
if (m_mainController->vedomostTableModel()) { if (m_mainController->vedomostTableModel()) {
qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в ведомости покупных изделий:" << m_mainController->vedomostTableModel()->rowCount(); qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в ведомости покупных изделий:" << m_mainController->vedomostTableModel()->rowCount();
@@ -320,10 +270,10 @@ void PreviewPdfWidget::generatePages()
qDebug() << "PreviewPdfWidget::generatePages: Вызываем getSpecificationPcbPagesInfo"; qDebug() << "PreviewPdfWidget::generatePages: Вызываем getSpecificationPcbPagesInfo";
m_pagesInfo = m_pdfController->getSpecificationPcbPagesInfo(m_mainController); m_pagesInfo = m_pdfController->getSpecificationPcbPagesInfo(m_mainController);
qDebug() << "PreviewPdfWidget::generatePages: Получено страниц спецификации PCB:" << m_pagesInfo.size(); qDebug() << "PreviewPdfWidget::generatePages: Получено страниц спецификации PCB:" << m_pagesInfo.size();
} else if (m_currentDocumentType == "Спецификация материалов") { } else if (m_currentDocumentType == "Спецификация") {
qDebug() << "PreviewPdfWidget::generatePages: Вызываем getSpecificationPagesInfo"; qDebug() << "PreviewPdfWidget::generatePages: Вызываем getSpecificationPagesInfo";
m_pagesInfo = m_pdfController->getSpecificationPagesInfo(m_mainController); m_pagesInfo = m_pdfController->getSpecificationPagesInfo(m_mainController);
qDebug() << "PreviewPdfWidget::generatePages: Получено страниц спецификации материалов:" << m_pagesInfo.size(); qDebug() << "PreviewPdfWidget::generatePages: Получено страниц спецификации:" << m_pagesInfo.size();
} else if (m_currentDocumentType == "Ведомость покупных изделий") { } else if (m_currentDocumentType == "Ведомость покупных изделий") {
qDebug() << "PreviewPdfWidget::generatePages: Вызываем getVedomostPagesInfo"; qDebug() << "PreviewPdfWidget::generatePages: Вызываем getVedomostPagesInfo";
m_pagesInfo = m_pdfController->getVedomostPagesInfo(m_mainController); m_pagesInfo = m_pdfController->getVedomostPagesInfo(m_mainController);
@@ -384,9 +334,9 @@ QPixmap PreviewPdfWidget::createPagePixmap(const PageInfo &pageInfo)
} else if (m_currentDocumentType == "Спецификация PCB") { } else if (m_currentDocumentType == "Спецификация PCB") {
success = m_pdfController->drawSpecificationPcbPage(painter, pageInfo, m_mainController); success = m_pdfController->drawSpecificationPcbPage(painter, pageInfo, m_mainController);
qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования спецификации PCB:" << success; qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования спецификации PCB:" << success;
} else if (m_currentDocumentType == "Спецификация материалов") { } else if (m_currentDocumentType == "Спецификация") {
success = m_pdfController->drawSpecificationPage(painter, pageInfo, m_mainController); success = m_pdfController->drawSpecificationPage(painter, pageInfo, m_mainController);
qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования спецификации материалов:" << success; qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования спецификации:" << success;
} else if (m_currentDocumentType == "Ведомость покупных изделий") { } else if (m_currentDocumentType == "Ведомость покупных изделий") {
success = m_pdfController->drawVedomostPage(painter, pageInfo, m_mainController); success = m_pdfController->drawVedomostPage(painter, pageInfo, m_mainController);
qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования ведомости:" << success; qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования ведомости:" << success;
+1 -4
View File
@@ -16,7 +16,6 @@
#include <QSpacerItem> #include <QSpacerItem>
#include <QTransform> #include <QTransform>
#include <QWheelEvent> #include <QWheelEvent>
#include <QTimer>
// Включаем структуру PageInfo // Включаем структуру PageInfo
#include "../model/pageinfo.h" #include "../model/pageinfo.h"
@@ -88,15 +87,13 @@ private:
QComboBox* m_pageCombo; QComboBox* m_pageCombo;
QPushButton* m_prevPageBtn; QPushButton* m_prevPageBtn;
QPushButton* m_nextPageBtn; QPushButton* m_nextPageBtn;
QPushButton* m_refreshBtn;
QLabel* m_pageInfoLabel; QLabel* m_pageInfoLabel;
// Контроллеры // Контроллеры
MainController* m_mainController; MainController* m_mainController;
PDFController* m_pdfController; PDFController* m_pdfController;
// Таймер для отложенного обновления (чтобы избежать множественных обновлений при массовых изменениях)
QTimer* m_updateTimer;
// Данные // Данные
QList<PageInfo> m_pagesInfo; QList<PageInfo> m_pagesInfo;
QList<QPixmap> m_pagePixmaps; QList<QPixmap> m_pagePixmaps;