diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index a27f510837..375e42ece4 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -803,6 +803,20 @@ def load_builtin_fonts(): if u'calibre Symbols' in fam: _rating_font = u'calibre Symbols' +def setup_gui_option_parser(parser): + if islinux: + parser.add_option('--detach', default=False, action='store_true', + help='Detach from the controlling terminal, if any (linux only)') + +def detach_gui(): + if islinux and not DEBUG and sys.stdout.isatty(): + # We are a GUI process running in a terminal so detach from the controlling terminal + if os.fork() != 0: + raise SystemExit(0) + os.setsid() + so, se = file(os.devnull, 'a+'), file(os.devnull, 'a+', 0) + os.dup2(so.fileno(), sys.__stdout__.fileno()) + os.dup2(se.fileno(), sys.__stderr__.fileno()) class Application(QApplication): @@ -824,7 +838,6 @@ class Application(QApplication): self._file_open_paths = [] self._file_open_lock = RLock() self.setup_styles(force_calibre_style) - if DEBUG: def notify(self, receiver, event): if self.redirect_notify: diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 10bc6c464c..7eeb295220 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -12,8 +12,9 @@ from calibre import prints, plugins, force_unicode from calibre.constants import (iswindows, __appname__, isosx, DEBUG, islinux, filesystem_encoding, get_portable_base) from calibre.utils.ipc import gui_socket_address, RC -from calibre.gui2 import (ORG_NAME, APP_UID, initialize_file_icon_provider, - Application, choose_dir, error_dialog, question_dialog, gprefs) +from calibre.gui2 import ( + ORG_NAME, APP_UID, initialize_file_icon_provider, Application, choose_dir, + error_dialog, question_dialog, gprefs, detach_gui, setup_gui_option_parser) from calibre.gui2.main_window import option_parser as _option_parser from calibre.utils.config import prefs, dynamic @@ -46,6 +47,7 @@ path_to_ebook to the database. help=_('Cause a running calibre instance, if any, to be' ' shutdown. Note that if there are running jobs, they ' 'will be silently aborted, so use with care.')) + setup_gui_option_parser(parser) return parser def find_portable_library(): @@ -84,6 +86,8 @@ def find_portable_library(): def init_qt(args): parser = option_parser() opts, args = parser.parse_args(args) + if getattr(opts, 'detach', False): + detach_gui() find_portable_library() if opts.with_library is not None: libpath = os.path.expanduser(opts.with_library) diff --git a/src/calibre/gui2/tweak_book/main.py b/src/calibre/gui2/tweak_book/main.py index be5aca6eb8..d414152c21 100644 --- a/src/calibre/gui2/tweak_book/main.py +++ b/src/calibre/gui2/tweak_book/main.py @@ -11,17 +11,20 @@ import sys, os from PyQt4.Qt import QIcon from calibre.constants import islinux -from calibre.gui2 import Application, ORG_NAME, APP_UID +from calibre.gui2 import Application, ORG_NAME, APP_UID, setup_gui_option_parser, detach_gui from calibre.ptempfile import reset_base_dir from calibre.utils.config import OptionParser from calibre.gui2.tweak_book.ui import Main def option_parser(): - return OptionParser('''\ + parser = OptionParser('''\ %prog [opts] [path_to_ebook] Launch the calibre tweak book tool. ''') + setup_gui_option_parser(parser) + return parser + def main(args=sys.argv): # Ensure we can continue to function if GUI is closed @@ -30,6 +33,8 @@ def main(args=sys.argv): parser = option_parser() opts, args = parser.parse_args(args) + if getattr(opts, 'detach', False): + detach_gui() override = 'calibre-tweak-book' if islinux else None app = Application(args, override_program_name=override) app.load_builtin_fonts() diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index ccb504b374..954df0ebe7 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -18,7 +18,7 @@ from calibre.gui2.viewer.toc import TOC from calibre.gui2.widgets import ProgressIndicator from calibre.gui2.main_window import MainWindow from calibre.gui2 import (Application, ORG_NAME, APP_UID, choose_files, - info_dialog, error_dialog, open_url, available_height) + info_dialog, error_dialog, open_url, available_height, setup_gui_option_parser, detach_gui) from calibre.ebooks.oeb.iterator.book import EbookIterator from calibre.ebooks import DRMError from calibre.constants import islinux, filesystem_encoding @@ -1183,11 +1183,13 @@ def config(defaults=None): def option_parser(): c = config() - return c.option_parser(usage=_('''\ + parser = c.option_parser(usage=_('''\ %prog [options] file View an ebook. ''')) + setup_gui_option_parser(parser) + return parser def main(args=sys.argv): @@ -1197,6 +1199,8 @@ def main(args=sys.argv): parser = option_parser() opts, args = parser.parse_args(args) + if getattr(opts, 'detach', False): + detach_gui() try: open_at = float(opts.open_at) except: