diff --git a/resources/calibre-mimetypes.xml b/resources/calibre-mimetypes.xml new file mode 100644 index 0000000000..c44c9092f0 --- /dev/null +++ b/resources/calibre-mimetypes.xml @@ -0,0 +1,42 @@ + + + + SONY E-book compiled format + + + + EPUB ebook format + + + + SONY E-book source format + + + + Amazon Mobipocket e-book format + + + + + Amazon Topaz ebook format + + + + + Amazon Kindle Application (Kindlet) + + + + + Amazon Mobipocket ebook newspaper format + + + + + + + Amazon KF8 ebook format + + + + diff --git a/src/calibre/linux.py b/src/calibre/linux.py index 64da046e58..61fd029bf0 100644 --- a/src/calibre/linux.py +++ b/src/calibre/linux.py @@ -84,42 +84,76 @@ class PreserveMIMEDefaults(object): # Uninstall script {{{ UNINSTALL = '''\ #!{python} +from __future__ import print_function, unicode_literals euid = {euid} import os, subprocess, shutil -if os.geteuid() != euid: - print 'WARNING: uninstaller must be run as', euid, 'to remove all files' +try: + raw_input +except NameError: + raw_input = input -for x in {manifest!r}: - if not os.path.exists(x): continue - print 'Removing', x +if os.geteuid() != euid: + print ('The installer was last run as user id:', euid, 'To remove all files you must run the uninstaller as the same user') + if raw_input('Proceed anyway? [y/n]:').lower() != 'y': + raise SystemExit(1) + +frozen_path = {frozen_path!r} +if not frozen_path or not os.path.exists(os.path.join(frozen_path, 'resources', 'calibre-mimetypes.xml')): + frozen_path = None + +for x in tuple({manifest!r}) + tuple({appdata_resources!r}) + (os.path.abspath(__file__), __file__, frozen_path): + if not x or not os.path.exists(x): + continue + print ('Removing', x) try: if os.path.isdir(x): shutil.rmtree(x) else: os.unlink(x) except Exception as e: - print 'Failed to delete', x - print '\t', e + print ('Failed to delete', x) + print ('\t', e) icr = {icon_resources!r} -for context, name, size in icr: +mimetype_icons = [] + +def remove_icon(context, name, size, update=False): cmd = ['xdg-icon-resource', 'uninstall', '--context', context, '--size', size, name] - if (context, name) != icr[-1]: + if not update: cmd.insert(2, '--noupdate') + print ('Removing icon:', name, 'from context:', context, 'at size:', size) ret = subprocess.call(cmd) if ret != 0: - print 'WARNING: Failed to remove icon', name + print ('WARNING: Failed to remove icon', name) + +for i, (context, name, size) in enumerate(icr): + if context == 'mimetypes': + mimetype_icons.append((name, size)) + continue + remove_icon(context, name, size, update=i == len(icr) - 1) mr = {menu_resources!r} for f in mr: cmd = ['xdg-desktop-menu', 'uninstall', f] + print ('Removing desktop file:', f) ret = subprocess.call(cmd) if ret != 0: - print 'WARNING: Failed to remove menu item', f + print ('WARNING: Failed to remove menu item', f) -os.remove(os.path.abspath(__file__)) +for f in {mime_resources!r}: + cmd = ['xdg-mime', 'uninstall', f] + print ('Removing mime resource:', os.path.basename(f)) + ret = subprocess.call(cmd) + if ret != 0: + print ('WARNING: Failed to remove mime resource', f) + +print () + +if mimetype_icons and raw_input('Remove the ebook format icons? [y/n]:').lower() in ['', 'y']: + for i, (name, size) in enumerate(mimetype_icons): + remove_icon('mimetypes', name, size, update=i == len(mimetype_icons) - 1) ''' # }}} @@ -447,6 +481,7 @@ class PostInstall: self.icon_resources = [] self.menu_resources = [] self.mime_resources = [] + self.appdata_resources = [] if islinux or isbsd: self.setup_completion() if islinux or isbsd: @@ -472,9 +507,12 @@ class PostInstall: def create_uninstaller(self): dest = os.path.join(self.opts.staging_bindir, 'calibre-uninstall') - raw = UNINSTALL.format(python=os.path.abspath(sys.executable), euid=os.geteuid(), - manifest=self.manifest, icon_resources=self.icon_resources, - menu_resources=self.menu_resources) + self.info('Creating un-installer:', dest) + raw = UNINSTALL.format( + python='/usr/bin/python', euid=os.geteuid(), + manifest=self.manifest, icon_resources=self.icon_resources, + mime_resources=self.mime_resources, menu_resources=self.menu_resources, + appdata_resources=self.appdata_resources, frozen_path=getattr(sys, 'frozen_path', None)) try: with open(dest, 'wb') as f: f.write(raw) @@ -677,13 +715,13 @@ class PostInstall: self.icon_resources.append(('mimetypes', 'application-x-mobi8-ebook', '128')) render_img('lt.png', 'calibre-gui.png', width=256, height=256) cc('xdg-icon-resource install --noupdate --size 256 calibre-gui.png calibre-gui', shell=True) - self.icon_resources.append(('apps', 'calibre-gui', '128')) - render_img('viewer.png', 'calibre-viewer.png') - cc('xdg-icon-resource install --size 128 calibre-viewer.png calibre-viewer', shell=True) - self.icon_resources.append(('apps', 'calibre-viewer', '128')) - render_img('tweak.png', 'calibre-ebook-edit.png') - cc('xdg-icon-resource install --size 128 calibre-ebook-edit.png calibre-ebook-edit', shell=True) - self.icon_resources.append(('apps', 'calibre-ebook-edit', '128')) + self.icon_resources.append(('apps', 'calibre-gui', '256')) + render_img('viewer.png', 'calibre-viewer.png', width=256, height=256) + cc('xdg-icon-resource install --size 256 calibre-viewer.png calibre-viewer', shell=True) + self.icon_resources.append(('apps', 'calibre-viewer', '256')) + render_img('tweak.png', 'calibre-ebook-edit.png', width=256, height=256) + cc('xdg-icon-resource install --size 256 calibre-ebook-edit.png calibre-ebook-edit', shell=True) + self.icon_resources.append(('apps', 'calibre-ebook-edit', '256')) mimetypes = set([]) for x in all_input_formats(): @@ -731,13 +769,11 @@ class PostInstall: self.menu_resources.append(x) ak = x.partition('.')[0] if ak in APPDATA and os.access(appdata, os.W_OK): - write_appdata(ak, APPDATA[ak], appdata, translators) + self.appdata_resources.append(write_appdata(ak, APPDATA[ak], appdata, translators)) cc(['xdg-desktop-menu', 'forceupdate']) - f = open('calibre-mimetypes.xml', 'wb') - f.write(MIME) - f.close() - self.mime_resources.append('calibre-mimetypes.xml') - cc('xdg-mime install ./calibre-mimetypes.xml', shell=True) + MIME = P('calibre-mimetypes.xml') + self.mime_resources.append(MIME) + cc(['xdg-mime', 'install', MIME]) except Exception: if self.opts.fatal_errors: raise @@ -972,51 +1008,6 @@ def write_appdata(key, entry, base, translators): return fpath -MIME = '''\ - - - - SONY E-book compiled format - - - - EPUB ebook format - - - - SONY E-book source format - - - - Amazon Mobipocket e-book format - - - - - Amazon Topaz ebook format - - - - - Amazon Kindle Application (Kindlet) - - - - - Amazon Mobipocket ebook newspaper format - - - - - - - Amazon KF8 ebook format - - - - -''' - def render_img(image, dest, width=128, height=128): from PyQt4.Qt import QImage, Qt img = QImage(I(image)).scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)