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

Compare commits

...

44 Commits

Author SHA1 Message Date
Virgil Dupras
9bd0ec8875 Added PE's "trigger happy" scan type
ref #242
2014-03-30 16:01:56 -04:00
Virgil Dupras
ba13b700b0 Fixed crashing save dialogs under Qt5 2014-03-30 15:57:07 -04:00
Virgil Dupras
640561a534 Updated F.A.Q.
Fixes #252
2014-03-30 13:43:29 -04:00
Virgil Dupras
e4f81cbf04 Update loc 2014-03-30 10:47:37 -04:00
Virgil Dupras
4be4825112 Bootstrapping: don't use system-site-packages under OS X 2014-03-30 10:26:09 -04:00
Virgil Dupras
7d107d8efa Moved Cocoa error reporting to Github mode. 2014-03-30 10:07:01 -04:00
Virgil Dupras
10d1363334 Changed the error report so it brings the user to Github directly
Making error reporting too easy results in too much context-less
tracebacks which demand attention and, in the end, aren't of much use.

Requiring the user to report errors on Github will reduce the number of
reports, but hopefully make these reports have better context.
2014-03-29 17:42:23 -04:00
Virgil Dupras
b76820ebde Fixed bootstrapping under Python 3.3 2014-03-28 16:27:45 -04:00
Virgil Dupras
72b3cfb364 Adapted bootstrapping procedure to Python 3.4 2014-03-28 16:21:05 -04:00
Virgil Dupras
8b83ed0e5c Removed needless PyQt signal overloading
After a PyQt5 update, dupeGuru wouldn't run anymore because it choked on
signal overloading that weren't necessary.
2014-03-27 19:09:10 -04:00
Virgil Dupras
781f13ae1a Overwrite subfolders' state when setting states in folder dialog
Fixes #248
2014-03-15 17:31:33 -04:00
Virgil Dupras
8193bbae6e Fixed broken tests in core_me 2014-03-15 14:09:36 -04:00
Virgil Dupras
4cafeaff91 Don't crash on malformed integer in iPhoto plist
Simply default to 0. Fixes #214.
2014-03-15 14:06:20 -04:00
Virgil Dupras
95c6a7d41f Add debugging data to iPhoto plist parsing
Fixes #233.
2014-03-15 13:59:15 -04:00
Virgil Dupras
a29e007475 cocoalib: Replaced the "Relevant Console log" mechanism
The old grepping method wasn't reliable and now, we simply keep the last
20 logs in memory to place in that section of error reporting.
2014-03-15 13:57:34 -04:00
Virgil Dupras
d924d7797a Qt: Don't use a native menubar for the Result Window
Having two native menu bars in the app made the result window all
glitchy under Ubuntu 13.10.
2014-02-15 21:02:38 -05:00
Virgil Dupras
33c217ecc8 Straightened out Qt window parenting chain 2014-02-15 15:05:46 -05:00
Virgil Dupras
c9035046ae Updated cocoalib 2014-02-01 17:54:30 -05:00
Virgil Dupras
ad31016825 Updated qtlib 2014-02-01 17:17:15 -05:00
Virgil Dupras
c809066a93 Updated hscommon 2014-02-01 16:18:00 -05:00
Virgil Dupras
60ca27b5e1 Make Cocoa use the new FTP report-sender 2014-01-26 15:27:02 -05:00
Virgil Dupras
1104e24408 Error reports are now dropped by FTP on drop.hardcoded.net 2014-01-26 15:03:24 -05:00
Virgil Dupras
f66db94ffd Merge branch 'master' into develop
Conflicts:
	bootstrap.sh
2014-01-26 09:49:57 -05:00
Virgil Dupras
d98b5b22da polib is now on PyPI 2014-01-26 09:48:30 -05:00
Virgil Dupras
937748e838 Improved source packaging and bootstrapping 2014-01-26 09:41:15 -05:00
Virgil Dupras
37ebf36cee Merge branch 'master' into develop
Conflicts:
	bootstrap.sh
2014-01-11 13:30:30 -05:00
Virgil Dupras
1c84bdd198 Fixed bootstrapping and README for pip 1.5 2014-01-11 13:27:31 -05:00
Virgil Dupras
4a2fa7cd2c Updated FAQ 2014-01-10 15:05:45 -05:00
Virgil Dupras
7d4110f6d3 Merge branch 'master' into develop
Conflicts:
	README.md
2014-01-10 15:00:02 -05:00
Virgil Dupras
8497343d7f Updated FAQ in docs 2014-01-05 21:45:57 -05:00
Virgil Dupras
235a2c2904 Added a "contribute" page to the docs. 2014-01-05 21:44:56 -05:00
Virgil Dupras
25169cfc20 Create an empty site.py in collect_stdlib_dependencies()
Since we have Python 3.3 as a minimum requirement, we don't need to
patch our site.py with copy_sysconfig_files_for_embed() anymore, but we
still need a site.py file on startup. We create it when we collect
stdlib deps.
2013-12-22 12:13:39 -05:00
Virgil Dupras
152f5f37ce pe v2.9.0 2013-12-22 10:23:54 -05:00
Virgil Dupras
3e42ad8469 Minimum Python version is now 3.3 2013-12-22 09:52:19 -05:00
Virgil Dupras
7ba2e38cd6 Package PyPI dependencies right into our source package 2013-12-21 12:13:26 -05:00
Virgil Dupras
46f8984bdc Merge branch 'qt5' into develop
Conflicts:
	README.md
	qtlib/about_box.py
	qtlib/reg.py
	qtlib/reg_demo_dialog.py
	qtlib/reg_submit_dialog.py
2013-12-07 19:49:27 -05:00
Virgil Dupras
c7d306b7d5 Minimum Python version is now 3.3 2013-12-07 17:23:18 -05:00
Virgil Dupras
cc5ea1dbc1 Fixed qt5 migration for ME and PE 2013-11-16 13:38:07 -05:00
Virgil Dupras
3b8d355b9e Merge branch 'develop' into qt5
Conflicts:
	hscommon/desktop.py
2013-11-16 12:11:32 -05:00
Virgil Dupras
64d3c211e6 Updated README 2013-10-20 16:26:16 -04:00
Virgil Dupras
fad112f554 Merge branch 'develop' into qt5 2013-10-20 16:02:36 -04:00
Virgil Dupras
5a8cb6f5e3 Implemented super() inheritance style suggested by PyQt5 2013-10-20 15:53:59 -04:00
Virgil Dupras
664d630b96 Fixed occasional core dumps on exit 2013-10-20 15:38:24 -04:00
Virgil Dupras
a4256d3d2b First Qt5 conversion commit
Replaced PyQt4 with PyQt5 and made all adjustments necessary to make
dupeGuru start up.
2013-10-20 15:15:09 -04:00
201 changed files with 23268 additions and 1741 deletions

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ dist
install
installer_tmp-cache
env
/deps
cocoa/autogen
/run.py

View File

@@ -46,26 +46,29 @@ and follow instructions from the script. You can then ignore the rest of the bui
Prerequisites are installed through `pip`. However, some of them are not "pip installable" and have
to be installed manually.
* All systems: [Python 3.2+][python] and [setuptools][setuptools]
* All systems: [Python 3.3+][python] and [setuptools][setuptools]
* Mac OS X: The last XCode to have the 10.6 SDK included.
* Windows: Visual Studio 2008, [PyQt 4.7+][pyqt], [cx_Freeze][cxfreeze] and
* Windows: Visual Studio 2010, [PyQt 5.0+][pyqt], [cx_Freeze][cxfreeze] and
[Advanced Installer][advinst] (you only need the last two if you want to create an installer)
On Ubuntu, the apt-get command to install all pre-requisites is:
On Ubuntu (13.10+), the apt-get command to install all pre-requisites is:
$ apt-get install python3-dev python3-pyqt4 pyqt4-dev-tools python3-setuptools
$ apt-get install python3-dev python3-pyqt5 pyqt5-dev-tools
## Virtualenv setup
On Arch, it's:
First, you need `pip` and `virtualenv` in your system Python install:
$ pacman -S python-pyqt5
$ sudo easy_install pip
$ sudo pip install virtualenv
## Setting up the virtual environment
Then, in dupeGuru's source folder, create a virtual environment and activate it:
Use Python's built-in `pyvenv` to create a virtual environment in which we're going to install our.
Python-related dependencies. `pyvenv` is built-in Python but, unlike its `virtualenv` predecessor,
it doesn't install setuptools and pip, so it has to be installed manually:
$ virtualenv --system-site-packages env
$ pyvenv --system-site-packages env
$ source env/bin/activate
$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
$ easy_install pip
Then, you can install pip requirements in your virtualenv:
@@ -73,17 +76,6 @@ Then, you can install pip requirements in your virtualenv:
([osx|win] depends, of course, on your platform. On other platforms, just use requirements.txt).
## Alternative: pyvenv
If you're on Python 3.3+, you can use the built-in `pyvenv` instead of `virtualenv`. `pyvenv` is
pretty much the same thing as `virtualenv`, except that it doesn't install setuptools and pip, so it
has to be installed manually:
$ pyvenv --system-site-packages env
$ source env/bin/activate
$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
$ easy_install pip
## Actual building and running
With your virtualenv activated, you can build and run dupeGuru with these commands:

View File

@@ -2,24 +2,39 @@
command -v python3 -m venv >/dev/null 2>&1 || { echo >&2 "Python 3.3 required. Install it and try again. Aborting"; exit 1; }
if [ -d "deps" ]; then
# We have a collection of dependencies in our source package. We might as well use it instead
# of downloading it from PyPI.
PIPARGS="--no-index --find-links=deps"
fi
if [ ! -d "env" ]; then
echo "No virtualenv. Creating one"
command -v curl >/dev/null 2>&1 || { echo >&2 "curl required. Install it and try again. Aborting"; exit 1; }
python3 -m venv --system-site-packages env
# We need a "system-site-packages" env to have PyQt, but we also need to ensure a local pip
# install. To achieve our latter goal, we start with a normal venv, which we later upgrade to
# a system-site-packages once pip is installed.
python3 -m venv env
source env/bin/activate
curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py | python
easy_install pip
if python -m ensurepip; then
echo "We're under Python 3.4+, no need to try to install pip!"
else
echo "There's already an env. Activating it"
source env/bin/activate
python get-pip.py $PIPARGS --force-reinstall
fi
deactivate
if [ "$(uname)" != "Darwin" ]; then
# We only need system site packages for PyQt, so under OS X, we don't enable it
python3 -m venv env --upgrade --system-site-packages
fi
fi
source env/bin/activate
echo "Installing pip requirements"
if [ "$(uname)" == "Darwin" ]; then
pip install -r requirements-osx.txt
pip install $PIPARGS -r requirements-osx.txt
else
python3 -c "import PyQt4" >/dev/null 2>&1 || { echo >&2 "PyQt 4.8+ required. Install it and try again. Aborting"; exit 1; }
pip install -r requirements.txt
python3 -c "import PyQt5" >/dev/null 2>&1 || { echo >&2 "PyQt 5.1+ required. Install it and try again. Aborting"; exit 1; }
pip install $PIPARGS -r requirements.txt
fi
echo "Bootstrapping complete! You can now configure, build and run dupeGuru with:"

View File

@@ -19,7 +19,7 @@ from setuptools import setup, Extension
from hscommon import sphinxgen
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, OSXAppStructure,
get_module_version, move_all, copy_all, OSXAppStructure,
build_cocoalib_xibless, fix_qt_resource_file, build_cocoa_ext, copy_embeddable_python_dylib,
collect_stdlib_dependencies, copy)
from hscommon import loc
@@ -123,7 +123,6 @@ def build_cocoa(edition, dev):
del sys.path[0]
# 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_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.
@@ -150,7 +149,7 @@ def build_qt(edition, dev, conf):
print("Building localizations")
build_localizations('qt', edition)
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("pyrcc5 {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'))
build_help(edition)
print("Creating the run.py file")
@@ -188,7 +187,7 @@ def build_localizations(ui, edition):
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
from PyQt5.QtCore import QLibraryInfo
trfolder = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
for lang in loc.get_langs('locale'):
qmname = 'qt_%s.qm' % lang

View File

@@ -126,6 +126,7 @@
"Select a file to save your results to" = "Select a file to save your results to";
"Select a folder to add to the scanning list" = "Select a folder to add to the scanning list";
"Select a results file to load" = "Select a results file to load";
"Select All" = "Select All";
"Select folders to scan and press \"Scan\"." = "Select folders to scan and press \"Scan\".";
"Selected" = "Selected";
"Send Marked to Trash..." = "Send Marked to Trash...";

View File

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

View File

@@ -14,7 +14,7 @@ class PyDupeGuruBase(PyBaseApp):
@dontwrap
def _init(self, modelclass):
logging.basicConfig(level=logging.WARNING, format='%(levelname)s %(message)s')
install_exception_hook()
install_exception_hook('https://github.com/hsoft/dupeguru/issues')
install_cocoa_logger()
patch_threaded_job_performer()
self.model = modelclass(self)

View File

@@ -150,8 +150,6 @@ class DupeGuruME(DupeGuruBase):
self.dead_tracks = []
def _do_delete(self, j, *args):
# XXX If I read correctly, Python 3.3 will allow us to go fetch inner function easily, so
# we'll be able to replace "op" below with DupeGuruBase._do_delete.op.
def op(dupe):
j.add_progress()
return self._do_delete_dupe(dupe, *args)

View File

@@ -6,9 +6,9 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
import plistlib
import logging
import re
import io
from appscript import app, its, k, CommandError, ApplicationNotFoundError
@@ -23,6 +23,7 @@ from core.app import JobType
from core_pe import _block_osx
from core_pe.photo import Photo as PhotoBase
from core_pe.app import DupeGuru as DupeGuruBase
from core_pe.iphoto_plist import IPhotoPlistParser
from .app import PyDupeGuruBase
tr = trget('ui')
@@ -89,7 +90,12 @@ def get_iphoto_or_aperture_pictures(plistpath: Path, photo_class):
s, count = re.subn(r'&(?![a-zA-Z0-9_-]+|#[0-9]+|#x[0-9a-fA-F]+;)', '', s)
if count:
logging.warning("%d invalid XML entities replacement made", count)
plist = plistlib.readPlistFromBytes(s.encode('utf-8'))
parser = IPhotoPlistParser()
try:
plist = parser.parse(io.BytesIO(s.encode('utf-8')))
except Exception:
logging.warning("iPhoto plist parsing choked on data: %r", parser.lastdata)
raise
result = []
for key, photo_data in plist['Master Image List'].items():
if photo_data['MediaType'] != 'Image':
@@ -325,6 +331,7 @@ class PyDupeGuru(PyDupeGuruBase):
self.model.scanner.scan_type = [
ScanType.FuzzyBlock,
ScanType.ExifTimestamp,
ScanType.TriggerHappyMode,
][scan_type]
except IndexError:
pass

View File

@@ -31,7 +31,7 @@ def configure(conf):
os.symlink('../build/Python', versioned_dylib_path)
# The rest is standard WAF code that you can find the the python and macapp demos.
conf.load('compiler_c python')
conf.check_python_version((3,2,0))
conf.check_python_version((3,3,0))
conf.check_python_headers()
conf.env.FRAMEWORK_COCOA = 'Cocoa'
conf.env.ARCH_COCOA = ['x86_64']

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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
@@ -11,13 +11,16 @@ http://www.hardcoded.net/licenses/bsd_license
@interface HSErrorReportWindow : NSWindowController
{
NSTextView *contentTextView;
NSString *githubUrl;
}
@property (readwrite, retain) NSTextView *contentTextView;
@property (readwrite, retain) NSString *githubUrl;
+ (void)showErrorReportWithContent:(NSString *)content;
- (id)initWithContent:(NSString *)content;
// True if the user wants to send the report
+ (void)showErrorReportWithContent:(NSString *)content githubUrl:(NSString *)githubUrl;
- (id)initWithContent:(NSString *)content githubUrl:(NSString *)githubUrl;
- (void)send;
- (void)dontSend;
- (void)goToGithub;
- (void)close;
@end

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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
@@ -12,37 +12,33 @@ http://www.hardcoded.net/licenses/bsd_license
@implementation HSErrorReportWindow
@synthesize contentTextView;
@synthesize githubUrl;
+ (void)showErrorReportWithContent:(NSString *)content
+ (void)showErrorReportWithContent:(NSString *)content githubUrl:(NSString *)githubUrl
{
HSErrorReportWindow *report = [[HSErrorReportWindow alloc] initWithContent:content];
HSErrorReportWindow *report = [[HSErrorReportWindow alloc] initWithContent:content githubUrl:githubUrl];
[NSApp runModalForWindow:[report window]];
[report release];
}
- (id)initWithContent:(NSString *)content
- (id)initWithContent:(NSString *)content githubUrl:(NSString *)aGithubUrl
{
self = [super initWithWindow:nil];
[self setWindow:createHSErrorReportWindow_UI(self)];
[contentTextView alignLeft:nil];
[[[contentTextView textStorage] mutableString] setString:content];
self.githubUrl = aGithubUrl;
return self;
}
- (void)send
- (void)goToGithub
{
NSString *text = [[contentTextView textStorage] string];
NSString *URL = [NSString stringWithFormat:@"mailto:support@hardcoded.net?SUBJECT=Error Report&BODY=%@",text];
NSString *encodedURL = [URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:encodedURL]];
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:self.githubUrl]];
}
- (void)close
{
[[self window] orderOut:self];
[NSApp stopModalWithCode:NSOKButton];
}
- (void)dontSend
{
[[self window] orderOut:self];
[NSApp stopModalWithCode:NSCancelButton];
}
@end

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -28,7 +28,7 @@
- (NSString *)url2path:(NSString *)url;
- (void)createPool;
- (void)destroyPool;
- (void)reportCrash:(NSString *)crashReport;
- (void)reportCrash:(NSString *)crashReport withGithubUrl:(NSString *)githubUrl;
- (void)log:(NSString *)s;
- (NSDictionary *)readExifData:(NSString *)imagePath;
@end

View File

@@ -143,9 +143,9 @@
}
}
- (void)reportCrash:(NSString *)crashReport
- (void)reportCrash:(NSString *)crashReport withGithubUrl:(NSString *)githubUrl
{
[HSErrorReportWindow showErrorReportWithContent:crashReport];
return [HSErrorReportWindow showErrorReportWithContent:crashReport githubUrl:githubUrl];
}
- (void)log:(NSString *)s

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras
# Created On: 2007-10-06
# Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
# 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
@@ -9,7 +9,6 @@
import logging
import time
import traceback
import subprocess
import sys
from .CocoaProxy import CocoaProxy
@@ -81,6 +80,7 @@ def safe_format_exception(type, value, tb):
result.extend(traceback.format_exception_only(type, value))
return result
def install_exception_hook(github_url):
def report_crash(type, value, tb):
app_identifier = proxy.bundleIdentifier()
app_version = proxy.appVersion()
@@ -89,22 +89,22 @@ def report_crash(type, value, tb):
s += "Application Version: {}\n".format(app_version)
s += "Mac OS X Version: {}\n\n".format(osx_version)
s += ''.join(safe_format_exception(type, value, tb))
if app_identifier:
if LOG_BUFFER:
s += '\nRelevant Console logs:\n\n'
p = subprocess.Popen(['grep', app_identifier, '/var/log/system.log'], stdout=subprocess.PIPE)
try:
s += str(p.communicate()[0], encoding='utf-8')
except IndexError:
# This can happen if something went wrong with the grep (permission errors?)
pass
proxy.reportCrash_(s)
s += '\n'.join(LOG_BUFFER)
proxy.reportCrash_withGithubUrl_(s, github_url)
def install_exception_hook():
sys.excepthook = report_crash
# A global log buffer to use for error reports
LOG_BUFFER = []
class CocoaHandler(logging.Handler):
def emit(self, record):
proxy.log_(record.getMessage())
msg = record.getMessage()
proxy.log_(msg)
LOG_BUFFER.append(msg)
del LOG_BUFFER[:-20]
def install_cocoa_logger():
logging.getLogger().addHandler(CocoaHandler())

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,14 +1,14 @@
"Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application." = "Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application.";
"Cancel" = "Cancel";
"Clear List" = "Clear List";
"Don't Send" = "Don't Send";
"Close" = "Close";
"Error Report" = "Error Report";
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n\nAlthough the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application." = "Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n\nAlthough the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application.";
"Go to Github" = "Go to Github";
"No" = "No";
"OK" = "OK";
"Please wait..." = "Please wait...";
"Send" = "Send";
"Something went wrong. Would you like to send the error report to Hardcoded Software?" = "Something went wrong. Would you like to send the error report to Hardcoded Software?";
"Something went wrong. How about reporting the error?" = "Something went wrong. How about reporting the error?";
"Status: Working..." = "Status: Working...";
"Work in progress, please wait." = "Work in progress, please wait.";
"Work in progress..." = "Work in progress...";

View File

@@ -2,12 +2,6 @@
msgid ""
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr ""
@@ -17,13 +11,24 @@ msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "No"
msgstr ""
@@ -37,13 +42,7 @@ msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Cancel"
@@ -23,10 +17,6 @@ msgstr "Cancel"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Don't Send"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,18 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Send"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -70,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Abbrechen"
@@ -23,10 +17,6 @@ msgstr "Abbrechen"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Don't Send"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,18 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Send"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -70,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,14 +9,6 @@ msgstr ""
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
"Aunque la aplicación debería continuar funcionado tras el fallo, sin embargo"
" podría volverse inestable. Se recomienda reiniciar la aplicación."
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Cancelar"
@@ -25,10 +17,6 @@ msgstr "Cancelar"
msgid "Clear List"
msgstr "Limpiar lista"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "No envíar"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr "Informe de error"
@@ -45,18 +33,6 @@ msgstr "Aceptar"
msgid "Please wait..."
msgstr "Por favor, espere..."
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Enviar"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Se ha producido un error. ¿Desea enviar un informe de error a Harcoded "
"Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr "Estado: procesando..."
@@ -72,3 +48,22 @@ msgstr "En proceso..."
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr "Sí"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Annuler"
@@ -23,10 +17,6 @@ msgstr "Annuler"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Ignorer"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,17 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Envoyer"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Il y a eu une erreur, voulez vous envoyer le rapport à Hardcoded Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -69,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: hy\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Չեղարկել"
@@ -23,10 +17,6 @@ msgstr "Չեղարկել"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Չուղարկել"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,17 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Ուղարկել"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Ինչ-որ բան սխալ էր: Ուղարկե՞լ սխալի մասին զեկույց Hardcoded Software-ին:"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -69,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Annulla"
@@ -23,10 +17,6 @@ msgstr "Annulla"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Non inviare"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,18 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Invia"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Qualcosa è andato storto. Desideri inviare la segnalazione di errore a "
"Hardcoded Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -70,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: nl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr ""
@@ -23,10 +17,6 @@ msgstr ""
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,16 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -68,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,14 +9,6 @@ msgstr ""
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
"Embora o aplicativo continue a funcionar após este erro, ele pode estar "
"instável. É recomendável reiniciá-lo."
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Cancelar"
@@ -25,10 +17,6 @@ msgstr "Cancelar"
msgid "Clear List"
msgstr "Limpar Lista"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Não Enviar"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -45,17 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr "Aguarde..."
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Enviar"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Algo deu errado. Deseja enviar o relatório de erro à Hardcoded Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -71,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr "Sim"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: ru\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Отменить"
@@ -23,10 +17,6 @@ msgstr "Отменить"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Не отправлять"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,17 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Отправить"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Что-то пошло не так. Хотите отправить отчет об ошибке в Hardcoded Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -69,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,14 +9,6 @@ msgstr ""
"Language: uk\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
"Хоча програма має продовжувати роботу після цієї помилки, вона може "
"перебувати у нестабільному стані, тож рекомендується перезапустити програму."
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "Відмінити"
@@ -25,10 +17,6 @@ msgstr "Відмінити"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Не надсилати"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -45,17 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Надіслати"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Щось пішло не так. Хочете відправити звіт про помилку до Hardcoded Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -71,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -10,12 +10,6 @@ msgstr ""
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr ""
@@ -24,10 +18,6 @@ msgstr ""
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -44,16 +34,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -69,3 +49,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -9,12 +9,6 @@ msgstr ""
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Although the application should continue to run after this error, it may be "
"in an instable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Cancel"
msgstr "取消"
@@ -23,10 +17,6 @@ msgstr "取消"
msgid "Clear List"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Don't Send"
msgstr "Don't Send"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Error Report"
msgstr ""
@@ -43,18 +33,6 @@ msgstr ""
msgid "Please wait..."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Send"
msgstr "Send"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
msgstr ""
"Something went wrong. Would you like to send the error report to Hardcoded "
"Software?"
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Status: Working..."
msgstr ""
@@ -70,3 +48,22 @@ msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Yes"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Close"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Go to Github"
msgstr ""
#: cocoalib/en.lproj/cocoalib.strings:0
msgid "Something went wrong. How about reporting the error?"
msgstr ""

View File

@@ -1,33 +1,41 @@
ownerclass = 'HSErrorReportWindow'
ownerimport = 'HSErrorReportWindow.h'
result = Window(524, 390, "Error Report")
result = Window(524, 470, "Error Report")
result.canClose = False
result.canResize = False
result.canMinimize = False
label1 = Label(result, "Something went wrong. Would you like to send the error report to Hardcoded Software?")
label1 = Label(result, "Something went wrong. How about reporting the error?")
errorTextView = TextView(result)
label2 = Label(result, "Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application.")
sendButton = Button(result, "Send")
dontSendButton = Button(result, "Don't Send")
label2 = Label(result,
"Error reports should be reported as Github issues. You can copy the error traceback "
"above and paste it in a new issue (bonus point if you run a search to make sure the "
"issue doesn't already exist). What usually really helps is if you add a description "
"of how you got the error. Thanks!"
"\n\n"
"Although the application should continue to run after this error, it may be in an "
"unstable state, so it is recommended that you restart the application."
)
sendButton = Button(result, "Go to Github")
dontSendButton = Button(result, "Close")
owner.contentTextView = errorTextView
sendButton.action = Action(owner, 'send')
sendButton.action = Action(owner, 'goToGithub')
sendButton.keyEquivalent = "\\r"
dontSendButton.action = Action(owner, 'dontSend')
dontSendButton.action = Action(owner, 'close')
dontSendButton.keyEquivalent = "\\E"
label1.height = 34
errorTextView.height = 221
label2.height = 51
label2.height = 130
sendButton.width = 100
dontSendButton.width = 100
label1.packToCorner(Pack.UpperLeft)
label1.moveTo(Pack.UpperLeft)
label1.fill(Pack.Right)
errorTextView.packRelativeTo(label1, Pack.Below, Pack.Left)
errorTextView.moveNextTo(label1, Pack.Below, Pack.Left)
errorTextView.fill(Pack.Right)
label2.packRelativeTo(errorTextView, Pack.Below, Pack.Left)
label2.moveNextTo(errorTextView, Pack.Below, Pack.Left)
label2.fill(Pack.Right)
sendButton.packRelativeTo(label2, Pack.Below, Pack.Right)
dontSendButton.packRelativeTo(sendButton, Pack.Left, Pack.Middle)
sendButton.moveNextTo(label2, Pack.Below, Pack.Right)
dontSendButton.moveNextTo(sendButton, Pack.Left, Pack.Middle)

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -1,5 +1,5 @@
/*
Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
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

View File

@@ -51,6 +51,7 @@ class Directories:
#---Override
def __init__(self, fileclasses=[fs.File]):
self._dirs = []
# {path: state}
self.states = {}
self.fileclasses = fileclasses
self.folderclass = fs.Folder
@@ -220,7 +221,7 @@ class Directories:
continue
path = attrib['path']
state = attrib['value']
self.set_state(Path(path), int(state))
self.states[Path(path)] = int(state)
def save_to_file(self, outfile):
"""Save folder selection as XML to ``outfile``.
@@ -248,11 +249,8 @@ class Directories:
"""
if self.get_state(path) == state:
return
# we don't want to needlessly fill self.states. if get_state returns the same thing
# without an explicit entry, remove that entry
if path in self.states:
del self.states[path]
if self.get_state(path) == state: # no need for an entry
return
for iter_path in list(self.states.keys()):
if path.is_parent_of(iter_path):
del self.states[iter_path]
self.states[path] = state

View File

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

View File

@@ -135,31 +135,18 @@ def test_get_state_with_path_not_there():
d.add_path(testpath['onefile'])
eq_(d.get_state(testpath), DirectoryState.Normal)
def test_states_remain_when_larger_directory_eat_smaller_ones():
def test_states_overwritten_when_larger_directory_eat_smaller_ones():
# ref #248
# When setting the state of a folder, we overwrite previously set states for subfolders.
d = Directories()
p = testpath['onefile']
d.add_path(p)
d.set_state(p, DirectoryState.Excluded)
d.add_path(testpath)
d.set_state(testpath, DirectoryState.Reference)
eq_(DirectoryState.Excluded ,d.get_state(p))
eq_(DirectoryState.Excluded ,d.get_state(p['dir1']))
eq_(DirectoryState.Reference ,d.get_state(testpath))
def test_set_state_keep_state_dict_size_to_minimum():
d = Directories()
p = testpath['fs']
d.add_path(p)
d.set_state(p, DirectoryState.Reference)
d.set_state(p['dir1'], DirectoryState.Reference)
eq_(1,len(d.states))
eq_(DirectoryState.Reference ,d.get_state(p['dir1']))
d.set_state(p['dir1'], DirectoryState.Normal)
eq_(2,len(d.states))
eq_(DirectoryState.Normal ,d.get_state(p['dir1']))
d.set_state(p['dir1'], DirectoryState.Reference)
eq_(1,len(d.states))
eq_(DirectoryState.Reference ,d.get_state(p['dir1']))
eq_(d.get_state(p), DirectoryState.Reference)
eq_(d.get_state(p['dir1']), DirectoryState.Reference)
eq_(d.get_state(testpath), DirectoryState.Reference)
def test_get_files():
d = Directories()

View File

@@ -7,7 +7,6 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon import io
from hscommon.path import Path
from core.engine import getwords
@@ -18,7 +17,6 @@ def pytest_funcarg__fake_fileexists(request):
# This is a hack to avoid invalidating all previous tests since the scanner started to test
# for file existence before doing the match grouping.
monkeypatch = request.getfuncargvalue('monkeypatch')
monkeypatch.setattr(io, 'exists', lambda _: True)
monkeypatch.setattr(Path, 'exists', lambda _: True)
def test_priorize_me(fake_fileexists):

View File

@@ -1,2 +1,2 @@
__version__ = '2.8.0'
__version__ = '2.9.0'
__appname__ = 'dupeGuru Picture Edition'

31
core_pe/iphoto_plist.py Normal file
View File

@@ -0,0 +1,31 @@
# Created By: Virgil Dupras
# Created On: 2014-03-15
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
#
# 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
# http://www.hardcoded.net/licenses/bsd_license
import plistlib
class IPhotoPlistParser(plistlib.PlistParser):
"""A parser for iPhoto plists.
iPhoto plists tend to be malformed, so we have to subclass the built-in parser to be a bit more
lenient.
"""
def __init__(self):
plistlib.PlistParser.__init__(self)
# For debugging purposes, we remember the last bit of data to be analyzed so that we can
# log it in case of an exception
self.lastdata = ''
def getData(self):
self.lastdata = plistlib.PlistParser.getData(self)
return self.lastdata
def end_integer(self):
try:
self.addObject(int(self.getData()))
except ValueError:
self.addObject(0)

View File

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

View File

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

2
debian/control vendored
View File

@@ -8,5 +8,5 @@ Homepage: http://www.hardcoded.net
Package: {pkgname}
Architecture: {arch}
Depends: python3 (>=3.2), python3-pyqt4
Depends: python3 (>=3.3), python3-pyqt4
Description: {longname}

25
download_deps.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
# The goal here is to have a folder with all packages needed as dependencies by the project. The
# obvious solution is "pip install --download deps -r requirements.txt", but this thing doesn't
# follow sub-dependencies. The 2nd obvious solution would be to use the result of a `pip freeze`
# instead of requirements.txt, but this command outputs everything on the system, which isn't cool.
# So, what about "pip freeze -l"? That would work, unless one of the dependencies is installed
# system-wide (Sphinx often is). We can't disable system site packages because we need PyQt, which
# is always installed globally.
# So, what we do here is that we create a brand new venv just for dependencies download, which
# we'll pip freeze.
rm -rf deps
rm -rf depsenv
mkdir deps
python3 -m venv depsenv
source depsenv/bin/activate
python get-pip.py
pip install -r requirements.txt
pip freeze -l > deps/requirements.freeze
pip install --download=deps -r deps/requirements.freeze setuptools pip
deactivate
rm -rf depsenv

21384
get-pip.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
* Fixed crash on Dupe Count sorting with Delta + Dupes Only. (#238)
* Improved documentation.
* Important internal refactorings.
* Dropped Ubuntu 12.04 and 12.10 support.
* Removed the fairware dialog ([More Info](http://www.hardcoded.net/articles/phasing-out-fairware)).
=== 6.6.0 (2013-08-18)

View File

@@ -1,3 +1,16 @@
=== 2.9.0 (2013-12-22)
* Read RAW pictures EXIF tags. [Mac] (#234)
* Disable symlink/hardlink deletion option when not relevant. (#247)
* Make Cmd+A select all folders in the Folder Selection dialog. [Mac] (#228)
* Make non-numeric delta comparison case insensitive. (#239)
* Fix surrogate-related UnicodeEncodeError on CSV export. (#210)
* Fixed crash on Dupe Count sorting with Delta + Dupes Only. (#238)
* Improved documentation.
* Important internal refactorings.
* Dropped Ubuntu 12.04 and 12.10 support.
* Removed the fairware dialog ([More Info](http://www.hardcoded.net/articles/phasing-out-fairware)).
=== 2.8.0 (2013-08-25)
* Improved delta values to support non-numerical values. (#213)

View File

@@ -7,6 +7,7 @@
* Fixed crash on Dupe Count sorting with Delta + Dupes Only. (#238)
* Improved documentation.
* Important internal refactorings.
* Dropped Ubuntu 12.04 and 12.10 support.
* Removed the fairware dialog ([More Info](http://www.hardcoded.net/articles/phasing-out-fairware)).
=== 3.7.1 (2013-08-19)

87
help/en/contribute.rst Normal file
View File

@@ -0,0 +1,87 @@
Contribute to dupeGuru
======================
dupeGuru was started as shareware (thus proprietary) so it doesn't have a legacy of
community-building. It's `been open source`_ for a while now and, although I've ("I" being Virgil
Dupras, author of the software) always wanted to have people other than me working on dupeGuru, I've
failed at attracting them.
Since the end of 2013, I've been putting a lot of efforts into dupeGuru's
:doc:`developer documentation </developer/index>` and I'm more serious about my commitment to create
a community around this project.
So, whatever your skills, if you're interested in contributing to dupeGuru, please do so. Normally,
this documentation should be enough to get you started, but if it isn't, then **please**,
`let me know`_ because it's a problem that I'm committed to fix. If there's any situation where you'd
wish to contribute but some doubt you're having prevent you from going forward, please contact me.
I'd much prefer to spend the time figuring out with you whether (and how) you can contribute than
taking the chance of missing that opportunity.
Development process
-------------------
* `Source code repository`_
* `Issue Tracker`_
* `Issue labels meaning`_
dupeGuru's source code is on Github and thus managed in a Git repository. At all times, you should
be able to build from source a fresh checkout of the ``master`` branch using instructions from the
``README.md`` file at the root of this project. If you can't, it's a bug. Please report it.
Bugfixes happen directly in the ``master`` branch, but feature development takes place in the
``develop`` branch. When implementing a big feature, it's possible that it gets its own branch until
it's stable enough to merge into ``develop``.
Every release is tagged, the tag name containing the edition and its version. For example, release
6.6.0 of dupeGuru ME is tagged ``me6.6.0``.
Once you're past building the software, the :doc:`developer documentation </developer/index>` should
be enough to get you started with actual development. Then again, proper documentation is a very
difficult task and, in the case of dupeGuru, this documentation was practically nonexistent until
late in the project, so it's still lacking.
However, I'm committed to fix this situation, so if you're in a situation where you lack proper
documentation to figure something out about this code, please contact me.
Tasks for non-developers
------------------------
**Create and comment issues**. The single most useful way for a user who is not a developer to
contribute to a software project is by thoroughly documenting a bug or a feature request. Most of
the time, what we get as developers are emails like "the app crashes" and we spend a lot of time
trying to figure out the cause of that bug. By properly describing the nature and context of a crash
(we learn to do that with experience as a user who reports bugs), you help developers so immensely,
you have no idea.
It's the same thing with feature requests. Description of a feature request, when thoughts have
already been given to how such a feature would fit in the current design, are precious to developers
and help them figure out a clear roadmap for the project.
So, even if you're not a developer, you can always open a Github account and create/comment issues.
Your contribution will be much appreciated.
**Documentation**. This is a bit trickier because dupeGuru's documentation is written with a rather
complex markup language, `Sphinx`_ (based on `reST`_). To properly work within the documentation,
you have to know that language. I don't think that learning this language is outside the realm of
possibility for a non-developer, but it might be a daunting task.
That being said, if it's a minor modification to the documentation, nothing stops you from opening
an issue (there's a label for documentation issues, so this kind of issue is relevant to the
tracker) describing the change you propose to make and I'll be happy to make the change myself (if
relevant, of course).
Even if it's a bigger contribution to the documentation you want to make, I probably wouldn't mind
doing the formatting myself. But in that case, it's better to contact me first to make sure that we
agree on what should be added to the documentation.
**Translation**. Creating or improving an existing translation is a very good way to contribute to
dupeGuru. For more information about how to do that, you can refer to the `translator guide`_.
.. _been open source: http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade
.. _let me know: mailto:hsoft@hardcoded.net
.. _Source code repository: https://github.com/hsoft/dupeguru
.. _Issue Tracker: https://github.com/hsoft/dupeguru/issues
.. _Issue labels meaning: https://github.com/hsoft/dupeguru/wiki/issue-labels
.. _Sphinx: http://sphinx-doc.org/
.. _reST: http://en.wikipedia.org/wiki/ReStructuredText
.. _translator guide: https://github.com/hsoft/dupeguru/wiki/Translator-Guide

View File

@@ -3,27 +3,22 @@ Frequently Asked Questions
.. contents::
What is |appname|?
------------------
.. only:: edition_se
What is dupeGuru?
-----------------
dupeGuru is a tool to find duplicate files on your computer. It can scan either filenames or
content. The filename scan features a fuzzy matching algorithm that can find duplicate
contents. The filename scan features a fuzzy matching algorithm that can find duplicate
filenames even when they are not exactly the same.
.. only:: edition_me
dupeGuru also comes in two extra flavors: Music Edition and Picture Edition. These editions behave
like the normal dupeGuru, but has specialized options.
dupeGuru Music Edition is a tool to find duplicate songs in your music collection. It can
base its scan on filenames, tags or content. The filename and tag scans feature a fuzzy
matching algorithm that can find duplicate filenames or tags even when they are not exactly
the same.
dupeGuru Music Edition [ME] is made to scan songs. It can base its scan on filenames, tags or
contents. The filename and tag scans feature a fuzzy matching algorithm that can find duplicate
filenames or tags even when they are not exactly the same.
.. only:: edition_pe
dupeGuru Picture Edition (PE for short) is a tool to find duplicate pictures on your
computer. Not only can it find exact matches, but it can also find duplicates among pictures
of different kind (PNG, JPG, GIF etc..) and quality.
dupeGuru Picture Edition [PE] is made to scan pictures. Not only can it find exact matches, but it
can also find duplicates among pictures of different kind (PNG, JPG, GIF etc..) and quality.
What makes it better than other duplicate scanners?
---------------------------------------------------
@@ -39,12 +34,6 @@ First, there is the reference folder system that lets you define folders where y
**don't** want dupeGuru to let you delete files there, and then there is the group reference system
that makes sure that you will **always** keep at least one member of the duplicate group.
What are the demo limitations of dupeGuru?
------------------------------------------
In demo mode, you can only perform actions on 10 duplicates at once. In
`Fairware <http://open.hardcoded.net/about/>`_ mode, however, there are no limitations.
The mark box of a file I want to delete is disabled. What must I do?
--------------------------------------------------------------------
@@ -82,8 +71,6 @@ Enable the :doc:`Dupes Only <results>` mode and click on the Folder column to so
by folder. It will then be easy for you to select all duplicates from the same folder, and then
press Space to mark all selected duplicates.
.. only:: edition_se or edition_pe
I want to remove all files that are more than 300 KB away from their reference file. What can I do?
---------------------------------------------------------------------------------------------------
@@ -111,11 +98,11 @@ press Space to mark all selected duplicates.
* Type "copy" in the "Filter" field in the top-right corner of the result window.
* Click on **Mark --> Mark All**.
.. only:: edition_me
I want to remove all songs that are more than 3 seconds away from their reference file. What can I do?
------------------------------------------------------------------------------------------------------
*ME only*
* Enable the :doc:`Dupes Only <results>` mode.
* Enable the **Delta Values** mode.
* Click on the "Time" column to sort the results by time.
@@ -127,6 +114,8 @@ press Space to mark all selected duplicates.
I want to make my highest bitrate songs reference files. What can I do?
-----------------------------------------------------------------------
*ME only*
* Enable the :doc:`Dupes Only <results>` mode.
* Enable the **Delta Values** mode.
* Click on the "Bitrate" column to sort the results by bitrate.
@@ -147,6 +136,15 @@ press Space to mark all selected duplicates.
* Click on **Mark --> Mark All**.
* Click on **Actions --> Remove Selected from Results**.
The "Filter Hardness" slider in the preferences won't move!
-----------------------------------------------------------
This slider is only relevant for scan types that support "fuzziness". Many scan types, such as the
"Contents" type, only support exact matches. When these types are selected, the slider is disabled.
On some OS, the fact that it's disabled is harder to see than on others, but if you can't move the
slider, it means that this preference is irrelevant in your current scan type.
I've tried to send my duplicates to Trash, but dupeGuru is telling me it can't do it. Why? What can I do?
---------------------------------------------------------------------------------------------------------
@@ -159,16 +157,25 @@ delete files" option that is offered to you when you activate Send to Trash. Thi
files to the Trash, but delete them immediately. In some cases, for example on network storage
(NAS), this has been known to work when normal deletion didn't.
.. only:: edition_pe
If you're trying to delete *iPhoto* pictures, then the reason for the failure is different. The
deletion fails because dupeGuru can't communicate with iPhoto. Be aware that for the deletion
to work correctly, you're not supposed to play around iPhoto while dupeGuru is working. Also,
sometimes, the Applescript system doesn't seem to know where to find iPhoto to launch it. It
*PE only.* If you're trying to delete *iPhoto* pictures, then the reason for the failure is
different. The deletion fails because dupeGuru can't communicate with iPhoto. Be aware that for the
deletion to work correctly, you're not supposed to play around iPhoto while dupeGuru is working.
Also, sometimes, the Applescript system doesn't seem to know where to find iPhoto to launch it. It
might help in these cases to launch iPhoto *before* you send your duplicates to Trash.
If all of this fail, `contact HS support`_, we'll figure it out.
Why is dupeGuru PE so slower than other editions?
-------------------------------------------------
dupeGuru PE's scanning method is very different from dupeGuru's. dupeGuru PE can detect duplicate
photos even if they are not exactly the same. This very cool capability has a cost: time. Every
picture has to be individually and fuzzily matched to all others, and this takes a lot of CPU power.
If all you need to find is exact duplicates, just use the standard edition of dupeGuru with the
Contents scan method. If your photos have EXIF tags, you can also try PE's "EXIF" scan method which
is much faster.
Where are user files located?
-----------------------------

View File

@@ -48,6 +48,7 @@ Contents:
.. toctree::
:maxdepth: 2
contribute
quick_start
folders
preferences

View File

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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras
# Created On: 2009-03-03
# Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
# 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
@@ -211,7 +211,7 @@ def copy_packages(packages_names, dest, create_links=False, extra_ignores=None):
shutil.copy(source_path, dest_path)
def copy_qt_plugins(folder_names, dest): # This is only for Windows
from PyQt4.QtCore import QLibraryInfo
from PyQt5.QtCore import QLibraryInfo
qt_plugin_dir = QLibraryInfo.location(QLibraryInfo.PluginsPath)
def ignore(path, names):
if path == qt_plugin_dir:
@@ -448,9 +448,11 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
# There's a couple of rather big exe files in the distutils folder that we absolutely don't
# need. Remove them.
delete_files_with_pattern(op.join(dest_folder, 'distutils'), '*.exe')
# And, finally, create an empty "site.py" that Python needs around on startup.
open(op.join(dest_folder, 'site.py'), 'w').close()
def fix_qt_resource_file(path):
# pyrcc4 under Windows, if the locale is non-english, can produce a source file with a date
# pyrcc5 under Windows, if the locale is non-english, can produce a source file with a date
# containing accented characters. If it does, the encoding is wrong and it prevents the file
# from being correctly frozen by cx_freeze. To work around that, we open the file, strip all
# comments, and save.

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras
# Created On: 2008-01-08
# Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras
# Created On: 2008-04-20
# Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
# 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

View File

@@ -1,6 +1,6 @@
# Created By: Virgil Dupras
# Created On: 2011-04-19
# Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
# Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
#
# 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

View File

@@ -61,8 +61,11 @@ try:
except ImportError:
try:
from PyQt4.QtCore import QUrl
from PyQt4.QtGui import QDesktopServices
from PyQt5.QtCore import QUrl, QStandardPaths
from PyQt5.QtGui import QDesktopServices
def _open_url(url):
QDesktopServices.openUrl(QUrl(url))
def _open_path(path):
url = QUrl.fromLocalFile(str(path))
QDesktopServices.openUrl(url)
@@ -72,10 +75,10 @@ except ImportError:
def _special_folder_path(special_folder, appname=None):
if special_folder == SpecialFolder.Cache:
qtfolder = QDesktopServices.CacheLocation
qtfolder = QStandardPaths.CacheLocation
else:
qtfolder = QDesktopServices.DataLocation
return str(QDesktopServices.storageLocation(qtfolder))
qtfolder = QStandardPaths.DataLocation
return QStandardPaths.standardLocations(qtfolder)[0]
except ImportError:
# We're either running tests, and these functions don't matter much or we're in a really

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