from krita import DockWidget from PyQt5.QtWidgets import QWidget, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QCheckBox, QPushButton from PyQt5.QtCore import QByteArray DOCKER_TITLE = 'Button Shy PNP Tools' class BsPnpTools(DockWidget): def __init__(self): super().__init__() self.setWindowTitle(DOCKER_TITLE) widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) layout.addSpacing(10) layout.addWidget(QLabel('Expand the Button Shy 6-card PNP layout to 8-cards')) # Expand Direction. Do we put the 2 new cards on the left or right? self.expandDir = QComboBox() dirs = ['Right', 'Left'] self.expandDir.addItems(dirs) row0 = QHBoxLayout() row0.addWidget(QLabel('Expand Direction:')) row0.addWidget(self.expandDir) layout.addLayout(row0) # Button (Shy)! layout.addSpacing(20) goButton = QPushButton("Expand") goButton.setIcon( Krita.instance().icon('animation_play') ) layout.addWidget(goButton) crop3Button = QPushButton("Create 3x2 Cropmarks") crop3Button.setIcon( Krita.instance().icon('animation_play') ) layout.addWidget(crop3Button) crop4Button = QPushButton("Create 4x2 Cropmarks") crop4Button.setIcon( Krita.instance().icon('animation_play') ) layout.addWidget(crop4Button) self.outerCheck = QCheckBox('Outer') self.outerCheck.setChecked(True) self.innerCheck = QCheckBox('Inner') self.innerCheck.setChecked(True) self.guidesCheck = QCheckBox('Guides') self.guidesCheck.setChecked(True) row1 = QHBoxLayout() row1.addWidget(self.outerCheck) row1.addWidget(self.innerCheck) row1.addWidget(self.guidesCheck) layout.addLayout(row1) # Add a stretch to prevent the rest of the content from stretching. layout.addStretch() # Add widget to the docker. self.setWidget(widget) # Hook up the action to the button. goButton.clicked.connect( self.expandBsPnp ) crop3Button.clicked.connect( self.add3x2CropMarks ) crop4Button.clicked.connect( self.add4x2CropMarks ) # notifies when views are added or removed # 'pass' means do not do anything def canvasChanged(self, canvas): pass ########## # Slots ########## # Actually expands the PNP. def expandBsPnp(self, e): # dialog = QDialog() # dialog.setWindowTitle("DEBUG") # layout = QVBoxLayout() # dialog.setLayout(layout) # Get the current layer. doc = Krita.instance().activeDocument() layer = doc.activeNode() if layer.type() != 'paintlayer': dialog = QDialog() dialog.setWindowTitle("Paint Layer Required") layout = QVBoxLayout() layout.addWidget(QLabel('Expander only works on paint layers. Please select one.')) dialog.setLayout(layout) dialog.exec_() return direction = self.expandDir.currentText() layerPos = layer.position() # Move layer 411 pixels left or right, which is half a card and gap width: (752 + 70) / 2 xDiff = 411 if direction == 'Left' else -411 layer.move(layerPos.x() + xDiff, layerPos.y()) # Fill in empty document area with white overlapHCrop = 341 # x-offset to overwrite old horizontal crop marks. whitePixel = b'\xff\xff\xff\xff' bds = layer.bounds() fillX = 0 if direction == 'Left' else bds.right() - overlapHCrop fillY = 0 fillWidth = bds.left() + overlapHCrop if direction == 'Left' else doc.width() - fillX fillHeight = doc.height() whiteFill = QByteArray(whitePixel * fillWidth * fillHeight) layer.setPixelData(whiteFill, fillX, fillY, fillWidth, fillHeight) # Create horizontal cropmarks at image edges. # Vertical distances (px): 1047 (38 midY 37) 1048 # 61px long. blackPixel = b'\x00\x00\x00\xff' cropMarkWidth = 61 cropMarkHeight = 2 cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight) midX = int(doc.width() / 2) midY = int(doc.height() / 2) ySet = [ midY - 1085, midY - 38, midY + 37, midY + 1085 ] for x in [midX - 1706, midX + 1645]: for y in ySet: layer.setPixelData(cropMark, x, y - 1, cropMarkWidth, cropMarkHeight) # Create vertical cropmarks for new card spaces # Horizontal distances (px): 752 70 752 (35 midX 35) 752 70 752 # For these marks, we only want either the first or last 2 positions. # 37px long. cropMarkWidth = 2 cropMarkHeight = 37 cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight) xSet = [ midX - 1609, midX - 857 ] if direction == 'Left' else [ midX + 857, midX + 1609 ] for y in [ midY - 1192, midY + 1155 ]: for x in xSet: layer.setPixelData(cropMark, x - 1, y, cropMarkWidth, cropMarkHeight) # Place guides on crop marks for new card spaces vList = doc.verticalGuides() hList = doc.horizontalGuides() vList.clear() hList.clear() doc.setVerticalGuides(xSet) doc.setHorizontalGuides(ySet) doc.setGuidesLocked(True) doc.setGuidesVisible(True) # Refresh the view, or the moved will not be immediately reflected. doc.refreshProjection() # Add 3x2 Internal cropmarks. def add3x2CropMarks(self, e): self.addCropMarks(3) # Add 4x2 Internal cropmarks. def add4x2CropMarks(self, e): self.addCropMarks(4) def addCropMarks(self, gridSize): # Cropmarks will be on a new layer. doc = Krita.instance().activeDocument() layer = doc.createNode('BSCropmarks', 'paintLayer') root = doc.rootNode() root.addChildNode(layer, None) # Calculate grid dimensions, assuming page is in centre position. midX = int(doc.width() / 2) midY = int(doc.height() / 2) xSet = [] ySet = [] if gridSize == 3: # Horizontal distances (px): 752 70 (376 midX 376) 70 752 # Vertical distances (px): 1047 (38 midY 37) 1048 xSet = [ midX - 1198, midX - 446, midX - 376, midX + 376, midX + 446, midX + 1198 ] ySet = [ midY - 1085, midY - 38, midY + 37, midY + 1085 ] else: # Horizontal distances (px): 752 70 752 (35 midX 35) 752 70 752 # Vertical distances (px): 1047 (38 midY 37) 1048 xSet = [ midX - 1609, midX - 857, midX - 787, midX - 35, midX + 35, midX + 787, midX + 857, midX + 1609 ] ySet = [ midY - 1085, midY - 38, midY + 37, midY + 1085 ] # Create inner and outer cropmarks. blackPixel = b'\x00\x00\x00\xff' cropMarkWidth = 2 if self.outerCheck.checkState(): cropMarkHeight = 48 cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight) for x in xSet: layer.setPixelData(cropMark, x-1, ySet[0]-35-48, cropMarkWidth, cropMarkHeight) # top vertical line layer.setPixelData(cropMark, x-1, ySet[-1]+35, cropMarkWidth, cropMarkHeight) # bottom vertical line for y in ySet: layer.setPixelData(cropMark, xSet[0]-35-48, y-1, cropMarkHeight, cropMarkWidth) # left horizontal line layer.setPixelData(cropMark, xSet[-1]+35, y-1, cropMarkHeight, cropMarkWidth) # right horizontal line if self.innerCheck.checkState(): cropMarkHeight = 36 cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight) for x in xSet: for y in ySet: layer.setPixelData(cropMark, x-1, int(y - cropMarkHeight/2), cropMarkWidth, cropMarkHeight) # vertical line layer.setPixelData(cropMark, int(x - cropMarkHeight/2), y-1, cropMarkHeight, cropMarkWidth) # horizontal line # Create guides. if self.guidesCheck.checkState(): vList = doc.verticalGuides() hList = doc.horizontalGuides() vList.clear() hList.clear() doc.setVerticalGuides(xSet) doc.setHorizontalGuides(ySet) doc.setGuidesLocked(True) doc.setGuidesVisible(True) # Refresh the view, or the cropmarks will not be immediately shown. doc.refreshProjection()