Files
GostGenerator/view/titleinscriptionsdialog.cpp
T

439 lines
28 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 "titleinscriptionsdialog.h"
#include <QApplication>
#include <QScreen>
#include <QToolTip>
#include <QMessageBox>
#include <QDebug>
// Инициализация статических данных о графах ГОСТ
QMap<int, QString> TitleInscriptionsDialog::s_fieldNames;
QMap<int, QString> TitleInscriptionsDialog::s_fieldDescriptions;
void TitleInscriptionsDialog::initializeFieldData()
{
if (!s_fieldNames.isEmpty()) {
qDebug() << "TitleInscriptionsDialog::initializeFieldData: Данные полей уже инициализированы";
return; // Уже инициализировано
}
qDebug() << "TitleInscriptionsDialog::initializeFieldData: Инициализируем данные полей ГОСТ";
s_fieldNames[1] = "Наименование изделия и документа";
s_fieldNames[2] = "Обозначение документа";
s_fieldNames[3] = "Обозначение материала детали";
s_fieldNames[4] = "Литера";
s_fieldNames[5] = "Масса изделия";
s_fieldNames[6] = "Масштаб";
s_fieldNames[7] = "Порядковый номер листа";
s_fieldNames[8] = "Общее количество листов";
s_fieldNames[9] = "Наименование организации";
s_fieldNames[10] = "Характер работы";
s_fieldNames[11] = "Фамилии лиц";
s_fieldNames[12] = "Подписи лиц";
s_fieldNames[13] = "Дата подписания";
s_fieldNames[14] = "Сведения об изменениях";
s_fieldNames[15] = "Сведения об изменениях";
s_fieldNames[16] = "Сведения об изменениях";
s_fieldNames[17] = "Сведения об изменениях";
s_fieldNames[18] = "Сведения об изменениях";
s_fieldNames[19] = "Инвентарный номер подлинника";
s_fieldNames[20] = "Сведения о приемке подлинника";
s_fieldNames[21] = "Инвентарный номер подлинника (взамен)";
s_fieldNames[22] = "Инвентарный номер дубликата";
s_fieldNames[23] = "Сведения о приемке дубликата";
s_fieldNames[24] = "Обозначение документа (взамен)";
s_fieldNames[25] = "Обозначение соответствующего документа";
s_fieldNames[26] = "Обозначение документа (повернутое)";
s_fieldNames[27] = "Знак заказчика";
s_fieldNames[28] = "Номер решения и год утверждения";
s_fieldNames[29] = "Номер решения и год утверждения";
s_fieldNames[30] = "Индекс заказчика";
s_fieldNames[31] = "Подпись лица, копировавшего документ";
s_fieldNames[32] = "Обозначение формата листа";
s_fieldNames[33] = "Обозначение зоны";
s_fieldNames[34] = "Номера авторских свидетельств";
s_fieldNames[35] = "Номер версии документа";
s_fieldNames[36] = "Единица измерения";
s_fieldNames[37] = "Метод проецирования";
s_fieldNames[38] = "Имя файла";
s_fieldNames[39] = "Признак аутентичного документа";
s_fieldNames[40] = "Код документа";
s_fieldNames[41] = "Обозначение документа аналогичного изделия";
// Описания граф согласно ГОСТ
s_fieldDescriptions[1] = "Наименование изделия и наименование документа, если этому документу присвоен код. Наименование изделия должно соответствовать принятой терминологии и быть по возможности кратким.";
s_fieldDescriptions[2] = "Обозначение документа по ГОСТ 2.201 и код, если его код определен ГОСТ 2.102, ГОСТ 2.601, ГОСТ 2.602, ГОСТ 2.701.";
s_fieldDescriptions[3] = "Обозначение материала детали (графу заполняют только на чертежах деталей).";
s_fieldDescriptions[4] = "Литера, присвоенная данному документу (на документе в бумажной форме графу заполняют последовательно, начиная с крайней левой клетки).";
s_fieldDescriptions[5] = "Масса изделия по ГОСТ 2.109.";
s_fieldDescriptions[6] = "Масштаб (проставляется в соответствии с ГОСТ 2.302 и ГОСТ 2.109).";
s_fieldDescriptions[7] = "Порядковый номер листа (на документах, состоящих из одного листа, графу не заполняют).";
s_fieldDescriptions[8] = "Общее количество листов документа (указывают только на первом листе).";
s_fieldDescriptions[9] = "Наименование или код организации, выпускающей документ (графу не заполняют, если код содержится в обозначении документа).";
s_fieldDescriptions[10] = "Характер работы, выполняемой лицом, подписывающим документ, в соответствии с формами 1 и 2.";
s_fieldDescriptions[11] = "Фамилии лиц, подписавших документ.";
s_fieldDescriptions[12] = "Подписи лиц, фамилии которых указаны в графе 11.";
s_fieldDescriptions[13] = "Дата подписания документа.";
s_fieldDescriptions[14] = "Сведения об изменениях, которые заполняют в соответствии с требованиями ГОСТ 2.503.";
s_fieldDescriptions[15] = "Сведения об изменениях, которые заполняют в соответствии с требованиями ГОСТ 2.503.";
s_fieldDescriptions[16] = "Сведения об изменениях, которые заполняют в соответствии с требованиями ГОСТ 2.503.";
s_fieldDescriptions[17] = "Сведения об изменениях, которые заполняют в соответствии с требованиями ГОСТ 2.503.";
s_fieldDescriptions[18] = "Сведения об изменениях, которые заполняют в соответствии с требованиями ГОСТ 2.503.";
s_fieldDescriptions[19] = "Инвентарный номер подлинника по ГОСТ 2.501.";
s_fieldDescriptions[20] = "Сведения о приемке подлинника в службу технической документации (подпись и дата приемки).";
s_fieldDescriptions[21] = "Инвентарный номер подлинника, взамен которого выпущен данный подлинник по ГОСТ 2.503.";
s_fieldDescriptions[22] = "Инвентарный номер дубликата по ГОСТ 2.502.";
s_fieldDescriptions[23] = "Сведения о приемке дубликата в службу технической документации (подпись и дата приемки).";
s_fieldDescriptions[24] = "Обозначение документа, взамен или на основании которого выпущен данный документ.";
s_fieldDescriptions[25] = "Обозначение соответствующего документа, в котором впервые записан данный документ. Обязательный реквизит для всех документов, заимствованных из документации других изделий.";
s_fieldDescriptions[26] = "Обозначение документа, повернутое на 180° для формата А4 и для форматов больше А4 при расположении основной надписи вдоль длинной стороны листа и на 90° для форматов больше А4 при расположении основной надписи вдоль короткой стороны листа.";
s_fieldDescriptions[27] = "Знак, установленный заказчиком в соответствии с требованиями нормативной документации и проставляемый заказчиком или представительством заказчика.";
s_fieldDescriptions[28] = "Номер решения и год утверждения документации соответствующей литеры. Год утверждения указывают четырьмя цифрами.";
s_fieldDescriptions[29] = "Номер решения и год утверждения документации. Год утверждения указывают четырьмя цифрами.";
s_fieldDescriptions[30] = "Индекс заказчика в соответствии с нормативной документацией.";
s_fieldDescriptions[31] = "Подпись лица, копировавшего документ. При копировании электронного документа обязательный реквизит.";
s_fieldDescriptions[32] = "Обозначение формата листа по ГОСТ 2.301. Для электронного документа указывают формат листа, на котором будет соответствовать указанный в графе 6 масштаб.";
s_fieldDescriptions[33] = "Обозначение зоны, в которой находится изменяемая часть изделия.";
s_fieldDescriptions[34] = "Номера авторских свидетельств на изобретения, использованные в данном изделии.";
s_fieldDescriptions[35] = "Номер версии документа в электронной форме, с которого на устройствах вывода ЭВМ получен документ в бумажной форме. Графу заполняют только для документов, изготавливаемых с применением ЭВМ.";
s_fieldDescriptions[36] = "Единица измерения (метрическая или дюймовая).";
s_fieldDescriptions[37] = "Метод проецирования. Способ расположения проекций детали на чертеже. Обязательный, если проецирование не соответствует ГОСТ 2.305.";
s_fieldDescriptions[38] = "Имя файла, содержащего документ в электронной форме. Графу заполняют только для документов, изготавливаемых с помощью ЭВМ.";
s_fieldDescriptions[39] = "Признак аутентичного документа (обязательный для аутентичных документов).";
s_fieldDescriptions[40] = "Код документа в зависимости от характера использования. Для электронных документов в соответствии с ГОСТ 2.102 применяют коды: 1 — оригинал, 2 — подлинник, 3 — дубликат, 4 — копия.";
s_fieldDescriptions[41] = "Обозначение документа аналогичного изделия, для которого ранее изготовлены средства технологического оснащения, необходимые для данного изделия.";
qDebug() << "TitleInscriptionsDialog::initializeFieldData: Инициализировано" << s_fieldNames.size() << "названий полей и" << s_fieldDescriptions.size() << "описаний";
}
TitleInscriptionsDialog::TitleInscriptionsDialog(ProjectParamTableModel *projectParamModel, QWidget *parent)
: QDialog{parent}
, m_projectParamModel{projectParamModel}
, m_titleInscriptionsModel{nullptr}
{
qDebug() << "TitleInscriptionsDialog: Конструктор, projectParamModel:" << (projectParamModel ? "доступен" : "nullptr");
initializeFieldData();
setUp();
qDebug() << "TitleInscriptionsDialog: Конструктор завершен, создано полей:" << s_fieldNames.size();
}
void TitleInscriptionsDialog::setUp()
{
qDebug() << "TitleInscriptionsDialog::setUp: Начинаем настройку диалога";
setWidgets();
setUpLayout();
setUpConnections();
createInscriptionFields();
createImagePreview();
// Устанавливаем размер окна
resize(1200, 800);
setWindowTitle("Настройка основных надписей документа");
qDebug() << "TitleInscriptionsDialog::setUp: Настройка диалога завершена";
}
void TitleInscriptionsDialog::setWidgets()
{
qDebug() << "TitleInscriptionsDialog::setWidgets: Создаем виджеты";
m_scrollArea = new QScrollArea(this);
m_scrollContent = new QWidget();
m_scrollArea->setWidget(m_scrollContent);
m_scrollArea->setWidgetResizable(true);
m_imageView = new QGraphicsView(this);
m_imageScene = new QGraphicsScene(this);
m_imageView->setScene(m_imageScene);
m_imageView->setRenderHint(QPainter::Antialiasing);
m_imageView->setDragMode(QGraphicsView::ScrollHandDrag);
m_zoomSlider = new QSlider(Qt::Horizontal, this);
m_zoomSlider->setRange(25, 200);
m_zoomSlider->setValue(100);
m_zoomSlider->setTickPosition(QSlider::TicksBelow);
m_zoomSlider->setTickInterval(25);
m_okButton = new QPushButton("ОК", this);
m_cancelButton = new QPushButton("Отмена", this);
qDebug() << "TitleInscriptionsDialog::setWidgets: Виджеты созданы";
}
void TitleInscriptionsDialog::setUpLayout()
{
qDebug() << "TitleInscriptionsDialog::setUpLayout: Настраиваем компоновку";
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// Создаем горизонтальный layout для разделения на две части
QHBoxLayout *contentLayout = new QHBoxLayout();
// Левая часть - поля надписей
QVBoxLayout *leftLayout = new QVBoxLayout();
leftLayout->addWidget(new QLabel("Настройка надписей:", this));
leftLayout->addWidget(m_scrollArea);
// Правая часть - изображение
QVBoxLayout *rightLayout = new QVBoxLayout();
rightLayout->addWidget(new QLabel("Предварительный просмотр:", this));
rightLayout->addWidget(m_imageView);
rightLayout->addWidget(new QLabel("Масштаб:", this));
rightLayout->addWidget(m_zoomSlider);
contentLayout->addLayout(leftLayout, 1);
contentLayout->addLayout(rightLayout, 1);
// Кнопки
QHBoxLayout *buttonLayout = new QHBoxLayout();
buttonLayout->addStretch();
buttonLayout->addWidget(m_okButton);
buttonLayout->addWidget(m_cancelButton);
mainLayout->addLayout(contentLayout);
mainLayout->addLayout(buttonLayout);
qDebug() << "TitleInscriptionsDialog::setUpLayout: Компоновка настроена";
}
void TitleInscriptionsDialog::setUpConnections()
{
qDebug() << "TitleInscriptionsDialog::setUpConnections: Настраиваем соединения сигналов";
connect(m_okButton, &QPushButton::clicked, this, &TitleInscriptionsDialog::onAccept);
connect(m_cancelButton, &QPushButton::clicked, this, &TitleInscriptionsDialog::onCancel);
connect(m_zoomSlider, &QSlider::valueChanged, this, &TitleInscriptionsDialog::onZoomChanged);
qDebug() << "TitleInscriptionsDialog::setUpConnections: Соединения сигналов настроены";
}
void TitleInscriptionsDialog::createInscriptionFields()
{
QVBoxLayout *fieldsLayout = new QVBoxLayout(m_scrollContent);
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Начинаем создание полей";
// Создаем поля для всех граф ГОСТ (1-41)
int createdFields = 0;
for (int i = 1; i <= 41; ++i) {
if (!s_fieldNames.contains(i)) continue;
QGroupBox *fieldGroup = new QGroupBox(QString("Графа %1: %2").arg(i).arg(s_fieldNames[i]), m_scrollContent);
QHBoxLayout *fieldLayout = new QHBoxLayout(fieldGroup);
// Метка с описанием
QLabel *descriptionLabel = new QLabel(s_fieldDescriptions[i], fieldGroup);
descriptionLabel->setWordWrap(true);
descriptionLabel->setToolTip(s_fieldDescriptions[i]);
fieldLayout->addWidget(descriptionLabel, 1);
// Комбобокс для выбора значения
QComboBox *comboBox = new QComboBox(fieldGroup);
comboBox->addItem("Пусто", "");
// Добавляем параметры проекта
if (m_projectParamModel) {
QList<ProjectParamTableData> params = m_projectParamModel->getData();
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Добавляем" << params.size() << "параметров проекта для поля" << i;
for (const auto &param : params) {
comboBox->addItem(param.name, param.name);
}
} else {
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Модель параметров проекта недоступна для поля" << i;
}
comboBox->addItem("Кастомное значение", "custom");
fieldLayout->addWidget(comboBox);
// Поле для кастомного значения (изначально скрыто)
QLineEdit *customEdit = new QLineEdit(fieldGroup);
customEdit->setPlaceholderText("Введите значение...");
customEdit->setVisible(false);
fieldLayout->addWidget(customEdit);
// Сохраняем ссылки на виджеты
m_comboBoxes[i] = comboBox;
m_customEdits[i] = customEdit;
m_fieldLabels[i] = descriptionLabel;
// Создаем структуру поля
TitleInscriptionField field;
field.number = i;
field.name = s_fieldNames[i];
field.description = s_fieldDescriptions[i];
field.currentValue = "";
field.isCustom = false;
m_fields[i] = field;
// Подключаем сигналы
connect(comboBox, QOverload<const QString &>::of(&QComboBox::currentTextChanged),
[this, i](const QString &value) { onComboBoxChanged(i, value); });
connect(customEdit, &QLineEdit::textChanged,
[this, i](const QString &value) { onCustomValueChanged(i, value); });
fieldsLayout->addWidget(fieldGroup);
createdFields++;
}
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Создано полей:" << createdFields;
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Размер m_fields:" << m_fields.size();
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Размер m_comboBoxes:" << m_comboBoxes.size();
qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Размер m_customEdits:" << m_customEdits.size();
fieldsLayout->addStretch();
}
void TitleInscriptionsDialog::createImagePreview()
{
qDebug() << "TitleInscriptionsDialog::createImagePreview: Создаем предварительный просмотр изображения";
// Загружаем изображение из ресурсов
QPixmap pixmap(":/assets/Title.PNG");
if (pixmap.isNull()) {
qDebug() << "TitleInscriptionsDialog::createImagePreview: Не удалось загрузить изображение Title.PNG";
return;
}
m_imageItem = m_imageScene->addPixmap(pixmap);
m_imageScene->setSceneRect(m_imageItem->boundingRect());
// Устанавливаем начальный масштаб
m_imageView->fitInView(m_imageItem, Qt::KeepAspectRatio);
qDebug() << "TitleInscriptionsDialog::createImagePreview: Предварительный просмотр создан, размер изображения:" << pixmap.size();
}
void TitleInscriptionsDialog::onComboBoxChanged(int fieldNumber, const QString &value)
{
QComboBox *comboBox = m_comboBoxes[fieldNumber];
QLineEdit *customEdit = m_customEdits[fieldNumber];
qDebug() << "TitleInscriptionsDialog::onComboBoxChanged: Поле" << fieldNumber << "комбобокс изменен на:" << value;
if (value == "custom") {
// Показываем поле для кастомного значения
customEdit->setVisible(true);
customEdit->setFocus();
// Очищаем значение поля, так как теперь оно кастомное
updateFieldValue(fieldNumber, "");
} else {
// Скрываем поле для кастомного значения
customEdit->setVisible(false);
customEdit->clear();
// Обновляем значение поля
updateFieldValue(fieldNumber, value);
}
}
void TitleInscriptionsDialog::onCustomValueChanged(int fieldNumber, const QString &value)
{
qDebug() << "TitleInscriptionsDialog::onCustomValueChanged: Поле" << fieldNumber << "кастомное значение изменено на:" << value;
updateFieldValue(fieldNumber, value);
}
void TitleInscriptionsDialog::updateFieldValue(int fieldNumber, const QString &value)
{
if (m_fields.contains(fieldNumber)) {
QString oldValue = m_fields[fieldNumber].currentValue;
m_fields[fieldNumber].currentValue = value;
m_fields[fieldNumber].isCustom = (m_comboBoxes[fieldNumber]->currentText() == "custom");
qDebug() << "TitleInscriptionsDialog::updateFieldValue: Поле" << fieldNumber
<< "изменено с" << oldValue << "на" << value
<< "(кастомное:" << m_fields[fieldNumber].isCustom << ")";
} else {
qDebug() << "TitleInscriptionsDialog::updateFieldValue: Поле" << fieldNumber << "не найдено в m_fields";
}
}
void TitleInscriptionsDialog::onZoomChanged(int value)
{
qreal scale = value / 100.0;
m_imageView->setTransform(QTransform::fromScale(scale, scale));
qDebug() << "TitleInscriptionsDialog::onZoomChanged: Масштаб изменен на" << value << "% (коэффициент:" << scale << ")";
}
void TitleInscriptionsDialog::onAccept()
{
qDebug() << "TitleInscriptionsDialog::onAccept: Принимаем диалог, собираем значения для сохранения";
QMap<int, QString> values = getInscriptionValues();
qDebug() << "TitleInscriptionsDialog::onAccept: Готово к сохранению" << values.size() << "значений";
accept();
}
void TitleInscriptionsDialog::onCancel()
{
qDebug() << "TitleInscriptionsDialog::onCancel: Отменяем диалог, изменения не сохраняются";
reject();
}
QMap<int, QString> TitleInscriptionsDialog::getInscriptionValues() const
{
QMap<int, QString> values;
qDebug() << "TitleInscriptionsDialog::getInscriptionValues: Собираем значения из" << m_fields.size() << "полей";
int nonEmptyCount = 0;
for (auto it = m_fields.begin(); it != m_fields.end(); ++it) {
QString fieldValue = it.value().currentValue;
values[it.key()] = fieldValue;
if (!fieldValue.isEmpty()) {
qDebug() << "TitleInscriptionsDialog::getInscriptionValues: Поле" << it.key() << "=" << fieldValue;
nonEmptyCount++;
}
}
qDebug() << "TitleInscriptionsDialog::getInscriptionValues: Возвращаем" << values.size() << "значений, из них непустых:" << nonEmptyCount;
return values;
}
void TitleInscriptionsDialog::setInscriptionValues(const QMap<int, QString> &values)
{
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Устанавливаем" << values.size() << "значений";
int nonEmptyCount = 0;
for (auto it = values.begin(); it != values.end(); ++it) {
int fieldNumber = it.key();
QString value = it.value();
if (!value.isEmpty()) {
nonEmptyCount++;
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Устанавливаем поле" << fieldNumber << "=" << value;
}
if (m_fields.contains(fieldNumber)) {
m_fields[fieldNumber].currentValue = value;
// Обновляем комбобокс
if (m_comboBoxes.contains(fieldNumber)) {
QComboBox *comboBox = m_comboBoxes[fieldNumber];
// Ищем значение в списке параметров проекта
int index = comboBox->findData(value);
if (index >= 0) {
comboBox->setCurrentIndex(index);
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Найдено в комбобоксе, индекс" << index;
} else if (!value.isEmpty()) {
// Если значение не найдено, устанавливаем кастомное
comboBox->setCurrentText("custom");
if (m_customEdits.contains(fieldNumber)) {
m_customEdits[fieldNumber]->setText(value);
m_customEdits[fieldNumber]->setVisible(true);
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Установлено кастомное значение";
}
}
} else {
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Комбобокс для поля" << fieldNumber << "не найден";
}
} else {
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Поле" << fieldNumber << "не найдено в m_fields";
}
}
qDebug() << "TitleInscriptionsDialog::setInscriptionValues: Установлено" << nonEmptyCount << "непустых значений";
}
void TitleInscriptionsDialog::setTitleInscriptionsModel(TitleInscriptionsModel *model)
{
qDebug() << "TitleInscriptionsDialog::setTitleInscriptionsModel: Устанавливаем модель надписей:" << (model ? "доступна" : "nullptr");
m_titleInscriptionsModel = model;
}
TitleInscriptionsModel* TitleInscriptionsDialog::getTitleInscriptionsModel() const
{
qDebug() << "TitleInscriptionsDialog::getTitleInscriptionsModel: Возвращаем модель надписей:" << (m_titleInscriptionsModel ? "доступна" : "nullptr");
return m_titleInscriptionsModel;
}