Esempio n. 1
0
def cellsInRegion(list, r):
    cells = QVector()
    for tilelayer in list:
        for rect in r.rects():
            for x in range(rect.left(), rect.right() + 1):
                for y in range(rect.top(), rect.bottom() + 1):
                    cell = tilelayer.cellAt(x, y)
                    if (not cells.contains(cell)):
                        cells.append(cell)

    return cells
Esempio n. 2
0
def cellsInRegion(list, r):
    cells = QVector()
    for tilelayer in list:
        for rect in r.rects():
            for x in range(rect.left(), rect.right()+1):
                for y in range(rect.top(), rect.bottom()+1):
                    cell = tilelayer.cellAt(x, y)
                    if (not cells.contains(cell)):
                        cells.append(cell)

    return cells
Esempio n. 3
0
class TileStampManager(QObject):
    setStamp = pyqtSignal(TileStamp)

    def __init__(self, toolManager, parent=None):
        super().__init__(parent)

        self.mStampsByName = QMap()
        self.mQuickStamps = QVector()
        for i in range(TileStampManager.quickStampKeys().__len__()):
            self.mQuickStamps.append(0)

        self.mTileStampModel = TileStampModel(self)
        self.mToolManager = toolManager

        prefs = preferences.Preferences.instance()
        prefs.stampsDirectoryChanged.connect(self.stampsDirectoryChanged)
        self.mTileStampModel.stampAdded.connect(self.stampAdded)
        self.mTileStampModel.stampRenamed.connect(self.stampRenamed)
        self.mTileStampModel.stampChanged.connect(self.saveStamp)
        self.mTileStampModel.stampRemoved.connect(self.deleteStamp)
        self.loadStamps()

    def __del__(self):
        # needs to be over here where the TileStamp type is complete
        pass

    ##
    # Returns the keys used for quickly accessible tile stamps.
    # Note: To store a tile layer <Ctrl> is added. The given keys will work
    # for recalling the stored values.
    ##
    def quickStampKeys():
        keys = [
            Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5, Qt.Key_6,
            Qt.Key_7, Qt.Key_8, Qt.Key_9
        ]
        return keys

    def tileStampModel(self):
        return self.mTileStampModel

    def createStamp(self):
        stamp = self.tampFromContext(self.mToolManager.selectedTool())
        if (not stamp.isEmpty()):
            self.mTileStampModel.addStamp(stamp)
        return stamp

    def addVariation(self, targetStamp):
        stamp = stampFromContext(self.mToolManager.selectedTool())
        if (stamp.isEmpty()):
            return
        if (stamp == targetStamp):  # avoid easy mistake of adding duplicates
            return
        for variation in stamp.variations():
            self.mTileStampModel.addVariation(targetStamp, variation)

    def selectQuickStamp(self, index):
        stamp = self.mQuickStamps.at(index)
        if (not stamp.isEmpty()):
            self.setStamp.emit(stamp)

    def createQuickStamp(self, index):
        stamp = stampFromContext(self.mToolManager.selectedTool())
        if (stamp.isEmpty()):
            return
        self.setQuickStamp(index, stamp)

    def extendQuickStamp(self, index):
        quickStamp = self.mQuickStamps[index]
        if (quickStamp.isEmpty()):
            self.createQuickStamp(index)
        else:
            self.addVariation(quickStamp)

    def stampsDirectoryChanged(self):
        # erase current stamps
        self.mQuickStamps.fill(TileStamp())
        self.mStampsByName.clear()
        self.mTileStampModel.clear()
        self.loadStamps()

    def eraseQuickStamp(self, index):
        stamp = self.mQuickStamps.at(index)
        if (not stamp.isEmpty()):
            self.mQuickStamps[index] = TileStamp()
            if (not self.mQuickStamps.contains(stamp)):
                self.mTileStampModel.removeStamp(stamp)

    def setQuickStamp(self, index, stamp):
        stamp.setQuickStampIndex(index)
        # make sure existing quickstamp is removed from stamp model
        self.eraseQuickStamp(index)
        self.mTileStampModel.addStamp(stamp)
        self.mQuickStamps[index] = stamp

    def loadStamps(self):
        prefs = preferences.Preferences.instance()
        stampsDirectory = prefs.stampsDirectory()
        stampsDir = QDir(stampsDirectory)
        iterator = QDirIterator(stampsDirectory, ["*.stamp"],
                                QDir.Files | QDir.Readable)
        while (iterator.hasNext()):
            stampFileName = iterator.next()
            stampFile = QFile(stampFileName)
            if (not stampFile.open(QIODevice.ReadOnly)):
                continue
            data = stampFile.readAll()
            document = QJsonDocument.fromBinaryData(data)
            if (document.isNull()):
                # document not valid binary data, maybe it's an JSON text file
                error = QJsonParseError()
                document = QJsonDocument.fromJson(data, error)
                if (error.error != QJsonParseError.NoError):
                    qDebug("Failed to parse stamp file:" + error.errorString())
                    continue

            stamp = TileStamp.fromJson(document.object(), stampsDir)
            if (stamp.isEmpty()):
                continue
            stamp.setFileName(iterator.fileInfo().fileName())
            self.mTileStampModel.addStamp(stamp)
            index = stamp.quickStampIndex()
            if (index >= 0 and index < self.mQuickStamps.size()):
                self.mQuickStamps[index] = stamp

    def stampAdded(self, stamp):
        if (stamp.name().isEmpty()
                or self.mStampsByName.contains(stamp.name())):
            # pick the first available stamp name
            name = QString()
            index = self.mTileStampModel.stamps().size()
            while (self.mStampsByName.contains(name)):
                name = str(index)
                index += 1

            stamp.setName(name)

        self.mStampsByName.insert(stamp.name(), stamp)
        if (stamp.fileName().isEmpty()):
            stamp.setFileName(findStampFileName(stamp.name()))
            self.saveStamp(stamp)

    def stampRenamed(self, stamp):
        existingName = self.mStampsByName.key(stamp)
        self.mStampsByName.remove(existingName)
        self.mStampsByName.insert(stamp.name(), stamp)
        existingFileName = stamp.fileName()
        newFileName = findStampFileName(stamp.name(), existingFileName)
        if (existingFileName != newFileName):
            if (QFile.rename(stampFilePath(existingFileName),
                             stampFilePath(newFileName))):
                stamp.setFileName(newFileName)

    def saveStamp(self, stamp):
        # make sure we have a stamps directory
        prefs = preferences.Preferences.instance()
        stampsDirectory = prefs.stampsDirectory()
        stampsDir = QDir(stampsDirectory)
        if (not stampsDir.exists() and not stampsDir.mkpath(".")):
            qDebug("Failed to create stamps directory" + stampsDirectory)
            return

        filePath = stampsDir.filePath(stamp.fileName())
        file = QSaveFile(filePath)
        if (not file.open(QIODevice.WriteOnly)):
            qDebug("Failed to open stamp file for writing" + filePath)
            return

        stampJson = stamp.toJson(QFileInfo(filePath).dir())
        file.write(QJsonDocument(stampJson).toJson(QJsonDocument.Compact))
        if (not file.commit()):
            qDebug() << "Failed to write stamp" << filePath

    def deleteStamp(self, stamp):
        self.mStampsByName.remove(stamp.name())
        QFile.remove(stampFilePath(stamp.fileName()))
Esempio n. 4
0
def compareLayerTo(setLayer, listYes, listNo, ruleRegion, offset):
    if (listYes.isEmpty() and listNo.isEmpty()):
        return False
    cells = QVector()
    if (listYes.isEmpty()):
        cells = cellsInRegion(listNo, ruleRegion)
    if (listNo.isEmpty()):
        cells = cellsInRegion(listYes, ruleRegion)
    for rect in ruleRegion.rects():
        for x in range(rect.left(), rect.right() + 1):
            for y in range(rect.top(), rect.bottom() + 1):
                # this is only used in the case where only one list has layers
                # it is needed for the exception mentioned above
                ruleDefinedListYes = False
                matchListYes = False
                matchListNo = False
                if (not setLayer.contains(x + offset.x(), y + offset.y())):
                    return False
                c1 = setLayer.cellAt(x + offset.x(), y + offset.y())
                # ruleDefined will be set when there is a tile in at least
                # one layer. if there is a tile in at least one layer, only
                # the given tiles in the different listYes layers are valid.
                # if there is given no tile at all in the listYes layers,
                # consider all tiles valid.
                for comparedTileLayer in listYes:
                    if (not comparedTileLayer.contains(x, y)):
                        return False
                    c2 = comparedTileLayer.cellAt(x, y)
                    if (not c2.isEmpty()):
                        ruleDefinedListYes = True
                    if (not c2.isEmpty() and c1 == c2):
                        matchListYes = True

                for comparedTileLayer in listNo:
                    if (not comparedTileLayer.contains(x, y)):
                        return False
                    c2 = comparedTileLayer.cellAt(x, y)
                    if (not c2.isEmpty() and c1 == c2):
                        matchListNo = True

                # when there are only layers in the listNo
                # check only if these layers are unmatched
                # no need to check explicitly the exception in this case.
                if (listYes.isEmpty()):
                    if (matchListNo):
                        return False
                    else:
                        continue

                # when there are only layers in the listYes
                # check if these layers are matched, or if the exception works
                if (listNo.isEmpty()):
                    if (matchListYes):
                        continue
                    if (not ruleDefinedListYes and not cells.contains(c1)):
                        continue
                    return False

                # there are layers in both lists:
                # no need to consider ruleDefinedListXXX
                if ((matchListYes or not ruleDefinedListYes)
                        and not matchListNo):
                    continue
                else:
                    return False

    return True
Esempio n. 5
0
class TileStampManager(QObject):
    setStamp = pyqtSignal(TileStamp)

    def __init__(self, toolManager, parent = None):
        super().__init__(parent)
        
        self.mStampsByName = QMap()
        self.mQuickStamps = QVector()
        for i in range(TileStampManager.quickStampKeys().__len__()):
            self.mQuickStamps.append(0)
        
        self.mTileStampModel = TileStampModel(self)
        self.mToolManager = toolManager

        prefs = preferences.Preferences.instance()
        prefs.stampsDirectoryChanged.connect(self.stampsDirectoryChanged)
        self.mTileStampModel.stampAdded.connect(self.stampAdded)
        self.mTileStampModel.stampRenamed.connect(self.stampRenamed)
        self.mTileStampModel.stampChanged.connect(self.saveStamp)
        self.mTileStampModel.stampRemoved.connect(self.deleteStamp)
        self.loadStamps()

    def __del__(self):
        # needs to be over here where the TileStamp type is complete
        pass
        
    ##
    # Returns the keys used for quickly accessible tile stamps.
    # Note: To store a tile layer <Ctrl> is added. The given keys will work
    # for recalling the stored values.
    ##
    def quickStampKeys():
        keys=[Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5, Qt.Key_6, Qt.Key_7, Qt.Key_8, Qt.Key_9]
        return keys
        
    def tileStampModel(self):
        return self.mTileStampModel
        
    def createStamp(self):
        stamp = self.tampFromContext(self.mToolManager.selectedTool())
        if (not stamp.isEmpty()):
            self.mTileStampModel.addStamp(stamp)
        return stamp
    
    def addVariation(self, targetStamp):
        stamp = stampFromContext(self.mToolManager.selectedTool())
        if (stamp.isEmpty()):
            return
        if (stamp == targetStamp): # avoid easy mistake of adding duplicates
            return
        for variation in stamp.variations():
            self.mTileStampModel.addVariation(targetStamp, variation)

    def selectQuickStamp(self, index):
        stamp = self.mQuickStamps.at(index)
        if (not stamp.isEmpty()):
            self.setStamp.emit(stamp)
    
    def createQuickStamp(self, index):
        stamp = stampFromContext(self.mToolManager.selectedTool())
        if (stamp.isEmpty()):
            return
        self.setQuickStamp(index, stamp)
    
    def extendQuickStamp(self, index):
        quickStamp = self.mQuickStamps[index]
        if (quickStamp.isEmpty()):
            self.createQuickStamp(index)
        else:
            self.addVariation(quickStamp)
    
    def stampsDirectoryChanged(self):
        # erase current stamps
        self.mQuickStamps.fill(TileStamp())
        self.mStampsByName.clear()
        self.mTileStampModel.clear()
        self.loadStamps()

    def eraseQuickStamp(self, index):
        stamp = self.mQuickStamps.at(index)
        if (not stamp.isEmpty()):
            self.mQuickStamps[index] = TileStamp()
            if (not self.mQuickStamps.contains(stamp)):
                self.mTileStampModel.removeStamp(stamp)

    def setQuickStamp(self, index, stamp):
        stamp.setQuickStampIndex(index)
        # make sure existing quickstamp is removed from stamp model
        self.eraseQuickStamp(index)
        self.mTileStampModel.addStamp(stamp)
        self.mQuickStamps[index] = stamp
    
    def loadStamps(self):
        prefs = preferences.Preferences.instance()
        stampsDirectory = prefs.stampsDirectory()
        stampsDir = QDir(stampsDirectory)
        iterator = QDirIterator(stampsDirectory,
                              ["*.stamp"],
                              QDir.Files | QDir.Readable)
        while (iterator.hasNext()):
            stampFileName = iterator.next()
            stampFile = QFile(stampFileName)
            if (not stampFile.open(QIODevice.ReadOnly)):
                continue
            data = stampFile.readAll()
            document = QJsonDocument.fromBinaryData(data)
            if (document.isNull()):
                # document not valid binary data, maybe it's an JSON text file
                error = QJsonParseError()
                document = QJsonDocument.fromJson(data, error)
                if (error.error != QJsonParseError.NoError):
                    qDebug("Failed to parse stamp file:" + error.errorString())
                    continue

            stamp = TileStamp.fromJson(document.object(), stampsDir)
            if (stamp.isEmpty()):
                continue
            stamp.setFileName(iterator.fileInfo().fileName())
            self.mTileStampModel.addStamp(stamp)
            index = stamp.quickStampIndex()
            if (index >= 0 and index < self.mQuickStamps.size()):
                self.mQuickStamps[index] = stamp


    def stampAdded(self, stamp):
        if (stamp.name().isEmpty() or self.mStampsByName.contains(stamp.name())):
            # pick the first available stamp name
            name = QString()
            index = self.mTileStampModel.stamps().size()
            while(self.mStampsByName.contains(name)):
                name = str(index)
                index += 1
            
            stamp.setName(name)
        
        self.mStampsByName.insert(stamp.name(), stamp)
        if (stamp.fileName().isEmpty()):
            stamp.setFileName(findStampFileName(stamp.name()))
            self.saveStamp(stamp)

    def stampRenamed(self, stamp):
        existingName = self.mStampsByName.key(stamp)
        self.mStampsByName.remove(existingName)
        self.mStampsByName.insert(stamp.name(), stamp)
        existingFileName = stamp.fileName()
        newFileName = findStampFileName(stamp.name(), existingFileName)
        if (existingFileName != newFileName):
            if (QFile.rename(stampFilePath(existingFileName),
                              stampFilePath(newFileName))):
                stamp.setFileName(newFileName)

    
    def saveStamp(self, stamp):
        # make sure we have a stamps directory
        prefs = preferences.Preferences.instance()
        stampsDirectory = prefs.stampsDirectory()
        stampsDir = QDir(stampsDirectory)
        if (not stampsDir.exists() and not stampsDir.mkpath(".")):
            qDebug("Failed to create stamps directory" + stampsDirectory)
            return
        
        filePath = stampsDir.filePath(stamp.fileName())
        file = QSaveFile(filePath)
        if (not file.open(QIODevice.WriteOnly)):
            qDebug("Failed to open stamp file for writing" + filePath)
            return
        
        stampJson = stamp.toJson(QFileInfo(filePath).dir())
        file.write(QJsonDocument(stampJson).toJson(QJsonDocument.Compact))
        if (not file.commit()):
            qDebug() << "Failed to write stamp" << filePath
    
    def deleteStamp(self, stamp):
        self.mStampsByName.remove(stamp.name())
        QFile.remove(stampFilePath(stamp.fileName()))
Esempio n. 6
0
def compareLayerTo(setLayer, listYes, listNo, ruleRegion, offset):
    if (listYes.isEmpty() and listNo.isEmpty()):
        return False
    cells = QVector()
    if (listYes.isEmpty()):
        cells = cellsInRegion(listNo, ruleRegion)
    if (listNo.isEmpty()):
        cells = cellsInRegion(listYes, ruleRegion)
    for rect in ruleRegion.rects():
        for x in range(rect.left(), rect.right()+1):
            for y in range(rect.top(), rect.bottom()+1):
                # this is only used in the case where only one list has layers
                # it is needed for the exception mentioned above
                ruleDefinedListYes = False
                matchListYes = False
                matchListNo  = False
                if (not setLayer.contains(x + offset.x(), y + offset.y())):
                    return False
                c1 = setLayer.cellAt(x + offset.x(),
                                                  y + offset.y())
                # ruleDefined will be set when there is a tile in at least
                # one layer. if there is a tile in at least one layer, only
                # the given tiles in the different listYes layers are valid.
                # if there is given no tile at all in the listYes layers,
                # consider all tiles valid.
                for comparedTileLayer in listYes:
                    if (not comparedTileLayer.contains(x, y)):
                        return False
                    c2 = comparedTileLayer.cellAt(x, y)
                    if (not c2.isEmpty()):
                        ruleDefinedListYes = True
                    if (not c2.isEmpty() and c1 == c2):
                        matchListYes = True

                for comparedTileLayer in listNo:
                    if (not comparedTileLayer.contains(x, y)):
                        return False
                    c2 = comparedTileLayer.cellAt(x, y)
                    if (not c2.isEmpty() and c1 == c2):
                        matchListNo = True

                # when there are only layers in the listNo
                # check only if these layers are unmatched
                # no need to check explicitly the exception in this case.
                if (listYes.isEmpty()):
                    if (matchListNo):
                        return False
                    else:
                        continue

                # when there are only layers in the listYes
                # check if these layers are matched, or if the exception works
                if (listNo.isEmpty()):
                    if (matchListYes):
                        continue
                    if (not ruleDefinedListYes and not cells.contains(c1)):
                        continue
                    return False

                # there are layers in both lists:
                # no need to consider ruleDefinedListXXX
                if ((matchListYes or not ruleDefinedListYes) and not matchListNo):
                    continue
                else:
                    return False

    return True