Workaround for Qt 5 no longer being able to change the dock icon

This commit is contained in:
Kovid Goyal 2014-06-16 16:08:59 +05:30
parent 4067331a7f
commit cbc95329fc
6 changed files with 86 additions and 15 deletions

BIN
icons/calibre.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

View File

@ -0,0 +1,42 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import os, shutil, subprocess
d, j, a = (getattr(os.path, x) for x in ('dirname', 'join', 'abspath'))
base = d(a(__file__))
os.chdir(base)
imgsrc = j(d(d(base)), 'imgsrc')
sources = {'calibre':j(d(base), 'calibre.png'), 'ebook-edit':j(imgsrc, 'tweak.svg'), 'ebook-viewer':j(imgsrc, 'viewer.svg')}
for name, src in sources.iteritems():
iconset = name + '.iconset'
if os.path.exists(iconset):
shutil.rmtree(iconset)
os.mkdir(iconset)
os.chdir(iconset)
try:
for sz in (16, 32, 128, 256, 512, 1024):
iname = 'icon_{0}x{0}.png'.format(sz)
iname2x = 'icon_{0}x{0}@2x.png'.format(sz // 2)
if src.endswith('.svg'):
subprocess.check_call(['rsvg-convert', src, '-w', str(sz), '-h', str(sz), '-o', iname])
else:
# We have a 512x512 png image
if sz == 512:
shutil.copy2(src, iname)
else:
subprocess.check_call(['convert', src, '-resize', '{0}x{0}'.format(sz), iname])
if sz > 16:
shutil.copy2(iname, iname2x)
if sz > 512:
os.remove(iname)
finally:
os.chdir('..')

Binary file not shown.

View File

@ -188,6 +188,7 @@ class Py2App(object):
self.compile_py_modules() self.compile_py_modules()
self.create_console_app() self.create_console_app()
self.create_gui_apps()
self.copy_site() self.copy_site()
self.create_exe() self.create_exe()
@ -317,8 +318,12 @@ class Py2App(object):
c = join(self.build_dir, 'Contents') c = join(self.build_dir, 'Contents')
for x in ('Frameworks', 'MacOS', 'Resources'): for x in ('Frameworks', 'MacOS', 'Resources'):
os.makedirs(join(c, x)) os.makedirs(join(c, x))
for x in ('library.icns', 'book.icns'): for x in ('book.icns',):
shutil.copyfile(join('icons', x), join(self.resources_dir, x)) shutil.copyfile(join('icons', x), join(self.resources_dir, x))
for x in glob.glob(join('icons', 'icns', '*.iconset')):
subprocess.check_call([
'iconutil', '-c', 'icns', x, '-o', join(
self.resources_dir, basename(x).partition('.')[0] + '.icns')])
@flush @flush
def add_calibre_plugins(self): def add_calibre_plugins(self):
@ -355,7 +360,7 @@ class Py2App(object):
NSHumanReadableCopyright='Copyright 2014, Kovid Goyal', NSHumanReadableCopyright='Copyright 2014, Kovid Goyal',
CFBundleGetInfoString=('calibre, an E-book management ' CFBundleGetInfoString=('calibre, an E-book management '
'application. Visit http://calibre-ebook.com for details.'), 'application. Visit http://calibre-ebook.com for details.'),
CFBundleIconFile='library.icns', CFBundleIconFile='calibre.icns',
NSHighResolutionCapable=True, NSHighResolutionCapable=True,
LSApplicationCategoryType='public.app-category.productivity', LSApplicationCategoryType='public.app-category.productivity',
LSEnvironment=env LSEnvironment=env
@ -590,11 +595,12 @@ class Py2App(object):
cc_dir = os.path.join(self.contents_dir, 'console.app', 'Contents') cc_dir = os.path.join(self.contents_dir, 'console.app', 'Contents')
os.makedirs(cc_dir) os.makedirs(cc_dir)
for x in os.listdir(self.contents_dir): for x in os.listdir(self.contents_dir):
if x == 'console.app': if x.endswith('.app'):
continue continue
if x == 'Info.plist': if x == 'Info.plist':
plist = plistlib.readPlist(join(self.contents_dir, x)) plist = plistlib.readPlist(join(self.contents_dir, x))
plist['LSUIElement'] = '1' plist['LSUIElement'] = '1'
plist['CFBundleIdentifier'] = 'com.calibre-ebook.console'
plist.pop('CFBundleDocumentTypes') plist.pop('CFBundleDocumentTypes')
plistlib.writePlist(plist, join(cc_dir, x)) plistlib.writePlist(plist, join(cc_dir, x))
else: else:
@ -605,6 +611,26 @@ class Py2App(object):
shutil.copytree(join(SW, 'build/notifier.app'), join( shutil.copytree(join(SW, 'build/notifier.app'), join(
self.contents_dir, 'calibre-notifier.app')) self.contents_dir, 'calibre-notifier.app'))
@flush
def create_gui_apps(self):
info('\nCreating launcher apps for viewer and editor')
for launcher in ('ebook-viewer', 'ebook-edit'):
cc_dir = os.path.join(self.contents_dir, launcher + '.app', 'Contents')
os.makedirs(cc_dir)
for x in os.listdir(self.contents_dir):
if x.endswith('.app'):
continue
if x == 'Info.plist':
plist = plistlib.readPlist(join(self.contents_dir, x))
plist['CFBundleDisplayName'] = plist['CFBundleName'] = {'ebook-viewer':'E-book Viewer', 'ebook-edit':'Edit Book'}[launcher]
plist['CFBundleExecutable'] = launcher
plist['CFBundleIconFile'] = launcher + '.icns'
plist['CFBundleIdentifier'] = 'com.calibre-ebook.' + launcher
plist.pop('CFBundleDocumentTypes')
plistlib.writePlist(plist, join(cc_dir, x))
else:
os.symlink(join('../..', x), join(cc_dir, x))
@flush @flush
def copy_site(self): def copy_site(self):
base = os.path.dirname(__file__) base = os.path.dirname(__file__)

View File

@ -58,8 +58,7 @@ class Worker(object):
e = self.exe_name e = self.exe_name
if iswindows: if iswindows:
return os.path.join(os.path.dirname(sys.executable), return os.path.join(os.path.dirname(sys.executable),
e+'.exe' if isfrozen else \ e+'.exe' if isfrozen else 'Scripts\\%s.exe'%e)
'Scripts\\%s.exe'%e)
if isosx: if isosx:
return os.path.join(sys.console_binaries_path, e) return os.path.join(sys.console_binaries_path, e)
@ -72,10 +71,11 @@ class Worker(object):
return c return c
return e return e
@property @property
def gui_executable(self): def gui_executable(self):
if isosx: if isosx:
if self.job_name in {'ebook-viewer', 'ebook-edit'}:
return self.executable.replace('/console.app/', '/%s.app/' % self.job_name)
return os.path.join(sys.binaries_path, self.exe_name) return os.path.join(sys.binaries_path, self.exe_name)
return self.executable return self.executable
@ -111,13 +111,15 @@ class Worker(object):
@property @property
def returncode(self): def returncode(self):
if not hasattr(self, 'child'): return None if not hasattr(self, 'child'):
return None
self.child.poll() self.child.poll()
return self.child.returncode return self.child.returncode
@property @property
def pid(self): def pid(self):
if not hasattr(self, 'child'): return None if not hasattr(self, 'child'):
return None
return getattr(self.child, 'pid', None) return getattr(self.child, 'pid', None)
def close_log_file(self): def close_log_file(self):
@ -143,9 +145,10 @@ class Worker(object):
except: except:
pass pass
def __init__(self, env, gui=False): def __init__(self, env, gui=False, job_name=None):
self._env = {} self._env = {}
self.gui = gui self.gui = gui
self.job_name = job_name
# Windows cannot handle unicode env vars # Windows cannot handle unicode env vars
for k, v in env.iteritems(): for k, v in env.iteritems():
try: try:

View File

@ -159,7 +159,7 @@ class Server(Thread):
self.start() self.start()
def launch_worker(self, gui=False, redirect_output=None): def launch_worker(self, gui=False, redirect_output=None, job_name=None):
start = time.time() start = time.time()
with self._worker_launch_lock: with self._worker_launch_lock:
self.launched_worker_count += 1 self.launched_worker_count += 1
@ -175,15 +175,15 @@ class Server(Thread):
'CALIBRE_WORKER_KEY' : hexlify(self.auth_key), 'CALIBRE_WORKER_KEY' : hexlify(self.auth_key),
'CALIBRE_WORKER_RESULT' : hexlify(rfile.encode('utf-8')), 'CALIBRE_WORKER_RESULT' : hexlify(rfile.encode('utf-8')),
} }
cw = self.do_launch(env, gui, redirect_output, rfile) cw = self.do_launch(env, gui, redirect_output, rfile, job_name=job_name)
if isinstance(cw, basestring): if isinstance(cw, basestring):
raise CriticalError('Failed to launch worker process:\n'+cw) raise CriticalError('Failed to launch worker process:\n'+cw)
if DEBUG: if DEBUG:
print 'Worker Launch took:', time.time() - start print 'Worker Launch took:', time.time() - start
return cw return cw
def do_launch(self, env, gui, redirect_output, rfile): def do_launch(self, env, gui, redirect_output, rfile, job_name=None):
w = Worker(env, gui=gui) w = Worker(env, gui=gui, job_name=job_name)
try: try:
w(redirect_output=redirect_output) w(redirect_output=redirect_output)
@ -204,7 +204,7 @@ class Server(Thread):
self.add_jobs_queue.put(job) self.add_jobs_queue.put(job)
def run_job(self, job, gui=True, redirect_output=False): def run_job(self, job, gui=True, redirect_output=False):
w = self.launch_worker(gui=gui, redirect_output=redirect_output) w = self.launch_worker(gui=gui, redirect_output=redirect_output, job_name=getattr(job, 'name', None))
w.start_job(job) w.start_job(job)
def run(self): def run(self):