From 0348bbe41d9f8bb2685f3de846c971c058e71239 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 10 Nov 2013 09:44:29 +0530 Subject: [PATCH] Windows: Dont launch calibre as an external viewer Windows: When viewing books with an external viewer, check if windows will open the file with calibre itself, and if so, popup an error message telling the user to install some software capable of viewing the file. Fixes #1249698 [Opening a PDF in calibre changes the default "Open with" app](https://bugs.launchpad.net/calibre/+bug/1249698) --- src/calibre/gui2/actions/view.py | 31 +++++++++++++++++++++----- src/calibre/utils/file_associations.py | 15 +++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/calibre/utils/file_associations.py diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 55e07533c3..05296cd065 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -10,9 +10,9 @@ from functools import partial from PyQt4.Qt import Qt, QAction, pyqtSignal -from calibre.constants import isosx -from calibre.gui2 import error_dialog, Dispatcher, question_dialog, config, \ - open_local_file, info_dialog +from calibre.constants import isosx, iswindows +from calibre.gui2 import ( + error_dialog, Dispatcher, question_dialog, config, open_local_file, info_dialog) from calibre.gui2.dialogs.choose_format import ChooseFormatDialog from calibre.utils.config import prefs, tweaks from calibre.ptempfile import PersistentTemporaryFile @@ -119,8 +119,26 @@ class ViewAction(InterfaceAction): self.gui.job_manager.launch_gui_app(viewer, kwargs=dict(args=args)) else: + if iswindows: + from calibre.utils.file_associations import file_assoc_windows + ext = name.rpartition('.')[-1] + if ext: + try: + prog = file_assoc_windows(ext) + except Exception: + prog = None + if prog and prog.lower().endswith('calibre.exe'): + name = os.path.basename(name) + return error_dialog( + self.gui, _('No associated program'), _( + 'Windows will try to open %s with calibre itself' + ' resulting in a duplicate in your calibre library. You' + ' should install some program capable of viewing this' + ' file format and tell windows to use that program to open' + ' files of this type.') % name, show=True) + open_local_file(name) - time.sleep(2) # User feedback + time.sleep(2) # User feedback finally: self.gui.unsetCursor() @@ -145,7 +163,8 @@ class ViewAction(InterfaceAction): all_fmts = set([]) for x in formats: if x: - for f in x: all_fmts.add(f) + for f in x: + all_fmts.add(f) if not all_fmts: error_dialog(self.gui, _('Format unavailable'), _('Selected books have no formats'), show=True) @@ -257,7 +276,7 @@ class ViewAction(InterfaceAction): self.build_menus(db) def view_device_book(self, path): - pt = PersistentTemporaryFile('_view_device_book'+\ + pt = PersistentTemporaryFile('_view_device_book'+ os.path.splitext(path)[1]) self.persistent_files.append(pt) pt.close() diff --git a/src/calibre/utils/file_associations.py b/src/calibre/utils/file_associations.py new file mode 100644 index 0000000000..c954418039 --- /dev/null +++ b/src/calibre/utils/file_associations.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal ' + +def file_assoc_windows(ft): + # See the IQueryAssociations::GetString method documentation on MSDN + from win32com.shell import shell, shellcon + a = shell.AssocCreate() + a.Init(0, '.' + ft.lower()) + return a.GetString(0, shellcon.ASSOCSTR_EXECUTABLE) +