1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-25 08:01:39 +00:00

Compare commits

...

70 Commits

Author SHA1 Message Date
Virgil Dupras
e86b23259c Improved selection handling during ref-swapping under dupes-only mode.
Previously, our selection would simply be lost (because the dupes that were
just swapped wouldn't be present in the table). Now, instead of trying to
preserve our dupe-selection, we preserve our index-selection when in dupes-only
mode. [#222]
2013-04-28 16:27:45 -04:00
Virgil Dupras
89955aa96a Sync locs with Transifex (BR loc by Victor Figueiredo). 2013-04-28 16:15:58 -04:00
Virgil Dupras
39a601e393 Merge heads. 2013-04-28 14:57:16 -04:00
Virgil Dupras
3b9e11d14f se v3.6.1 2013-04-28 14:56:54 -04:00
Virgil Dupras
81a7c4d6a6 Sync locs with Transifex (BR loc by Victor Figueiredo). 2013-04-28 14:45:35 -04:00
Virgil Dupras
35a162faf4 Added "..." next to "Re-Prioritize Results" in cocoa's main menu.
[#225 state:fixed]
2013-04-28 14:32:57 -04:00
Virgil Dupras
70e505ad92 Tweaked Make Selected into Reference.
Having dupes from ref folders (which makes ref switching impossible) would make
the new feature glitchy (selection would be emptied). Now, in cases where the action
results in nothing being changed, the selection stays intact. [#222]
2013-04-28 14:12:08 -04:00
Virgil Dupras
aa3cf9700d Changed the shebang line to #!/usr/bin/python3 under Qt.
This way, the activity monitor correctly shows the app name instead of showing
"python3".
2013-04-28 11:38:41 -04:00
Virgil Dupras
e4b949abf6 README tweak again. 2013-04-28 11:06:48 -04:00
Virgil Dupras
2e23303d7e README tweak. 2013-04-28 11:04:34 -04:00
Virgil Dupras
2fcaacd285 Updated README which was somewhat outdated. 2013-04-28 11:03:38 -04:00
Virgil Dupras
6627f0dbea Renaming README to make Bitbucket correctly format it.
--HG--
rename : README => README.rst
2013-04-28 10:51:11 -04:00
Virgil Dupras
a64b42de65 Oops, there wasn't only one place to fix in [49fa0fc]. 2013-04-28 10:46:36 -04:00
Virgil Dupras
6dddcb1a47 Fixed scanner_test which was broken.
The monkeypatching made to hscommon.io wasn't correctly transferred to Path
after the migration at [dfc82cd].
2013-04-28 10:43:20 -04:00
Virgil Dupras
4a8ce9b6c4 Updated copyright year to 2013. 2013-04-28 10:35:51 -04:00
Virgil Dupras
d4e6632e7e Fixed typo in messages.
Sucessfully --> Successfully. [#216 state:fixed]
2013-04-28 10:20:59 -04:00
Virgil Dupras
0ced3e39c8 Allow "Open selected" to open more than one file at once.
When there's mpre than 10 selected dupes, a warning is shown, asking
confirmation. [#142 state:fixed]
2013-04-28 10:12:25 -04:00
Virgil Dupras
26d923e175 Updated localizations from Transifex. 2013-04-27 10:42:55 -04:00
Virgil Dupras
592eba9eaa [#222] Tweaked dupe selection after a ref-swapping action. 2013-04-27 10:08:38 -04:00
Virgil Dupras
11450ae56a [#222] Tweaked ref-swapping action text.
Make Selected Reference --> Make Selected into Reference.
2013-04-27 09:38:08 -04:00
Virgil Dupras
008bd1414e Added tag pe2.7.0-arch for changeset 286ba6959cd0 2013-04-14 18:13:38 -04:00
Virgil Dupras
62f6cc3705 Added tag me6.5.0-arch for changeset df6e045b9e76 2013-04-14 17:59:23 -04:00
Virgil Dupras
e16041c703 Added tag se3.6.0-arch for changeset 6b42e0d5628b 2013-04-14 17:46:54 -04:00
Virgil Dupras
1103b58ec5 Fixed Arch packaging. 2013-04-14 17:39:13 -04:00
Virgil Dupras
dc8b1b3b02 Fixed typo in packaging. 2013-04-14 17:37:01 -04:00
Virgil Dupras
36b214443a Added packaging support for Arch Linux. 2013-04-14 17:21:08 -04:00
Virgil Dupras
d11e20f6ba Adapted to fairware changes. 2013-03-24 18:53:41 -04:00
Virgil Dupras
477f73ffa4 Make build and package work with a 64bit Windows install. 2013-03-24 12:02:41 -04:00
Virgil Dupras
0b5cd61540 Updated subrepo. 2013-03-24 11:33:08 -04:00
Virgil Dupras
17b5703885 While keeping demo dialogs, removed fairware dialogs.
Npw, when in "fairware mode", we simply show no dialog at all.
2013-03-24 11:27:02 -04:00
Virgil Dupras
7cac0b5d6e Added missing import in build script. 2013-03-24 11:15:27 -04:00
Virgil Dupras
a4003b6072 Removed fairware dialogs under Linux. 2013-03-24 11:10:07 -04:00
Virgil Dupras
fb26d7d077 When under Linux, load qt_*.qm files from the system Qt.
We previously bundled up these files in the .deb, but this was unnecessary.
2013-03-24 11:06:08 -04:00
Virgil Dupras
f2cbb513d3 Fixed build.py --updatepot on non-OSX systems.
Previously, when running this command on non-OSX system, the ui.pot file would
lose all its previsouly cocoa-related strings.
2013-03-24 10:59:41 -04:00
Virgil Dupras
8c36218150 In addition to EnvironmentError, catch UnicodeEncodeError when performing actions on marked duplicates.
When running dupeGuru under Linux with a messed up locale, it's
UnicodeEncodeError we get. Instead of popping a reportable traceback, it's
better to just pop the Problems dialog up.
2012-10-28 11:06:09 -04:00
Virgil Dupras
7637e493a6 In Debian packaging, create package for both precise and quantal. 2012-10-26 10:23:50 -04:00
Virgil Dupras
62be8da6f9 Pulled localizations from Transifex. 2012-10-24 16:45:25 -04:00
Virgil Dupras
b1c2941616 Fixed cocoa dev builds which were badly broken. 2012-09-14 12:55:53 -04:00
Virgil Dupras
8efd3033a3 Removed pluginbuilder usage in build script and replaced it with hscommon functions. 2012-09-10 15:37:57 -04:00
Virgil Dupras
d417dbd2e3 Removed code duplication with hscommon in the build script. 2012-09-10 10:14:50 -04:00
Virgil Dupras
3a717a86d8 Added Transifex config file. 2012-09-05 08:52:04 -07:00
Virgil Dupras
e1f7260774 Removed duplicate entries in some PO files. 2012-09-05 11:29:09 -04:00
Virgil Dupras
bfc1ee90ec Added "Content-Transfer-Encoding: utf-8\n" to po files. 2012-09-05 11:18:06 -04:00
Virgil Dupras
93a5fd01b5 Added "Content-Transfer-Encoding: utf-8\n" to pot files. 2012-09-05 11:15:18 -04:00
Virgil Dupras
b028670250 Updated locs and improved brazilian loc with Victor Figueiredo's tips. 2012-08-30 16:09:33 -04:00
Virgil Dupras
dff141e800 Renamed cocoa/base/ResultWindow to ResultWindowBase to avoid ambiguities in the result_winodw cocoa UI script.
--HG--
rename : cocoa/base/ResultWindow.h => cocoa/base/ResultWindowBase.h
rename : cocoa/base/ResultWindow.m => cocoa/base/ResultWindowBase.m
2012-08-30 16:08:21 -04:00
Virgil Dupras
f49c7dee96 Fixed cocoa build script to work with Python 3.3. 2012-08-30 15:35:18 -04:00
Virgil Dupras
5da793b029 Fixed wrong assignment in result_window cocoa ui. 2012-08-15 15:16:29 -04:00
Virgil Dupras
a56258f8b3 Fixed debian packaging to not include the recently moved qt run template. 2012-08-15 08:07:32 -07:00
Virgil Dupras
ab6e0945a7 Added the 'ubuntu-store' configuration option to build a package that is already registered for the Ubuntu Store. 2012-08-15 08:01:29 -07:00
Virgil Dupras
8ac035c8a9 Moved run templates from root folder to cocoa/qt subfolders.
--HG--
rename : run_template_cocoa.py => cocoa/run_template.py
rename : run_template_qt.py => qt/run_template.py
2012-08-15 07:33:01 -07:00
Virgil Dupras
1c15b0114b Updated subrepo URLs to use HTTPS instead of HTTP. 2012-08-15 07:27:57 -07:00
Virgil Dupras
e78b14f9a2 Added tag pe2.7.0 for changeset d773721e6c32 2012-08-11 12:31:33 -04:00
Virgil Dupras
573d088088 pe v2.7.0 2012-08-11 12:00:16 -04:00
Virgil Dupras
75b08125c0 [#201 state:fixed] Added an EXIF Timestamp column in PE. 2012-08-10 16:34:27 -04:00
Virgil Dupras
20320f539f [#199 state:fixed] Added a mtime column to PE's cache DB so that we can purge outdated caches. 2012-08-10 15:58:37 -04:00
Virgil Dupras
24771af955 Removed obsolete hgignore entries. 2012-08-10 15:15:38 -04:00
Virgil Dupras
2bfe9960f1 Fixed typo in changelog. 2012-08-10 11:13:23 -04:00
Virgil Dupras
215bcb0d76 Added tag me6.5.0 for changeset 8f478379ec62 2012-08-10 11:07:03 -04:00
Virgil Dupras
2dbf8b80ae Updated hsaudiotag version req. 2012-08-10 10:30:50 -04:00
Virgil Dupras
470cd92030 me v6.5.0 2012-08-10 10:23:35 -04:00
Virgil Dupras
111edc3ce5 Fixed a bug causing groups with more than one ref file in it to appear (which looks weird and messes with selection).
Contents scans already weeded them out, bu t they were still possible with name-based scans. Now, the Scanner removes them all.
2012-08-09 11:16:06 -04:00
Virgil Dupras
df30a31782 Refactoring: Began to phase out to the use of hscommon.io in favor of Path methods. 2012-08-09 10:53:24 -04:00
Virgil Dupras
91f3a59523 Fixed add_directory() test which were broken. 2012-08-09 10:22:04 -04:00
Virgil Dupras
3441e51c0e [#200 state:fixed] Fixed a KeyError wihle parsing iTunes XML. 2012-08-09 10:01:44 -04:00
Virgil Dupras
a99c40b5d8 Updated PO files from POTs. 2012-08-09 09:58:14 -04:00
Virgil Dupras
5b4de58c38 Oops, I had forgot one of the credits file. 2012-08-08 16:53:08 -04:00
Virgil Dupras
cd83b16dbd Added Kyrill Detinov to credits for russian loc improvements. 2012-08-08 16:39:17 -04:00
Virgil Dupras
b67db988ab Improvement to the Russian loc by Kyrill Detinov. 2012-08-08 16:32:14 -04:00
Virgil Dupras
7ebea44cb0 Added tag se3.6.0 for changeset 0f18c4498a6c 2012-08-08 11:27:04 -04:00
223 changed files with 5565 additions and 4818 deletions

View File

@@ -8,26 +8,15 @@ run.py
*.pyd *.pyd
*.waf* *.waf*
.lock-waf* .lock-waf*
*.xcodeproj/xcuserdata
*.xcodeproj/project.xcworkspace/xcuserdata
conf.json conf.json
build build
dist dist
install install
installer_tmp-cache installer_tmp-cache
env
cocoa/autogen cocoa/autogen
cocoa/*/Info.plist cocoa/*/Info.plist
cocoa/*/build cocoa/*/build
cocoa/*/*.app
cs.lproj
de.lproj
fr.lproj
it.lproj
hy.lproj
ru.lproj
uk.lproj
zh_CN.lproj
pt_BR.lproj
qt/base/*_rc.py qt/base/*_rc.py
help/*/conf.py help/*/conf.py
help/*/changelog.rst help/*/changelog.rst

View File

@@ -78,3 +78,9 @@ c3d9f91dc9c9d60f370c72bc211f09be3e4fc18d se3.5.0
e772f1de86744999ffbbe5845554417965b1dfba me6.4.1 e772f1de86744999ffbbe5845554417965b1dfba me6.4.1
c8a9a4d355927e509f514308c82306192bc71f92 pe2.6.0 c8a9a4d355927e509f514308c82306192bc71f92 pe2.6.0
a618e954f01e4bbdbe9a03e5667a67d62be995a7 me6.4.2 a618e954f01e4bbdbe9a03e5667a67d62be995a7 me6.4.2
0f18c4498a6c7529bf77207db70aed8a5ec96ee4 se3.6.0
8f478379ec62fd1329d527aafb1ab0f2410f3a79 me6.5.0
d773721e6c3260f8130f40b4ab10442edc9965ec pe2.7.0
6b42e0d5628b937aee8039ee34d4b329149718a5 se3.6.0-arch
df6e045b9e7679f2a1949a57060e5c1863904444 me6.5.0-arch
286ba6959cd0af059f245371a3afb52c1da91dee pe2.7.0-arch

21
.tx/config Normal file
View File

@@ -0,0 +1,21 @@
[main]
host = https://www.transifex.net
[dupeguru.core]
file_filter = locale/<lang>/LC_MESSAGES/core.po
source_file = locale/core.pot
source_lang = en
type = PO
[dupeguru.columns]
file_filter = locale/<lang>/LC_MESSAGES/columns.po
source_file = locale/columns.pot
source_lang = en
type = PO
[dupeguru.ui]
file_filter = locale/<lang>/LC_MESSAGES/ui.po
source_file = locale/ui.pot
source_lang = en
type = PO

View File

@@ -1,4 +1,4 @@
Copyright 2012 Hardcoded Software Inc. (http://www.hardcoded.net) Copyright 2013 Hardcoded Software Inc. (http://www.hardcoded.net)
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

View File

@@ -1,18 +1,19 @@
Contents Contents
======== ========
This package contains the source for dupeGuru. To learn how to build it, refer to the "Build dupeGuru" section. Below is the description of the various subfolders: This package contains the source for dupeGuru. To learn how to build it, refer to the
"Build dupeGuru" section. Below is the description of the various subfolders:
- core: Contains the core logic code for dupeGuru. It's Python code written in TDD style. - core: Contains the core logic code for dupeGuru. It's Python code.
- core_*: Edition-specific-cross-toolkit code written in Python. - core_*: Edition-specific-cross-toolkit code written in Python.
- cocoa: UI code for the Cocoa toolkit. It's Objective-C code. - cocoa: UI code for the Cocoa toolkit. It's Objective-C code.
- qt: UI code for the Qt toolkit. It's written in Python and uses PyQt. - qt: UI code for the Qt toolkit. It's written in Python and uses PyQt.
- images: Images used by the different UI codebases. - images: Images used by the different UI codebases.
- debian_*: Skeleton files required to create a .deb package - debian: Skeleton files required to create a .deb package
- help: Help document, written for Sphinx. - help: Help document, written for Sphinx.
There are also other sub-folder that comes from external repositories (automatically checked out There are also other sub-folder that comes from external repositories (automatically checked out
with as mercurial subrepos): as mercurial subrepos):
- hscommon: A collection of helpers used across HS applications. - hscommon: A collection of helpers used across HS applications.
- cocoalib: A collection of helpers used across Cocoa UI codebases of HS applications. - cocoalib: A collection of helpers used across Cocoa UI codebases of HS applications.
@@ -21,7 +22,8 @@ with as mercurial subrepos):
dupeGuru Dependencies dupeGuru Dependencies
===================== =====================
Before being able to build dupeGuru, a few dependencies have to be installed: Before being able to build dupeGuru, a few dependencies have to be installed. If you use pip, you
will not have to install them all manually (see "The easy way!" below):
General dependencies General dependencies
-------------------- --------------------
@@ -39,7 +41,6 @@ OS X prerequisites
- XCode's command line tools - XCode's command line tools
- objp 1.1.0 (http://bitbucket.org/hsoft/objp) - objp 1.1.0 (http://bitbucket.org/hsoft/objp)
- pluginbuilder 1.1.0 (http://bitbucket.org/hsoft/pluginbuilder)
- appscript 1.0.0 for ME and PE (http://appscript.sourceforge.net/) - appscript 1.0.0 for ME and PE (http://appscript.sourceforge.net/)
- xibless 0.4.0 (https://bitbucket.org/hsoft/xibless) - xibless 0.4.0 (https://bitbucket.org/hsoft/xibless)
@@ -47,14 +48,14 @@ Windows prerequisites
--------------------- ---------------------
- Visual Studio 2008 (Express is enough) is needed to build C extensions. (http://www.microsoft.com/Express/) - Visual Studio 2008 (Express is enough) is needed to build C extensions. (http://www.microsoft.com/Express/)
- PyQt 4.7.5 (http://www.riverbankcomputing.co.uk/news) - PyQt 4.7+ (http://www.riverbankcomputing.co.uk/news)
- cx_Freeze, if you want to build a exe. You don't need it if you just want to run dupeGuru. (http://cx-freeze.sourceforge.net/) - cx_Freeze, if you want to build a exe. You don't need it if you just want to run dupeGuru. (http://cx-freeze.sourceforge.net/)
- Advanced Installer, if you want to build the installer file. (http://www.advancedinstaller.com/) - Advanced Installer, if you want to build the installer file. (http://www.advancedinstaller.com/)
Linux prerequisites Linux prerequisites
------------------- -------------------
- PyQt 4.7.5 (http://www.riverbankcomputing.co.uk/news) - PyQt 4.7+ (http://www.riverbankcomputing.co.uk/news)
The easy way! The easy way!
------------- -------------
@@ -64,12 +65,15 @@ There's an easy way to install the majority of the prerequisites above, and it's
pip install -r requirements-[osx|win].txt pip install -r requirements-[osx|win].txt
([osx|win] depends, of course, on your platform. On other platforms, just use requirements.txt). ([osx|win] depends, of course, on your platform. On other platforms, just use requirements.txt).
You might have to compile PyObjC manually (see gotchas below). Sparkle and
Advanced Installer, having nothing to do with Python, are also manual installs. Advanced Installer, having nothing to do with Python, needs to be installed manually.
PyQt isn't in the requirements file either (there's no package uploaded on PyPI) and you also have PyQt isn't in the requirements file either (there's no package uploaded on PyPI) and you also have
to install it manually. to install it manually.
If you use a virtualenv (which you should), you have to enable the "site-packages" option because
dupeGuru will need the PyQt library which you'll have installed on your system.
Prerequisite gotchas Prerequisite gotchas
-------------------- --------------------
@@ -93,17 +97,21 @@ pyqt4-dev-tools, mercurial and then python3-setuptools. Once you've done that, i
Building dupeGuru Building dupeGuru
================= =================
First, make sure you meet the dependencies listed in the section above. Then you need to configure your build with: First, make sure you meet the dependencies listed in the section above. Then you need to configure
your build with::
python configure.py python configure.py
If you want, you can specify a UI to use with the `--ui` option. So, if you want to build dupeGuru with Qt on OS X, then you have to type `python configure.py --ui=qt`. You can also use the `--dev` flag to indicate a dev build (it will build `dg_cocoa.plugin` in alias mode and use the "dev" config in XCode). If you want, you can specify a UI to use with the ``--ui`` option. So, if you want to build dupeGuru
with Qt on OS X, then you have to type ``python configure.py --ui=qt``. You can also use the
``--dev`` flag to indicate a dev build (mostly useful in OS X, where the python code in symlinked
so you don't have to repackage whenever you make a change in the python code).
Then, just build the thing and then run it with: Then, just build the thing and then run it with::
python build.py python build.py
python run.py python run.py
If you want to create ready-to-upload package, run: If you want to create ready-to-upload package, run::
python package.py python package.py

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2009-12-30 # Created On: 2009-12-30
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -13,16 +13,18 @@ from optparse import OptionParser
import shutil import shutil
import json import json
import importlib import importlib
import compileall
from setuptools import setup, Extension from setuptools import setup, Extension
from hscommon import sphinxgen from hscommon import sphinxgen
from hscommon.build import (add_to_pythonpath, print_and_do, copy_packages, filereplace, from hscommon.build import (add_to_pythonpath, print_and_do, copy_packages, filereplace,
get_module_version, move_all, copy_sysconfig_files_for_embed, copy_all, move, copy, get_module_version, move_all, copy_sysconfig_files_for_embed, copy_all, OSXAppStructure,
OSXAppStructure, build_cocoalib_xibless, fix_qt_resource_file) build_cocoalib_xibless, fix_qt_resource_file, build_cocoa_ext, copy_embeddable_python_dylib,
collect_stdlib_dependencies, copy)
from hscommon import loc from hscommon import loc
from hscommon.plat import ISOSX from hscommon.plat import ISOSX, ISLINUX
from hscommon.util import ensure_folder from hscommon.util import ensure_folder, delete_files_with_pattern
def parse_args(): def parse_args():
usage = "usage: %prog [options]" usage = "usage: %prog [options]"
@@ -95,7 +97,6 @@ def build_cocoa(edition, dev):
build_cocoa_proxy_module() build_cocoa_proxy_module()
build_cocoa_bridging_interfaces(edition) build_cocoa_bridging_interfaces(edition)
print("Building the cocoa layer") print("Building the cocoa layer")
from pluginbuilder import copy_embeddable_python_dylib, collect_dependencies
copy_embeddable_python_dylib('build') copy_embeddable_python_dylib('build')
pydep_folder = op.join(app.resources, 'py') pydep_folder = op.join(app.resources, 'py')
if not op.exists(pydep_folder): if not op.exists(pydep_folder):
@@ -106,16 +107,21 @@ def build_cocoa(edition, dev):
'me': ['core_me'], 'me': ['core_me'],
'pe': ['core_pe'], 'pe': ['core_pe'],
}[edition] }[edition]
tocopy = ['core', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa'] + specific_packages tocopy = ['core', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa', 'jobprogress', 'objp',
copy_packages(tocopy, 'build') 'send2trash'] + specific_packages
copy_packages(tocopy, pydep_folder, create_links=dev)
sys.path.insert(0, 'build') sys.path.insert(0, 'build')
collect_dependencies('build/dg_cocoa.py', pydep_folder, excludes=['PyQt4']) collect_stdlib_dependencies('build/dg_cocoa.py', pydep_folder)
del sys.path[0] del sys.path[0]
if dev:
copy_packages(tocopy, pydep_folder, create_links=True)
# Views are not referenced by python code, so they're not found by the collector. # Views are not referenced by python code, so they're not found by the collector.
copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) copy_all('build/inter/*.so', op.join(pydep_folder, 'inter'))
copy_sysconfig_files_for_embed(pydep_folder) copy_sysconfig_files_for_embed(pydep_folder)
if not dev:
# Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll
# be deleting all py files in symlinked folders.
compileall.compile_dir(pydep_folder, force=True, legacy=True)
delete_files_with_pattern(pydep_folder, '*.py')
delete_files_with_pattern(pydep_folder, '__pycache__')
print("Compiling with WAF") print("Compiling with WAF")
os.chdir('cocoa') os.chdir('cocoa')
print_and_do(cocoa_compile_command(edition)) print_and_do(cocoa_compile_command(edition))
@@ -127,20 +133,18 @@ def build_cocoa(edition, dev):
app.copy_resources(*resources, use_symlinks=dev) app.copy_resources(*resources, use_symlinks=dev)
app.copy_frameworks('build/Python', 'cocoalib/Sparkle.framework') app.copy_frameworks('build/Python', 'cocoalib/Sparkle.framework')
print("Creating the run.py file") print("Creating the run.py file")
tmpl = open('run_template_cocoa.py', 'rt').read() tmpl = open('cocoa/run_template.py', 'rt').read()
run_contents = tmpl.replace('{{app_path}}', app.dest) run_contents = tmpl.replace('{{app_path}}', app.dest)
open('run.py', 'wt').write(run_contents) open('run.py', 'wt').write(run_contents)
def build_qt(edition, dev): def build_qt(edition, dev, conf):
print("Building localizations") print("Building localizations")
build_localizations('qt', edition) build_localizations('qt', edition)
print("Building Qt stuff") 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_and_do("pyrcc4 -py3 {0} > {1}".format(op.join('qt', 'base', 'dg.qrc'), op.join('qt', 'base', 'dg_rc.py')))
fix_qt_resource_file(op.join('qt', 'base', 'dg_rc.py')) fix_qt_resource_file(op.join('qt', 'base', 'dg_rc.py'))
print("Creating the run.py file") print("Creating the run.py file")
tmpl = open('run_template_qt.py', 'rt').read() filereplace(op.join('qt', 'run_template.py'), 'run.py', edition=edition)
run_contents = tmpl.replace('{{edition}}', edition)
open('run.py', 'wt').write(run_contents)
def build_help(edition): def build_help(edition):
print("Generating Help") print("Generating Help")
@@ -161,24 +165,6 @@ def build_base_localizations():
loc.compile_all_po(op.join('hscommon', 'locale')) loc.compile_all_po(op.join('hscommon', 'locale'))
loc.merge_locale_dir(op.join('hscommon', 'locale'), 'locale') loc.merge_locale_dir(op.join('hscommon', 'locale'), 'locale')
def build_cocoa_localizations(edition):
print("Creating lproj folders based on .po files")
app = cocoa_app(edition)
en_stringsfile = op.join('cocoa', 'base', 'en.lproj', 'Localizable.strings')
en_cocoastringsfile = op.join('cocoalib', 'en.lproj', 'cocoalib.strings')
for lang in loc.get_langs('locale'):
pofile = op.join('locale', lang, 'LC_MESSAGES', 'ui.po')
dest_lproj = op.join(app.resources, lang + '.lproj')
ensure_folder(dest_lproj)
loc.po2strings(pofile, en_stringsfile, op.join(dest_lproj, 'Localizable.strings'))
pofile = op.join('cocoalib', 'locale', lang, 'LC_MESSAGES', 'cocoalib.po')
loc.po2strings(pofile, en_cocoastringsfile, op.join(dest_lproj, 'cocoalib.strings'))
# We also have to copy the "en.lproj" strings
en_lproj = op.join(app.resources, 'en.lproj')
ensure_folder(en_lproj)
copy(en_stringsfile, en_lproj)
copy(en_cocoastringsfile, en_lproj)
def build_qt_localizations(): def build_qt_localizations():
loc.compile_all_po(op.join('qtlib', 'locale')) loc.compile_all_po(op.join('qtlib', 'locale'))
loc.merge_locale_dir(op.join('qtlib', 'locale'), 'locale') loc.merge_locale_dir(op.join('qtlib', 'locale'), 'locale')
@@ -186,14 +172,24 @@ def build_qt_localizations():
def build_localizations(ui, edition): def build_localizations(ui, edition):
build_base_localizations() build_base_localizations()
if ui == 'cocoa': if ui == 'cocoa':
build_cocoa_localizations(edition) app = cocoa_app(edition)
locale_dest = op.join(cocoa_app(edition).resources, 'locale') loc.build_cocoa_localizations(app, en_stringsfile=op.join('cocoa', 'base', 'en.lproj', 'Localizable.strings'))
locale_dest = op.join(app.resources, 'locale')
elif ui == 'qt': elif ui == 'qt':
build_qt_localizations() build_qt_localizations()
locale_dest = op.join('build', 'locale') locale_dest = op.join('build', 'locale')
if op.exists(locale_dest): if op.exists(locale_dest):
shutil.rmtree(locale_dest) shutil.rmtree(locale_dest)
shutil.copytree('locale', locale_dest, ignore=shutil.ignore_patterns('*.po', '*.pot')) shutil.copytree('locale', locale_dest, ignore=shutil.ignore_patterns('*.po', '*.pot'))
if ui == 'qt' and not ISLINUX:
print("Copying qt_*.qm files into the 'locale' folder")
from PyQt4.QtCore import QLibraryInfo
trfolder = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
for lang in loc.get_langs('locale'):
qmname = 'qt_%s.qm' % lang
src = op.join(trfolder, qmname)
if op.exists(src):
copy(src, op.join('build', 'locale', qmname))
def build_updatepot(): def build_updatepot():
if ISOSX: if ISOSX:
@@ -212,8 +208,10 @@ def build_updatepot():
print("Building columns.pot") print("Building columns.pot")
loc.generate_pot(all_cores, op.join('locale', 'columns.pot'), ['coltr']) loc.generate_pot(all_cores, op.join('locale', 'columns.pot'), ['coltr'])
print("Building ui.pot") print("Building ui.pot")
# When we're not under OS X, we don't want to overwrite ui.pot because it contains Cocoa locs
# We want to merge the generated pot with the old pot in the most preserving way possible.
ui_packages = ['qt', op.join('cocoa', 'inter')] ui_packages = ['qt', op.join('cocoa', 'inter')]
loc.generate_pot(ui_packages, op.join('locale', 'ui.pot'), ['tr']) loc.generate_pot(ui_packages, op.join('locale', 'ui.pot'), ['tr'], merge=(not ISOSX))
print("Building hscommon.pot") print("Building hscommon.pot")
loc.generate_pot(['hscommon'], op.join('hscommon', 'locale', 'hscommon.pot'), ['tr']) loc.generate_pot(['hscommon'], op.join('hscommon', 'locale', 'hscommon.pot'), ['tr'])
print("Building qtlib.pot") print("Building qtlib.pot")
@@ -234,16 +232,6 @@ def build_mergepot():
loc.merge_pots_into_pos(op.join('qtlib', 'locale')) loc.merge_pots_into_pos(op.join('qtlib', 'locale'))
loc.merge_pots_into_pos(op.join('cocoalib', 'locale')) loc.merge_pots_into_pos(op.join('cocoalib', 'locale'))
def build_cocoa_ext(extname, dest, source_files, extra_frameworks=(), extra_includes=()):
extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"]
for extra in extra_frameworks:
extra_link_args += ['-framework', extra]
ext = Extension(extname, source_files, extra_link_args=extra_link_args, include_dirs=extra_includes)
setup(script_args=['build_ext', '--inplace'], ext_modules=[ext])
fn = extname + '.so'
assert op.exists(fn)
move(fn, op.join(dest, fn))
def build_cocoa_proxy_module(): def build_cocoa_proxy_module():
print("Building Cocoa Proxy") print("Building Cocoa Proxy")
import objp.p2o import objp.p2o
@@ -261,7 +249,7 @@ def build_cocoa_bridging_interfaces(edition):
add_to_pythonpath('cocoa') add_to_pythonpath('cocoa')
add_to_pythonpath('cocoalib') add_to_pythonpath('cocoalib')
from cocoa.inter import (PyGUIObject, GUIObjectView, PyColumns, ColumnsView, PyOutline, from cocoa.inter import (PyGUIObject, GUIObjectView, PyColumns, ColumnsView, PyOutline,
OutlineView, PySelectableList, SelectableListView, PyTable, TableView, PyFairware) OutlineView, PySelectableList, SelectableListView, PyTable, TableView, PyBaseApp, PyFairware)
from inter.deletion_options import PyDeletionOptions, DeletionOptionsView from inter.deletion_options import PyDeletionOptions, DeletionOptionsView
from inter.details_panel import PyDetailsPanel, DetailsPanelView from inter.details_panel import PyDetailsPanel, DetailsPanelView
from inter.directory_outline import PyDirectoryOutline, DirectoryOutlineView from inter.directory_outline import PyDirectoryOutline, DirectoryOutlineView
@@ -273,7 +261,7 @@ def build_cocoa_bridging_interfaces(edition):
from inter.stats_label import PyStatsLabel, StatsLabelView from inter.stats_label import PyStatsLabel, StatsLabelView
from inter.app import PyDupeGuruBase, DupeGuruView from inter.app import PyDupeGuruBase, DupeGuruView
appmod = importlib.import_module('inter.app_{}'.format(edition)) appmod = importlib.import_module('inter.app_{}'.format(edition))
allclasses = [PyGUIObject, PyColumns, PyOutline, PySelectableList, PyTable, PyFairware, allclasses = [PyGUIObject, PyColumns, PyOutline, PySelectableList, PyTable, PyBaseApp, PyFairware,
PyDetailsPanel, PyDirectoryOutline, PyPrioritizeDialog, PyPrioritizeList, PyProblemDialog, PyDetailsPanel, PyDirectoryOutline, PyPrioritizeDialog, PyPrioritizeList, PyProblemDialog,
PyIgnoreListDialog, PyDeletionOptions, PyResultTable, PyStatsLabel, PyDupeGuruBase, PyIgnoreListDialog, PyDeletionOptions, PyResultTable, PyStatsLabel, PyDupeGuruBase,
appmod.PyDupeGuru] appmod.PyDupeGuru]
@@ -310,7 +298,7 @@ def build_pe_modules(ui):
move_all('_block*', 'core_pe') move_all('_block*', 'core_pe')
move_all('_cache*', 'core_pe') move_all('_cache*', 'core_pe')
def build_normal(edition, ui, dev): def build_normal(edition, ui, dev, conf):
print("Building dupeGuru {0} with UI {1}".format(edition.upper(), ui)) print("Building dupeGuru {0} with UI {1}".format(edition.upper(), ui))
add_to_pythonpath('.') add_to_pythonpath('.')
build_help(edition) build_help(edition)
@@ -320,7 +308,7 @@ def build_normal(edition, ui, dev):
if ui == 'cocoa': if ui == 'cocoa':
build_cocoa(edition, dev) build_cocoa(edition, dev)
elif ui == 'qt': elif ui == 'qt':
build_qt(edition, dev) build_qt(edition, dev, conf)
def main(): def main():
options = parse_args() options = parse_args()
@@ -355,7 +343,7 @@ def main():
build_cocoalib_xibless() build_cocoalib_xibless()
build_xibless(edition) build_xibless(edition)
else: else:
build_normal(edition, ui, dev) build_normal(edition, ui, dev, conf)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
@@ -13,7 +13,7 @@ http://www.hardcoded.net/licenses/bsd_license
#import "DetailsPanel.h" #import "DetailsPanel.h"
#import "DirectoryPanel.h" #import "DirectoryPanel.h"
#import "IgnoreListDialog.h" #import "IgnoreListDialog.h"
#import "HSAboutBox.h" #import "HSFairwareAboutBox.h"
#import "HSRecentFiles.h" #import "HSRecentFiles.h"
@interface AppDelegateBase : NSObject @interface AppDelegateBase : NSObject
@@ -28,7 +28,7 @@ http://www.hardcoded.net/licenses/bsd_license
DetailsPanel *_detailsPanel; DetailsPanel *_detailsPanel;
IgnoreListDialog *_ignoreListDialog; IgnoreListDialog *_ignoreListDialog;
NSWindowController *_preferencesPanel; NSWindowController *_preferencesPanel;
HSAboutBox *_aboutBox; HSFairwareAboutBox *_aboutBox;
HSRecentFiles *_recentResults; HSRecentFiles *_recentResults;
} }
@@ -72,6 +72,5 @@ http://www.hardcoded.net/licenses/bsd_license
/* model --> view */ /* model --> view */
- (void)showMessage:(NSString *)msg; - (void)showMessage:(NSString *)msg;
- (void)setupAsRegistered; - (void)setupAsRegistered;
- (void)showFairwareNagWithPrompt:(NSString *)prompt;
- (void)showDemoNagWithPrompt:(NSString *)prompt; - (void)showDemoNagWithPrompt:(NSString *)prompt;
@end @end

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
@@ -160,7 +160,7 @@ http://www.hardcoded.net/licenses/bsd_license
- (void)showAboutBox - (void)showAboutBox
{ {
if (_aboutBox == nil) { if (_aboutBox == nil) {
_aboutBox = [[HSAboutBox alloc] initWithApp:model]; _aboutBox = [[HSFairwareAboutBox alloc] initWithApp:model];
} }
[[_aboutBox window] makeKeyAndOrderFront:nil]; [[_aboutBox window] makeKeyAndOrderFront:nil];
} }
@@ -265,11 +265,6 @@ http://www.hardcoded.net/licenses/bsd_license
// Nothing to do. // Nothing to do.
} }
- (void)showFairwareNagWithPrompt:(NSString *)prompt
{
[HSFairwareReminder showFairwareNagWithApp:[self model] prompt:prompt];
}
- (void)showDemoNagWithPrompt:(NSString *)prompt - (void)showDemoNagWithPrompt:(NSString *)prompt
{ {
[HSFairwareReminder showDemoNagWithApp:[self model] prompt:prompt]; [HSFairwareReminder showDemoNagWithApp:[self model] prompt:prompt];

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,12 +1,12 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
*/ */
#import "ResultWindow.h" #import "ResultWindowBase.h"
#import "ResultWindow_UI.h" #import "ResultWindow_UI.h"
#import "Dialogs.h" #import "Dialogs.h"
#import "ProgressController.h" #import "ProgressController.h"
@@ -29,7 +29,7 @@ http://www.hardcoded.net/licenses/bsd_license
app = aApp; app = aApp;
model = [app model]; model = [app model];
[self setWindow:createResultWindow_UI(self)]; [self setWindow:createResultWindow_UI(self)];
[[self window] setTitle:fmt(@"%@ Results", [model appName])]; [[self window] setTitle:fmt(NSLocalizedString(@"%@ Results", @""), [model appName])];
/* Put a cute iTunes-like bottom bar */ /* Put a cute iTunes-like bottom bar */
[[self window] setContentBorderThickness:28 forEdge:NSMinYEdge]; [[self window] setContentBorderThickness:28 forEdge:NSMinYEdge];
table = [[ResultTable alloc] initWithPyRef:[model resultTable] view:matches]; table = [[ResultTable alloc] initWithPyRef:[model resultTable] view:matches];

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,4 +1,5 @@
"%@ Results" = "%@ Results";
"A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again." = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."; "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again." = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again.";
"About dupeGuru" = "About dupeGuru"; "About dupeGuru" = "About dupeGuru";
"Action" = "Action"; "Action" = "Action";
@@ -82,7 +83,7 @@
"Load Recent Results" = "Load Recent Results"; "Load Recent Results" = "Load Recent Results";
"Load Results" = "Load Results"; "Load Results" = "Load Results";
"Load Results..." = "Load Results..."; "Load Results..." = "Load Results...";
"Make Selected Reference" = "Make Selected Reference"; "Make Selected into Reference" = "Make Selected into Reference";
"Mark All" = "Mark All"; "Mark All" = "Mark All";
"Mark None" = "Mark None"; "Mark None" = "Mark None";
"Mark Selected" = "Mark Selected"; "Mark Selected" = "Mark Selected";
@@ -104,7 +105,7 @@
"Quick Look" = "Quick Look"; "Quick Look" = "Quick Look";
"Quit dupeGuru" = "Quit dupeGuru"; "Quit dupeGuru" = "Quit dupeGuru";
"Re-Prioritize duplicates" = "Re-Prioritize duplicates"; "Re-Prioritize duplicates" = "Re-Prioritize duplicates";
"Re-Prioritize Results" = "Re-Prioritize Results"; "Re-Prioritize Results..." = "Re-Prioritize Results...";
"Recreate absolute path" = "Recreate absolute path"; "Recreate absolute path" = "Recreate absolute path";
"Recreate relative path" = "Recreate relative path"; "Recreate relative path" = "Recreate relative path";
"Reference" = "Reference"; "Reference" = "Reference";

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -52,11 +52,11 @@ actionMenu.addItem("Send Marked to Trash...", Action(None, 'trashMarked'), 'cmd+
actionMenu.addItem("Move Marked to...", Action(None, 'moveMarked'), 'cmd+m') actionMenu.addItem("Move Marked to...", Action(None, 'moveMarked'), 'cmd+m')
actionMenu.addItem("Copy Marked to...", Action(None, 'copyMarked'), 'cmd+alt+m') actionMenu.addItem("Copy Marked to...", Action(None, 'copyMarked'), 'cmd+alt+m')
actionMenu.addItem("Remove Marked from Results", Action(None, 'removeMarked'), 'cmd+r') actionMenu.addItem("Remove Marked from Results", Action(None, 'removeMarked'), 'cmd+r')
actionMenu.addItem("Re-Prioritize Results", Action(None, 'reprioritizeResults')) actionMenu.addItem("Re-Prioritize Results...", Action(None, 'reprioritizeResults'))
actionMenu.addSeparator() actionMenu.addSeparator()
actionMenu.addItem("Remove Selected from Results", Action(None, 'removeSelected'), 'cmd+backspace') actionMenu.addItem("Remove Selected from Results", Action(None, 'removeSelected'), 'cmd+backspace')
actionMenu.addItem("Add Selected to Ignore List", Action(None, 'ignoreSelected'), 'cmd+g') actionMenu.addItem("Add Selected to Ignore List", Action(None, 'ignoreSelected'), 'cmd+g')
actionMenu.addItem("Make Selected Reference", Action(None, 'switchSelected'), 'cmd+arrowup') actionMenu.addItem("Make Selected into Reference", Action(None, 'switchSelected'), 'cmd+arrowup')
actionMenu.addSeparator() actionMenu.addSeparator()
actionMenu.addItem("Open Selected with Default Application", Action(None, 'openSelected'), 'cmd+return') actionMenu.addItem("Open Selected with Default Application", Action(None, 'openSelected'), 'cmd+return')
actionMenu.addItem("Reveal Selected in Finder", Action(None, 'revealSelected'), 'cmd+alt+return') actionMenu.addItem("Reveal Selected in Finder", Action(None, 'revealSelected'), 'cmd+alt+return')

View File

@@ -1,5 +1,5 @@
wnerclass = 'ResultWindow' ownerclass = 'ResultWindowBase'
ownerimport = 'ResultWindow.h' ownerimport = 'ResultWindowBase.h'
result = Window(557, 400, "dupeGuru Results") result = Window(557, 400, "dupeGuru Results")
toolbar = result.createToolbar('ResultsToolbar') toolbar = result.createToolbar('ResultsToolbar')
@@ -57,7 +57,7 @@ actionPopup.menu.addSeparator()
for menu in (actionPopup.menu, contextMenu): for menu in (actionPopup.menu, contextMenu):
menu.addItem("Remove Selected from Results", action=Action(owner, 'removeSelected')) menu.addItem("Remove Selected from Results", action=Action(owner, 'removeSelected'))
menu.addItem("Add Selected to Ignore List", action=Action(owner, 'ignoreSelected')) menu.addItem("Add Selected to Ignore List", action=Action(owner, 'ignoreSelected'))
menu.addItem("Make Selected Reference", action=Action(owner, 'switchSelected')) menu.addItem("Make Selected into Reference", action=Action(owner, 'switchSelected'))
menu.addSeparator() menu.addSeparator()
menu.addItem("Open Selected with Default Application", action=Action(owner, 'openSelected')) menu.addItem("Open Selected with Default Application", action=Action(owner, 'openSelected'))
menu.addItem("Reveal Selected in Finder", action=Action(owner, 'revealSelected')) menu.addItem("Reveal Selected in Finder", action=Action(owner, 'revealSelected'))

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/11/16 # Created On: 2006/11/16
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -14,7 +14,6 @@ from appscript import app, its, k, CommandError, ApplicationNotFoundError
from . import tunes from . import tunes
from cocoa import as_fetch, proxy from cocoa import as_fetch, proxy
from hscommon import io
from hscommon.trans import trget from hscommon.trans import trget
from hscommon.path import Path from hscommon.path import Path
from hscommon.util import remove_invalid_xml from hscommon.util import remove_invalid_xml
@@ -78,21 +77,21 @@ def get_itunes_database_path():
return Path(plistpath) return Path(plistpath)
def get_itunes_songs(plistpath): def get_itunes_songs(plistpath):
if not io.exists(plistpath): if not plistpath.exists():
return [] return []
s = io.open(plistpath, 'rt', encoding='utf-8').read() s = plistpath.open('rt', encoding='utf-8').read()
# iTunes sometimes produces XML files with invalid characters in it. # iTunes sometimes produces XML files with invalid characters in it.
s = remove_invalid_xml(s, replace_with='') s = remove_invalid_xml(s, replace_with='')
plist = plistlib.readPlistFromBytes(s.encode('utf-8')) plist = plistlib.readPlistFromBytes(s.encode('utf-8'))
result = [] result = []
for song_data in plist['Tracks'].values(): for song_data in plist['Tracks'].values():
try:
if song_data['Track Type'] != 'File': if song_data['Track Type'] != 'File':
continue continue
try:
song = ITunesSong(song_data) song = ITunesSong(song_data)
except KeyError: # No "Location" or "Track ID" key in track except KeyError: # No "Track Type", "Location" or "Track ID" key in track
continue continue
if io.exists(song.path): if song.path.exists():
result.append(song) result.append(song)
return result return result

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/11/13 # Created On: 2006/11/13
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2009-05-24 # Created On: 2009-05-24
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,5 @@
# Created On: 2012-05-30 # Created On: 2012-05-30
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -31,7 +31,7 @@
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>© Hardcoded Software, 2012</string> <string>© Hardcoded Software, 2013</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>http://www.hardcoded.net/updates/dupeguru_me.appcast</string> <string>http://www.hardcoded.net/updates/dupeguru_me.appcast</string>
<key>SUPublicDSAKeyFile</key> <key>SUPublicDSAKeyFile</key>

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
@@ -7,7 +7,7 @@ http://www.hardcoded.net/licenses/bsd_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "../base/ResultWindow.h" #import "ResultWindowBase.h"
@interface ResultWindow : ResultWindowBase {} @interface ResultWindow : ResultWindowBase {}
- (void)removeDeadTracks; - (void)removeDeadTracks;

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,4 +1,4 @@
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -31,7 +31,7 @@
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>© Hardcoded Software, 2012</string> <string>© Hardcoded Software, 2013</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>http://www.hardcoded.net/updates/dupeguru_pe.appcast</string> <string>http://www.hardcoded.net/updates/dupeguru_pe.appcast</string>
<key>SUPublicDSAKeyFile</key> <key>SUPublicDSAKeyFile</key>

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
@@ -7,7 +7,7 @@ http://www.hardcoded.net/licenses/bsd_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "../base/ResultWindow.h" #import "ResultWindowBase.h"
@interface ResultWindow : ResultWindowBase {} @interface ResultWindow : ResultWindowBase {}
- (void)clearPictureCache; - (void)clearPictureCache;

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
@@ -22,6 +22,7 @@ http://www.hardcoded.net/licenses/bsd_license
{@"size", 63, 16, 0, YES, nil}, {@"size", 63, 16, 0, YES, nil},
{@"extension", 40, 16, 0, YES, nil}, {@"extension", 40, 16, 0, YES, nil},
{@"dimensions", 73, 16, 0, YES, nil}, {@"dimensions", 73, 16, 0, YES, nil},
{@"exif_timestamp", 120, 16, 0, YES, nil},
{@"mtime", 120, 16, 0, YES, nil}, {@"mtime", 120, 16, 0, YES, nil},
{@"percentage", 58, 16, 0, YES, nil}, {@"percentage", 58, 16, 0, YES, nil},
{@"dupe_count", 80, 16, 0, YES, nil}, {@"dupe_count", 80, 16, 0, YES, nil},

View File

@@ -1,4 +1,4 @@
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -29,7 +29,7 @@
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>© Hardcoded Software, 2012</string> <string>© Hardcoded Software, 2013</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>http://www.hardcoded.net/updates/dupeguru.appcast</string> <string>http://www.hardcoded.net/updates/dupeguru.appcast</string>
<key>SUPublicDSAKeyFile</key> <key>SUPublicDSAKeyFile</key>

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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
@@ -7,7 +7,7 @@ http://www.hardcoded.net/licenses/bsd_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "../base/ResultWindow.h" #import "ResultWindowBase.h"
@interface ResultWindow : ResultWindowBase {} @interface ResultWindow : ResultWindowBase {}
@end @end

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 Hardcoded Software (http://www.hardcoded.net) Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "BSD" License as described in the "LICENSE" file, This software is licensed under the "BSD" License as described in the "LICENSE" file,
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

View File

@@ -1,4 +1,4 @@
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys
import os import os
import os.path as op import os.path as op
@@ -25,8 +26,9 @@ def configure(conf):
# I did a lot of fiddling-around, but I didn't find how to tell WAF the Python library name # I did a lot of fiddling-around, but I didn't find how to tell WAF the Python library name
# to look for without making the whole compilation process fail, so I just create a symlink # to look for without making the whole compilation process fail, so I just create a symlink
# with the name WAF is looking for. # with the name WAF is looking for.
if not op.exists('../build/libpython3.2.dylib'): versioned_dylib_path = '../build/libpython{}.dylib'.format(sys.version[:3])
os.symlink('../build/Python', '../build/libpython3.2.dylib') if not op.exists(versioned_dylib_path):
os.symlink('../build/Python', versioned_dylib_path)
# The rest is standard WAF code that you can find the the python and macapp demos. # The rest is standard WAF code that you can find the the python and macapp demos.
conf.load('compiler_c python') conf.load('compiler_c python')
conf.check_python_version((3,2,0)) conf.check_python_version((3,2,0))
@@ -42,7 +44,7 @@ def build(ctx):
cocoalib_node = ctx.srcnode.find_dir('..').find_dir('cocoalib') cocoalib_node = ctx.srcnode.find_dir('..').find_dir('cocoalib')
cocoalib_folders = ['controllers', 'views'] cocoalib_folders = ['controllers', 'views']
cocoalib_includes = [cocoalib_node] + [cocoalib_node.find_dir(folder) for folder in cocoalib_folders] cocoalib_includes = [cocoalib_node] + [cocoalib_node.find_dir(folder) for folder in cocoalib_folders]
cocoalib_uses = ['NSEventAdditions', 'Dialogs', 'HSAboutBox', 'HSFairwareReminder', 'Utils', cocoalib_uses = ['NSEventAdditions', 'Dialogs', 'HSFairwareAboutBox', 'HSFairwareReminder', 'Utils',
'HSPyUtil', 'ProgressController', 'HSRecentFiles', 'HSQuicklook', 'ValueTransformers', 'HSPyUtil', 'ProgressController', 'HSRecentFiles', 'HSQuicklook', 'ValueTransformers',
'NSImageAdditions', 'NSNotificationAdditions', 'NSImageAdditions', 'NSNotificationAdditions',
'views/HSTableView', 'views/HSOutlineView', 'views/NSIndexPathAdditions', 'views/HSTableView', 'views/HSOutlineView', 'views/NSIndexPathAdditions',

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2009-12-30 # Created On: 2009-12-30
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -12,17 +12,17 @@ import json
from hscommon.plat import ISOSX from hscommon.plat import ISOSX
def main(edition, ui, dev): def main(options):
if edition not in {'se', 'me', 'pe'}: if options.edition not in {'se', 'me', 'pe'}:
edition = 'se' options.edition = 'se'
if ui not in {'cocoa', 'qt'}: if options.ui not in {'cocoa', 'qt'}:
ui = 'cocoa' if ISOSX else 'qt' options.ui = 'cocoa' if ISOSX else 'qt'
build_type = 'Dev' if dev else 'Release' build_type = 'Dev' if options.dev else 'Release'
print("Configuring dupeGuru {0} for UI {1} ({2})".format(edition.upper(), ui, build_type)) print("Configuring dupeGuru {0} for UI {1} ({2})".format(options.edition.upper(), options.ui, build_type))
conf = { conf = {
'edition': edition, 'edition': options.edition,
'ui': ui, 'ui': options.ui,
'dev': dev, 'dev': options.dev,
} }
json.dump(conf, open('conf.json', 'w')) json.dump(conf, open('conf.json', 'w'))
@@ -36,4 +36,4 @@ if __name__ == '__main__':
parser.add_option('--dev', action='store_true', dest='dev', default=False, parser.add_option('--dev', action='store_true', dest='dev', default=False,
help="If this flag is set, will configure for dev builds.") help="If this flag is set, will configure for dev builds.")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
main(options.edition, options.ui, options.dev) main(options)

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/11/11 # Created On: 2006/11/11
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -15,7 +15,6 @@ import time
import shutil import shutil
from send2trash import send2trash from send2trash import send2trash
from hscommon import io
from hscommon.reg import RegistrableApplication from hscommon.reg import RegistrableApplication
from hscommon.notify import Broadcaster from hscommon.notify import Broadcaster
from hscommon.path import Path from hscommon.path import Path
@@ -37,6 +36,8 @@ DEBUG_MODE_PREFERENCE = 'DebugMode'
MSG_NO_MARKED_DUPES = tr("There are no marked duplicates. Nothing has been done.") MSG_NO_MARKED_DUPES = tr("There are no marked duplicates. Nothing has been done.")
MSG_NO_SELECTED_DUPES = tr("There are no selected duplicates. Nothing has been done.") MSG_NO_SELECTED_DUPES = tr("There are no selected duplicates. Nothing has been done.")
MSG_MANY_FILES_TO_OPEN = tr("You're about to open many files at once. Depending on what those "
"files are opened with, doing so can create quite a mess. Continue?")
class DestType: class DestType:
Direct = 0 Direct = 0
@@ -168,7 +169,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
self.results.perform_on_marked(op, True) self.results.perform_on_marked(op, True)
def _do_delete_dupe(self, dupe, link_deleted, use_hardlinks, direct_deletion): def _do_delete_dupe(self, dupe, link_deleted, use_hardlinks, direct_deletion):
if not io.exists(dupe.path): if not dupe.path.exists():
return return
logging.debug("Sending '%s' to trash", dupe.path) logging.debug("Sending '%s' to trash", dupe.path)
str_path = str(dupe.path) str_path = str(dupe.path)
@@ -241,9 +242,9 @@ class DupeGuru(RegistrableApplication, Broadcaster):
self.view.show_problem_dialog() self.view.show_problem_dialog()
else: else:
msg = { msg = {
JobType.Copy: tr("All marked files were copied sucessfully."), JobType.Copy: tr("All marked files were copied successfully."),
JobType.Move: tr("All marked files were moved sucessfully."), JobType.Move: tr("All marked files were moved successfully."),
JobType.Delete: tr("All marked files were sucessfully sent to Trash."), JobType.Delete: tr("All marked files were successfully sent to Trash."),
}[jobid] }[jobid]
self.view.show_message(msg) self.view.show_message(msg)
@@ -253,7 +254,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
result = [] result = []
for file in files: for file in files:
try: try:
inode = io.stat(file.path).st_ino inode = file.path.stat().st_ino
except OSError: except OSError:
# The file was probably deleted or something # The file was probably deleted or something
continue continue
@@ -324,8 +325,8 @@ class DupeGuru(RegistrableApplication, Broadcaster):
if dest_type == DestType.Relative: if dest_type == DestType.Relative:
source_base = source_base[location_path:] source_base = source_base[location_path:]
dest_path = dest_path + source_base dest_path = dest_path + source_base
if not io.exists(dest_path): if not dest_path.exists():
io.makedirs(dest_path) dest_path.makedirs()
# Add filename to dest_path. For file move/copy, it's not required, but for folders, yes. # Add filename to dest_path. For file move/copy, it's not required, but for folders, yes.
dest_path = dest_path + source_path[-1] dest_path = dest_path + source_path[-1]
logging.debug("Copy/Move operation from '%s' to '%s'", source_path, dest_path) logging.debug("Copy/Move operation from '%s' to '%s'", source_path, dest_path)
@@ -441,8 +442,24 @@ class DupeGuru(RegistrableApplication, Broadcaster):
for dupe in dupes: for dupe in dupes:
g = self.results.get_group_of_duplicate(dupe) g = self.results.get_group_of_duplicate(dupe)
if g not in changed_groups: if g not in changed_groups:
self.results.make_ref(dupe) if self.results.make_ref(dupe):
changed_groups.add(g) changed_groups.add(g)
# It's not always obvious to users what this action does, so to make it a bit clearer,
# we change our selection to the ref of all changed groups. However, we also want to keep
# the files that were ref before and weren't changed by the action. In effect, what this
# does is that we keep our old selection, but remove all non-ref dupes from it.
# If no group was changed, however, we don't touch the selection.
if not self.result_table.power_marker:
if changed_groups:
self.selected_dupes = [d for d in self.selected_dupes
if self.results.get_group_of_duplicate(d).ref is d]
self.notify('results_changed')
else:
# If we're in "Dupes Only" mode (previously called Power Marker), things are a bit
# different. The refs are not shown in the table, and if our operation is successful,
# this means that there's no way to follow our dupe selection. Then, the best thing to
# do is to keep our selection index-wise (different dupe selection, but same index
# selection).
self.notify('results_changed_but_keep_selection') self.notify('results_changed_but_keep_selection')
def mark_all(self): def mark_all(self):
@@ -465,8 +482,11 @@ class DupeGuru(RegistrableApplication, Broadcaster):
self.notify('marking_changed') self.notify('marking_changed')
def open_selected(self): def open_selected(self):
if self.selected_dupes: if len(self.selected_dupes) > 10:
self.view.open_path(self.selected_dupes[0].path) if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN):
return
for dupe in self.selected_dupes:
self.view.open_path(dupe.path)
def purge_ignore_list(self): def purge_ignore_list(self):
self.scanner.ignore_list.Filter(lambda f,s:op.exists(f) and op.exists(s)) self.scanner.ignore_list.Filter(lambda f,s:op.exists(f) and op.exists(s))

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/02/27 # Created On: 2006/02/27
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -10,7 +10,6 @@ from xml.etree import ElementTree as ET
import logging import logging
from jobprogress import job from jobprogress import job
from hscommon import io
from hscommon.path import Path from hscommon.path import Path
from hscommon.util import FileOrPath from hscommon.util import FileOrPath
@@ -73,9 +72,9 @@ class Directories:
file.is_ref = state == DirectoryState.Reference file.is_ref = state == DirectoryState.Reference
filepaths.add(file.path) filepaths.add(file.path)
yield file yield file
subpaths = [from_path + name for name in io.listdir(from_path)] subpaths = [from_path + name for name in from_path.listdir()]
# it's possible that a folder (bundle) gets into the file list. in that case, we don't want to recurse into it # it's possible that a folder (bundle) gets into the file list. in that case, we don't want to recurse into it
subfolders = [p for p in subpaths if not io.islink(p) and io.isdir(p) and p not in filepaths] subfolders = [p for p in subpaths if not p.islink() and p.isdir() and p not in filepaths]
for subfolder in subfolders: for subfolder in subfolders:
for file in self._get_files(subfolder, j): for file in self._get_files(subfolder, j):
yield file yield file
@@ -106,7 +105,7 @@ class Directories:
""" """
if path in self: if path in self:
raise AlreadyThereError() raise AlreadyThereError()
if not io.exists(path): if not path.exists():
raise InvalidPathError() raise InvalidPathError()
self._dirs = [p for p in self._dirs if p not in path] self._dirs = [p for p in self._dirs if p not in path]
self._dirs.append(path) self._dirs.append(path)
@@ -115,7 +114,7 @@ class Directories:
def get_subfolders(path): def get_subfolders(path):
"""returns a sorted list of paths corresponding to subfolders in `path`""" """returns a sorted list of paths corresponding to subfolders in `path`"""
try: try:
names = [name for name in io.listdir(path) if io.isdir(path + name)] names = [name for name in path.listdir() if (path + name).isdir()]
names.sort(key=lambda x:x.lower()) names.sort(key=lambda x:x.lower())
return [path + name for name in names] return [path + name for name in names]
except EnvironmentError: except EnvironmentError:

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/01/29 # Created On: 2006/01/29
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -325,14 +325,15 @@ class Group:
def switch_ref(self, with_dupe): def switch_ref(self, with_dupe):
if self.ref.is_ref: if self.ref.is_ref:
return return False
try: try:
self.ordered.remove(with_dupe) self.ordered.remove(with_dupe)
self.ordered.insert(0, with_dupe) self.ordered.insert(0, with_dupe)
self._percentage = None self._percentage = None
self._matches_for_ref = None self._matches_for_ref = None
return True
except ValueError: except ValueError:
pass return False
dupes = property(lambda self: self[1:]) dupes = property(lambda self: self[1:])

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/09/16 # Created On: 2006/09/16
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2009-10-22 # Created On: 2009-10-22
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -14,7 +14,6 @@
import hashlib import hashlib
import logging import logging
from hscommon import io
from hscommon.util import nonone, get_file_ext from hscommon.util import nonone, get_file_ext
NOT_SET = object() NOT_SET = object()
@@ -89,12 +88,12 @@ class File:
def _read_info(self, field): def _read_info(self, field):
if field in ('size', 'mtime'): if field in ('size', 'mtime'):
stats = io.stat(self.path) stats = self.path.stat()
self.size = nonone(stats.st_size, 0) self.size = nonone(stats.st_size, 0)
self.mtime = nonone(stats.st_mtime, 0) self.mtime = nonone(stats.st_mtime, 0)
elif field == 'md5partial': elif field == 'md5partial':
try: try:
fp = io.open(self.path, 'rb') fp = self.path.open('rb')
offset, size = self._get_md5partial_offset_and_size() offset, size = self._get_md5partial_offset_and_size()
fp.seek(offset) fp.seek(offset)
partialdata = fp.read(size) partialdata = fp.read(size)
@@ -105,7 +104,7 @@ class File:
pass pass
elif field == 'md5': elif field == 'md5':
try: try:
fp = io.open(self.path, 'rb') fp = self.path.open('rb')
md5 = hashlib.md5() md5 = hashlib.md5()
CHUNK_SIZE = 8192 CHUNK_SIZE = 8192
filedata = fp.read(CHUNK_SIZE) filedata = fp.read(CHUNK_SIZE)
@@ -130,19 +129,19 @@ class File:
#--- Public #--- Public
@classmethod @classmethod
def can_handle(cls, path): def can_handle(cls, path):
return not io.islink(path) and io.isfile(path) return not path.islink() and path.isfile()
def rename(self, newname): def rename(self, newname):
if newname == self.name: if newname == self.name:
return return
destpath = self.path[:-1] + newname destpath = self.path[:-1] + newname
if io.exists(destpath): if destpath.exists():
raise AlreadyExistsError(newname, self.path[:-1]) raise AlreadyExistsError(newname, self.path[:-1])
try: try:
io.rename(self.path, destpath) self.path.rename(destpath)
except EnvironmentError: except EnvironmentError:
raise OperationError(self) raise OperationError(self)
if not io.exists(destpath): if not destpath.exists():
raise OperationError(self) raise OperationError(self)
self.path = destpath self.path = destpath
@@ -180,7 +179,7 @@ class Folder(File):
if field in {'size', 'mtime'}: if field in {'size', 'mtime'}:
size = sum((f.size for f in self._all_items()), 0) size = sum((f.size for f in self._all_items()), 0)
self.size = size self.size = size
stats = io.stat(self.path) stats = self.path.stat()
self.mtime = nonone(stats.st_mtime, 0) self.mtime = nonone(stats.st_mtime, 0)
elif field in {'md5', 'md5partial'}: elif field in {'md5', 'md5partial'}:
# What's sensitive here is that we must make sure that subfiles' # What's sensitive here is that we must make sure that subfiles'
@@ -199,14 +198,14 @@ class Folder(File):
@property @property
def subfolders(self): def subfolders(self):
if self._subfolders is None: if self._subfolders is None:
subpaths = [self.path + name for name in io.listdir(self.path)] subpaths = [self.path + name for name in self.path.listdir()]
subfolders = [p for p in subpaths if not io.islink(p) and io.isdir(p)] subfolders = [p for p in subpaths if not p.islink() and p.isdir()]
self._subfolders = [Folder(p) for p in subfolders] self._subfolders = [Folder(p) for p in subfolders]
return self._subfolders return self._subfolders
@classmethod @classmethod
def can_handle(cls, path): def can_handle(cls, path):
return not io.islink(path) and io.isdir(path) return not path.islink() and path.isdir()
def get_file(path, fileclasses=[File]): def get_file(path, fileclasses=[File]):
@@ -225,7 +224,7 @@ def get_files(path, fileclasses=[File]):
raise raise
try: try:
paths = [combine_paths(path, name) for name in io.listdir(path)] paths = [combine_paths(path, name) for name in path.listdir()]
result = [] result = []
for path in paths: for path in paths:
file = get_file(path, fileclasses=fileclasses) file = get_file(path, fileclasses=fileclasses)

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-02-06 # Created On: 2010-02-06
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,5 @@
# Created On: 2012-05-30 # Created On: 2012-05-30
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-02-05 # Created On: 2010-02-05
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-02-06 # Created On: 2010-02-06
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,5 +1,5 @@
# Created On: 2012/03/13 # Created On: 2012/03/13
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2012-03-13 # Created On: 2012-03-13
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2011-09-06 # Created On: 2011-09-06
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-04-12 # Created On: 2010-04-12
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-04-12 # Created On: 2010-04-12
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-02-11 # Created On: 2010-02-11
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2010-02-11 # Created On: 2010-02-11
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/05/02 # Created On: 2006/05/02
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/02/23 # Created On: 2006/02/23
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2011/09/07 # Created On: 2011/09/07
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/02/23 # Created On: 2006/02/23
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -244,8 +244,9 @@ class Results(Markable):
def make_ref(self, dupe): def make_ref(self, dupe):
g = self.get_group_of_duplicate(dupe) g = self.get_group_of_duplicate(dupe)
r = g.ref r = g.ref
if not g.switch_ref(dupe):
return False
self._remove_mark_flag(dupe) self._remove_mark_flag(dupe)
g.switch_ref(dupe);
if not r.is_ref: if not r.is_ref:
self.__total_count += 1 self.__total_count += 1
self.__total_size += r.size self.__total_size += r.size
@@ -254,6 +255,7 @@ class Results(Markable):
self.__total_size -= dupe.size self.__total_size -= dupe.size
self.__dupes = None self.__dupes = None
self.is_modified = True self.is_modified = True
return True
def perform_on_marked(self, func, remove_from_results): def perform_on_marked(self, func, remove_from_results):
# Performs `func` on all marked dupes. If an EnvironmentError is raised during the call, # Performs `func` on all marked dupes. If an EnvironmentError is raised during the call,
@@ -265,7 +267,7 @@ class Results(Markable):
try: try:
func(dupe) func(dupe)
to_remove.append(dupe) to_remove.append(dupe)
except EnvironmentError as e: except (EnvironmentError, UnicodeEncodeError) as e:
self.problems.append((dupe, str(e))) self.problems.append((dupe, str(e)))
if remove_from_results: if remove_from_results:
self.remove_duplicates(to_remove) self.remove_duplicates(to_remove)

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/03/03 # Created On: 2006/03/03
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -11,7 +11,6 @@ import re
import os.path as op import os.path as op
from jobprogress import job from jobprogress import job
from hscommon import io
from hscommon.util import dedupe, rem_file_ext, get_file_ext from hscommon.util import dedupe, rem_file_ext, get_file_ext
from hscommon.trans import tr from hscommon.trans import tr
@@ -129,6 +128,11 @@ class Scanner:
matches = self._getmatches(files, j) matches = self._getmatches(files, j)
logging.info('Found %d matches' % len(matches)) logging.info('Found %d matches' % len(matches))
j.set_progress(100, tr("Removing false matches")) j.set_progress(100, tr("Removing false matches"))
# In removing what we call here "false matches", we first want to remove, if we scan by
# folders, we want to remove folder matches for which the parent is also in a match (they're
# "duplicated duplicates if you will). Then, we also don't want mixed file kinds if the
# option isn't enabled, we want matches for which both files exist and, lastly, we don't
# want matches with both files as ref.
if self.scan_type == ScanType.Folders and matches: if self.scan_type == ScanType.Folders and matches:
allpath = {m.first.path for m in matches} allpath = {m.first.path for m in matches}
allpath |= {m.second.path for m in matches} allpath |= {m.second.path for m in matches}
@@ -143,7 +147,8 @@ class Scanner:
matches = [m for m in matches if m.first.path not in toremove or m.second.path not in toremove] matches = [m for m in matches if m.first.path not in toremove or m.second.path not in toremove]
if not self.mix_file_kind: if not self.mix_file_kind:
matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)] matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)]
matches = [m for m in matches if io.exists(m.first.path) and io.exists(m.second.path)] matches = [m for m in matches if m.first.path.exists() and m.second.path.exists()]
matches = [m for m in matches if not (m.first.is_ref and m.second.is_ref)]
if self.ignore_list: if self.ignore_list:
j = j.start_subjob(2) j = j.start_subjob(2)
iter_matches = j.iter_with_progress(matches, tr("Processed %d/%d matches against the ignore list")) iter_matches = j.iter_with_progress(matches, tr("Processed %d/%d matches against the ignore list"))

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2007-06-23 # Created On: 2007-06-23
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -330,18 +330,22 @@ class TestCaseDupeGuruWithResults:
app = self.app app = self.app
# any other path that isn't a parent or child of the already added path # any other path that isn't a parent or child of the already added path
otherpath = Path(op.dirname(__file__)) otherpath = Path(op.dirname(__file__))
eq_(app.add_directory(otherpath), 0) app.add_directory(otherpath)
eq_(len(app.directories), 2) eq_(len(app.directories), 2)
def test_addDirectory_already_there(self, do_setup): def test_addDirectory_already_there(self, do_setup):
app = self.app app = self.app
otherpath = Path(op.dirname(__file__)) otherpath = Path(op.dirname(__file__))
eq_(app.add_directory(otherpath), 0) app.add_directory(otherpath)
eq_(app.add_directory(otherpath), 1) app.add_directory(otherpath)
eq_(len(app.view.messages), 1)
assert "already" in app.view.messages[0]
def test_addDirectory_does_not_exist(self, do_setup): def test_addDirectory_does_not_exist(self, do_setup):
app = self.app app = self.app
eq_(2,app.add_directory('/does_not_exist')) app.add_directory('/does_not_exist')
eq_(len(app.view.messages), 1)
assert "exist" in app.view.messages[0]
def test_ignore(self, do_setup): def test_ignore(self, do_setup):
app = self.app app = self.app

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2011/09/07 # Created On: 2011/09/07
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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
@@ -24,6 +24,9 @@ from ..gui.prioritize_dialog import PrioritizeDialog
class DupeGuruView: class DupeGuruView:
JOB = nulljob JOB = nulljob
def __init__(self):
self.messages = []
def start_job(self, jobid, func, args=()): def start_job(self, jobid, func, args=()):
try: try:
func(self.JOB, *args) func(self.JOB, *args)
@@ -37,7 +40,7 @@ class DupeGuruView:
pass pass
def show_message(self, msg): def show_message(self, msg):
pass self.messages.append(msg)
def ask_yes_no(self, prompt): def ask_yes_no(self, prompt):
return True # always answer yes return True # always answer yes

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/02/27 # Created On: 2006/02/27
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/01/29 # Created On: 2006/01/29
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2009-10-23 # Created On: 2009-10-23
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/05/02 # Created On: 2006/05/02
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# #
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/02/23 # Created On: 2006/02/23
# Copyright 2012 Hardcoded Software (http://www.hardcoded.net) # Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# This software is licensed under the "BSD" License as described in the "LICENSE" file, # This software is licensed under the "BSD" License as described in the "LICENSE" file,
# 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

Some files were not shown because too many files have changed in this diff Show More