mirror of
https://github.com/arsenetar/dupeguru.git
synced 2024-12-06 12:49:02 +00:00
Merge pull request #1089 from arsenetar/as/pre-commit
feat: Add pre-commit, include python 3.11 in tests
This commit is contained in:
commit
1e651a1603
45
.github/workflows/default.yml
vendored
45
.github/workflows/default.yml
vendored
@ -9,43 +9,22 @@ on:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt -r requirements-extra.txt
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
flake8 .
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt -r requirements-extra.txt
|
||||
- name: Check format with black
|
||||
run: |
|
||||
black .
|
||||
python-version: "3.11"
|
||||
- uses: pre-commit/action@v3.0.0
|
||||
test:
|
||||
needs: [lint, format]
|
||||
needs: [pre-commit]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
python-version: [3.7, 3.8, 3.9, "3.10"]
|
||||
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
python-version: 3.7
|
||||
@ -53,17 +32,21 @@ jobs:
|
||||
python-version: 3.8
|
||||
- os: macos-latest
|
||||
python-version: 3.9
|
||||
- os: macos-latest
|
||||
python-version: "3.10"
|
||||
- os: windows-latest
|
||||
python-version: 3.7
|
||||
- os: windows-latest
|
||||
python-version: 3.8
|
||||
- os: windows-latest
|
||||
python-version: 3.9
|
||||
- os: windows-latest
|
||||
python-version: "3.10"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -108,4 +108,4 @@ cocoa/autogen
|
||||
|
||||
*.waf*
|
||||
.lock-waf*
|
||||
/tags
|
||||
/tags
|
||||
|
24
.pre-commit-config.yaml
Normal file
24
.pre-commit-config.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: check-toml
|
||||
- id: end-of-file-fixer
|
||||
exclude: ".*.json"
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
exclude: ^(.tox|env|build|dist|help|qt/dg_rc.py|pkg).*
|
||||
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
||||
rev: v9.3.0
|
||||
hooks:
|
||||
- id: commitlint
|
||||
stages: [commit-msg]
|
||||
additional_dependencies: ["@commitlint/config-conventional"]
|
@ -1 +1 @@
|
||||
sonar.python.version=3.7, 3.8, 3.9, 3.10
|
||||
sonar.python.version=3.7, 3.8, 3.9, 3.10, 3.11
|
||||
|
@ -18,4 +18,3 @@ file_filter = locale/<lang>/LC_MESSAGES/ui.po
|
||||
source_file = locale/ui.pot
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
||||
|
1
LICENSE
1
LICENSE
@ -619,4 +619,3 @@ Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
8
Makefile
8
Makefile
@ -4,7 +4,7 @@ PYRCC5 ?= pyrcc5
|
||||
REQ_MINOR_VERSION = 7
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
# Window compatability via Msys2
|
||||
# Window compatability via Msys2
|
||||
# - venv creates Scripts instead of bin
|
||||
# - compile generates .pyd instead of .so
|
||||
# - venv with --sytem-site-packages has issues on windows as well...
|
||||
@ -12,7 +12,7 @@ PREFIX ?= /usr/local
|
||||
ifeq ($(shell ${PYTHON} -c "import platform; print(platform.system())"), Windows)
|
||||
BIN = Scripts
|
||||
SO = *.pyd
|
||||
VENV_OPTIONS =
|
||||
VENV_OPTIONS =
|
||||
else
|
||||
BIN = bin
|
||||
SO = *.so
|
||||
@ -43,7 +43,7 @@ mofiles = $(patsubst %.po,%.mo,$(pofiles))
|
||||
vpath %.po $(localedirs)
|
||||
vpath %.mo $(localedirs)
|
||||
|
||||
all: | env i18n modules qt/dg_rc.py
|
||||
all: | env i18n modules qt/dg_rc.py
|
||||
@echo "Build complete! You can run dupeGuru with 'make run'"
|
||||
|
||||
run:
|
||||
@ -82,7 +82,7 @@ qt/dg_rc.py: qt/dg.qrc
|
||||
i18n: $(mofiles)
|
||||
|
||||
%.mo: %.po
|
||||
msgfmt -o $@ $<
|
||||
msgfmt -o $@ $<
|
||||
|
||||
modules: | env
|
||||
$(VENV_PYTHON) build.py --modules
|
||||
|
@ -63,7 +63,7 @@ dupeGuru comes with a makefile that can be used to build and run:
|
||||
$ python run.py
|
||||
|
||||
### Generating Debian/Ubuntu package
|
||||
To generate packages the extra requirements in requirements-extra.txt must be installed, the
|
||||
To generate packages the extra requirements in requirements-extra.txt must be installed, the
|
||||
steps are as follows:
|
||||
|
||||
$ cd <dupeGuru directory>
|
||||
|
@ -29,7 +29,7 @@ To build with a different python version 3.7 vs 3.8 or 32 bit vs 64 bit specify
|
||||
It is possible to build dupeGuru with the makefile on windows using a compatable POSIX environment. The following steps have been tested using [msys2][msys2]. Before running make:
|
||||
1. Install msys2 or other POSIX environment
|
||||
2. Install PyQt5 globally via pip
|
||||
3. Use the respective console for msys2 it is `msys2 msys`
|
||||
3. Use the respective console for msys2 it is `msys2 msys`
|
||||
|
||||
Then the following execution of the makefile should work. Pass the correct value for PYTHON to the makefile if not on the path as python3.
|
||||
|
||||
|
17
commitlint.config.js
Normal file
17
commitlint.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
const Configuration = {
|
||||
/*
|
||||
* Resolve and load @commitlint/config-conventional from node_modules.
|
||||
* Referenced packages must be installed
|
||||
*/
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
/*
|
||||
* Any rules defined here will override rules from @commitlint/config-conventional
|
||||
*/
|
||||
rules: {
|
||||
'header-max-length': [2, 'always', 72],
|
||||
'subject-case': [2, 'always', 'sentence-case'],
|
||||
'scope-enum': [2, 'always'],
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = Configuration;
|
@ -97,12 +97,14 @@ class FilesDB:
|
||||
schema_version = 1
|
||||
schema_version_description = "Changed from md5 to xxhash if available."
|
||||
|
||||
create_table_query = "CREATE TABLE IF NOT EXISTS files (path TEXT PRIMARY KEY, size INTEGER, mtime_ns INTEGER, entry_dt DATETIME, digest BLOB, digest_partial BLOB, digest_samples BLOB)"
|
||||
create_table_query = """CREATE TABLE IF NOT EXISTS files (path TEXT PRIMARY KEY, size INTEGER, mtime_ns INTEGER,
|
||||
entry_dt DATETIME, digest BLOB, digest_partial BLOB, digest_samples BLOB)"""
|
||||
drop_table_query = "DROP TABLE IF EXISTS files;"
|
||||
select_query = "SELECT {key} FROM files WHERE path=:path AND size=:size and mtime_ns=:mtime_ns"
|
||||
select_query_ignore_mtime = "SELECT {key} FROM files WHERE path=:path AND size=:size"
|
||||
insert_query = """
|
||||
INSERT INTO files (path, size, mtime_ns, entry_dt, {key}) VALUES (:path, :size, :mtime_ns, datetime('now'), :value)
|
||||
INSERT INTO files (path, size, mtime_ns, entry_dt, {key})
|
||||
VALUES (:path, :size, :mtime_ns, datetime('now'), :value)
|
||||
ON CONFLICT(path) DO UPDATE SET size=:size, mtime_ns=:mtime_ns, entry_dt=datetime('now'), {key}=:value;
|
||||
"""
|
||||
|
||||
@ -153,7 +155,8 @@ class FilesDB:
|
||||
self.cur.execute(self.select_query_ignore_mtime.format(key=key), {"path": str(path), "size": size})
|
||||
else:
|
||||
self.cur.execute(
|
||||
self.select_query.format(key=key), {"path": str(path), "size": size, "mtime_ns": mtime_ns}
|
||||
self.select_query.format(key=key),
|
||||
{"path": str(path), "size": size, "mtime_ns": mtime_ns},
|
||||
)
|
||||
result = self.cur.fetchone()
|
||||
|
||||
|
@ -245,4 +245,4 @@ PyObject *PyInit__block(void) {
|
||||
PyModule_AddObject(m, "DifferentBlockCountError", DifferentBlockCountError);
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
* Created On: 2010-02-04
|
||||
* Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
**/
|
||||
|
||||
@ -22,7 +22,7 @@ pystring2cfstring(PyObject *pystring)
|
||||
UInt8 *s;
|
||||
CFIndex size;
|
||||
CFStringRef result;
|
||||
|
||||
|
||||
if (PyUnicode_Check(pystring)) {
|
||||
encoded = PyUnicode_AsUTF8String(pystring);
|
||||
if (encoded == NULL) {
|
||||
@ -32,7 +32,7 @@ pystring2cfstring(PyObject *pystring)
|
||||
encoded = pystring;
|
||||
Py_INCREF(encoded);
|
||||
}
|
||||
|
||||
|
||||
s = (UInt8*)PyBytes_AS_STRING(encoded);
|
||||
size = PyBytes_GET_SIZE(encoded);
|
||||
result = CFStringCreateWithBytes(NULL, s, size, kCFStringEncodingUTF8, FALSE);
|
||||
@ -50,20 +50,20 @@ static PyObject* block_osx_get_image_size(PyObject *self, PyObject *args)
|
||||
long width, height;
|
||||
PyObject *pwidth, *pheight;
|
||||
PyObject *result;
|
||||
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
if (!PyArg_ParseTuple(args, "O", &path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
image_path = pystring2cfstring(path);
|
||||
if (image_path == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
image_url = CFURLCreateWithFileSystemPath(NULL, image_path, kCFURLPOSIXPathStyle, FALSE);
|
||||
CFRelease(image_path);
|
||||
|
||||
|
||||
source = CGImageSourceCreateWithURL(image_url, NULL);
|
||||
CFRelease(image_url);
|
||||
if (source != NULL) {
|
||||
@ -75,7 +75,7 @@ static PyObject* block_osx_get_image_size(PyObject *self, PyObject *args)
|
||||
}
|
||||
CFRelease(source);
|
||||
}
|
||||
|
||||
|
||||
pwidth = PyLong_FromLong(width);
|
||||
if (pwidth == NULL) {
|
||||
return NULL;
|
||||
@ -91,19 +91,19 @@ static PyObject* block_osx_get_image_size(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
static CGContextRef
|
||||
MyCreateBitmapContext(int width, int height)
|
||||
MyCreateBitmapContext(int width, int height)
|
||||
{
|
||||
CGContextRef context = NULL;
|
||||
CGColorSpaceRef colorSpace;
|
||||
void *bitmapData;
|
||||
int bitmapByteCount;
|
||||
int bitmapBytesPerRow;
|
||||
|
||||
|
||||
bitmapBytesPerRow = (width * 4);
|
||||
bitmapByteCount = (bitmapBytesPerRow * height);
|
||||
|
||||
|
||||
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||
|
||||
|
||||
// calloc() must be used to allocate bitmapData here because the buffer has to be zeroed.
|
||||
// If it's not zeroes, when images with transparency are drawn in the context, this buffer
|
||||
// will stay with undefined pixels, which means that two pictures with the same pixels will
|
||||
@ -113,7 +113,7 @@ MyCreateBitmapContext(int width, int height)
|
||||
fprintf(stderr, "Memory not allocated!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
context = CGBitmapContextCreate(bitmapData, width, height, 8, bitmapBytesPerRow, colorSpace,
|
||||
(CGBitmapInfo)kCGImageAlphaNoneSkipLast);
|
||||
if (context== NULL) {
|
||||
@ -128,7 +128,7 @@ MyCreateBitmapContext(int width, int height)
|
||||
static PyObject* getblock(unsigned char *imageData, int imageWidth, int imageHeight, int boxX, int boxY, int boxW, int boxH)
|
||||
{
|
||||
int i,j, totalR, totalG, totalB;
|
||||
|
||||
|
||||
totalR = totalG = totalB = 0;
|
||||
for(i=boxY; i<boxY+boxH; i++) {
|
||||
for(j=boxX; j<boxX+boxW; j++) {
|
||||
@ -142,7 +142,7 @@ static PyObject* getblock(unsigned char *imageData, int imageWidth, int imageHei
|
||||
totalR /= pixelCount;
|
||||
totalG /= pixelCount;
|
||||
totalB /= pixelCount;
|
||||
|
||||
|
||||
return inttuple(3, totalR, totalG, totalB);
|
||||
}
|
||||
|
||||
@ -155,27 +155,27 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
CGImageRef image;
|
||||
size_t width, height, image_width, image_height;
|
||||
int block_count, block_width, block_height, orientation, i;
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oii", &path, &block_count, &orientation)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (PySequence_Length(path) == 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "empty path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if ((orientation > 8) || (orientation < 0)) {
|
||||
orientation = 0; // simplifies checks later since we can only have values in 0-8
|
||||
}
|
||||
|
||||
|
||||
image_path = pystring2cfstring(path);
|
||||
if (image_path == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
image_url = CFURLCreateWithFileSystemPath(NULL, image_path, kCFURLPOSIXPathStyle, FALSE);
|
||||
CFRelease(image_path);
|
||||
|
||||
|
||||
source = CGImageSourceCreateWithURL(image_url, NULL);
|
||||
CFRelease(image_url);
|
||||
if (source == NULL) {
|
||||
@ -187,8 +187,8 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
CFRelease(source);
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
width = image_width = CGImageGetWidth(image);
|
||||
height = image_height = CGImageGetHeight(image);
|
||||
if (orientation >= 5) {
|
||||
@ -196,9 +196,9 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
width = image_height;
|
||||
height = image_width;
|
||||
}
|
||||
|
||||
|
||||
CGContextRef context = MyCreateBitmapContext(width, height);
|
||||
|
||||
|
||||
if (orientation == 2) {
|
||||
// Flip X
|
||||
CGContextTranslateCTM(context, width, 0);
|
||||
@ -207,7 +207,7 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
else if (orientation == 3) {
|
||||
// Rot 180
|
||||
CGContextTranslateCTM(context, width, height);
|
||||
CGContextRotateCTM(context, RADIANS(180));
|
||||
CGContextRotateCTM(context, RADIANS(180));
|
||||
}
|
||||
else if (orientation == 4) {
|
||||
// Flip Y
|
||||
@ -242,21 +242,21 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
CGContextDrawImage(context, myBoundingBox, image);
|
||||
unsigned char *bitmapData = CGBitmapContextGetData(context);
|
||||
CGContextRelease(context);
|
||||
|
||||
|
||||
CGImageRelease(image);
|
||||
CFRelease(source);
|
||||
if (bitmapData == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
|
||||
block_width = max(width/block_count, 1);
|
||||
block_height = max(height/block_count, 1);
|
||||
|
||||
|
||||
result = PyList_New(block_count * block_count);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for(i=0; i<block_count; i++) {
|
||||
int j, top;
|
||||
top = min(i*block_height, height-block_height);
|
||||
@ -271,8 +271,8 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
PyList_SET_ITEM(result, i*block_count+j, block);
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmapData);
|
||||
|
||||
free(bitmapData);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -302,4 +302,4 @@ PyInit__block_osx(void)
|
||||
return NULL;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
* Created On: 2010-01-30
|
||||
* Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "BSD" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* 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
|
||||
*/
|
||||
|
||||
@ -34,27 +34,27 @@ cache_string_to_colors(PyObject *self, PyObject *args)
|
||||
char *s;
|
||||
Py_ssize_t char_count, color_count, i;
|
||||
PyObject *result;
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#", &s, &char_count)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
color_count = (char_count / 6);
|
||||
result = PyList_New(color_count);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i<color_count; i++) {
|
||||
long r, g, b;
|
||||
Py_ssize_t ci;
|
||||
PyObject *color_tuple;
|
||||
|
||||
|
||||
ci = i * 6;
|
||||
r = (xchar_to_long(s[ci]) << 4) + xchar_to_long(s[ci+1]);
|
||||
g = (xchar_to_long(s[ci+2]) << 4) + xchar_to_long(s[ci+3]);
|
||||
b = (xchar_to_long(s[ci+4]) << 4) + xchar_to_long(s[ci+5]);
|
||||
|
||||
|
||||
color_tuple = inttuple(3, r, g, b);
|
||||
if (color_tuple == NULL) {
|
||||
Py_DECREF(result);
|
||||
@ -62,7 +62,7 @@ cache_string_to_colors(PyObject *self, PyObject *args)
|
||||
}
|
||||
PyList_SET_ITEM(result, i, color_tuple);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -92,4 +92,4 @@ PyInit__cache(void)
|
||||
return NULL;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
* Created On: 2010-02-04
|
||||
* Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "BSD" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* 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
|
||||
*/
|
||||
|
||||
@ -27,10 +27,10 @@ PyObject* inttuple(int n, ...)
|
||||
PyObject *pnumber;
|
||||
PyObject *result;
|
||||
va_list numbers;
|
||||
|
||||
|
||||
va_start(numbers, n);
|
||||
result = PyTuple_New(n);
|
||||
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
pnumber = PyLong_FromLong(va_arg(numbers, long));
|
||||
if (pnumber == NULL) {
|
||||
@ -39,7 +39,7 @@ PyObject* inttuple(int n, ...)
|
||||
}
|
||||
PyTuple_SET_ITEM(result, i, pnumber);
|
||||
}
|
||||
|
||||
|
||||
va_end(numbers);
|
||||
return result;
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
* Created On: 2010-02-04
|
||||
* Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
@ -17,4 +17,4 @@ int min(int a, int b);
|
||||
#endif
|
||||
|
||||
/* Create a tuple out of an array of integers. */
|
||||
PyObject* inttuple(int n, ...);
|
||||
PyObject* inttuple(int n, ...);
|
||||
|
@ -57,7 +57,7 @@
|
||||
|
||||
=== 4.1.1 (2021-03-21)
|
||||
|
||||
* Add Japanese
|
||||
* Add Japanese
|
||||
* Update internationalization and translations to be up to date with current UI.
|
||||
* Minor translation and UI language updates
|
||||
* Fix language selection issues on Windows (#760)
|
||||
@ -419,7 +419,7 @@
|
||||
|
||||
=== 2.6.1 (2009-03-27)
|
||||
* **Fixed** an occasional crash caused by permission issues.
|
||||
* **Fixed** a bug where the "X discarded" notice would show a too large number of discarded
|
||||
* **Fixed** a bug where the "X discarded" notice would show a too large number of discarded
|
||||
duplicates.
|
||||
|
||||
=== 2.6.0 (2008-09-10)
|
||||
@ -453,14 +453,14 @@
|
||||
* **Added** the "Remove empty folders" option.
|
||||
* **Fixed** results load/save issues.
|
||||
* **Fixed** occasional status bar inaccuracies when the results are filtered.
|
||||
|
||||
|
||||
|
||||
=== 2.5.0 (2007-09-15)
|
||||
|
||||
* **Added** post scan filtering.
|
||||
* **Fixed** issues with the rename feature under Windows
|
||||
* **Fixed** some user interface annoyances under Windows
|
||||
|
||||
|
||||
|
||||
=== 2.4.8 (2007-04-14)
|
||||
|
||||
@ -476,7 +476,7 @@
|
||||
|
||||
* **Added** Re-orderable columns. In fact, I re-added the feature which was lost in the C# conversion in 2.4.0 (Windows).
|
||||
* **Changed** the behavior of the scanning engine when setting the hardness to 100. It will now only match files that have their words in the same order.
|
||||
* **Fixed** a bug with all the Delete/Move/Copy actions with certain kinds of files.
|
||||
* **Fixed** a bug with all the Delete/Move/Copy actions with certain kinds of files.
|
||||
|
||||
=== 2.4.5 (2007-01-11)
|
||||
|
||||
@ -514,7 +514,7 @@
|
||||
|
||||
=== 2.3.4 (2006-11-07)
|
||||
|
||||
* **Improved** speed and memory usage of the scanning engine, again. Does it mean there was a lot of improvements to be made? Nah...
|
||||
* **Improved** speed and memory usage of the scanning engine, again. Does it mean there was a lot of improvements to be made? Nah...
|
||||
|
||||
=== 2.3.3 (2006-11-02)
|
||||
|
||||
@ -572,7 +572,7 @@
|
||||
=== 2.2.3 (2006-06-15)
|
||||
|
||||
* **Improved** duplicate scanning speed.
|
||||
* **Added** a warning that a file couldn't be renamed if a file with the same name already exists.
|
||||
* **Added** a warning that a file couldn't be renamed if a file with the same name already exists.
|
||||
|
||||
=== 2.2.2 (2006-06-07)
|
||||
|
||||
@ -616,9 +616,9 @@
|
||||
|
||||
=== 2.0.0 (2006-03-17)
|
||||
|
||||
* Complete rewrite.
|
||||
* Complete rewrite.
|
||||
* Now runs on Mac OS X.
|
||||
|
||||
=== 1.0.0 (2004-09-24)
|
||||
|
||||
* Initial release.
|
||||
* Initial release.
|
||||
|
@ -71,7 +71,7 @@ Häufig gestellte Fragen
|
||||
* Klicken Sie **Markieren --> Alle Markieren**.
|
||||
|
||||
.. only:: edition_me
|
||||
|
||||
|
||||
.. topic:: Ich möchte alle Stücke markieren, die mehr als 3 Sekunden von ihrer Referenz verschieden sind. Was kann ich tun?
|
||||
|
||||
* Aktivieren Sie den :doc:`Nur Duplikate <results>` Modus.
|
||||
@ -83,7 +83,7 @@ Häufig gestellte Fragen
|
||||
* Klicken Sie auf **Entferne Ausgewählte von den Ergebnissen**.
|
||||
|
||||
.. topic:: Ich möchte meine Stücke mit der höchsten Bitrate zur Referenz machen. Was kann ich tun?
|
||||
|
||||
|
||||
* Aktivieren Sie den :doc:`Nur Duplikate <results>` Modus.
|
||||
* Aktivieren Sie den **Deltawerte** Modus.
|
||||
* Klicken Sie auf die "Bitrate" Spalte, um nach Bitrate zu sortieren.
|
||||
@ -92,9 +92,9 @@ Häufig gestellte Fragen
|
||||
* Klicken Sie auf **Mache Ausgewählte zur Referenz**.
|
||||
|
||||
.. topic:: Ich möchte nicht das [live] und [remix] Versionen meiner Stücke als Duplikate erkannt werden. Was kann ich tun?
|
||||
|
||||
|
||||
Ist Ihre Vergleichsschwelle niedrig genug, werden möglicherweise die live und remix Versionen in der Ergebnisliste landen. Das kann nicht verhindert werden, aber es gibt die Möglichkeit die Ergebnisse nach dem Scan zu entfernen, mittels dem Filter. Möchten Sie jedes Stück mit irgendetwas in eckigen Klammern [] im Dateinamen entfernen, so:
|
||||
|
||||
|
||||
* **Windows**: Klicken Sie auf **Aktionen --> Filter anwenden**, geben "[*]" ein und klicken OK.
|
||||
* **Mac OS X**: Geben Sie "[*]" in das "Filter" Feld der Werkzeugleiste ein.
|
||||
* Klicken Sie auf **Markieren --> Alle Markieren**.
|
||||
|
@ -16,7 +16,7 @@ Jeder Ordner kann in einem von 3 Zuständen sein:
|
||||
* **Referenz:** Duplikate in diesem Ordner können **nicht** gelöscht werden. Dateien dieses Ordners können sich nur in der **Referenz** Position einer Duplikatgruppe befinden. Ist mehr als eine Datei des Referenzordners in derselben Duplikatgruppe, so wird nur Eine behalten. Die Anderen werden aus der Gruppe entfernt.
|
||||
* **Ausgeschlossen:** Dateien in diesem Verzeichnis sind nicht im Scan eingeschlossen.
|
||||
|
||||
Der Standardzustand eines Ordners ist natürlich **Normal**. Sie können den **Referenz** Zustand für Ordner nutzen, in denen auf keinen Fall eine Datei gelöscht werden soll.
|
||||
Der Standardzustand eines Ordners ist natürlich **Normal**. Sie können den **Referenz** Zustand für Ordner nutzen, in denen auf keinen Fall eine Datei gelöscht werden soll.
|
||||
|
||||
Wenn sie einen Zustand für ein Verzeichnis setzen, erben alle Unterordner automatisch diesen Zustand, es sei denn Sie ändern den Zustand der Unterordner explizit.
|
||||
|
||||
|
@ -21,7 +21,7 @@ Inhalte:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
quick_start
|
||||
folders
|
||||
preferences
|
||||
|
@ -4,9 +4,9 @@ Einstellungen
|
||||
.. only:: edition_se
|
||||
|
||||
**Scan Typ:** Diese Option bestimmt nach welcher Eigenschaft die Dateien in einem Duplikate Scan verglichen werden. Wenn Sie **Dateiname** auswählen, wird dupeGuru jeden Dateinamen Wort für Wort vergleichen und, abhängig von den unteren Einstellungen, feststellen ob genügend Wörter übereinstimmen, um 2 Dateien als Duplikate zu betrachten. Wenn Sie **Inhalt** wählen, werden nur Dateien mit dem exakt gleichen Inhalt zusammenpassen.
|
||||
|
||||
|
||||
Der **Ordner** Scan Typ ist etwas speziell. Wird er ausgewählt, scannt dupeGuru nach doppelten Ordnern anstelle von Dateien. Um festzustellen ob 2 Ordner identisch sind, werden alle Datein im Ordner gescannt und wenn die Inhalte aller Dateien der Ordner übereinstimmen, werden die Ordner als Duplikate erkannt.
|
||||
|
||||
|
||||
**Filterempfindlichkeit:** Wenn Sie den **Dateiname** Scan Typ wählen, bestimmt diese Option wie ähnlich 2 Dateinamen für dupeGuru sein müssen, um Duplikate zu sein. Ist die Empfindlichkeit zum Beispiel 80, müssen 80% der Worte der 2 Dateinamen übereinstimmen. Um den Übereinstimmungsanteil herauszufinden, zählt dupeGuru zuerst die Gesamtzahl der Wörter **beider** Dateinamen, dann werden die gleichen Wörter gezählt (jedes Wort zählt als 2) und durch die Gesamtzahl der Wörter dividiert. Ist das Resultat größer oder gleich der Filterempfindlichkeit, haben wir ein Duplikat. Zum Beispiel, "a b c d" und "c d e" haben einen Übereinstimmungsanteil von 57 (4 gleiche Wörter, insgesamt 7 Wörter).
|
||||
|
||||
.. only:: edition_me
|
||||
@ -33,7 +33,7 @@ Einstellungen
|
||||
.. only:: edition_pe
|
||||
|
||||
**Scan Typ:** Diese option bestimmt, welcher Scan Typ bei Ihren Bildern angewendet wird. Der **Inhalte** Scan Typ vergleicht den Inhalt der Bilder auf eine ungenaue Art und Weise (so werden nicht nur exakte Duplikate gefunden, sondern auch Ähnliche). Der **EXIF Zeitstempel** Scan Typ schaut auf die EXIF Metadaten der Bilder (wenn vorhanden) und erkennt Bilder die den Selben haben. Er ist viel schneller als der Inhalte Scan. **Warnung:** Veränderte Bilder behalten oft den selben EXIF Zeitstempel, also achten Sie auf Falschpositive bei der Nutzung dieses Scans.
|
||||
|
||||
|
||||
**Filterempfindlichkeit:** *Nur Inhalte Scan.* Je höher diese Einstellung, desto strenger ist der Filter (Mit anderen Worten, desto weniger Ergebnisse erhalten Sie). Die meisten Bilder der selben Qualität stimmen zu 100% überein, selbst wenn das Format anders ist (PNG und JPG zum Beispiel). Wie auch immer, wenn ein PNG mit einem JPG niederiger Qualität übereinstimmen soll, muss die Filterempfindlichkeit kleiner als 100 sein. Die Voreinstellung, 95, ist eine gute Wahl.
|
||||
|
||||
**Bilder unterschiedlicher Abmessung gleich:** Wird diese Box gewählt, dürfen Bilder unterschiedlicher Abmessung in einer Duplikategruppe sein..
|
||||
@ -57,7 +57,7 @@ Auf jeden Fall behandelt dupeGuru Namenskonflikte indem es dem Ziel-Dateinamen e
|
||||
**Eigener Befehl:** Diese Einstellung bestimmt den Befehl der durch "Führe eigenen Befehl aus" ausgeführt wird. Sie können jede externe Anwendung durch diese Aktion aufrufen. Dies ist zum Beispiel hilfreich, wenn Sie eine gute diff-Anwendung installiert haben.
|
||||
|
||||
Das Format des Befehls ist das Selbe wie in einer Befehlszeile, außer das 2 Platzhalter vorhanden sind: **%d** und **%r**. Diese Platzhalter werden durch den Pfad des markierten Duplikates (%d) und dem Pfad der Duplikatereferenz ersetzt (%r).
|
||||
|
||||
|
||||
Wenn der Pfad Ihrer ausführbaren Datei Leerzeichen enthält, so schließen sie ihn bitte mit "" Zeichen ein. Sie sollten auch Platzhalter mit den Zitatzeichen einschließen, denn es ist möglich, das die Pfade der Duplikate und Referenzen ebenfalls Leerzeichen enthalten. Hier ist ein Beispiel eines eigenen Befehls::
|
||||
|
||||
|
||||
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"
|
||||
|
@ -22,4 +22,4 @@ criterion is used and so on and so on. For example, if your arguments are "Size
|
||||
"Filename (Doesn't end with a number)", the reference file that will be picked in a group will be
|
||||
the biggest file, and if two or more files have the same size, the one that has a filename that
|
||||
doesn't end with a number will be used. When all criteria result in ties, the order in which dupes
|
||||
previously were in the group will be used.
|
||||
previously were in the group will be used.
|
||||
|
@ -98,4 +98,4 @@ Aktionen Menü
|
||||
* **Ausgewählte umbenennen:** Fragt nach einem neuen Namen und benennt die ausgewählte Datei um.
|
||||
|
||||
.. todo:: Add Move and iPhoto/iTunes warning
|
||||
.. todo:: Add "Deletion Options" section.
|
||||
.. todo:: Add "Deletion Options" section.
|
||||
|
@ -2,12 +2,12 @@ core.engine
|
||||
===========
|
||||
|
||||
.. automodule:: core.engine
|
||||
|
||||
|
||||
.. autoclass:: Match
|
||||
|
||||
|
||||
.. autoclass:: Group
|
||||
:members:
|
||||
|
||||
|
||||
.. autofunction:: build_word_dict
|
||||
.. autofunction:: compare
|
||||
.. autofunction:: compare_fields
|
||||
@ -16,7 +16,7 @@ core.engine
|
||||
.. autofunction:: get_groups
|
||||
.. autofunction:: merge_similar_words
|
||||
.. autofunction:: reduce_common_words
|
||||
|
||||
|
||||
.. _fields:
|
||||
|
||||
Fields
|
||||
|
@ -6,5 +6,5 @@ core.gui
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
deletion_options
|
||||
|
@ -3,7 +3,7 @@ core
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
app
|
||||
fs
|
||||
engine
|
||||
|
@ -4,9 +4,9 @@ hscommon.gui.base
|
||||
.. automodule:: hscommon.gui.base
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
GUIObject
|
||||
|
||||
|
||||
.. autoclass:: GUIObject
|
||||
:members:
|
||||
:private-members:
|
||||
|
@ -4,22 +4,22 @@ hscommon.gui.column
|
||||
.. automodule:: hscommon.gui.column
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
Columns
|
||||
Column
|
||||
ColumnsView
|
||||
PrefAccessInterface
|
||||
|
||||
|
||||
.. autoclass:: Columns
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: Column
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: ColumnsView
|
||||
:members:
|
||||
|
||||
|
||||
.. autoclass:: PrefAccessInterface
|
||||
:members:
|
||||
|
@ -4,15 +4,14 @@ hscommon.gui.progress_window
|
||||
.. automodule:: hscommon.gui.progress_window
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
ProgressWindow
|
||||
ProgressWindowView
|
||||
|
||||
|
||||
.. autoclass:: ProgressWindow
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: ProgressWindowView
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
@ -4,23 +4,23 @@ hscommon.gui.selectable_list
|
||||
.. automodule:: hscommon.gui.selectable_list
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
Selectable
|
||||
SelectableList
|
||||
GUISelectableList
|
||||
GUISelectableListView
|
||||
|
||||
|
||||
.. autoclass:: Selectable
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: SelectableList
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: GUISelectableList
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: GUISelectableListView
|
||||
:members:
|
||||
|
@ -2,18 +2,18 @@ hscommon.gui.table
|
||||
==================
|
||||
|
||||
.. automodule:: hscommon.gui.table
|
||||
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
Table
|
||||
Row
|
||||
GUITable
|
||||
GUITableView
|
||||
|
||||
|
||||
.. autoclass:: Table
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: Row
|
||||
:members:
|
||||
:private-members:
|
||||
@ -21,6 +21,6 @@ hscommon.gui.table
|
||||
.. autoclass:: GUITable
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: GUITableView
|
||||
:members:
|
||||
|
@ -4,10 +4,10 @@ hscommon.gui.text_field
|
||||
.. automodule:: hscommon.gui.text_field
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
TextField
|
||||
TextFieldView
|
||||
|
||||
|
||||
.. autoclass:: TextField
|
||||
:members:
|
||||
:private-members:
|
||||
|
@ -2,17 +2,16 @@ hscommon.gui.tree
|
||||
=================
|
||||
|
||||
.. automodule:: hscommon.gui.tree
|
||||
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
Tree
|
||||
Node
|
||||
|
||||
|
||||
.. autoclass:: Tree
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. autoclass:: Node
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
@ -4,7 +4,7 @@ hscommon
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
|
||||
|
||||
build
|
||||
conflict
|
||||
desktop
|
||||
@ -13,4 +13,3 @@ hscommon
|
||||
util
|
||||
jobprogress/*
|
||||
gui/*
|
||||
|
||||
|
@ -4,14 +4,13 @@ hscommon.jobprogress.job
|
||||
.. automodule:: hscommon.jobprogress.job
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
Job
|
||||
NullJob
|
||||
|
||||
|
||||
.. autoclass:: Job
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
.. autoclass:: NullJob
|
||||
:members:
|
||||
|
||||
|
@ -4,9 +4,8 @@ hscommon.jobprogress.performer
|
||||
.. automodule:: hscommon.jobprogress.performer
|
||||
|
||||
.. autosummary::
|
||||
|
||||
|
||||
ThreadedJobPerformer
|
||||
|
||||
|
||||
.. autoclass:: ThreadedJobPerformer
|
||||
:members:
|
||||
|
||||
|
@ -69,6 +69,6 @@ API
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
core/index
|
||||
hscommon/index
|
||||
|
@ -31,7 +31,7 @@ How can I report a bug a suggest a feature?
|
||||
-------------------------------------------
|
||||
|
||||
dupeGuru is hosted on `Github`_ and it's also where issues are tracked. The best way to report a
|
||||
bug or suggest a feature is to sign up on Github and `open an issue`_.
|
||||
bug or suggest a feature is to sign up on Github and `open an issue`_.
|
||||
|
||||
The mark box of a file I want to delete is disabled. What must I do?
|
||||
--------------------------------------------------------------------
|
||||
@ -178,4 +178,3 @@ Preferences are stored elsewhere:
|
||||
|
||||
.. _Github: https://github.com/arsenetar/dupeguru
|
||||
.. _open an issue: https://github.com/arsenetar/dupeguru/wiki/issue-labels
|
||||
|
||||
|
@ -24,7 +24,7 @@ Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
contribute
|
||||
quick_start
|
||||
folders
|
||||
|
@ -67,11 +67,11 @@ filename if the filename already exists in the destination.
|
||||
The format of the command is the same as what you would write in the command line, except that there
|
||||
are 2 placeholders: **%d** and **%r**. These placeholders will be replaced by the path of the
|
||||
selected dupe (%d) and the path of the selected dupe's reference file (%r).
|
||||
|
||||
|
||||
If the path to your executable contains space characters, you should enclose it in "" quotes. You
|
||||
should also enclose placeholders in quotes because it's very possible that paths to dupes and refs
|
||||
will contain spaces. Here's an example custom command::
|
||||
|
||||
|
||||
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"
|
||||
|
||||
.. _inode: http://en.wikipedia.org/wiki/Inode
|
||||
|
@ -22,4 +22,4 @@ criterion is used and so on and so on. For example, if your arguments are "Size
|
||||
"Filename (Doesn't end with a number)", the reference file that will be picked in a group will be
|
||||
the biggest file, and if two or more files have the same size, the one that has a filename that
|
||||
doesn't end with a number will be used. When all criteria result in ties, the order in which dupes
|
||||
previously were in the group will be used.
|
||||
previously were in the group will be used.
|
||||
|
@ -180,7 +180,7 @@ any of them.
|
||||
the file's path. If the original file is deleted or moved, the link is broken. A hardlink is a
|
||||
link to the file *itself*. That link is as good as a "real" file. Only when *all* hardlinks to a
|
||||
file are deleted is the file itself deleted.
|
||||
|
||||
|
||||
On OSX and Linux, this feature is supported fully, but under Windows, it's a bit complicated.
|
||||
Windows XP doesn't support it, but Vista and up support it. However, for the feature to work,
|
||||
dupeGuru has to run with administrative privileges.
|
||||
|
@ -51,7 +51,7 @@ Tour groupe de doublons contient au moins un fichier dit "référence" et ce fic
|
||||
effacé. Par contre, ce que vous pouvez faire c'est de le remplacer par un autre fichier du groupe.
|
||||
Pour ce faire, sélectionnez un fichier du groupe et cliquez sur l'action **Transformer sélectionnés
|
||||
en références**.
|
||||
|
||||
|
||||
Notez que si le fichier référence du groupe vient d'un dossier qui a été défini comme dossier
|
||||
référence, ce fichier ne peut pas être déplacé de sa position de référence du groupe.
|
||||
|
||||
@ -71,7 +71,7 @@ doublons. Example: Nous avons 3 fichiers, A, B et C. Nous les comparons en utili
|
||||
de filtre. La comparaison détermine que A est un double de B, A est un double C, mais que B n'est
|
||||
**pas** un double de C. dupeGuru a ici un problème. Il ne peut pas créer un groupe avec A, B et C.
|
||||
Il décide donc de jeter C hors du groupe. C'est de là que vient la notice '(X hors-groupe)'.
|
||||
|
||||
|
||||
Cette notice veut dire que si jamais vous effacez tout les doubles contenus dans vos résultats et
|
||||
que vous faites un nouveau scan, vous pourriez avoir de nouveaux résultats.
|
||||
|
||||
|
@ -3,7 +3,7 @@ Sélection de dossiers
|
||||
|
||||
La première fenêtre qui apparaît lorsque dupeGuru démarre est la fenêtre de sélection de dossiers à scanner. Elle détermine la liste des dossiers qui seront scannés lorsque vous cliquerez sur **Scan**.
|
||||
|
||||
Pour ajouter un dossier, cliquez sur le bouton **+**. Si vous avez ajouté des dossiers dans le passé, un menu vous permettra de rapidement choisir un de ceux ci. Autrement, il vous sera demandé d'indiquer le dossier à ajouter.
|
||||
Pour ajouter un dossier, cliquez sur le bouton **+**. Si vous avez ajouté des dossiers dans le passé, un menu vous permettra de rapidement choisir un de ceux ci. Autrement, il vous sera demandé d'indiquer le dossier à ajouter.
|
||||
|
||||
Vous pouvez aussi utiliser le drag & drop pour ajouter des dossiers à la liste.
|
||||
|
||||
@ -26,14 +26,14 @@ Le type d'un dossier s'applique à ses sous-dossiers, excepté si un sous-dossie
|
||||
|
||||
Bibliothèques iPhoto et Aperture
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
dupeGuru PE supporte iPhoto et Aperture, ce qui veut dire qu'il sait comment lire le contenu de
|
||||
ces bibliothèques et comment communiquer avec ces applications pour correctement supprimer des
|
||||
photos de celles-ci. Pour utiliser cette fonctionnalité, vous devez ajouter iPhoto et/ou
|
||||
Aperture avec les boutons spéciaux "Ajouter librairie iPhoto" et "Ajouter librairie Aperture",
|
||||
qui apparaissent quand on clique sur le petit "+". Les dossiers ajoutés seront alors
|
||||
correctement interprétés par dupeGuru.
|
||||
|
||||
|
||||
Quand une photo est supprimée d'iPhoto, elle est envoyée dans la corbeille d'iPhoto.
|
||||
|
||||
Quand une photo est supprimée d'Aperture, il n'est malheureusement pas possible de l'envoyer
|
||||
@ -45,13 +45,13 @@ Le type d'un dossier s'applique à ses sous-dossiers, excepté si un sous-dossie
|
||||
|
||||
Bibliothèques iTunes
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
dupeGuru ME supporte iTunes, ce qui veut dire qu'il sait comment lire le contenu de sa
|
||||
bibliothèque et comment communiquer avec iTunes pour correctement supprimer des chansons de sa
|
||||
bibliothèque. Pour utiliser cette fonctionnalité, vous devez ajouter iTunes avec le bouton
|
||||
spécial "Ajouter librairie iTunes", qui apparait quand on clique sur le petit "+". Le dossier
|
||||
ajouté sera alors correctement interprété par dupeGuru.
|
||||
|
||||
|
||||
Quand une chanson est supprimée d'iTunes, elle est envoyée à la corebeille du système, comme un
|
||||
fichier normal. La différence ici, c'est qu'après la suppression, iTunes est correctement mis au
|
||||
fait de cette suppression et retire sa référence à cette chanson de sa bibliothèque.
|
||||
|
@ -21,7 +21,7 @@ Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
quick_start
|
||||
folders
|
||||
preferences
|
||||
|
@ -4,9 +4,9 @@ Préférences
|
||||
.. only:: edition_se
|
||||
|
||||
**Type de scan:** Cette option détermine quels aspects du fichier doit être comparé. Un scan par **Nom de fichier** compare les noms de fichiers mot-à-mot et, dépendant des autres préférences ci-dessous, déterminera si les noms se ressemblent assez pour être considérés comme doublons. Un scan par **Contenu** trouvera les doublons qui ont exactement le même contenu.
|
||||
|
||||
|
||||
Le scan **Dossiers** est spécial. Si vous le sélectionnez, dupeGuru cherchera des doublons de *dossiers* plutôt que des doublons de fichiers. Pour déterminer si deux dossiers sont des doublons, dupeGuru regarde le contenu de tous les fichiers dans les dossiers, et si **tous** sont les mêmes, les dossiers sont considérés comme des doublons.
|
||||
|
||||
|
||||
**Seuil du filtre:** Pour les scan de type **Nom de fichier**, cette option détermine le degré de similtude nécessaire afin de considérer deux noms comme doublons. Avec un seuil de 80, 80% des mots doivent être égaux. Pour déterminer ce pourcentage, dupeGuru compte le nombre de mots total des deux noms, puis compte le nombre de mots égaux, puis fait la division des deux. Un résultat égalisant ou dépassant le seuil sera considéré comme un doublon. Exemple: "a b c d" et "c d e" ont un pourcentage de 57 (4 mots égaux, 7 au total).
|
||||
|
||||
.. only:: edition_me
|
||||
@ -33,7 +33,7 @@ Préférences
|
||||
.. only:: edition_pe
|
||||
|
||||
**Type de scan:** Détermine le type de scan qui sera fait sur vos images. Le type **Contenu** compare le contenu des images de façon "fuzzy", rendant possible de trouver non seulement les doublons exactes, mais aussi les similaires. Le type **EXIF Timestamp** compare les métadonnées EXIF des images (si existantes) et détermine si le "timestamp" (moment de prise de la photo) est pareille. C'est beaucoup plus rapide que le scan par Contenu. **Attention:** Les photos modifiées gardent souvent le même timestamp, donc faites attention aux faux doublons si vous utilisez cette méthode.
|
||||
|
||||
|
||||
**Seuil du filtre:** *Scan par Contenu seulement.* Plus il est élevé, plus les images doivent être similaires pour être considérées comme des doublons. Le défaut de 95% permet quelques petites différence, comme par exemple une différence de qualité ou bien une légère modification des couleurs.
|
||||
|
||||
**Comparer les images de tailles différentes:** Le nom dit tout. Sans cette option, les images de tailles différentes ne sont pas comparées.
|
||||
@ -58,6 +58,6 @@ Dans tous les cas, dupeGuru résout les conflits de noms de fichier en ajoutant
|
||||
|
||||
Le format de la ligne de commande est la même que celle que vous écrireriez manuellement, excepté pour les arguments, **%d** et **%r**. L'endroit où vous placez ces deux arguments sera remplacé par le chemin du fichier sélectionné (%d) et le chemin de son fichier référence dans le groupe (%r).
|
||||
|
||||
Si le chemin de votre executable contient un espace, vous devez le placer entre guillemets "". Vous devriez aussi placer vos arguments %d et %r entre guillemets parce qu'il est très possible d'avoir des chemins de fichier |