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

Compare commits

...

19 Commits

Author SHA1 Message Date
hsoft
b8bb40de62 dgme cocoa: v5.7.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40271
2009-12-18 13:04:30 +00:00
hsoft
67dff7fbf2 dgme qt: v5.7.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40270
2009-12-18 12:58:14 +00:00
hsoft
6e226f32fd dgme help: "packagified" help and updated to 5.7.0.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40269
2009-12-18 12:57:47 +00:00
hsoft
cf819dc0a8 dgme qt: fixed gen script and updated FAQ.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40268
2009-12-18 12:21:33 +00:00
hsoft
4f6af6e4dc dgpe cocoa: ugh... fixed typo
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40266
2009-12-16 16:16:22 +00:00
hsoft
a6d2a9b7b3 dgpe cocoa: Fixed a crash happening when iPhoto was never launched.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40265
2009-12-16 15:51:26 +00:00
hsoft
cf34164191 dg cocoa: Since there are problems with the latest pyobjc + py2app + Snow Leopard, I've got to stick with pyobjc1.4 for a while after all...
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40264
2009-12-16 14:48:37 +00:00
hsoft
9a7bb30df4 dgse cocoa: Since there are problems with the latest pyobjc + py2app + Snow Leopard, I've got to stick with pyobjc1.4 for a while after all...
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40263
2009-12-16 14:48:18 +00:00
hsoft
5dc78809b6 dgpe: oops, wrong release date for 1.8.0.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40262
2009-12-16 10:29:02 +00:00
hsoft
2b53a6e7d6 dgpe cocoa: removed the forgotten "-A" flag in bundle generation script.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40261
2009-12-16 10:10:18 +00:00
hsoft
eb82a35e5b dgpe cocoa v1.8.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40260
2009-12-16 09:54:51 +00:00
hsoft
51b14435e0 dgpe qt v1.8.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40259
2009-12-16 09:54:00 +00:00
hsoft
59de033523 [#79 state:fixed] Wrapped PIL's IOError into a warning logging.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40258
2009-12-15 16:54:47 +00:00
hsoft
c9b0a278ca [#78 state:fixed] Wrapped appscript errors, updated error message and the F.A.Q. to give users a clue of what to do.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40257
2009-12-15 16:23:02 +00:00
hsoft
b487189742 [#76 state:fixed] Added combobox painting for the selected item in Directories' State column.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40256
2009-12-15 14:09:13 +00:00
hsoft
d5a60b1580 dgpe cocoa: Made the help file generation process independent from the current work directory. Reverted XCode version of the project to 3.0 so that it can be compiled on Leopard.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40255
2009-12-15 12:52:21 +00:00
hsoft
e2665610e9 dgpe qt: Packagified help.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40254
2009-12-15 11:35:30 +00:00
hsoft
3262ee9938 dgbase: Changed ask_for_reg_code() to askForRegCode() to adapt to change in qtlib.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40253
2009-12-15 11:35:08 +00:00
hsoft
2f153003b3 dgpe help: packagified the help folder.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40252
2009-12-15 11:34:21 +00:00
23 changed files with 155 additions and 53 deletions

View File

@@ -403,7 +403,11 @@ http://www.hardcoded.net/licenses/hs_license
if ([lastAction isEqualTo:jobDelete]) if ([lastAction isEqualTo:jobDelete])
{ {
if (r > 0) if (r > 0)
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be sent to Trash. They were kept in the results, and still are marked.",r]]; {
NSString *msg = @"%d file(s) couldn't be sent to Trash. They were kept in the results, "\
"and still are marked. See the F.A.Q. section in the help file for details.";
[Dialogs showMessage:[NSString stringWithFormat:msg,r]];
}
else else
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."]; [Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
} }

View File

@@ -7,6 +7,7 @@
# 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/hs_license # http://www.hardcoded.net/licenses/hs_license
import objc
from Foundation import * from Foundation import *
from AppKit import * from AppKit import *
import logging import logging
@@ -55,6 +56,10 @@ class DupeGuru(app.DupeGuru):
def _recycle_dupe(dupe): def _recycle_dupe(dupe):
directory = unicode(dupe.path[:-1]) directory = unicode(dupe.path[:-1])
filename = dupe.name filename = dupe.name
if objc.__version__ == '1.4': # For a while, we have to support this.
result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_(
NSWorkspaceRecycleOperation, directory, '', [filename])
else:
result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_( result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_(
NSWorkspaceRecycleOperation, directory, '', [filename], None) NSWorkspaceRecycleOperation, directory, '', [filename], None)

View File

@@ -144,7 +144,7 @@ class DupeGuru(DupeGuruBase, QObject):
DupeGuruBase.apply_filter(self, filter) DupeGuruBase.apply_filter(self, filter)
self.emit(SIGNAL('resultsChanged()')) self.emit(SIGNAL('resultsChanged()'))
def ask_for_reg_code(self): def askForRegCode(self):
self.reg.ask_for_code() self.reg.ask_for_code()
@demo_method @demo_method

View File

@@ -10,7 +10,8 @@
import urllib import urllib
from PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint, QUrl from PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint, QUrl
from PyQt4.QtGui import QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush from PyQt4.QtGui import (QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush, QStyle,
QStyleOptionComboBox, QStyleOptionViewItemV4)
from qtlib.tree_model import TreeNode, TreeModel from qtlib.tree_model import TreeNode, TreeModel
@@ -23,6 +24,24 @@ class DirectoriesDelegate(QStyledItemDelegate):
editor.addItems(STATES) editor.addItems(STATES)
return editor return editor
def paint(self, painter, option, index):
self.initStyleOption(option, index)
# No idea why, but this cast is required if we want to have access to the V4 valuess
option = QStyleOptionViewItemV4(option)
if (index.column() == 1) and (option.state & QStyle.State_Selected):
cboption = QStyleOptionComboBox()
cboption.rect = option.rect
# On OS X (with Qt4.6.0), adding State_Enabled to the flags causes the whole drawing to
# fail (draw nothing), but it's an OS X only glitch. On Windows, it works alright.
cboption.state |= QStyle.State_Enabled
QApplication.style().drawComplexControl(QStyle.CC_ComboBox, cboption, painter)
painter.setBrush(option.palette.text())
rect = QRect(option.rect)
rect.setLeft(rect.left()+4)
painter.drawText(rect, Qt.AlignLeft, option.text)
else:
QStyledItemDelegate.paint(self, painter, option, index)
def setEditorData(self, editor, index): def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole) value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(value); editor.setCurrentIndex(value);

View File

@@ -23,7 +23,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>hsft</string> <string>hsft</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>5.6.6</string> <string>5.7.0</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>

View File

@@ -5,13 +5,15 @@
# 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/hs_license # http://www.hardcoded.net/licenses/hs_license
import sys
sys.path.insert(0, 'py') # for hsutil and hsdocgen
import os import os
from help import gen
print "Generating help" print "Generating help"
os.chdir('help') gen.generate()
os.system('python -u gen.py') os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer help/dupeguru_me_help')
os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer dupeguru_me_help')
os.chdir('..')
print "Generating py plugin" print "Generating py plugin"
os.chdir('py') os.chdir('py')

0
me/help/__init__.py Normal file
View File

View File

@@ -1,3 +1,12 @@
- date: 2009-12-18
version: 5.7.0
description: |
* Added drag & drop support in the Directories panel. (#9)
* Fixed a bug causing dupeGuru to be confused if a scanned file was moved during the scan. (#72)
* Clarified how directories' state are set by painting a combo box in the state cells. [Windows]
(#76)
* Fixed some crashes. (#78 and #79)
* Dropped Mac OS X Tiger support.
- date: 2009-10-14 - date: 2009-10-14
version: 5.6.6 version: 5.6.6
description: | description: |

View File

@@ -5,10 +5,10 @@
# 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/hs_license # http://www.hardcoded.net/licenses/hs_license
import os import os.path as op
from hsdocgen import generate_help, filters from hsdocgen import generate_help, filters
def generate(windows=False):
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}") tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}")
basepath = op.dirname(__file__)
generate_help.main('.', 'dupeguru_me_help', force_render=True, tix=tix) generate_help.main(basepath, op.join(basepath, 'dupeguru_me_help'), force_render=True, tix=tix, windows=windows)

View File

@@ -64,4 +64,12 @@ If your comparison threshold is low enough, you will probably end up with live a
* **Mac OS X**: Type "[*]" in the "Filter" field in the toolbar. * **Mac OS X**: Type "[*]" in the "Filter" field in the toolbar.
* Click on **Mark --> Mark All**. * Click on **Mark --> Mark All**.
* Click on **Actions --> Remove Selected from Results**. * Click on **Actions --> Remove Selected from Results**.
### I tried to send my duplicates to Trash, but dupeGuru is telling me it can't do it. Why? What can I do?
Most of the time, the reason why dupeGuru can't send files to Trash is because of file permissions. You need *write* permissions on files you want to send to Trash. If you're not familiar with the command line, you can use utilities such as [BatChmod](http://macchampion.com/arbysoft/BatchMod) to fix your permissions.
If dupeGuru still gives you troubles after fixing your permissions, there have been some cases where using "Move Marked to..." as a workaround did the trick. So instead of sending your files to Trash, you send them to a temporary folder with the "Move Marked to..." action, and then you delete that temporary folder manually.
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
</%text> </%text>

View File

@@ -17,7 +17,7 @@ from preferences_dialog import PreferencesDialog
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_me' LOGO_NAME = 'logo_me'
NAME = 'dupeGuru Music Edition' NAME = 'dupeGuru Music Edition'
VERSION = '5.6.6' VERSION = '5.7.0'
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7, 8]) DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7, 8])
def __init__(self): def __init__(self):

View File

@@ -13,10 +13,13 @@ import os.path as op
from hsutil.build import print_and_do, build_all_qt_ui from hsutil.build import print_and_do, build_all_qt_ui
from help import gen
build_all_qt_ui(op.join('qtlib', 'ui')) build_all_qt_ui(op.join('qtlib', 'ui'))
build_all_qt_ui('base') build_all_qt_ui('base')
build_all_qt_ui('.') build_all_qt_ui('.')
os.chdir('base')
os.chdir('help') print_and_do("pyrcc4 dg.qrc > dg_rc.py")
print_and_do('python gen.py')
os.chdir('..') os.chdir('..')
gen.generate(windows=True)

View File

@@ -23,7 +23,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>hsft</string> <string>hsft</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.8.0b</string> <string>1.8.0</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>

View File

@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 46; objectVersion = 44;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -360,7 +360,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.0";
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */; mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */;
projectDirPath = ""; projectDirPath = "";
@@ -480,12 +480,13 @@
C01FCF5008A954540054247B /* Release */ = { C01FCF5008A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)"; ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386";
GCC_C_LANGUAGE_STANDARD = c99; GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.5; MACOSX_DEPLOYMENT_TARGET = 10.5;
SDKROOT = macosx10.5; SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
}; };
name = Release; name = Release;
}; };

View File

@@ -5,13 +5,15 @@
# 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/hs_license # http://www.hardcoded.net/licenses/hs_license
import sys
sys.path.insert(0, 'py') # for hsutil and hsdocgen
import os import os
from help import gen
print "Generating help" print "Generating help"
os.chdir('help') gen.generate()
os.system('python -u gen.py') os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer help/dupeguru_pe_help')
os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer dupeguru_pe_help')
os.chdir('..')
print "Generating py plugin" print "Generating py plugin"
os.chdir('py') os.chdir('py')

0
pe/help/__init__.py Normal file
View File

View File

@@ -1,3 +1,12 @@
- date: 2009-12-16
version: 1.8.0
description: |
* Added drag & drop support in the Directories panel. (#9)
* Fixed a bug causing dupeGuru to be confused if a scanned file was moved during the scan. (#72)
* Clarified how directories' state are set by painting a combo box in the state cells. [Windows]
(#76)
* Fixed some crashes. (#78 and #79)
* Dropped Mac OS X Tiger support.
- date: 2009-10-24 - date: 2009-10-24
version: 1.7.8 version: 1.7.8
description: | description: |

View File

@@ -5,10 +5,10 @@
# 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/hs_license # http://www.hardcoded.net/licenses/hs_license
import os import os.path as op
from hsdocgen import generate_help, filters from hsdocgen import generate_help, filters
def generate(windows=False):
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}") tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}")
basepath = op.dirname(__file__)
generate_help.main('.', 'dupeguru_pe_help', force_render=True, tix=tix) generate_help.main(basepath, op.join(basepath, 'dupeguru_pe_help'), force_render=True, tix=tix, windows=windows)

View File

@@ -61,4 +61,14 @@ Enable the [Power Marker](power_marker.htm) mode and click on the Directory colu
* **Windows**: Click on **Actions --> Apply Filter**, then type "copy", then click OK. * **Windows**: Click on **Actions --> Apply Filter**, then type "copy", then click OK.
* **Mac OS X**: Type "copy" in the "Filter" field in the toolbar. * **Mac OS X**: Type "copy" in the "Filter" field in the toolbar.
* Click on **Mark --> Mark All**. * Click on **Mark --> Mark All**.
### I tried to send my duplicates to Trash, but dupeGuru is telling me it can't do it. Why? What can I do?
Most of the time, the reason why dupeGuru can't send files to Trash is because of file permissions. You need *write* permissions on files you want to send to Trash. If you're not familiar with the command line, you can use utilities such as [BatChmod](http://macchampion.com/arbysoft/BatchMod) to fix your permissions.
If dupeGuru still gives you troubles after fixing your permissions, there have been some cases where using "Move Marked to..." as a workaround did the trick. So instead of sending your files to Trash, you send them to a temporary folder with the "Move Marked to..." action, and then you delete that temporary folder manually.
If you're trying to delete *iPhoto* pictures, then the reason for the failure is different. The deletion fails because dupeGuru can't communicate with iPhoto. Be aware that for the deletion to work correctly, you're not supposed to play around iPhoto while dupeGuru is working. Also, sometimes, the Applescript system doesn't seem to know where to find iPhoto to launch it. It might help in these cases to launch iPhoto *before* you send your duplicates to Trash.
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
</%text> </%text>

View File

@@ -14,7 +14,7 @@ import re
from Foundation import * from Foundation import *
from AppKit import * from AppKit import *
from appscript import app, k from appscript import app, k, CommandError
from hsutil import io from hsutil import io
from hsutil.str import get_file_ext from hsutil.str import get_file_ext
@@ -66,6 +66,8 @@ class IPhoto(Photo):
def get_iphoto_database_path(): def get_iphoto_database_path():
ud = NSUserDefaults.standardUserDefaults() ud = NSUserDefaults.standardUserDefaults()
prefs = ud.persistentDomainForName_('com.apple.iApps') prefs = ud.persistentDomainForName_('com.apple.iApps')
if prefs is None:
raise directories.InvalidPathError()
if 'iPhotoRecentDatabases' not in prefs: if 'iPhotoRecentDatabases' not in prefs:
raise directories.InvalidPathError() raise directories.InvalidPathError()
plisturl = NSURL.URLWithString_(prefs['iPhotoRecentDatabases'][0]) plisturl = NSURL.URLWithString_(prefs['iPhotoRecentDatabases'][0])
@@ -96,11 +98,16 @@ def get_iphoto_pictures(plistpath):
class Directories(directories.Directories): class Directories(directories.Directories):
def __init__(self): def __init__(self):
directories.Directories.__init__(self, fileclasses=[Photo]) directories.Directories.__init__(self, fileclasses=[Photo])
try:
self.iphoto_libpath = get_iphoto_database_path() self.iphoto_libpath = get_iphoto_database_path()
self.set_state(self.iphoto_libpath[:-1], directories.STATE_EXCLUDED) self.set_state(self.iphoto_libpath[:-1], directories.STATE_EXCLUDED)
except directories.InvalidPathError:
self.iphoto_libpath = None
def _get_files(self, from_path): def _get_files(self, from_path):
if from_path == Path('iPhoto Library'): if from_path == Path('iPhoto Library'):
if self.iphoto_libpath is None:
return []
is_ref = self.get_state(from_path) == directories.STATE_REFERENCE is_ref = self.get_state(from_path) == directories.STATE_REFERENCE
photos = get_iphoto_pictures(self.iphoto_libpath) photos = get_iphoto_pictures(self.iphoto_libpath)
for photo in photos: for photo in photos:
@@ -142,12 +149,18 @@ class DupeGuruPE(app_cocoa.DupeGuru):
self.path2iphoto = {} self.path2iphoto = {}
if any(isinstance(dupe, IPhoto) for dupe in marked): if any(isinstance(dupe, IPhoto) for dupe in marked):
j = j.start_subjob([6, 4], "Probing iPhoto. Don\'t touch it during the operation!") j = j.start_subjob([6, 4], "Probing iPhoto. Don\'t touch it during the operation!")
try:
a = app('iPhoto') a = app('iPhoto')
a.activate(timeout=0) a.activate(timeout=0)
a.select(a.photo_library_album(timeout=0), timeout=0) a.select(a.photo_library_album(timeout=0), timeout=0)
photos = as_fetch(a.photo_library_album().photos, k.item) photos = as_fetch(a.photo_library_album().photos, k.item)
for photo in j.iter_with_progress(photos): for photo in j.iter_with_progress(photos):
try:
self.path2iphoto[unicode(photo.image_path(timeout=0))] = photo self.path2iphoto[unicode(photo.image_path(timeout=0))] = photo
except CommandError:
pass
except (CommandError, RuntimeError):
pass
j.start_job(self.results.mark_count, "Sending dupes to the Trash") j.start_job(self.results.mark_count, "Sending dupes to the Trash")
self.last_op_error_count = self.results.perform_on_marked(op, True) self.last_op_error_count = self.results.perform_on_marked(op, True)
del self.path2iphoto del self.path2iphoto
@@ -156,11 +169,15 @@ class DupeGuruPE(app_cocoa.DupeGuru):
if isinstance(dupe, IPhoto): if isinstance(dupe, IPhoto):
if unicode(dupe.path) in self.path2iphoto: if unicode(dupe.path) in self.path2iphoto:
photo = self.path2iphoto[unicode(dupe.path)] photo = self.path2iphoto[unicode(dupe.path)]
try:
a = app('iPhoto') a = app('iPhoto')
a.remove(photo, timeout=0) a.remove(photo, timeout=0)
return True return True
except (CommandError, RuntimeError):
return False
else: else:
logging.warning("Could not find photo {0} in iPhoto Library", unicode(dupe.path)) logging.warning(u"Could not find photo %s in iPhoto Library", unicode(dupe.path))
return False
else: else:
return app_cocoa.DupeGuru._do_delete_dupe(self, dupe) return app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
@@ -170,7 +187,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
def _get_file(self, str_path): def _get_file(self, str_path):
p = Path(str_path) p = Path(str_path)
if p in self.directories.iphoto_libpath[:-1]: if (self.directories.iphoto_libpath is not None) and (p in self.directories.iphoto_libpath[:-1]):
return IPhoto(p) return IPhoto(p)
return app_cocoa.DupeGuru._get_file(self, str_path) return app_cocoa.DupeGuru._get_file(self, str_path)

View File

@@ -8,6 +8,7 @@
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
import os.path as op import os.path as op
import logging
from PyQt4.QtGui import QImage from PyQt4.QtGui import QImage
import PIL.Image import PIL.Image
@@ -40,8 +41,12 @@ class File(fs.File):
def _read_info(self, field): def _read_info(self, field):
fs.File._read_info(self, field) fs.File._read_info(self, field)
if field == 'dimensions': if field == 'dimensions':
try:
im = PIL.Image.open(unicode(self.path)) im = PIL.Image.open(unicode(self.path))
self.dimensions = im.size self.dimensions = im.size
except IOError:
self.dimensions = (0, 0)
logging.warning(u"Could not read image '%s'", unicode(self.path))
def get_blocks(self, block_count_per_side): def get_blocks(self, block_count_per_side):
image = QImage(unicode(self.path)) image = QImage(unicode(self.path))
@@ -52,7 +57,7 @@ class File(fs.File):
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_pe' LOGO_NAME = 'logo_pe'
NAME = 'dupeGuru Picture Edition' NAME = 'dupeGuru Picture Edition'
VERSION = '1.7.7' VERSION = '1.8.0'
DELTA_COLUMNS = frozenset([2, 5, 6]) DELTA_COLUMNS = frozenset([2, 5, 6])
def __init__(self): def __init__(self):

View File

@@ -13,10 +13,14 @@ import os.path as op
from hsutil.build import print_and_do, build_all_qt_ui from hsutil.build import print_and_do, build_all_qt_ui
from help import gen
build_all_qt_ui(op.join('qtlib', 'ui')) build_all_qt_ui(op.join('qtlib', 'ui'))
build_all_qt_ui('base') build_all_qt_ui('base')
build_all_qt_ui('.') build_all_qt_ui('.')
print_and_do("pyrcc4 base\\dg.qrc > base\\dg_rc.py") os.chdir('base')
print_and_do("pyrcc4 dg.qrc > dg_rc.py")
os.chdir('..')
def move(src, dst): def move(src, dst):
if not op.exists(src): if not op.exists(src):
@@ -39,5 +43,5 @@ move(op.join('modules', 'block', '_block.so'), op.join('.', '_block.so'))
move(op.join('modules', 'block', '_block.pyd'), op.join('.', '_block.pyd')) move(op.join('modules', 'block', '_block.pyd'), op.join('.', '_block.pyd'))
os.chdir('help') os.chdir('help')
print_and_do('python gen.py') gen.generate(windows=True)
os.chdir('..') os.chdir('..')

View File

@@ -11,6 +11,7 @@ from __future__ import unicode_literals
import logging import logging
import objc
from AppKit import * from AppKit import *
from hsutil import io from hsutil import io
@@ -25,6 +26,9 @@ from .fs import Bundle as BundleBase
def is_bundle(str_path): def is_bundle(str_path):
sw = NSWorkspace.sharedWorkspace() sw = NSWorkspace.sharedWorkspace()
if objc.__version__ == '1.4': # For a while, we have to support this.
uti, error = sw.typeOfFile_error_(str_path)
else:
uti, error = sw.typeOfFile_error_(str_path, None) uti, error = sw.typeOfFile_error_(str_path, None)
if error is not None: if error is not None:
logging.warning(u'There was an error trying to detect the UTI of %s', str_path) logging.warning(u'There was an error trying to detect the UTI of %s', str_path)