Files
GostGenerator/pdfView.qml
T

915 lines
39 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
Item {
id: root
anchors.fill: parent
readonly property real a4Ratio: 1.4142 // высота = ширина * 1.4142
readonly property int pagesCount: 3
readonly property int pageSpacing: 12
// ГОСТ 2.104-2006 параметры рамок
readonly property int outerMargin: 5 // отступ внешней рамки от края
readonly property int frameSpacing: 20 // расстояние между рамками
readonly property int innerFrameWidth: 1 // толщина внутренней рамки
readonly property int outerFrameWidth: 2 // толщина внешней рамки
// Преобразование ширины в условные единицы (мм)
// A4: 210x297 мм, соотношение сторон 1:1.4142
readonly property real mmPerUnit: width / 210.0 // мм в одной единице QML
readonly property real unitPerMm: 210.0 / width // единиц QML в одном мм
// Удобные функции для работы с размерами в мм
function mmToUnits(mm) {
return mm * mmPerUnit
}
function unitsToMm(units) {
return units * unitPerMm
}
Flickable {
id: flick
anchors.fill: parent
clip: true
boundsBehavior: Flickable.StopAtBounds
interactive: true
flickableDirection: Flickable.VerticalFlick
contentWidth: width
contentHeight: columnContent.height
Column {
id: columnContent
width: flick.width
spacing: root.pageSpacing
// Явно задаем высоту, чтобы contentHeight корректно вычислялся
height: implicitHeight
// Верхний отступ, чтобы страница не прилипала к краю
Item { width: 1; height: root.pageSpacing }
// Первая страница - специальная, готовая для TableModel
Rectangle {
id: firstPage
width: columnContent.width
height: width * root.a4Ratio
radius: 4
color: "#F7F2D0"
border.color: "#D6CEAA"
border.width: 1
// Внешняя рамка ГОСТ
Rectangle {
id: outerFrame1
anchors.fill: parent
anchors.leftMargin: mmToUnits(20)
anchors.topMargin: mmToUnits(5)
anchors.bottomMargin: mmToUnits(5)
anchors.rightMargin: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
Rectangle{
id:leftFrame1
anchors.bottom: outerFrame1.bottom
anchors.right: outerFrame1.left
width: mmToUnits(5+7)
height: mmToUnits(35+25+25+35+25)
anchors.rightMargin: -outerFrame1.border.width
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
id:field19Wrapper
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(25)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Инв. № подл")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(19)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle{
id:field20Wrapper
anchors.bottom: field19Wrapper.top
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(35)+ root.outerFrameWidth
anchors.bottomMargin: - root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Подп. и дата")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(20)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle{
id:field21Wrapper
anchors.bottom: field20Wrapper.top
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(25)+ root.outerFrameWidth
anchors.bottomMargin: - root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Взам. инв. №")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(21)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle{
id:field22Wrapper
anchors.bottom: field21Wrapper.top
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(25) + root.outerFrameWidth
anchors.bottomMargin: - root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Инв. № дубл")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(22)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle{
id:field23Wrapper
anchors.bottom: field22Wrapper.top
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(35) +root.outerFrameWidth
anchors.bottomMargin: -root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Подп. и дата")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(23)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
Rectangle{
id:leftFrame1_2
anchors.top: outerFrame1.top
anchors.right: outerFrame1.left
width: mmToUnits(5+7)
height: mmToUnits(120)
anchors.rightMargin: -outerFrame1.border.width
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
id:field24Wrapper
anchors.bottom: leftFrame1_2.bottom
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(60) + root.outerFrameWidth
// anchors.bottomMargin: - root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Справ. №")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(24)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle{
id:field25Wrapper
anchors.bottom: field24Wrapper.top
anchors.left: parent.left
anchors.right: parent.right
height: mmToUnits(60) //+root.outerFrameWidth
anchors.bottomMargin: -root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(5)
color: "transparent"
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("Перв. примен")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle{
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
width:mmToUnits(7)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.centerIn: parent
rotation: -90
text: qsTr("(25)")
font.pixelSize: Math.min(parent.width * 0.8, parent.height * 0.3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
Rectangle{
id:innerBottomFrame1
anchors.bottom: outerFrame1.bottom
anchors.right: outerFrame1.right
width: mmToUnits(185)
height: mmToUnits(55)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Rectangle{
id:firstColumn1
anchors.left: parent.left
anchors.top:parent.top
anchors.bottom: parent.bottom
width: mmToUnits(17) +2*root.outerFrameWidth// border
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
Rectangle{
id:secondColumn1
anchors.left: firstColumn1.right
anchors.top:parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: -root.outerFrameWidth
width: mmToUnits(23)+2*root.outerFrameWidth // border
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
Rectangle{
id:thirdColumn1
anchors.left: secondColumn1.right
anchors.top:parent.top
anchors.bottom: parent.bottom
width: mmToUnits(15)+2*root.outerFrameWidth // border
anchors.leftMargin: -root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
Rectangle{
id:forthColumn1
anchors.left: thirdColumn1.right
anchors.top:parent.top
anchors.bottom: parent.bottom
width: mmToUnits(10)+2*root.outerFrameWidth // border
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
anchors.leftMargin: -root.outerFrameWidth
}
Rectangle{
id:fifthColumn1
anchors.left: forthColumn1.right
anchors.top:parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
anchors.leftMargin: -root.outerFrameWidth
Rectangle{
id:field2Wrapper
anchors.top: parent.top
anchors.left:parent.left
anchors.right: parent.right
height: mmToUnits(15)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
Text {
anchors.fill:parent
text: qsTr("(2)")
}
}
Rectangle{
id:field21_4Wrapper
anchors.top: field2Wrapper.bottom
anchors.left:parent.left
anchors.right: parent.right
anchors.topMargin: -root.outerFrameWidth
height: mmToUnits(25) + 2* root.outerFrameWidth
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
Rectangle{
id:field3__Wrapper
anchors.top: field21_4Wrapper.bottom
anchors.left:parent.left
anchors.right: parent.right
anchors.topMargin: -root.outerFrameWidth
height: mmToUnits(15)
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
}
}
// Внутренняя рамка ГОСТ
// Rectangle {
// id: innerFrame1
// anchors.fill: parent
// anchors.margins: root.outerMargin + root.frameSpacing
// color: "transparent"
// border.color: "#000000"
// border.width: root.innerFrameWidth
// }
// Основная надпись (левая нижняя часть)
// Rectangle {
// id: mainInscription1
// anchors.left: innerFrame1.left
// anchors.bottom: innerFrame1.bottom
// width: mmToUnits(185) // 185 мм
// height: mmToUnits(55) // 55 мм
// color: "transparent"
// border.color: "#000000"
// border.width: 1
// // Графы основной надписи
// Grid {
// anchors.fill: parent
// columns: 8
// rows: 11
// // Инв. номер
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Инв. №"
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Подпись и дата
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Подп."
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Лист
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Лист"
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Листов
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Листов"
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Масштаб
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Масштаб"
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Масса
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Масса"
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Разработал
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Разраб."
// font.pixelSize: 8
// color: "#000000"
// }
// }
// // Проверил
// Rectangle {
// width: mmToUnits(25); height: mmToUnits(5)
// color: "transparent"
// border.color: "#000000"
// border.width: 0.5
// Text {
// anchors.centerIn: parent
// text: "Пров."
// font.pixelSize: 8
// color: "#000000"
// }
// }
// }
// }
// Заголовок первой страницы
// Здесь будет TableModel
}
// Остальные страницы
Repeater {
model: root.pagesCount - 1
delegate: Rectangle {
id: pageDelegate
width: columnContent.width
height: width * root.a4Ratio
radius: 4
color: "#F7F2D0"
border.color: "#D6CEAA"
border.width: 1
// Внешняя рамка ГОСТ
Rectangle {
id: outerFrame
anchors.fill: parent
anchors.margins: root.outerMargin
color: "transparent"
border.color: "#000000"
border.width: root.outerFrameWidth
}
// Внутренняя рамка ГОСТ
Rectangle {
id: innerFrame
anchors.fill: parent
anchors.margins: root.outerMargin + root.frameSpacing
color: "transparent"
border.color: "#000000"
border.width: root.innerFrameWidth
}
// Основная надпись (левая нижняя часть)
Rectangle {
id: mainInscription
anchors.left: innerFrame.left
anchors.bottom: innerFrame.bottom
width: mmToUnits(185) // 185 мм
height: mmToUnits(55) // 55 мм
color: "transparent"
border.color: "#000000"
border.width: 1
// Графы основной надписи
Grid {
anchors.fill: parent
columns: 8
rows: 11
// Инв. номер
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Инв. №"
font.pixelSize: 8
color: "#000000"
}
}
// Подпись и дата
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Подп."
font.pixelSize: 8
color: "#000000"
}
}
// Лист
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Лист"
font.pixelSize: 8
color: "#000000"
}
}
// Листов
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Листов"
font.pixelSize: 8
color: "#000000"
}
}
// Масштаб
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Масштаб"
font.pixelSize: 8
color: "#000000"
}
}
// Масса
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Масса"
font.pixelSize: 8
color: "#000000"
}
}
// Разработал
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Разраб."
font.pixelSize: 8
color: "#000000"
}
}
// Проверил
Rectangle {
width: mmToUnits(25); height: mmToUnits(5)
color: "transparent"
border.color: "#000000"
border.width: 0.5
Text {
anchors.centerIn: parent
text: "Пров."
font.pixelSize: 8
color: "#000000"
}
}
}
}
Text {
anchors.centerIn: parent
text: "Страница " + (index + 2)
color: "#2c2c2c"
font.pixelSize: 16
}
}
}
// Нижний отступ
Item { width: 1; height: root.pageSpacing }
}
// Прокрутка колесом мыши (актуально для QQuickWidget)
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
propagateComposedEvents: true
onWheel: {
const maxY = Math.max(0, flick.contentHeight - flick.height)
// angleDelta.y положителен при прокрутке вверх
const step = wheel.angleDelta.y
flick.contentY = Math.min(maxY, Math.max(0, flick.contentY - step))
wheel.accepted = true
}
}
}
// Вертикальная полоса прокрутки
ScrollBar {
id: vbar
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
orientation: Qt.Vertical
policy: ScrollBar.AsNeeded
width: 14
z: 1000
// Настроим видимость и позиционирование относительно содержимого Flickable
size: Math.min(1, flick.height / Math.max(1, flick.contentHeight))
position: flick.contentY / Math.max(1, (flick.contentHeight - flick.height))
onPositionChanged: {
const maxY = Math.max(0, flick.contentHeight - flick.height)
flick.contentY = position * maxY
}
}
}