CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
Exporter.py142 linesDownload Raw Back to exporters
1import os2import re3 4from ..GraphicsScene import GraphicsScene5from ..Qt import QtCore, QtWidgets6from ..widgets.FileDialog import FileDialog7 8LastExportDirectory = None9 10 11class Exporter(object):12    """13    Abstract class used for exporting graphics to file / printer / whatever.14    """    15    allowCopy = False  # subclasses set this to True if they can use the copy buffer16    Exporters = []17    18    @classmethod19    def register(cls):20        """21        Used to register Exporter classes to appear in the export dialog.22        """23        Exporter.Exporters.append(cls)24    25    def __init__(self, item):26        """27        Initialize with the item to be exported.28        Can be an individual graphics item or a scene.29        """30        object.__init__(self)31        self.item = item32        33    def parameters(self):34        """Return the parameters used to configure this exporter."""35        raise Exception("Abstract method must be overridden in subclass.")36        37    def export(self, fileName=None, toBytes=False, copy=False):38        """39        If *fileName* is None, pop-up a file dialog.40        If *toBytes* is True, return a bytes object rather than writing to file.41        If *copy* is True, export to the copy buffer rather than writing to file.42        """43        raise Exception("Abstract method must be overridden in subclass.")44 45    def fileSaveDialog(self, filter=None, opts=None):46        ## Show a file dialog, call self.export(fileName) when finished.47        if opts is None:48            opts = {}49        self.fileDialog = FileDialog()50        self.fileDialog.setFileMode(QtWidgets.QFileDialog.FileMode.AnyFile)51        self.fileDialog.setAcceptMode(QtWidgets.QFileDialog.AcceptMode.AcceptSave)52        if filter is not None:53            if isinstance(filter, str):54                self.fileDialog.setNameFilter(filter)55            elif isinstance(filter, list):56                self.fileDialog.setNameFilters(filter)57        global LastExportDirectory58        exportDir = LastExportDirectory59        if exportDir is not None:60            self.fileDialog.setDirectory(exportDir)61        self.fileDialog.show()62        self.fileDialog.opts = opts63        self.fileDialog.fileSelected.connect(self.fileSaveFinished)64        return65        66    def fileSaveFinished(self, fileName):67        global LastExportDirectory68        LastExportDirectory = os.path.split(fileName)[0]69        70        ## If file name does not match selected extension, append it now71        ext = os.path.splitext(fileName)[1].lower().lstrip('.')72        selectedExt = re.search(r'\*\.(\w+)\b', self.fileDialog.selectedNameFilter())73        if selectedExt is not None:74            selectedExt = selectedExt.groups()[0].lower()75            if ext != selectedExt:76                fileName = fileName + '.' + selectedExt.lstrip('.')77        78        self.export(fileName=fileName, **self.fileDialog.opts)79        80    def getScene(self):81        if isinstance(self.item, GraphicsScene):82            return self.item83        else:84            return self.item.scene()85        86    def getSourceRect(self):87        if isinstance(self.item, GraphicsScene):88            w = self.item.getViewWidget()89            return w.viewportTransform().inverted()[0].mapRect(w.rect())90        else:91            return self.item.sceneBoundingRect()92        93    def getTargetRect(self):        94        if isinstance(self.item, GraphicsScene):95            return self.item.getViewWidget().rect()96        else:97            return self.item.mapRectToDevice(self.item.boundingRect())98        99    def setExportMode(self, export, opts=None):100        """101        Call setExportMode(export, opts) on all items that will 102        be painted during the export. This informs the item103        that it is about to be painted for export, allowing it to 104        alter its appearance temporarily105        106        107        *export*  - bool; must be True before exporting and False afterward108        *opts*    - dict; common parameters are 'antialias' and 'background'109        """110        if opts is None:111            opts = {}112        for item in self.getPaintItems():113            if hasattr(item, 'setExportMode'):114                item.setExportMode(export, opts)115    116    def getPaintItems(self, root=None):117        """Return a list of all items that should be painted in the correct order."""118        if root is None:119            root = self.item120        preItems = []121        postItems = []122        if isinstance(root, QtWidgets.QGraphicsScene):123            childs = [i for i in root.items() if i.parentItem() is None]124            rootItem = []125        else:126            childs = root.childItems()127            rootItem = [root]128        childs.sort(key=lambda a: a.zValue())129        while len(childs) > 0:130            ch = childs.pop(0)131            tree = self.getPaintItems(ch)132            if (ch.flags() & ch.GraphicsItemFlag.ItemStacksBehindParent) or \133               (ch.zValue() < 0 and (ch.flags() & ch.GraphicsItemFlag.ItemNegativeZStacksBehindParent)):134                preItems.extend(tree)135            else:136                postItems.extend(tree)137                138        return preItems + rootItem + postItems139 140    def render(self, painter, targetRect, sourceRect, item=None):141        self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))142 
Aluode/PerceptionLabPortable · CoolFace