def _listed_contents(self, archive, files): if not self.file_loading: return self.file_loading = False files = self._extractor.get_files() archive_images = [image for image in files if self._image_re.search(image) # Remove MacOS meta files from image list and not u'__MACOSX' in os.path.normpath(image).split(os.sep)] self._sort_archive_images(archive_images) image_files = [ os.path.join(self._tmp_dir, f) for f in archive_images ] comment_files = filter(self._comment_re.search, files) tools.alphanumeric_sort(comment_files) self._comment_files = [ os.path.join(self._tmp_dir, f) for f in comment_files ] self._name_table = dict(zip(image_files, archive_images)) self._name_table.update(zip(self._comment_files, comment_files)) self._extractor.set_files(archive_images + comment_files) self._archive_opened(image_files)
def _listed_contents(self, archive, files): if not self.file_loading: return self.file_loading = False files = self._extractor.get_files() archive_images = [ image for image in files if image_tools.is_image_file(image) # Remove MacOS meta files from image list and not '__MACOSX' in os.path.normpath(image).split(os.sep) ] self._sort_archive_images(archive_images) image_files = [os.path.join(self._tmp_dir, f) for f in archive_images] comment_files = list(filter(self._comment_re.search, files)) tools.alphanumeric_sort(comment_files) self._comment_files = [ os.path.join(self._tmp_dir, f) for f in comment_files ] self._name_table = dict(zip(image_files, archive_images)) self._name_table.update(zip(self._comment_files, comment_files)) self._extractor.set_files(archive_images + comment_files) self._archive_opened(image_files)
def _guess_cover(self, files): """Return the filename within <files> that is the most likely to be the cover of an archive using some simple heuristics. """ # Ignore MacOSX meta files. files = itertools.ifilter(lambda filename: u'__MACOSX' not in os.path.normpath(filename).split(os.sep), files) # Ignore credit files if possible. files = itertools.ifilter(lambda filename: u'credit' not in os.path.split(filename)[1].lower(), files) images = list(itertools.ifilter(constants.SUPPORTED_IMAGE_REGEX.search, files)) tools.alphanumeric_sort(images) front_re = re.compile('(cover|front)', re.I) candidates = filter(front_re.search, images) candidates = [c for c in candidates if 'back' not in c.lower()] if candidates: return candidates[0] if images: return images[0] return None
def _guess_cover(self, files): '''Return the filename within <files> that is the most likely to be the cover of an archive using some simple heuristics. ''' # Ignore MacOSX meta files. files = filter( lambda filename: '__MACOSX' not in os.path.normpath(filename). split(os.sep), files) # Ignore credit files if possible. files = filter( lambda filename: 'credit' not in os.path.split(filename)[1].lower( ), files) images = [f for f in files if image_tools.is_image_file(f)] tools.alphanumeric_sort(images) front_re = re.compile('(cover|front)', re.I) candidates = filter(front_re.search, images) candidates = [c for c in candidates if 'back' not in c.lower()] if candidates: return candidates[0] if images: return images[0] return None
def _guess_cover(self, files): """Return the filename within <files> that is the most likely to be the cover of an archive using some simple heuristics. """ # Ignore MacOSX meta files. files = itertools.ifilter(lambda filename: u'__MACOSX' not in os.path.normpath(filename).split(os.sep), files) # Ignore credit files if possible. files = itertools.ifilter(lambda filename: u'credit' not in os.path.split(filename)[1].lower(), files) images = list(itertools.ifilter(image_tools.is_image_file, files)) tools.alphanumeric_sort(images) front_re = re.compile('(cover|front)', re.I) candidates = filter(front_re.search, images) candidates = [c for c in candidates if 'back' not in c.lower()] if candidates: return candidates[0] if images: return images[0] return None
def __get_sibling_directories(self, dir): """ Returns a list of all sibling directories of <dir>, already sorted. """ parent_dir = os.path.dirname(dir) directories = [ os.path.join(parent_dir, directory) for directory in os.listdir(parent_dir) if os.path.isdir(os.path.join(parent_dir, directory)) ] tools.alphanumeric_sort(directories) return directories
def _sort_archive_images(self, filelist): ''' Sorts the image list passed in C{filelist} based on the sorting preference option. ''' if prefs['sort archive by'] == constants.SORT_NAME: tools.alphanumeric_sort(filelist) elif prefs['sort archive by'] == constants.SORT_NAME_LITERAL: filelist.sort() else: # No sorting pass if prefs['sort archive order'] == constants.SORT_DESCENDING: filelist.reverse()
def _sort_archive_images(self, filelist): """ Sorts the image list passed in C{filelist} based on the sorting preference option. """ if prefs['sort archive by'] == constants.SORT_NAME: tools.alphanumeric_sort(filelist) elif prefs['sort archive by'] == constants.SORT_NAME_LITERAL: filelist.sort() else: # No sorting pass if prefs['sort archive order'] == constants.SORT_DESCENDING: filelist.reverse()
def sort_files(files): """ Sorts a list of C{files} depending on the current preferences. The list is sorted in-place. """ if preferences.prefs['sort by'] == constants.SORT_NAME: tools.alphanumeric_sort(files) elif preferences.prefs['sort by'] == constants.SORT_LAST_MODIFIED: # Most recently modified file first files.sort(key=lambda filename: os.path.getmtime(filename)*-1) elif preferences.prefs['sort by'] == constants.SORT_SIZE: # Smallest file first files.sort(key=lambda filename: os.stat(filename).st_size) # else: don't sort at all: use OS ordering. # Default is ascending. if preferences.prefs['sort order'] == constants.SORT_DESCENDING: files.reverse()
def _sort_archive_images(self, filelist): """ Sorts the image list passed in C{filelist} based on the sorting preference option, and returns the newly sorted list. """ filelist = list(filelist) # Create a copy of the list if prefs['sort archive by'] == constants.SORT_NAME: tools.alphanumeric_sort(filelist) elif prefs['sort archive by'] == constants.SORT_NAME_LITERAL: filelist.sort() else: # No sorting pass if prefs['sort archive order'] == constants.SORT_DESCENDING: filelist.reverse() return filelist
def sort_files(files): ''' Sorts a list of C{files} depending on the current preferences. The list is sorted in-place. ''' if prefs['sort by'] == constants.SORT_NAME: tools.alphanumeric_sort(files) elif prefs['sort by'] == constants.SORT_LAST_MODIFIED: # Most recently modified file first files.sort(key=lambda filename: os.path.getmtime(filename) * -1) elif prefs['sort by'] == constants.SORT_SIZE: # Smallest file first files.sort(key=lambda filename: os.stat(filename).st_size) elif prefs['sort by'] == constants.SORT_LOCALE: # Use the user's local to match ordering in most applications. files.sort(key=locale.strxfrm) # else: don't sort at all: use arbitrary ordering. # Default is ascending. if prefs['sort order'] == constants.SORT_DESCENDING: files.reverse()
def list_files(self, mode=FileProvider.IMAGES): """ Lists all files in the current directory. Returns a list of absolute paths, already sorted. """ if mode == FileProvider.IMAGES: should_accept = lambda file: image_tools.is_image_file(file) elif mode == FileProvider.ARCHIVES: should_accept = lambda file: \ constants.SUPPORTED_ARCHIVE_REGEX.search(file, re.I) is not None else: should_accept = lambda file: True try: files = [ os.path.join(self.base_dir, filename) for filename in # Explicitly convert all files to Unicode, even when # os.listdir returns a mixture of byte/unicode strings. # (MComix bug #3424405) [i18n.to_unicode(fn) for fn in os.listdir(self.base_dir)] if should_accept(os.path.join(self.base_dir, filename)) ] if preferences.prefs['sort by'] == constants.SORT_NAME: tools.alphanumeric_sort(files) elif preferences.prefs['sort by'] == constants.SORT_LAST_MODIFIED: # Most recently modified file first files.sort( key=lambda filename: os.path.getmtime(filename) * -1) elif preferences.prefs['sort by'] == constants.SORT_SIZE: # Smallest file first files.sort(key=lambda filename: os.stat(filename).st_size) # else: don't sort at all: use OS ordering. # Default is ascending. if preferences.prefs['sort order'] == constants.SORT_DESCENDING: files.reverse() return files except OSError: log.warning(u'! ' + _('Could not open %s: Permission denied.'), self.base_dir) return []
def list_files(self, mode=FileProvider.IMAGES): """ Lists all files in the current directory. Returns a list of absolute paths, already sorted. """ if mode == FileProvider.IMAGES: should_accept = lambda file: image_tools.is_image_file(file) elif mode == FileProvider.ARCHIVES: should_accept = lambda file: \ constants.SUPPORTED_ARCHIVE_REGEX.search(file, re.I) is not None else: should_accept = lambda file: True try: files = [ os.path.join(self.base_dir, filename) for filename in # Explicitly convert all files to Unicode, even when # os.listdir returns a mixture of byte/unicode strings. # (MComix bug #3424405) [ i18n.to_unicode(fn) for fn in os.listdir(self.base_dir) ] if should_accept(os.path.join(self.base_dir, filename)) ] if preferences.prefs['sort by'] == constants.SORT_NAME: tools.alphanumeric_sort(files) elif preferences.prefs['sort by'] == constants.SORT_LAST_MODIFIED: # Most recently modified file first files.sort(key=lambda filename: os.path.getmtime(filename)*-1) elif preferences.prefs['sort by'] == constants.SORT_SIZE: # Smallest file first files.sort(key=lambda filename: os.stat(filename).st_size) # else: don't sort at all: use OS ordering. # Default is ascending. if preferences.prefs['sort order'] == constants.SORT_DESCENDING: files.reverse() return files except OSError: log.warning(u'! ' + _('Could not open %s: Permission denied.'), self.base_dir) return []
self._window.scroll_to_fixed(horiz='startfirst', vert='top') self._window.uimanager.set_sensitivities() self._window.thumbnailsidebar.load_thumbnails() self._window.uimanager.set_sensitivities() self.write_fileinfo_file() # If no extraction is required, mark all files as available instantly. if self.archive_type is None: for path in filelist: self.file_available(path) result = True tools.alphanumeric_sort(self._comment_files) self._window.uimanager.recent.add(self._current_file) self._window.draw_image() return result def close_file(self, *args): """Run tasks for "closing" the currently opened file(s).""" self.update_last_read_page() self.file_loaded = False self.archive_type = None self._current_file = None self._base_path = None self._stop_waiting = True self._comment_files = []
def _archive_opened(self, image_files, current_image_index): """ Called once the archive has been opened and its contents listed. """ if self.archive_type is not None: # Update status bar archive_list = self._file_provider.list_files( file_provider.FileProvider.ARCHIVES) if self._current_file in archive_list: current_index = archive_list.index(self._current_file) else: current_index = 0 self._window.statusbar.set_file_number(current_index + 1, len(archive_list)) else: # Update status bar (0 disables file numbers for images) self._window.statusbar.set_file_number(0, 0) if not image_files: self.file_loaded = False self.file_load_failed = True self._window.imagehandler._image_files = None msg = _("No images in '%s'") % os.path.basename(self._current_file) self._window.statusbar.set_message(msg) self._window.osd.show(msg) result = False self._window.uimanager.set_sensitivities() else: self.file_loaded = True self.file_load_failed = False self._window.imagehandler._image_files = image_files self._window.imagehandler._current_image_index = current_image_index self._window.imagehandler._base_path = self._base_path self._window.imagehandler._current_file = self._current_file self._window.imagehandler._name_table = self._name_table self._window.imagehandler.do_cacheing() self._window.scroll_to_predefined((constants.SCROLL_TO_START,) * 2, constants.FIRST_INDEX) self._window.uimanager.set_sensitivities() self._window.thumbnailsidebar.load_thumbnails() self._window.uimanager.set_sensitivities() self.write_fileinfo_file() # If no extraction is required, mark all files as available instantly. if self.archive_type is None: self.file_available(self.filelist) tools.alphanumeric_sort(self._comment_files) self._window.uimanager.recent.add(self._current_file) if self._must_call_draw: self._must_call_draw = False self._window.draw_image() self.file_opened()
def _archive_opened(self, image_files, current_image_index): """ Called once the archive has been opened and its contents listed. """ if self.archive_type is not None: # Update status bar archive_list = self._file_provider.list_files( file_provider.FileProvider.ARCHIVES) if self._current_file in archive_list: current_index = archive_list.index(self._current_file) else: current_index = 0 self._window.statusbar.set_file_number(current_index + 1, len(archive_list)) else: # Update status bar (0 disables file numbers for images) self._window.statusbar.set_file_number(0, 0) if not image_files: self.file_loaded = False self.file_load_failed = True self._window.imagehandler._image_files = None msg = _("No images in '%s'") % os.path.basename(self._current_file) self._window.statusbar.set_message(msg) self._window.osd.show(msg) result = False self._window.uimanager.set_sensitivities() else: self.file_loaded = True self.file_load_failed = False self._window.imagehandler._image_files = image_files self._window.imagehandler._current_image_index = current_image_index self._window.imagehandler._base_path = self._base_path self._window.imagehandler._current_file = self._current_file self._window.imagehandler._name_table = self._name_table self._window.imagehandler.do_cacheing() self._window.scroll_to_predefined( (constants.SCROLL_TO_START, ) * 2, constants.FIRST_INDEX) self._window.uimanager.set_sensitivities() self._window.thumbnailsidebar.load_thumbnails() self._window.uimanager.set_sensitivities() self.write_fileinfo_file() # If no extraction is required, mark all files as available instantly. if self.archive_type is None: self.file_available(self.filelist) tools.alphanumeric_sort(self._comment_files) self._window.uimanager.recent.add(self._current_file) if self._must_call_draw: self._must_call_draw = False self._window.draw_image() self.file_opened()
def split_images(self): if self._did_split: print "Already split, yo" return # NOTE: this can happen on startup if len(self._name_table) == 0: return self._did_split = True filenames = [k for k in self._name_table] # TODO: hyper unreliable exe_name = os.path.join(os.path.dirname(sys.argv[0]), "bins", "comic_splitter") if not os.path.exists(exe_name): print base + " doesn't exist!" return print(exe_name) output_dirname = os.path.dirname(filenames[0]) # print filenames print "Splitting at %s..." % (output_dirname) subprocess.call([exe_name, "-output", output_dirname, "-delete"] + filenames) # prefix = os.path.basename(output_dirname) # prefix = os.path.basename(output_dirname) # print prefix prefix = output_dirname files = [ os.path.join(prefix, f) for f in os.listdir(output_dirname) if os.path.isfile(os.path.join(output_dirname, f)) ] archive_images = [ image for image in files if self._image_re.search(image) # Remove MacOS meta files from image list and not u'__MACOSX' in os.path.normpath(image).split(os.sep) ] self._sort_archive_images(archive_images) image_files = [os.path.join(self._tmp_dir, f) for f in archive_images] comment_files = filter(self._comment_re.search, files) tools.alphanumeric_sort(comment_files) self._comment_files = [ os.path.join(self._tmp_dir, f) for f in comment_files ] self._name_table = dict(zip(files, archive_images)) self._name_table.update(zip(self._comment_files, comment_files)) # self.file_available(self.filelist, True) self._archive_opened(image_files) self.filelist = files self._window.imagehandler._available_images = set( range(0, len(image_files))) self._window.imagehandler._image_files = image_files # self._extractor.set_files(archive_images + comment_files) return True
def _open_archive(self, path, start_page): """ Opens the archive passed in C{path}. Creates an L{archive_extractor.Extractor} and extracts all images found within the archive. @return: A tuple containing C{(image_files, image_index)}. """ self._base_path = path try: self._condition = self._extractor.setup(self._base_path, self._tmp_dir, self.archive_type) except Exception: self._condition = None raise if self._condition != None: files = self._extractor.get_files() archive_images = [image for image in files if self._image_re.search(image) # Remove MacOS meta files from image list and not u'__MACOSX' in os.path.normpath(image).split(os.sep)] tools.alphanumeric_sort(archive_images) image_files = [ os.path.join(self._tmp_dir, f) for f in archive_images ] comment_files = filter(self._comment_re.search, files) self._comment_files = [ os.path.join(self._tmp_dir, f) for f in comment_files ] # Allow managing sub-archives by keeping archives based on extension archive_files = filter(constants.SUPPORTED_ARCHIVE_REGEX.search, files) archive_files_paths = [ os.path.join(self._tmp_dir, f) for f in archive_files ] for name, full_path in zip(archive_images, image_files): self._name_table[full_path] = name for name, full_path in zip(comment_files, self._comment_files): self._name_table[full_path] = name for name, full_path in zip(archive_files, archive_files_paths): self._name_table[full_path] = name # Determine current archive image index. current_image_index = self._get_index_for_page(start_page, len(image_files), path) # Sort files to determine extraction order. self._sort_archive_files(archive_images, current_image_index) self._extractor.set_files(archive_images + comment_files + archive_files) self._extractor.file_extracted += self._extracted_file self._extractor.extract() # Manage subarchive through recursion if archive_files: has_subarchive = False # For each potential archive, change the current extractor, # extract recursively, and restore the internal extractor. for f in archive_files_paths: if not self._extractor.is_ready(f): self._wait_on_file(f) if archive_tools.archive_mime_type(f) is not None: # save self data state = self._save_state() # Setup temporary data self._extractor = archive_extractor.Extractor() self._tmp_dir = os.path.join(self._tmp_dir, os.path.basename(f) + u'.dir') if not os.path.exists(self._tmp_dir): os.mkdir(self._tmp_dir) self._condition = self._extractor.setup(self._base_path, self._tmp_dir, self.archive_type) self._extractor.file_extracted += self._extracted_file add_images, dummy_idx = self._open_archive(f, 1) # recursion here # Since it's recursive, we do not want to loose the way to ensure # that the file was extracted, so too bad but it will be a lil' slower. for image in add_images: self._wait_on_file(image) image_files.extend(add_images) self._extractor.stop() self._extractor.close() # restore self data self._restore_state(state) has_subarchive = True # Allows to avoid any behaviour changes if there was no subarchive.. if has_subarchive: # Mark additional files as extracted self._comment_files = \ filter(self._comment_re.search, image_files) tmp_image_files = \ filter(self._image_re.search, image_files) self._name_table.clear() for full_path in tmp_image_files + self._comment_files: self._name_table[full_path] = os.path.basename(full_path) # This trick here allows to avoid indefinite waiting on # the sub-extracted files. self._extractor._extracted[os.path.basename(full_path)] = True # set those files instead of image_files for the return image_files = tmp_image_files # Image index may have changed after additional files were extracted. current_image_index = self._get_index_for_page(start_page, len(image_files), path) return image_files, current_image_index else: # No condition was returned from the Extractor, i.e. invalid archive. return [], 0