Ejemplo n.º 1
0
def GetSaveFiles(folder: Path) -> List[Tuple[str, Path]]:
    """ Finds all save files recursively, grouped by the
    subfolder relative to the `folder` input.

    Returns a list of tuples joining each save file with the
    subfolder it belongs to.
        [
            (subfolder1name, path/to/save/file/1/in/sub/1)
            (subfolder1name, path/to/save/file/2/in/sub/1)
            (subfolder2name, path/to/save/file/1/in/sub/2)
            (subfolder2name, path/to/save/file/2/in/sub/2)
        ]
    """
    markedFolderMatchString = config.markedImageFolderName
    subfolders = [f for f in os.scandir(folder) if f.is_dir()]
    saveFiles = []
    for dirname in list(subfolders):
        allfolders = fast_scandir(dirname)
        markedFolders = [
            d for d in allfolders if d.name == markedFolderMatchString
        ]
        for markedFolder in markedFolders:
            saveFile = config.markedDataFile(
                transectFolder=Path(markedFolder).parent)
            if saveFile.exists():
                saveFiles.append((dirname.name, saveFile))
    return saveFiles
Ejemplo n.º 2
0
    def transectData(self):
        """ Computes the transect save data and returns it. **Unused** """
        if len(self._changedIndexes) == 0:
            return

        # If the save file doesn't exist, initialize empty.
        transectPath = config.markedDataFile(transectFolder=self._folder())
        if transectPath.exists():
            saveData = TransectData.load(transectPath)
        else:
            saveData = TransectData({}, fp=transectPath)

        # Only save files that have changed
        for index in self._changedIndexes:

            # If this index is None, i.e., was already taken care of
            # by a previous index (part of same overall image), continue
            # to next index.
            if index is None:
                continue

            # Retreive the path of the original image, and find
            # the indexes of the images that also correspond
            # to that path.
            originalPath: Path = self.data(index, role=UserRoles.ImagePath)
            indexes = self.matchPath(originalPath)

            # Now that we have all the indexes associated with this
            # path, we no longer need them in "changedIndexes"
            for idx in indexes:
                try:
                    num = self._changedIndexes.index(idx)
                except ValueError:
                    pass
                else:
                    self._changedIndexes[num] = None

            # Merge the indexes togther, create a preview image
            mergedIndexes = MergedIndexes(indexes)
            _ = mergedIndexes.resultantImage()

            # Merge drawn items and draw them onto the image
            drawings = mergedIndexes.drawnItems()
            if drawings is not None:

                # We should only save these drawings if they aren't already saved.
                if not saveData.imageHasDrawings(originalPath.name, drawings):
                    saveData.addDrawings(originalPath.name, drawings)

            else:
                saveData.removeDrawings(originalPath.name)

        # Return the transect data
        return saveData
Ejemplo n.º 3
0
    def readDirectory(self, fp):
        """ Populates model from directory. `fp`: any Path()-able type"""
        self._parentDir = str(fp)
        fp = Path(fp)

        # Error checks
        if not fp.exists():
            raise ValueError(
                f"Cannot read data from path that does not exist: {fp}")
        if not fp.is_dir():
            raise ValueError(f"Can only read from dir, not file: {fp}")

        # If the .marked/ folder exists, this is a single transect
        if config.markedFolder(transectFolder=fp).exists():

            self.inTransect = True

            # If the save file exists, read it
            saveFile = config.markedDataFile(transectFolder=fp)
            if saveFile.exists():
                saveDatas = TransectDataGroupList([])
                saveDatas.load(saveFile)
                self._resetData(saveDatas)
            else:
                self._resetData(TransectDataGroupList())

        # Otherwise, try to find all .marked/ folders within this dir
        else:

            self.inTransect = False

            filesToLoad: List[Tuple[str, Path]] = GetSaveFiles(fp)
            if filesToLoad:
                newTransectDataGroupList = self._loadFiles(filesToLoad)
            else:
                newTransectDataGroupList = TransectDataGroupList([])
            self._resetData(newTransectDataGroupList)
Ejemplo n.º 4
0
    def _readSaveData(self):
        """
        Reads in save data, if it can be found.
        Save file specified in Config().
        """

        # Nothing to read if there are no images
        if len(self._images) == 0:
            return

        # Generate the save path
        originalFolder = self._folder()
        savePath = config.markedDataFile(transectFolder=originalFolder)

        # If the path doesn't exist, don't try to load anything
        if not savePath.is_file():
            return

        # Load save data
        saveData = TransectData.load(savePath)
        for imageName, drawings in saveData.drawings():

            # Merge indexes that compose this file, and
            # set the drawings to the merged set.
            indexes = self.matchPath(originalFolder / imageName)

            if not indexes:
                print(f"Warning: bad save file -- {imageName} not found.")
            else:
                mergedIndexes = MergedIndexes(indexes)
                mergedIndexes.setModelDrawings(self, drawings)

                # Since we just read in new data and will have changed
                # the indexes as a part of that, we should note that
                # these indexes actually don't have to be saved again.
                self._changedIndexes = []
Ejemplo n.º 5
0
    def save(self):
        """
        Save changes made to the images. This involves:
        * Writing drawing data to a file
        * Saving the marked up image to a file
        """

        if len(self._changedIndexes) == 0:
            return

        # Setup save directory files and folders
        markedFolder = config.markedFolder(transectFolder=self._folder())
        markedFolder.mkdir(exist_ok=True)

        transectPath = config.markedDataFile(transectFolder=self._folder())
        transectPath.parent.mkdir(exist_ok=True)

        if transectPath.exists():
            # Initialize save data from old data path
            saveData = TransectData.load(transectPath)
        else:
            transectPath.touch()
            saveData = TransectData({}, fp=transectPath)

        # List of images to be saved and the `save` arguments
        # [(image, ['C:/Photos/myFavoriteImage.jpg']), ]
        markedImages = []

        # Only save files that have changed
        for index in self._changedIndexes:

            # If this index is None, i.e., was already taken care of
            # by a previous index (part of same overall image), continue
            # to next index.
            if index is None:
                continue

            # Retreive the path of the original image, and find
            # the indexes of the images that also correspond
            # to that path.
            originalPath: Path = self.data(index, role=UserRoles.ImagePath)
            indexes = self.matchPath(originalPath)

            # Now that we have all the indexes associated with this
            # path, we no longer need them in "changedIndexes".
            # Setting them to None will cause them to be skipped higher
            # in the loop
            for idx in indexes:
                try:
                    num = self._changedIndexes.index(idx)
                except ValueError:
                    pass
                else:
                    self._changedIndexes[num] = None

            # Merge the indexes togther, create a preview image
            mergedIndexes = MergedIndexes(indexes)
            preview = mergedIndexes.resultantImage()

            # Form the new path (./.marked/Alpha_001.JPG)
            markedPath = markedFolder / originalPath.name

            # Merge drawn items and draw them onto the image
            drawings: DrawingDataList = mergedIndexes.drawnItems()
            if not drawings.isEmpty():

                # We should only save these drawings if they aren't
                # already saved.
                if not saveData.imageHasDrawings(originalPath.name, drawings):

                    # Add this image to the list of images
                    # to save and add the drawn item string to the save data
                    drawings.paintToDevice(preview)
                    markedImages.append((preview, [str(markedPath)]))
                    saveData.addDrawings(originalPath.name, drawings)

            # If there are no drawings, we should delete the image
            # from the marked folder. (If applicable.)
            else:
                try:
                    markedPath.unlink()
                except FileNotFoundError:
                    pass
                finally:
                    # Ensure that there are no drawings saved alongside
                    # this image (in particular, if the drawings already
                    # existed, we need to delete them)
                    saveData.removeDrawings(originalPath.name)

        # Save & emit the transect data
        saveData.dump(transectPath)
        self.transectDataChanged.emit(saveData)

        # Clear the changed index list
        self._changedIndexes = []

        # On another thread, do the heavily-lifing of
        # saving the images.
        if len(markedImages) != 1:
            msg = f"Saving {len(markedImages)} images..."
        else:
            msg = f"Saving {Path(*markedImages[0][1]).name}..."
        self.message.emit((msg,))
        self._saveWorker = QWorker(saveManyImages, [markedImages])
        self._saveWorker.signals.finished.connect(self._resetSaveWorker)
        self._saveWorker.signals.finished.connect(self._saveWorkerFinished)
        self._threadpool.start(self._saveWorker)