def render_drop_shadow_frame(pixmap, shadow_rect, shadow_color, offset, radius, rect_fill_color): pixmap.fill(QColor(0, 0, 0, 0)) scene = QGraphicsScene() rect = QGraphicsRectItem(shadow_rect) rect.setBrush(QColor(rect_fill_color)) rect.setPen(QPen(Qt.NoPen)) scene.addItem(rect) effect = QGraphicsDropShadowEffect(color=shadow_color, blurRadius=radius, offset=offset) rect.setGraphicsEffect(effect) scene.setSceneRect(QRectF(QPointF(0, 0), QSizeF(pixmap.size()))) painter = QPainter(pixmap) scene.render(painter) painter.end() scene.clear() scene.deleteLater() return pixmap
class Factura: def __init__(self,padre,num): self.padre=padre self.cursor=padre.cursor self.curser=padre.curser self.parent=padre self.num=num self.escena=QGraphicsScene() self.gvDocumento=QGraphicsView() #self.cfg=padre.cfg self.iniciar() def iniciar(self): if self.cargarPlantilla(): iva=0 subtotal=0 total=0 alto=int(self.cfg.get("documento", "alto")) ancho=int(self.cfg.get("documento", "ancho")) cfont=QFont("Droid Sans", int(self.cfg.get("cliente", "fuente")), int(self.cfg.get("cliente", "peso") )) pfont=QFont("Droid Sans", int(self.cfg.get("productos", "fuente")), int(self.cfg.get("productos", "peso") )) ffont=QFont("Droid Sans", int(self.cfg.get("fecha", "fuente")), int(self.cfg.get("fecha", "peso") )) tfont=QFont("Droid Sans", int(self.cfg.get("totales", "fuente")), int(self.cfg.get("totales", "peso") )) self.escena.setSceneRect(-int(self.cfg.get("documento", "x")),-int(self.cfg.get("documento", "y")),ancho,alto) fuente=QFont("Droid Sans", int(self.cfg.get("documento", "fuente")), int(self.cfg.get("documento", "peso") )) smallDroid=QFont("Droid Sans", 9) sql="""SELECT * FROM clientes as C, notas WHERE notas.id=%s and notas.cliente=C.id;"""%self.num self.curser.execute(sql) cliente=self.curser.fetchone() if cliente!=None: cliente=dicursor(self.curser,cliente) datos=self.escena.addText("",cfont) datos.setHtml("<p><b>Nombre:</b> %s<br><b>Direccion:</b> %s, C.P %s %s, %s.<br><b>RFC:</b> %s</p>"%(cliente['nombre'],cliente['direccion'],cliente['correo'],cliente['poblacion'],cliente['estado'],cliente['rfc'])) datos.setPos(int(self.cfg.get("cliente", "x")) ,int(self.cfg.get("cliente", "y"))) datos.setTextWidth(int(self.cfg.get("cliente", "ancho"))) self.curser.execute("SELECT cantidad, `descripcion`,total/cantidad as precio,total,porcentaje as imp,unidades.nombre as unidad, ' ' as espacio from productos,vendidos, impuestos , unidades where ref=producto and venta="+str(self.num)+" and impuestos.id=impuesto and unidades.id=unidad group by ref") fecha=self.escena.addText("",ffont) if isinstance(cliente['fecha'],datetime.datetime): fecha.setHtml(cliente['fecha'].strftime(self.cfg.get("fecha", "formato"))) else: fecha.setHtml(datetime.datetime.strptime(cliente['fecha'],'%Y-%m-%d %H:%M:%S').strftime(self.cfg.get("fecha", "formato"))) fecha.setPos(int(self.cfg.get("fecha", "x")),int(self.cfg.get("fecha", "y"))) fecha.setTextWidth(int(self.cfg.get("fecha", "ancho"))) #print "SELECT cantidad, `descripcion`,precio,total from productos,vendidos where ref=producto and venta="+str(self.num)+" group by ref" arts=self.curser.fetchall() if arts!=None: arts=dicursor(self.curser,arts) col=[[],[],[],[],[]] #dict(arts) for item in arts: imp=0;porc=0 imp=item['total']/float("1.%d"%item['imp']) porc=imp*(int(item['imp'])*.01) #imp=round(imp,2) #porc=round(porc,2) #porc+=item['total']-(imp+porc) total+=item['total'] item['precio']=round(imp/item['cantidad'],2) item['total']=round(imp,2) iva+=porc subtotal+=imp subtotal=round(subtotal,2) iva=round(iva,2) filas=[] campos=self.cfg.get("productos", "campos").replace(" ","").split(",") heads="{%s}"%"},{".join(campos) anchos=self.cfg.get("productos", "anchos").replace(" ","").split(",") #cabezas=heads.replace("{","").replace("}","").split(",") for item in arts: row=heads.format(**item) filas.append(row.split(',')) heads=heads.replace("{","").replace("}","") tabla=self.escena.addText("",pfont) tabla.setHtml(listaHtml(filas,cabezas=campos,color='#fff',fondo="#FFF", tfuente=11,opc="101",css="th{color:#FFF} .celda{margin:10px;padding:5px;}",anchos=anchos)) tabla.setPos(int(self.cfg.get("productos", "x")),int(self.cfg.get("productos", "y"))) tabla.setTextWidth(int(self.cfg.get("productos", "ancho"))) cantidad=self.escena.addText("",pfont) cantidad.setHtml("<center>%s</center>"%nletra(total)) cantidad.setPos(int(self.cfg.get("nletra", "x")),int(self.cfg.get("nletra", "y"))) cantidad.setTextWidth(int(self.cfg.get("nletra", "ancho"))) totales=self.escena.addText("",tfont) totales.setHtml("<p ALIGN=right>%.2f</p><p ALIGN=right>%.2f</p><p ALIGN=right>%.2f</p>"%(float(subtotal),float(iva),float(total))) totales.setPos(int(self.cfg.get("totales", "x")),int(self.cfg.get("totales", "y"))) totales.setTextWidth(int(self.cfg.get("totales", "ancho"))) #self.curser.execute("SELECT cantidad, `descripcion`,precio,total from productos,vendidos where ref=producto and venta="+str(self.num)+" group by ref") self.gvDocumento.setScene(self.escena) else: print "Error al cargar plantilla" def alinear(self,item): formato=QTextBlockFormat() formato.setAlignment(Qt.AlignRight) cursor = item.textCursor() cursor.select(QTextCursor.Document) cursor.mergeBlockFormat(formato) cursor.clearSelection() item.setTextCursor(cursor) def cargarPlantilla(self): self.cfg = Cp.ConfigParser() if self.cfg.read([os.path.join(home,"formas","factura.cfg")]): if self.cfg.has_option("documento", "version"): return True else: return False def br(self,texto): offset=1 font=texto.font() pos=texto.pos() return QPointF(pos.x(),float(pos.y())+float(font.pointSize())+offset) def imprimir(self): printer=QPrinter(QPrinter.HighResolution) printer.setPaperSize(QPrinter.Letter) printer.setOutputFormat(QPrinter.PdfFormat) ruta=os.path.join(self.parent.cfg.get("factura", "ruta"),'Factura-'+str(self.num)+'.pdf') printer.setOutputFileName(ruta) prev=QPrintDialog(printer,self.padre) if prev.exec_()==QDialog.Accepted: paint=QPainter() paint.begin(printer) self.escena.render(paint) paint.end() print "Imprimiendo..." if sys.platform == 'linux2': os.system("gnome-open '%s' "%ruta) elif sys.platform == 'win32': os.system("start '%s'"%ruta)
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not(self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert(self.pos == pos) self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height()))) painter.end() ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0] labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0)) labels = labels.swapaxes(0,1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0: labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX,oldY), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize/2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize/2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) ) #update/move position self.pos = pos
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self): QObject.__init__(self) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not(self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): print "Setting Drawnnumer", num self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x()+0.0001, pos.y()+0.0001) line = self.moveTo(pos) return line def endDrawing(self, pos): self.moveTo(pos) tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height()))) painter.end() ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0] labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0)) labels = labels.swapaxes(0,1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() #print "BrushingModel.moveTo(pos=%r)" % (pos) line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(x,y), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize/2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize/2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) ) #update/move position self.pos = pos
class Level(QFrame): def __init__(self, parent): QFrame.__init__(self,parent) self.filename = QString() self.copiedItem = QByteArray() self.pasteOffset = 5 self.prevPoint = QPoint() self.addOffset = 5 self.screenSize = (320, 240) self.bgColor = QColor(244,244,244) '''0.Portrait 1.Landscape''' self.orientation = 0 self.currentItem = None self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) '''1.Header''' self.levelBar = LevelBar(self) '''3.Tiler''' self.tiler = TileMapGrid(self)#Tiler(self) self.tiler.setMinimumHeight(100) #self.tiler.currentChanged.connect(self.closeDesigner) #self.tiler.setTabsClosable(True) #self.tiler.setTabShape(0) #self.tiler.hide() #self.levelLayout.addWidget(self.levelBar) '''2.view''' viewLayoutWidget = QFrame() viewLayoutWidget.setFrameShape(QFrame.StyledPanel) viewLayout = QHBoxLayout(viewLayoutWidget) #viewLayout.setMargin(10) self.view = LevelView(viewLayoutWidget) '''scene''' self.scene = QGraphicsScene(self) #self.scene.selectionChanged.connect(self.setConnect) #self.view.setStyleSheet("border: 1px solid red;") self.setBackgroundColor(self.bgColor) self.setScreenSize(self.screenSize) self.view.setScene(self.scene) self.view.setAlignment(Qt.AlignCenter) self.scroll_off = 1 self.setScrollBar() viewLayout.setMargin(0) viewLayout.addWidget(self.view) self.wrapped = [] # Needed to keep wrappers alive layout = QVBoxLayout(self) layout.addWidget(self.levelBar) layout.addWidget(viewLayoutWidget) layout.addWidget(self.tiler) layout.setMargin(0) self.setLayout(layout) def setScrollBar(self): if(self.scroll_off): self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll_off = 0 else: self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scroll_off = 1 def setBackgroundColor(self,color): self.bgColor = color self.scene.setBackgroundBrush(QBrush(color)) def setScreenSize(self,size): self.screenSize = size self.setOrientation(self.orientation) def setOrientation(self,idx): self.orientation = idx if(idx == 0): self.view.setMaximumSize(self.screenSize[1], self.screenSize[0]) self.scene.setSceneRect(0, 0, self.screenSize[1], self.screenSize[0]) else: self.view.setMaximumSize(self.screenSize[0], self.screenSize[1]) self.scene.setSceneRect(0, 0, self.screenSize[0], self.screenSize[1]) def offerSave(self): if (Dirty and QMessageBox.question(self, "Designer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes): self.save() def position(self): point = self.mapFromGlobal(QCursor.pos()) if not self.view.geometry().contains(point): coord = random.randint(36, 144) point = QPoint(coord, coord) else: if point == self.prevPoint: point += QPoint(self.addOffset, self.addOffset) self.addOffset += 5 else: self.addOffset = 5 self.prevPoint = point return self.view.mapToScene(point) def selectedItem(self): items = self.scene.selectedItems() if len(items) == 1: return items[0] return None def current(self,item): self.scene.clearSelection() sceneItems = self.scene.items() for items in sceneItems: if(items != item): item.setSelected(False) if(item.isConnected()): self.propertyBar.disconnectText(item) item.setConnected(False) self.currentItem = item self.currentItem.setConnected(True) self.currentItem.setSelected(True) self.propertyBar.connectText(self.currentItem) self.propertyBar.initText(self.currentItem) def addText(self): item = TextItem("SomeText", self.position()) self.connect(item, SIGNAL("current"),self.current) self.connect(item, SIGNAL("copy"),self.copy) self.connect(item, SIGNAL("cut"),self.cut) self.connect(item, SIGNAL("paste"),self.paste) self.connect(item, SIGNAL("delete"),self.delete) #self.current(item) self.scene.addItem(item) def copy(self): item = self.selectedItem() if item is None: return self.copiedItem.clear() self.pasteOffset = 5 stream = QDataStream(self.copiedItem, QIODevice.WriteOnly) self.writeItemToStream(stream, item) def cut(self): item = self.selectedItem() if item is None: return self.copy() self.scene.removeItem(item) del item def paste(self): if self.copiedItem.isEmpty(): return stream = QDataStream(self.copiedItem, QIODevice.ReadOnly) item = self.readItemFromStream(stream, self.pasteOffset) self.pasteOffset += 5 #self.scene.addItem(item) def delete(self): items = self.scene.selectedItems() if (len(items) and QMessageBox.question(self, "Designer - Delete", "Delete {0} item{1}?".format(len(items), "s" if len(items) != 1 else ""), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes): while items: item = items.pop() self.scene.removeItem(item) del item def readItemFromStream(self, stream, offset=0): type = QString() position = QPointF() matrix = QMatrix() stream >> type >> position >> matrix if offset: position += QPointF(offset, offset) if type == "Text": text = QString() font = QFont() stream >> text >> font self.scene.addItem(TextItem(text, position, font, matrix)) elif type == "Box": rect = QRectF() stream >> rect style = Qt.PenStyle(stream.readInt16()) self.scene.addItem(BoxItem(position, style, matrix)) elif type == "Pixmap": pixmap = QPixmap() stream >> pixmap self.scene.addItem(self.createPixmapItem(pixmap, position, matrix)) def writeItemToStream(self, stream, item): if isinstance(item, QGraphicsTextItem): stream << QString("Text") << item.pos() \ << item.matrix() << item.toPlainText() << item.font() elif isinstance(item, QGraphicsPixmapItem): stream << QString("Pixmap") << item.pos() \ << item.matrix() << item.pixmap() elif isinstance(item, BoxItem): stream << QString("Box") << item.pos() \ << item.matrix() << item.rect stream.writeInt16(item.style) def rotate(self): for item in self.scene.selectedItems(): item.rotate(30) def print_(self): dialog = QPrintDialog(self.printer) if dialog.exec_(): painter = QPainter(self.printer) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.TextAntialiasing) self.scene.clearSelection() #self.removeBorders() self.scene.render(painter) #self.addBorders() def open(self): self.offerSave() path = (QFileInfo(self.filename).path() if not self.filename.isEmpty() else ".") fname = QFileDialog.getOpenFileName(self, "Page Designer - Open", path, "Page Designer Files (*.pgd)") if fname.isEmpty(): return self.filename = fname fh = None try: fh = QFile(self.filename) if not fh.open(QIODevice.ReadOnly): raise IOError, unicode(fh.errorString()) items = self.scene.items() while items: item = items.pop() self.scene.removeItem(item) del item self.addBorders() stream = QDataStream(fh) stream.setVersion(QDataStream.Qt_4_2) magic = stream.readInt32() if magic != MagicNumber: raise IOError, "not a valid .pgd file" fileVersion = stream.readInt16() if fileVersion != FileVersion: raise IOError, "unrecognised .pgd file version" while not fh.atEnd(): self.readItemFromStream(stream) except IOError, e: QMessageBox.warning(self, "Page Designer -- Open Error", "Failed to open {0}: {1}".format(self.filename, e)) finally:
def paintBoundaries(tgslicesFile, zSlice, d, boundaryData, mask, filename, swapCoordinates=False, colortable=None, penWidth=4.0): print "* making boundary img '%s'" % filename #b = BoundariesLayerPy(tgslicesFile=tgslicesFile, normalAxis=2, data2scene=QTransform(), swapCoordinates=True) b = BoundariesLayer(None, 2, QTransform(), True) n = b.normalAxis() axis = None if swapCoordinates: if n == 0: axis = "z" elif n == 1: axis = "y" else: axis = "x" else: if n == 0: axis = "x" elif n == 1: axis = "y" else: axis = "z" f = h5py.File(tgslicesFile, 'r') group = "%s/%d" % (axis, zSlice) serializedBoundaries = f[group].value f.close() assert d.ndim == 2 scene = QGraphicsScene() b.setSliceNumber( zSlice ) b.setBoundaries(serializedBoundaries) b.setColormap("tyr") assert boundaryData.dtype == numpy.float32 assert mask.dtype == numpy.float32 b.setBoundaryData(boundaryData, boundaryData.size, boundaryData) b.setBoundaryMask(mask, mask.size) if colortable is not None: b.setColormap(colortable) print "setting pen width to be %f" % penWidth b.setPenWidth(float(penWidth)) print "...done" mag = 4 shape = d.shape dBig = vigra.sampling.resizeImageNoInterpolation(d.astype(numpy.float32), (mag*shape[0], mag*shape[1])) #dBig = dBig.swapaxes(0,1) qimg = qimage2ndarray.gray2qimage(dBig) #qimg = qimg.mirrored(True, False) imgItm = QGraphicsPixmapItem(QPixmap(qimg)) imgItm.setScale(1.0/mag) scene.addItem(imgItm) sourceRect = QRectF(0,0,shape[1], shape[0]) targetRect = QRectF(0,0,mag*shape[1], mag*shape[0]) scene.setSceneRect(sourceRect) scene.addItem(b) img = QImage(targetRect.width(), targetRect.height(), QImage.Format_ARGB32); painter = QPainter(img); painter.setRenderHint(QPainter.Antialiasing); scene.render(painter, targetRect, sourceRect ); img.save(filename) painter.end() #print "img has size ", img.width(), img.height() img = None painter = None scene = None
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not (self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b - 1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b + 1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert (self.pos == pos) self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001)) # move a little # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage. # We seem to get better results if we do the following: # 1) Slightly offset the source window because apparently there is a small shift in the data # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x) # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image, # applying some threshold to determine if the final pixel is on or off. tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) # Offset the source window. At first I thought the right offset was 0.5, because # that would seem to make sure points are rounded to pixel CENTERS, but # experimentation indicates that 0.25 is slightly better for some reason... source_rect = QRectF(QPointF(self.bb.x() + 0.25, self.bb.y() + 0.25), QSizeF(self.bb.width(), self.bb.height())) target_rect = QRectF(QPointF(0, 0), QSizeF(4 * self.bb.width(), 4 * self.bb.height())) self.scene.render(painter, target=target_rect, source=source_rect) painter.end() # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int) ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) + (4, )) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) + (4, )) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr //= 4 * 4 downsample_threshold = (7. / 16) * 255 labels = numpy.where(ndarr >= downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0, 1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero( labels) == 0: labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen( QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x - self.brushSize // 2 - 1))) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1))) self.bb.setBottom( max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1))) #update/move position self.pos = pos
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not (self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b - 1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b + 1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert (self.pos == pos) self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001)) # move a little tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, target=QRectF(), source=QRectF( QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height()))) painter.end() ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0] labels = numpy.where(ndarr > 0, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0, 1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero( labels) == 0: labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen( QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) #grow bounding box self.bb.setLeft(min(self.bb.left(), max(0, x - self.brushSize / 2 - 1))) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize / 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize / 2 - 1))) self.bb.setBottom( max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize / 2 + 1))) #update/move position self.pos = pos
# ready for drawable in diagram.elements(): scene.addItem(drawable) drawable.resize_scene_rect() adj_scene_rect = scene.sceneRect().adjusted(-margin, -margin, margin, margin) scene.setSceneRect(adj_scene_rect) diagramsize = adj_scene_rect.toRect().size() img = QImage(QSize(diagramsize.width() * scale, diagramsize.height() * scale), QImage.Format_ARGB32) painter = QPainter(img) print margin absoluteRect = QRectF(0, 0, scene.sceneRect().width() * scale, scene.sceneRect().height() * scale) painter.fillRect(absoluteRect, QBrush(QColor(255, 255, 255), Qt.SolidPattern)) painter.resetMatrix() scene.render(painter) painter.end() ret = img.save(output) print("Saved to " + output) for e in logger.events: print str(e) if not logger.has("ERROR CRITICAL"): return 0 else: return 1 if __name__ == "__main__": exit(main(sys.argv))
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not(self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert(self.pos == pos) self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage. # We seem to get better results if we do the following: # 1) Slightly offset the source window because apparently there is a small shift in the data # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x) # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image, # applying some threshold to determine if the final pixel is on or off. tempi = QImage(QSize(4*self.bb.width(), 4*self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) # Offset the source window. At first I thought the right offset was 0.5, because # that would seem to make sure points are rounded to pixel CENTERS, but # experimentation indicates that 0.25 is slightly better for some reason... source_rect = QRectF( QPointF(self.bb.x()+0.25, self.bb.y()+0.25), QSizeF(self.bb.width(), self.bb.height()) ) target_rect = QRectF( QPointF(0,0), QSizeF(4*self.bb.width(), 4*self.bb.height()) ) self.scene.render(painter, target=target_rect, source=source_rect) painter.end() # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0].astype(int) ndarr = ndarr.reshape( (ndarr.shape[0],) + (ndarr.shape[1]//4,) + (4,) ) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr = ndarr.reshape( (ndarr.shape[0],) + (ndarr.shape[1]//4,) + (4,) ) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr //= 4*4 downsample_threshold = (7./16)*255 labels = numpy.where(ndarr>=downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0,1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0: labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX,oldY), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize//2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize//2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize//2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize//2+1) ) ) #update/move position self.pos = pos
class DrawManager(QObject): """ DEPRECATED. Will be replaced with BrushingModel, BrushingControler, BrushStroke. """ brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black def __init__(self): QObject.__init__(self) self.shape = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self.drawnNumber = self.defaultDrawnNumber self.penVis = QPen(self.drawColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) self.penDraw = QPen(self.drawColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) self.pos = None self.erasing = False #on which layer do we want to draw when self.drawingEnabled? self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def growBoundingBox(self): self.bb.setLeft( max(0, self.bb.left()-self.brushSize-1)) self.bb.setTop( max(0, self.bb.top()-self.brushSize-1 )) self.bb.setRight( min(self.shape[0], self.bb.right()+self.brushSize+1)) self.bb.setBottom(min(self.shape[1], self.bb.bottom()+self.brushSize+1)) def toggleErase(self): self.erasing = not(self.erasing) def setErasing(self): self.erasing = True self.brushColorChanged.emit(self.erasingColor) def disableErasing(self): self.erasing = False self.brushColorChanged.emit(self.drawColor) def setBrushSize(self, size): self.brushSize = size self.penVis.setWidth(size) self.penDraw.setWidth(size) self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.penVis.setColor(color) self.emit.brushColorChanged(self.drawColor) def beginDrawing(self, pos, shape): self.shape = shape self.bb = QRectF(0, 0, self.shape[0], self.shape[1]) self.scene.clear() if self.erasing: self.penVis.setColor(self.erasingColor) else: self.penVis.setColor(self.drawColor) self.pos = QPointF(pos.x()+0.0001, pos.y()+0.0001) line = self.moveTo(pos) return line def endDrawing(self, pos): self.moveTo(pos) self.growBoundingBox() tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, QRectF(QPointF(0,0), self.bb.size()), self.bb) return (self.bb.left(), self.bb.top(), tempi) #TODO: hackish, probably return a class ?? def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.shape) return res def moveTo(self, pos): lineVis = QGraphicsLineItem(self.pos.x(), self.pos.y(), pos.x(), pos.y()) lineVis.setPen(self.penVis) line = QGraphicsLineItem(self.pos.x(), self.pos.y(), pos.x(), pos.y()) line.setPen(self.penDraw) self.scene.addItem(line) self.pos = pos x = pos.x() y = pos.y() #update bounding Box : if x > self.bb.right(): self.bb.setRight(x) if x < self.bb.left(): self.bb.setLeft(x) if y > self.bb.bottom(): self.bb.setBottom(y) if y < self.bb.top(): self.bb.setTop(y) return lineVis
class Printer(object): """For printing in diferent card formats and sizes the associated deck, be it to the screen or pdfs or image files""" card_sizes = {"Jumbo":(3.5,5.5), "Tarot":(2.75,4.75), "Square":(3.5,3.5), "Poker":(2.5,3.5), "Bridge":(2.25,3.5), "Biz":(2,3.5), "Mini":(1.75,2.5), "Micro":(1.25,1.75)} paper_sizes = {"A0":(33.1,46.8), "A1":(23.4,33.1), "A2":(16.5,23.4), "A3":(11.7,16.5), "A4":(8.3,11.7), "A5":(5.8,8.3), "A6":(4.1,5.8)} #TODO paper margins when printing and centering the images def __init__(self, deck=None): self.deck = deck self.scene = QGraphicsScene() self.orientation = getattr(QPrinter, "Portrait") self.path = "output.pdf" self.paper = getattr(QPrinter, "A4") self.card_size = Printer.card_sizes["Poker"] def config(self, *args, **kwargs): """kwargs: deck, card_size, paper_size, orientation, print_path if card_size is present I have to join the elements of the deck following the premises""" if "orientation" in kwargs: self.orientation = kwargs["orientation"] if "card_size" in kwargs: self.card_size = Printer.card_sizes[kwargs["card_size"][:kwargs["card_size"].find(" ")]] if "print_path" in kwargs: self.path = kwargs["print_path"] if "paper_size" in kwargs: self.paper = kwargs["paper_size"] if "deck" in kwargs: self.deck = kwargs["deck"] def print_grid(self): if self.deck is not None: #Setting the printer printer = QPrinter(QPrinter.HighResolution) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(getattr(QPrinter, self.orientation)) printer.setOutputFileName(self.path) printer.setPaperSize(getattr(QPrinter, self.paper)) #Start printing with QPainter(printer) as paint: first = True for c in self.deck: if not first: printer.newPage() first = False self.preview_card(c) self.scene.render(paint) def max_cards(self): """Taking in count the card_size, paper_size returns the max number of cards per page, horientation and margins""" port = {} port["orientation"] = "Portrait" pw = self.paper_sizes[self.paper][0] ph = self.paper_sizes[self.paper][1] port["horizontal"] = int(pw//self.card_size[0]) port["vertical"] = int(ph//self.card_size[1]) port["max"] = port["horizontal"] * port["vertical"] port["margin_horizontal"] = (pw % self.card_size[0]) / 2.0 port["margin_vertical"] = (ph % self.card_size[1]) / 2.0 land = {} land["orientation"] = "Landscape" pw = self.paper_sizes[self.paper][1] ph = self.paper_sizes[self.paper][0] land["horizontal"] = int(pw//self.card_size[0]) land["vertical"] = int(ph//self.card_size[1]) land["max"] = land["horizontal"] * land["vertical"] land["margin_horizontal"] = (pw % self.card_size[0]) / 2.0 land["margin_vertical"] = (ph % self.card_size[1]) / 2.0 if land["max"] > port["max"]: return land else: return port def print_pdf(self): if self.deck is not None: #Setting the printer printer = QPrinter(QPrinter.HighResolution) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(getattr(QPrinter, "Portrait")) printer.setOutputFileName(self.path) printer.setPaperSize(getattr(QPrinter, self.paper)) printer.setFullPage(True) guide = self.max_cards() printer.setOrientation(getattr(QPrinter, guide["orientation"])) print guide, self.card_size #Start printing with QPainter(printer) as paint: ind = 0 resol = printer.resolution() for c in self.deck: c.resize(self.card_size[0], self.card_size[1]) if ind == guide["max"]: printer.newPage() ind = 0 col = ind % guide["horizontal"] fil = ind // guide["horizontal"] print ind, fil, col target = QRectF((col)*self.card_size[0]*resol, (fil)*self.card_size[1]*resol, self.card_size[0]*resol, self.card_size[1]*resol) self.preview_card(c) self.scene.render(paint, target=target, source=QRectF(0,0,c.width(),c.height())) ind += 1 def save_images(self): if self.deck is not None: num = 1 for c in self.deck: c.save_as("".join([str(self.path),str(num),".",c.format()])) num += 1 def preview_card(self, card): try: self.scene.clear() ret = self.scene.addPixmap(card.pixmap()) except: self.scene.clear() ret = self.scene.addText("Image not available") return ret