mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-25 08:01:39 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
526bcf2566 | ||
|
|
56207f4dbb | ||
|
|
cd9fd3a10b | ||
|
|
4399fe9d17 | ||
|
|
2a6f524a5b | ||
|
|
caee5e37f0 | ||
|
|
bbd9d68dfd | ||
|
|
16b1b00906 |
1
.hgtags
1
.hgtags
@@ -48,3 +48,4 @@ ff43c6d9feb388f103b7857eaa6f7809185f78ec before-pluginbuilder
|
||||
d274bcb98f2d02b86470a04cd62e718eff33b74f pe2.1.0
|
||||
77e169f757195c11e9c1c5febeb2db8eb3589510 se3.0.2
|
||||
97893f37d7d0767b5aedf1b4b40de57ee36d426b se3.1.0
|
||||
e44d5127ed605daa7a17a01eee65d0a157de20c0 pe2.2.0
|
||||
|
||||
27
build.py
27
build.py
@@ -24,17 +24,15 @@ def parse_args():
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option('--clean', action='store_true', dest='clean',
|
||||
help="Clean build folder before building")
|
||||
parser.add_option('--only-help', action='store_true', dest='only_help',
|
||||
help="Build only help file")
|
||||
parser.add_option('--doc', action='store_true', dest='doc',
|
||||
help="Build only the help file")
|
||||
parser.add_option('--loc', action='store_true', dest='loc',
|
||||
help="Build only localization")
|
||||
(options, args) = parser.parse_args()
|
||||
return options
|
||||
|
||||
def build_cocoa(edition, dev):
|
||||
from pluginbuilder import build_plugin
|
||||
build_all_cocoa_locs('cocoalib')
|
||||
build_all_cocoa_locs(op.join('cocoa', 'base'))
|
||||
build_all_cocoa_locs(op.join('cocoa', edition))
|
||||
|
||||
print("Building dg_cocoa.plugin")
|
||||
if not dev:
|
||||
specific_packages = {
|
||||
@@ -83,8 +81,6 @@ def build_cocoa(edition, dev):
|
||||
open('run.py', 'wt').write(run_contents)
|
||||
|
||||
def build_qt(edition, dev):
|
||||
print("Building .ts files")
|
||||
build_all_qt_locs(op.join('qt', 'lang'), extradirs=[op.join('qtlib', 'lang')])
|
||||
print("Building Qt stuff")
|
||||
print_and_do("pyrcc4 -py3 {0} > {1}".format(op.join('qt', 'base', 'dg.qrc'), op.join('qt', 'base', 'dg_rc.py')))
|
||||
print("Creating the run.py file")
|
||||
@@ -104,6 +100,16 @@ def build_help(edition):
|
||||
confrepl = {'edition': edition, 'appname': appname, 'homepage': homepage}
|
||||
sphinxgen.gen(help_basepath, help_destpath, changelog_path, tixurl, confrepl)
|
||||
|
||||
def build_localizations(ui, edition):
|
||||
print("Building localizations")
|
||||
if ui == 'cocoa':
|
||||
build_all_cocoa_locs('cocoalib')
|
||||
build_all_cocoa_locs(op.join('cocoa', 'base'))
|
||||
build_all_cocoa_locs(op.join('cocoa', edition))
|
||||
elif ui == 'qt':
|
||||
print("Building .ts files")
|
||||
build_all_qt_locs(op.join('qt', 'lang'), extradirs=[op.join('qtlib', 'lang')])
|
||||
|
||||
def build_pe_modules(ui):
|
||||
def move(src, dst):
|
||||
if not op.exists(src):
|
||||
@@ -144,6 +150,7 @@ def build_normal(edition, ui, dev):
|
||||
print("Building dupeGuru {0} with UI {1}".format(edition.upper(), ui))
|
||||
add_to_pythonpath('.')
|
||||
build_help(edition)
|
||||
build_localizations(ui, edition)
|
||||
print("Building dupeGuru")
|
||||
if edition == 'pe':
|
||||
build_pe_modules(ui)
|
||||
@@ -165,8 +172,10 @@ def main():
|
||||
shutil.rmtree('build')
|
||||
if not op.exists('build'):
|
||||
os.mkdir('build')
|
||||
if options.only_help:
|
||||
if options.doc:
|
||||
build_help(edition)
|
||||
elif options.loc:
|
||||
build_localizations(ui, edition)
|
||||
else:
|
||||
build_normal(edition, ui, dev)
|
||||
|
||||
|
||||
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1050</int>
|
||||
<string key="IBDocument.SystemVersion">10J869</string>
|
||||
<string key="IBDocument.SystemVersion">10J4138</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">851</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.35</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
@@ -34,10 +34,6 @@
|
||||
<string key="NSClassName">NSApplication</string>
|
||||
</object>
|
||||
<object class="NSUserDefaultsController" id="455472712">
|
||||
<object class="NSMutableArray" key="NSDeclaredKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>scanType</string>
|
||||
</object>
|
||||
<bool key="NSSharedInstance">YES</bool>
|
||||
</object>
|
||||
<object class="NSWindowTemplate" id="809668081">
|
||||
@@ -232,7 +228,7 @@
|
||||
<object class="NSButtonCell" key="NSCell" id="911281323">
|
||||
<int key="NSCellFlags">67239424</int>
|
||||
<int key="NSCellFlags2">0</int>
|
||||
<string key="NSContents">Match scaled pictures together</string>
|
||||
<string key="NSContents">Match pictures of different dimensions</string>
|
||||
<reference key="NSSupport" ref="26"/>
|
||||
<reference key="NSControlView" ref="722670516"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
@@ -289,7 +285,7 @@
|
||||
<object class="NSTextField" id="403531548">
|
||||
<reference key="NSNextResponder" ref="1073354031"/>
|
||||
<int key="NSvFlags">256</int>
|
||||
<string key="NSFrame">{{301, 145}, {31, 14}}</string>
|
||||
<string key="NSFrame">{{301, 112}, {31, 14}}</string>
|
||||
<reference key="NSSuperview" ref="1073354031"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="983190380">
|
||||
@@ -386,7 +382,7 @@
|
||||
<object class="NSPopUpButton" id="337614813">
|
||||
<reference key="NSNextResponder" ref="1073354031"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{113, 135}, {216, 26}}</string>
|
||||
<string key="NSFrame">{{113, 135}, {219, 26}}</string>
|
||||
<reference key="NSSuperview" ref="1073354031"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSPopUpButtonCell" key="NSCell" id="697629846">
|
||||
@@ -988,26 +984,6 @@
|
||||
</object>
|
||||
<int key="connectionID">98</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBBindingConnection" key="connection">
|
||||
<string key="label">enabled: values.scanType</string>
|
||||
<reference key="source" ref="722670516"/>
|
||||
<reference key="destination" ref="455472712"/>
|
||||
<object class="NSNibBindingConnector" key="connector">
|
||||
<reference key="NSSource" ref="722670516"/>
|
||||
<reference key="NSDestination" ref="455472712"/>
|
||||
<string key="NSLabel">enabled: values.scanType</string>
|
||||
<string key="NSBinding">enabled</string>
|
||||
<string key="NSKeyPath">values.scanType</string>
|
||||
<object class="NSDictionary" key="NSOptions">
|
||||
<string key="NS.key.0">NSValueTransformerName</string>
|
||||
<string key="NS.object.0">vtScanTypeIsFuzzy</string>
|
||||
</object>
|
||||
<int key="NSNibBindingConnectorVersion">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<int key="connectionID">100</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<object class="NSArray" key="orderedObjects">
|
||||
@@ -1124,7 +1100,6 @@
|
||||
<reference key="object" ref="1073354031"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="403531548"/>
|
||||
<reference ref="266372855"/>
|
||||
<reference ref="869007847"/>
|
||||
<reference ref="171701149"/>
|
||||
@@ -1135,6 +1110,7 @@
|
||||
<reference ref="472028782"/>
|
||||
<reference ref="337614813"/>
|
||||
<reference ref="536472926"/>
|
||||
<reference ref="403531548"/>
|
||||
</object>
|
||||
<reference key="parent" ref="700068878"/>
|
||||
</object>
|
||||
@@ -1466,6 +1442,7 @@
|
||||
<string>10.IBViewBoundsToFrameTransform</string>
|
||||
<string>10.ImportedFromIB2</string>
|
||||
<string>11.IBPluginDependency</string>
|
||||
<string>11.IBViewBoundsToFrameTransform</string>
|
||||
<string>11.ImportedFromIB2</string>
|
||||
<string>12.IBPluginDependency</string>
|
||||
<string>12.IBViewBoundsToFrameTransform</string>
|
||||
@@ -1577,6 +1554,9 @@
|
||||
</object>
|
||||
<boolean value="YES"/>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
<bytes key="NSTransformStruct">P4AAAL+AAABDloAAwxAAAA</bytes>
|
||||
</object>
|
||||
<boolean value="YES"/>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
@@ -1606,9 +1586,9 @@
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>{{88, 591}, {392, 254}}</string>
|
||||
<string>{{413, 591}, {392, 254}}</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>{{88, 591}, {392, 254}}</string>
|
||||
<string>{{413, 591}, {392, 254}}</string>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<string>{213, 107}</string>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
/* Class = "NSMenuItem"; title = "Right in destination"; ObjectID = "30"; */
|
||||
"30.title" = "Directement à la destination";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Match scaled pictures together"; ObjectID = "31"; */
|
||||
/* Class = "NSButtonCell"; title = "Match pictures of different dimensions"; ObjectID = "31"; */
|
||||
"31.title" = "Comparer les images de tailles différentes";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Automatically check for updates"; ObjectID = "32"; */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1050</int>
|
||||
<string key="IBDocument.SystemVersion">10J869</string>
|
||||
<string key="IBDocument.SystemVersion">10J4138</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">851</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.35</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
@@ -209,7 +209,7 @@
|
||||
<reference key="NSControlView" ref="488256664"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<object class="NSCustomResource" key="NSNormalImage" id="596695557">
|
||||
<object class="NSCustomResource" key="NSNormalImage" id="949163782">
|
||||
<string key="NSClassName">NSImage</string>
|
||||
<string key="NSResourceName">NSSwitch</string>
|
||||
</object>
|
||||
@@ -236,7 +236,7 @@
|
||||
<reference key="NSControlView" ref="722670516"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<reference key="NSNormalImage" ref="596695557"/>
|
||||
<reference key="NSNormalImage" ref="949163782"/>
|
||||
<reference key="NSAlternateImage" ref="990345653"/>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
@@ -258,7 +258,7 @@
|
||||
<reference key="NSControlView" ref="472028782"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<reference key="NSNormalImage" ref="596695557"/>
|
||||
<reference key="NSNormalImage" ref="949163782"/>
|
||||
<reference key="NSAlternateImage" ref="990345653"/>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
@@ -280,7 +280,7 @@
|
||||
<reference key="NSControlView" ref="279087998"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<reference key="NSNormalImage" ref="596695557"/>
|
||||
<reference key="NSNormalImage" ref="949163782"/>
|
||||
<reference key="NSAlternateImage" ref="990345653"/>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
@@ -291,7 +291,7 @@
|
||||
<object class="NSTextField" id="403531548">
|
||||
<reference key="NSNextResponder" ref="1073354031"/>
|
||||
<int key="NSvFlags">256</int>
|
||||
<string key="NSFrame">{{301, 145}, {31, 14}}</string>
|
||||
<string key="NSFrame">{{301, 112}, {31, 14}}</string>
|
||||
<reference key="NSSuperview" ref="1073354031"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="983190380">
|
||||
@@ -388,7 +388,7 @@
|
||||
<object class="NSPopUpButton" id="337614813">
|
||||
<reference key="NSNextResponder" ref="1073354031"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{113, 135}, {216, 26}}</string>
|
||||
<string key="NSFrame">{{113, 135}, {219, 26}}</string>
|
||||
<reference key="NSSuperview" ref="1073354031"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSPopUpButtonCell" key="NSCell" id="697629846">
|
||||
@@ -479,7 +479,7 @@
|
||||
<reference key="NSControlView" ref="1018598123"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<reference key="NSNormalImage" ref="596695557"/>
|
||||
<reference key="NSNormalImage" ref="949163782"/>
|
||||
<reference key="NSAlternateImage" ref="990345653"/>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
@@ -501,7 +501,7 @@
|
||||
<reference key="NSControlView" ref="519470955"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<reference key="NSNormalImage" ref="596695557"/>
|
||||
<reference key="NSNormalImage" ref="949163782"/>
|
||||
<reference key="NSAlternateImage" ref="990345653"/>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
@@ -523,7 +523,7 @@
|
||||
<reference key="NSControlView" ref="606836304"/>
|
||||
<int key="NSButtonFlags">1211912703</int>
|
||||
<int key="NSButtonFlags2">2</int>
|
||||
<reference key="NSNormalImage" ref="596695557"/>
|
||||
<reference key="NSNormalImage" ref="949163782"/>
|
||||
<reference key="NSAlternateImage" ref="990345653"/>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
@@ -992,26 +992,6 @@
|
||||
</object>
|
||||
<int key="connectionID">98</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBBindingConnection" key="connection">
|
||||
<string key="label">enabled: values.scanType</string>
|
||||
<reference key="source" ref="722670516"/>
|
||||
<reference key="destination" ref="455472712"/>
|
||||
<object class="NSNibBindingConnector" key="connector">
|
||||
<reference key="NSSource" ref="722670516"/>
|
||||
<reference key="NSDestination" ref="455472712"/>
|
||||
<string key="NSLabel">enabled: values.scanType</string>
|
||||
<string key="NSBinding">enabled</string>
|
||||
<string key="NSKeyPath">values.scanType</string>
|
||||
<object class="NSDictionary" key="NSOptions">
|
||||
<string key="NS.key.0">NSValueTransformerName</string>
|
||||
<string key="NS.object.0">vtScanTypeIsFuzzy</string>
|
||||
</object>
|
||||
<int key="NSNibBindingConnectorVersion">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<int key="connectionID">100</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<object class="NSArray" key="orderedObjects">
|
||||
@@ -1128,7 +1108,6 @@
|
||||
<reference key="object" ref="1073354031"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="403531548"/>
|
||||
<reference ref="266372855"/>
|
||||
<reference ref="869007847"/>
|
||||
<reference ref="171701149"/>
|
||||
@@ -1139,6 +1118,7 @@
|
||||
<reference ref="472028782"/>
|
||||
<reference ref="337614813"/>
|
||||
<reference ref="536472926"/>
|
||||
<reference ref="403531548"/>
|
||||
</object>
|
||||
<reference key="parent" ref="700068878"/>
|
||||
</object>
|
||||
@@ -1470,6 +1450,7 @@
|
||||
<string>10.IBViewBoundsToFrameTransform</string>
|
||||
<string>10.ImportedFromIB2</string>
|
||||
<string>11.IBPluginDependency</string>
|
||||
<string>11.IBViewBoundsToFrameTransform</string>
|
||||
<string>11.ImportedFromIB2</string>
|
||||
<string>12.IBPluginDependency</string>
|
||||
<string>12.IBViewBoundsToFrameTransform</string>
|
||||
@@ -1582,6 +1563,9 @@
|
||||
</object>
|
||||
<boolean value="YES"/>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
<bytes key="NSTransformStruct">P4AAAL+AAABDloAAwxAAAA</bytes>
|
||||
</object>
|
||||
<boolean value="YES"/>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
@@ -1611,9 +1595,9 @@
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>{{88, 591}, {392, 254}}</string>
|
||||
<string>{{413, 591}, {392, 254}}</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>{{88, 591}, {392, 254}}</string>
|
||||
<string>{{413, 591}, {392, 254}}</string>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<string>{1.79769e+308, 1.79769e+308}</string>
|
||||
|
||||
@@ -92,10 +92,13 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
||||
logging.warning("Exception on GetDisplayInfo for %s: %s", str(dupe.path), str(e))
|
||||
return ['---'] * len(self.data.COLUMNS)
|
||||
|
||||
def _create_file(self, path):
|
||||
# We add fs.Folder to fileclasses in case the file we're loading contains folder paths.
|
||||
return fs.get_file(path, self.directories.fileclasses + [fs.Folder])
|
||||
|
||||
def _get_file(self, str_path):
|
||||
path = Path(str_path)
|
||||
# We add fs.Folder to fileclasses in case the file we're loading contains folder paths.
|
||||
f = fs.get_file(path, self.directories.fileclasses + [fs.Folder])
|
||||
f = self._create_file(path)
|
||||
if f is None:
|
||||
return None
|
||||
try:
|
||||
|
||||
@@ -14,9 +14,6 @@ import time
|
||||
|
||||
Column = namedtuple('Column', 'attr display')
|
||||
|
||||
def format_path(p):
|
||||
return str(p[:-1])
|
||||
|
||||
def format_timestamp(t, delta):
|
||||
if delta:
|
||||
return format_time_decimal(t)
|
||||
|
||||
@@ -149,6 +149,10 @@ class File:
|
||||
def name(self):
|
||||
return self.path[-1]
|
||||
|
||||
@property
|
||||
def folder_path(self):
|
||||
return self.path[:-1]
|
||||
|
||||
|
||||
class Folder(File):
|
||||
"""A wrapper around a folder path.
|
||||
|
||||
@@ -328,15 +328,13 @@ class Results(Markable):
|
||||
def sort_dupes(self, key, asc=True, delta=False):
|
||||
if not self.__dupes:
|
||||
self.__get_dupe_list()
|
||||
self.__dupes.sort(key=lambda d: self.data.GetDupeSortKey(d, lambda: self.get_group_of_duplicate(d), key, delta))
|
||||
if not asc:
|
||||
self.__dupes.reverse()
|
||||
keyfunc = lambda d: self.data.GetDupeSortKey(d, lambda: self.get_group_of_duplicate(d), key, delta)
|
||||
self.__dupes.sort(key=keyfunc, reverse=not asc)
|
||||
self.__dupes_sort_descriptor = (key,asc,delta)
|
||||
|
||||
def sort_groups(self,key,asc=True):
|
||||
self.groups.sort(key=lambda g: self.data.GetGroupSortKey(g, key))
|
||||
if not asc:
|
||||
self.groups.reverse()
|
||||
keyfunc = lambda g: self.data.GetGroupSortKey(g, key)
|
||||
self.groups.sort(key=keyfunc, reverse=not asc)
|
||||
self.__groups_sort_descriptor = (key,asc)
|
||||
|
||||
#---Properties
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
# data module for tests
|
||||
|
||||
from hscommon.util import format_size
|
||||
from ..data import format_path, cmp_value, Column
|
||||
from ..data import cmp_value, Column
|
||||
|
||||
COLUMNS = [
|
||||
Column('name', 'Filename'),
|
||||
Column('path', 'Directory'),
|
||||
Column('folder_path', 'Directory'),
|
||||
Column('size', 'Size (KB)'),
|
||||
Column('extension', 'Kind'),
|
||||
]
|
||||
@@ -29,7 +29,7 @@ def GetDisplayInfo(dupe, group, delta):
|
||||
size -= r.size
|
||||
return [
|
||||
dupe.name,
|
||||
format_path(dupe.path),
|
||||
str(dupe.folder_path),
|
||||
format_size(size, 0, 1, False),
|
||||
dupe.extension if hasattr(dupe, 'extension') else '---',
|
||||
]
|
||||
|
||||
@@ -26,6 +26,11 @@ class NamedObject(engine_test.NamedObject):
|
||||
|
||||
def __bool__(self):
|
||||
return False #Make sure that operations are made correctly when the bool value of files is false.
|
||||
|
||||
@property
|
||||
def folder_path(self):
|
||||
return self.path[:-1]
|
||||
|
||||
|
||||
# Returns a group set that looks like that:
|
||||
# "foo bar" (1)
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
from hscommon.util import format_time, format_size
|
||||
from hscommon.trans import tr as trbase
|
||||
from core.data import (format_path, format_timestamp, format_words, format_perc,
|
||||
format_dupe_count, cmp_value, Column)
|
||||
from core.data import (format_timestamp, format_words, format_perc, format_dupe_count, cmp_value,
|
||||
Column)
|
||||
|
||||
tr = lambda s: trbase(s, 'columns')
|
||||
|
||||
COLUMNS = [
|
||||
Column('name', tr("Filename")),
|
||||
Column('path', tr("Folder")),
|
||||
Column('folder_path', tr("Folder")),
|
||||
Column('size', tr("Size (MB)")),
|
||||
Column('duration', tr("Time")),
|
||||
Column('bitrate', tr("Bitrate")),
|
||||
@@ -63,7 +63,7 @@ def GetDisplayInfo(dupe, group, delta):
|
||||
dupe_count = len(group.dupes)
|
||||
return [
|
||||
dupe.name,
|
||||
format_path(dupe.path),
|
||||
str(dupe.folder_path),
|
||||
format_size(size, 2, 2, False),
|
||||
format_time(duration, with_hours=False),
|
||||
str(bitrate),
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
__version__ = '2.2.0'
|
||||
__version__ = '2.2.1'
|
||||
__appname__ = 'dupeGuru Picture Edition'
|
||||
@@ -28,7 +28,7 @@ IPHOTO_PATH = Path('iPhoto Library')
|
||||
|
||||
class Photo(PhotoBase):
|
||||
HANDLED_EXTS = PhotoBase.HANDLED_EXTS.copy()
|
||||
HANDLED_EXTS.update({'psd', 'nef', 'cr2'})
|
||||
HANDLED_EXTS.update({'psd', 'nef', 'cr2', 'orf'})
|
||||
|
||||
def _plat_get_dimensions(self):
|
||||
return _block_osx.get_image_size(str(self.path))
|
||||
@@ -45,8 +45,8 @@ class Photo(PhotoBase):
|
||||
|
||||
class IPhoto(Photo):
|
||||
@property
|
||||
def display_path(self):
|
||||
return Path(('iPhoto Library', self.name))
|
||||
def display_folder_path(self):
|
||||
return IPHOTO_PATH
|
||||
|
||||
def get_iphoto_database_path():
|
||||
ud = NSUserDefaults.standardUserDefaults()
|
||||
@@ -166,11 +166,10 @@ class DupeGuruPE(app_cocoa.DupeGuru):
|
||||
else:
|
||||
app_cocoa.DupeGuru._do_delete_dupe(self, dupe, replace_with_hardlinks)
|
||||
|
||||
def _get_file(self, str_path):
|
||||
p = Path(str_path)
|
||||
if (self.directories.iphoto_libpath is not None) and (p in self.directories.iphoto_libpath[:-1]):
|
||||
return IPhoto(p)
|
||||
return app_cocoa.DupeGuru._get_file(self, str_path)
|
||||
def _create_file(self, path):
|
||||
if (self.directories.iphoto_libpath is not None) and (path in self.directories.iphoto_libpath[:-1]):
|
||||
return IPhoto(path)
|
||||
return app_cocoa.DupeGuru._create_file(self, path)
|
||||
|
||||
def copy_or_move(self, dupe, copy, destination, dest_type):
|
||||
if isinstance(dupe, IPhoto):
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
from hscommon.util import format_size
|
||||
from hscommon.trans import tr as trbase
|
||||
from core.data import format_path, format_timestamp, format_perc, format_dupe_count, cmp_value, Column
|
||||
from core.data import format_timestamp, format_perc, format_dupe_count, cmp_value, Column
|
||||
|
||||
tr = lambda s: trbase(s, 'columns')
|
||||
|
||||
@@ -17,7 +17,7 @@ def format_dimensions(dimensions):
|
||||
|
||||
COLUMNS = [
|
||||
Column('name', tr("Filename")),
|
||||
Column('path', tr("Folder")),
|
||||
Column('folder_path', tr("Folder")),
|
||||
Column('size', tr("Size (KB)")),
|
||||
Column('extension', tr("Kind")),
|
||||
Column('dimensions', tr("Dimensions")),
|
||||
@@ -26,6 +26,7 @@ COLUMNS = [
|
||||
Column('dupe_count', tr("Dupe Count")),
|
||||
]
|
||||
|
||||
FOLDER_COL = 1
|
||||
MATCHPERC_COL = 6
|
||||
DUPECOUNT_COL = 7
|
||||
DELTA_COLUMNS = {2, 4, 5}
|
||||
@@ -53,10 +54,10 @@ def GetDisplayInfo(dupe,group,delta=False):
|
||||
else:
|
||||
percentage = group.percentage
|
||||
dupe_count = len(group.dupes)
|
||||
dupe_path = getattr(dupe, 'display_path', dupe.path)
|
||||
dupe_folder_path = getattr(dupe, 'display_folder_path', dupe.folder_path)
|
||||
return [
|
||||
dupe.name,
|
||||
format_path(dupe_path),
|
||||
str(dupe_folder_path),
|
||||
format_size(size, 0, 1, False),
|
||||
dupe.extension,
|
||||
format_dimensions(dimensions),
|
||||
@@ -71,6 +72,9 @@ def GetDupeSortKey(dupe, get_group, key, delta):
|
||||
return m.percentage
|
||||
if key == DUPECOUNT_COL:
|
||||
return 0
|
||||
if key == FOLDER_COL:
|
||||
dupe_folder_path = getattr(dupe, 'display_folder_path', dupe.folder_path)
|
||||
return cmp_value(str(dupe_folder_path))
|
||||
r = cmp_value(getattr(dupe, COLUMNS[key].attr, ''))
|
||||
if delta and (key in DELTA_COLUMNS):
|
||||
ref_value = cmp_value(getattr(get_group().ref, COLUMNS[key].attr, ''))
|
||||
@@ -85,5 +89,8 @@ def GetGroupSortKey(group, key):
|
||||
return group.percentage
|
||||
if key == DUPECOUNT_COL:
|
||||
return len(group)
|
||||
if key == FOLDER_COL:
|
||||
dupe_folder_path = getattr(group.ref, 'display_folder_path', group.ref.folder_path)
|
||||
return cmp_value(str(dupe_folder_path))
|
||||
return cmp_value(getattr(group.ref, COLUMNS[key].attr, ''))
|
||||
|
||||
|
||||
@@ -154,6 +154,12 @@ GPS_TA0GS = {
|
||||
INTEL_ENDIAN = ord('I')
|
||||
MOTOROLA_ENDIAN = ord('M')
|
||||
|
||||
# About MAX_COUNT: It's possible to have corrupted exif tags where the entry count is way too high
|
||||
# and thus makes us loop, not endlessly, but for heck of a long time for nothing. Therefore, we put
|
||||
# an arbitrary limit on the entry count we'll allow ourselves to read and any IFD reporting more
|
||||
# entries than that will be considered corrupt.
|
||||
MAX_COUNT = 0xffff
|
||||
|
||||
def s2n_motorola(bytes):
|
||||
x = 0
|
||||
for c in bytes:
|
||||
@@ -214,6 +220,9 @@ class TIFF_file:
|
||||
def dump_IFD(self, ifd):
|
||||
entries = self.s2n(ifd, 2)
|
||||
logging.debug("Entries for IFD %d: %d", ifd, entries)
|
||||
if entries > MAX_COUNT:
|
||||
logging.debug("Probably corrupt. Aborting.")
|
||||
return []
|
||||
a = []
|
||||
for i in range(entries):
|
||||
entry = ifd + 2 + 12*i
|
||||
@@ -223,6 +232,9 @@ class TIFF_file:
|
||||
continue # not handled
|
||||
typelen = [ 1, 1, 2, 4, 8, 1, 1, 2, 4, 8 ] [type-1]
|
||||
count = self.s2n(entry+4, 4)
|
||||
if count > MAX_COUNT:
|
||||
logging.debug("Probably corrupt. Aborting.")
|
||||
return []
|
||||
offset = entry+8
|
||||
if count*typelen > 4:
|
||||
offset = self.s2n(offset, 4)
|
||||
|
||||
@@ -16,7 +16,7 @@ from hscommon.trans import tr
|
||||
from core.engine import Match
|
||||
from . import exif
|
||||
|
||||
def getmatches(files, j):
|
||||
def getmatches(files, match_scaled, j):
|
||||
timestamp2pic = defaultdict(set)
|
||||
for picture in j.iter_with_progress(files, tr("Read EXIF of %d/%d pictures")):
|
||||
try:
|
||||
@@ -30,5 +30,8 @@ def getmatches(files, j):
|
||||
del timestamp2pic['0000:00:00 00:00:00']
|
||||
matches = []
|
||||
for pictures in timestamp2pic.values():
|
||||
matches += [Match(p1, p2, 100) for p1, p2 in combinations(pictures, 2)]
|
||||
for p1, p2 in combinations(pictures, 2):
|
||||
if (not match_scaled) and (p1.dimensions != p2.dimensions):
|
||||
continue
|
||||
matches.append(Match(p1, p2, 100))
|
||||
return matches
|
||||
@@ -20,7 +20,7 @@ class ScannerPE(Scanner):
|
||||
if self.scan_type == ScanType.FuzzyBlock:
|
||||
return matchblock.getmatches(files, self.cache_path, self.threshold, self.match_scaled, j)
|
||||
elif self.scan_type == ScanType.ExifTimestamp:
|
||||
return matchexif.getmatches(files, j)
|
||||
return matchexif.getmatches(files, self.match_scaled, j)
|
||||
else:
|
||||
raise Exception("Invalid scan type")
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
from hscommon.util import format_size
|
||||
from hscommon.trans import tr as trbase
|
||||
from core.data import (format_path, format_timestamp, format_words, format_perc,
|
||||
format_dupe_count, cmp_value, Column)
|
||||
from core.data import (format_timestamp, format_words, format_perc, format_dupe_count, cmp_value,
|
||||
Column)
|
||||
|
||||
tr = lambda s: trbase(s, 'columns')
|
||||
|
||||
COLUMNS = [
|
||||
Column('name', tr("Filename")),
|
||||
Column('path', tr("Folder")),
|
||||
Column('folder_path', tr("Folder")),
|
||||
Column('size', tr("Size (KB)")),
|
||||
Column('extension', tr("Kind")),
|
||||
Column('mtime', tr("Modification")),
|
||||
@@ -46,7 +46,7 @@ def GetDisplayInfo(dupe, group, delta):
|
||||
dupe_count = len(group.dupes)
|
||||
return [
|
||||
dupe.name,
|
||||
format_path(dupe.path),
|
||||
str(dupe.folder_path),
|
||||
format_size(size, 0, 1, False),
|
||||
dupe.extension,
|
||||
format_timestamp(mtime, delta and m),
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
=== 2.2.1 (2011-06-15)
|
||||
|
||||
* Brought back the filter hardness label which disappeared in 2.2.0. [Mac OS X] (#164)
|
||||
* Added support for Olympus RAW files (.orf). [Mac OS X] (#159)
|
||||
* Fixed a bug causing the picture analysis to stall on some corrupt EXIF data.
|
||||
* Make the "Match scaled pictures" option apply to the new EXIF timestamp scan. (#162)
|
||||
* Fixed glitch in the sorting feature of the Folder column. (#161)
|
||||
|
||||
=== 2.2.0 (2011-06-02)
|
||||
|
||||
* Added the EXIF Timestamp scan type.
|
||||
|
||||
@@ -32,11 +32,11 @@ Preferences
|
||||
|
||||
.. only:: edition_pe
|
||||
|
||||
**Scan Type:** This option determines the type of scan that will be made on your pictures. The **Contents** scan type compares the actual contents of the pictures in a fuzzy way (making it possible to find not only exact duplicates, but also similar ones). The **EXIF Timestamp** scan type looks at the EXIF metadata of the picture (if it exists) and matches pictures that have the same one. It's much faster than the Contents scan.
|
||||
**Scan Type:** This option determines the type of scan that will be made on your pictures. The **Contents** scan type compares the actual contents of the pictures in a fuzzy way (making it possible to find not only exact duplicates, but also similar ones). The **EXIF Timestamp** scan type looks at the EXIF metadata of the picture (if it exists) and matches pictures that have the same one. It's much faster than the Contents scan. **Warning:** Modified pictures often keep the same EXIF timestamp, so watch out for false positives when you use that scan type.
|
||||
|
||||
**Filter Hardness:** *Contents scan type only.* The higher is this setting, the "harder" is the filter (In other words, the less results you get). Most pictures of the same quality match at 100% even if the format is different (PNG and JPG for example.). However, if you want to make a PNG match with a lower quality JPG, you will have to set the filer hardness to lower than 100. The default, 95, is a sweet spot.
|
||||
|
||||
**Match scaled pictures together:** *Contents scan type only.* If you check this box, pictures of different dimensions will be allowed in the same duplicate group.
|
||||
**Match pictures of different dimensions:** If you check this box, pictures of different dimensions will be allowed in the same duplicate group.
|
||||
|
||||
**Can mix file kind:** If you check this box, duplicate groups are allowed to have files with different extensions. If you don't check it, well, they aren't!
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@ Préférences
|
||||
|
||||
.. only:: edition_pe
|
||||
|
||||
**Type de scan:** Détermine le type de scan qui sera fait sur vos images. Le type **Contenu** compare le contenu des images de façon "fuzzy", rendant possible de trouver non seulement les doublons exactes, mais aussi les similaires. Le type **EXIF Timestamp** compare les métadonnées EXIF des images (si existantes) et détermine si le "timestamp" (moment de prise de la photo) est pareille. C'est beaucoup plus rapide que le scan par Contenu.
|
||||
**Type de scan:** Détermine le type de scan qui sera fait sur vos images. Le type **Contenu** compare le contenu des images de façon "fuzzy", rendant possible de trouver non seulement les doublons exactes, mais aussi les similaires. Le type **EXIF Timestamp** compare les métadonnées EXIF des images (si existantes) et détermine si le "timestamp" (moment de prise de la photo) est pareille. C'est beaucoup plus rapide que le scan par Contenu. **Attention:** Les photos modifiées gardent souvent le même timestamp, donc faites attention aux faux doublons si vous utilisez cette méthode.
|
||||
|
||||
**Seuil du filtre:** *Scan par Contenu seulement.* Plus il est élevé, plus les images doivent être similaires pour être considérées comme des doublons. Le défaut de 95% permet quelques petites différence, comme par exemple une différence de qualité ou bien une légère modification des couleurs.
|
||||
|
||||
**Comparer les images de tailles différentes:** *Scan par Contenu seulement.* Le nom dit tout. Sans cette option, les images de tailles différentes ne sont pas comparées.
|
||||
**Comparer les images de tailles différentes:** Le nom dit tout. Sans cette option, les images de tailles différentes ne sont pas comparées.
|
||||
|
||||
**Comparer les fichiers de différents types:** Sans cette option, seulement les fichiers du même type seront comparés.
|
||||
|
||||
|
||||
@@ -530,7 +530,7 @@
|
||||
<translation>Année</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Match scaled pictures together</source>
|
||||
<source>Match pictures of different dimensions</source>
|
||||
<translation>Comparer les images de tailles différentes</translation>
|
||||
</message>
|
||||
<message>
|
||||
|
||||
@@ -32,7 +32,7 @@ class PreferencesDialog(PreferencesDialogBase):
|
||||
self._setupScanTypeBox(scanTypeLabels)
|
||||
self._setupFilterHardnessBox()
|
||||
self.widgetsVLayout.addLayout(self.filterHardnessHLayout)
|
||||
self._setupAddCheckbox('matchScaledBox', tr("Match scaled pictures together"))
|
||||
self._setupAddCheckbox('matchScaledBox', tr("Match pictures of different dimensions"))
|
||||
self.widgetsVLayout.addWidget(self.matchScaledBox)
|
||||
self._setupAddCheckbox('mixFileKindBox', tr("Can mix file kind"))
|
||||
self.widgetsVLayout.addWidget(self.mixFileKindBox)
|
||||
@@ -63,7 +63,6 @@ class PreferencesDialog(PreferencesDialogBase):
|
||||
scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()]
|
||||
fuzzy_scan = scan_type == ScanType.FuzzyBlock
|
||||
self.filterHardnessSlider.setEnabled(fuzzy_scan)
|
||||
self.matchScaledBox.setEnabled(fuzzy_scan)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user