2011-09-07 19:46:41 +00:00
|
|
|
# Created By: Virgil Dupras
|
|
|
|
# Created On: 2011/09/07
|
2015-01-03 21:30:57 +00:00
|
|
|
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
2020-01-01 02:16:27 +00:00
|
|
|
#
|
|
|
|
# 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
|
2015-01-03 21:33:16 +00:00
|
|
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
2011-09-07 19:46:41 +00:00
|
|
|
|
2012-07-31 15:18:39 +00:00
|
|
|
from hscommon.util import dedupe, flatten, rem_file_ext
|
2011-11-01 19:44:18 +00:00
|
|
|
from hscommon.trans import trget, tr
|
2011-09-07 19:46:41 +00:00
|
|
|
|
2020-01-01 02:16:27 +00:00
|
|
|
coltr = trget("columns")
|
|
|
|
|
2011-09-16 22:01:56 +00:00
|
|
|
|
2011-09-07 19:46:41 +00:00
|
|
|
class CriterionCategory:
|
|
|
|
NAME = "Undefined"
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-07 19:46:41 +00:00
|
|
|
def __init__(self, results):
|
|
|
|
self.results = results
|
2020-01-01 02:16:27 +00:00
|
|
|
|
|
|
|
# --- Virtual
|
2011-09-08 17:28:19 +00:00
|
|
|
def extract_value(self, dupe):
|
2011-09-07 19:46:41 +00:00
|
|
|
raise NotImplementedError()
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def format_criterion_value(self, value):
|
2011-09-08 17:28:19 +00:00
|
|
|
return value
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def sort_key(self, dupe, crit_value):
|
2011-09-20 14:38:48 +00:00
|
|
|
raise NotImplementedError()
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-07 19:46:41 +00:00
|
|
|
def criteria_list(self):
|
2011-09-20 14:38:48 +00:00
|
|
|
raise NotImplementedError()
|
2011-09-07 19:46:41 +00:00
|
|
|
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-07 19:46:41 +00:00
|
|
|
class Criterion:
|
|
|
|
def __init__(self, category, value):
|
|
|
|
self.category = category
|
|
|
|
self.value = value
|
2011-09-12 14:33:17 +00:00
|
|
|
self.display_value = category.format_criterion_value(value)
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def sort_key(self, dupe):
|
|
|
|
return self.category.sort_key(dupe, self.value)
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-07 19:46:41 +00:00
|
|
|
@property
|
|
|
|
def display(self):
|
2022-04-28 01:53:12 +00:00
|
|
|
return f"{self.category.NAME} ({self.display_value})"
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-07 19:46:41 +00:00
|
|
|
|
2011-09-20 14:38:48 +00:00
|
|
|
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
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-20 14:38:48 +00:00
|
|
|
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]
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-20 14:38:48 +00:00
|
|
|
|
|
|
|
class KindCategory(ValueListCategory):
|
2011-09-16 22:01:56 +00:00
|
|
|
NAME = coltr("Kind")
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def extract_value(self, dupe):
|
2011-09-20 14:38:48 +00:00
|
|
|
value = dupe.extension
|
|
|
|
if not value:
|
|
|
|
value = tr("None")
|
|
|
|
return value
|
2011-09-08 17:28:19 +00:00
|
|
|
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-20 14:38:48 +00:00
|
|
|
class FolderCategory(ValueListCategory):
|
2011-09-16 22:01:56 +00:00
|
|
|
NAME = coltr("Folder")
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def extract_value(self, dupe):
|
|
|
|
return dupe.folder_path
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def format_criterion_value(self, value):
|
2011-09-08 17:28:19 +00:00
|
|
|
return str(value)
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-20 14:38:48 +00:00
|
|
|
def sort_key(self, dupe, crit_value):
|
|
|
|
value = self.extract_value(dupe)
|
2022-03-28 05:04:32 +00:00
|
|
|
# This is instead of using is_relative_to() which was added in py 3.9
|
|
|
|
try:
|
|
|
|
value.relative_to(crit_value)
|
|
|
|
except ValueError:
|
2011-09-20 14:38:48 +00:00
|
|
|
return 1
|
2022-03-28 05:04:32 +00:00
|
|
|
return 0
|
2011-09-08 17:28:19 +00:00
|
|
|
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
class FilenameCategory(CriterionCategory):
|
2011-09-16 22:01:56 +00:00
|
|
|
NAME = coltr("Filename")
|
2011-09-12 14:33:17 +00:00
|
|
|
ENDS_WITH_NUMBER = 0
|
|
|
|
DOESNT_END_WITH_NUMBER = 1
|
2012-07-31 15:18:39 +00:00
|
|
|
LONGEST = 2
|
|
|
|
SHORTEST = 3
|
2024-07-16 18:41:20 +00:00
|
|
|
LONGEST_PATH = 4
|
|
|
|
SHORTEST_PATH = 5
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def format_criterion_value(self, value):
|
2012-07-31 15:18:39 +00:00
|
|
|
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"),
|
2024-07-16 18:41:20 +00:00
|
|
|
self.SHORTEST_PATH: tr("Longest Path"),
|
|
|
|
self.SHORTEST_PATH: tr("Shortest Path"),
|
2012-07-31 15:18:39 +00:00
|
|
|
}[value]
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def extract_value(self, dupe):
|
|
|
|
return rem_file_ext(dupe.name)
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def sort_key(self, dupe, crit_value):
|
|
|
|
value = self.extract_value(dupe)
|
2012-07-31 15:18:39 +00:00
|
|
|
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
|
2024-07-16 18:41:20 +00:00
|
|
|
elif crit_value == self.LONGEST_PATH:
|
|
|
|
return len(str(dupe.folder_path)) * -1
|
|
|
|
elif crit_value == self.SHORTEST_PATH:
|
|
|
|
return len(str(dupe.folder_path))
|
2011-09-12 14:33:17 +00:00
|
|
|
else:
|
2012-07-31 15:18:39 +00:00
|
|
|
value = len(value)
|
|
|
|
if crit_value == self.LONGEST:
|
2020-01-01 02:16:27 +00:00
|
|
|
value *= -1 # We want the biggest values on top
|
2012-07-31 15:18:39 +00:00
|
|
|
return value
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def criteria_list(self):
|
2020-01-01 02:16:27 +00:00
|
|
|
return [
|
|
|
|
Criterion(self, crit_value)
|
|
|
|
for crit_value in [
|
|
|
|
self.ENDS_WITH_NUMBER,
|
|
|
|
self.DOESNT_END_WITH_NUMBER,
|
|
|
|
self.LONGEST,
|
|
|
|
self.SHORTEST,
|
2024-07-16 18:41:20 +00:00
|
|
|
self.LONGEST_PATH,
|
|
|
|
self.SHORTEST_PATH,
|
2020-01-01 02:16:27 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
class NumericalCategory(CriterionCategory):
|
|
|
|
HIGHEST = 0
|
|
|
|
LOWEST = 1
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def format_criterion_value(self, value):
|
|
|
|
return tr("Highest") if value == self.HIGHEST else tr("Lowest")
|
2020-01-01 02:16:27 +00:00
|
|
|
|
|
|
|
def invert_numerical_value(self, value): # Virtual
|
2011-09-16 16:44:20 +00:00
|
|
|
return value * -1
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def sort_key(self, dupe, crit_value):
|
|
|
|
value = self.extract_value(dupe)
|
2020-01-01 02:16:27 +00:00
|
|
|
if crit_value == self.HIGHEST: # we want highest values on top
|
2011-09-16 16:44:20 +00:00
|
|
|
value = self.invert_numerical_value(value)
|
2011-09-08 17:28:19 +00:00
|
|
|
return value
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def criteria_list(self):
|
|
|
|
return [Criterion(self, self.HIGHEST), Criterion(self, self.LOWEST)]
|
2020-01-01 02:16:27 +00:00
|
|
|
|
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
class SizeCategory(NumericalCategory):
|
2011-09-16 22:01:56 +00:00
|
|
|
NAME = coltr("Size")
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def extract_value(self, dupe):
|
|
|
|
return dupe.size
|
|
|
|
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
class MtimeCategory(NumericalCategory):
|
2011-09-16 22:01:56 +00:00
|
|
|
NAME = coltr("Modification")
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def extract_value(self, dupe):
|
|
|
|
return dupe.mtime
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-12 14:33:17 +00:00
|
|
|
def format_criterion_value(self, value):
|
|
|
|
return tr("Newest") if value == self.HIGHEST else tr("Oldest")
|
|
|
|
|
2020-01-01 02:16:27 +00:00
|
|
|
|
2011-09-08 17:28:19 +00:00
|
|
|
def all_categories():
|
2011-09-12 14:33:17 +00:00
|
|
|
return [KindCategory, FolderCategory, FilenameCategory, SizeCategory, MtimeCategory]
|