from krita import * from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QComboBox, QCheckBox, QPushButton from PyQt5.QtCore import * class BoxGenerator(Extension): def __init__(self, parent): super().__init__(parent) # Krita.instance() exists, so do any setup work def setup(self): pass # called after setup(self) def createActions(self, window): # Create menu item in Tools > Scripts. action = window.createAction("boxgen", "Box Generator") action.triggered.connect(self.box_generator) def box_generator(self): # Get the current selected layer, called a 'node' self.doc = Krita.instance().activeDocument() if not self.doc: # Create and show a new document (A4 300ppi). self.doc = Krita.instance().createDocument(3508, 2480, "", "RGBA", "U8", "", 300.0) Krita.instance().activeWindow().addView(self.doc) # Dialog creation. newDialog = QDialog() newDialog.setWindowTitle("Box Generator") # Description row. desc = QLabel('Creates outlines for a foldable box with lid.') desc.setAlignment(Qt.AlignCenter) row0 = QHBoxLayout() row0.addWidget(desc) # Dimension row. self.lengthInput = QLineEdit('95') self.widthInput = QLineEdit('70') self.heightInput = QLineEdit('20') self.unitInput = QComboBox() self.unitInput.addItems( ['mm', 'inch', 'px'] ) row1 = QHBoxLayout() row1.addWidget(QLabel('Dimensions: L:')) row1.addWidget(self.lengthInput) row1.addWidget(QLabel(' x W:')) row1.addWidget(self.widthInput) row1.addWidget(QLabel(' x H:')) row1.addWidget(self.heightInput) row1.addWidget(self.unitInput) # Decision row. self.flapCheck = QCheckBox('Flap') self.flapCheck.setChecked(True) row2 = QHBoxLayout() row2.addWidget(self.flapCheck) # Do It row. goButton = QPushButton("Create Box") goButton.setIcon( Krita.instance().icon('animation_play') ) row3 = QHBoxLayout() row3.addWidget(goButton) layoutMain = QVBoxLayout() layoutMain.addLayout(row0) layoutMain.addLayout(row1) layoutMain.addLayout(row2) layoutMain.addLayout(row3) newDialog.setLayout(layoutMain) # hook up the actions. # goButton.clicked.connect( self.generateBox ) # self.unitInput.currentIndexChanged.connect( self.convertCount ) # show the dialog. newDialog.exec_() ########## # Slots ########## # Actually generates the box! def generateBox(self, e): # Calculate how many lines of pixels to copy. unit = self.unitInput.currentIndex() count = float(self.countInput.text()) ppi = self.doc.resolution() if unit == 0: # mm count = count * (ppi / 24.5) if unit == 1: # inch count = count * ppi offset = round(float(self.offsetInput.text())) count = round(count) - offset print("Pixel bleed amount: ", count) print("Edge offset: ", offset) # Copy lines for selected sides. if self.topCheck.checkState(): bds = self.layer.bounds() xpos = bds.left() ypos = bds.top() - offset len = bds.width() bleedline = self.layer.pixelData(xpos, ypos, len, 1) for c in range(1, count+1): self.layer.setPixelData(bleedline, xpos, (ypos - c), len, 1) print("Top lines cloned: ", count) if self.botCheck.checkState(): bds = self.layer.bounds() xpos = bds.left() ypos = bds.bottom() + offset len = bds.width() bleedline = self.layer.pixelData(xpos, ypos, len, 1) for c in range(1, count+1): self.layer.setPixelData(bleedline, xpos, (ypos + c), len, 1) print("Bottom lines cloned: ", count) if self.leftCheck.checkState(): bds = self.layer.bounds() xpos = bds.left() - offset ypos = bds.top() len = bds.height() bleedline = self.layer.pixelData(xpos, ypos, 1, len) for c in range(1, count+1): self.layer.setPixelData(bleedline, (xpos - c), ypos, 1, len) print("Left lines cloned: ", count) if self.rightCheck.checkState(): bds = self.layer.bounds() xpos = bds.right() + offset ypos = bds.top() len = bds.height() bleedline = self.layer.pixelData(xpos, ypos, 1, len) for c in range(1, count+1): self.layer.setPixelData(bleedline, (xpos + c), ypos, 1, len) print("Right lines cloned: ", count) self.doc.refreshProjection() # Convert count input values to relevant units def convertCount(): unitIndex = unitInput.currentIndex() print("Updated unit index: ", unitIndex)