Files
GostGenerator/controller/pdfcontroller.cpp
T

3328 lines
177 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 "pdfcontroller.h"
#include "maincontroller.h"
#include "perechentablecontroller.h"
#include "specificationpcbcontroller.h"
#include "specificationcontroller.h"
#include "vedomostcontroller.h"
#include "../model/perechentablemodel.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/titleinscriptionsmodel.h"
#include "../model/projectparamtablemodel.h"
#include "../model/specificationtablemodel.h"
#include "../model/vedomosttablemodel.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/pageinfo.h"
#include <QDebug>
#include <QPainter>
// Регистрируем метатипы для работы с QVariant в PDFController
// Примечание: SpecificationPCBCellData уже объявлен в specificationpcbtablemodel.h
// Эти объявления должны быть после включения заголовков, где определены структуры
Q_DECLARE_METATYPE(PerechenCellData)
Q_DECLARE_METATYPE(SpecificationCellData)
Q_DECLARE_METATYPE(VedomostCellData)
#include <QPdfWriter>
#include <QPageSize>
#include <QPageLayout>
#include <QFont>
#include <QFontMetrics>
#include <QTextOption>
#include <QFontDatabase>
#include <QDir>
PDFController::PDFController(QObject *parent)
: QObject{parent}
{}
bool PDFController::exportPerechenToPdf(const QString &filePath, MainController *mainController)
{
if (!mainController) {
qDebug() << "PDFController::exportPerechenToPdf: MainController не передан";
return false;
}
// Получаем модель перечня элементов из MainController
PerechenTableModel *perechenModel = mainController->perechenTableModel();
if (!perechenModel) {
qDebug() << "PDFController::exportPerechenToPdf: Модель перечня элементов недоступна";
return false;
}
// Получаем модель надписей титульного листа из MainController
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
qDebug() << "PDFController::exportPerechenToPdf: Модель надписей титульного листа недоступна";
return false;
}
// Получаем модель параметров проекта из MainController
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
qDebug() << "PDFController::exportPerechenToPdf: Модель параметров проекта недоступна";
return false;
}
qDebug() << "PDFController::exportPerechenToPdf: Начинаем экспорт перечня в PDF:" << filePath;
qDebug() << "PDFController::exportPerechenToPdf: Количество строк в модели:" << perechenModel->rowCount();
qDebug() << "PDFController::exportPerechenToPdf: Количество полей надписей:" << titleModel->getFieldCount();
// Создаем PDF документ формата А4
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageMargins(QMarginsF(0, 0, 0, 0));
QPainter painter(&writer);
if (!painter.isActive()) {
qDebug() << "PDFController::exportPerechenToPdf: Не удалось создать painter";
return false;
}
// Получаем размеры страницы
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах
const int rowsOnFirstPage = 27; // На первой странице 23 строки
const int rowsOnOtherPages = 33; // На последующих страницах 29 строк
int totalRows = perechenModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц заранее
int totalPages = 2;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
while (currentRow < totalRows) {
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем новую страницу (кроме первой)
if (pageNumber > 1) {
writer.newPage();
}
// Добавляем рамку ГОСТ в зависимости от номера страницы
if (pageNumber == 1) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,1);
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,1);
}
// Вычисляем область для таблицы
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу с указанным диапазоном строк (включая пустые строки на последней странице)
addPerechenTableRange(painter, perechenModel, tableRect, currentRow, rowsOnThisPage, mainController);
currentRow += (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
pageNumber++;
}
writer.newPage();
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,1);
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -20*mmToPixels);
addListRegistrationTable(painter, tableRect);
painter.end();
qDebug() << "PDFController::exportPerechenToPdf: Экспорт завершен успешно. Создано страниц:" << (pageNumber - 1);
return true;
}
bool PDFController::exportSpecificationPcbToPdf(const QString &filePath, MainController *mainController)
{
if (!mainController) {
qDebug() << "PDFController::exportSpecificationPcbToPdf: MainController не передан";
return false;
}
// Получаем модель спецификации PCB из MainController
SpecificationPCBTableModel *specificationModel = mainController->specificationPCBTableModel();
if (!specificationModel) {
qDebug() << "PDFController::exportSpecificationPcbToPdf: Модель спецификации PCB недоступна";
return false;
}
// Получаем модель надписей титульного листа из MainController
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
qDebug() << "PDFController::exportSpecificationPcbToPdf: Модель надписей титульного листа недоступна";
return false;
}
// Получаем модель параметров проекта из MainController
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
qDebug() << "PDFController::exportSpecificationPcbToPdf: Модель параметров проекта недоступна";
return false;
}
qDebug() << "PDFController::exportSpecificationPcbToPdf: Начинаем экспорт спецификации PCB в PDF:" << filePath;
qDebug() << "PDFController::exportSpecificationPcbToPdf: Количество строк в модели:" << specificationModel->rowCount();
qDebug() << "PDFController::exportSpecificationPcbToPdf: Количество полей надписей:" << titleModel->getFieldCount();
// Создаем PDF документ формата А4
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageMargins(QMarginsF(0, 0, 0, 0));
QPainter painter(&writer);
if (!painter.isActive()) {
qDebug() << "PDFController::exportSpecificationPcbToPdf: Не удалось создать painter";
return false;
}
// Получаем размеры страницы
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах (аналогично перечню)
const int rowsOnFirstPage = 26; // На первой странице 27 строк
const int rowsOnOtherPages = 32; // На последующих страницах 33 строки
int totalRows = specificationModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц заранее
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
while (currentRow < totalRows) {
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем новую страницу (кроме первой)
if (pageNumber > 1) {
writer.newPage();
}
// Добавляем рамку ГОСТ в зависимости от номера страницы
if (pageNumber == 1) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,2);
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,2);
}
// Вычисляем область для таблицы
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу спецификации с указанным диапазоном строк (включая пустые строки на последней странице)
addSpecificationPcbTableRange(painter, specificationModel, tableRect, currentRow, rowsOnThisPage, mainController);
currentRow += (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
pageNumber++;
}
writer.newPage();
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,1);
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -20*mmToPixels);
addListRegistrationTable(painter, tableRect);
painter.end();
qDebug() << "PDFController::exportSpecificationPcbToPdf: Экспорт завершен успешно. Создано страниц:" << (pageNumber - 1);
return true;
}
bool PDFController::exportSpecificationToPdf(const QString &filePath, MainController *mainController)
{
if (!mainController) {
qDebug() << "PDFController::exportSpecificationToPdf: MainController не передан";
return false;
}
// Получаем модель спецификации материалов из MainController
SpecificationTableModel *specificationModel = mainController->specificationTableModel();
if (!specificationModel) {
qDebug() << "PDFController::exportSpecificationToPdf: Модель спецификации материалов недоступна";
return false;
}
// Получаем модель надписей титульного листа из MainController
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
qDebug() << "PDFController::exportSpecificationToPdf: Модель надписей титульного листа недоступна";
return false;
}
// Получаем модель параметров проекта из MainController
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
qDebug() << "PDFController::exportSpecificationToPdf: Модель параметров проекта недоступна";
return false;
}
qDebug() << "PDFController::exportSpecificationToPdf: Начинаем экспорт спецификации материалов в PDF:" << filePath;
qDebug() << "PDFController::exportSpecificationToPdf: Количество строк в модели:" << specificationModel->rowCount();
qDebug() << "PDFController::exportSpecificationToPdf: Количество полей надписей:" << titleModel->getFieldCount();
// Создаем PDF документ формата А4
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageMargins(QMarginsF(0, 0, 0, 0));
QPainter painter(&writer);
if (!painter.isActive()) {
qDebug() << "PDFController::exportSpecificationToPdf: Не удалось создать painter";
return false;
}
// Получаем размеры страницы
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах (аналогично перечню)
const int rowsOnFirstPage = 26; // На первой странице 27 строк
const int rowsOnOtherPages = 32; // На последующих страницах 33 строки
int totalRows = specificationModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц заранее
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
while (currentRow < totalRows) {
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем новую страницу (кроме первой)
if (pageNumber > 1) {
writer.newPage();
}
// Добавляем рамку ГОСТ в зависимости от номера страницы
if (pageNumber == 1) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,3);
// painter.drawText(pageRect.left()+65*mmToPixels, pageRect.top(), 120*mmToPixels, 15*mmToPixels, Qt::AlignCenter, "ХУй");
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,3);
}
// Вычисляем область для таблицы
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу спецификации с указанным диапазоном строк (включая пустые строки на последней странице)
addSpecificationTableRange(painter, specificationModel, tableRect, currentRow, rowsOnThisPage, mainController);
currentRow += (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
pageNumber++;
}
writer.newPage();
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,1);
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -20*mmToPixels);
addListRegistrationTable(painter, tableRect);
painter.end();
qDebug() << "PDFController::exportSpecificationToPdf: Экспорт завершен успешно. Создано страниц:" << (pageNumber - 1);
return true;
}
bool PDFController::exportVedomostToPdf(const QString &filePath, MainController *mainController)
{
if (!mainController) {
qDebug() << "PDFController::exportVedomostToPdf: MainController не передан";
return false;
}
// Получаем модель ведомости покупных изделий из MainController
VedomostTableModel *vedomostModel = mainController->vedomostTableModel();
if (!vedomostModel) {
qDebug() << "PDFController::exportVedomostToPdf: Модель ведомости покупных изделий недоступна";
return false;
}
// Получаем модель надписей титульного листа из MainController
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
qDebug() << "PDFController::exportVedomostToPdf: Модель надписей титульного листа недоступна";
return false;
}
// Получаем модель параметров проекта из MainController
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
qDebug() << "PDFController::exportVedomostToPdf: Модель параметров проекта недоступна";
return false;
}
qDebug() << "PDFController::exportVedomostToPdf: Начинаем экспорт ведомости покупных изделий в PDF:" << filePath;
qDebug() << "PDFController::exportVedomostToPdf: Количество строк в модели:" << vedomostModel->rowCount();
// Создаем PDF документ формата А5
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A3));
writer.setPageMargins(QMarginsF(0, 0, 0, 0));
writer.setPageOrientation(QPageLayout::Landscape);
QPainter painter(&writer);
if (!painter.isActive()) {
qDebug() << "PDFController::exportVedomostToPdf: Не удалось создать painter";
return false;
}
// Получаем размеры страницы
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах (для А5 формата)
const int rowsOnFirstPage = 24; // На первой странице 20 строк
const int rowsOnOtherPages = 30; // На последующих страницах 25 строк
int totalRows = vedomostModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц заранее
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
while (currentRow < totalRows) {
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем новую страницу (кроме первой)
if (pageNumber > 1) {
writer.newPage();
}
// Добавляем рамку ГОСТ A5
if(pageNumber==1){
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,4);
}else{
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageNumber, totalPages,4);
}
// Вычисляем область для таблицы (A5 формат)
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу ведомости с указанным диапазоном строк
addVedomostTableRange(painter, vedomostModel, tableRect, currentRow, rowsOnThisPage, mainController);
currentRow += (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
pageNumber++;
}
// Устанавливаем размер и ориентацию страницы ДО создания новой страницы
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageOrientation(QPageLayout::Portrait);
writer.setPageMargins(QMarginsF(0, 0, 0, 0));
// Создаем новую страницу с новыми настройками
writer.newPage();
// Обновляем pageRect для A4 формата после изменения размера и ориентации страницы
QRectF pageRectA4 = writer.pageLayout().paintRectPixels(writer.resolution());
addGostFrameA4(painter, pageRectA4, titleModel, projectParamModel, pageNumber, totalPages,1);
QRectF tableRect = pageRectA4.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -20*mmToPixels);
addListRegistrationTable(painter, tableRect);
painter.end();
qDebug() << "PDFController::exportVedomostToPdf: Экспорт завершен успешно. Создано страниц:" << (pageNumber - 1);
return true;
}
bool PDFController::generateTableA4(const QString &filePath, MainController *mainController)
{
if (!mainController) {
qDebug() << "PDFController::generateTableA4: MainController не передан";
return false;
}
PerechenTableModel *perechenModel = mainController->perechenTableModel();
if (!perechenModel) {
qDebug() << "PDFController::generateTableA4: Модель перечня элементов недоступна";
return false;
}
qDebug() << "PDFController::generateTableA4: Начинаем генерацию таблицы А4:" << filePath;
// Создаем PDF документ
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageMargins(QMarginsF(20, 20, 20, 20));
QPainter painter(&writer);
if (!painter.isActive()) {
qDebug() << "PDFController::generateTableA4: Не удалось создать painter";
return false;
}
// Получаем размеры страницы
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
// Добавляем рамку ГОСТ
//addGostFrameA4(painter, pageRect, nullptr, 1, 1);
// Добавляем заголовок
QFont titleFont("Arial", 14, QFont::Bold);
painter.setFont(titleFont);
painter.drawText(QRectF(pageRect.x() + 50, pageRect.y() + 50, pageRect.width() - 100, 50),
"ПЕРЕЧЕНЬ ЭЛЕМЕНТОВ", QTextOption(Qt::AlignCenter));
// Добавляем таблицу перечня
QRectF tableRect(pageRect.x() + 50, pageRect.y() + 120, pageRect.width() - 100, pageRect.height() - 170);
addPerechenTable(painter, perechenModel, tableRect, mainController);
painter.end();
qDebug() << "PDFController::generateTableA4: Таблица А4 сгенерирована успешно";
return true;
}
bool PDFController::generateTableA5(const QString &filePath, MainController *mainController)
{
qDebug() << "PDFController::generateTableA5: Заглушка для А5 формата - пока не реализовано";
// TODO: Реализовать генерацию таблицы А5
return false;
}
bool PDFController::generateGostStampA4(const QString &filePath, MainController *mainController)
{
if (!mainController) {
qDebug() << "PDFController::generateGostStampA4: MainController не передан";
return false;
}
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
qDebug() << "PDFController::generateGostStampA4: Модель надписей титульного листа недоступна";
return false;
}
qDebug() << "PDFController::generateGostStampA4: Начинаем генерацию штампа ГОСТ А4:" << filePath;
// Создаем PDF документ
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageMargins(QMarginsF(20, 20, 20, 20));
QPainter painter(&writer);
if (!painter.isActive()) {
qDebug() << "PDFController::generateGostStampA4: Не удалось создать painter";
return false;
}
// Получаем размеры страницы
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
// Добавляем рамку ГОСТ
addGostFrameA4(painter, pageRect, titleModel, nullptr, 1, 1,0);
// Добавляем штамп ГОСТ в правом нижнем углу
QRectF stampRect(pageRect.width() - 200, pageRect.height() - 100, 180, 80);
addTitleInscriptions(painter, titleModel, stampRect);
painter.end();
qDebug() << "PDFController::generateGostStampA4: Штамп ГОСТ А4 сгенерирован успешно";
return true;
}
bool PDFController::generateGostStampA5(const QString &filePath, MainController *mainController)
{
qDebug() << "PDFController::generateGostStampA5: Заглушка для А5 формата - пока не реализовано";
// TODO: Реализовать генерацию штампа ГОСТ А5
return false;
}
bool PDFController::createPdfDocument(const QString &filePath, const QString &title)
{
QPdfWriter writer(filePath);
writer.setPageSize(QPageSize(QPageSize::A4));
writer.setPageMargins(QMarginsF(20, 20, 20, 20));
QPainter painter(&writer);
if (!painter.isActive()) {
return false;
}
// Добавляем заголовок
QFont titleFont("Arial", 16, QFont::Bold);
painter.setFont(titleFont);
QRectF pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
painter.drawText(QRectF(pageRect.x(), pageRect.y(), pageRect.width(), 100),
title, QTextOption(Qt::AlignCenter));
painter.end();
return true;
}
bool PDFController::addListRegistrationTable(QPainter &painter, const QRectF &pageRect)
{
QPen framePen(Qt::black, 1.0);
painter.setPen(framePen);
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
float rowHeight = 8.175;
int rowCount = 29;
// Создаем QTextOption с правильными настройками для переноса строк
QTextOption textOption;
textOption.setAlignment(Qt::AlignCenter);
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
QRectF nameRect = QRectF(pageRect.left(), pageRect.top(),185*mmToPixels, 10*mmToPixels);
painter.drawLine(nameRect.bottomLeft(),nameRect.bottomRight());
painter.drawText(nameRect, "Лист регистрации изменений", textOption);
painter.drawLine(pageRect.left()+8*mmToPixels,pageRect.top()+16*mmToPixels,pageRect.left()+88*mmToPixels,pageRect.top()+16*mmToPixels);
painter.drawText(QRectF(pageRect.left()+8*mmToPixels,pageRect.top()+10*mmToPixels,80*mmToPixels, 6*mmToPixels), "Номера листов (страниц)", textOption);
painter.drawLine(pageRect.left(),pageRect.top()+35*mmToPixels,pageRect.left()+185*mmToPixels, pageRect.top()+35*mmToPixels);
painter.drawLine(pageRect.left()+8*mmToPixels,pageRect.top()+10*mmToPixels,pageRect.left()+8*mmToPixels,pageRect.top()+35*mmToPixels+(rowCount)*rowHeight*mmToPixels);
painter.drawLine(pageRect.left()+28*mmToPixels,pageRect.top()+16*mmToPixels,pageRect.left()+28*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+48*mmToPixels,pageRect.top()+16*mmToPixels,pageRect.left()+48*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+68*mmToPixels,pageRect.top()+16*mmToPixels,pageRect.left()+68*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+88*mmToPixels,pageRect.top()+10*mmToPixels,pageRect.left()+88*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+108*mmToPixels,pageRect.top()+10*mmToPixels,pageRect.left()+108*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+133*mmToPixels,pageRect.top()+10*mmToPixels,pageRect.left()+133*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+158*mmToPixels,pageRect.top()+10*mmToPixels,pageRect.left()+158*mmToPixels,pageRect.bottom());
painter.drawLine(pageRect.left()+173*mmToPixels,pageRect.top()+10*mmToPixels,pageRect.left()+173*mmToPixels,pageRect.bottom());
painter.drawText(QRectF(pageRect.left(),pageRect.top()+10*mmToPixels, 8*mmToPixels, 25*mmToPixels), "Изм.", textOption);
painter.drawText(QRectF(pageRect.left()+8*mmToPixels,pageRect.top()+16*mmToPixels, 20*mmToPixels, 19*mmToPixels), "измененных", textOption);
painter.drawText(QRectF(pageRect.left()+28*mmToPixels,pageRect.top()+16*mmToPixels, 20*mmToPixels, 19*mmToPixels), "замененных", textOption);
painter.drawText(QRectF(pageRect.left()+48*mmToPixels,pageRect.top()+16*mmToPixels, 20*mmToPixels, 19*mmToPixels), "новых", textOption);
painter.drawText(QRectF(pageRect.left()+68*mmToPixels,pageRect.top()+16*mmToPixels, 20*mmToPixels, 19*mmToPixels), "аннулиро-ванных", textOption);
painter.drawText(QRectF(pageRect.left()+88*mmToPixels,pageRect.top()+10*mmToPixels, 20*mmToPixels, 25*mmToPixels), "Всего листов (страниц) в документе", textOption);
painter.drawText(QRectF(pageRect.left()+108*mmToPixels,pageRect.top()+10*mmToPixels, 25*mmToPixels, 25*mmToPixels), "Номер документа", textOption);
painter.drawText(QRectF(pageRect.left()+133*mmToPixels,pageRect.top()+10*mmToPixels, 25*mmToPixels, 25*mmToPixels), "Входящий номер сопроводительного документа и дата", textOption);
painter.drawText(QRectF(pageRect.left()+158*mmToPixels,pageRect.top()+10*mmToPixels, 15*mmToPixels, 25*mmToPixels), "Подпись", textOption);
painter.drawText(QRectF(pageRect.left()+173*mmToPixels,pageRect.top()+10*mmToPixels, 12*mmToPixels, 25*mmToPixels), "Дата", textOption);
for(int i =1; i<=rowCount;i++){
painter.drawLine(pageRect.left(), pageRect.top()+35*mmToPixels+i*rowHeight*mmToPixels, pageRect.left()+ 185*mmToPixels,pageRect.top()+35*mmToPixels+i*rowHeight*mmToPixels);
}
return true;
}
bool PDFController::addGostFrameA4FirstPage(QPainter &painter, const QRectF &pageRect, const TitleInscriptionsModel* model, const ProjectParamTableModel* projectParamModel, int currentPage, int totalPages, int docType)
{
// Загружаем TTF шрифт из QRC ресурсов
QString fontPath = ":/assets/GOST_A.TTF";
int fontId = QFontDatabase::addApplicationFont(fontPath);
if (fontId == -1) {
qDebug() << "PDFController::addGostFrameA4: Не удалось загрузить шрифт из ресурсов:/assets/GOST_A.TTF";
// Используем стандартный шрифт как fallback
QFont fallbackFont("Arial", 12);
painter.setFont(fallbackFont);
} else {
// Получаем имя семейства шрифта
QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);
if (!fontFamilies.isEmpty()) {
QString fontFamily = fontFamilies.first();
qDebug() << "PDFController::addGostFrameA4: Загружен шрифт из ресурсов:" << fontFamily;
// Создаем шрифт с нужным кеглем (размером)
QFont gostFont(fontFamily, 12); // кегль 12 пунктов
painter.setFont(gostFont);
}
}
// Рисуем только внутреннюю рамку ГОСТ с отступами:
// Слева: 20мм, Сверху: 5мм, Справа: 5мм, Снизу: 5мм
QPen framePen(Qt::black, 1.0);
painter.setPen(framePen);
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4; // 25.4 мм = 1 дюйм
// Вычисляем отступы в пикселях
qreal leftMargin = 20 * mmToPixels; // 20мм слева
qreal topMargin = 5 * mmToPixels; // 5мм сверху
qreal rightMargin = 5 * mmToPixels; // 5мм справа
qreal bottomMargin = 5 * mmToPixels; // 5мм снизу
// Внутренняя рамка с указанными отступами в пикселях
QRectF innerRect = pageRect.adjusted(leftMargin, topMargin, -rightMargin, -bottomMargin);
painter.drawRect(innerRect);
// Пример использования шрифта для текста
// Получаем текущий шрифт
QFont currentFont = painter.font();
// Устанавливаем разные кегли для разных элементов
// Угловые маркеры для фальцовки
// qreal markerSize = 5.0;
// painter.drawLine(innerRect.left(), innerRect.top() - markerSize,
// innerRect.left(), innerRect.top() + markerSize);
// painter.drawLine(innerRect.left() - markerSize, innerRect.top(),
// innerRect.left() + markerSize, innerRect.top());
// painter.drawLine(innerRect.right(), innerRect.top() - markerSize,
// innerRect.right(), innerRect.top() + markerSize);
// painter.drawLine(innerRect.right() - markerSize, innerRect.top(),
// innerRect.right() + markerSize, innerRect.top());
// Уменьшаем шрифт для лучшего размещения текста
QRectF lowTableRect = QRectF(innerRect.left(), innerRect.bottom(), -12*mmToPixels, -(25+35+25+25+35)*mmToPixels);
// Сначала рисуем всё в обычном прямоугольнике
painter.drawRect(lowTableRect);
// Рисуем повернутый прямоугольник с тем же содержимым
painter.drawLine(lowTableRect.right()+5*mmToPixels, lowTableRect.top(), lowTableRect.right()+5*mmToPixels, lowTableRect.bottom());
painter.drawLine(lowTableRect.right(), lowTableRect.top()-25*mmToPixels, lowTableRect.left(), lowTableRect.top()-25*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels);
QRectF topTableRect = QRectF(innerRect.left(), innerRect.top(), -12*mmToPixels, 120*mmToPixels);
painter.drawRect(topTableRect);
painter.drawLine(topTableRect.right()+5*mmToPixels, topTableRect.top(), topTableRect.right()+5*mmToPixels, topTableRect.bottom());
painter.drawLine(topTableRect.right(), topTableRect.top()+60*mmToPixels, topTableRect.left(),topTableRect.top()+60*mmToPixels);
QRectF mainTableRect = QRect(innerRect.right()-185*mmToPixels,innerRect.bottom()-40*mmToPixels,185*mmToPixels, 40*mmToPixels);
painter.drawRect(mainTableRect);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+5*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+5*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+10*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+10*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+15*mmToPixels,mainTableRect.right(), mainTableRect.top()+15*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+20*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+20*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+25*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+30*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+30*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+35*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+35*mmToPixels);
painter.drawLine(mainTableRect.right()-50*mmToPixels, mainTableRect.top()+20*mmToPixels,mainTableRect.right(), mainTableRect.top()+20*mmToPixels);
painter.drawLine(mainTableRect.right()-50*mmToPixels, mainTableRect.top()+25*mmToPixels,mainTableRect.right(), mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.left()+65*mmToPixels, mainTableRect.top(),mainTableRect.left()+65*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+55*mmToPixels, mainTableRect.top(),mainTableRect.left()+55*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+40*mmToPixels, mainTableRect.top(),mainTableRect.left()+40*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+17*mmToPixels, mainTableRect.top(),mainTableRect.left()+17*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+7*mmToPixels, mainTableRect.top(),mainTableRect.left()+7*mmToPixels, mainTableRect.top()+15*mmToPixels);
painter.drawLine(mainTableRect.right()-50*mmToPixels, mainTableRect.top()+15*mmToPixels,mainTableRect.right()-50*mmToPixels,mainTableRect.bottom());
painter.drawLine(mainTableRect.right()-45*mmToPixels, mainTableRect.top()+20*mmToPixels,mainTableRect.right()-45*mmToPixels,mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.right()-40*mmToPixels, mainTableRect.top()+20*mmToPixels,mainTableRect.right()-40*mmToPixels,mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.right()-35*mmToPixels, mainTableRect.top()+15*mmToPixels,mainTableRect.right()-35*mmToPixels,mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.right()-20*mmToPixels, mainTableRect.top()+15*mmToPixels,mainTableRect.right()-20*mmToPixels,mainTableRect.top()+25*mmToPixels);
QRectF idkTableRect = QRectF(mainTableRect.right()-120*mmToPixels,mainTableRect.top()-22*mmToPixels, 120*mmToPixels, 22*mmToPixels);
// painter.drawRect(idkTableRect);
painter.drawLine(idkTableRect.topLeft(), idkTableRect.bottomLeft());
painter.drawLine(idkTableRect.topRight(), idkTableRect.bottomRight());
painter.drawLine(idkTableRect.topRight(), idkTableRect.topLeft());
painter.drawLine(idkTableRect.left(),idkTableRect.top()+14*mmToPixels, idkTableRect.right(),idkTableRect.top()+14*mmToPixels);
painter.drawLine(idkTableRect.left()+14*mmToPixels,idkTableRect.top(), idkTableRect.left()+14*mmToPixels,idkTableRect.top()+14*mmToPixels);
painter.drawLine(idkTableRect.left()+67*mmToPixels, idkTableRect.top(), idkTableRect.left()+67*mmToPixels, idkTableRect.top()+14*mmToPixels);
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left(),mainTableRect.top()+5*mmToPixels, 7*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 14));
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.top()+5*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 15));
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.top()+5*mmToPixels, 23*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 16));
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.top()+5*mmToPixels, 15*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 17));
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.top()+5*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 18));
painter.drawText(mainTableRect.left(),mainTableRect.top()+10*mmToPixels, 7*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Изм.");
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.top()+10*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Лист");
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.top()+10*mmToPixels, 23*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"№ докум.");
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.top()+10*mmToPixels, 15*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Подп.");
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.top()+10*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Дата");
painter.drawText(mainTableRect.left()+1*mmToPixels,mainTableRect.top()+15*mmToPixels, 17*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,"Разраб.");
painter.drawText(mainTableRect.left()+1*mmToPixels,mainTableRect.top()+20*mmToPixels, 17*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,"Пров.");
painter.drawText(mainTableRect.left()+1*mmToPixels,mainTableRect.top()+25*mmToPixels, 17*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 10));
painter.drawText(mainTableRect.left()+17*mmToPixels+1*mmToPixels,mainTableRect.top()+25*mmToPixels, 23*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 11));
painter.drawText(mainTableRect.left()+17*mmToPixels+1*mmToPixels,mainTableRect.top()+15*mmToPixels, 23*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 111));
painter.drawText(mainTableRect.left()+17*mmToPixels+1*mmToPixels,mainTableRect.top()+20*mmToPixels, 23*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 112));
painter.drawText(mainTableRect.left()+17*mmToPixels+1*mmToPixels,mainTableRect.top()+30*mmToPixels, 23*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 113));
painter.drawText(mainTableRect.left()+17*mmToPixels+1*mmToPixels,mainTableRect.top()+35*mmToPixels, 23*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 114));
painter.drawText(mainTableRect.left()+40*mmToPixels+1*mmToPixels,mainTableRect.top()+25*mmToPixels, 15*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 12));
painter.drawText(mainTableRect.left()+55*mmToPixels+1*mmToPixels,mainTableRect.top()+25*mmToPixels, 10*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 13));
painter.drawText(mainTableRect.left()+1*mmToPixels,mainTableRect.top()+30*mmToPixels, 17*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,"Н. контр.");
painter.drawText(mainTableRect.left()+1*mmToPixels,mainTableRect.top()+35*mmToPixels, 17*mmToPixels-1*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter,"Утв.");
if(docType!=4){
QFont nameFont = createGostFont(18, false, true);
QString nameText = getInscriptionValueWithProjectParams(model, projectParamModel, 1);
if(docType==3){
nameText = getInscriptionValueWithProjectParams(model, projectParamModel, 1002);
}
QRectF nameRect(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+15*mmToPixels, 70*mmToPixels, 25*mmToPixels);
drawTextMultiline(painter, nameRect, nameText, nameFont, 3);
painter.setFont(createGostFont(12, false, true));
if(docType==1){
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+15*mmToPixels,70*mmToPixels, 25*mmToPixels,Qt::AlignHCenter|Qt::AlignBottom, "Перечень элементов");
}
}
else{
painter.setFont(createGostFont(18, false, true));
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+15*mmToPixels,70*mmToPixels, 20*mmToPixels,Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 1));
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+35*mmToPixels,70*mmToPixels, 5*mmToPixels,Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 301));
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.bottom()-20*mmToPixels,70*mmToPixels, 20*mmToPixels,Qt::AlignHCenter|Qt::AlignBottom, "Ведомость покупных изделий");
}
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.bottom(),70*mmToPixels, 5*mmToPixels,Qt::AlignLeft|Qt::AlignVCenter, "Копировал");
// if(docType==4){
// painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top(), 120*mmToPixels, 10*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 2));
// painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+10*mmToPixels, 120*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 301));
// }
// else{
painter.setFont(createGostFont(18, false, true));
QString titleText = getInscriptionValueWithProjectParams(model, projectParamModel, 2);
if(docType==1){
titleText += " ПЭ3";
}
else if(docType == 4){
titleText += " ВП";
}
else if(docType == 3){
// Для спецификации используем значение из поля 1001 вместо стандартного
titleText = getInscriptionValueWithProjectParams(model, projectParamModel, 1001);
}
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top(), 120*mmToPixels, 15*mmToPixels, Qt::AlignCenter, titleText);
// }
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left()+135*mmToPixels, mainTableRect.top()+15*mmToPixels, 15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Лит.");
painter.drawText(mainTableRect.left()+150*mmToPixels, mainTableRect.top()+15*mmToPixels, 15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Лист");
painter.drawText(mainTableRect.left()+165*mmToPixels, mainTableRect.top()+15*mmToPixels, 20*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Листов");
QString littera = getInscriptionValueWithProjectParams(model, projectParamModel, 4);
for(int litI = 0 ; litI<3; litI++){
if(littera.size()>litI)
painter.drawText(mainTableRect.left()+135*mmToPixels+5*mmToPixels*litI, mainTableRect.top()+20*mmToPixels, 5*mmToPixels, 5*mmToPixels, Qt::AlignCenter, littera.at(litI));
}
if(totalPages>1){
painter.drawText(mainTableRect.left()+150*mmToPixels, mainTableRect.top()+20*mmToPixels, 15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, QString::number(currentPage));
}
painter.drawText(mainTableRect.left()+165*mmToPixels, mainTableRect.top()+20*mmToPixels, 20*mmToPixels, 5*mmToPixels, Qt::AlignCenter, QString::number(totalPages));
painter.drawText(mainTableRect.left()+135*mmToPixels, mainTableRect.top()+25*mmToPixels, 50*mmToPixels, 15*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 9));
if(docType==4){
painter.drawText(mainTableRect.left()+135*mmToPixels, mainTableRect.bottom(), 50*mmToPixels, 5*mmToPixels, Qt::AlignLeft|Qt::AlignVCenter, "Формат А3");
}
else{
painter.drawText(mainTableRect.left()+135*mmToPixels, mainTableRect.bottom(), 50*mmToPixels, 5*mmToPixels, Qt::AlignLeft|Qt::AlignVCenter, "Формат А4");
}
painter.drawText(idkTableRect.left(), idkTableRect.top(), 14*mmToPixels, 14*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 27));
painter.drawText(idkTableRect.left()+14*mmToPixels, idkTableRect.top(), 53*mmToPixels, 14*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 28));
painter.drawText(idkTableRect.left()+67*mmToPixels, idkTableRect.top(), 53*mmToPixels, 14*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 29));
painter.drawText(idkTableRect.left(), idkTableRect.top()+14*mmToPixels,120*mmToPixels, 8*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 30));
painter.save();
// Создаем трансформацию для поворота текста на 90 градусов
QTransform transform;
transform.translate(lowTableRect.right(), lowTableRect.top());
transform.rotate(-90);
painter.setTransform(transform);
// Рисуем повернутый текст
painter.drawText(0, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № подл");
painter.drawText(25*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(60*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Взам. инв. №");
painter.drawText(85*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № дубл");
painter.drawText(110*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(0, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 19));
painter.drawText(25*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 20));
painter.drawText(60*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 21));
painter.drawText(85*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 22));
painter.drawText(110*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 23));
// painter.drawRect(0, 0, 145*mmToPixels, 12*mmToPixels);
// Восстанавливаем трансформацию
painter.restore();
painter.save();
QTransform transformTop;
transformTop.translate(topTableRect.right(), topTableRect.bottom());
transformTop.rotate(-90);
painter.setTransform(transformTop);
painter.drawText(0,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(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 25));
painter.restore();
return true;
}
bool PDFController::addGostFrameA4(QPainter &painter, const QRectF &pageRect, const TitleInscriptionsModel* model, const ProjectParamTableModel* projectParamModel, int currentPage, int totalPages, int docType)
{
// Рисуем только внутреннюю рамку ГОСТ с отступами:
// Слева: 20мм, Сверху: 5мм, Справа: 5мм, Снизу: 5мм
QPen framePen(Qt::black, 1.0);
painter.setPen(framePen);
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4; // 25.4 мм = 1 дюйм
// Вычисляем отступы в пикселях
qreal leftMargin = 20 * mmToPixels; // 20мм слева
qreal topMargin = 5 * mmToPixels; // 5мм сверху
qreal rightMargin = 5 * mmToPixels; // 5мм справа
qreal bottomMargin = 5 * mmToPixels; // 5мм снизу
// Внутренняя рамка с указанными отступами в пикселях
QRectF innerRect = pageRect.adjusted(leftMargin, topMargin, -rightMargin, -bottomMargin);
painter.drawRect(innerRect);
// Пример использования шрифта для текста
// Получаем текущий шрифт
QFont currentFont = painter.font();
QRectF lowTableRect = QRectF(innerRect.left(), innerRect.bottom(), -12*mmToPixels, -(25+35+25+25+35)*mmToPixels);
// Сначала рисуем всё в обычном прямоугольнике
painter.drawRect(lowTableRect);
// Рисуем повернутый прямоугольник с тем же содержимым
painter.drawLine(lowTableRect.right()+5*mmToPixels, lowTableRect.top(), lowTableRect.right()+5*mmToPixels, lowTableRect.bottom());
painter.drawLine(lowTableRect.right(), lowTableRect.top()-25*mmToPixels, lowTableRect.left(), lowTableRect.top()-25*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels);
QRectF mainTableRect = QRect(innerRect.right()-185*mmToPixels,innerRect.bottom()-15*mmToPixels,185*mmToPixels, 15*mmToPixels);
painter.drawRect(mainTableRect);
painter.drawLine(mainTableRect.left()+7*mmToPixels, mainTableRect.top(),mainTableRect.left()+7*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+17*mmToPixels, mainTableRect.top(),mainTableRect.left()+17*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+40*mmToPixels, mainTableRect.top(),mainTableRect.left()+40*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+55*mmToPixels, mainTableRect.top(),mainTableRect.left()+55*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+65*mmToPixels, mainTableRect.top(),mainTableRect.left()+65*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+175*mmToPixels, mainTableRect.top(),mainTableRect.left()+175*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left(),mainTableRect.top()+5*mmToPixels,mainTableRect.left()+65*mmToPixels, mainTableRect.top()+5*mmToPixels);
painter.drawLine(mainTableRect.left(),mainTableRect.top()+10*mmToPixels,mainTableRect.left()+65*mmToPixels, mainTableRect.top()+10*mmToPixels);
painter.drawLine(mainTableRect.right()-10*mmToPixels,mainTableRect.top()+7*mmToPixels,mainTableRect.right(), mainTableRect.top()+7*mmToPixels);
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left(),mainTableRect.bottom()-5*mmToPixels,7*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Изм.");
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.bottom()-5*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Лист");
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.bottom()-5*mmToPixels,23*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "№ докум");
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.bottom()-5*mmToPixels,15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп.");
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.bottom()-5*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Дата");
painter.drawText(mainTableRect.left(),mainTableRect.bottom()-10*mmToPixels,7*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 14));
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.bottom()-10*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 15));
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.bottom()-10*mmToPixels,23*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 16));
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.bottom()-10*mmToPixels,15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 17));
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.bottom()-10*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 18));
// if(docType==4){
// painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top(), 110*mmToPixels, 10*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 2));
// painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+10*mmToPixels, 110*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 301));
// }
// else{
// painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top(), 110*mmToPixels, 15*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 2));
// }
painter.setFont(createGostFont(24, false, true));
QString titleText = getInscriptionValueWithProjectParams(model, projectParamModel, 2);
if(docType==1){
titleText += " ПЭ3";
}
else if(docType == 4){
titleText += " ВП";
}
else if(docType == 3){
// Для спецификации используем значение из поля 1001 вместо стандартного
titleText = getInscriptionValueWithProjectParams(model, projectParamModel, 1001);
}
painter.drawText(mainTableRect.left()+65*mmToPixels,mainTableRect.top(),110*mmToPixels, 15*mmToPixels, Qt::AlignCenter,titleText);
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left()+65*mmToPixels,mainTableRect.bottom(),110*mmToPixels, 5*mmToPixels, Qt::AlignLeft|Qt::AlignVCenter, "Копировал");
if(docType==4){
painter.drawText(mainTableRect.left()+65*mmToPixels,mainTableRect.bottom(),110*mmToPixels, 5*mmToPixels, Qt::AlignRight|Qt::AlignVCenter, "Формат А3");
}
else{
painter.drawText(mainTableRect.left()+65*mmToPixels,mainTableRect.bottom(),110*mmToPixels, 5*mmToPixels, Qt::AlignRight|Qt::AlignVCenter, "Формат А4");
}
painter.drawText(mainTableRect.right()-10*mmToPixels,mainTableRect.top(),10*mmToPixels, 7*mmToPixels, Qt::AlignCenter, "Лист");
painter.drawText(mainTableRect.right()-10*mmToPixels,mainTableRect.top()+7*mmToPixels,10*mmToPixels, 8*mmToPixels, Qt::AlignCenter, QString::number(currentPage));
painter.save();
// Создаем трансформацию для поворота текста на 90 градусов
QTransform transform;
transform.translate(lowTableRect.right(), lowTableRect.top());
transform.rotate(-90);
painter.setTransform(transform);
// Рисуем повернутый текст
painter.drawText(0, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № подл");
painter.drawText(25*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(60*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Взам. инв. №");
painter.drawText(85*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № дубл");
painter.drawText(110*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(0, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 19));
painter.drawText(25*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 20));
painter.drawText(60*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 21));
painter.drawText(85*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 22));
painter.drawText(110*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 23));
painter.restore();
return true;
}
bool PDFController::addGostFrameA3FirstPage(QPainter &painter, const QRectF &pageRect, const TitleInscriptionsModel *model, const ProjectParamTableModel *projectParamModel, int currentPage, int totalPages)
{
QString fontPath = ":/assets/GOST_A.TTF";
int fontId = QFontDatabase::addApplicationFont(fontPath);
if (fontId == -1) {
qDebug() << "PDFController::addGostFrameA4: Не удалось загрузить шрифт из ресурсов:/assets/GOST_A.TTF";
// Используем стандартный шрифт как fallback
QFont fallbackFont("Arial", 6);
painter.setFont(fallbackFont);
} else {
// Получаем имя семейства шрифта
QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);
if (!fontFamilies.isEmpty()) {
QString fontFamily = fontFamilies.first();
qDebug() << "PDFController::addGostFrameA4: Загружен шрифт из ресурсов:" << fontFamily;
// Создаем шрифт с нужным кеглем (размером)
QFont gostFont(fontFamily, 12); // кегль 12 пунктов
painter.setFont(gostFont);
}
}
// Рисуем только внутреннюю рамку ГОСТ с отступами:
// Слева: 20мм, Сверху: 5мм, Справа: 5мм, Снизу: 5мм
QPen framePen(Qt::black, 1.0);
painter.setPen(framePen);
// Конвертируем миллиметры в пиксели
qreal mmToPixels = (painter.device()->logicalDpiY() / 25.4); // 25.4 мм = 1 дюйм
// Вычисляем отступы в пикселях
qreal leftMargin = 20 * mmToPixels; // 20мм слева
qreal topMargin = 5 * mmToPixels; // 5мм сверху
qreal rightMargin = 5 * mmToPixels; // 5мм справа
qreal bottomMargin = 5 * mmToPixels; // 5мм снизу
QRectF innerRect = pageRect.adjusted(leftMargin, topMargin, -rightMargin, -bottomMargin);
painter.drawRect(innerRect);
QFont currentFont = painter.font();
QRectF lowTableRect = QRectF(innerRect.left(), innerRect.bottom(), -12*mmToPixels, -(25+35+25+25+35)*mmToPixels);
// Сначала рисуем всё в обычном прямоугольнике
painter.drawRect(lowTableRect);
// Рисуем повернутый прямоугольник с тем же содержимым
painter.drawLine(lowTableRect.right()+5*mmToPixels, lowTableRect.top(), lowTableRect.right()+5*mmToPixels, lowTableRect.bottom());
painter.drawLine(lowTableRect.right(), lowTableRect.top()-25*mmToPixels, lowTableRect.left(), lowTableRect.top()-25*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels);
QRectF topTableRect = QRectF(innerRect.left(), innerRect.top(), -12*mmToPixels, 120*mmToPixels);
painter.drawRect(topTableRect);
painter.drawLine(topTableRect.right()+5*mmToPixels, topTableRect.top(), topTableRect.right()+5*mmToPixels, topTableRect.bottom());
painter.drawLine(topTableRect.right(), topTableRect.top()+60*mmToPixels, topTableRect.left(),topTableRect.top()+60*mmToPixels);
QRectF mainTableRect = QRect(innerRect.right()-185*mmToPixels,innerRect.bottom()-40*mmToPixels,185*mmToPixels, 40*mmToPixels);
painter.drawRect(mainTableRect);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+5*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+5*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+10*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+10*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+15*mmToPixels,mainTableRect.right(), mainTableRect.top()+15*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+20*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+20*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+25*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+30*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+30*mmToPixels);
painter.drawLine(mainTableRect.left(), mainTableRect.top()+35*mmToPixels,mainTableRect.left()+(7+10+23+15+10)*mmToPixels, mainTableRect.top()+35*mmToPixels);
painter.drawLine(mainTableRect.right()-50*mmToPixels, mainTableRect.top()+20*mmToPixels,mainTableRect.right(), mainTableRect.top()+20*mmToPixels);
painter.drawLine(mainTableRect.right()-50*mmToPixels, mainTableRect.top()+25*mmToPixels,mainTableRect.right(), mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.left()+65*mmToPixels, mainTableRect.top(),mainTableRect.left()+65*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+55*mmToPixels, mainTableRect.top(),mainTableRect.left()+55*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+40*mmToPixels, mainTableRect.top(),mainTableRect.left()+40*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+17*mmToPixels, mainTableRect.top(),mainTableRect.left()+17*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+7*mmToPixels, mainTableRect.top(),mainTableRect.left()+7*mmToPixels, mainTableRect.top()+15*mmToPixels);
painter.drawLine(mainTableRect.right()-50*mmToPixels, mainTableRect.top()+15*mmToPixels,mainTableRect.right()-50*mmToPixels,mainTableRect.bottom());
painter.drawLine(mainTableRect.right()-45*mmToPixels, mainTableRect.top()+20*mmToPixels,mainTableRect.right()-45*mmToPixels,mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.right()-40*mmToPixels, mainTableRect.top()+20*mmToPixels,mainTableRect.right()-40*mmToPixels,mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.right()-35*mmToPixels, mainTableRect.top()+15*mmToPixels,mainTableRect.right()-35*mmToPixels,mainTableRect.top()+25*mmToPixels);
painter.drawLine(mainTableRect.right()-20*mmToPixels, mainTableRect.top()+15*mmToPixels,mainTableRect.right()-20*mmToPixels,mainTableRect.top()+25*mmToPixels);
QRectF idkTableRect = QRectF(mainTableRect.right()-120*mmToPixels,mainTableRect.top()-22*mmToPixels, 120*mmToPixels, 22*mmToPixels);
// painter.drawRect(idkTableRect);
painter.drawLine(idkTableRect.topLeft(), idkTableRect.bottomLeft());
painter.drawLine(idkTableRect.topRight(), idkTableRect.bottomRight());
painter.drawLine(idkTableRect.topRight(), idkTableRect.topLeft());
painter.drawLine(idkTableRect.left(),idkTableRect.top()+14*mmToPixels, idkTableRect.right(),idkTableRect.top()+14*mmToPixels);
painter.drawLine(idkTableRect.left()+14*mmToPixels,idkTableRect.top(), idkTableRect.left()+14*mmToPixels,idkTableRect.top()+14*mmToPixels);
painter.drawLine(idkTableRect.left()+67*mmToPixels, idkTableRect.top(), idkTableRect.left()+67*mmToPixels, idkTableRect.top()+14*mmToPixels);
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left(),mainTableRect.top()+5*mmToPixels, 7*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 14));
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.top()+5*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 15));
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.top()+5*mmToPixels, 23*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 16));
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.top()+5*mmToPixels, 15*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 17));
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.top()+5*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 18));
painter.drawText(mainTableRect.left(),mainTableRect.top()+10*mmToPixels, 7*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Изм.");
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.top()+10*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Лист");
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.top()+10*mmToPixels, 23*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"№ докум.");
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.top()+10*mmToPixels, 15*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Подп.");
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.top()+10*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Дата");
painter.drawText(mainTableRect.left(),mainTableRect.top()+15*mmToPixels, 17*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Разраб.");
painter.drawText(mainTableRect.left(),mainTableRect.top()+20*mmToPixels, 17*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Пров.");
painter.drawText(mainTableRect.left(),mainTableRect.top()+25*mmToPixels, 17*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 10));
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.top()+25*mmToPixels, 23*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 11));
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.top()+25*mmToPixels, 15*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 12));
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.top()+25*mmToPixels, 10*mmToPixels, 5*mmToPixels,Qt::AlignCenter,getInscriptionValueWithProjectParams(model, projectParamModel, 13));
painter.drawText(mainTableRect.left(),mainTableRect.top()+30*mmToPixels, 17*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Н. контр.");
painter.drawText(mainTableRect.left(),mainTableRect.top()+35*mmToPixels, 17*mmToPixels, 5*mmToPixels,Qt::AlignCenter,"Утв.");
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+15*mmToPixels,70*mmToPixels, 25*mmToPixels,Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 1));
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.top(), 120*mmToPixels, 15*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 2));
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.bottom()+5*mmToPixels, 120*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 301));
painter.drawText(mainTableRect.left()+135*mmToPixels, mainTableRect.top()+15*mmToPixels, 15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Лит.");
painter.drawText(mainTableRect.left()+150*mmToPixels, mainTableRect.top()+15*mmToPixels, 15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Лист");
painter.drawText(mainTableRect.left()+165*mmToPixels, mainTableRect.top()+15*mmToPixels, 20*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Листов");
painter.drawText(mainTableRect.left()+140*mmToPixels, mainTableRect.top()+20*mmToPixels, 5*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 4));
painter.drawText(mainTableRect.left()+150*mmToPixels, mainTableRect.top()+20*mmToPixels, 15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, QString::number(currentPage));
painter.drawText(mainTableRect.left()+165*mmToPixels, mainTableRect.top()+20*mmToPixels, 20*mmToPixels, 5*mmToPixels, Qt::AlignCenter, QString::number(totalPages));
painter.drawText(mainTableRect.left()+135*mmToPixels, mainTableRect.top()+25*mmToPixels, 50*mmToPixels, 15*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 9));
painter.drawText(idkTableRect.left(), idkTableRect.top(), 14*mmToPixels, 14*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 27));
painter.drawText(idkTableRect.left()+14*mmToPixels, idkTableRect.top(), 53*mmToPixels, 14*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 28));
painter.drawText(idkTableRect.left()+67*mmToPixels, idkTableRect.top(), 53*mmToPixels, 14*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 29));
painter.drawText(idkTableRect.left(), idkTableRect.top()+14*mmToPixels,120*mmToPixels, 8*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 30));
painter.save();
// Создаем трансформацию для поворота текста на 90 градусов
QTransform transform;
transform.translate(lowTableRect.right(), lowTableRect.top());
transform.rotate(-90);
painter.setTransform(transform);
// Рисуем повернутый текст
painter.drawText(0, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № подл");
painter.drawText(25*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(60*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Взам. инв. №");
painter.drawText(85*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № дубл");
painter.drawText(110*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(0, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 19));
painter.drawText(25*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 20));
painter.drawText(60*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 21));
painter.drawText(85*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 22));
painter.drawText(110*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 23));
// painter.drawRect(0, 0, 145*mmToPixels, 12*mmToPixels);
// Восстанавливаем трансформацию
painter.restore();
painter.save();
QTransform transformTop;
transformTop.translate(topTableRect.right(), topTableRect.bottom());
transformTop.rotate(-90);
painter.setTransform(transformTop);
painter.drawText(0,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(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 25));
painter.restore();
return true;
}
bool PDFController::addGostFrameA3(QPainter &painter, const QRectF &pageRect, const TitleInscriptionsModel *model, const ProjectParamTableModel *projectParamModel, int currentPage, int totalPages)
{
// Рисуем только внутреннюю рамку ГОСТ с отступами:
// Слева: 20мм, Сверху: 5мм, Справа: 5мм, Снизу: 5мм
QPen framePen(Qt::black, 1.0);
painter.setPen(framePen);
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4; // 25.4 мм = 1 дюйм
// Вычисляем отступы в пикселях
qreal leftMargin = 20 * mmToPixels; // 20мм слева
qreal topMargin = 5 * mmToPixels; // 5мм сверху
qreal rightMargin = 5 * mmToPixels; // 5мм справа
qreal bottomMargin = 5 * mmToPixels; // 5мм снизу
// Внутренняя рамка с указанными отступами в пикселях
QRectF innerRect = pageRect.adjusted(leftMargin, topMargin, -rightMargin, -bottomMargin);
painter.drawRect(innerRect);
// Пример использования шрифта для текста
// Получаем текущий шрифт
QFont currentFont = painter.font();
QRectF lowTableRect = QRectF(innerRect.left(), innerRect.bottom(), -12*mmToPixels, -(25+35+25+25+35)*mmToPixels);
// Сначала рисуем всё в обычном прямоугольнике
painter.drawRect(lowTableRect);
// Рисуем повернутый прямоугольник с тем же содержимым
painter.drawLine(lowTableRect.right()+5*mmToPixels, lowTableRect.top(), lowTableRect.right()+5*mmToPixels, lowTableRect.bottom());
painter.drawLine(lowTableRect.right(), lowTableRect.top()-25*mmToPixels, lowTableRect.left(), lowTableRect.top()-25*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25)*mmToPixels);
painter.drawLine(lowTableRect.right(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels, lowTableRect.left(), lowTableRect.top()-(25+35+25+25+35)*mmToPixels);
QRectF mainTableRect = QRect(innerRect.right()-185*mmToPixels,innerRect.bottom()-15*mmToPixels,185*mmToPixels, 15*mmToPixels);
painter.drawRect(mainTableRect);
painter.drawLine(mainTableRect.left()+7*mmToPixels, mainTableRect.top(),mainTableRect.left()+7*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+17*mmToPixels, mainTableRect.top(),mainTableRect.left()+17*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+40*mmToPixels, mainTableRect.top(),mainTableRect.left()+40*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+55*mmToPixels, mainTableRect.top(),mainTableRect.left()+55*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+65*mmToPixels, mainTableRect.top(),mainTableRect.left()+65*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left()+175*mmToPixels, mainTableRect.top(),mainTableRect.left()+175*mmToPixels, mainTableRect.bottom());
painter.drawLine(mainTableRect.left(),mainTableRect.top()+5*mmToPixels,mainTableRect.left()+65*mmToPixels, mainTableRect.top()+5*mmToPixels);
painter.drawLine(mainTableRect.left(),mainTableRect.top()+10*mmToPixels,mainTableRect.left()+65*mmToPixels, mainTableRect.top()+10*mmToPixels);
painter.drawLine(mainTableRect.right()-10*mmToPixels,mainTableRect.top()+7*mmToPixels,mainTableRect.right(), mainTableRect.top()+7*mmToPixels);
painter.setFont(createGostFont(12, false, true));
painter.drawText(mainTableRect.left(),mainTableRect.bottom()-5*mmToPixels,7*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Изм.");
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.bottom()-5*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Лист");
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.bottom()-5*mmToPixels,23*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "№ докум");
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.bottom()-5*mmToPixels,15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп.");
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.bottom()-5*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Дата");
painter.drawText(mainTableRect.left(),mainTableRect.bottom()-10*mmToPixels,7*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 14));
painter.drawText(mainTableRect.left()+7*mmToPixels,mainTableRect.bottom()-10*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 15));
painter.drawText(mainTableRect.left()+17*mmToPixels,mainTableRect.bottom()-10*mmToPixels,23*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 16));
painter.drawText(mainTableRect.left()+40*mmToPixels,mainTableRect.bottom()-10*mmToPixels,15*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 17));
painter.drawText(mainTableRect.left()+55*mmToPixels,mainTableRect.bottom()-10*mmToPixels,10*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 18));
painter.drawText(mainTableRect.left()+65*mmToPixels,mainTableRect.top(),110*mmToPixels, 15*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 2));
painter.drawText(mainTableRect.left()+65*mmToPixels, mainTableRect.bottom()+5*mmToPixels, 120*mmToPixels, 5*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 301));
painter.drawText(mainTableRect.right()-10*mmToPixels,mainTableRect.top(),10*mmToPixels, 7*mmToPixels, Qt::AlignCenter, "Лист");
painter.drawText(mainTableRect.right()-10*mmToPixels,mainTableRect.top()+7*mmToPixels,10*mmToPixels, 8*mmToPixels, Qt::AlignCenter, QString::number(currentPage));
painter.save();
// Создаем трансформацию для поворота текста на 90 градусов
QTransform transform;
transform.translate(lowTableRect.right(), lowTableRect.top());
transform.rotate(-90);
painter.setTransform(transform);
// Рисуем повернутый текст
painter.drawText(0, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № подл");
painter.drawText(25*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(60*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Взам. инв. №");
painter.drawText(85*mmToPixels, 0, 25*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Инв. № дубл");
painter.drawText(110*mmToPixels, 0, 35*mmToPixels, 5*mmToPixels, Qt::AlignCenter, "Подп. и дата");
painter.drawText(0, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 19));
painter.drawText(25*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 20));
painter.drawText(60*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 21));
painter.drawText(85*mmToPixels, 5*mmToPixels, 25*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 22));
painter.drawText(110*mmToPixels, 5*mmToPixels, 35*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 23));
painter.restore();
return true;
}
bool PDFController::addTitleInscriptions(QPainter &painter, TitleInscriptionsModel *titleModel, const QRectF &stampRect)
{
if (!titleModel) {
return false;
}
// Рисуем рамку штампа
QPen stampPen(Qt::black, 0.5);
painter.setPen(stampPen);
painter.drawRect(stampRect);
// Добавляем надписи из модели
QFont stampFont("Arial", 8);
painter.setFont(stampFont);
QMap<int, QString> inscriptions = titleModel->getAllInscriptions();
int yOffset = 0;
int lineHeight = 12;
for (auto it = inscriptions.begin(); it != inscriptions.end(); ++it) {
if (!it.value().isEmpty()) {
QString text = QString("%1: %2").arg(it.key()).arg(it.value());
painter.drawText(QRectF(stampRect.x() + 5, stampRect.y() + 5 + yOffset,
stampRect.width() - 10, lineHeight),
text, QTextOption(Qt::AlignLeft));
yOffset += lineHeight;
}
}
return true;
}
bool PDFController::addPerechenTable(QPainter &painter, PerechenTableModel *perechenModel, const QRectF &tableRect, MainController *mainController)
{
// Используем новый метод для отображения всех строк
return addPerechenTableRange(painter, perechenModel, tableRect, 0, perechenModel->rowCount(), mainController);
}
bool PDFController::addPerechenTableRange(QPainter &painter, PerechenTableModel *perechenModel, const QRectF &tableRect, int startRow, int rowCount, MainController *mainController)
{
if (!perechenModel) {
return false;
}
// Рисуем рамку таблицы
QPen tablePen(Qt::black, 1.0);
painter.setPen(tablePen);
// Настройки шрифта для таблицы - получаем из настроек проекта
int fontSize = 12;
int fontStretch = 100;
if (mainController && mainController->perechenTableController()) {
fontSize = mainController->perechenTableController()->getFontSize();
fontStretch = mainController->perechenTableController()->getFontStretch();
}
QFont tableFont = createGostFont(fontSize, false, true, fontStretch);
painter.setFont(tableFont);
// Заголовки колонок
QStringList headers = {"Поз.", "Наименование", "Кол.", "Примечание"};
// Размеры колонок в миллиметрах (конвертируем в пиксели)
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
qreal posWidth = 20 * mmToPixels; // Поз.: 20мм
qreal nameWidth = 110 * mmToPixels; // Наименование: 110мм
qreal qtyWidth = 10 * mmToPixels; // Кол.: 10мм
qreal noteWidth = 45 * mmToPixels; // Примечание: 45мм
qreal rowHeight = 8 * mmToPixels;
// Позиция начала таблицы
qreal tableStartX = tableRect.x();
// Рисуем заголовки с фиксированными размерами колонок
qreal currentX = tableStartX;
// Колонка "Поз." (20мм)
QRectF posHeaderRect(currentX, tableRect.y(), posWidth, rowHeight);
painter.drawRect(posHeaderRect);
painter.drawText(posHeaderRect, headers[0], QTextOption(Qt::AlignCenter));
currentX += posWidth;
// Колонка "Наименование" (110мм)
QRectF nameHeaderRect(currentX, tableRect.y(), nameWidth, rowHeight);
painter.drawRect(nameHeaderRect);
painter.drawText(nameHeaderRect, headers[1], QTextOption(Qt::AlignCenter));
currentX += nameWidth;
// Колонка "Кол." (10мм)
QRectF qtyHeaderRect(currentX, tableRect.y(), qtyWidth, rowHeight);
painter.drawRect(qtyHeaderRect);
painter.drawText(qtyHeaderRect, headers[2], QTextOption(Qt::AlignCenter));
currentX += qtyWidth;
// Колонка "Примечание" (45мм)
QRectF noteHeaderRect(currentX, tableRect.y(), noteWidth, rowHeight);
painter.drawRect(noteHeaderRect);
painter.drawText(noteHeaderRect, headers[3], QTextOption(Qt::AlignCenter));
// Рисуем данные с указанным диапазоном строк
int totalRows = perechenModel->rowCount();
int endRow = qMin(startRow + rowCount, totalRows);
for (int displayRow = 0; displayRow < rowCount; ++displayRow) {
int row = startRow + displayRow; // Номер строки в модели
currentX = tableStartX;
// Колонка "Поз." (20мм)
QRectF posCellRect(currentX, tableRect.y() + (displayRow + 1) * rowHeight, posWidth, rowHeight);
painter.drawRect(posCellRect);
// Если это реальная строка данных (не пустая)
if (row < totalRows) {
QModelIndex posIndex = perechenModel->index(row, 0);
if (posIndex.isValid()) {
QString cellText = perechenModel->data(posIndex, Qt::DisplayRole).toString();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(posIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
painter.setFont(cellFont);
painter.drawText(posCellRect, cellText, QTextOption(Qt::AlignCenter));
// Восстанавливаем основной шрифт
painter.setFont(tableFont);
}
}
currentX += posWidth;
// Колонка "Наименование" (110мм)
QRectF nameCellRect(currentX, tableRect.y() + (displayRow + 1) * rowHeight, nameWidth, rowHeight);
painter.drawRect(nameCellRect);
// Если это реальная строка данных (не пустая)
if (row < totalRows) {
QModelIndex nameIndex = perechenModel->index(row, 1);
if (nameIndex.isValid()) {
QString cellText = perechenModel->data(nameIndex, Qt::DisplayRole).toString();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(nameIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
// Проверяем, является ли ячейка заголовком из PerechenCellData
bool isHeader = false;
bool shouldUnderline = false;
QVariant cellData = perechenModel->data(nameIndex, Qt::UserRole);
if (cellData.isValid() && cellData.canConvert<PerechenCellData>()) {
PerechenCellData cell = cellData.value<PerechenCellData>();
isHeader = cell.isHeader;
shouldUnderline = cell.isUnderline;
}
// Если это заголовок, применяем специальное форматирование
if (isHeader) {
// Сохраняем текущие настройки
QPen originalPen = painter.pen();
QFont originalFont = painter.font();
// Устанавливаем шрифт с поджимом для заголовка
painter.setFont(cellFont);
// Рисуем текст по центру без переноса строк
QTextOption headerTextOption(Qt::AlignCenter);
headerTextOption.setWrapMode(QTextOption::NoWrap); // Явно отключаем перенос строк
painter.drawText(nameCellRect, cellText.trimmed(), headerTextOption);
// Проверяем, нужно ли рисовать подчеркивание
if (shouldUnderline) {
// Рисуем подчеркивание вручную с настраиваемым расстоянием
QFontMetrics metrics(painter.font());
QRectF textRect = metrics.boundingRect(cellText.trimmed());
// Вычисляем позицию текста по центру
qreal textX = nameCellRect.x() + (nameCellRect.width() - textRect.width()) / 2;
qreal textY = nameCellRect.y() + (nameCellRect.height() + textRect.height()) / 2;
// Настраиваемое расстояние подчеркивания от текста (в пикселях)
qreal underlineOffset = 2.0; // Можно изменить это значение
// Рисуем линию подчеркивания
QPen underlinePen(Qt::black, 1.0);
painter.setPen(underlinePen);
painter.drawLine(
textX,
textY + underlineOffset,
textX + textRect.width(),
textY + underlineOffset
);
}
// Восстанавливаем оригинальные настройки
painter.setFont(originalFont);
painter.setPen(originalPen);
} else {
// Обычное форматирование (по левому краю) - используем drawCellWithStretch без переноса
drawCellWithStretch(painter, nameIndex, nameCellRect.adjusted(2*mmToPixels,0,0,0), cellText, fontSize, fontStretch, tableFont, Qt::AlignLeft|Qt::AlignVCenter, mainController);
}
}
}
currentX += nameWidth;
// Колонка "Кол." (10мм)
QRectF qtyCellRect(currentX, tableRect.y() + (displayRow + 1) * rowHeight, qtyWidth, rowHeight);
painter.drawRect(qtyCellRect);
// Если это реальная строка данных (не пустая)
if (row < totalRows) {
QModelIndex qtyIndex = perechenModel->index(row, 2);
if (qtyIndex.isValid()) {
QString cellText = perechenModel->data(qtyIndex, Qt::DisplayRole).toString();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(qtyIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
painter.setFont(cellFont);
painter.drawText(qtyCellRect, cellText, QTextOption(Qt::AlignCenter));
// Восстанавливаем основной шрифт
painter.setFont(tableFont);
}
}
currentX += qtyWidth;
// Колонка "Примечание" (45мм)
QRectF noteCellRect(currentX, tableRect.y() + (displayRow + 1) * rowHeight, noteWidth, rowHeight);
painter.drawRect(noteCellRect);
// Если это реальная строка данных (не пустая)
if (row < totalRows) {
QModelIndex noteIndex = perechenModel->index(row, 3);
if (noteIndex.isValid()) {
QString cellText = perechenModel->data(noteIndex, Qt::DisplayRole).toString();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(noteIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
painter.setFont(cellFont);
painter.drawText(noteCellRect, cellText, QTextOption(Qt::AlignCenter));
// Восстанавливаем основной шрифт
painter.setFont(tableFont);
}
}
}
return true;
}
// Утилитарные функции для работы с шрифтом ГОСТ
// Вспомогательная функция для получения поджима ячейки
int PDFController::getCellStretch(const QModelIndex &index, int defaultStretch)
{
if (!index.isValid()) {
return defaultStretch;
}
QVariant cellData = index.model()->data(index, Qt::UserRole);
if (cellData.isValid()) {
// Пытаемся получить поджим из разных типов CellData
if (cellData.canConvert<PerechenCellData>()) {
PerechenCellData cell = cellData.value<PerechenCellData>();
if (cell.stretch != 100) {
return cell.stretch;
}
} else if (cellData.canConvert<SpecificationPCBCellData>()) {
SpecificationPCBCellData cell = cellData.value<SpecificationPCBCellData>();
if (cell.stretch != 100) {
return cell.stretch;
}
} else if (cellData.canConvert<SpecificationCellData>()) {
SpecificationCellData cell = cellData.value<SpecificationCellData>();
if (cell.stretch != 100) {
return cell.stretch;
}
} else if (cellData.canConvert<VedomostCellData>()) {
VedomostCellData cell = cellData.value<VedomostCellData>();
if (cell.stretch != 100) {
return cell.stretch;
}
}
}
return defaultStretch;
}
bool PDFController::getCellUnderline(const QModelIndex &index, bool defaultUnderline)
{
if (!index.isValid()) {
return defaultUnderline;
}
QVariant cellData = index.model()->data(index, Qt::UserRole);
if (cellData.isValid()) {
// Пытаемся получить флаг подчеркивания из разных типов CellData
if (cellData.canConvert<SpecificationPCBCellData>()) {
SpecificationPCBCellData cell = cellData.value<SpecificationPCBCellData>();
return cell.isUnderline;
} else if (cellData.canConvert<VedomostCellData>()) {
VedomostCellData cell = cellData.value<VedomostCellData>();
return cell.isUnderline;
} else if (cellData.canConvert<SpecificationCellData>()) {
SpecificationCellData cell = cellData.value<SpecificationCellData>();
return cell.isUnderline;
} else if (cellData.canConvert<PerechenCellData>()) {
PerechenCellData cell = cellData.value<PerechenCellData>();
return cell.isUnderline;
}
// Для других типов CellData пока используем значение по умолчанию
// (можно добавить поддержку позже, если понадобится)
}
return defaultUnderline;
}
// Вспомогательная функция для рисования ячейки с учетом поджима
// Без автоматического переноса строк - текст рисуется в одну строку
// Использует масштабирование через QTransform вместо setStretch для более плавного изменения
void PDFController::drawCellWithStretch(QPainter &painter, const QModelIndex &index, const QRectF &rect,
const QString &text, int fontSize, int defaultStretch,
const QFont &baseFont, Qt::Alignment alignment, MainController *mainController)
{
int cellStretch = getCellStretch(index, defaultStretch);
// Создаем шрифт без поджима для измерения ширины текста
QFont cellFont = createGostFont(fontSize, false, true, 100);
painter.setFont(cellFont);
QFontMetrics metrics(cellFont);
// Вычисляем коэффициент масштабирования (stretch = 100 означает масштаб 1.0)
qreal scaleX = cellStretch / 100.0;
// Вычисляем ширину текста после масштабирования
qreal textWidth = metrics.horizontalAdvance(text) * scaleX;
// Проверяем, помещается ли текст в ячейку после масштабирования
QString displayText = text;
bool isOverflow = false;
if (textWidth > rect.width()) {
// Текст не помещается даже после масштабирования - обрезаем его с многоточием
// Вычисляем максимальную ширину текста до масштабирования
qreal maxTextWidth = rect.width() / scaleX;
displayText = metrics.elidedText(text, Qt::ElideRight, maxTextWidth);
isOverflow = true;
}
// Уведомляем модель о переполнении ячейки (если передан MainController и индекс валиден)
if (mainController && index.isValid() && index.model()) {
// Определяем тип модели и вызываем соответствующий метод
// Используем dynamic_cast, так как модели наследуются от QAbstractTableModel (QObject)
QAbstractItemModel *model = const_cast<QAbstractItemModel*>(index.model());
if (model) {
// Пытаемся привести к конкретным типам моделей через dynamic_cast
PerechenTableModel *perechenModel = dynamic_cast<PerechenTableModel*>(model);
if (perechenModel) {
perechenModel->setCellOverflow(index.row(), index.column(), isOverflow);
} else {
SpecificationPCBTableModel *specPcbModel = dynamic_cast<SpecificationPCBTableModel*>(model);
if (specPcbModel) {
specPcbModel->setCellOverflow(index.row(), index.column(), isOverflow);
} else {
SpecificationTableModel *specModel = dynamic_cast<SpecificationTableModel*>(model);
if (specModel) {
specModel->setCellOverflow(index.row(), index.column(), isOverflow);
} else {
VedomostTableModel *vedomostModel = dynamic_cast<VedomostTableModel*>(model);
if (vedomostModel) {
vedomostModel->setCellOverflow(index.row(), index.column(), isOverflow);
}
}
}
}
}
}
if (cellStretch == 100) {
// Если поджим 100%, используем обычный шрифт без масштабирования
QTextOption textOption(alignment);
textOption.setWrapMode(QTextOption::NoWrap);
painter.drawText(rect, displayText, textOption);
} else {
// Используем масштабирование через QTransform для более плавного изменения ширины
// Сохраняем текущее преобразование
painter.save();
// Применяем масштабирование по оси X
// Масштабируем относительно левого края ячейки (для выравнивания влево)
// или центра (для выравнивания по центру)
qreal scaleOriginX = rect.x();
if (alignment & Qt::AlignHCenter) {
scaleOriginX = rect.x() + rect.width() / 2.0;
} else if (alignment & Qt::AlignRight) {
scaleOriginX = rect.x() + rect.width();
}
QTransform transform;
transform.translate(scaleOriginX, rect.y());
transform.scale(scaleX, 1.0);
transform.translate(-scaleOriginX, -rect.y());
painter.setTransform(transform, true);
// Создаем расширенную область для рисования текста, чтобы он не обрезался
// После применения transform с scaleX, текст будет масштабирован
// Чтобы текст после масштабирования поместился в rect, нужно рисовать его
// в области, которая после масштабирования будет равна rect
// Формула: drawRect.width() * scaleX = rect.width()
// Значит: drawRect.width() = rect.width() / scaleX
QRectF drawRect = rect;
drawRect.setWidth(rect.width() / scaleX);
// Но также нужно учесть реальную ширину текста
// Если текст уже помещается в расширенную область, используем его ширину
qreal originalTextWidth = metrics.horizontalAdvance(displayText);
if (originalTextWidth < drawRect.width()) {
// Текст помещается, но нужно учесть выравнивание
// Для выравнивания влево оставляем как есть
// Для выравнивания по центру или вправо нужно сдвинуть drawRect
if (alignment & Qt::AlignHCenter) {
drawRect.setX(rect.x() + (rect.width() / scaleX - originalTextWidth) / 2.0);
drawRect.setWidth(originalTextWidth);
} else if (alignment & Qt::AlignRight) {
drawRect.setX(rect.x() + rect.width() / scaleX - originalTextWidth);
drawRect.setWidth(originalTextWidth);
} else {
// Выравнивание влево - используем полную ширину для корректного масштабирования
// но текст будет рисоваться с левого края
}
}
// Рисуем текст без переноса в расширенной области
QTextOption textOption(alignment);
textOption.setWrapMode(QTextOption::NoWrap);
painter.drawText(drawRect, displayText, textOption);
// Восстанавливаем преобразование
painter.restore();
}
painter.setFont(baseFont);
}
QFont PDFController::createGostFont(int pointSize, bool bold, bool italic, int stretch)
{
// Загружаем TTF шрифт из QRC ресурсов
QString fontPath = ":/assets/GOST_A.TTF";
int fontId = QFontDatabase::addApplicationFont(fontPath);
if (fontId == -1) {
qDebug() << "PDFController::createGostFont: Не удалось загрузить шрифт из ресурсов, используем Arial";
QFont fallbackFont("Arial", pointSize);
fallbackFont.setBold(bold);
fallbackFont.setItalic(italic);
fallbackFont.setStretch(stretch);
return fallbackFont;
}
QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);
if (fontFamilies.isEmpty()) {
qDebug() << "PDFController::createGostFont: Не удалось получить имя семейства шрифта, используем Arial";
QFont fallbackFont("Arial", pointSize);
fallbackFont.setBold(bold);
fallbackFont.setItalic(italic);
fallbackFont.setStretch(stretch);
return fallbackFont;
}
QFont gostFont(fontFamilies.first(), pointSize);
gostFont.setBold(bold);
gostFont.setItalic(italic);
gostFont.setStretch(stretch);
return gostFont;
}
void PDFController::drawTextWithGostFont(QPainter &painter, const QRectF &rect,
const QString &text, int pointSize,
Qt::Alignment alignment)
{
QFont gostFont = createGostFont(pointSize);
painter.setFont(gostFont);
painter.drawText(rect, text, QTextOption(alignment));
}
void PDFController::drawTextWithAutoSize(QPainter &painter, const QRectF &rect,
const QString &text, int maxPointSize)
{
QFont testFont = createGostFont(maxPointSize);
QFontMetrics metrics(testFont);
// Уменьшаем размер шрифта, пока текст не поместится
int pointSize = maxPointSize;
while (pointSize > 6) {
testFont.setPointSize(pointSize);
metrics = QFontMetrics(testFont);
if (metrics.horizontalAdvance(text) <= rect.width() &&
metrics.height() <= rect.height()) {
break;
}
pointSize--;
}
painter.setFont(testFont);
painter.drawText(rect, text, QTextOption(Qt::AlignCenter));
}
void PDFController::drawTextMultiline(QPainter &painter, const QRectF &rect,
const QString &text, const QFont &font,
int maxLines)
{
painter.setFont(font);
QFontMetrics metrics(font);
// Проверяем, помещается ли текст в одну строку
if (metrics.horizontalAdvance(text) <= rect.width()) {
painter.drawText(rect, text, QTextOption(Qt::AlignCenter));
return;
}
// Разбиваем текст на слова
QStringList words = text.split(' ', Qt::SkipEmptyParts);
if (words.isEmpty()) {
painter.drawText(rect, text, QTextOption(Qt::AlignCenter));
return;
}
// Пытаемся разбить на строки
QStringList lines;
QString currentLine = words.first();
// Проверяем, помещается ли первое слово
if (metrics.horizontalAdvance(currentLine) > rect.width()) {
// Если слово не помещается, обрезаем его
currentLine = metrics.elidedText(currentLine, Qt::ElideRight, rect.width());
}
for (int i = 1; i < words.size(); ++i) {
QString testLine = currentLine + " " + words[i];
if (metrics.horizontalAdvance(testLine) <= rect.width()) {
currentLine = testLine;
} else {
lines.append(currentLine);
currentLine = words[i];
// Проверяем, помещается ли слово
if (metrics.horizontalAdvance(currentLine) > rect.width()) {
currentLine = metrics.elidedText(currentLine, Qt::ElideRight, rect.width());
}
if (lines.size() >= maxLines - 1) {
// Если достигли максимального количества строк, добавляем оставшиеся слова
for (int j = i + 1; j < words.size(); ++j) {
QString testCurrent = currentLine + " " + words[j];
if (metrics.horizontalAdvance(testCurrent) <= rect.width()) {
currentLine = testCurrent;
} else {
break;
}
}
// Обрезаем последнюю строку, если она не помещается
if (metrics.horizontalAdvance(currentLine) > rect.width()) {
currentLine = metrics.elidedText(currentLine, Qt::ElideRight, rect.width());
}
break;
}
}
}
lines.append(currentLine);
// Ограничиваем количество строк
if (lines.size() > maxLines) {
lines = lines.mid(0, maxLines);
// Обрезаем последнюю строку, если она не помещается
QString lastLine = lines.last();
if (metrics.horizontalAdvance(lastLine) > rect.width()) {
lastLine = metrics.elidedText(lastLine, Qt::ElideRight, rect.width());
lines[lines.size() - 1] = lastLine;
}
}
// Рисуем строки по центру
qreal lineHeight = metrics.height();
qreal totalHeight = lines.size() * lineHeight;
qreal startY = rect.top() + (rect.height() - totalHeight) / 2;
for (int i = 0; i < lines.size(); ++i) {
QRectF lineRect(rect.left(), startY + i * lineHeight, rect.width(), lineHeight);
painter.drawText(lineRect, lines[i], QTextOption(Qt::AlignCenter));
}
}
QString PDFController::getInscriptionValueWithProjectParams(const TitleInscriptionsModel* titleModel,
const ProjectParamTableModel* projectParamModel,
int inscriptionIndex)
{
if (!titleModel) {
return QString();
}
// Получаем значение из модели надписей
QString inscriptionValue = titleModel->getInscriptionValue(inscriptionIndex);
// Если значение пустое, возвращаем его как есть
if (inscriptionValue.isEmpty() || inscriptionValue == "-- Не выбрано --") {
return "";
}
// Если модель параметров проекта не передана, возвращаем значение надписи
if (!projectParamModel) {
return inscriptionValue;
}
// Получаем карту параметров проекта
QMap<QString, QString> projectParams = projectParamModel->getDataAsMap();
// Ищем параметр с таким же названием
if (projectParams.contains(inscriptionValue)) {
QString projectParamValue = projectParams[inscriptionValue];
// Если значение параметра проекта не пустое, возвращаем его
if (!projectParamValue.isEmpty()) {
return projectParamValue;
}
}
// Если сопоставления нет или значение параметра пустое, возвращаем значение надписи
return inscriptionValue;
}
bool PDFController::addSpecificationPcbTableRange(QPainter &painter, SpecificationPCBTableModel *specificationModel, const QRectF &tableRect, int startRow, int rowCount, MainController *mainController)
{
if (!specificationModel) {
return false;
}
// Рисуем рамку таблицы
QPen tablePen(Qt::black, 1.0);
painter.setPen(tablePen);
// Настройки шрифта для таблицы - получаем из настроек проекта
int fontSize = 12;
int fontStretch = 100;
if (mainController && mainController->specificationPCBController()) {
fontSize = mainController->specificationPCBController()->getFontSize();
fontStretch = mainController->specificationPCBController()->getFontStretch();
}
QFont tableFont = createGostFont(fontSize, false, true, fontStretch);
painter.setFont(tableFont);
// Заголовки колонок для спецификации PCB
QStringList headers = {"Формат", "Зона", "Поз.", "Обозначение", "Наименование", "Кол.", "Примечание"};
// Размеры колонок в миллиметрах (конвертируем в пиксели)
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
qreal formatWidth = 6 * mmToPixels; // Формат: 15мм
qreal zoneWidth = 6 * mmToPixels; // Зона: 15мм
qreal posWidth = 8 * mmToPixels; // Поз.: 15мм
qreal designationWidth = 70 * mmToPixels; // Обозначение: 25мм
qreal nameWidth = 63 * mmToPixels; // Наименование: 60мм
qreal qtyWidth = 10 * mmToPixels; // Кол.: 10мм
qreal noteWidth = 22 * mmToPixels; // Примечание: 30мм
qreal headerHeight = 15*mmToPixels;
qreal rowHeight = 8.035 * mmToPixels;
// Позиция начала таблицы
qreal tableStartX = tableRect.x();
// Рисуем заголовки с фиксированными размерами колонок
qreal currentX = tableStartX;
// Колонка "Формат" (15мм)
QRectF formatHeaderRect(currentX, tableRect.y(), formatWidth, headerHeight);
painter.drawRect(formatHeaderRect);
painter.save();
QTransform transform2;
transform2.translate(formatHeaderRect.left(),formatHeaderRect.bottom());
transform2.rotate(-90);
painter.setTransform(transform2);
painter.drawText(0,0,formatHeaderRect.height(),formatHeaderRect.width(), Qt::AlignCenter, headers[0]);
painter.restore();
currentX += formatWidth;
// Колонка "Зона" (15мм)
QRectF zoneHeaderRect(currentX, tableRect.y(), zoneWidth, headerHeight);
painter.drawRect(zoneHeaderRect);
painter.save();
QTransform transform1;
transform1.translate(zoneHeaderRect.left(),zoneHeaderRect.bottom());
transform1.rotate(-90);
painter.setTransform(transform1);
painter.drawText(0,0,zoneHeaderRect.height(),zoneHeaderRect.width(), Qt::AlignCenter, headers[1]);
painter.restore();
currentX += zoneWidth;
// Колонка "Поз." (15мм)
QRectF posHeaderRect(currentX, tableRect.y(), posWidth, headerHeight);
painter.drawRect(posHeaderRect);
painter.save();
QTransform transform3;
transform3.translate(posHeaderRect.left(),posHeaderRect.bottom());
transform3.rotate(-90);
painter.setTransform(transform3);
painter.drawRect(0,0,posHeaderRect.height(),posHeaderRect.width());
painter.drawText(0,0,posHeaderRect.height(),posHeaderRect.width(),Qt::AlignCenter ,headers[2]);
painter.restore();
currentX += posWidth;
// Колонка "Обозначение" (25мм)
QRectF designationHeaderRect(currentX, tableRect.y(), designationWidth, headerHeight);
painter.drawRect(designationHeaderRect);
painter.drawText(designationHeaderRect, headers[3], QTextOption(Qt::AlignCenter));
currentX += designationWidth;
// Колонка "Наименование" (60мм)
QRectF nameHeaderRect(currentX, tableRect.y(), nameWidth, headerHeight);
painter.drawRect(nameHeaderRect);
painter.drawText(nameHeaderRect, headers[4], QTextOption(Qt::AlignCenter));
currentX += nameWidth;
// Колонка "Кол." (10мм)
QRectF qtyHeaderRect(currentX, tableRect.y(), qtyWidth, headerHeight);
painter.drawRect(qtyHeaderRect);
painter.drawText(qtyHeaderRect, headers[5], QTextOption(Qt::AlignCenter));
currentX += qtyWidth;
// Колонка "Примечание" (30мм)
QRectF noteHeaderRect(currentX, tableRect.y(), noteWidth, headerHeight);
painter.drawRect(noteHeaderRect);
painter.drawText(noteHeaderRect, headers[6], QTextOption(Qt::AlignCenter));
// Рисуем данные с указанным диапазоном строк
int totalRows = specificationModel->rowCount();
int endRow = qMin(startRow + rowCount, totalRows);
for (int displayRow = 0; displayRow < rowCount; ++displayRow) {
int row = startRow + displayRow; // Номер строки в модели
currentX = tableStartX;
// Колонка "Формат" (15мм)
QRectF formatCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, formatWidth, rowHeight);
painter.drawRect(formatCellRect);
// Если это реальная строка данных (не пустая)
if (row < totalRows) {
QModelIndex formatIndex = specificationModel->index(row, 0);
if (formatIndex.isValid()) {
QString cellText = specificationModel->data(formatIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, formatIndex, formatCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += formatWidth;
// Колонка "Зона" (15мм)
QRectF zoneCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, zoneWidth, rowHeight);
painter.drawRect(zoneCellRect);
if (row < totalRows) {
QModelIndex zoneIndex = specificationModel->index(row, 1);
if (zoneIndex.isValid()) {
QString cellText = specificationModel->data(zoneIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, zoneIndex, zoneCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += zoneWidth;
// Колонка "Поз." (15мм)
QRectF posCellRect(currentX, tableRect.y() + (displayRow ) * rowHeight+headerHeight, posWidth, rowHeight);
painter.drawRect(posCellRect);
if (row < totalRows) {
QModelIndex posIndex = specificationModel->index(row, 2);
if (posIndex.isValid()) {
QString cellText = specificationModel->data(posIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, posIndex, posCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += posWidth;
// Колонка "Обозначение" (25мм)
QRectF designationCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, designationWidth, rowHeight);
painter.drawRect(designationCellRect);
if (row < totalRows) {
QModelIndex designationIndex = specificationModel->index(row, 3);
if (designationIndex.isValid()) {
QString cellText = " "+ specificationModel->data(designationIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, designationIndex, designationCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignLeft|Qt::AlignVCenter, mainController);
}
}
currentX += designationWidth;
// Колонка "Наименование" (60мм)
QRectF nameCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, nameWidth, rowHeight);
painter.drawRect(nameCellRect);
if (row < totalRows) {
QModelIndex nameIndex = specificationModel->index(row, 4);
if (nameIndex.isValid()) {
QString cellText = specificationModel->data(nameIndex, Qt::DisplayRole).toString();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(nameIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
// Проверяем, является ли ячейка заголовком из SpecificationPCBCellData
bool isHeader = false;
bool shouldUnderline = false;
QVariant cellData = specificationModel->data(nameIndex, Qt::UserRole);
if (cellData.isValid() && cellData.canConvert<SpecificationPCBCellData>()) {
SpecificationPCBCellData cell = cellData.value<SpecificationPCBCellData>();
isHeader = cell.isHeader;
shouldUnderline = cell.isUnderline;
}
// Если это заголовок, применяем специальное форматирование
if (isHeader) {
// Сохраняем текущие настройки
QPen originalPen = painter.pen();
QFont originalFont = painter.font();
// Устанавливаем шрифт с поджимом
painter.setFont(cellFont);
// Рисуем текст по центру без переноса строк
QTextOption headerTextOption(Qt::AlignCenter);
headerTextOption.setWrapMode(QTextOption::NoWrap); // Явно отключаем перенос строк
painter.drawText(nameCellRect, cellText.trimmed(), headerTextOption);
// Проверяем, нужно ли рисовать подчеркивание (уже получено из cellData выше)
if (shouldUnderline) {
// Рисуем подчеркивание вручную с настраиваемым расстоянием
QFontMetrics metrics(painter.font());
QRectF textRect = metrics.boundingRect(cellText.trimmed());
// Вычисляем позицию текста по центру
qreal textX = nameCellRect.x() + (nameCellRect.width() - textRect.width()) / 2;
qreal textY = nameCellRect.y() + (nameCellRect.height() + textRect.height()) / 2;
// Настраиваемое расстояние подчеркивания от текста (в пикселях)
qreal underlineOffset = 2.0; // Можно изменить это значение
// Рисуем линию подчеркивания
QPen underlinePen(Qt::black, 1.0);
painter.setPen(underlinePen);
painter.drawLine(
textX,
textY + underlineOffset,
textX + textRect.width(),
textY + underlineOffset
);
}
// Восстанавливаем оригинальные настройки
painter.setFont(originalFont);
painter.setPen(originalPen);
} else {
// Обычное форматирование (по левому краю) - используем drawCellWithStretch без переноса
drawCellWithStretch(painter, nameIndex, nameCellRect.adjusted(2*mmToPixels,0,0,0), cellText, fontSize, fontStretch, tableFont, Qt::AlignLeft|Qt::AlignVCenter, mainController);
}
}
}
currentX += nameWidth;
// Колонка "Кол." (10мм)
QRectF qtyCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, qtyWidth, rowHeight);
painter.drawRect(qtyCellRect);
if (row < totalRows) {
QModelIndex qtyIndex = specificationModel->index(row, 5);
if (qtyIndex.isValid()) {
QString cellText = specificationModel->data(qtyIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, qtyIndex, qtyCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += qtyWidth;
// Колонка "Примечание" (30мм)
QRectF noteCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, noteWidth, rowHeight);
painter.drawRect(noteCellRect);
if (row < totalRows) {
QModelIndex noteIndex = specificationModel->index(row, 6);
if (noteIndex.isValid()) {
QString cellText = specificationModel->data(noteIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, noteIndex, noteCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
}
return true;
}
bool PDFController::addSpecificationTableRange(QPainter &painter, SpecificationTableModel *specificationModel, const QRectF &tableRect, int startRow, int rowCount, MainController *mainController)
{
if (!specificationModel) {
return false;
}
// Рисуем рамку таблицы
QPen tablePen(Qt::black, 1.0);
painter.setPen(tablePen);
// Настройки шрифта для таблицы - получаем из настроек проекта
int fontSize = 12;
int fontStretch = 100;
if (mainController && mainController->specificationController()) {
fontSize = mainController->specificationController()->getFontSize();
fontStretch = mainController->specificationController()->getFontStretch();
}
QFont tableFont = createGostFont(fontSize, false, true, fontStretch);
painter.setFont(tableFont);
// Заголовки колонок для спецификации материалов
QStringList headers = {"Формат", "Зона", "Поз.", "Обозначение", "Наименование", "Кол.", "Примечание"};
// Размеры колонок в миллиметрах (конвертируем в пиксели)
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
qreal formatWidth = 6 * mmToPixels; // Формат: 15мм
qreal zoneWidth = 6 * mmToPixels; // Зона: 15мм
qreal posWidth = 8 * mmToPixels; // Поз.: 15мм
qreal designationWidth = 70 * mmToPixels; // Обозначение: 25мм
qreal nameWidth = 63 * mmToPixels; // Наименование: 60мм
qreal qtyWidth = 10 * mmToPixels; // Кол.: 10мм
qreal noteWidth = 22 * mmToPixels; // Примечание: 30мм
qreal headerHeight = 15*mmToPixels;
qreal rowHeight = 8.035 * mmToPixels;
// Позиция начала таблицы
qreal tableStartX = tableRect.x();
// Рисуем заголовки с фиксированными размерами колонок
qreal currentX = tableStartX;
// Колонка "Формат" (15мм)
QRectF formatHeaderRect(currentX, tableRect.y(), formatWidth, headerHeight);
painter.drawRect(formatHeaderRect);
painter.save();
QTransform transform2;
transform2.translate(formatHeaderRect.left(),formatHeaderRect.bottom());
transform2.rotate(-90);
painter.setTransform(transform2);
painter.drawText(0,0,formatHeaderRect.height(),formatHeaderRect.width(), Qt::AlignCenter, headers[0]);
painter.restore();
currentX += formatWidth;
// Колонка "Зона" (15мм)
QRectF zoneHeaderRect(currentX, tableRect.y(), zoneWidth, headerHeight);
painter.drawRect(zoneHeaderRect);
painter.save();
QTransform transform1;
transform1.translate(zoneHeaderRect.left(),zoneHeaderRect.bottom());
transform1.rotate(-90);
painter.setTransform(transform1);
painter.drawText(0,0,zoneHeaderRect.height(),zoneHeaderRect.width(), Qt::AlignCenter, headers[1]);
painter.restore();
currentX += zoneWidth;
// Колонка "Поз." (15мм)
QRectF posHeaderRect(currentX, tableRect.y(), posWidth, headerHeight);
painter.drawRect(posHeaderRect);
painter.save();
QTransform transform3;
transform3.translate(posHeaderRect.left(),posHeaderRect.bottom());
transform3.rotate(-90);
painter.setTransform(transform3);
painter.drawRect(0,0,posHeaderRect.height(),posHeaderRect.width());
painter.drawText(0,0,posHeaderRect.height(),posHeaderRect.width(),Qt::AlignCenter ,headers[2]);
painter.restore();
currentX += posWidth;
// Колонка "Обозначение" (25мм)
QRectF designationHeaderRect(currentX, tableRect.y(), designationWidth, headerHeight);
painter.drawRect(designationHeaderRect);
painter.drawText(designationHeaderRect, headers[3], QTextOption(Qt::AlignCenter));
currentX += designationWidth;
// Колонка "Наименование" (60мм)
QRectF nameHeaderRect(currentX, tableRect.y(), nameWidth, headerHeight);
painter.drawRect(nameHeaderRect);
painter.drawText(nameHeaderRect, headers[4], QTextOption(Qt::AlignCenter));
currentX += nameWidth;
// Колонка "Кол." (10мм)
QRectF qtyHeaderRect(currentX, tableRect.y(), qtyWidth, headerHeight);
painter.drawRect(qtyHeaderRect);
painter.drawText(qtyHeaderRect, headers[5], QTextOption(Qt::AlignCenter));
currentX += qtyWidth;
// Колонка "Примечание" (30мм)
QRectF noteHeaderRect(currentX, tableRect.y(), noteWidth, headerHeight);
painter.drawRect(noteHeaderRect);
painter.drawText(noteHeaderRect, headers[6], QTextOption(Qt::AlignCenter));
// Рисуем данные с указанным диапазоном строк
int totalRows = specificationModel->rowCount();
int endRow = qMin(startRow + rowCount, totalRows);
for (int displayRow = 0; displayRow < rowCount; ++displayRow) {
int row = startRow + displayRow; // Номер строки в модели
currentX = tableStartX;
// Колонка "Формат" (15мм)
QRectF formatCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, formatWidth, rowHeight);
painter.drawRect(formatCellRect);
// Если это реальная строка данных (не пустая)
if (row < totalRows) {
QModelIndex formatIndex = specificationModel->index(row, 0);
if (formatIndex.isValid()) {
QString cellText = specificationModel->data(formatIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, formatIndex, formatCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += formatWidth;
// Колонка "Зона" (15мм)
QRectF zoneCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, zoneWidth, rowHeight);
painter.drawRect(zoneCellRect);
if (row < totalRows) {
QModelIndex zoneIndex = specificationModel->index(row, 1);
if (zoneIndex.isValid()) {
QString cellText = specificationModel->data(zoneIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, zoneIndex, zoneCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += zoneWidth;
// Колонка "Поз." (15мм)
QRectF posCellRect(currentX, tableRect.y() + (displayRow ) * rowHeight+headerHeight, posWidth, rowHeight);
painter.drawRect(posCellRect);
if (row < totalRows) {
QModelIndex posIndex = specificationModel->index(row, 2);
if (posIndex.isValid()) {
QString cellText = specificationModel->data(posIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, posIndex, posCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += posWidth;
// Колонка "Обозначение" (25мм)
QRectF designationCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, designationWidth, rowHeight);
painter.drawRect(designationCellRect);
if (row < totalRows) {
QModelIndex designationIndex = specificationModel->index(row, 3);
if (designationIndex.isValid()) {
QString cellText = " " + specificationModel->data(designationIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, designationIndex, designationCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignLeft|Qt::AlignVCenter, mainController);
}
}
currentX += designationWidth;
// Колонка "Наименование" (60мм)
QRectF nameCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, nameWidth, rowHeight);
painter.drawRect(nameCellRect);
if (row < totalRows) {
QModelIndex nameIndex = specificationModel->index(row, 4);
if (nameIndex.isValid()) {
QString cellText = specificationModel->data(nameIndex, Qt::DisplayRole).toString();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(nameIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
// Проверяем, является ли ячейка заголовком из SpecificationCellData
bool isHeader = false;
bool shouldUnderline = false;
QVariant cellData = specificationModel->data(nameIndex, Qt::UserRole);
if (cellData.isValid() && cellData.canConvert<SpecificationCellData>()) {
SpecificationCellData cell = cellData.value<SpecificationCellData>();
isHeader = cell.isHeader;
shouldUnderline = cell.isUnderline;
}
// Если это заголовок, применяем специальное форматирование
if (isHeader) {
// Сохраняем текущие настройки
QPen originalPen = painter.pen();
QFont originalFont = painter.font();
// Устанавливаем шрифт с поджимом
painter.setFont(cellFont);
// Рисуем текст по центру без переноса строк
QTextOption headerTextOption(Qt::AlignCenter);
headerTextOption.setWrapMode(QTextOption::NoWrap); // Явно отключаем перенос строк
painter.drawText(nameCellRect, cellText.trimmed(), headerTextOption);
// Проверяем, нужно ли рисовать подчеркивание (уже получено из cellData выше)
if (shouldUnderline) {
// Рисуем подчеркивание вручную с настраиваемым расстоянием
QFontMetrics metrics(painter.font());
QRectF textRect = metrics.boundingRect(cellText.trimmed());
// Вычисляем позицию текста по центру
qreal textX = nameCellRect.x() + (nameCellRect.width() - textRect.width()) / 2;
qreal textY = nameCellRect.y() + (nameCellRect.height() + textRect.height()) / 2;
// Настраиваемое расстояние подчеркивания от текста (в пикселях)
qreal underlineOffset = 2.0; // Можно изменить это значение
// Рисуем линию подчеркивания
QPen underlinePen(Qt::black, 1.0);
painter.setPen(underlinePen);
painter.drawLine(
textX,
textY + underlineOffset,
textX + textRect.width(),
textY + underlineOffset
);
}
// Восстанавливаем оригинальные настройки
painter.setFont(originalFont);
painter.setPen(originalPen);
} else {
// Обычное форматирование (по левому краю) - используем drawCellWithStretch без переноса
drawCellWithStretch(painter, nameIndex, nameCellRect.adjusted(2*mmToPixels,0,0,0), cellText, fontSize, fontStretch, tableFont, Qt::AlignLeft|Qt::AlignVCenter, mainController);
}
}
}
currentX += nameWidth;
// Колонка "Кол." (10мм)
QRectF qtyCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, qtyWidth, rowHeight);
painter.drawRect(qtyCellRect);
if (row < totalRows) {
QModelIndex qtyIndex = specificationModel->index(row, 5);
if (qtyIndex.isValid()) {
QString cellText = specificationModel->data(qtyIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, qtyIndex, qtyCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignCenter, mainController);
}
}
currentX += qtyWidth;
// Колонка "Примечание" (30мм)
QRectF noteCellRect(currentX, tableRect.y() + (displayRow) * rowHeight+headerHeight, noteWidth, rowHeight);
painter.drawRect(noteCellRect);
if (row < totalRows) {
QModelIndex noteIndex = specificationModel->index(row, 6);
if (noteIndex.isValid()) {
QString cellText = specificationModel->data(noteIndex, Qt::DisplayRole).toString();
drawCellWithStretch(painter, noteIndex, noteCellRect, cellText, fontSize, fontStretch, tableFont, Qt::AlignLeft|Qt::AlignVCenter, mainController);
}
}
}
return true;
}
bool PDFController::addVedomostTableRange(QPainter &painter, VedomostTableModel *vedomostModel, const QRectF &tableRect, int startRow, int rowCount, MainController *mainController)
{
if (!vedomostModel) {
return false;
}
// Рисуем рамку таблицы
QPen tablePen(Qt::black, 1.0);
painter.setPen(tablePen);
// Настройки шрифта для таблицы - получаем из настроек проекта
int fontSize = 12;
int fontStretch = 100;
if (mainController && mainController->vedomostController()) {
fontSize = mainController->vedomostController()->getFontSize();
fontStretch = mainController->vedomostController()->getFontStretch();
}
QFont tableFont = createGostFont(fontSize, false, true, fontStretch);
painter.setFont(tableFont);
// Заголовки колонок для ведомости покупных изделий
QStringList headers = {"№ строки","Наименование", "Код продукции", "Обозначение документа на поставку", "Поставщик",
"Куда входит (обозначение)", "Количество на изделие", "Количество в комплекте",
"Количество на регулир", "Количество всего", "Примечание"};
// Размеры колонок в миллиметрах (конвертируем в пиксели) для А5 формата
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
qreal nnRowWidth = 7*mmToPixels;
qreal nameWidth = 60 * mmToPixels; // Наименование
qreal productCodeWidth = 45 * mmToPixels; // Код продукции
qreal docCodeWidth = 70 * mmToPixels; // Обозначение документа на поставку
qreal supplierWidth = 55 * mmToPixels; // Поставщик
qreal whereUsedWidth = 70 * mmToPixels; // Куда входит (обозначение)
qreal qtyPerItemWidth = 16 * mmToPixels; // Количество на изделие
qreal qtyInSetWidth = 16 * mmToPixels; // Количество в комплекте
qreal qtyForRegWidth = 16 * mmToPixels; // Количество на регулир
qreal totalQtyWidth = 16 * mmToPixels; // Количество всего
qreal noteWidth = 24 * mmToPixels; // Примечание
qreal headerHeight = 27 * mmToPixels;
qreal rowHeight = 8.17 * mmToPixels;
// Позиция начала таблицы
qreal tableStartX = tableRect.x();
// Рисуем заголовки с фиксированными размерами колонок
qreal currentX = tableStartX;
//qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
qreal topHeaderHeight = 9 * mmToPixels; // Высота верхней части заголовка
qreal bottomHeaderHeight = 18 * mmToPixels; // Высота нижней части заголовка
// Рисуем верхнюю строку заголовков (первые 6 колонок + объединенная "Количество")
for (int i = 0; i < 6; ++i) {
qreal colWidth = 0;
switch (i) {
case 0: colWidth = nnRowWidth; break;
case 1: colWidth = nameWidth; break;
case 2: colWidth = productCodeWidth; break;
case 3: colWidth = docCodeWidth; break;
case 4: colWidth = supplierWidth; break;
case 5: colWidth = whereUsedWidth; break;
}
QRectF headerRect(currentX, tableRect.y(), colWidth, headerHeight);
painter.drawRect(headerRect);
// Для длинных заголовков используем поворот текста
if (i ==0) { // "Обозначение документа на поставку" и "Куда входит (обозначение)"
painter.save();
QTransform transform;
transform.translate(headerRect.left(), headerRect.bottom());
transform.rotate(-90);
painter.setTransform(transform);
painter.drawText(0, 0, headerRect.height(), headerRect.width(), Qt::AlignCenter, headers[i]);
painter.restore();
} else {
painter.drawText(headerRect, headers[i], QTextOption(Qt::AlignCenter));
}
currentX += colWidth;
}
// Рисуем объединенную ячейку "Количество" (4 колонки)
qreal quantityTotalWidth = qtyPerItemWidth + qtyInSetWidth + qtyForRegWidth + totalQtyWidth;
QRectF quantityHeaderRect(currentX, tableRect.y(), quantityTotalWidth, topHeaderHeight);
painter.drawRect(quantityHeaderRect);
painter.drawText(quantityHeaderRect, "Количество", QTextOption(Qt::AlignCenter));
// Рисуем нижнюю строку заголовков для колонок количества
qreal bottomHeaderY = tableRect.y() + topHeaderHeight;
qreal bottomCurrentX = currentX;
QStringList quantityHeaders = {"на из-делии", "в ком-плекте", "на ре-гулир.", "всего"};
qreal quantityWidths[] = {qtyPerItemWidth, qtyInSetWidth, qtyForRegWidth, totalQtyWidth};
for (int i = 0; i < 4; ++i) {
QRectF bottomHeaderRect(bottomCurrentX, bottomHeaderY, quantityWidths[i], bottomHeaderHeight);
painter.drawRect(bottomHeaderRect);
painter.drawText(bottomHeaderRect, quantityHeaders[i], QTextOption(Qt::AlignCenter));
bottomCurrentX += quantityWidths[i];
}
// Рисуем последнюю колонку "Примечание"
QRectF noteHeaderRect(bottomCurrentX, tableRect.y(), noteWidth, headerHeight);
painter.drawRect(noteHeaderRect);
painter.drawText(noteHeaderRect, headers[10], QTextOption(Qt::AlignCenter));
// Рисуем данные с указанным диапазоном строк
int totalRows = vedomostModel->rowCount();
int endRow = qMin(startRow + rowCount, totalRows);
for (int displayRow = 0; displayRow < rowCount; ++displayRow) {
int row = startRow + displayRow; // Номер строки в модели
currentX = tableStartX;
// Рисуем ячейки для каждой колонки
for (int col = 0; col < 11; ++col) {
qreal colWidth = 0;
switch (col) {
case 0: colWidth = nnRowWidth; break; // № строки
case 1: colWidth = nameWidth; break; // Наименование
case 2: colWidth = productCodeWidth; break; // Код продукции
case 3: colWidth = docCodeWidth; break; // Обозначение документа на поставку
case 4: colWidth = supplierWidth; break; // Поставщик
case 5: colWidth = whereUsedWidth; break; // Куда входит (обозначение)
case 6: colWidth = qtyPerItemWidth; break; // Количество на изделие
case 7: colWidth = qtyInSetWidth; break; // Количество в комплекте
case 8: colWidth = qtyForRegWidth; break; // Количество на регулир
case 9: colWidth = totalQtyWidth; break; // Количество всего
case 10: colWidth = noteWidth; break; // Примечание
}
// Учитываем новую высоту заголовка (верхняя + нижняя части)
qreal totalHeaderHeight = topHeaderHeight + bottomHeaderHeight;
QRectF cellRect(currentX, tableRect.y() + (displayRow) * rowHeight + totalHeaderHeight, colWidth, rowHeight);
painter.drawRect(cellRect);
// Обрабатываем каждую колонку отдельно
if (col == 0) {
// Первая колонка - номер строки (начиная с 1)
painter.drawText(cellRect, QString::number(row + 1), QTextOption(Qt::AlignCenter));
} else if (row < totalRows) {
// Остальные колонки - данные из модели (смещение на -1, так как первая колонка не входит в модель)
QModelIndex cellIndex = vedomostModel->index(row, col - 1);
if (cellIndex.isValid()) {
QString cellText = " "+ vedomostModel->data(cellIndex, Qt::DisplayRole).toString();
// Проверяем, является ли ячейка заголовком (для колонки "Наименование" - col == 1)
bool isHeader = false;
bool shouldUnderline = false;
if (col == 1) { // Колонка "Наименование"
QVariant cellData = vedomostModel->data(cellIndex, Qt::UserRole);
if (cellData.isValid() && cellData.canConvert<VedomostCellData>()) {
VedomostCellData cell = cellData.value<VedomostCellData>();
isHeader = cell.isHeader;
shouldUnderline = cell.isUnderline;
}
}
if (isHeader) {
// Если это заголовок, применяем специальное форматирование
// Сохраняем текущие настройки
QPen originalPen = painter.pen();
QFont originalFont = painter.font();
// Получаем поджим для этой ячейки
int cellStretch = getCellStretch(cellIndex, fontStretch);
QFont cellFont = createGostFont(fontSize, false, true, cellStretch);
painter.setFont(cellFont);
// Рисуем текст по центру без переноса строк
QTextOption headerTextOption(Qt::AlignCenter);
headerTextOption.setWrapMode(QTextOption::NoWrap);
painter.drawText(cellRect, cellText.trimmed(), headerTextOption);
// Проверяем, нужно ли рисовать подчеркивание
if (shouldUnderline) {
// Рисуем подчеркивание вручную с настраиваемым расстоянием
QFontMetrics metrics(painter.font());
QRectF textRect = metrics.boundingRect(cellText.trimmed());
// Вычисляем позицию текста по центру
qreal textX = cellRect.x() + (cellRect.width() - textRect.width()) / 2;
qreal textY = cellRect.y() + (cellRect.height() + textRect.height()) / 2;
// Настраиваемое расстояние подчеркивания от текста (в пикселях)
qreal underlineOffset = 2.0;
// Рисуем линию подчеркивания
QPen underlinePen(Qt::black, 1.0);
painter.setPen(underlinePen);
painter.drawLine(
textX,
textY + underlineOffset,
textX + textRect.width(),
textY + underlineOffset
);
}
// Восстанавливаем оригинальные настройки
painter.setFont(originalFont);
painter.setPen(originalPen);
} else {
// Обычное форматирование
Qt::Alignment alignment = (col==6||col==7||col==8||col==9) ? Qt::AlignCenter : (Qt::AlignLeft|Qt::AlignVCenter);
drawCellWithStretch(painter, cellIndex, cellRect, cellText, fontSize, fontStretch, tableFont, alignment, mainController);
}
}
}
currentX += colWidth;
}
}
return true;
}
// Новые методы для предварительного просмотра
QList<PageInfo> PDFController::getPerechenPagesInfo(MainController *mainController)
{
QList<PageInfo> pagesInfo;
if (!mainController) {
qDebug() << "PDFController::getPerechenPagesInfo: MainController не передан";
return pagesInfo;
}
PerechenTableModel *perechenModel = mainController->perechenTableModel();
if (!perechenModel) {
qDebug() << "PDFController::getPerechenPagesInfo: Модель перечня элементов недоступна";
return pagesInfo;
}
qDebug() << "PDFController::getPerechenPagesInfo: Количество строк в модели:" << perechenModel->rowCount();
// Константы для количества строк на страницах
const int rowsOnFirstPage = 27; // На первой странице 27 строк
const int rowsOnOtherPages = 33; // На последующих страницах 33 строк
int totalRows = perechenModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
qDebug() << "PDFController::getPerechenPagesInfo: Всего строк:" << totalRows << "всего страниц:" << totalPages;
// Создаем информацию о каждой странице
while (currentRow < totalRows) {
PageInfo pageInfo;
pageInfo.pageNumber = pageNumber;
pageInfo.totalPages = totalPages;
pageInfo.isFirstPage = (pageNumber == 1);
pagesInfo.append(pageInfo);
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
qDebug() << "PDFController::getPerechenPagesInfo: Создана страница" << pageNumber - 1 << "строки" << currentRow - rowsOnThisPage << "-" << currentRow - 1;
}
qDebug() << "PDFController::getPerechenPagesInfo: Создано страниц:" << pagesInfo.size();
return pagesInfo;
}
QList<PageInfo> PDFController::getSpecificationPcbPagesInfo(MainController *mainController)
{
QList<PageInfo> pagesInfo;
if (!mainController) {
return pagesInfo;
}
SpecificationPCBTableModel *specificationModel = mainController->specificationPCBTableModel();
if (!specificationModel) {
return pagesInfo;
}
// Константы для количества строк на страницах
const int rowsOnFirstPage = 26; // На первой странице 26 строк
const int rowsOnOtherPages = 32; // На последующих страницах 32 строки
int totalRows = specificationModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
// Создаем информацию о каждой странице
while (currentRow < totalRows) {
PageInfo pageInfo;
pageInfo.pageNumber = pageNumber;
pageInfo.totalPages = totalPages;
pageInfo.isFirstPage = (pageNumber == 1);
pagesInfo.append(pageInfo);
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
}
return pagesInfo;
}
QList<PageInfo> PDFController::getSpecificationPagesInfo(MainController *mainController)
{
QList<PageInfo> pagesInfo;
if (!mainController) {
return pagesInfo;
}
SpecificationTableModel *specificationModel = mainController->specificationTableModel();
if (!specificationModel) {
return pagesInfo;
}
// Константы для количества строк на страницах
const int rowsOnFirstPage = 26; // На первой странице 26 строк
const int rowsOnOtherPages = 32; // На последующих страницах 32 строки
int totalRows = specificationModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
// Создаем информацию о каждой странице
while (currentRow < totalRows) {
PageInfo pageInfo;
pageInfo.pageNumber = pageNumber;
pageInfo.totalPages = totalPages;
pageInfo.isFirstPage = (pageNumber == 1);
pagesInfo.append(pageInfo);
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
}
return pagesInfo;
}
bool PDFController::drawPerechenPage(QPainter &painter, const PageInfo &pageInfo, MainController *mainController)
{
if (!mainController) {
return false;
}
PerechenTableModel *perechenModel = mainController->perechenTableModel();
if (!perechenModel) {
return false;
}
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
return false;
}
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
return false;
}
// Получаем размеры страницы из painter
QRectF pageRect = painter.viewport();
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах
const int rowsOnFirstPage = 27;
const int rowsOnOtherPages = 33;
int totalRows = perechenModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Находим нужную страницу
while (pageNumber < pageInfo.pageNumber) {
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
}
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageInfo.isFirstPage) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем рамку ГОСТ в зависимости от номера страницы
if (pageInfo.isFirstPage) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages,1);
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages,1);
}
// Вычисляем область для таблицы
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу с указанным диапазоном строк
addPerechenTableRange(painter, perechenModel, tableRect, currentRow, rowsOnThisPage, mainController);
return true;
}
bool PDFController::drawSpecificationPcbPage(QPainter &painter, const PageInfo &pageInfo, MainController *mainController)
{
if (!mainController) {
return false;
}
SpecificationPCBTableModel *specificationModel = mainController->specificationPCBTableModel();
if (!specificationModel) {
return false;
}
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
return false;
}
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
return false;
}
// Получаем размеры страницы из painter
QRectF pageRect = painter.viewport();
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах
const int rowsOnFirstPage = 26;
const int rowsOnOtherPages = 32;
int totalRows = specificationModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Находим нужную страницу
while (pageNumber < pageInfo.pageNumber) {
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
}
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageInfo.isFirstPage) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем рамку ГОСТ в зависимости от номера страницы
if (pageInfo.isFirstPage) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages,2);
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages,2);
}
// Вычисляем область для таблицы
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу спецификации с указанным диапазоном строк
addSpecificationPcbTableRange(painter, specificationModel, tableRect, currentRow, rowsOnThisPage, mainController);
return true;
}
bool PDFController::drawSpecificationPage(QPainter &painter, const PageInfo &pageInfo, MainController *mainController)
{
if (!mainController) {
return false;
}
SpecificationTableModel *specificationModel = mainController->specificationTableModel();
if (!specificationModel) {
return false;
}
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
return false;
}
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
return false;
}
// Получаем размеры страницы из painter
QRectF pageRect = painter.viewport();
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах
const int rowsOnFirstPage = 26;
const int rowsOnOtherPages = 32;
int totalRows = specificationModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Находим нужную страницу
while (pageNumber < pageInfo.pageNumber) {
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
}
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageInfo.isFirstPage) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем рамку ГОСТ в зависимости от номера страницы
if (pageInfo.isFirstPage) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages,3);
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages,3);
}
// Вычисляем область для таблицы
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу спецификации с указанным диапазоном строк
addSpecificationTableRange(painter, specificationModel, tableRect, currentRow, rowsOnThisPage, mainController);
return true;
}
QList<PageInfo> PDFController::getVedomostPagesInfo(MainController *mainController)
{
QList<PageInfo> pagesInfo;
if (!mainController) {
qDebug() << "PDFController::getVedomostPagesInfo: MainController не передан";
return pagesInfo;
}
VedomostTableModel *vedomostModel = mainController->vedomostTableModel();
if (!vedomostModel) {
qDebug() << "PDFController::getVedomostPagesInfo: Модель ведомости покупных изделий недоступна";
return pagesInfo;
}
qDebug() << "PDFController::getVedomostPagesInfo: Количество строк в модели:" << vedomostModel->rowCount();
// Константы для количества строк на страницах (должны совпадать с экспортом)
const int rowsOnFirstPage = 24; // На первой странице 24 строки (как в экспорте)
const int rowsOnOtherPages = 30; // На последующих страницах 30 строк (как в экспорте)
int totalRows = vedomostModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Вычисляем общее количество страниц
int totalPages = 1;
int tempRow = 0;
while (tempRow < totalRows) {
int rowsOnThisPage = (totalPages == 1) ? rowsOnFirstPage : rowsOnOtherPages;
tempRow += rowsOnThisPage;
if (tempRow < totalRows) {
totalPages++;
}
}
qDebug() << "PDFController::getVedomostPagesInfo: Всего строк:" << totalRows << "всего страниц:" << totalPages;
// Создаем информацию о каждой странице
while (currentRow < totalRows) {
PageInfo pageInfo;
pageInfo.pageNumber = pageNumber;
pageInfo.totalPages = totalPages;
pageInfo.isFirstPage = (pageNumber == 1);
pagesInfo.append(pageInfo);
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
qDebug() << "PDFController::getVedomostPagesInfo: Создана страница" << pageNumber - 1 << "строки" << currentRow - rowsOnThisPage << "-" << currentRow - 1;
}
qDebug() << "PDFController::getVedomostPagesInfo: Создано страниц:" << pagesInfo.size();
return pagesInfo;
}
bool PDFController::drawVedomostPage(QPainter &painter, const PageInfo &pageInfo, MainController *mainController)
{
if (!mainController) {
return false;
}
VedomostTableModel *vedomostModel = mainController->vedomostTableModel();
if (!vedomostModel) {
return false;
}
TitleInscriptionsModel *titleModel = mainController->titleInscriptionsModel();
if (!titleModel) {
return false;
}
ProjectParamTableModel *projectParamModel = mainController->projectParamTableModel();
if (!projectParamModel) {
return false;
}
// Получаем размеры страницы из painter
QRectF pageRect = painter.viewport();
// Конвертируем миллиметры в пиксели
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
// Константы для количества строк на страницах (должны совпадать с экспортом)
const int rowsOnFirstPage = 24; // На первой странице 24 строки (как в экспорте)
const int rowsOnOtherPages = 30; // На последующих страницах 30 строк (как в экспорте)
int totalRows = vedomostModel->rowCount();
int currentRow = 0;
int pageNumber = 1;
// Находим нужную страницу
while (pageNumber < pageInfo.pageNumber) {
int rowsOnThisPage = (pageNumber == 1) ? rowsOnFirstPage : rowsOnOtherPages;
currentRow += rowsOnThisPage;
pageNumber++;
}
// Определяем количество строк для текущей страницы
int rowsOnThisPage = (pageInfo.isFirstPage) ? rowsOnFirstPage : rowsOnOtherPages;
// Проверяем, является ли это последней страницей
bool isLastPage = (currentRow + rowsOnThisPage >= totalRows);
// Если это последняя страница, добавляем пустые строки до конца страницы
if (isLastPage) {
int remainingRows = totalRows - currentRow;
int emptyRowsToAdd = rowsOnThisPage - remainingRows;
rowsOnThisPage = remainingRows + emptyRowsToAdd;
}
// Добавляем рамку ГОСТ (используем те же методы, что и в экспорте)
if (pageInfo.isFirstPage) {
addGostFrameA4FirstPage(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages, 4);
} else {
addGostFrameA4(painter, pageRect, titleModel, projectParamModel, pageInfo.pageNumber, pageInfo.totalPages, 4);
}
// Вычисляем область для таблицы (используем те же отступы, что и в экспорте)
QRectF tableRect = pageRect.adjusted(20*mmToPixels, 5*mmToPixels, -5*mmToPixels, -5*mmToPixels);
// Добавляем таблицу ведомости с указанным диапазоном строк
addVedomostTableRange(painter, vedomostModel, tableRect, currentRow, rowsOnThisPage, mainController);
return true;
}