mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-25 16:11:39 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8980b4667 | ||
|
|
e0adec7b2b | ||
|
|
eb8b9d663f | ||
|
|
fa4b0cf9ec | ||
|
|
f72db8dd1d | ||
|
|
c5bf0f228a | ||
|
|
e150b26cab | ||
|
|
da41d07dae | ||
|
|
c885cb35d8 |
2
.hgtags
2
.hgtags
@@ -41,3 +41,5 @@ ca93352ce35184853ad9fcb881935a43a8b1e249 me5.10.3
|
|||||||
3f71a8f5bf8f6d0729748a27af9163e013723294 pe1.11.3
|
3f71a8f5bf8f6d0729748a27af9163e013723294 pe1.11.3
|
||||||
0056293b0dade8b8230f68c1fe6f0c2d1e0b74d8 se2.12.3
|
0056293b0dade8b8230f68c1fe6f0c2d1e0b74d8 se2.12.3
|
||||||
8d12cab3b12b723e3a86d02cf8002731a0f73f95 se3.0.0
|
8d12cab3b12b723e3a86d02cf8002731a0f73f95 se3.0.0
|
||||||
|
778876a8a9787658aa6adf6944b53aebcb7faeea se3.0.1
|
||||||
|
f1d40b556c01f32c58f9ef9f9acac5b78e01ba7a pe2.0.0
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
- (NSNumber *)getMarkCount;
|
- (NSNumber *)getMarkCount;
|
||||||
- (BOOL)scanWasProblematic;
|
- (BOOL)scanWasProblematic;
|
||||||
- (BOOL)resultsAreModified;
|
- (BOOL)resultsAreModified;
|
||||||
|
- (NSArray *)deltaColumns;
|
||||||
|
|
||||||
//Scanning options
|
//Scanning options
|
||||||
- (void)setMinMatchPercentage:(NSNumber *)percentage;
|
- (void)setMinMatchPercentage:(NSNumber *)percentage;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[self fillColumnsMenu];
|
[self fillColumnsMenu];
|
||||||
[matches setTarget:self];
|
[matches setTarget:self];
|
||||||
[matches setDoubleAction:@selector(openClicked:)];
|
[matches setDoubleAction:@selector(openClicked:)];
|
||||||
|
[table setDeltaColumns:[Utils array2IndexSet:[py deltaColumns]]];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobCompleted:) name:JobCompletedNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobCompleted:) name:JobCompletedNotification object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobStarted:) name:JobStarted object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobStarted:) name:JobStarted object:nil];
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"56.title" = "Référence";
|
"56.title" = "Référence";
|
||||||
|
|
||||||
/* Class = "NSMenuItem"; title = "Excluded"; ObjectID = "57"; */
|
/* Class = "NSMenuItem"; title = "Excluded"; ObjectID = "57"; */
|
||||||
"57.title" = "Exclus";
|
"57.title" = "Exclu";
|
||||||
|
|
||||||
/* Class = "NSTextFieldCell"; title = "Select folders to scan and press \"Scan\"."; ObjectID = "71"; */
|
/* Class = "NSTextFieldCell"; title = "Select folders to scan and press \"Scan\"."; ObjectID = "71"; */
|
||||||
"71.title" = "Sélectionnez les dossiers à scanner et cliquez sur Scan.";
|
"71.title" = "Sélectionnez les dossiers à scanner et cliquez sur Scan.";
|
||||||
|
|||||||
@@ -191,7 +191,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSMenuItem" id="142495353">
|
<object class="NSMenuItem" id="142495353">
|
||||||
<reference key="NSMenu" ref="104112446"/>
|
<reference key="NSMenu" ref="104112446"/>
|
||||||
<string key="NSTitle">Exclus</string>
|
<string key="NSTitle">Exclu</string>
|
||||||
<string key="NSKeyEquiv"/>
|
<string key="NSKeyEquiv"/>
|
||||||
<int key="NSMnemonicLoc">2147483647</int>
|
<int key="NSMnemonicLoc">2147483647</int>
|
||||||
<string key="NSAction">_popUpItemAction:</string>
|
<string key="NSAction">_popUpItemAction:</string>
|
||||||
|
|||||||
@@ -14,15 +14,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
@implementation ResultWindow
|
@implementation ResultWindow
|
||||||
/* Override */
|
/* Override */
|
||||||
- (id)initWithParentApp:(AppDelegateBase *)aApp;
|
|
||||||
{
|
|
||||||
self = [super initWithParentApp:aApp];
|
|
||||||
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,6)];
|
|
||||||
[deltaColumns removeIndex:6];
|
|
||||||
[table setDeltaColumns:deltaColumns];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setScanOptions
|
- (void)setScanOptions
|
||||||
{
|
{
|
||||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||||
|
|||||||
@@ -14,15 +14,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
@implementation ResultWindow
|
@implementation ResultWindow
|
||||||
/* Override */
|
/* Override */
|
||||||
- (id)initWithParentApp:(AppDelegateBase *)aApp;
|
|
||||||
{
|
|
||||||
self = [super initWithParentApp:aApp];
|
|
||||||
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndex:2];
|
|
||||||
[deltaColumns addIndex:5];
|
|
||||||
[table setDeltaColumns:deltaColumns];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)initResultColumns
|
- (void)initResultColumns
|
||||||
{
|
{
|
||||||
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
|
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
|
||||||
|
|||||||
@@ -13,15 +13,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
@implementation ResultWindow
|
@implementation ResultWindow
|
||||||
/* Override */
|
/* Override */
|
||||||
- (id)initWithParentApp:(AppDelegateBase *)aApp;
|
|
||||||
{
|
|
||||||
self = [super initWithParentApp:aApp];
|
|
||||||
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndex:2];
|
|
||||||
[deltaColumns addIndex:4];
|
|
||||||
[table setDeltaColumns:deltaColumns];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)initResultColumns
|
- (void)initResultColumns
|
||||||
{
|
{
|
||||||
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
|
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
column_ids = [colid for colid in column_ids if colid.isdigit()]
|
column_ids = [colid for colid in column_ids if colid.isdigit()]
|
||||||
column_ids = list(map(int, column_ids))
|
column_ids = list(map(int, column_ids))
|
||||||
column_ids.sort()
|
column_ids.sort()
|
||||||
colnames = [col['display'] for i, col in enumerate(self.data.COLUMNS) if i in column_ids]
|
colnames = [col.display for i, col in enumerate(self.data.COLUMNS) if i in column_ids]
|
||||||
rows = []
|
rows = []
|
||||||
for group in self.results.groups:
|
for group in self.results.groups:
|
||||||
for dupe in group:
|
for dupe in group:
|
||||||
|
|||||||
@@ -112,6 +112,9 @@ class PyDupeGuruBase(PyFairware):
|
|||||||
def resultsAreModified(self):
|
def resultsAreModified(self):
|
||||||
return self.py.results.is_modified
|
return self.py.results.is_modified
|
||||||
|
|
||||||
|
def deltaColumns(self):
|
||||||
|
return list(self.py.data.DELTA_COLUMNS)
|
||||||
|
|
||||||
#---Properties
|
#---Properties
|
||||||
@signature('v@:c')
|
@signature('v@:c')
|
||||||
def setMixFileKind_(self, mix_file_kind):
|
def setMixFileKind_(self, mix_file_kind):
|
||||||
|
|||||||
@@ -6,10 +6,14 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from hscommon.util import format_time_decimal, format_size
|
from hscommon.util import format_time_decimal, format_size
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
Column = namedtuple('Column', 'attr display')
|
||||||
|
|
||||||
def format_path(p):
|
def format_path(p):
|
||||||
return str(p[:-1])
|
return str(p[:-1])
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class DetailsPanel(GUIObject):
|
|||||||
# we don't want the two sides of the table to display the stats for the same file
|
# we don't want the two sides of the table to display the stats for the same file
|
||||||
ref = group.ref if group is not None and group.ref is not dupe else None
|
ref = group.ref if group is not None and group.ref is not dupe else None
|
||||||
l2 = self.app._get_display_info(ref, group, False)
|
l2 = self.app._get_display_info(ref, group, False)
|
||||||
names = [c['display'] for c in self.app.data.COLUMNS]
|
names = [c.display for c in self.app.data.COLUMNS]
|
||||||
self._table = list(zip(names, l1, l2))
|
self._table = list(zip(names, l1, l2))
|
||||||
|
|
||||||
#--- Public
|
#--- Public
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Created By: Virgil Dupras
|
# Created By: Virgil Dupras
|
||||||
# Created On: 2009-10-23
|
# Created On: 2009-10-23
|
||||||
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
|
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
|
||||||
@@ -10,16 +9,17 @@
|
|||||||
# data module for tests
|
# data module for tests
|
||||||
|
|
||||||
from hscommon.util import format_size
|
from hscommon.util import format_size
|
||||||
from ..data import format_path, cmp_value
|
from ..data import format_path, cmp_value, Column
|
||||||
|
|
||||||
COLUMNS = [
|
COLUMNS = [
|
||||||
{'attr':'name','display':'Filename'},
|
Column('name', 'Filename'),
|
||||||
{'attr':'path','display':'Directory'},
|
Column('path', 'Directory'),
|
||||||
{'attr':'size','display':'Size (KB)'},
|
Column('size', 'Size (KB)'),
|
||||||
{'attr':'extension','display':'Kind'},
|
Column('extension', 'Kind'),
|
||||||
]
|
]
|
||||||
|
|
||||||
METADATA_TO_READ = ['size']
|
METADATA_TO_READ = ['size']
|
||||||
|
DELTA_COLUMNS = {2,}
|
||||||
|
|
||||||
def GetDisplayInfo(dupe, group, delta):
|
def GetDisplayInfo(dupe, group, delta):
|
||||||
size = dupe.size
|
size = dupe.size
|
||||||
@@ -35,10 +35,10 @@ def GetDisplayInfo(dupe, group, delta):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def GetDupeSortKey(dupe, get_group, key, delta):
|
def GetDupeSortKey(dupe, get_group, key, delta):
|
||||||
r = cmp_value(getattr(dupe, COLUMNS[key]['attr']))
|
r = cmp_value(getattr(dupe, COLUMNS[key].attr))
|
||||||
if delta and (key == 2):
|
if delta and (key in DELTA_COLUMNS):
|
||||||
r -= cmp_value(getattr(get_group().ref, COLUMNS[key]['attr']))
|
r -= cmp_value(getattr(get_group().ref, COLUMNS[key].attr))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def GetGroupSortKey(group, key):
|
def GetGroupSortKey(group, key):
|
||||||
return cmp_value(getattr(group.ref, COLUMNS[key]['attr']))
|
return cmp_value(getattr(group.ref, COLUMNS[key].attr))
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
__version__ = '5.10.4'
|
__version__ = '6.0.0'
|
||||||
__appname__ = 'dupeGuru Music Edition'
|
__appname__ = 'dupeGuru Music Edition'
|
||||||
@@ -9,33 +9,34 @@
|
|||||||
from hscommon.util import format_time, format_size
|
from hscommon.util import format_time, format_size
|
||||||
from hscommon.trans import tr as trbase
|
from hscommon.trans import tr as trbase
|
||||||
from core.data import (format_path, format_timestamp, format_words, format_perc,
|
from core.data import (format_path, format_timestamp, format_words, format_perc,
|
||||||
format_dupe_count, cmp_value)
|
format_dupe_count, cmp_value, Column)
|
||||||
|
|
||||||
tr = lambda s: trbase(s, 'columns')
|
tr = lambda s: trbase(s, 'columns')
|
||||||
|
|
||||||
COLUMNS = [
|
COLUMNS = [
|
||||||
{'attr': 'name', 'display': tr("Filename")},
|
Column('name', tr("Filename")),
|
||||||
{'attr': 'path', 'display': tr("Folder")},
|
Column('path', tr("Folder")),
|
||||||
{'attr': 'size', 'display': tr("Size (MB)")},
|
Column('size', tr("Size (MB)")),
|
||||||
{'attr': 'duration', 'display': tr("Time")},
|
Column('duration', tr("Time")),
|
||||||
{'attr': 'bitrate', 'display': tr("Bitrate")},
|
Column('bitrate', tr("Bitrate")),
|
||||||
{'attr': 'samplerate', 'display': tr("Sample Rate")},
|
Column('samplerate', tr("Sample Rate")),
|
||||||
{'attr': 'extension', 'display': tr("Kind")},
|
Column('extension', tr("Kind")),
|
||||||
{'attr': 'mtime', 'display': tr("Modification")},
|
Column('mtime', tr("Modification")),
|
||||||
{'attr': 'title', 'display': tr("Title")},
|
Column('title', tr("Title")),
|
||||||
{'attr': 'artist', 'display': tr("Artist")},
|
Column('artist', tr("Artist")),
|
||||||
{'attr': 'album', 'display': tr("Album")},
|
Column('album', tr("Album")),
|
||||||
{'attr': 'genre', 'display': tr("Genre")},
|
Column('genre', tr("Genre")),
|
||||||
{'attr': 'year', 'display': tr("Year")},
|
Column('year', tr("Year")),
|
||||||
{'attr': 'track', 'display': tr("Track Number")},
|
Column('track', tr("Track Number")),
|
||||||
{'attr': 'comment', 'display': tr("Comment")},
|
Column('comment', tr("Comment")),
|
||||||
{'attr': 'percentage', 'display': tr("Match %")},
|
Column('percentage', tr("Match %")),
|
||||||
{'attr': 'words', 'display': tr("Words Used")},
|
Column('words', tr("Words Used")),
|
||||||
{'attr': 'dupe_count', 'display': tr("Dupe Count")},
|
Column('dupe_count', tr("Dupe Count")),
|
||||||
]
|
]
|
||||||
|
|
||||||
MATCHPERC_COL = 15
|
MATCHPERC_COL = 15
|
||||||
DUPECOUNT_COL = 17
|
DUPECOUNT_COL = 17
|
||||||
|
DELTA_COLUMNS = {2, 3, 4, 5, 7}
|
||||||
|
|
||||||
METADATA_TO_READ = ['size', 'mtime', 'duration', 'bitrate', 'samplerate', 'title', 'artist',
|
METADATA_TO_READ = ['size', 'mtime', 'duration', 'bitrate', 'samplerate', 'title', 'artist',
|
||||||
'album', 'genre', 'year', 'track', 'comment']
|
'album', 'genre', 'year', 'track', 'comment']
|
||||||
@@ -87,9 +88,9 @@ def GetDupeSortKey(dupe, get_group, key, delta):
|
|||||||
return m.percentage
|
return m.percentage
|
||||||
if key == DUPECOUNT_COL:
|
if key == DUPECOUNT_COL:
|
||||||
return 0
|
return 0
|
||||||
r = cmp_value(getattr(dupe, COLUMNS[key]['attr'], ''))
|
r = cmp_value(getattr(dupe, COLUMNS[key].attr, ''))
|
||||||
if delta and (key in {2, 3, 4, 7}):
|
if delta and (key in DELTA_COLUMNS):
|
||||||
r -= cmp_value(getattr(get_group().ref, COLUMNS[key]['attr'], ''))
|
r -= cmp_value(getattr(get_group().ref, COLUMNS[key].attr, ''))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def GetGroupSortKey(group, key):
|
def GetGroupSortKey(group, key):
|
||||||
@@ -97,4 +98,4 @@ def GetGroupSortKey(group, key):
|
|||||||
return group.percentage
|
return group.percentage
|
||||||
if key == DUPECOUNT_COL:
|
if key == DUPECOUNT_COL:
|
||||||
return len(group)
|
return len(group)
|
||||||
return cmp_value(getattr(group.ref, COLUMNS[key]['attr'], ''))
|
return cmp_value(getattr(group.ref, COLUMNS[key].attr, ''))
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
__version__ = '1.11.3'
|
__version__ = '2.0.0'
|
||||||
__appname__ = 'dupeGuru Picture Edition'
|
__appname__ = 'dupeGuru Picture Edition'
|
||||||
@@ -81,9 +81,9 @@ class Cache(object):
|
|||||||
try:
|
try:
|
||||||
self.con.execute(sql, [value, key])
|
self.con.execute(sql, [value, key])
|
||||||
except sqlite.OperationalError:
|
except sqlite.OperationalError:
|
||||||
logging.warning('Picture cache could not set %r for key %r', value, key)
|
logging.warning('Picture cache could not set value for key %r', key)
|
||||||
except sqlite.DatabaseError as e:
|
except sqlite.DatabaseError as e:
|
||||||
logging.warning('DatabaseError while setting %r for key %r: %s', value, key, str(e))
|
logging.warning('DatabaseError while setting value for key %r: %s', key, str(e))
|
||||||
|
|
||||||
def _create_con(self, second_try=False):
|
def _create_con(self, second_try=False):
|
||||||
def create_tables():
|
def create_tables():
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
from hscommon.util import format_size
|
from hscommon.util import format_size
|
||||||
from hscommon.trans import tr as trbase
|
from hscommon.trans import tr as trbase
|
||||||
from core.data import format_path, format_timestamp, format_perc, format_dupe_count, cmp_value
|
from core.data import format_path, format_timestamp, format_perc, format_dupe_count, cmp_value, Column
|
||||||
|
|
||||||
tr = lambda s: trbase(s, 'columns')
|
tr = lambda s: trbase(s, 'columns')
|
||||||
|
|
||||||
@@ -16,26 +16,31 @@ def format_dimensions(dimensions):
|
|||||||
return '%d x %d' % (dimensions[0], dimensions[1])
|
return '%d x %d' % (dimensions[0], dimensions[1])
|
||||||
|
|
||||||
COLUMNS = [
|
COLUMNS = [
|
||||||
{'attr':'name', 'display': tr("Filename")},
|
Column('name', tr("Filename")),
|
||||||
{'attr':'path', 'display': tr("Folder")},
|
Column('path', tr("Folder")),
|
||||||
{'attr':'size', 'display': tr("Size (KB)")},
|
Column('size', tr("Size (KB)")),
|
||||||
{'attr':'extension', 'display': tr("Kind")},
|
Column('extension', tr("Kind")),
|
||||||
{'attr':'dimensions', 'display': tr("Dimensions")},
|
Column('dimensions', tr("Dimensions")),
|
||||||
{'attr':'mtime', 'display': tr("Modification")},
|
Column('mtime', tr("Modification")),
|
||||||
{'attr':'percentage', 'display': tr("Match %")},
|
Column('percentage', tr("Match %")),
|
||||||
{'attr':'dupe_count', 'display': tr("Dupe Count")},
|
Column('dupe_count', tr("Dupe Count")),
|
||||||
]
|
]
|
||||||
|
|
||||||
MATCHPERC_COL = 6
|
MATCHPERC_COL = 6
|
||||||
DUPECOUNT_COL = 7
|
DUPECOUNT_COL = 7
|
||||||
|
DELTA_COLUMNS = {2, 4, 5}
|
||||||
|
|
||||||
METADATA_TO_READ = ['size', 'mtime', 'dimensions']
|
METADATA_TO_READ = ['size', 'mtime', 'dimensions']
|
||||||
|
|
||||||
|
def get_delta_dimensions(value, ref_value):
|
||||||
|
return (value[0]-ref_value[0], value[1]-ref_value[1])
|
||||||
|
|
||||||
def GetDisplayInfo(dupe,group,delta=False):
|
def GetDisplayInfo(dupe,group,delta=False):
|
||||||
if (dupe is None) or (group is None):
|
if (dupe is None) or (group is None):
|
||||||
return ['---'] * len(COLUMNS)
|
return ['---'] * len(COLUMNS)
|
||||||
size = dupe.size
|
size = dupe.size
|
||||||
mtime = dupe.mtime
|
mtime = dupe.mtime
|
||||||
|
dimensions = dupe.dimensions
|
||||||
m = group.get_match_of(dupe)
|
m = group.get_match_of(dupe)
|
||||||
if m:
|
if m:
|
||||||
percentage = m.percentage
|
percentage = m.percentage
|
||||||
@@ -44,6 +49,7 @@ def GetDisplayInfo(dupe,group,delta=False):
|
|||||||
r = group.ref
|
r = group.ref
|
||||||
size -= r.size
|
size -= r.size
|
||||||
mtime -= r.mtime
|
mtime -= r.mtime
|
||||||
|
dimensions = get_delta_dimensions(dimensions, r.dimensions)
|
||||||
else:
|
else:
|
||||||
percentage = group.percentage
|
percentage = group.percentage
|
||||||
dupe_count = len(group.dupes)
|
dupe_count = len(group.dupes)
|
||||||
@@ -53,7 +59,7 @@ def GetDisplayInfo(dupe,group,delta=False):
|
|||||||
format_path(dupe_path),
|
format_path(dupe_path),
|
||||||
format_size(size, 0, 1, False),
|
format_size(size, 0, 1, False),
|
||||||
dupe.extension,
|
dupe.extension,
|
||||||
format_dimensions(dupe.dimensions),
|
format_dimensions(dimensions),
|
||||||
format_timestamp(mtime, delta and m),
|
format_timestamp(mtime, delta and m),
|
||||||
format_perc(percentage),
|
format_perc(percentage),
|
||||||
format_dupe_count(dupe_count)
|
format_dupe_count(dupe_count)
|
||||||
@@ -65,9 +71,13 @@ def GetDupeSortKey(dupe, get_group, key, delta):
|
|||||||
return m.percentage
|
return m.percentage
|
||||||
if key == DUPECOUNT_COL:
|
if key == DUPECOUNT_COL:
|
||||||
return 0
|
return 0
|
||||||
r = cmp_value(getattr(dupe, COLUMNS[key]['attr'], ''))
|
r = cmp_value(getattr(dupe, COLUMNS[key].attr, ''))
|
||||||
if delta and (key in {2, 5}):
|
if delta and (key in DELTA_COLUMNS):
|
||||||
r -= cmp_value(getattr(get_group().ref, COLUMNS[key]['attr'], ''))
|
ref_value = cmp_value(getattr(get_group().ref, COLUMNS[key].attr, ''))
|
||||||
|
if key == 4: # dimensions
|
||||||
|
r = get_delta_dimensions(r, ref_value)
|
||||||
|
else:
|
||||||
|
r -= ref_value
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def GetGroupSortKey(group, key):
|
def GetGroupSortKey(group, key):
|
||||||
@@ -75,5 +85,5 @@ def GetGroupSortKey(group, key):
|
|||||||
return group.percentage
|
return group.percentage
|
||||||
if key == DUPECOUNT_COL:
|
if key == DUPECOUNT_COL:
|
||||||
return len(group)
|
return len(group)
|
||||||
return cmp_value(getattr(group.ref, COLUMNS[key]['attr'], ''))
|
return cmp_value(getattr(group.ref, COLUMNS[key].attr, ''))
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ def prepare_pictures(pictures, cache_path, j=job.nulljob):
|
|||||||
prepared = [] # only pictures for which there was no error getting blocks
|
prepared = [] # only pictures for which there was no error getting blocks
|
||||||
try:
|
try:
|
||||||
for picture in j.iter_with_progress(pictures, tr("Analyzed %d/%d pictures")):
|
for picture in j.iter_with_progress(pictures, tr("Analyzed %d/%d pictures")):
|
||||||
picture.dimensions
|
|
||||||
picture.unicode_path = str(picture.path)
|
picture.unicode_path = str(picture.path)
|
||||||
|
logging.debug("Analyzing picture at {}".format(picture.unicode_path))
|
||||||
|
picture.dimensions # pre-read dimensions
|
||||||
try:
|
try:
|
||||||
if picture.unicode_path not in cache:
|
if picture.unicode_path not in cache:
|
||||||
blocks = picture.get_blocks(BLOCK_COUNT_PER_SIDE)
|
blocks = picture.get_blocks(BLOCK_COUNT_PER_SIDE)
|
||||||
|
|||||||
@@ -9,23 +9,24 @@
|
|||||||
from hscommon.util import format_size
|
from hscommon.util import format_size
|
||||||
from hscommon.trans import tr as trbase
|
from hscommon.trans import tr as trbase
|
||||||
from core.data import (format_path, format_timestamp, format_words, format_perc,
|
from core.data import (format_path, format_timestamp, format_words, format_perc,
|
||||||
format_dupe_count, cmp_value)
|
format_dupe_count, cmp_value, Column)
|
||||||
|
|
||||||
tr = lambda s: trbase(s, 'columns')
|
tr = lambda s: trbase(s, 'columns')
|
||||||
|
|
||||||
COLUMNS = [
|
COLUMNS = [
|
||||||
{'attr':'name', 'display': tr("Filename")},
|
Column('name', tr("Filename")),
|
||||||
{'attr':'path', 'display': tr("Folder")},
|
Column('path', tr("Folder")),
|
||||||
{'attr':'size', 'display': tr("Size (KB)")},
|
Column('size', tr("Size (KB)")),
|
||||||
{'attr':'extension', 'display': tr("Kind")},
|
Column('extension', tr("Kind")),
|
||||||
{'attr':'mtime', 'display': tr("Modification")},
|
Column('mtime', tr("Modification")),
|
||||||
{'attr':'percentage', 'display': tr("Match %")},
|
Column('percentage', tr("Match %")),
|
||||||
{'attr':'words', 'display': tr("Words Used")},
|
Column('words', tr("Words Used")),
|
||||||
{'attr':'dupe_count', 'display': tr("Dupe Count")},
|
Column('dupe_count', tr("Dupe Count")),
|
||||||
]
|
]
|
||||||
|
|
||||||
MATCHPERC_COL = 5
|
MATCHPERC_COL = 5
|
||||||
DUPECOUNT_COL = 7
|
DUPECOUNT_COL = 7
|
||||||
|
DELTA_COLUMNS = {2, 4}
|
||||||
|
|
||||||
METADATA_TO_READ = ['size', 'mtime']
|
METADATA_TO_READ = ['size', 'mtime']
|
||||||
|
|
||||||
@@ -60,9 +61,9 @@ def GetDupeSortKey(dupe, get_group, key, delta):
|
|||||||
return m.percentage
|
return m.percentage
|
||||||
if key == DUPECOUNT_COL:
|
if key == DUPECOUNT_COL:
|
||||||
return 0
|
return 0
|
||||||
r = cmp_value(getattr(dupe, COLUMNS[key]['attr'], ''))
|
r = cmp_value(getattr(dupe, COLUMNS[key].attr, ''))
|
||||||
if delta and (key in {2, 4}):
|
if delta and (key in DELTA_COLUMNS):
|
||||||
r -= cmp_value(getattr(get_group().ref, COLUMNS[key]['attr'], ''))
|
r -= cmp_value(getattr(get_group().ref, COLUMNS[key].attr, ''))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def GetGroupSortKey(group, key):
|
def GetGroupSortKey(group, key):
|
||||||
@@ -70,4 +71,4 @@ def GetGroupSortKey(group, key):
|
|||||||
return group.percentage
|
return group.percentage
|
||||||
if key == DUPECOUNT_COL:
|
if key == DUPECOUNT_COL:
|
||||||
return len(group)
|
return len(group)
|
||||||
return cmp_value(getattr(group.ref, COLUMNS[key]['attr'], ''))
|
return cmp_value(getattr(group.ref, COLUMNS[key].attr, ''))
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
=== 6.0.0 (2011-02-01)
|
||||||
|
|
||||||
|
* Re-designed the UI. (#129)
|
||||||
|
* Internationalized dupeGuru and localized it to french. (#32)
|
||||||
|
* Changed the format of the help file. (#130)
|
||||||
|
* Fixed crashes when reading malformed songs. (#127 #131)
|
||||||
|
* Removed focus from the cancel button in the progress dialog to avoid accidental cancellations. [Mac OS X] (#135)
|
||||||
|
* Folders added through drag and drop are added to the recent folders list. (#136)
|
||||||
|
* Added a debugging mode. (#132)
|
||||||
|
|
||||||
=== 5.10.4 (2010-12-30)
|
=== 5.10.4 (2010-12-30)
|
||||||
|
|
||||||
* Fixed bug causing results to be corrupted after a scan cancellation. (#120)
|
* Fixed bug causing results to be corrupted after a scan cancellation. (#120)
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
=== 2.0.0 (2011-01-29)
|
||||||
|
|
||||||
|
* Re-designed the UI. (#129)
|
||||||
|
* Internationalized dupeGuru and localized it to french. (#32)
|
||||||
|
* Changed the format of the help file. (#130)
|
||||||
|
* The "Dimensions" column is now affected by the delta mode. (#115)
|
||||||
|
* Removed focus from the cancel button in the progress dialog to avoid accidental cancellations. [Mac OS X] (#135)
|
||||||
|
* Folders added through drag and drop are added to the recent folders list. (#136)
|
||||||
|
* Added a debugging mode. (#132)
|
||||||
|
|
||||||
=== 1.11.3 (2010-12-31)
|
=== 1.11.3 (2010-12-31)
|
||||||
|
|
||||||
* Fixed bug causing results to be corrupted after a scan cancellation. (#120)
|
* Fixed bug causing results to be corrupted after a scan cancellation. (#120)
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ JOBID2TITLE = {
|
|||||||
class DupeGuru(DupeGuruBase, QObject):
|
class DupeGuru(DupeGuruBase, QObject):
|
||||||
LOGO_NAME = '<replace this>'
|
LOGO_NAME = '<replace this>'
|
||||||
NAME = '<replace this>'
|
NAME = '<replace this>'
|
||||||
DELTA_COLUMNS = frozenset()
|
|
||||||
|
|
||||||
def __init__(self, data_module):
|
def __init__(self, data_module):
|
||||||
appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
|
appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from PyQt4.QtGui import (QWidget, QFileDialog, QHeaderView, QVBoxLayout, QHBoxLa
|
|||||||
|
|
||||||
from hscommon.trans import tr, trmsg
|
from hscommon.trans import tr, trmsg
|
||||||
from qtlib.recent import Recent
|
from qtlib.recent import Recent
|
||||||
|
from qtlib.util import moveToScreenCenter
|
||||||
from core.app import NoScannableFileError
|
from core.app import NoScannableFileError
|
||||||
|
|
||||||
from . import platform
|
from . import platform
|
||||||
@@ -144,6 +145,8 @@ class DirectoriesDialog(QMainWindow):
|
|||||||
|
|
||||||
if self.app.prefs.directoriesWindowRect is not None:
|
if self.app.prefs.directoriesWindowRect is not None:
|
||||||
self.setGeometry(self.app.prefs.directoriesWindowRect)
|
self.setGeometry(self.app.prefs.directoriesWindowRect)
|
||||||
|
else:
|
||||||
|
moveToScreenCenter(self)
|
||||||
|
|
||||||
def _updateAddButton(self):
|
def _updateAddButton(self):
|
||||||
if self.recentFolders.isEmpty():
|
if self.recentFolders.isEmpty():
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from PyQt4.QtGui import (QMainWindow, QMenu, QLabel, QHeaderView, QMessageBox, Q
|
|||||||
|
|
||||||
from hscommon.trans import tr, trmsg
|
from hscommon.trans import tr, trmsg
|
||||||
from hscommon.util import nonone
|
from hscommon.util import nonone
|
||||||
|
from qtlib.util import moveToScreenCenter
|
||||||
|
|
||||||
from .results_model import ResultsModel, ResultsView
|
from .results_model import ResultsModel, ResultsView
|
||||||
from .stats_label import StatsLabel
|
from .stats_label import StatsLabel
|
||||||
@@ -137,7 +138,7 @@ class ResultWindow(QMainWindow):
|
|||||||
menu = self.menuColumns
|
menu = self.menuColumns
|
||||||
self._column_actions = []
|
self._column_actions = []
|
||||||
for index, column in enumerate(self.app.data.COLUMNS):
|
for index, column in enumerate(self.app.data.COLUMNS):
|
||||||
action = menu.addAction(column['display'])
|
action = menu.addAction(column.display)
|
||||||
action.setCheckable(True)
|
action.setCheckable(True)
|
||||||
action.column_index = index
|
action.column_index = index
|
||||||
self._column_actions.append(action)
|
self._column_actions.append(action)
|
||||||
@@ -192,8 +193,11 @@ class ResultWindow(QMainWindow):
|
|||||||
|
|
||||||
if self.app.prefs.resultWindowIsMaximized:
|
if self.app.prefs.resultWindowIsMaximized:
|
||||||
self.setWindowState(self.windowState() | Qt.WindowMaximized)
|
self.setWindowState(self.windowState() | Qt.WindowMaximized)
|
||||||
if self.app.prefs.resultWindowRect is not None and not self.app.prefs.resultWindowIsMaximized:
|
else:
|
||||||
self.setGeometry(self.app.prefs.resultWindowRect)
|
if self.app.prefs.resultWindowRect is not None:
|
||||||
|
self.setGeometry(self.app.prefs.resultWindowRect)
|
||||||
|
else:
|
||||||
|
moveToScreenCenter(self)
|
||||||
|
|
||||||
#--- Private
|
#--- Private
|
||||||
def _load_columns(self):
|
def _load_columns(self):
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class ResultsModel(Table):
|
|||||||
model = ResultTableModel(self, app)
|
model = ResultTableModel(self, app)
|
||||||
self._app = app
|
self._app = app
|
||||||
self._data = app.data
|
self._data = app.data
|
||||||
self._delta_columns = app.DELTA_COLUMNS
|
self._delta_columns = app.data.DELTA_COLUMNS
|
||||||
Table.__init__(self, model, view)
|
Table.__init__(self, model, view)
|
||||||
self.model.connect()
|
self.model.connect()
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class ResultsModel(Table):
|
|||||||
|
|
||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(self._data.COLUMNS):
|
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(self._data.COLUMNS):
|
||||||
return self._data.COLUMNS[section]['display']
|
return self._data.COLUMNS[section].display
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def setData(self, index, value, role):
|
def setData(self, index, value, role):
|
||||||
|
|||||||
@@ -244,7 +244,7 @@
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Excluded</source>
|
<source>Excluded</source>
|
||||||
<translation>Exclus</translation>
|
<translation>Exclu</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Problems!</source>
|
<source>Problems!</source>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class DupeGuru(DupeGuruBase):
|
|||||||
EDITION = 'me'
|
EDITION = 'me'
|
||||||
LOGO_NAME = 'logo_me'
|
LOGO_NAME = 'logo_me'
|
||||||
NAME = __appname__
|
NAME = __appname__
|
||||||
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7])
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
DupeGuruBase.__init__(self, data)
|
DupeGuruBase.__init__(self, data)
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ class DupeGuru(DupeGuruBase):
|
|||||||
EDITION = 'pe'
|
EDITION = 'pe'
|
||||||
LOGO_NAME = 'logo_pe'
|
LOGO_NAME = 'logo_pe'
|
||||||
NAME = __appname__
|
NAME = __appname__
|
||||||
DELTA_COLUMNS = frozenset([2, 5])
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
DupeGuruBase.__init__(self, data_pe)
|
DupeGuruBase.__init__(self, data_pe)
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ class DupeGuru(DupeGuruBase):
|
|||||||
EDITION = 'se'
|
EDITION = 'se'
|
||||||
LOGO_NAME = 'logo_se'
|
LOGO_NAME = 'logo_se'
|
||||||
NAME = __appname__
|
NAME = __appname__
|
||||||
DELTA_COLUMNS = frozenset([2, 4])
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
DupeGuruBase.__init__(self, data)
|
DupeGuruBase.__init__(self, data)
|
||||||
|
|||||||
Reference in New Issue
Block a user