#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;
}
