3393 lines
182 KiB
C++
3393 lines
182 KiB
C++
#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>
|
||
#include <typeinfo>
|
||
#include <cstring>
|
||
|
||
// Вспомогательная функция для получения правильного разрешения устройства
|
||
// Для QPdfWriter использует resolution(), для других устройств - logicalDpiX()
|
||
static qreal getDeviceResolution(QPaintDevice *device)
|
||
{
|
||
if (!device) {
|
||
return 96.0; // Значение по умолчанию
|
||
}
|
||
|
||
// QPdfWriter наследуется от QPaintDevice
|
||
// Используем dynamic_cast (QPaintDevice имеет виртуальные функции в Qt)
|
||
QPdfWriter *pdfWriter = dynamic_cast<QPdfWriter*>(device);
|
||
if (pdfWriter) {
|
||
return pdfWriter->resolution();
|
||
}
|
||
|
||
// Если dynamic_cast не сработал, используем logicalDpiX()
|
||
return device->logicalDpiX();
|
||
}
|
||
|
||
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 = 25; // На первой странице 23 строки
|
||
const int rowsOnOtherPages = 32; // На последующих страницах 29 строк
|
||
|
||
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++;
|
||
}
|
||
}
|
||
|
||
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,2);
|
||
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,3);
|
||
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 = 29; // На последующих страницах 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,4);
|
||
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)
|
||
{
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4;
|
||
// Используем физические единицы для PDF (0.5 мм для рамок)
|
||
QPen framePen(Qt::black, 0.5 * mmToPixels);
|
||
framePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
painter.setPen(framePen);
|
||
|
||
// Конвертируем миллиметры в пиксели
|
||
|
||
|
||
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 ресурсов
|
||
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", 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мм
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4; // 25.4 мм = 1 дюйм
|
||
// Используем физические единицы для PDF (0.5 мм для рамок ГОСТ)
|
||
QPen framePen(Qt::black, 0.5 * mmToPixels);
|
||
framePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
painter.setPen(framePen);
|
||
|
||
|
||
// Вычисляем отступы в пикселях
|
||
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{
|
||
QFont nameFont = createGostFont(18, false, true);
|
||
QString nameText = getInscriptionValueWithProjectParams(model, projectParamModel, 1);
|
||
QRectF nameRect(mainTableRect.left()+65*mmToPixels, mainTableRect.top()+15*mmToPixels, 70*mmToPixels, 20*mmToPixels);
|
||
drawTextMultiline(painter, nameRect, nameText, nameFont, 3);
|
||
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));
|
||
// Определяем номер поля "Первичное применение" в зависимости от типа документа
|
||
int primaryApplicationField = 25; // По умолчанию
|
||
if (docType == 1) {
|
||
primaryApplicationField = 251; // Перечень
|
||
} else if (docType == 2) {
|
||
primaryApplicationField = 252; // Спецификация ПП
|
||
} else if (docType == 3) {
|
||
primaryApplicationField = 253; // Спецификация материалов
|
||
} else if (docType == 4) {
|
||
primaryApplicationField = 254; // Ведомость
|
||
}
|
||
painter.drawText(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, primaryApplicationField));
|
||
|
||
|
||
painter.restore();
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
bool PDFController::addGostFrameA4(QPainter &painter, const QRectF &pageRect, const TitleInscriptionsModel* model, const ProjectParamTableModel* projectParamModel, int currentPage, int totalPages, int docType)
|
||
{
|
||
totalPages++;
|
||
|
||
// Рисуем только внутреннюю рамку ГОСТ с отступами:
|
||
// Слева: 20мм, Сверху: 5мм, Справа: 5мм, Снизу: 5мм
|
||
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4; // 25.4 мм = 1 дюйм
|
||
// Используем физические единицы для PDF (0.5 мм для рамок ГОСТ)
|
||
QPen framePen(Qt::black, 0.5 * mmToPixels);
|
||
framePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
painter.setPen(framePen);
|
||
|
||
|
||
// Вычисляем отступы в пикселях
|
||
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мм
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4; // 25.4 мм = 1 дюйм
|
||
// Используем физические единицы для PDF (0.5 мм для рамок ГОСТ)
|
||
QPen framePen(Qt::black, 0.5 * mmToPixels);
|
||
framePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
painter.setPen(framePen);
|
||
|
||
|
||
// Вычисляем отступы в пикселях
|
||
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));
|
||
// A3 формат используется только для ведомости, поэтому используем поле 254
|
||
painter.drawText(60*mmToPixels,5*mmToPixels, 60*mmToPixels, 7*mmToPixels, Qt::AlignCenter, getInscriptionValueWithProjectParams(model, projectParamModel, 254));
|
||
|
||
|
||
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мм
|
||
qreal mmToPixels = painter.device()->logicalDpiX() / 25.4;
|
||
// Используем физические единицы для PDF (0.5 мм для рамок ГОСТ)
|
||
QPen framePen(Qt::black, 0.5 * mmToPixels);
|
||
framePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
painter.setPen(framePen);
|
||
|
||
// Вычисляем отступы в пикселях
|
||
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;
|
||
}
|
||
|
||
// Размеры колонок в миллиметрах (конвертируем в пиксели)
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4;
|
||
|
||
// Рисуем рамку таблицы с увеличенной толщиной (0.5 мм = примерно в 5 раз толще)
|
||
// Используем ту же толщину, что и для рамок ГОСТ, чтобы линии были заметными
|
||
QPen tablePen(Qt::black, 0.5 * mmToPixels);
|
||
tablePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
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 = {"Поз.\nобозначение", "Наименование", "Кол.", "Примечание"};
|
||
|
||
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 headerHeight = 15 * mmToPixels;
|
||
|
||
// Позиция начала таблицы
|
||
qreal tableStartX = tableRect.x();
|
||
|
||
// Рисуем заголовки с фиксированными размерами колонок
|
||
qreal currentX = tableStartX;
|
||
|
||
// Колонка "Поз." (20мм)
|
||
QRectF posHeaderRect(currentX, tableRect.y(), posWidth, headerHeight);
|
||
painter.drawRect(posHeaderRect);
|
||
painter.drawText(posHeaderRect, headers[0], QTextOption(Qt::AlignCenter));
|
||
currentX += posWidth;
|
||
|
||
// Колонка "Наименование" (110мм)
|
||
QRectF nameHeaderRect(currentX, tableRect.y(), nameWidth, headerHeight);
|
||
painter.drawRect(nameHeaderRect);
|
||
painter.drawText(nameHeaderRect, headers[1], QTextOption(Qt::AlignCenter));
|
||
currentX += nameWidth;
|
||
|
||
// Колонка "Кол." (10мм)
|
||
QRectF qtyHeaderRect(currentX, tableRect.y(), qtyWidth, headerHeight);
|
||
painter.drawRect(qtyHeaderRect);
|
||
painter.drawText(qtyHeaderRect, headers[2], QTextOption(Qt::AlignCenter));
|
||
currentX += qtyWidth;
|
||
|
||
// Колонка "Примечание" (45мм)
|
||
QRectF noteHeaderRect(currentX, tableRect.y(), noteWidth, headerHeight);
|
||
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) * rowHeight+headerHeight, 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) * rowHeight+headerHeight, 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) * rowHeight+headerHeight, 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) * rowHeight+headerHeight, 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;
|
||
}
|
||
|
||
// Размеры колонок в миллиметрах (конвертируем в пиксели)
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4;
|
||
|
||
// Рисуем рамку таблицы с увеличенной толщиной (0.5 мм = примерно в 5 раз толще)
|
||
// Используем ту же толщину, что и для рамок ГОСТ, чтобы линии были заметными
|
||
QPen tablePen(Qt::black, 0.5 * mmToPixels);
|
||
tablePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
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 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;
|
||
}
|
||
|
||
// Размеры колонок в миллиметрах (конвертируем в пиксели)
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4;
|
||
|
||
// Рисуем рамку таблицы с увеличенной толщиной (0.5 мм = примерно в 5 раз толще)
|
||
// Используем ту же толщину, что и для рамок ГОСТ, чтобы линии были заметными
|
||
QPen tablePen(Qt::black, 0.5 * mmToPixels);
|
||
tablePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
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 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;
|
||
}
|
||
|
||
// Размеры колонок в миллиметрах (конвертируем в пиксели) для А5 формата
|
||
// Используем правильное разрешение для PDF
|
||
qreal resolution = getDeviceResolution(painter.device());
|
||
qreal mmToPixels = resolution / 25.4;
|
||
|
||
// Рисуем рамку таблицы с увеличенной толщиной (0.5 мм = примерно в 5 раз толще)
|
||
// Используем ту же толщину, что и для рамок ГОСТ, чтобы линии были заметными
|
||
QPen tablePen(Qt::black, 0.5 * mmToPixels);
|
||
tablePen.setCosmetic(false); // Важно для PDF - использовать физические единицы
|
||
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 = {"№ строки","Наименование", "Код продукции", "Обозначение документа на поставку", "Поставщик",
|
||
"Куда входит (обозначение)", "Количество на изделие", "Количество в комплекте",
|
||
"Количество на регулир", "Количество всего", "Примечание"};
|
||
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(displayRow + 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 = 25; // На первой странице 27 строк
|
||
const int rowsOnOtherPages = 32; // На последующих страницах 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 = 25;
|
||
const int rowsOnOtherPages = 32;
|
||
|
||
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 = 29; // На последующих страницах 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 = 29; // На последующих страницах 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;
|
||
}
|