# Created By: Virgil Dupras # Created On: 2011/09/07 # Copyright 2015 Hardcoded Software (http://www.hardcoded.net) # # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, # which should be included with this package. The terms are also available at # http://www.gnu.org/licenses/gpl-3.0.html from hscommon.util import dedupe, flatten, rem_file_ext from hscommon.trans import trget, tr coltr = trget("columns") class CriterionCategory: NAME = "Undefined" def __init__(self, results): self.results = results # --- Virtual def extract_value(self, dupe): raise NotImplementedError() def format_criterion_value(self, value): return value def sort_key(self, dupe, crit_value): raise NotImplementedError() def criteria_list(self): raise NotImplementedError() class Criterion: def __init__(self, category, value): self.category = category self.value = value self.display_value = category.format_criterion_value(value) def sort_key(self, dupe): return self.category.sort_key(dupe, self.value) @property def display(self): return f"{self.category.NAME} ({self.display_value})" class ValueListCategory(CriterionCategory): def sort_key(self, dupe, crit_value): # Use this sort key when the order in the list depends on whether or not the dupe meets the # criteria. If it does, we return 0 (top of the list), if it doesn't, we return 1. if self.extract_value(dupe) == crit_value: return 0 else: return 1 def criteria_list(self): dupes = flatten(g[:] for g in self.results.groups) values = sorted(dedupe(self.extract_value(d) for d in dupes)) return [Criterion(self, value) for value in values] class KindCategory(ValueListCategory): NAME = coltr("Kind") def extract_value(self, dupe): value = dupe.extension if not value: value = tr("None") return value class FolderCategory(ValueListCategory): NAME = coltr("Folder") def extract_value(self, dupe): return dupe.folder_path def format_criterion_value(self, value): return str(value) def sort_key(self, dupe, crit_value): value = self.extract_value(dupe) # This is instead of using is_relative_to() which was added in py 3.9 try: value.relative_to(crit_value) except ValueError: return 1 return 0 class FilenameCategory(CriterionCategory): NAME = coltr("Filename") ENDS_WITH_NUMBER = 0 DOESNT_END_WITH_NUMBER = 1 LONGEST = 2 SHORTEST = 3 def format_criterion_value(self, value): return { self.ENDS_WITH_NUMBER: tr("Ends with number"), self.DOESNT_END_WITH_NUMBER: tr("Doesn't end with number"), self.LONGEST: tr("Longest"), self.SHORTEST: tr("Shortest"), }[value] def extract_value(self, dupe): return rem_file_ext(dupe.name) def sort_key(self, dupe, crit_value): value = self.extract_value(dupe) if crit_value in {self.ENDS_WITH_NUMBER, self.DOESNT_END_WITH_NUMBER}: ends_with_digit = value.strip()[-1:].isdigit() if crit_value == self.ENDS_WITH_NUMBER: return 0 if ends_with_digit else 1 else: return 1 if ends_with_digit else 0 else: value = len(value) if crit_value == self.LONGEST: value *= -1 # We want the biggest values on top return value def criteria_list(self): return [ Criterion(self, crit_value) for crit_value in [ self.ENDS_WITH_NUMBER, self.DOESNT_END_WITH_NUMBER, self.LONGEST, self.SHORTEST, ] ] class NumericalCategory(CriterionCategory): HIGHEST = 0 LOWEST = 1 def format_criterion_value(self, value): return tr("Highest") if value == self.HIGHEST else tr("Lowest") def invert_numerical_value(self, value): # Virtual return value * -1 def sort_key(self, dupe, crit_value): value = self.extract_value(dupe) if crit_value == self.HIGHEST: # we want highest values on top value = self.invert_numerical_value(value) return value def criteria_list(self): return [Criterion(self, self.HIGHEST), Criterion(self, self.LOWEST)] class SizeCategory(NumericalCategory): NAME = coltr("Size") def extract_value(self, dupe): return dupe.size class MtimeCategory(NumericalCategory): NAME = coltr("Modification") def extract_value(self, dupe): return dupe.mtime def format_criterion_value(self, value): return tr("Newest") if value == self.HIGHEST else tr("Oldest") def all_categories(): return [KindCategory, FolderCategory, FilenameCategory, SizeCategory, MtimeCategory]