mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix error message in OSX when dragging and dropping a cover onto the edit metadata dialog
This commit is contained in:
parent
ff57c45613
commit
7448079aa8
@ -57,7 +57,7 @@ r'''
|
||||
def _check_symlinks_prescript():
|
||||
import os, tempfile, traceback, sys
|
||||
from Authorization import Authorization, kAuthorizationFlagDestroyRights
|
||||
|
||||
|
||||
AUTHTOOL="""#!%(sp)s
|
||||
import os
|
||||
scripts = %(sp)s
|
||||
@ -71,13 +71,13 @@ for s, l in zip(scripts, links):
|
||||
os.symlink(s, l)
|
||||
os.umask(omask)
|
||||
"""
|
||||
|
||||
|
||||
dest_path = %(dest_path)s
|
||||
resources_path = os.environ['RESOURCEPATH']
|
||||
scripts = %(scripts)s
|
||||
scripts = %(scripts)s
|
||||
links = [os.path.join(dest_path, i) for i in scripts]
|
||||
scripts = [os.path.join(resources_path, 'loaders', i) for i in scripts]
|
||||
|
||||
|
||||
bad = False
|
||||
for s, l in zip(scripts, links):
|
||||
if os.path.exists(l) and os.path.exists(os.path.realpath(l)):
|
||||
@ -111,22 +111,22 @@ _check_symlinks_prescript()
|
||||
packages=self.packages,
|
||||
excludes=self.excludes,
|
||||
debug=debug)
|
||||
|
||||
|
||||
@classmethod
|
||||
def makedmg(cls, d, volname,
|
||||
destdir='dist',
|
||||
def makedmg(cls, d, volname,
|
||||
destdir='dist',
|
||||
internet_enable=True,
|
||||
format='UDBZ'):
|
||||
''' Copy a directory d into a dmg named volname '''
|
||||
dmg = os.path.join(destdir, volname+'.dmg')
|
||||
if os.path.exists(dmg):
|
||||
os.unlink(dmg)
|
||||
subprocess.check_call(['/usr/bin/hdiutil', 'create', '-srcfolder', os.path.abspath(d),
|
||||
subprocess.check_call(['/usr/bin/hdiutil', 'create', '-srcfolder', os.path.abspath(d),
|
||||
'-volname', volname, '-format', format, dmg])
|
||||
if internet_enable:
|
||||
subprocess.check_call(['/usr/bin/hdiutil', 'internet-enable', '-yes', dmg])
|
||||
return dmg
|
||||
|
||||
|
||||
@classmethod
|
||||
def qt_dependencies(cls, path):
|
||||
pipe = subprocess.Popen('/usr/bin/otool -L '+path, shell=True, stdout=subprocess.PIPE).stdout
|
||||
@ -134,12 +134,12 @@ _check_symlinks_prescript()
|
||||
for l in pipe.readlines():
|
||||
match = re.search(r'(.*)\(', l)
|
||||
if not match:
|
||||
continue
|
||||
continue
|
||||
lib = match.group(1).strip()
|
||||
if lib.startswith(BuildAPP.QT_PREFIX):
|
||||
deps.append(lib)
|
||||
return deps
|
||||
|
||||
|
||||
@classmethod
|
||||
def fix_qt_dependencies(cls, path, deps):
|
||||
fp = '@executable_path/../Frameworks/'
|
||||
@ -155,8 +155,8 @@ _check_symlinks_prescript()
|
||||
newpath = fp + '%s.framework/Versions/Current/%s'%(module, module)
|
||||
cmd = ' '.join(['/usr/bin/install_name_tool', '-change', dep, newpath, path])
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
|
||||
|
||||
|
||||
def add_qt_plugins(self):
|
||||
macos_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'MacOS')
|
||||
for root, dirs, files in os.walk(BuildAPP.QT_PREFIX+'/plugins'):
|
||||
@ -172,14 +172,14 @@ _check_symlinks_prescript()
|
||||
shutil.copymode(path, target)
|
||||
deps = BuildAPP.qt_dependencies(target)
|
||||
BuildAPP.fix_qt_dependencies(target, deps)
|
||||
|
||||
|
||||
|
||||
|
||||
#deps = BuildAPP.qt_dependencies(path)
|
||||
|
||||
|
||||
def fix_python_dependencies(self, files):
|
||||
for f in files:
|
||||
subprocess.check_call(['/usr/bin/install_name_tool', '-change', '/Library/Frameworks/Python.framework/Versions/2.6/Python', '@executable_path/../Frameworks/Python.framework/Versions/2.6/Python', f])
|
||||
|
||||
|
||||
def fix_misc_dependencies(self, files):
|
||||
for path in files:
|
||||
frameworks_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'Frameworks')
|
||||
@ -195,15 +195,15 @@ _check_symlinks_prescript()
|
||||
if os.path.exists(bundle):
|
||||
subprocess.check_call(['/usr/bin/install_name_tool', '-change', dep,
|
||||
'@executable_path/../Frameworks/'+name, path])
|
||||
|
||||
|
||||
|
||||
|
||||
def add_plugins(self):
|
||||
self.add_qt_plugins()
|
||||
frameworks_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'Frameworks')
|
||||
plugins_dir = os.path.join(frameworks_dir, 'plugins')
|
||||
if not os.path.exists(plugins_dir):
|
||||
os.mkdir(plugins_dir)
|
||||
|
||||
|
||||
maps = {}
|
||||
for f in glob.glob('src/calibre/plugins/*'):
|
||||
tgt = plugins_dir
|
||||
@ -217,8 +217,8 @@ _check_symlinks_prescript()
|
||||
deps.append(dst)
|
||||
self.fix_python_dependencies(deps)
|
||||
self.fix_misc_dependencies(deps)
|
||||
|
||||
|
||||
|
||||
|
||||
def run(self):
|
||||
py2app.run(self)
|
||||
resource_dir = os.path.join(self.dist_dir,
|
||||
@ -242,8 +242,8 @@ _check_symlinks_prescript()
|
||||
os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\
|
||||
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
||||
self.add_plugins()
|
||||
|
||||
|
||||
|
||||
|
||||
print
|
||||
print 'Adding pdftohtml'
|
||||
os.link(os.path.expanduser('~/pdftohtml'), os.path.join(frameworks_dir, 'pdftohtml'))
|
||||
@ -259,21 +259,21 @@ _check_symlinks_prescript()
|
||||
if os.path.exists(dst):
|
||||
shutil.rmtree(dst)
|
||||
shutil.copytree('/usr/local/etc/fonts', dst, symlinks=False)
|
||||
|
||||
|
||||
print
|
||||
print 'Adding IPython'
|
||||
dst = os.path.join(resource_dir, 'lib', 'python2.6', 'IPython')
|
||||
if os.path.exists(dst): shutil.rmtree(dst)
|
||||
shutil.copytree(os.path.expanduser('~/build/ipython/IPython'), dst)
|
||||
|
||||
print
|
||||
|
||||
print
|
||||
print 'Adding ImageMagick'
|
||||
dest = os.path.join(frameworks_dir, 'ImageMagick')
|
||||
if os.path.exists(dest):
|
||||
sutil.rmtree(dest)
|
||||
shutil.rmtree(dest)
|
||||
shutil.copytree(os.path.expanduser('~/ImageMagick'), dest, True)
|
||||
shutil.copyfile('/usr/local/lib/libpng12.0.dylib', os.path.join(dest, 'lib', 'libpng12.0.dylib'))
|
||||
|
||||
|
||||
print
|
||||
print 'Installing prescipt'
|
||||
sf = [os.path.basename(s) for s in all_names]
|
||||
@ -293,13 +293,13 @@ sys.frameworks_dir = os.path.join(os.path.dirname(os.environ['RESOURCEPATH']), '
|
||||
print >>f, 'import sys, os'
|
||||
f.write(src)
|
||||
f.close()
|
||||
print
|
||||
print
|
||||
print 'Adding main scripts to site-packages'
|
||||
f = zipfile.ZipFile(os.path.join(self.dist_dir, APPNAME+'.app', 'Contents', 'Resources', 'lib', 'python'+sys.version[:3], 'site-packages.zip'), 'a', zipfile.ZIP_DEFLATED)
|
||||
for script in scripts['gui']+scripts['console']:
|
||||
f.write(script, script.partition('/')[-1])
|
||||
f.close()
|
||||
print
|
||||
print
|
||||
print 'Creating console.app'
|
||||
contents_dir = os.path.dirname(resource_dir)
|
||||
cc_dir = os.path.join(contents_dir, 'console.app', 'Contents')
|
||||
@ -312,7 +312,7 @@ sys.frameworks_dir = os.path.join(os.path.dirname(os.environ['RESOURCEPATH']), '
|
||||
plist['LSUIElement'] = '1'
|
||||
plistlib.writePlist(plist, os.path.join(cc_dir, x))
|
||||
else:
|
||||
os.symlink(os.path.join('../..', x),
|
||||
os.symlink(os.path.join('../..', x),
|
||||
os.path.join(cc_dir, x))
|
||||
print
|
||||
print 'Building disk image'
|
||||
@ -343,9 +343,10 @@ def main():
|
||||
'calibre.ebooks.lrf.any.*', 'calibre.ebooks.lrf.feeds.*',
|
||||
'keyword', 'codeop', 'pydoc', 'readline',
|
||||
'BeautifulSoup', 'calibre.ebooks.lrf.fonts.prs500.*',
|
||||
'dateutil',
|
||||
'dateutil', 'email.iterators',
|
||||
'email.generator',
|
||||
],
|
||||
'packages' : ['PIL', 'Authorization', 'lxml'],
|
||||
'packages' : ['PIL', 'Authorization', 'lxml', 'dns'],
|
||||
'excludes' : ['IPython'],
|
||||
'plist' : { 'CFBundleGetInfoString' : '''calibre, an E-book management application.'''
|
||||
''' Visit http://calibre.kovidgoyal.net for details.''',
|
||||
|
@ -11,7 +11,7 @@ from calibre.utils.config import OptionParser
|
||||
|
||||
class FetchGoogle(Thread):
|
||||
name = 'Google Books'
|
||||
|
||||
|
||||
def __init__(self, title, author, publisher, isbn, verbose):
|
||||
self.title = title
|
||||
self.verbose = verbose
|
||||
@ -21,17 +21,17 @@ class FetchGoogle(Thread):
|
||||
Thread.__init__(self, None)
|
||||
self.daemon = True
|
||||
self.exception, self.tb = None, None
|
||||
|
||||
|
||||
def run(self):
|
||||
from calibre.ebooks.metadata.google_books import search
|
||||
try:
|
||||
self.results = search(self.title, self.author, self.publisher,
|
||||
self.isbn, max_results=10,
|
||||
self.results = search(self.title, self.author, self.publisher,
|
||||
self.isbn, max_results=10,
|
||||
verbose=self.verbose)
|
||||
except Exception, e:
|
||||
self.results = []
|
||||
self.exception = e
|
||||
self.tb = traceback.format_exc()
|
||||
self.tb = traceback.format_exc()
|
||||
|
||||
|
||||
class FetchISBNDB(Thread):
|
||||
@ -46,19 +46,21 @@ class FetchISBNDB(Thread):
|
||||
self.daemon = True
|
||||
self.exception, self.tb = None, None
|
||||
self.key = key
|
||||
|
||||
|
||||
def run(self):
|
||||
from calibre.ebooks.metadata.isbndb import option_parser, create_books
|
||||
args = ['isbndb']
|
||||
if self.isbn:
|
||||
args.extend(['--isbn', self.isbn])
|
||||
else:
|
||||
else:
|
||||
if self.title:
|
||||
args.extend(['--title', self.title])
|
||||
if self.author:
|
||||
args.extend(['--author', self.author])
|
||||
if self.publisher:
|
||||
args.extend(['--publisher', self.publisher])
|
||||
if self.verbose:
|
||||
args.extend(['--verbose'])
|
||||
args.append(self.key)
|
||||
try:
|
||||
opts, args = option_parser().parse_args(args)
|
||||
@ -75,7 +77,7 @@ def result_index(source, result):
|
||||
if x.isbn == result.isbn:
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
def merge_results(one, two):
|
||||
for x in two:
|
||||
idx = result_index(one, x)
|
||||
@ -90,42 +92,42 @@ def search(title=None, author=None, publisher=None, isbn=None, isbndb_key=None,
|
||||
isbn is None)
|
||||
fetchers = [FetchGoogle(title, author, publisher, isbn, verbose)]
|
||||
if isbndb_key:
|
||||
fetchers.append(FetchISBNDB(title, author, publisher, isbn, verbose,
|
||||
fetchers.append(FetchISBNDB(title, author, publisher, isbn, verbose,
|
||||
isbndb_key))
|
||||
|
||||
|
||||
|
||||
|
||||
for fetcher in fetchers:
|
||||
fetcher.start()
|
||||
for fetcher in fetchers:
|
||||
fetcher.join()
|
||||
for fetcher in fetchers[1:]:
|
||||
merge_results(fetchers[0].results, fetcher.results)
|
||||
|
||||
|
||||
results = sorted(fetchers[0].results, cmp=lambda x, y : cmp(
|
||||
(x.comments.strip() if x.comments else ''),
|
||||
(y.comments.strip() if y.comments else '')
|
||||
), reverse=True)
|
||||
|
||||
|
||||
return results, [(x.name, x.exception, x.tb) for x in fetchers]
|
||||
|
||||
|
||||
|
||||
def option_parser():
|
||||
parser = OptionParser(textwrap.dedent(
|
||||
'''\
|
||||
%prog [options]
|
||||
|
||||
Fetch book metadata from online sources. You must specify at least one
|
||||
of title, author, publisher or ISBN. If you specify ISBN, the others
|
||||
are ignored.
|
||||
|
||||
Fetch book metadata from online sources. You must specify at least one
|
||||
of title, author, publisher or ISBN. If you specify ISBN, the others
|
||||
are ignored.
|
||||
'''
|
||||
))
|
||||
parser.add_option('-t', '--title', help='Book title')
|
||||
parser.add_option('-a', '--author', help='Book author(s)')
|
||||
parser.add_option('-p', '--publisher', help='Book publisher')
|
||||
parser.add_option('-i', '--isbn', help='Book ISBN')
|
||||
parser.add_option('-m', '--max-results', default=10,
|
||||
parser.add_option('-m', '--max-results', default=10,
|
||||
help='Maximum number of results to fetch')
|
||||
parser.add_option('-k', '--isbndb-key',
|
||||
parser.add_option('-k', '--isbndb-key',
|
||||
help=('The access key for your ISBNDB.com account. '
|
||||
'Only needed if you want to search isbndb.com'))
|
||||
parser.add_option('-v', '--verbose', default=0, action='count',
|
||||
@ -135,19 +137,19 @@ def option_parser():
|
||||
def main(args=sys.argv):
|
||||
parser = option_parser()
|
||||
opts, args = parser.parse_args(args)
|
||||
results, exceptions = search(opts.title, opts.author, opts.publisher,
|
||||
results, exceptions = search(opts.title, opts.author, opts.publisher,
|
||||
opts.isbn, opts.isbndb_key, opts.verbose)
|
||||
for result in results:
|
||||
print unicode(result).encode(preferred_encoding)
|
||||
print
|
||||
|
||||
|
||||
for name, exception, tb in exceptions:
|
||||
if exception is not None:
|
||||
print 'WARNING: Fetching from', name, 'failed with error:'
|
||||
print exception
|
||||
print tb
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
|
@ -10,10 +10,10 @@ from calibre.gui2.dialogs.jobs_ui import Ui_JobsDialog
|
||||
from calibre import __appname__
|
||||
|
||||
class ProgressBarDelegate(QAbstractItemDelegate):
|
||||
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
return QSize(120, 30)
|
||||
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
opts = QStyleOptionProgressBarV2()
|
||||
opts.rect = option.rect
|
||||
@ -44,20 +44,23 @@ class JobsDialog(QDialog, Ui_JobsDialog):
|
||||
self.jobs_view.model().kill_job)
|
||||
self.pb_delegate = ProgressBarDelegate(self)
|
||||
self.jobs_view.setItemDelegateForColumn(2, self.pb_delegate)
|
||||
|
||||
|
||||
self.running_time_timer = QTimer(self)
|
||||
self.connect(self.running_time_timer, SIGNAL('timeout()'), self.update_running_time)
|
||||
self.running_time_timer.start(1000)
|
||||
|
||||
|
||||
def update_running_time(self, *args):
|
||||
self.model.running_time_updated()
|
||||
|
||||
try:
|
||||
self.model.running_time_updated()
|
||||
except: # Raises random exceptions on OS X
|
||||
pass
|
||||
|
||||
def kill_job(self):
|
||||
for index in self.jobs_view.selectedIndexes():
|
||||
row = index.row()
|
||||
self.model.kill_job(row, self)
|
||||
return
|
||||
|
||||
|
||||
def closeEvent(self, e):
|
||||
self.jobs_view.write_settings()
|
||||
e.accept()
|
||||
|
@ -18,27 +18,27 @@ from calibre.gui2.dialogs.job_view_ui import Ui_Dialog
|
||||
NONE = QVariant()
|
||||
|
||||
class JobManager(QAbstractTableModel):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
QAbstractTableModel.__init__(self)
|
||||
self.wait_icon = QVariant(QIcon(':/images/jobs.svg'))
|
||||
self.running_icon = QVariant(QIcon(':/images/exec.svg'))
|
||||
self.error_icon = QVariant(QIcon(':/images/dialog_error.svg'))
|
||||
self.done_icon = QVariant(QIcon(':/images/ok.svg'))
|
||||
|
||||
|
||||
self.jobs = []
|
||||
self.server = Server()
|
||||
self.add_job = Dispatcher(self._add_job)
|
||||
self.status_update = Dispatcher(self._status_update)
|
||||
self.start_work = Dispatcher(self._start_work)
|
||||
self.job_done = Dispatcher(self._job_done)
|
||||
|
||||
|
||||
def columnCount(self, parent=QModelIndex()):
|
||||
return 4
|
||||
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
return len(self.jobs)
|
||||
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role != Qt.DisplayRole:
|
||||
return NONE
|
||||
@ -50,14 +50,14 @@ class JobManager(QAbstractTableModel):
|
||||
return QVariant(text)
|
||||
else:
|
||||
return QVariant(section+1)
|
||||
|
||||
|
||||
def data(self, index, role):
|
||||
try:
|
||||
if role not in (Qt.DisplayRole, Qt.DecorationRole):
|
||||
return NONE
|
||||
row, col = index.row(), index.column()
|
||||
job = self.jobs[row]
|
||||
|
||||
|
||||
if role == Qt.DisplayRole:
|
||||
if col == 0:
|
||||
desc = job.description
|
||||
@ -102,31 +102,31 @@ class JobManager(QAbstractTableModel):
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return NONE
|
||||
|
||||
|
||||
def _add_job(self, job):
|
||||
self.emit(SIGNAL('layoutAboutToBeChanged()'))
|
||||
self.jobs.append(job)
|
||||
self.jobs.sort()
|
||||
self.emit(SIGNAL('job_added(int)'), self.rowCount())
|
||||
self.emit(SIGNAL('layoutChanged()'))
|
||||
|
||||
|
||||
def done_jobs(self):
|
||||
return [j for j in self.jobs if j.status() in ['DONE', 'ERROR']]
|
||||
|
||||
|
||||
def row_to_job(self, row):
|
||||
return self.jobs[row]
|
||||
|
||||
|
||||
def _start_work(self, job):
|
||||
self.emit(SIGNAL('layoutAboutToBeChanged()'))
|
||||
self.jobs.sort()
|
||||
self.emit(SIGNAL('layoutChanged()'))
|
||||
|
||||
|
||||
def _job_done(self, job):
|
||||
self.emit(SIGNAL('layoutAboutToBeChanged()'))
|
||||
self.jobs.sort()
|
||||
self.emit(SIGNAL('job_done(int)'), len(self.jobs) - len(self.done_jobs()))
|
||||
self.emit(SIGNAL('layoutChanged()'))
|
||||
|
||||
|
||||
def _status_update(self, job):
|
||||
try:
|
||||
row = self.jobs.index(job)
|
||||
@ -134,38 +134,38 @@ class JobManager(QAbstractTableModel):
|
||||
return
|
||||
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'),
|
||||
self.index(row, 0), self.index(row, 3))
|
||||
|
||||
def running_time_updated(self):
|
||||
|
||||
def running_time_updated(self, *args):
|
||||
for job in self.jobs:
|
||||
if not job.is_running:
|
||||
continue
|
||||
row = self.jobs.index(job)
|
||||
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'),
|
||||
self.index(row, 3), self.index(row, 3))
|
||||
|
||||
self.index(row, 3), self.index(row, 3))
|
||||
|
||||
def has_device_jobs(self):
|
||||
for job in self.jobs:
|
||||
if job.is_running and isinstance(job, DeviceJob):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def has_jobs(self):
|
||||
for job in self.jobs:
|
||||
if job.is_running:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def run_job(self, done, func, args=[], kwargs={},
|
||||
description=None):
|
||||
job = ParallelJob(func, done, self, args=args, kwargs=kwargs,
|
||||
description=description)
|
||||
self.server.add_job(job)
|
||||
return job
|
||||
|
||||
|
||||
|
||||
|
||||
def output(self, job):
|
||||
self.emit(SIGNAL('output_received()'))
|
||||
|
||||
|
||||
def kill_job(self, row, view):
|
||||
job = self.jobs[row]
|
||||
if isinstance(job, DeviceJob):
|
||||
@ -183,20 +183,20 @@ class JobManager(QAbstractTableModel):
|
||||
|
||||
|
||||
self.server.kill(job)
|
||||
|
||||
|
||||
def terminate_all_jobs(self):
|
||||
pass
|
||||
|
||||
|
||||
class DetailView(QDialog, Ui_Dialog):
|
||||
|
||||
|
||||
def __init__(self, parent, job):
|
||||
QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.setWindowTitle(job.description)
|
||||
self.job = job
|
||||
self.update()
|
||||
|
||||
|
||||
|
||||
|
||||
def update(self):
|
||||
self.log.setPlainText(self.job.console_text())
|
||||
vbar = self.log.verticalScrollBar()
|
||||
|
Loading…
x
Reference in New Issue
Block a user