mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-25 16:11:39 +00:00
Compare commits
92 Commits
se3.7.1
...
trigger-ha
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bd0ec8875 | ||
|
|
ba13b700b0 | ||
|
|
640561a534 | ||
|
|
e4f81cbf04 | ||
|
|
4be4825112 | ||
|
|
7d107d8efa | ||
|
|
10d1363334 | ||
|
|
b76820ebde | ||
|
|
72b3cfb364 | ||
|
|
8b83ed0e5c | ||
|
|
781f13ae1a | ||
|
|
8193bbae6e | ||
|
|
4cafeaff91 | ||
|
|
95c6a7d41f | ||
|
|
a29e007475 | ||
|
|
d924d7797a | ||
|
|
33c217ecc8 | ||
|
|
c9035046ae | ||
|
|
ad31016825 | ||
|
|
c809066a93 | ||
|
|
60ca27b5e1 | ||
|
|
1104e24408 | ||
|
|
f66db94ffd | ||
|
|
d98b5b22da | ||
|
|
937748e838 | ||
|
|
37ebf36cee | ||
|
|
1c84bdd198 | ||
|
|
4a2fa7cd2c | ||
|
|
7d4110f6d3 | ||
|
|
8497343d7f | ||
|
|
235a2c2904 | ||
|
|
25169cfc20 | ||
|
|
152f5f37ce | ||
|
|
3e42ad8469 | ||
|
|
7ba2e38cd6 | ||
|
|
c7c7a73384 | ||
|
|
46f8984bdc | ||
|
|
c7d306b7d5 | ||
|
|
47e636e949 | ||
|
|
0562729d8b | ||
|
|
4a36227a18 | ||
|
|
28b8b2e415 | ||
|
|
fd82464564 | ||
|
|
418acf6e5e | ||
|
|
d14d076989 | ||
|
|
cb8bb5a70e | ||
|
|
563c9aeff3 | ||
|
|
a0cc1f2e03 | ||
|
|
01403a3f92 | ||
|
|
7116674663 | ||
|
|
b6bc5de79c | ||
|
|
5a275db67d | ||
|
|
31395d8794 | ||
|
|
3734bd6f6c | ||
|
|
da06ef8cad | ||
|
|
0b00171655 | ||
|
|
c1cfa86ad1 | ||
|
|
c34c9562d3 | ||
|
|
0e542577b0 | ||
|
|
42be49da83 | ||
|
|
398ac9b7c6 | ||
|
|
508e9a5d94 | ||
|
|
cc5ea1dbc1 | ||
|
|
3b8d355b9e | ||
|
|
10dbfa9b38 | ||
|
|
e8c42740cf | ||
|
|
4b6c4f048d | ||
|
|
7594cccf8c | ||
|
|
1d9573cf6f | ||
|
|
76f45fb5a6 | ||
|
|
12cf9b800b | ||
|
|
ba7e6494c6 | ||
|
|
72d8160b28 | ||
|
|
6d53511cee | ||
|
|
64d3c211e6 | ||
|
|
fad112f554 | ||
|
|
a563327723 | ||
|
|
096e2bb78a | ||
|
|
5a8cb6f5e3 | ||
|
|
664d630b96 | ||
|
|
a4256d3d2b | ||
|
|
8e65f15e1a | ||
|
|
9ea9f60e92 | ||
|
|
8efefaf0bf | ||
|
|
33d9569427 | ||
|
|
2fdfacb34e | ||
|
|
97fcf1ffa8 | ||
|
|
350b2c64e0 | ||
|
|
dcc57a7afb | ||
|
|
8b510994ad | ||
|
|
4a4d1bbfcd | ||
|
|
78c3c8ec2d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,6 +11,7 @@ dist
|
|||||||
install
|
install
|
||||||
installer_tmp-cache
|
installer_tmp-cache
|
||||||
env
|
env
|
||||||
|
/deps
|
||||||
cocoa/autogen
|
cocoa/autogen
|
||||||
|
|
||||||
/run.py
|
/run.py
|
||||||
|
|||||||
50
README.md
50
README.md
@@ -1,7 +1,17 @@
|
|||||||
# dupeGuru
|
# dupeGuru
|
||||||
|
|
||||||
This package contains the source for dupeGuru. Its documentation is
|
[dupeGuru][dupeguru] is a cross-platform (Linux, OS X, Windows) GUI tool to find duplicate files in
|
||||||
[available online][documentation]. Here's how this source tree is organised:
|
a system. It's written mostly in Python 3 and has the peculiarity of using
|
||||||
|
[multiple GUI toolkits][cross-toolkit], all using the same core Python code. On OS X, the UI layer
|
||||||
|
is written in Objective-C and uses Cocoa. On Linux and Windows, it's written in Python and uses Qt4.
|
||||||
|
|
||||||
|
dupeGuru comes in 3 editions (standard, music and picture) which are all buildable from this same
|
||||||
|
source tree. You choose the edition you want to build in a ``configure.py`` flag.
|
||||||
|
|
||||||
|
# Contents of this folder
|
||||||
|
|
||||||
|
This folder contains the source for dupeGuru. Its documentation is in ``help``, but is also
|
||||||
|
[available online][documentation] in its built form. Here's how this source tree is organised:
|
||||||
|
|
||||||
* core: Contains the core logic code for dupeGuru. It's Python code.
|
* 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.
|
||||||
@@ -36,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
|
Prerequisites are installed through `pip`. However, some of them are not "pip installable" and have
|
||||||
to be installed manually.
|
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.
|
* 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)
|
[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
|
## Setting up the virtual environment
|
||||||
$ sudo pip install virtualenv
|
|
||||||
|
|
||||||
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
|
$ 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:
|
Then, you can install pip requirements in your virtualenv:
|
||||||
|
|
||||||
@@ -63,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).
|
([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
|
## Actual building and running
|
||||||
|
|
||||||
With your virtualenv activated, you can build and run dupeGuru with these commands:
|
With your virtualenv activated, you can build and run dupeGuru with these commands:
|
||||||
@@ -86,6 +88,8 @@ You can also package dupeGuru into an installable package with:
|
|||||||
|
|
||||||
$ python package.py
|
$ python package.py
|
||||||
|
|
||||||
|
[dupeguru]: http://www.hardcoded.net/dupeguru/
|
||||||
|
[cross-toolkit]: http://www.hardcoded.net/articles/cross-toolkit-software
|
||||||
[documentation]: http://www.hardcoded.net/dupeguru/help/en/
|
[documentation]: http://www.hardcoded.net/dupeguru/help/en/
|
||||||
[python]: http://www.python.org/
|
[python]: http://www.python.org/
|
||||||
[setuptools]: https://pypi.python.org/pypi/setuptools
|
[setuptools]: https://pypi.python.org/pypi/setuptools
|
||||||
|
|||||||
35
bootstrap.sh
35
bootstrap.sh
@@ -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; }
|
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
|
if [ ! -d "env" ]; then
|
||||||
echo "No virtualenv. Creating one"
|
echo "No virtualenv. Creating one"
|
||||||
command -v curl >/dev/null 2>&1 || { echo >&2 "curl required. Install it and try again. Aborting"; exit 1; }
|
# We need a "system-site-packages" env to have PyQt, but we also need to ensure a local pip
|
||||||
python3 -m venv --system-site-packages env
|
# install. To achieve our latter goal, we start with a normal venv, which we later upgrade to
|
||||||
source env/bin/activate
|
# a system-site-packages once pip is installed.
|
||||||
curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py | python
|
python3 -m venv env
|
||||||
easy_install pip
|
|
||||||
else
|
|
||||||
echo "There's already an env. Activating it"
|
|
||||||
source env/bin/activate
|
source env/bin/activate
|
||||||
|
if python -m ensurepip; then
|
||||||
|
echo "We're under Python 3.4+, no need to try to install pip!"
|
||||||
|
else
|
||||||
|
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
|
fi
|
||||||
|
|
||||||
|
source env/bin/activate
|
||||||
|
|
||||||
echo "Installing pip requirements"
|
echo "Installing pip requirements"
|
||||||
if [ "$(uname)" == "Darwin" ]; then
|
if [ "$(uname)" == "Darwin" ]; then
|
||||||
pip install -r requirements-osx.txt
|
pip install $PIPARGS -r requirements-osx.txt
|
||||||
else
|
else
|
||||||
python3 -c "import PyQt4" >/dev/null 2>&1 || { echo >&2 "PyQt 4.8+ required. Install it and try again. Aborting"; exit 1; }
|
python3 -c "import PyQt5" >/dev/null 2>&1 || { echo >&2 "PyQt 5.1+ required. Install it and try again. Aborting"; exit 1; }
|
||||||
pip install -r requirements.txt
|
pip install $PIPARGS -r requirements.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Bootstrapping complete! You can now configure, build and run dupeGuru with:"
|
echo "Bootstrapping complete! You can now configure, build and run dupeGuru with:"
|
||||||
|
|||||||
30
build.py
30
build.py
@@ -19,7 +19,7 @@ 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, OSXAppStructure,
|
get_module_version, move_all, copy_all, OSXAppStructure,
|
||||||
build_cocoalib_xibless, fix_qt_resource_file, build_cocoa_ext, copy_embeddable_python_dylib,
|
build_cocoalib_xibless, fix_qt_resource_file, build_cocoa_ext, copy_embeddable_python_dylib,
|
||||||
collect_stdlib_dependencies, copy)
|
collect_stdlib_dependencies, copy)
|
||||||
from hscommon import loc
|
from hscommon import loc
|
||||||
@@ -123,7 +123,6 @@ def build_cocoa(edition, dev):
|
|||||||
del sys.path[0]
|
del sys.path[0]
|
||||||
# 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)
|
|
||||||
if not dev:
|
if not dev:
|
||||||
# Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll
|
# Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll
|
||||||
# be deleting all py files in symlinked folders.
|
# be deleting all py files in symlinked folders.
|
||||||
@@ -135,6 +134,7 @@ def build_cocoa(edition, dev):
|
|||||||
print_and_do(cocoa_compile_command(edition))
|
print_and_do(cocoa_compile_command(edition))
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
app.copy_executable('cocoa/build/dupeGuru')
|
app.copy_executable('cocoa/build/dupeGuru')
|
||||||
|
build_help(edition)
|
||||||
print("Copying resources and frameworks")
|
print("Copying resources and frameworks")
|
||||||
image_path = ed('cocoa/{}/dupeguru.icns')
|
image_path = ed('cocoa/{}/dupeguru.icns')
|
||||||
resources = [image_path, 'cocoa/base/dsa_pub.pem', 'build/dg_cocoa.py', 'build/help']
|
resources = [image_path, 'cocoa/base/dsa_pub.pem', 'build/dg_cocoa.py', 'build/help']
|
||||||
@@ -149,8 +149,9 @@ 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("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'))
|
fix_qt_resource_file(op.join('qt', 'base', 'dg_rc.py'))
|
||||||
|
build_help(edition)
|
||||||
print("Creating the run.py file")
|
print("Creating the run.py file")
|
||||||
filereplace(op.join('qt', 'run_template.py'), 'run.py', edition=edition)
|
filereplace(op.join('qt', 'run_template.py'), 'run.py', edition=edition)
|
||||||
|
|
||||||
@@ -168,17 +169,12 @@ def build_help(edition):
|
|||||||
conftmpl = op.join(current_path, 'help', 'conf.tmpl')
|
conftmpl = op.join(current_path, 'help', 'conf.tmpl')
|
||||||
sphinxgen.gen(help_basepath, help_destpath, changelog_path, tixurl, confrepl, conftmpl, changelogtmpl)
|
sphinxgen.gen(help_basepath, help_destpath, changelog_path, tixurl, confrepl, conftmpl, changelogtmpl)
|
||||||
|
|
||||||
def build_base_localizations():
|
|
||||||
loc.compile_all_po('locale')
|
|
||||||
loc.compile_all_po(op.join('hscommon', 'locale'))
|
|
||||||
loc.merge_locale_dir(op.join('hscommon', 'locale'), 'locale')
|
|
||||||
|
|
||||||
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')
|
||||||
|
|
||||||
def build_localizations(ui, edition):
|
def build_localizations(ui, edition):
|
||||||
build_base_localizations()
|
loc.compile_all_po('locale')
|
||||||
if ui == 'cocoa':
|
if ui == 'cocoa':
|
||||||
app = cocoa_app(edition)
|
app = cocoa_app(edition)
|
||||||
loc.build_cocoa_localizations(app, en_stringsfile=op.join('cocoa', 'base', 'en.lproj', 'Localizable.strings'))
|
loc.build_cocoa_localizations(app, en_stringsfile=op.join('cocoa', 'base', 'en.lproj', 'Localizable.strings'))
|
||||||
@@ -191,7 +187,7 @@ def build_localizations(ui, edition):
|
|||||||
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:
|
if ui == 'qt' and not ISLINUX:
|
||||||
print("Copying qt_*.qm files into the 'locale' folder")
|
print("Copying qt_*.qm files into the 'locale' folder")
|
||||||
from PyQt4.QtCore import QLibraryInfo
|
from PyQt5.QtCore import QLibraryInfo
|
||||||
trfolder = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
|
trfolder = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
|
||||||
for lang in loc.get_langs('locale'):
|
for lang in loc.get_langs('locale'):
|
||||||
qmname = 'qt_%s.qm' % lang
|
qmname = 'qt_%s.qm' % lang
|
||||||
@@ -220,8 +216,6 @@ def build_updatepot():
|
|||||||
# We want to merge the generated pot with the old pot in the most preserving way possible.
|
# 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'], merge=(not ISOSX))
|
loc.generate_pot(ui_packages, op.join('locale', 'ui.pot'), ['tr'], merge=(not ISOSX))
|
||||||
print("Building hscommon.pot")
|
|
||||||
loc.generate_pot(['hscommon'], op.join('hscommon', 'locale', 'hscommon.pot'), ['tr'])
|
|
||||||
print("Building qtlib.pot")
|
print("Building qtlib.pot")
|
||||||
loc.generate_pot(['qtlib'], op.join('qtlib', 'locale', 'qtlib.pot'), ['tr'])
|
loc.generate_pot(['qtlib'], op.join('qtlib', 'locale', 'qtlib.pot'), ['tr'])
|
||||||
if ISOSX:
|
if ISOSX:
|
||||||
@@ -236,13 +230,11 @@ def build_updatepot():
|
|||||||
def build_mergepot():
|
def build_mergepot():
|
||||||
print("Updating .po files using .pot files")
|
print("Updating .po files using .pot files")
|
||||||
loc.merge_pots_into_pos('locale')
|
loc.merge_pots_into_pos('locale')
|
||||||
loc.merge_pots_into_pos(op.join('hscommon', 'locale'))
|
|
||||||
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_normpo():
|
def build_normpo():
|
||||||
loc.normalize_all_pos('locale')
|
loc.normalize_all_pos('locale')
|
||||||
loc.normalize_all_pos(op.join('hscommon', 'locale'))
|
|
||||||
loc.normalize_all_pos(op.join('qtlib', 'locale'))
|
loc.normalize_all_pos(op.join('qtlib', 'locale'))
|
||||||
loc.normalize_all_pos(op.join('cocoalib', 'locale'))
|
loc.normalize_all_pos(op.join('cocoalib', 'locale'))
|
||||||
|
|
||||||
@@ -264,7 +256,7 @@ def build_cocoa_bridging_interfaces(edition):
|
|||||||
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, PyBaseApp,
|
OutlineView, PySelectableList, SelectableListView, PyTable, TableView, PyBaseApp,
|
||||||
PyFairware, PyTextField, ProgressWindowView, PyProgressWindow)
|
PyTextField, ProgressWindowView, PyProgressWindow)
|
||||||
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
|
||||||
@@ -276,7 +268,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, PyBaseApp, PyFairware,
|
allclasses = [PyGUIObject, PyColumns, PyOutline, PySelectableList, PyTable, PyBaseApp,
|
||||||
PyDetailsPanel, PyDirectoryOutline, PyPrioritizeDialog, PyPrioritizeList, PyProblemDialog,
|
PyDetailsPanel, PyDirectoryOutline, PyPrioritizeDialog, PyPrioritizeList, PyProblemDialog,
|
||||||
PyIgnoreListDialog, PyDeletionOptions, PyResultTable, PyStatsLabel, PyDupeGuruBase,
|
PyIgnoreListDialog, PyDeletionOptions, PyResultTable, PyStatsLabel, PyDupeGuruBase,
|
||||||
PyTextField, PyProgressWindow, appmod.PyDupeGuru]
|
PyTextField, PyProgressWindow, appmod.PyDupeGuru]
|
||||||
@@ -317,7 +309,6 @@ def build_pe_modules(ui):
|
|||||||
def build_normal(edition, ui, dev, conf):
|
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)
|
|
||||||
print("Building dupeGuru")
|
print("Building dupeGuru")
|
||||||
if edition == 'pe':
|
if edition == 'pe':
|
||||||
build_pe_modules(ui)
|
build_pe_modules(ui)
|
||||||
@@ -335,8 +326,9 @@ def main():
|
|||||||
if dev:
|
if dev:
|
||||||
print("Building in Dev mode")
|
print("Building in Dev mode")
|
||||||
if options.clean:
|
if options.clean:
|
||||||
if op.exists('build'):
|
for path in ['build', op.join('cocoa', 'build'), op.join('cocoa', 'autogen')]:
|
||||||
shutil.rmtree('build')
|
if op.exists(path):
|
||||||
|
shutil.rmtree(path)
|
||||||
if not op.exists('build'):
|
if not op.exists('build'):
|
||||||
os.mkdir('build')
|
os.mkdir('build')
|
||||||
if options.doc:
|
if options.doc:
|
||||||
|
|||||||
@@ -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 "HSFairwareAboutBox.h"
|
#import "HSAboutBox.h"
|
||||||
#import "HSRecentFiles.h"
|
#import "HSRecentFiles.h"
|
||||||
#import "HSProgressWindow.h"
|
#import "HSProgressWindow.h"
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
IgnoreListDialog *_ignoreListDialog;
|
IgnoreListDialog *_ignoreListDialog;
|
||||||
HSProgressWindow *_progressWindow;
|
HSProgressWindow *_progressWindow;
|
||||||
NSWindowController *_preferencesPanel;
|
NSWindowController *_preferencesPanel;
|
||||||
HSFairwareAboutBox *_aboutBox;
|
HSAboutBox *_aboutBox;
|
||||||
HSRecentFiles *_recentResults;
|
HSRecentFiles *_recentResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +73,4 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
/* model --> view */
|
/* model --> view */
|
||||||
- (void)showMessage:(NSString *)msg;
|
- (void)showMessage:(NSString *)msg;
|
||||||
- (void)setupAsRegistered;
|
|
||||||
- (void)showDemoNagWithPrompt:(NSString *)prompt;
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
#import "AppDelegateBase.h"
|
#import "AppDelegateBase.h"
|
||||||
#import "ProgressController.h"
|
#import "ProgressController.h"
|
||||||
#import "HSFairwareReminder.h"
|
|
||||||
#import "HSPyUtil.h"
|
#import "HSPyUtil.h"
|
||||||
#import "Consts.h"
|
#import "Consts.h"
|
||||||
#import "Dialogs.h"
|
#import "Dialogs.h"
|
||||||
@@ -140,7 +139,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[op setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
|
[op setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
|
||||||
[op setTitle:NSLocalizedString(@"Select a results file to load", @"")];
|
[op setTitle:NSLocalizedString(@"Select a results file to load", @"")];
|
||||||
if ([op runModal] == NSOKButton) {
|
if ([op runModal] == NSOKButton) {
|
||||||
NSString *filename = [[op filenames] objectAtIndex:0];
|
NSString *filename = [[[op URLs] objectAtIndex:0] path];
|
||||||
[model loadResultsFrom:filename];
|
[model loadResultsFrom:filename];
|
||||||
[[self recentResults] addFile:filename];
|
[[self recentResults] addFile:filename];
|
||||||
}
|
}
|
||||||
@@ -162,7 +161,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
- (void)showAboutBox
|
- (void)showAboutBox
|
||||||
{
|
{
|
||||||
if (_aboutBox == nil) {
|
if (_aboutBox == nil) {
|
||||||
_aboutBox = [[HSFairwareAboutBox alloc] initWithApp:model];
|
_aboutBox = [[HSAboutBox alloc] initWithApp:model];
|
||||||
}
|
}
|
||||||
[[_aboutBox window] makeKeyAndOrderFront:nil];
|
[[_aboutBox window] makeKeyAndOrderFront:nil];
|
||||||
}
|
}
|
||||||
@@ -199,7 +198,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
/* Delegate */
|
/* Delegate */
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
[model initialRegistrationSetup];
|
|
||||||
[model loadSession];
|
[model loadSession];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,16 +259,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[[self resultWindow] showProblemDialog];
|
[[self resultWindow] showProblemDialog];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setupAsRegistered
|
|
||||||
{
|
|
||||||
// Nothing to do.
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)showDemoNagWithPrompt:(NSString *)prompt
|
|
||||||
{
|
|
||||||
[HSFairwareReminder showDemoNagWithApp:[self model] prompt:prompt];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)selectDestFolderWithPrompt:(NSString *)prompt
|
- (NSString *)selectDestFolderWithPrompt:(NSString *)prompt
|
||||||
{
|
{
|
||||||
NSOpenPanel *op = [NSOpenPanel openPanel];
|
NSOpenPanel *op = [NSOpenPanel openPanel];
|
||||||
@@ -280,7 +268,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[op setAllowsMultipleSelection:NO];
|
[op setAllowsMultipleSelection:NO];
|
||||||
[op setTitle:prompt];
|
[op setTitle:prompt];
|
||||||
if ([op runModal] == NSOKButton) {
|
if ([op runModal] == NSOKButton) {
|
||||||
return [[op filenames] objectAtIndex:0];
|
return [[[op URLs] objectAtIndex:0] path];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil;
|
return nil;
|
||||||
@@ -294,7 +282,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[sp setAllowedFileTypes:[NSArray arrayWithObject:extension]];
|
[sp setAllowedFileTypes:[NSArray arrayWithObject:extension]];
|
||||||
[sp setTitle:prompt];
|
[sp setTitle:prompt];
|
||||||
if ([sp runModal] == NSOKButton) {
|
if ([sp runModal] == NSOKButton) {
|
||||||
return [sp filename];
|
return [[sp URL] path];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil;
|
return nil;
|
||||||
|
|||||||
@@ -64,4 +64,9 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[[self window] close];
|
[[self window] close];
|
||||||
return r == NSOKButton;
|
return r == NSOKButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setHardlinkOptionEnabled:(BOOL)enabled
|
||||||
|
{
|
||||||
|
[linkTypeRadio setEnabled:enabled];
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
@@ -16,4 +16,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
@interface DirectoryOutline : HSOutline {}
|
@interface DirectoryOutline : HSOutline {}
|
||||||
- (id)initWithPyRef:(PyObject *)aPyRef outlineView:(HSOutlineView *)aOutlineView;
|
- (id)initWithPyRef:(PyObject *)aPyRef outlineView:(HSOutlineView *)aOutlineView;
|
||||||
- (PyDirectoryOutline *)model;
|
- (PyDirectoryOutline *)model;
|
||||||
|
|
||||||
|
- (void)selectAll;
|
||||||
@end;
|
@end;
|
||||||
@@ -22,6 +22,12 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
return (PyDirectoryOutline *)model;
|
return (PyDirectoryOutline *)model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Public */
|
||||||
|
- (void)selectAll
|
||||||
|
{
|
||||||
|
[[self model] selectAll];
|
||||||
|
}
|
||||||
|
|
||||||
/* Delegate */
|
/* Delegate */
|
||||||
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
|
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,4 +46,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
- (void)addDirectory:(NSString *)directory;
|
- (void)addDirectory:(NSString *)directory;
|
||||||
- (void)refreshRemoveButtonText;
|
- (void)refreshRemoveButtonText;
|
||||||
|
- (void)markAll;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[op setTitle:NSLocalizedString(@"Select a folder to add to the scanning list", @"")];
|
[op setTitle:NSLocalizedString(@"Select a folder to add to the scanning list", @"")];
|
||||||
[op setDelegate:self];
|
[op setDelegate:self];
|
||||||
if ([op runModal] == NSOKButton) {
|
if ([op runModal] == NSOKButton) {
|
||||||
for (NSString *directory in [op filenames]) {
|
for (NSURL *directoryURL in [op URLs]) {
|
||||||
[self addDirectory:directory];
|
[self addDirectory:[directoryURL path]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,6 +158,14 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)markAll
|
||||||
|
{
|
||||||
|
/* markAll isn't very descriptive of what we do, but since we re-use the Mark All button from
|
||||||
|
the result window, we don't have much choice.
|
||||||
|
*/
|
||||||
|
[outline selectAll];
|
||||||
|
}
|
||||||
|
|
||||||
/* Delegate */
|
/* Delegate */
|
||||||
- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)path
|
- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)path
|
||||||
{
|
{
|
||||||
@@ -171,6 +179,14 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[self addDirectory:path];
|
[self addDirectory:path];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||||
|
{
|
||||||
|
if ([item action] == @selector(markAll)) {
|
||||||
|
[item setTitle:NSLocalizedString(@"Select All", @"")];
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
/* Notifications */
|
/* Notifications */
|
||||||
|
|
||||||
- (void)directorySelectionChanged:(NSNotification *)aNotification
|
- (void)directorySelectionChanged:(NSNotification *)aNotification
|
||||||
|
|||||||
@@ -258,8 +258,8 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[sp setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
|
[sp setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
|
||||||
[sp setTitle:NSLocalizedString(@"Select a file to save your results to", @"")];
|
[sp setTitle:NSLocalizedString(@"Select a file to save your results to", @"")];
|
||||||
if ([sp runModal] == NSOKButton) {
|
if ([sp runModal] == NSOKButton) {
|
||||||
[model saveResultsAs:[sp filename]];
|
[model saveResultsAs:[[sp URL] path]];
|
||||||
[[app recentResults] addFile:[sp filename]];
|
[[app recentResults] addFile:[[sp URL] path]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +344,9 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||||
{
|
{
|
||||||
|
if ([item action] == @selector(markAll)) {
|
||||||
|
[item setTitle:NSLocalizedString(@"Mark All", @"")];
|
||||||
|
}
|
||||||
return ![[ProgressController mainProgressController] isShown];
|
return ![[ProgressController mainProgressController] isShown];
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
"%@ Results" = "%@ Results";
|
"%@ 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.";
|
|
||||||
"About dupeGuru" = "About dupeGuru";
|
"About dupeGuru" = "About dupeGuru";
|
||||||
"Action" = "Action";
|
"Action" = "Action";
|
||||||
"Actions" = "Actions";
|
"Actions" = "Actions";
|
||||||
@@ -127,6 +126,7 @@
|
|||||||
"Select a file to save your results to" = "Select a file to save your results to";
|
"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 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 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\".";
|
"Select folders to scan and press \"Scan\"." = "Select folders to scan and press \"Scan\".";
|
||||||
"Selected" = "Selected";
|
"Selected" = "Selected";
|
||||||
"Send Marked to Trash..." = "Send Marked to Trash...";
|
"Send Marked to Trash..." = "Send Marked to Trash...";
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ dialogHeights = {
|
|||||||
scanTypeNames = {
|
scanTypeNames = {
|
||||||
'se': ["Filename", "Content", "Folders"],
|
'se': ["Filename", "Content", "Folders"],
|
||||||
'me': ["Filename", "Filename - Fields", "Filename - Fields (No Order)", "Tags", "Content", "Audio Content"],
|
'me': ["Filename", "Filename - Fields", "Filename - Fields (No Order)", "Tags", "Content", "Audio Content"],
|
||||||
'pe': ["Contents", "EXIF Timestamp"],
|
'pe': ["Contents", "EXIF Timestamp", "Trigger-happy mode"],
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Window(410, dialogHeights[edition], dialogTitles[edition])
|
result = Window(410, dialogHeights[edition], dialogTitles[edition])
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from objp.util import pyref, dontwrap
|
from objp.util import pyref, dontwrap
|
||||||
from cocoa import install_exception_hook, install_cocoa_logger, patch_threaded_job_performer, proxy
|
from cocoa import install_exception_hook, install_cocoa_logger, patch_threaded_job_performer
|
||||||
from cocoa.inter import PyFairware, FairwareView
|
from cocoa.inter import PyBaseApp, BaseAppView
|
||||||
|
|
||||||
class DupeGuruView(FairwareView):
|
class DupeGuruView(BaseAppView):
|
||||||
def askYesNoWithPrompt_(self, prompt: str) -> bool: pass
|
def askYesNoWithPrompt_(self, prompt: str) -> bool: pass
|
||||||
def showProblemDialog(self): pass
|
def showProblemDialog(self): pass
|
||||||
def selectDestFolderWithPrompt_(self, prompt: str) -> str: pass
|
def selectDestFolderWithPrompt_(self, prompt: str) -> str: pass
|
||||||
def selectDestFileWithPrompt_extension_(self, prompt: str, extension: str) -> str: pass
|
def selectDestFileWithPrompt_extension_(self, prompt: str, extension: str) -> str: pass
|
||||||
|
|
||||||
class PyDupeGuruBase(PyFairware):
|
class PyDupeGuruBase(PyBaseApp):
|
||||||
@dontwrap
|
@dontwrap
|
||||||
def _init(self, modelclass):
|
def _init(self, modelclass):
|
||||||
logging.basicConfig(level=logging.WARNING, format='%(levelname)s %(message)s')
|
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()
|
install_cocoa_logger()
|
||||||
patch_threaded_job_performer()
|
patch_threaded_job_performer()
|
||||||
appdata = proxy.getAppdataPath()
|
self.model = modelclass(self)
|
||||||
self.model = modelclass(self, appdata)
|
|
||||||
|
|
||||||
#---Sub-proxies
|
#---Sub-proxies
|
||||||
def detailsPanel(self) -> pyref:
|
def detailsPanel(self) -> pyref:
|
||||||
@@ -144,14 +143,6 @@ class PyDupeGuruBase(PyFairware):
|
|||||||
self.model.options['copymove_dest_type'] = copymove_dest_type
|
self.model.options['copymove_dest_type'] = copymove_dest_type
|
||||||
|
|
||||||
#--- model --> view
|
#--- model --> view
|
||||||
@dontwrap
|
|
||||||
def open_path(self, path):
|
|
||||||
proxy.openPath_(str(path))
|
|
||||||
|
|
||||||
@dontwrap
|
|
||||||
def reveal_path(self, path):
|
|
||||||
proxy.revealPath_(str(path))
|
|
||||||
|
|
||||||
@dontwrap
|
@dontwrap
|
||||||
def ask_yes_no(self, prompt):
|
def ask_yes_no(self, prompt):
|
||||||
return self.callback.askYesNoWithPrompt_(prompt)
|
return self.callback.askYesNoWithPrompt_(prompt)
|
||||||
|
|||||||
@@ -143,16 +143,13 @@ class Directories(directories.Directories):
|
|||||||
|
|
||||||
|
|
||||||
class DupeGuruME(DupeGuruBase):
|
class DupeGuruME(DupeGuruBase):
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
appdata = op.join(appdata, 'dupeGuru Music Edition')
|
DupeGuruBase.__init__(self, view)
|
||||||
DupeGuruBase.__init__(self, view, appdata)
|
|
||||||
# Use fileclasses set in DupeGuruBase.__init__()
|
# Use fileclasses set in DupeGuruBase.__init__()
|
||||||
self.directories = Directories(fileclasses=self.directories.fileclasses)
|
self.directories = Directories(fileclasses=self.directories.fileclasses)
|
||||||
self.dead_tracks = []
|
self.dead_tracks = []
|
||||||
|
|
||||||
def _do_delete(self, j, *args):
|
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):
|
def op(dupe):
|
||||||
j.add_progress()
|
j.add_progress()
|
||||||
return self._do_delete_dupe(dupe, *args)
|
return self._do_delete_dupe(dupe, *args)
|
||||||
@@ -174,7 +171,7 @@ class DupeGuruME(DupeGuruBase):
|
|||||||
DupeGuruBase._do_delete_dupe(self, dupe, *args)
|
DupeGuruBase._do_delete_dupe(self, dupe, *args)
|
||||||
|
|
||||||
def _create_file(self, path):
|
def _create_file(self, path):
|
||||||
if (self.directories.itunes_libpath is not None) and (path in self.directories.itunes_libpath[:-1]):
|
if (self.directories.itunes_libpath is not None) and (path in self.directories.itunes_libpath.parent()):
|
||||||
if not hasattr(self, 'itunes_songs'):
|
if not hasattr(self, 'itunes_songs'):
|
||||||
songs = get_itunes_songs(self.directories.itunes_libpath)
|
songs = get_itunes_songs(self.directories.itunes_libpath)
|
||||||
self.itunes_songs = {song.path: song for song in songs}
|
self.itunes_songs = {song.path: song for song in songs}
|
||||||
|
|||||||
@@ -6,16 +6,14 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
import os.path as op
|
|
||||||
import plistlib
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import io
|
||||||
|
|
||||||
from appscript import app, its, k, CommandError, ApplicationNotFoundError
|
from appscript import app, its, k, CommandError, ApplicationNotFoundError
|
||||||
|
|
||||||
from hscommon import io
|
|
||||||
from hscommon.util import remove_invalid_xml, first
|
from hscommon.util import remove_invalid_xml, first
|
||||||
from hscommon.path import Path
|
from hscommon.path import Path, pathify
|
||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
from cocoa import proxy
|
from cocoa import proxy
|
||||||
|
|
||||||
@@ -25,6 +23,7 @@ from core.app import JobType
|
|||||||
from core_pe import _block_osx
|
from core_pe import _block_osx
|
||||||
from core_pe.photo import Photo as PhotoBase
|
from core_pe.photo import Photo as PhotoBase
|
||||||
from core_pe.app import DupeGuru as DupeGuruBase
|
from core_pe.app import DupeGuru as DupeGuruBase
|
||||||
|
from core_pe.iphoto_plist import IPhotoPlistParser
|
||||||
from .app import PyDupeGuruBase
|
from .app import PyDupeGuruBase
|
||||||
|
|
||||||
tr = trget('ui')
|
tr = trget('ui')
|
||||||
@@ -48,6 +47,16 @@ class Photo(PhotoBase):
|
|||||||
raise IOError('The picture %s could not be read' % str(self.path))
|
raise IOError('The picture %s could not be read' % str(self.path))
|
||||||
return blocks
|
return blocks
|
||||||
|
|
||||||
|
def _get_exif_timestamp(self):
|
||||||
|
exifdata = proxy.readExifData_(str(self.path))
|
||||||
|
if exifdata:
|
||||||
|
try:
|
||||||
|
return exifdata['{Exif}']['DateTimeOriginal']
|
||||||
|
except KeyError:
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class IPhoto(Photo):
|
class IPhoto(Photo):
|
||||||
def __init__(self, path, db_id):
|
def __init__(self, path, db_id):
|
||||||
@@ -67,11 +76,12 @@ class AperturePhoto(Photo):
|
|||||||
def display_folder_path(self):
|
def display_folder_path(self):
|
||||||
return APERTURE_PATH
|
return APERTURE_PATH
|
||||||
|
|
||||||
def get_iphoto_or_aperture_pictures(plistpath, photo_class):
|
@pathify
|
||||||
|
def get_iphoto_or_aperture_pictures(plistpath: Path, photo_class):
|
||||||
# The structure of iPhoto and Aperture libraries for the base photo list are excactly the same.
|
# The structure of iPhoto and Aperture libraries for the base photo list are excactly the same.
|
||||||
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()
|
||||||
# There was a case where a guy had 0x10 chars in his plist, causing expat errors on loading
|
# There was a case where a guy had 0x10 chars in his plist, causing expat errors on loading
|
||||||
s = remove_invalid_xml(s, replace_with='')
|
s = remove_invalid_xml(s, replace_with='')
|
||||||
# It seems that iPhoto sometimes doesn't properly escape & chars. The regexp below is to find
|
# It seems that iPhoto sometimes doesn't properly escape & chars. The regexp below is to find
|
||||||
@@ -80,7 +90,12 @@ def get_iphoto_or_aperture_pictures(plistpath, photo_class):
|
|||||||
s, count = re.subn(r'&(?![a-zA-Z0-9_-]+|#[0-9]+|#x[0-9a-fA-F]+;)', '', s)
|
s, count = re.subn(r'&(?![a-zA-Z0-9_-]+|#[0-9]+|#x[0-9a-fA-F]+;)', '', s)
|
||||||
if count:
|
if count:
|
||||||
logging.warning("%d invalid XML entities replacement made", 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 = []
|
result = []
|
||||||
for key, photo_data in plist['Master Image List'].items():
|
for key, photo_data in plist['Master Image List'].items():
|
||||||
if photo_data['MediaType'] != 'Image':
|
if photo_data['MediaType'] != 'Image':
|
||||||
@@ -114,12 +129,12 @@ class Directories(directories.Directories):
|
|||||||
directories.Directories.__init__(self, fileclasses=[Photo])
|
directories.Directories.__init__(self, fileclasses=[Photo])
|
||||||
try:
|
try:
|
||||||
self.iphoto_libpath = get_iphoto_database_path()
|
self.iphoto_libpath = get_iphoto_database_path()
|
||||||
self.set_state(self.iphoto_libpath[:-1], directories.DirectoryState.Excluded)
|
self.set_state(self.iphoto_libpath.parent(), directories.DirectoryState.Excluded)
|
||||||
except directories.InvalidPathError:
|
except directories.InvalidPathError:
|
||||||
self.iphoto_libpath = None
|
self.iphoto_libpath = None
|
||||||
try:
|
try:
|
||||||
self.aperture_libpath = get_aperture_database_path()
|
self.aperture_libpath = get_aperture_database_path()
|
||||||
self.set_state(self.aperture_libpath[:-1], directories.DirectoryState.Excluded)
|
self.set_state(self.aperture_libpath.parent(), directories.DirectoryState.Excluded)
|
||||||
except directories.InvalidPathError:
|
except directories.InvalidPathError:
|
||||||
self.aperture_libpath = None
|
self.aperture_libpath = None
|
||||||
|
|
||||||
@@ -171,9 +186,8 @@ class Directories(directories.Directories):
|
|||||||
|
|
||||||
|
|
||||||
class DupeGuruPE(DupeGuruBase):
|
class DupeGuruPE(DupeGuruBase):
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
appdata = op.join(appdata, 'dupeGuru Picture Edition')
|
DupeGuruBase.__init__(self, view)
|
||||||
DupeGuruBase.__init__(self, view, appdata)
|
|
||||||
self.directories = Directories()
|
self.directories = Directories()
|
||||||
|
|
||||||
def _do_delete(self, j, *args):
|
def _do_delete(self, j, *args):
|
||||||
@@ -247,20 +261,20 @@ class DupeGuruPE(DupeGuruBase):
|
|||||||
DupeGuruBase._do_delete_dupe(self, dupe, *args)
|
DupeGuruBase._do_delete_dupe(self, dupe, *args)
|
||||||
|
|
||||||
def _create_file(self, path):
|
def _create_file(self, path):
|
||||||
if (self.directories.iphoto_libpath is not None) and (path in self.directories.iphoto_libpath[:-1]):
|
if (self.directories.iphoto_libpath is not None) and (path in self.directories.iphoto_libpath.parent()):
|
||||||
if not hasattr(self, 'path2iphoto'):
|
if not hasattr(self, 'path2iphoto'):
|
||||||
photos = get_iphoto_pictures(self.directories.iphoto_libpath)
|
photos = get_iphoto_pictures(self.directories.iphoto_libpath)
|
||||||
self.path2iphoto = {p.path: p for p in photos}
|
self.path2iphoto = {p.path: p for p in photos}
|
||||||
return self.path2iphoto.get(path)
|
return self.path2iphoto.get(path)
|
||||||
if (self.directories.aperture_libpath is not None) and (path in self.directories.aperture_libpath[:-1]):
|
if (self.directories.aperture_libpath is not None) and (path in self.directories.aperture_libpath.parent()):
|
||||||
if not hasattr(self, 'path2aperture'):
|
if not hasattr(self, 'path2aperture'):
|
||||||
photos = get_aperture_pictures(self.directories.aperture_libpath)
|
photos = get_aperture_pictures(self.directories.aperture_libpath)
|
||||||
self.path2aperture = {p.path: p for p in photos}
|
self.path2aperture = {p.path: p for p in photos}
|
||||||
return self.path2aperture.get(path)
|
return self.path2aperture.get(path)
|
||||||
return DupeGuruBase._create_file(self, path)
|
return DupeGuruBase._create_file(self, path)
|
||||||
|
|
||||||
def _job_completed(self, jobid, exc):
|
def _job_completed(self, jobid):
|
||||||
DupeGuruBase._job_completed(self, jobid, exc)
|
DupeGuruBase._job_completed(self, jobid)
|
||||||
if jobid == JobType.Load:
|
if jobid == JobType.Load:
|
||||||
if hasattr(self, 'path2iphoto'):
|
if hasattr(self, 'path2iphoto'):
|
||||||
del self.path2iphoto
|
del self.path2iphoto
|
||||||
@@ -317,6 +331,7 @@ class PyDupeGuru(PyDupeGuruBase):
|
|||||||
self.model.scanner.scan_type = [
|
self.model.scanner.scan_type = [
|
||||||
ScanType.FuzzyBlock,
|
ScanType.FuzzyBlock,
|
||||||
ScanType.ExifTimestamp,
|
ScanType.ExifTimestamp,
|
||||||
|
ScanType.TriggerHappyMode,
|
||||||
][scan_type]
|
][scan_type]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import os.path as op
|
import os.path as op
|
||||||
|
|
||||||
from hscommon import io
|
from hscommon.path import Path, pathify
|
||||||
from hscommon.path import Path
|
|
||||||
from cocoa import proxy
|
from cocoa import proxy
|
||||||
|
|
||||||
from core.scanner import ScanType
|
from core.scanner import ScanType
|
||||||
@@ -27,8 +26,9 @@ def is_bundle(str_path):
|
|||||||
|
|
||||||
class Bundle(fs.Folder):
|
class Bundle(fs.Folder):
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_handle(cls, path):
|
@pathify
|
||||||
return not io.islink(path) and io.isdir(path) and is_bundle(str(path))
|
def can_handle(cls, path: Path):
|
||||||
|
return not path.islink() and path.isdir() and is_bundle(str(path))
|
||||||
|
|
||||||
|
|
||||||
class Directories(DirectoriesBase):
|
class Directories(DirectoriesBase):
|
||||||
@@ -68,9 +68,10 @@ class Directories(DirectoriesBase):
|
|||||||
|
|
||||||
|
|
||||||
class DupeGuru(DupeGuruBase):
|
class DupeGuru(DupeGuruBase):
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
appdata = op.join(appdata, 'dupeGuru')
|
# appdata = op.join(appdata, 'dupeGuru')
|
||||||
DupeGuruBase.__init__(self, view, appdata)
|
# print(repr(appdata))
|
||||||
|
DupeGuruBase.__init__(self, view)
|
||||||
self.directories = Directories()
|
self.directories = Directories()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from cocoa.inter import PyGUIObject, GUIObjectView
|
|||||||
class DeletionOptionsView(GUIObjectView):
|
class DeletionOptionsView(GUIObjectView):
|
||||||
def updateMsg_(self, msg: str): pass
|
def updateMsg_(self, msg: str): pass
|
||||||
def show(self) -> bool: pass
|
def show(self) -> bool: pass
|
||||||
|
def setHardlinkOptionEnabled_(self, enabled: bool): pass
|
||||||
|
|
||||||
class PyDeletionOptions(PyGUIObject):
|
class PyDeletionOptions(PyGUIObject):
|
||||||
def setLinkDeleted_(self, link_deleted: bool):
|
def setLinkDeleted_(self, link_deleted: bool):
|
||||||
@@ -31,3 +32,6 @@ class PyDeletionOptions(PyGUIObject):
|
|||||||
def show(self):
|
def show(self):
|
||||||
return self.callback.show()
|
return self.callback.show()
|
||||||
|
|
||||||
|
@dontwrap
|
||||||
|
def set_hardlink_option_enabled(self, enabled):
|
||||||
|
self.callback.setHardlinkOptionEnabled_(enabled)
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ class PyDirectoryOutline(PyOutline):
|
|||||||
def removeSelectedDirectory(self):
|
def removeSelectedDirectory(self):
|
||||||
self.model.remove_selected()
|
self.model.remove_selected()
|
||||||
|
|
||||||
|
def selectAll(self):
|
||||||
|
self.model.select_all()
|
||||||
|
|
||||||
# python --> cocoa
|
# python --> cocoa
|
||||||
@dontwrap
|
@dontwrap
|
||||||
def refresh_states(self):
|
def refresh_states(self):
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def configure(conf):
|
|||||||
os.symlink('../build/Python', 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,3,0))
|
||||||
conf.check_python_headers()
|
conf.check_python_headers()
|
||||||
conf.env.FRAMEWORK_COCOA = 'Cocoa'
|
conf.env.FRAMEWORK_COCOA = 'Cocoa'
|
||||||
conf.env.ARCH_COCOA = ['x86_64']
|
conf.env.ARCH_COCOA = ['x86_64']
|
||||||
@@ -44,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', 'HSFairwareAboutBox', 'HSFairwareReminder', 'Utils',
|
cocoalib_uses = ['NSEventAdditions', 'Dialogs', 'HSAboutBox', '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',
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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,8 +14,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
NSTextField *titleTextField;
|
NSTextField *titleTextField;
|
||||||
NSTextField *versionTextField;
|
NSTextField *versionTextField;
|
||||||
NSTextField *copyrightTextField;
|
NSTextField *copyrightTextField;
|
||||||
NSTextField *registeredTextField;
|
|
||||||
NSButton *registerButton;
|
|
||||||
|
|
||||||
PyBaseApp *app;
|
PyBaseApp *app;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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,13 +11,16 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
@interface HSErrorReportWindow : NSWindowController
|
@interface HSErrorReportWindow : NSWindowController
|
||||||
{
|
{
|
||||||
NSTextView *contentTextView;
|
NSTextView *contentTextView;
|
||||||
|
NSString *githubUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (readwrite, retain) NSTextView *contentTextView;
|
@property (readwrite, retain) NSTextView *contentTextView;
|
||||||
|
@property (readwrite, retain) NSString *githubUrl;
|
||||||
|
|
||||||
+ (void)showErrorReportWithContent:(NSString *)content;
|
// True if the user wants to send the report
|
||||||
- (id)initWithContent:(NSString *)content;
|
+ (void)showErrorReportWithContent:(NSString *)content githubUrl:(NSString *)githubUrl;
|
||||||
|
- (id)initWithContent:(NSString *)content githubUrl:(NSString *)githubUrl;
|
||||||
|
|
||||||
- (void)send;
|
- (void)goToGithub;
|
||||||
- (void)dontSend;
|
- (void)close;
|
||||||
@end
|
@end
|
||||||
@@ -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,
|
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,37 +12,33 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
@implementation HSErrorReportWindow
|
@implementation HSErrorReportWindow
|
||||||
|
|
||||||
@synthesize contentTextView;
|
@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]];
|
[NSApp runModalForWindow:[report window]];
|
||||||
[report release];
|
[report release];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithContent:(NSString *)content
|
- (id)initWithContent:(NSString *)content githubUrl:(NSString *)aGithubUrl
|
||||||
{
|
{
|
||||||
self = [super initWithWindow:nil];
|
self = [super initWithWindow:nil];
|
||||||
[self setWindow:createHSErrorReportWindow_UI(self)];
|
[self setWindow:createHSErrorReportWindow_UI(self)];
|
||||||
[contentTextView alignLeft:nil];
|
[contentTextView alignLeft:nil];
|
||||||
[[[contentTextView textStorage] mutableString] setString:content];
|
[[[contentTextView textStorage] mutableString] setString:content];
|
||||||
|
self.githubUrl = aGithubUrl;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)send
|
- (void)goToGithub
|
||||||
{
|
{
|
||||||
NSString *text = [[contentTextView textStorage] string];
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:self.githubUrl]];
|
||||||
NSString *URL = [NSString stringWithFormat:@"mailto:support@hardcoded.net?SUBJECT=Error Report&BODY=%@",text];
|
}
|
||||||
NSString *encodedURL = [URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:encodedURL]];
|
|
||||||
|
|
||||||
|
- (void)close
|
||||||
|
{
|
||||||
[[self window] orderOut:self];
|
[[self window] orderOut:self];
|
||||||
[NSApp stopModalWithCode:NSOKButton];
|
[NSApp stopModalWithCode:NSOKButton];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dontSend
|
|
||||||
{
|
|
||||||
[[self window] orderOut:self];
|
|
||||||
[NSApp stopModalWithCode:NSCancelButton];
|
|
||||||
}
|
|
||||||
@end
|
@end
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 <Cocoa/Cocoa.h>
|
|
||||||
#import "HSFairwareProtocol.h"
|
|
||||||
|
|
||||||
@interface HSFairware : NSObject <HSFairwareProtocol>
|
|
||||||
{
|
|
||||||
NSInteger appId;
|
|
||||||
NSString *name;
|
|
||||||
BOOL registered;
|
|
||||||
}
|
|
||||||
- (id)initWithAppId:(NSInteger)aAppId name:(NSString *)aName;
|
|
||||||
@end
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 "HSFairware.h"
|
|
||||||
#import <CommonCrypto/CommonDigest.h>
|
|
||||||
#import "HSFairwareReminder.h"
|
|
||||||
#import "Dialogs.h"
|
|
||||||
#import "Utils.h"
|
|
||||||
|
|
||||||
NSString* md5str(NSString *source)
|
|
||||||
{
|
|
||||||
const char *cSource = [source UTF8String];
|
|
||||||
unsigned char result[16];
|
|
||||||
CC_MD5(cSource, strlen(cSource), result);
|
|
||||||
return fmt(@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL validateCode(NSString *code, NSString *email, NSInteger appId)
|
|
||||||
{
|
|
||||||
if ([code length] != 32) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
NSInteger i;
|
|
||||||
for (i=0; i<=100; i++) {
|
|
||||||
NSString *blob = fmt(@"%i%@%iaybabtu", appId, email, i);
|
|
||||||
if ([md5str(blob) isEqualTo:code]) {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString* normalizeString(NSString *str)
|
|
||||||
{
|
|
||||||
return [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] lowercaseString];
|
|
||||||
}
|
|
||||||
|
|
||||||
@implementation HSFairware
|
|
||||||
- (id)initWithAppId:(NSInteger)aAppId name:(NSString *)aName;
|
|
||||||
{
|
|
||||||
self = [super init];
|
|
||||||
appId = aAppId;
|
|
||||||
name = [aName retain];
|
|
||||||
registered = NO;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
[name release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Private */
|
|
||||||
- (void)setRegistrationCode:(NSString *)aCode email:(NSString *)aEmail
|
|
||||||
{
|
|
||||||
registered = validateCode(aCode, aEmail, appId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Public */
|
|
||||||
- (void)initialRegistrationSetup
|
|
||||||
{
|
|
||||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
|
||||||
NSString *code = [ud stringForKey:@"RegistrationCode"];
|
|
||||||
NSString *email = [ud stringForKey:@"RegistrationEmail"];
|
|
||||||
if (code && email) {
|
|
||||||
[self setRegistrationCode:code email:email];
|
|
||||||
}
|
|
||||||
if (!registered) {
|
|
||||||
BOOL fairwareMode = [ud boolForKey:@"FairwareMode"];
|
|
||||||
if (!fairwareMode) {
|
|
||||||
NSString *prompt = @"%@ is fairware, which means \"open source software developed "
|
|
||||||
"with expectation of fair contributions from users\". It's a very interesting "
|
|
||||||
"concept, but one year of fairware has shown that most people just want to know "
|
|
||||||
"how much it costs and not be bothered with theories about intellectual property."
|
|
||||||
"\n\n"
|
|
||||||
"So I won't bother you and will be very straightforward: You can try %@ for "
|
|
||||||
"free but you have to buy it in order to use it without limitations. In demo mode, "
|
|
||||||
"%@ will show this dialog on startup."
|
|
||||||
"\n\n"
|
|
||||||
"So it's as simple as this. If you're curious about fairware, however, I encourage "
|
|
||||||
"you to read more about it by clicking on the \"Fairware?\" button.";
|
|
||||||
[HSFairwareReminder showDemoNagWithApp:self prompt:fmt(prompt, name, name, name)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)appName
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)appLongName
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)isRegistered
|
|
||||||
{
|
|
||||||
return registered;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)setRegisteredCode:(NSString *)code andEmail:(NSString *)email
|
|
||||||
{
|
|
||||||
code = normalizeString(code);
|
|
||||||
email = normalizeString(email);
|
|
||||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
|
||||||
if (([code isEqualTo:@"fairware"]) || ([email isEqualTo:@"fairware"])) {
|
|
||||||
[ud setBool:YES forKey:@"FairwareMode"];
|
|
||||||
[Dialogs showMessage:@"Fairware mode enabled."];
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
[self setRegistrationCode:code email:email];
|
|
||||||
if (registered) {
|
|
||||||
[ud setObject:code forKey:@"RegistrationCode"];
|
|
||||||
[ud setObject:email forKey:@"RegistrationEmail"];
|
|
||||||
[Dialogs showMessage:@"Your code is valid, thanks!"];
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
[Dialogs showMessage:@"Your code is invalid. Make sure that you wrote the good code. Also "
|
|
||||||
"make sure that the e-mail you gave is the same as the e-mail you used for your purchase."];
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)contribute
|
|
||||||
{
|
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://open.hardcoded.net/contribute/"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)buy
|
|
||||||
{
|
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/purchase.htm"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)aboutFairware
|
|
||||||
{
|
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://open.hardcoded.net/about/"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 <Cocoa/Cocoa.h>
|
|
||||||
#import "PyFairware.h"
|
|
||||||
|
|
||||||
@interface HSFairwareAboutBox : NSWindowController
|
|
||||||
{
|
|
||||||
NSTextField *titleTextField;
|
|
||||||
NSTextField *versionTextField;
|
|
||||||
NSTextField *copyrightTextField;
|
|
||||||
NSTextField *registeredTextField;
|
|
||||||
NSButton *registerButton;
|
|
||||||
|
|
||||||
PyFairware *app;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (readwrite, retain) NSTextField *titleTextField;
|
|
||||||
@property (readwrite, retain) NSTextField *versionTextField;
|
|
||||||
@property (readwrite, retain) NSTextField *copyrightTextField;
|
|
||||||
@property (readwrite, retain) NSTextField *registeredTextField;
|
|
||||||
@property (readwrite, retain) NSButton *registerButton;
|
|
||||||
|
|
||||||
- (id)initWithApp:(PyFairware *)app;
|
|
||||||
- (void)updateFields;
|
|
||||||
|
|
||||||
- (void)showRegisterDialog;
|
|
||||||
@end
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 "HSFairwareAboutBox.h"
|
|
||||||
#import "HSFairwareAboutBox_UI.h"
|
|
||||||
#import "HSFairwareReminder.h"
|
|
||||||
|
|
||||||
@implementation HSFairwareAboutBox
|
|
||||||
|
|
||||||
@synthesize titleTextField;
|
|
||||||
@synthesize versionTextField;
|
|
||||||
@synthesize copyrightTextField;
|
|
||||||
@synthesize registeredTextField;
|
|
||||||
@synthesize registerButton;
|
|
||||||
|
|
||||||
- (id)initWithApp:(PyFairware *)aApp
|
|
||||||
{
|
|
||||||
self = [super initWithWindow:nil];
|
|
||||||
[self setWindow:createHSFairwareAboutBox_UI(self)];
|
|
||||||
app = [aApp retain];
|
|
||||||
[self updateFields];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
[app release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)updateFields
|
|
||||||
{
|
|
||||||
[titleTextField setStringValue:[app appLongName]];
|
|
||||||
NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
|
|
||||||
[versionTextField setStringValue:[NSString stringWithFormat:@"Version: %@",version]];
|
|
||||||
NSString *copyright = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSHumanReadableCopyright"];
|
|
||||||
[copyrightTextField setStringValue:copyright];
|
|
||||||
if ([app isRegistered]) {
|
|
||||||
[registeredTextField setHidden:NO];
|
|
||||||
[registerButton setHidden:YES];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
[registeredTextField setHidden:YES];
|
|
||||||
[registerButton setHidden:NO];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)showRegisterDialog
|
|
||||||
{
|
|
||||||
HSFairwareReminder *fr = [[HSFairwareReminder alloc] initWithApp:app];
|
|
||||||
[fr enterCode];
|
|
||||||
[fr release];
|
|
||||||
[self updateFields];
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 <Cocoa/Cocoa.h>
|
|
||||||
|
|
||||||
@protocol HSFairwareProtocol
|
|
||||||
- (void)initialRegistrationSetup;
|
|
||||||
- (NSString *)appName;
|
|
||||||
- (NSString *)appLongName;
|
|
||||||
- (BOOL)isRegistered;
|
|
||||||
- (BOOL)setRegisteredCode:(NSString *)code andEmail:(NSString *)email;
|
|
||||||
- (void)contribute;
|
|
||||||
- (void)buy;
|
|
||||||
- (void)aboutFairware;
|
|
||||||
@end
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 <Cocoa/Cocoa.h>
|
|
||||||
#import "HSFairwareProtocol.h"
|
|
||||||
|
|
||||||
@interface HSFairwareReminder : NSObject
|
|
||||||
{
|
|
||||||
NSWindow *codePanel;
|
|
||||||
NSTextField *codePromptTextField;
|
|
||||||
NSTextField *codeTextField;
|
|
||||||
NSTextField *emailTextField;
|
|
||||||
NSWindow *demoNagPanel;
|
|
||||||
NSTextField *demoPromptTextField;
|
|
||||||
|
|
||||||
id <HSFairwareProtocol> app;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (readwrite, retain) NSWindow *codePanel;
|
|
||||||
@property (readwrite, retain) NSTextField *codePromptTextField;
|
|
||||||
@property (readwrite, retain) NSTextField *codeTextField;
|
|
||||||
@property (readwrite, retain) NSTextField *emailTextField;
|
|
||||||
@property (readwrite, retain) NSWindow *demoNagPanel;
|
|
||||||
@property (readwrite, retain) NSTextField *demoPromptTextField;
|
|
||||||
|
|
||||||
//Show nag only if needed
|
|
||||||
+ (BOOL)showDemoNagWithApp:(id <HSFairwareProtocol>)app prompt:(NSString *)prompt;
|
|
||||||
- (id)initWithApp:(id <HSFairwareProtocol>)app;
|
|
||||||
|
|
||||||
- (void)contribute;
|
|
||||||
- (void)buy;
|
|
||||||
- (void)moreInfo;
|
|
||||||
- (void)cancelCode;
|
|
||||||
- (void)showEnterCode;
|
|
||||||
- (void)submitCode;
|
|
||||||
- (void)closeDialog;
|
|
||||||
|
|
||||||
- (BOOL)showNagPanel:(NSWindow *)panel; //YES: The code has been sucessfully submitted NO: The use wan't to try the demo.
|
|
||||||
- (BOOL)showDemoNagPanelWithPrompt:(NSString *)prompt;
|
|
||||||
- (NSInteger)enterCode; //returns the modal code.
|
|
||||||
@end
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2013 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 "HSFairwareReminder.h"
|
|
||||||
#import "HSDemoReminder_UI.h"
|
|
||||||
#import "HSEnterCode_UI.h"
|
|
||||||
#import "Dialogs.h"
|
|
||||||
#import "Utils.h"
|
|
||||||
|
|
||||||
@implementation HSFairwareReminder
|
|
||||||
|
|
||||||
@synthesize codePanel;
|
|
||||||
@synthesize codePromptTextField;
|
|
||||||
@synthesize codeTextField;
|
|
||||||
@synthesize emailTextField;
|
|
||||||
@synthesize demoNagPanel;
|
|
||||||
@synthesize demoPromptTextField;
|
|
||||||
|
|
||||||
+ (BOOL)showDemoNagWithApp:(id <HSFairwareProtocol>)app prompt:(NSString *)prompt
|
|
||||||
{
|
|
||||||
HSFairwareReminder *fr = [[HSFairwareReminder alloc] initWithApp:app];
|
|
||||||
BOOL r = [fr showDemoNagPanelWithPrompt:prompt];
|
|
||||||
[fr release];
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)initWithApp:(id <HSFairwareProtocol>)aApp
|
|
||||||
{
|
|
||||||
self = [super init];
|
|
||||||
app = aApp;
|
|
||||||
[self setDemoNagPanel:createHSDemoReminder_UI(self)];
|
|
||||||
[self setCodePanel:createHSEnterCode_UI(self)];
|
|
||||||
[codePanel update];
|
|
||||||
[codePromptTextField setStringValue:fmt([codePromptTextField stringValue],[app appName])];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)contribute
|
|
||||||
{
|
|
||||||
[app contribute];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)buy
|
|
||||||
{
|
|
||||||
[app buy];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)moreInfo
|
|
||||||
{
|
|
||||||
[app aboutFairware];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)cancelCode
|
|
||||||
{
|
|
||||||
[codePanel close];
|
|
||||||
[NSApp stopModalWithCode:NSCancelButton];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)showEnterCode
|
|
||||||
{
|
|
||||||
[demoNagPanel close];
|
|
||||||
[NSApp stopModalWithCode:NSOKButton];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)submitCode
|
|
||||||
{
|
|
||||||
NSString *code = [codeTextField stringValue];
|
|
||||||
NSString *email = [emailTextField stringValue];
|
|
||||||
if ([app setRegisteredCode:code andEmail:email]) {
|
|
||||||
[codePanel close];
|
|
||||||
[NSApp stopModalWithCode:NSOKButton];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)closeDialog
|
|
||||||
{
|
|
||||||
[demoNagPanel close];
|
|
||||||
[NSApp stopModalWithCode:NSCancelButton];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)showNagPanel:(NSWindow *)panel;
|
|
||||||
{
|
|
||||||
NSInteger r;
|
|
||||||
while (YES) {
|
|
||||||
r = [NSApp runModalForWindow:panel];
|
|
||||||
if (r == NSOKButton) {
|
|
||||||
r = [self enterCode];
|
|
||||||
if (r == NSOKButton) {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)showDemoNagPanelWithPrompt:(NSString *)prompt
|
|
||||||
{
|
|
||||||
[demoNagPanel setTitle:fmt([demoNagPanel title],[app appName])];
|
|
||||||
[demoPromptTextField setStringValue:prompt];
|
|
||||||
return [self showNagPanel:demoNagPanel];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)enterCode
|
|
||||||
{
|
|
||||||
return [NSApp runModalForWindow:codePanel];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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.
|
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:
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
- (NSString *)bundleIdentifier;
|
- (NSString *)bundleIdentifier;
|
||||||
- (NSString *)appVersion;
|
- (NSString *)appVersion;
|
||||||
- (NSString *)osxVersion;
|
- (NSString *)osxVersion;
|
||||||
|
- (NSString *)bundleInfo:(NSString *)key;
|
||||||
- (void)postNotification:(NSString *)name userInfo:(NSDictionary *)userInfo;
|
- (void)postNotification:(NSString *)name userInfo:(NSDictionary *)userInfo;
|
||||||
- (id)prefValue:(NSString *)prefname;
|
- (id)prefValue:(NSString *)prefname;
|
||||||
- (void)setPrefValue:(NSString *)prefname value:(id)value;
|
- (void)setPrefValue:(NSString *)prefname value:(id)value;
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
- (NSString *)url2path:(NSString *)url;
|
- (NSString *)url2path:(NSString *)url;
|
||||||
- (void)createPool;
|
- (void)createPool;
|
||||||
- (void)destroyPool;
|
- (void)destroyPool;
|
||||||
- (void)reportCrash:(NSString *)crashReport;
|
- (void)reportCrash:(NSString *)crashReport withGithubUrl:(NSString *)githubUrl;
|
||||||
- (void)log:(NSString *)s;
|
- (void)log:(NSString *)s;
|
||||||
|
- (NSDictionary *)readExifData:(NSString *)imagePath;
|
||||||
@end
|
@end
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#import "CocoaProxy.h"
|
#import "CocoaProxy.h"
|
||||||
#import <CoreServices/CoreServices.h>
|
|
||||||
#import "HSErrorReportWindow.h"
|
#import "HSErrorReportWindow.h"
|
||||||
|
|
||||||
@implementation CocoaProxy
|
@implementation CocoaProxy
|
||||||
@@ -92,13 +91,14 @@
|
|||||||
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
|
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)bundleInfo:(NSString *)key
|
||||||
|
{
|
||||||
|
return [[NSBundle mainBundle] objectForInfoDictionaryKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *)osxVersion
|
- (NSString *)osxVersion
|
||||||
{
|
{
|
||||||
SInt32 major, minor, bugfix;
|
return [[NSProcessInfo processInfo] operatingSystemVersionString];
|
||||||
Gestalt(gestaltSystemVersionMajor, &major);
|
|
||||||
Gestalt(gestaltSystemVersionMinor, &minor);
|
|
||||||
Gestalt(gestaltSystemVersionBugFix, &bugfix);
|
|
||||||
return [NSString stringWithFormat:@"%d.%d.%d", major, minor, bugfix];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)postNotification:(NSString *)name userInfo:(NSDictionary *)userInfo
|
- (void)postNotification:(NSString *)name userInfo:(NSDictionary *)userInfo
|
||||||
@@ -143,13 +143,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reportCrash:(NSString *)crashReport
|
- (void)reportCrash:(NSString *)crashReport withGithubUrl:(NSString *)githubUrl
|
||||||
{
|
{
|
||||||
[HSErrorReportWindow showErrorReportWithContent:crashReport];
|
return [HSErrorReportWindow showErrorReportWithContent:crashReport githubUrl:githubUrl];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)log:(NSString *)s
|
- (void)log:(NSString *)s
|
||||||
{
|
{
|
||||||
NSLog(@"%@", s);
|
NSLog(@"%@", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)readExifData:(NSString *)imagePath
|
||||||
|
{
|
||||||
|
NSDictionary *result = nil;
|
||||||
|
NSURL* url = [NSURL fileURLWithPath:imagePath];
|
||||||
|
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, nil);
|
||||||
|
if (source != nil) {
|
||||||
|
CFDictionaryRef metadataRef = CGImageSourceCopyPropertiesAtIndex (source, 0, nil);
|
||||||
|
if (metadataRef != nil) {
|
||||||
|
result = [NSDictionary dictionaryWithDictionary:(NSDictionary *)metadataRef];
|
||||||
|
CFRelease(metadataRef);
|
||||||
|
}
|
||||||
|
CFRelease(source);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Created By: Virgil Dupras
|
# Created By: Virgil Dupras
|
||||||
# Created On: 2007-10-06
|
# 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,
|
# 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
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .CocoaProxy import CocoaProxy
|
from .CocoaProxy import CocoaProxy
|
||||||
@@ -81,30 +80,31 @@ def safe_format_exception(type, value, tb):
|
|||||||
result.extend(traceback.format_exception_only(type, value))
|
result.extend(traceback.format_exception_only(type, value))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def report_crash(type, value, tb):
|
def install_exception_hook(github_url):
|
||||||
app_identifier = proxy.bundleIdentifier()
|
def report_crash(type, value, tb):
|
||||||
app_version = proxy.appVersion()
|
app_identifier = proxy.bundleIdentifier()
|
||||||
osx_version = proxy.osxVersion()
|
app_version = proxy.appVersion()
|
||||||
s = "Application Identifier: {}\n".format(app_identifier)
|
osx_version = proxy.osxVersion()
|
||||||
s += "Application Version: {}\n".format(app_version)
|
s = "Application Identifier: {}\n".format(app_identifier)
|
||||||
s += "Mac OS X Version: {}\n\n".format(osx_version)
|
s += "Application Version: {}\n".format(app_version)
|
||||||
s += ''.join(safe_format_exception(type, value, tb))
|
s += "Mac OS X Version: {}\n\n".format(osx_version)
|
||||||
if app_identifier:
|
s += ''.join(safe_format_exception(type, value, tb))
|
||||||
s += '\nRelevant Console logs:\n\n'
|
if LOG_BUFFER:
|
||||||
p = subprocess.Popen(['grep', app_identifier, '/var/log/system.log'], stdout=subprocess.PIPE)
|
s += '\nRelevant Console logs:\n\n'
|
||||||
try:
|
s += '\n'.join(LOG_BUFFER)
|
||||||
s += str(p.communicate()[0], encoding='utf-8')
|
proxy.reportCrash_withGithubUrl_(s, github_url)
|
||||||
except IndexError:
|
|
||||||
# This can happen if something went wrong with the grep (permission errors?)
|
|
||||||
pass
|
|
||||||
proxy.reportCrash_(s)
|
|
||||||
|
|
||||||
def install_exception_hook():
|
|
||||||
sys.excepthook = report_crash
|
sys.excepthook = report_crash
|
||||||
|
|
||||||
|
# A global log buffer to use for error reports
|
||||||
|
LOG_BUFFER = []
|
||||||
|
|
||||||
class CocoaHandler(logging.Handler):
|
class CocoaHandler(logging.Handler):
|
||||||
def emit(self, record):
|
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():
|
def install_cocoa_logger():
|
||||||
logging.getLogger().addHandler(CocoaHandler())
|
logging.getLogger().addHandler(CocoaHandler())
|
||||||
|
|||||||
@@ -294,45 +294,7 @@ class PyBaseApp(PyGUIObject):
|
|||||||
def set_default(self, key_name, value):
|
def set_default(self, key_name, value):
|
||||||
proxy.setPrefValue_value_(key_name, value)
|
proxy.setPrefValue_value_(key_name, value)
|
||||||
|
|
||||||
@dontwrap
|
|
||||||
def open_url(self, url):
|
|
||||||
proxy.openURL_(url)
|
|
||||||
|
|
||||||
@dontwrap
|
@dontwrap
|
||||||
def show_message(self, msg):
|
def show_message(self, msg):
|
||||||
self.callback.showMessage_(msg)
|
self.callback.showMessage_(msg)
|
||||||
|
|
||||||
class FairwareView(BaseAppView):
|
|
||||||
def setupAsRegistered(self): pass
|
|
||||||
def showDemoNagWithPrompt_(self, prompt: str): pass
|
|
||||||
|
|
||||||
class PyFairware(PyBaseApp):
|
|
||||||
FOLLOW_PROTOCOLS = ['HSFairwareProtocol']
|
|
||||||
|
|
||||||
def initialRegistrationSetup(self):
|
|
||||||
self.model.initial_registration_setup()
|
|
||||||
|
|
||||||
def isRegistered(self) -> bool:
|
|
||||||
return self.model.registered
|
|
||||||
|
|
||||||
def setRegisteredCode_andEmail_(self, code: str, email: str) -> bool:
|
|
||||||
return self.model.set_registration(code, email, False)
|
|
||||||
|
|
||||||
def contribute(self):
|
|
||||||
self.model.contribute()
|
|
||||||
|
|
||||||
def buy(self):
|
|
||||||
self.model.buy()
|
|
||||||
|
|
||||||
def aboutFairware(self):
|
|
||||||
self.model.about_fairware()
|
|
||||||
|
|
||||||
#--- Python --> Cocoa
|
|
||||||
@dontwrap
|
|
||||||
def setup_as_registered(self):
|
|
||||||
self.callback.setupAsRegistered()
|
|
||||||
|
|
||||||
@dontwrap
|
|
||||||
def show_demo_nag(self, prompt):
|
|
||||||
self.callback.showDemoNagWithPrompt_(prompt)
|
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
@@ -101,7 +101,13 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[[self view] setDelegate:nil];
|
[[self view] setDelegate:nil];
|
||||||
[[self view] reloadData];
|
[[self view] reloadData];
|
||||||
[[self view] setDelegate:self];
|
[[self view] setDelegate:self];
|
||||||
[oldRetainer release];
|
/* Item retainer and releasing
|
||||||
|
|
||||||
|
In theory, [oldRetainer release] should work, but in practice, doing so causes occasional
|
||||||
|
crashes during drag & drop, which I guess keep the reference of an item a bit longer than it
|
||||||
|
should. This is why we autorelease here. See #354.
|
||||||
|
*/
|
||||||
|
[oldRetainer autorelease];
|
||||||
[self updateSelection];
|
[self updateSelection];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -1,28 +1,15 @@
|
|||||||
|
|
||||||
"%@ is Fairware" = "%@ is Fairware";
|
|
||||||
"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.";
|
|
||||||
"Buy" = "Buy";
|
|
||||||
"Cancel" = "Cancel";
|
"Cancel" = "Cancel";
|
||||||
"Clear List" = "Clear List";
|
"Clear List" = "Clear List";
|
||||||
"Contribute" = "Contribute";
|
"Close" = "Close";
|
||||||
"Don't Send" = "Don't Send";
|
|
||||||
"Enter Key" = "Enter Key";
|
|
||||||
"Enter your key" = "Enter your key";
|
|
||||||
"Error Report" = "Error Report";
|
"Error Report" = "Error Report";
|
||||||
"Fairware?" = "Fairware?";
|
"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";
|
"No" = "No";
|
||||||
"OK" = "OK";
|
"OK" = "OK";
|
||||||
"Please wait..." = "Please wait...";
|
"Please wait..." = "Please wait...";
|
||||||
"Register" = "Register";
|
"Something went wrong. How about reporting the error?" = "Something went wrong. How about reporting the error?";
|
||||||
"Registration e-mail:" = "Registration e-mail:";
|
|
||||||
"Registration key:" = "Registration key:";
|
|
||||||
"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?";
|
|
||||||
"Status: Working..." = "Status: Working...";
|
"Status: Working..." = "Status: Working...";
|
||||||
"Submit" = "Submit";
|
|
||||||
"This app is registered, thanks!" = "This app is registered, thanks!";
|
|
||||||
"Try" = "Try";
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase." = "Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase.";
|
|
||||||
"Work in progress, please wait." = "Work in progress, please wait.";
|
"Work in progress, please wait." = "Work in progress, please wait.";
|
||||||
"Work in progress..." = "Work in progress...";
|
"Work in progress..." = "Work in progress...";
|
||||||
"Yes" = "Yes";
|
"Yes" = "Yes";
|
||||||
|
|||||||
@@ -1,22 +1,6 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
|
||||||
"Content-Transfer-Encoding: utf-8\n"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
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 "Buy"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
@@ -27,19 +11,7 @@ msgid "Clear List"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Contribute"
|
msgid "Close"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
@@ -47,7 +19,14 @@ msgid "Error Report"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Fairware?"
|
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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
@@ -63,49 +42,13 @@ msgid "Please wait..."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Register"
|
msgid "Something went wrong. How about reporting the error?"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: cs\n"
|
"Language: cs\n"
|
||||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ is Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Buy"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Cancel"
|
msgstr "Cancel"
|
||||||
@@ -31,30 +17,10 @@ msgstr "Cancel"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Contribute"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Don't Send"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Enter Key"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Enter your key"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,54 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Register"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
msgstr "Registration key:"
|
|
||||||
|
|
||||||
#: 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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Submit"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "This app is registered, thanks!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Try"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -126,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ is Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Buy"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Abbrechen"
|
msgstr "Abbrechen"
|
||||||
@@ -31,30 +17,10 @@ msgstr "Abbrechen"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Spenden"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Don't Send"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Registrieren"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Schlüssel eingeben"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,54 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Register"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
msgstr "Registrierungsschlüssel:"
|
|
||||||
|
|
||||||
#: 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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Abschicken"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "This app is registered, thanks!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Try"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Geben Sie den empfangenen Schlüssel und die E-Mail-Adresse als Referenz für "
|
|
||||||
"den Kauf an, wenn Sie für %@ gespendet haben."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -126,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,22 +9,6 @@ msgstr ""
|
|||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ es Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Comprar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Cancelar"
|
msgstr "Cancelar"
|
||||||
@@ -33,30 +17,10 @@ msgstr "Cancelar"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr "Limpiar lista"
|
msgstr "Limpiar lista"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Donar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "No envíar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Introducir clave"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Introduzca su clave"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr "Informe de error"
|
msgstr "Informe de error"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "¿Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "No"
|
msgstr "No"
|
||||||
@@ -69,54 +33,10 @@ msgstr "Aceptar"
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr "Por favor, espere..."
|
msgstr "Por favor, espere..."
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Registrar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr "Correo electrónico de registro:"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
msgstr "Clave de registro"
|
|
||||||
|
|
||||||
#: 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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr "Estado: procesando..."
|
msgstr "Estado: procesando..."
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Enviar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "La aplicación está registrada. ¡Gracias!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Probar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Escriba la clave que recibió al donar a %@, así como el correo electrónico "
|
|
||||||
"que usó en el proceso."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr "En proceso, por favor, espere."
|
msgstr "En proceso, por favor, espere."
|
||||||
@@ -128,3 +48,22 @@ msgstr "En proceso..."
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Sí"
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ est Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Acheter"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Annuler"
|
msgstr "Annuler"
|
||||||
@@ -31,30 +17,10 @@ msgstr "Annuler"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Contribuer"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Ignorer"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Enregistrer"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Entrez votre clé"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,53 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Enregistrer"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
msgstr "Clé d'enregistrement:"
|
|
||||||
|
|
||||||
#: 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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Soumettre"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "L'application est enregistrée, merci!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Essayer"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Entrez la clé que vous avez reçue en contribuant à %@, ainsi que le courriel"
|
|
||||||
" utilisé pour la contribution."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -125,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: hy\n"
|
"Language: hy\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "$appname-ը Fairware է"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Գնել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Չեղարկել"
|
msgstr "Չեղարկել"
|
||||||
@@ -31,30 +17,10 @@ msgstr "Չեղարկել"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Մասնակցել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Չուղարկել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Գրել բանալին"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Շարունակել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware է՞"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,53 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Գրանցել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Հաստատել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "Այս ծրագիրը գրանցված է, շնորհակալություն!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Փորձել"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Մուտքագրեք այն բանալին, որը ստացել եք %@-ին աջակցելիս, քանզի Ձեր էլ. հասցեն "
|
|
||||||
"օգտագործվել է գնման ժամանակ:"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -125,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ è Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Acquista"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Annulla"
|
msgstr "Annulla"
|
||||||
@@ -31,30 +17,10 @@ msgstr "Annulla"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Contribuisci"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Non inviare"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Inserisci Codice"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Inserisci il tuo codice"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,54 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Registra"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
msgstr "Codice di registrazione:"
|
|
||||||
|
|
||||||
#: 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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Invia"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "Questa applicazione è registrata, grazie!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Prova"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Inserisci il codice che hai ricevuto quando hai contribuito a %@, così come "
|
|
||||||
"l'email di riferimento utilizzata per l'acquisto."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -126,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: nl\n"
|
"Language: nl\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
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 "Buy"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -31,30 +17,10 @@ msgstr ""
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,50 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "This app is registered, thanks!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -122,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,22 +9,6 @@ msgstr ""
|
|||||||
"Language: pt_BR\n"
|
"Language: pt_BR\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ é Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Comprar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Cancelar"
|
msgstr "Cancelar"
|
||||||
@@ -33,30 +17,10 @@ msgstr "Cancelar"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr "Limpar Lista"
|
msgstr "Limpar Lista"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Contribuir"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Não Enviar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Entrar Chave"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Entre sua chave"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Não"
|
msgstr "Não"
|
||||||
@@ -69,53 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr "Aguarde..."
|
msgstr "Aguarde..."
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Registrar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
msgstr "Chave de registro:"
|
|
||||||
|
|
||||||
#: 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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Enviar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "O app está registrado, obrigado!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Testar"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Digite a chave que você recebeu ao contribuir com o %@, assim como o e-mail "
|
|
||||||
"usado para a compra."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -127,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Sim"
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: ru\n"
|
"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"
|
"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 "%@ is Fairware"
|
|
||||||
msgstr "%@ является Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Купить"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Отменить"
|
msgstr "Отменить"
|
||||||
@@ -31,30 +17,10 @@ msgstr "Отменить"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Способствовайте"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Не отправлять"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Видите ключ"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Видите Ваш ключ"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,53 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Регистрация"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Передать"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "Это приложение зарегистрировано, спасибо!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Пробовать"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Тип ключа, который вы получили при способствовала %@, а также электронной "
|
|
||||||
"почты используется в качестве ссылки для покупки."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -125,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,22 +9,6 @@ msgstr ""
|
|||||||
"Language: uk\n"
|
"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"
|
"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 "%@ is Fairware"
|
|
||||||
msgstr "%@ це Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Купити"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Відмінити"
|
msgstr "Відмінити"
|
||||||
@@ -33,30 +17,10 @@ msgstr "Відмінити"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "Зробити внесок"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Не надсилати"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "Введіть ключ"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Введіть Ваш ключ"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -69,53 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Зареєструвати"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "Надіслати"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "Програму зареєстровано, дякуємо!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Спробувати"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
"Введіть ключ, який Ви отримали зробивши внесок за %@, а також адресу "
|
|
||||||
"електронної пошти, яка була вказана під час покупки."
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -127,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -10,20 +10,6 @@ msgstr ""
|
|||||||
"Language: vi\n"
|
"Language: vi\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
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 "Buy"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -32,30 +18,10 @@ msgstr ""
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -68,50 +34,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -123,3 +49,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -9,20 +9,6 @@ msgstr ""
|
|||||||
"Language: zh_CN\n"
|
"Language: zh_CN\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "%@ is Fairware"
|
|
||||||
msgstr "%@ is Fairware"
|
|
||||||
|
|
||||||
#: 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 "Buy"
|
|
||||||
msgstr "Buy"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "取消"
|
msgstr "取消"
|
||||||
@@ -31,30 +17,10 @@ msgstr "取消"
|
|||||||
msgid "Clear List"
|
msgid "Clear List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Contribute"
|
|
||||||
msgstr "捐助"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Don't Send"
|
|
||||||
msgstr "Don't Send"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter Key"
|
|
||||||
msgstr "输入密钥"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Enter your key"
|
|
||||||
msgstr "Enter your key"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Error Report"
|
msgid "Error Report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Fairware?"
|
|
||||||
msgstr "Fairware?"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -67,52 +33,10 @@ msgstr ""
|
|||||||
msgid "Please wait..."
|
msgid "Please wait..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Register"
|
|
||||||
msgstr "Register"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration e-mail:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Registration key:"
|
|
||||||
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
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Status: Working..."
|
msgid "Status: Working..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr "提交"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "This app is registered, thanks!"
|
|
||||||
msgstr "This app is registered, thanks!"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid "Try"
|
|
||||||
msgstr "Try"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
|
||||||
msgid ""
|
|
||||||
"Type the key you received when you contributed to %@, as well as the e-mail "
|
|
||||||
"used as a reference for the purchase."
|
|
||||||
msgstr "当您捐助 %@ 后,请输入收到的注册密钥以及电子邮件,这将作为购买凭证。"
|
|
||||||
|
|
||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Work in progress, please wait."
|
msgid "Work in progress, please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -124,3 +48,22 @@ msgstr ""
|
|||||||
#: cocoalib/en.lproj/cocoalib.strings:0
|
#: cocoalib/en.lproj/cocoalib.strings:0
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
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 ""
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
ownerclass = 'HSFairwareReminder'
|
|
||||||
ownerimport = 'HSFairwareReminder.h'
|
|
||||||
|
|
||||||
result = Window(528, 253, "%@ is Fairware")
|
|
||||||
result.canClose = False
|
|
||||||
result.canResize = False
|
|
||||||
result.canMinimize = False
|
|
||||||
demoPromptLabel = Label(result, NLSTR("<demo prompt>"))
|
|
||||||
tryButton = Button(result, "Try")
|
|
||||||
enterKeyButton = Button(result, "Enter Key")
|
|
||||||
buyButton = Button(result, "Buy")
|
|
||||||
fairwareButton = Button(result, "Fairware?")
|
|
||||||
|
|
||||||
owner.demoPromptTextField = demoPromptLabel
|
|
||||||
result.initialFirstResponder = tryButton
|
|
||||||
demoPromptLabel.font = Font(FontFamily.Label, FontSize.SmallControl)
|
|
||||||
tryButton.action = Action(owner, 'closeDialog')
|
|
||||||
tryButton.keyEquivalent = "\\r"
|
|
||||||
enterKeyButton.action = Action(owner, 'showEnterCode')
|
|
||||||
buyButton.action = Action(owner, 'buy')
|
|
||||||
fairwareButton.action = Action(owner, 'moreInfo')
|
|
||||||
|
|
||||||
for button in (tryButton, enterKeyButton, buyButton, fairwareButton):
|
|
||||||
button.width = 113
|
|
||||||
demoPromptLabel.height = 185
|
|
||||||
|
|
||||||
demoPromptLabel.packToCorner(Pack.UpperLeft)
|
|
||||||
demoPromptLabel.fill(Pack.Right)
|
|
||||||
tryButton.packRelativeTo(demoPromptLabel, Pack.Below, Pack.Left)
|
|
||||||
enterKeyButton.packRelativeTo(tryButton, Pack.Right, Pack.Middle)
|
|
||||||
buyButton.packRelativeTo(enterKeyButton, Pack.Right, Pack.Middle)
|
|
||||||
fairwareButton.packRelativeTo(buyButton, Pack.Right, Pack.Middle)
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
ownerclass = 'HSFairwareReminder'
|
|
||||||
ownerimport = 'HSFairwareReminder.h'
|
|
||||||
|
|
||||||
result = Window(450, 185, "Enter Key")
|
|
||||||
result.canClose = False
|
|
||||||
result.canResize = False
|
|
||||||
result.canMinimize = False
|
|
||||||
titleLabel = Label(result, "Enter your key")
|
|
||||||
promptLabel = Label(result, "Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase.")
|
|
||||||
regkeyLabel = Label(result, "Registration key:")
|
|
||||||
regkeyField = TextField(result, "")
|
|
||||||
regemailLabel = Label(result, "Registration e-mail:")
|
|
||||||
regemailField = TextField(result, "")
|
|
||||||
contributeButton = Button(result, "Contribute")
|
|
||||||
cancelButton = Button(result, "Cancel")
|
|
||||||
submitButton = Button(result, "Submit")
|
|
||||||
|
|
||||||
owner.codePromptTextField = promptLabel
|
|
||||||
owner.codeTextField = regkeyField
|
|
||||||
owner.emailTextField = regemailField
|
|
||||||
result.initialFirstResponder = regkeyField
|
|
||||||
|
|
||||||
titleLabel.font = Font(FontFamily.Label, FontSize.RegularControl, traits=[FontTrait.Bold])
|
|
||||||
smallerFont = Font(FontFamily.Label, FontSize.SmallControl)
|
|
||||||
for control in (promptLabel, regkeyLabel, regemailLabel):
|
|
||||||
control.font = smallerFont
|
|
||||||
regkeyField.usesSingleLineMode = regemailField.usesSingleLineMode = True
|
|
||||||
contributeButton.action = Action(owner, 'contribute')
|
|
||||||
cancelButton.action = Action(owner, 'cancelCode')
|
|
||||||
cancelButton.keyEquivalent = "\\E"
|
|
||||||
submitButton.action = Action(owner, 'submitCode')
|
|
||||||
submitButton.keyEquivalent = "\\r"
|
|
||||||
|
|
||||||
for button in (contributeButton, cancelButton, submitButton):
|
|
||||||
button.width = 100
|
|
||||||
regkeyLabel.width = 128
|
|
||||||
regemailLabel.width = 128
|
|
||||||
promptLabel.height = 32
|
|
||||||
|
|
||||||
titleLabel.packToCorner(Pack.UpperLeft)
|
|
||||||
titleLabel.fill(Pack.Right)
|
|
||||||
promptLabel.packRelativeTo(titleLabel, Pack.Below, Pack.Left)
|
|
||||||
promptLabel.fill(Pack.Right)
|
|
||||||
regkeyField.packRelativeTo(promptLabel, Pack.Below, Pack.Right)
|
|
||||||
regkeyLabel.packRelativeTo(regkeyField, Pack.Left, Pack.Middle)
|
|
||||||
regkeyField.fill(Pack.Left)
|
|
||||||
regemailField.packRelativeTo(regkeyField, Pack.Below, Pack.Right)
|
|
||||||
regemailLabel.packRelativeTo(regemailField, Pack.Left, Pack.Middle)
|
|
||||||
regemailField.fill(Pack.Left)
|
|
||||||
contributeButton.packRelativeTo(regemailLabel, Pack.Below, Pack.Left)
|
|
||||||
submitButton.packRelativeTo(regemailField, Pack.Below, Pack.Right)
|
|
||||||
cancelButton.packRelativeTo(submitButton, Pack.Left, Pack.Middle)
|
|
||||||
@@ -1,33 +1,41 @@
|
|||||||
ownerclass = 'HSErrorReportWindow'
|
ownerclass = 'HSErrorReportWindow'
|
||||||
ownerimport = 'HSErrorReportWindow.h'
|
ownerimport = 'HSErrorReportWindow.h'
|
||||||
|
|
||||||
result = Window(524, 390, "Error Report")
|
result = Window(524, 470, "Error Report")
|
||||||
result.canClose = False
|
result.canClose = False
|
||||||
result.canResize = False
|
result.canResize = False
|
||||||
result.canMinimize = 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)
|
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.")
|
label2 = Label(result,
|
||||||
sendButton = Button(result, "Send")
|
"Error reports should be reported as Github issues. You can copy the error traceback "
|
||||||
dontSendButton = Button(result, "Don't Send")
|
"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
|
owner.contentTextView = errorTextView
|
||||||
sendButton.action = Action(owner, 'send')
|
sendButton.action = Action(owner, 'goToGithub')
|
||||||
sendButton.keyEquivalent = "\\r"
|
sendButton.keyEquivalent = "\\r"
|
||||||
dontSendButton.action = Action(owner, 'dontSend')
|
dontSendButton.action = Action(owner, 'close')
|
||||||
dontSendButton.keyEquivalent = "\\E"
|
dontSendButton.keyEquivalent = "\\E"
|
||||||
|
|
||||||
label1.height = 34
|
label1.height = 34
|
||||||
errorTextView.height = 221
|
errorTextView.height = 221
|
||||||
label2.height = 51
|
label2.height = 130
|
||||||
sendButton.width = 100
|
sendButton.width = 100
|
||||||
dontSendButton.width = 100
|
dontSendButton.width = 100
|
||||||
|
|
||||||
label1.packToCorner(Pack.UpperLeft)
|
label1.moveTo(Pack.UpperLeft)
|
||||||
label1.fill(Pack.Right)
|
label1.fill(Pack.Right)
|
||||||
errorTextView.packRelativeTo(label1, Pack.Below, Pack.Left)
|
errorTextView.moveNextTo(label1, Pack.Below, Pack.Left)
|
||||||
errorTextView.fill(Pack.Right)
|
errorTextView.fill(Pack.Right)
|
||||||
label2.packRelativeTo(errorTextView, Pack.Below, Pack.Left)
|
label2.moveNextTo(errorTextView, Pack.Below, Pack.Left)
|
||||||
label2.fill(Pack.Right)
|
label2.fill(Pack.Right)
|
||||||
sendButton.packRelativeTo(label2, Pack.Below, Pack.Right)
|
sendButton.moveNextTo(label2, Pack.Below, Pack.Right)
|
||||||
dontSendButton.packRelativeTo(sendButton, Pack.Left, Pack.Middle)
|
dontSendButton.moveNextTo(sendButton, Pack.Left, Pack.Middle)
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
ownerclass = 'HSFairwareAboutBox'
|
|
||||||
ownerimport = 'HSFairwareAboutBox.h'
|
|
||||||
|
|
||||||
result = Window(259, 217, "")
|
|
||||||
result.canResize = False
|
|
||||||
result.canMinimize = False
|
|
||||||
image = ImageView(result, "NSApplicationIcon")
|
|
||||||
titleLabel = Label(result, NLSTR("AppTitle"))
|
|
||||||
versionLabel = Label(result, NLSTR("AppVersion"))
|
|
||||||
copyrightLabel = Label(result, NLSTR("AppCopyright"))
|
|
||||||
registeredLabel = Label(result, "This app is registered, thanks!")
|
|
||||||
registerButton = Button(result, "Register")
|
|
||||||
|
|
||||||
owner.window = result
|
|
||||||
owner.titleTextField = titleLabel
|
|
||||||
owner.versionTextField = versionLabel
|
|
||||||
owner.copyrightTextField = copyrightLabel
|
|
||||||
owner.registeredTextField = registeredLabel
|
|
||||||
owner.registerButton = registerButton
|
|
||||||
for label in (titleLabel, versionLabel, copyrightLabel, registeredLabel):
|
|
||||||
label.alignment = const.NSCenterTextAlignment
|
|
||||||
titleLabel.font = Font(FontFamily.Label, FontSize.RegularControl, traits=[FontTrait.Bold])
|
|
||||||
for label in (versionLabel, copyrightLabel, registeredLabel):
|
|
||||||
label.font = Font(FontFamily.Label, FontSize.SmallControl)
|
|
||||||
label.height = 14
|
|
||||||
registerButton.bezelStyle = const.NSRoundRectBezelStyle
|
|
||||||
registerButton.action = Action(owner, 'showRegisterDialog')
|
|
||||||
|
|
||||||
image.height = 96
|
|
||||||
image.packToCorner(Pack.UpperLeft)
|
|
||||||
image.y = result.height - 10 - image.height
|
|
||||||
image.fill(Pack.Right)
|
|
||||||
image.setAnchor(Pack.UpperLeft, growX=True)
|
|
||||||
titleLabel.packRelativeTo(image, Pack.Below, Pack.Left)
|
|
||||||
titleLabel.fill(Pack.Right)
|
|
||||||
titleLabel.setAnchor(Pack.UpperLeft, growX=True)
|
|
||||||
versionLabel.packRelativeTo(titleLabel, Pack.Below, Pack.Left)
|
|
||||||
versionLabel.fill(Pack.Right)
|
|
||||||
versionLabel.setAnchor(Pack.UpperLeft, growX=True)
|
|
||||||
copyrightLabel.packRelativeTo(versionLabel, Pack.Below, Pack.Left)
|
|
||||||
copyrightLabel.fill(Pack.Right)
|
|
||||||
copyrightLabel.setAnchor(Pack.UpperLeft, growX=True)
|
|
||||||
registeredLabel.packRelativeTo(copyrightLabel, Pack.Below, Pack.Left)
|
|
||||||
registeredLabel.fill(Pack.Right)
|
|
||||||
registeredLabel.setAnchor(Pack.UpperLeft, growX=True)
|
|
||||||
registerButton.packRelativeTo(copyrightLabel, Pack.Below, Pack.Middle)
|
|
||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
@@ -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,
|
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
|
||||||
|
|||||||
152
core/app.py
152
core/app.py
@@ -16,15 +16,14 @@ import shutil
|
|||||||
|
|
||||||
from send2trash import send2trash
|
from send2trash import send2trash
|
||||||
from jobprogress import job
|
from jobprogress import job
|
||||||
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
|
||||||
from hscommon.conflict import smart_move, smart_copy
|
from hscommon.conflict import smart_move, smart_copy
|
||||||
from hscommon.gui.progress_window import ProgressWindow
|
from hscommon.gui.progress_window import ProgressWindow
|
||||||
from hscommon.util import (delete_if_empty, first, escape, nonone, format_time_decimal, allsame,
|
from hscommon.util import delete_if_empty, first, escape, nonone, format_time_decimal, allsame
|
||||||
rem_file_ext)
|
|
||||||
from hscommon.trans import tr
|
from hscommon.trans import tr
|
||||||
from hscommon.plat import ISWINDOWS
|
from hscommon.plat import ISWINDOWS
|
||||||
|
from hscommon import desktop
|
||||||
|
|
||||||
from . import directories, results, scanner, export, fs
|
from . import directories, results, scanner, export, fs
|
||||||
from .gui.deletion_options import DeletionOptions
|
from .gui.deletion_options import DeletionOptions
|
||||||
@@ -89,20 +88,38 @@ def format_dupe_count(c):
|
|||||||
return str(c) if c else '---'
|
return str(c) if c else '---'
|
||||||
|
|
||||||
def cmp_value(dupe, attrname):
|
def cmp_value(dupe, attrname):
|
||||||
if attrname == 'name':
|
value = getattr(dupe, attrname, '')
|
||||||
value = rem_file_ext(dupe.name)
|
|
||||||
else:
|
|
||||||
value = getattr(dupe, attrname, '')
|
|
||||||
return value.lower() if isinstance(value, str) else value
|
return value.lower() if isinstance(value, str) else value
|
||||||
|
|
||||||
class DupeGuru(RegistrableApplication, Broadcaster):
|
def fix_surrogate_encoding(s, encoding='utf-8'):
|
||||||
|
# ref #210. It's possible to end up with file paths that, while correct unicode strings, are
|
||||||
|
# decoded with the 'surrogateescape' option, which make the string unencodable to utf-8. We fix
|
||||||
|
# these strings here by trying to encode them and, if it fails, we do an encode/decode dance
|
||||||
|
# to remove the problematic characters. This dance is *lossy* but there's not much we can do
|
||||||
|
# because if we end up with this type of string, it means that we don't know the encoding of the
|
||||||
|
# underlying filesystem that brought them. Don't use this for strings you're going to re-use in
|
||||||
|
# fs-related functions because you're going to lose your path (it's going to change). Use this
|
||||||
|
# if you need to export the path somewhere else, outside of the unicode realm.
|
||||||
|
# See http://lucumr.pocoo.org/2013/7/2/the-updated-guide-to-unicode/
|
||||||
|
try:
|
||||||
|
s.encode(encoding)
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
return s.encode(encoding, 'replace').decode(encoding)
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
|
||||||
|
class DupeGuru(Broadcaster):
|
||||||
"""Holds everything together.
|
"""Holds everything together.
|
||||||
|
|
||||||
Instantiated once per running application, it holds a reference to every high-level object
|
Instantiated once per running application, it holds a reference to every high-level object
|
||||||
whose reference needs to be held: :class:`Results`, :class:`Scanner`,
|
whose reference needs to be held: :class:`~core.results.Results`, :class:`Scanner`,
|
||||||
:class:`~core.directories.Directories`, :mod:`core.gui` instances, etc..
|
:class:`~core.directories.Directories`, :mod:`core.gui` instances, etc..
|
||||||
|
|
||||||
It also hosts high level methods and acts as a coordinator for all those elements.
|
It also hosts high level methods and acts as a coordinator for all those elements. This is why
|
||||||
|
some of its methods seem a bit shallow, like for example :meth:`mark_all` and
|
||||||
|
:meth:`remove_duplicates`. These methos are just proxies for a method in :attr:`results`, but
|
||||||
|
they are also followed by a notification call which is very important if we want GUI elements
|
||||||
|
to be correctly notified of a change in the data they're presenting.
|
||||||
|
|
||||||
.. attribute:: directories
|
.. attribute:: directories
|
||||||
|
|
||||||
@@ -123,6 +140,10 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
Instance of :mod:`meta-gui <core.gui>` table listing the results from :attr:`results`
|
Instance of :mod:`meta-gui <core.gui>` table listing the results from :attr:`results`
|
||||||
"""
|
"""
|
||||||
#--- View interface
|
#--- View interface
|
||||||
|
# get_default(key_name)
|
||||||
|
# set_default(key_name, value)
|
||||||
|
# show_message(msg)
|
||||||
|
# open_url(url)
|
||||||
# open_path(path)
|
# open_path(path)
|
||||||
# reveal_path(path)
|
# reveal_path(path)
|
||||||
# ask_yes_no(prompt) --> bool
|
# ask_yes_no(prompt) --> bool
|
||||||
@@ -133,15 +154,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
|
|
||||||
# in fairware prompts, we don't mention the edition, it's too long.
|
# in fairware prompts, we don't mention the edition, it's too long.
|
||||||
PROMPT_NAME = "dupeGuru"
|
PROMPT_NAME = "dupeGuru"
|
||||||
DEMO_LIMITATION = tr("will only be able to delete, move or copy 10 duplicates at once")
|
|
||||||
|
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
if view.get_default(DEBUG_MODE_PREFERENCE):
|
if view.get_default(DEBUG_MODE_PREFERENCE):
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
logging.debug("Debug mode enabled")
|
logging.debug("Debug mode enabled")
|
||||||
RegistrableApplication.__init__(self, view, appid=1)
|
|
||||||
Broadcaster.__init__(self)
|
Broadcaster.__init__(self)
|
||||||
self.appdata = appdata
|
self.view = view
|
||||||
|
self.appdata = desktop.special_folder_path(desktop.SpecialFolder.AppData, appname=self.NAME)
|
||||||
if not op.exists(self.appdata):
|
if not op.exists(self.appdata):
|
||||||
os.makedirs(self.appdata)
|
os.makedirs(self.appdata)
|
||||||
self.directories = directories.Directories()
|
self.directories = directories.Directories()
|
||||||
@@ -179,19 +199,17 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
return self.results.is_marked(dupe)
|
return self.results.is_marked(dupe)
|
||||||
if key == 'percentage':
|
if key == 'percentage':
|
||||||
m = get_group().get_match_of(dupe)
|
m = get_group().get_match_of(dupe)
|
||||||
result = m.percentage
|
return m.percentage
|
||||||
elif key == 'dupe_count':
|
elif key == 'dupe_count':
|
||||||
result = 0
|
return 0
|
||||||
else:
|
else:
|
||||||
result = cmp_value(dupe, key)
|
result = cmp_value(dupe, key)
|
||||||
if delta:
|
if delta:
|
||||||
refval = getattr(get_group().ref, key)
|
refval = cmp_value(get_group().ref, key)
|
||||||
if key in self.result_table.DELTA_COLUMNS:
|
if key in self.result_table.DELTA_COLUMNS:
|
||||||
result -= refval
|
result -= refval
|
||||||
else:
|
else:
|
||||||
# We use directly getattr() because cmp_value() does thing that we don't want to do
|
same = cmp_value(dupe, key) == refval
|
||||||
# when we want to determine whether two values are exactly the same.
|
|
||||||
same = getattr(dupe, key) == refval
|
|
||||||
result = (same, result)
|
result = (same, result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -229,7 +247,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
ref = group.ref
|
ref = group.ref
|
||||||
linkfunc = os.link if use_hardlinks else os.symlink
|
linkfunc = os.link if use_hardlinks else os.symlink
|
||||||
linkfunc(str(ref.path), str_path)
|
linkfunc(str(ref.path), str_path)
|
||||||
self.clean_empty_dirs(dupe.path[:-1])
|
self.clean_empty_dirs(dupe.path.parent())
|
||||||
|
|
||||||
def _create_file(self, path):
|
def _create_file(self, path):
|
||||||
# We add fs.Folder to fileclasses in case the file we're loading contains folder paths.
|
# We add fs.Folder to fileclasses in case the file we're loading contains folder paths.
|
||||||
@@ -254,7 +272,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
for group_id, group in enumerate(self.results.groups):
|
for group_id, group in enumerate(self.results.groups):
|
||||||
for dupe in group:
|
for dupe in group:
|
||||||
data = self.get_display_info(dupe, group)
|
data = self.get_display_info(dupe, group)
|
||||||
row = [data[col.name] for col in columns]
|
row = [fix_surrogate_encoding(data[col.name]) for col in columns]
|
||||||
row.insert(0, group_id)
|
row.insert(0, group_id)
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
return colnames, rows
|
return colnames, rows
|
||||||
@@ -316,13 +334,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self.selected_dupes = dupes
|
self.selected_dupes = dupes
|
||||||
self.notify('dupes_selected')
|
self.notify('dupes_selected')
|
||||||
|
|
||||||
def _check_demo(self):
|
|
||||||
if self.should_apply_demo_limitation and self.results.mark_count > 10:
|
|
||||||
msg = tr("You cannot delete, move or copy more than 10 duplicates at once in demo mode.")
|
|
||||||
self.view.show_message(msg)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
#--- Public
|
#--- Public
|
||||||
def add_directory(self, d):
|
def add_directory(self, d):
|
||||||
"""Adds folder ``d`` to :attr:`directories`.
|
"""Adds folder ``d`` to :attr:`directories`.
|
||||||
@@ -372,7 +383,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
def clean_empty_dirs(self, path):
|
def clean_empty_dirs(self, path):
|
||||||
if self.options['clean_empty_dirs']:
|
if self.options['clean_empty_dirs']:
|
||||||
while delete_if_empty(path, ['.DS_Store']):
|
while delete_if_empty(path, ['.DS_Store']):
|
||||||
path = path[:-1]
|
path = path.parent()
|
||||||
|
|
||||||
def copy_or_move(self, dupe, copy: bool, destination: str, dest_type: DestType):
|
def copy_or_move(self, dupe, copy: bool, destination: str, dest_type: DestType):
|
||||||
source_path = dupe.path
|
source_path = dupe.path
|
||||||
@@ -380,21 +391,21 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
dest_path = Path(destination)
|
dest_path = Path(destination)
|
||||||
if dest_type in {DestType.Relative, DestType.Absolute}:
|
if dest_type in {DestType.Relative, DestType.Absolute}:
|
||||||
# no filename, no windows drive letter
|
# no filename, no windows drive letter
|
||||||
source_base = source_path.remove_drive_letter()[:-1]
|
source_base = source_path.remove_drive_letter().parent()
|
||||||
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 dest_path.exists():
|
if not dest_path.exists():
|
||||||
dest_path.makedirs()
|
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.name]
|
||||||
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)
|
||||||
# Raises an EnvironmentError if there's a problem
|
# Raises an EnvironmentError if there's a problem
|
||||||
if copy:
|
if copy:
|
||||||
smart_copy(source_path, dest_path)
|
smart_copy(source_path, dest_path)
|
||||||
else:
|
else:
|
||||||
smart_move(source_path, dest_path)
|
smart_move(source_path, dest_path)
|
||||||
self.clean_empty_dirs(source_path[:-1])
|
self.clean_empty_dirs(source_path.parent())
|
||||||
|
|
||||||
def copy_or_move_marked(self, copy):
|
def copy_or_move_marked(self, copy):
|
||||||
"""Start an async move (or copy) job on marked duplicates.
|
"""Start an async move (or copy) job on marked duplicates.
|
||||||
@@ -409,8 +420,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
j.start_job(self.results.mark_count)
|
j.start_job(self.results.mark_count)
|
||||||
self.results.perform_on_marked(op, not copy)
|
self.results.perform_on_marked(op, not copy)
|
||||||
|
|
||||||
if not self._check_demo():
|
|
||||||
return
|
|
||||||
if not self.results.mark_count:
|
if not self.results.mark_count:
|
||||||
self.view.show_message(MSG_NO_MARKED_DUPES)
|
self.view.show_message(MSG_NO_MARKED_DUPES)
|
||||||
return
|
return
|
||||||
@@ -425,8 +434,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
def delete_marked(self):
|
def delete_marked(self):
|
||||||
"""Start an async job to send marked duplicates to the trash.
|
"""Start an async job to send marked duplicates to the trash.
|
||||||
"""
|
"""
|
||||||
if not self._check_demo():
|
|
||||||
return
|
|
||||||
if not self.results.mark_count:
|
if not self.results.mark_count:
|
||||||
self.view.show_message(MSG_NO_MARKED_DUPES)
|
self.view.show_message(MSG_NO_MARKED_DUPES)
|
||||||
return
|
return
|
||||||
@@ -438,11 +445,22 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self._start_job(JobType.Delete, self._do_delete, args=args)
|
self._start_job(JobType.Delete, self._do_delete, args=args)
|
||||||
|
|
||||||
def export_to_xhtml(self):
|
def export_to_xhtml(self):
|
||||||
|
"""Export current results to XHTML.
|
||||||
|
|
||||||
|
The configuration of the :attr:`result_table` (columns order and visibility) is used to
|
||||||
|
determine how the data is presented in the export. In other words, the exported table in
|
||||||
|
the resulting XHTML will look just like the results table.
|
||||||
|
"""
|
||||||
colnames, rows = self._get_export_data()
|
colnames, rows = self._get_export_data()
|
||||||
export_path = export.export_to_xhtml(colnames, rows)
|
export_path = export.export_to_xhtml(colnames, rows)
|
||||||
self.view.open_path(export_path)
|
desktop.open_path(export_path)
|
||||||
|
|
||||||
def export_to_csv(self):
|
def export_to_csv(self):
|
||||||
|
"""Export current results to CSV.
|
||||||
|
|
||||||
|
The columns and their order in the resulting CSV file is determined in the same way as in
|
||||||
|
:meth:`export_to_xhtml`.
|
||||||
|
"""
|
||||||
dest_file = self.view.select_dest_file(tr("Select a destination for your exported CSV"), 'csv')
|
dest_file = self.view.select_dest_file(tr("Select a destination for your exported CSV"), 'csv')
|
||||||
if dest_file:
|
if dest_file:
|
||||||
colnames, rows = self._get_export_data()
|
colnames, rows = self._get_export_data()
|
||||||
@@ -490,6 +508,12 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
subprocess.Popen(cmd, shell=True)
|
subprocess.Popen(cmd, shell=True)
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
|
"""Load directory selection and ignore list from files in appdata.
|
||||||
|
|
||||||
|
This method is called during startup so that directory selection and ignore list, which
|
||||||
|
is persistent data, is the same as when the last session was closed (when :meth:`save` was
|
||||||
|
called).
|
||||||
|
"""
|
||||||
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
|
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
|
||||||
self.notify('directories_changed')
|
self.notify('directories_changed')
|
||||||
p = op.join(self.appdata, 'ignore_list.xml')
|
p = op.join(self.appdata, 'ignore_list.xml')
|
||||||
@@ -506,6 +530,12 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self._start_job(JobType.Load, do)
|
self._start_job(JobType.Load, do)
|
||||||
|
|
||||||
def make_selected_reference(self):
|
def make_selected_reference(self):
|
||||||
|
"""Promote :attr:`selected_dupes` to reference position within their respective groups.
|
||||||
|
|
||||||
|
Each selected dupe will become the :attr:`~core.engine.Group.ref` of its group. If there's
|
||||||
|
more than one dupe selected for the same group, only the first (in the order currently shown
|
||||||
|
in :attr:`result_table`) dupe will be promoted.
|
||||||
|
"""
|
||||||
dupes = self.without_ref(self.selected_dupes)
|
dupes = self.without_ref(self.selected_dupes)
|
||||||
changed_groups = set()
|
changed_groups = set()
|
||||||
for dupe in dupes:
|
for dupe in dupes:
|
||||||
@@ -532,18 +562,30 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self.notify('results_changed_but_keep_selection')
|
self.notify('results_changed_but_keep_selection')
|
||||||
|
|
||||||
def mark_all(self):
|
def mark_all(self):
|
||||||
|
"""Set all dupes in the results as marked.
|
||||||
|
"""
|
||||||
self.results.mark_all()
|
self.results.mark_all()
|
||||||
self.notify('marking_changed')
|
self.notify('marking_changed')
|
||||||
|
|
||||||
def mark_none(self):
|
def mark_none(self):
|
||||||
|
"""Set all dupes in the results as unmarked.
|
||||||
|
"""
|
||||||
self.results.mark_none()
|
self.results.mark_none()
|
||||||
self.notify('marking_changed')
|
self.notify('marking_changed')
|
||||||
|
|
||||||
def mark_invert(self):
|
def mark_invert(self):
|
||||||
|
"""Invert the marked state of all dupes in the results.
|
||||||
|
"""
|
||||||
self.results.mark_invert()
|
self.results.mark_invert()
|
||||||
self.notify('marking_changed')
|
self.notify('marking_changed')
|
||||||
|
|
||||||
def mark_dupe(self, dupe, marked):
|
def mark_dupe(self, dupe, marked):
|
||||||
|
"""Change marked status of ``dupe``.
|
||||||
|
|
||||||
|
:param dupe: dupe to mark/unmark
|
||||||
|
:type dupe: :class:`~core.fs.File`
|
||||||
|
:param bool marked: True = mark, False = unmark
|
||||||
|
"""
|
||||||
if marked:
|
if marked:
|
||||||
self.results.mark(dupe)
|
self.results.mark(dupe)
|
||||||
else:
|
else:
|
||||||
@@ -557,13 +599,20 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN):
|
if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN):
|
||||||
return
|
return
|
||||||
for dupe in self.selected_dupes:
|
for dupe in self.selected_dupes:
|
||||||
self.view.open_path(dupe.path)
|
desktop.open_path(dupe.path)
|
||||||
|
|
||||||
def purge_ignore_list(self):
|
def purge_ignore_list(self):
|
||||||
|
"""Remove files that don't exist from :attr:`ignore_list`.
|
||||||
|
"""
|
||||||
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))
|
||||||
self.ignore_list_dialog.refresh()
|
self.ignore_list_dialog.refresh()
|
||||||
|
|
||||||
def remove_directories(self, indexes):
|
def remove_directories(self, indexes):
|
||||||
|
"""Remove root directories at ``indexes`` from :attr:`directories`.
|
||||||
|
|
||||||
|
:param indexes: Indexes of the directories to remove.
|
||||||
|
:type indexes: list of int
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
indexes = sorted(indexes, reverse=True)
|
indexes = sorted(indexes, reverse=True)
|
||||||
for index in indexes:
|
for index in indexes:
|
||||||
@@ -573,6 +622,13 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def remove_duplicates(self, duplicates):
|
def remove_duplicates(self, duplicates):
|
||||||
|
"""Remove ``duplicates`` from :attr:`results`.
|
||||||
|
|
||||||
|
Calls :meth:`~core.results.Results.remove_duplicates` and send appropriate notifications.
|
||||||
|
|
||||||
|
:param duplicates: duplicates to remove.
|
||||||
|
:type duplicates: list of :class:`~core.fs.File`
|
||||||
|
"""
|
||||||
self.results.remove_duplicates(self.without_ref(duplicates))
|
self.results.remove_duplicates(self.without_ref(duplicates))
|
||||||
self.notify('results_changed_but_keep_selection')
|
self.notify('results_changed_but_keep_selection')
|
||||||
|
|
||||||
@@ -601,6 +657,12 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self.remove_duplicates(dupes)
|
self.remove_duplicates(dupes)
|
||||||
|
|
||||||
def rename_selected(self, newname):
|
def rename_selected(self, newname):
|
||||||
|
"""Renames the selected dupes's file to ``newname``.
|
||||||
|
|
||||||
|
If there's more than one selected dupes, the first one is used.
|
||||||
|
|
||||||
|
:param str newname: The filename to rename the dupe's file to.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
d = self.selected_dupes[0]
|
d = self.selected_dupes[0]
|
||||||
d.rename(newname)
|
d.rename(newname)
|
||||||
@@ -610,6 +672,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def reprioritize_groups(self, sort_key):
|
def reprioritize_groups(self, sort_key):
|
||||||
|
"""Sort dupes in each group (in :attr:`results`) according to ``sort_key``.
|
||||||
|
|
||||||
|
Called by the re-prioritize dialog. Calls :meth:`~core.engine.Group.prioritize` and, once
|
||||||
|
the sorting is done, show a message that confirms the action.
|
||||||
|
|
||||||
|
:param sort_key: The key being sent to :meth:`~core.engine.Group.prioritize`
|
||||||
|
:type sort_key: f(dupe)
|
||||||
|
"""
|
||||||
count = 0
|
count = 0
|
||||||
for group in self.results.groups:
|
for group in self.results.groups:
|
||||||
if group.prioritize(key_func=sort_key):
|
if group.prioritize(key_func=sort_key):
|
||||||
@@ -620,7 +690,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
|
|
||||||
def reveal_selected(self):
|
def reveal_selected(self):
|
||||||
if self.selected_dupes:
|
if self.selected_dupes:
|
||||||
self.view.reveal_path(self.selected_dupes[0].path)
|
desktop.reveal_path(self.selected_dupes[0].path)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
if not op.exists(self.appdata):
|
if not op.exists(self.appdata):
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user