1
0
zrcadlo https://github.com/arsenetar/dupeguru.git synchronizováno 2026-03-28 09:31:39 +00:00

Porovnat revize

...

1 Commity

Autor SHA1 Zpráva Datum
Virgil Dupras
9bd0ec8875 Added PE's "trigger happy" scan type
ref #242
2014-03-30 16:01:56 -04:00
6 změnil soubory, kde provedl 42 přidání a 6 odebrání

Zobrazit soubor

@@ -12,7 +12,7 @@ dialogHeights = {
scanTypeNames = { scanTypeNames = {
'se': ["Filename", "Content", "Folders"], 'se': ["Filename", "Content", "Folders"],
'me': ["Filename", "Filename - Fields", "Filename - Fields (No Order)", "Tags", "Content", "Audio Content"], 'me': ["Filename", "Filename - Fields", "Filename - Fields (No Order)", "Tags", "Content", "Audio Content"],
'pe': ["Contents", "EXIF Timestamp"], 'pe': ["Contents", "EXIF Timestamp", "Trigger-happy mode"],
} }
result = Window(410, dialogHeights[edition], dialogTitles[edition]) result = Window(410, dialogHeights[edition], dialogTitles[edition])

Zobrazit soubor

@@ -331,6 +331,7 @@ class PyDupeGuru(PyDupeGuruBase):
self.model.scanner.scan_type = [ self.model.scanner.scan_type = [
ScanType.FuzzyBlock, ScanType.FuzzyBlock,
ScanType.ExifTimestamp, ScanType.ExifTimestamp,
ScanType.TriggerHappyMode,
][scan_type] ][scan_type]
except IndexError: except IndexError:
pass pass

Zobrazit soubor

@@ -33,6 +33,7 @@ class ScanType:
#PE #PE
FuzzyBlock = 10 FuzzyBlock = 10
ExifTimestamp = 11 ExifTimestamp = 11
TriggerHappyMode = 12
SCANNABLE_TAGS = ['track', 'artist', 'album', 'title', 'genre', 'year'] SCANNABLE_TAGS = ['track', 'artist', 'album', 'title', 'genre', 'year']

Zobrazit soubor

@@ -10,21 +10,43 @@ from collections import defaultdict
from itertools import combinations from itertools import combinations
from hscommon.trans import tr from hscommon.trans import tr
from jobprogress import job
from core.engine import Match from core.engine import Match
def getmatches(files, match_scaled, j): def group_by_timestamp(files, date_only=False, j=job.nulljob):
"""Returns a mapping timestamp --> set(files).
If ``date_only`` is ``True``, ignore the "time" part of the timestamp and consider files as
matching as soon as their date part match.
"""
timestamp2pic = defaultdict(set) timestamp2pic = defaultdict(set)
for picture in j.iter_with_progress(files, tr("Read EXIF of %d/%d pictures")): for picture in j.iter_with_progress(files, tr("Read EXIF of %d/%d pictures")):
timestamp = picture.exif_timestamp timestamp = picture.exif_timestamp
if timestamp: if timestamp:
if date_only:
timestamp = timestamp[:10]
timestamp2pic[timestamp].add(picture) timestamp2pic[timestamp].add(picture)
if '0000:00:00 00:00:00' in timestamp2pic: # very likely false matches NULL_TS = '0000:00:00 00:00:00'
del timestamp2pic['0000:00:00 00:00:00'] if date_only:
NULL_TS = NULL_TS[:10]
if NULL_TS in timestamp2pic: # very likely false matches
del timestamp2pic[NULL_TS]
return timestamp2pic
def getmatches(files, match_scaled=True, date_only=False, j=job.nulljob):
"""Returns a list of files with the same EXIF date.
Reads the EXIF tag of all ``files`` and return a :class:`Match` for every pair of files having
the exact same EXIF timestamp (DateTimeOriginal).
If ``match_scaled`` if ``False``, ignore files that don't have the same dimensions.
"""
timestamp2pic = group_by_timestamp(files, j=j)
matches = [] matches = []
for pictures in timestamp2pic.values(): for pictures in timestamp2pic.values():
for p1, p2 in combinations(pictures, 2): for p1, p2 in combinations(pictures, 2):
if (not match_scaled) and (p1.dimensions != p2.dimensions): if (not match_scaled) and (p1.dimensions != p2.dimensions):
continue continue
matches.append(Match(p1, p2, 100)) matches.append(Match(p1, p2, 100))
return matches return matches

Zobrazit soubor

@@ -20,7 +20,17 @@ class ScannerPE(Scanner):
if self.scan_type == ScanType.FuzzyBlock: if self.scan_type == ScanType.FuzzyBlock:
return matchblock.getmatches(files, self.cache_path, self.threshold, self.match_scaled, j) return matchblock.getmatches(files, self.cache_path, self.threshold, self.match_scaled, j)
elif self.scan_type == ScanType.ExifTimestamp: elif self.scan_type == ScanType.ExifTimestamp:
return matchexif.getmatches(files, self.match_scaled, j) return matchexif.getmatches(files, match_scaled=self.match_scaled, j=j)
elif self.scan_type == ScanType.TriggerHappyMode:
j = j.start_subjob([1, 9])
groups = matchexif.group_by_timestamp(files, date_only=True, j=j)
j = j.start_subjob(len(groups))
matches = []
for subfiles in groups.values():
matches += matchblock.getmatches(
list(subfiles), self.cache_path, self.threshold, self.match_scaled, j
)
return matches
else: else:
raise Exception("Invalid scan type") raise Exception("Invalid scan type")

Zobrazit soubor

@@ -20,6 +20,7 @@ tr = trget('ui')
SCAN_TYPE_ORDER = [ SCAN_TYPE_ORDER = [
ScanType.FuzzyBlock, ScanType.FuzzyBlock,
ScanType.ExifTimestamp, ScanType.ExifTimestamp,
ScanType.TriggerHappyMode,
] ]
class PreferencesDialog(PreferencesDialogBase): class PreferencesDialog(PreferencesDialogBase):
@@ -32,6 +33,7 @@ class PreferencesDialog(PreferencesDialogBase):
scanTypeLabels = [ scanTypeLabels = [
tr("Contents"), tr("Contents"),
tr("EXIF Timestamp"), tr("EXIF Timestamp"),
tr("Trigger-happy mode"),
] ]
self._setupScanTypeBox(scanTypeLabels) self._setupScanTypeBox(scanTypeLabels)
self._setupFilterHardnessBox() self._setupFilterHardnessBox()