#include "titleinscriptionsdialog.h" #include #include #include #include #include // Инициализация статических данных о графах ГОСТ QMap TitleInscriptionsDialog::s_fieldNames; QMap 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 params = m_projectParamModel->getData(); qDebug() << "TitleInscriptionsDialog::createInscriptionFields: Добавляем" << params.size() << "параметров проекта для поля" << i; for (const auto ¶m : 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::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 values = getInscriptionValues(); qDebug() << "TitleInscriptionsDialog::onAccept: Готово к сохранению" << values.size() << "значений"; accept(); } void TitleInscriptionsDialog::onCancel() { qDebug() << "TitleInscriptionsDialog::onCancel: Отменяем диалог, изменения не сохраняются"; reject(); } QMap TitleInscriptionsDialog::getInscriptionValues() const { QMap 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 &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; }