mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Add item to Preferences menu to restart calibre in debug mode. Fixes #7359 (Make debug mode accessible from within the GUI)
This commit is contained in:
parent
29dd71b130
commit
3960f3d6f3
@ -23,6 +23,12 @@ Run an embedded python interpreter.
|
|||||||
help='Debug the specified device driver.')
|
help='Debug the specified device driver.')
|
||||||
parser.add_option('-g', '--gui', default=False, action='store_true',
|
parser.add_option('-g', '--gui', default=False, action='store_true',
|
||||||
help='Run the GUI',)
|
help='Run the GUI',)
|
||||||
|
parser.add_option('--gui-debug', default=None,
|
||||||
|
help='Run the GUI with a debug console, logging to the'
|
||||||
|
' specified path',)
|
||||||
|
parser.add_option('--show-gui-debug', default=None,
|
||||||
|
help='Display the specified log file.',)
|
||||||
|
|
||||||
parser.add_option('-w', '--viewer', default=False, action='store_true',
|
parser.add_option('-w', '--viewer', default=False, action='store_true',
|
||||||
help='Run the ebook viewer',)
|
help='Run the ebook viewer',)
|
||||||
parser.add_option('--paths', default=False, action='store_true',
|
parser.add_option('--paths', default=False, action='store_true',
|
||||||
@ -135,7 +141,28 @@ def add_simple_plugin(path_to_plugin):
|
|||||||
os.chdir(odir)
|
os.chdir(odir)
|
||||||
shutil.rmtree(tdir)
|
shutil.rmtree(tdir)
|
||||||
|
|
||||||
|
def run_debug_gui(logpath):
|
||||||
|
import time, platform
|
||||||
|
time.sleep(3) # Give previous GUI time to shutdown fully and release locks
|
||||||
|
from calibre.constants import __appname__, __version__, isosx
|
||||||
|
print __appname__, _('Debug log')
|
||||||
|
print __appname__, __version__
|
||||||
|
print platform.platform()
|
||||||
|
print platform.system()
|
||||||
|
print platform.system_alias(platform.system(), platform.release(),
|
||||||
|
platform.version())
|
||||||
|
print 'Python', platform.python_version()
|
||||||
|
try:
|
||||||
|
if iswindows:
|
||||||
|
print 'Windows:', platform.win32_ver()
|
||||||
|
elif isosx:
|
||||||
|
print 'OSX:', platform.mac_ver()
|
||||||
|
else:
|
||||||
|
print 'Linux:', platform.linux_distribution()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
from calibre.gui2.main import main
|
||||||
|
main(['__CALIBRE_GUI_DEBUG__', logpath])
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
from calibre.constants import debug
|
from calibre.constants import debug
|
||||||
@ -154,6 +181,20 @@ def main(args=sys.argv):
|
|||||||
if opts.gui:
|
if opts.gui:
|
||||||
from calibre.gui2.main import main
|
from calibre.gui2.main import main
|
||||||
main(['calibre'])
|
main(['calibre'])
|
||||||
|
elif opts.gui_debug is not None:
|
||||||
|
run_debug_gui(opts.gui_debug)
|
||||||
|
elif opts.show_gui_debug:
|
||||||
|
import time, re
|
||||||
|
time.sleep(1)
|
||||||
|
from calibre.gui2 import open_local_file
|
||||||
|
if iswindows:
|
||||||
|
with open(opts.show_gui_debug, 'r+b') as f:
|
||||||
|
raw = f.read()
|
||||||
|
raw = re.sub('(?<!\r)\n', '\r\n', raw)
|
||||||
|
f.seek(0)
|
||||||
|
f.truncate()
|
||||||
|
f.write(raw)
|
||||||
|
open_local_file(opts.show_gui_debug)
|
||||||
elif opts.viewer:
|
elif opts.viewer:
|
||||||
from calibre.gui2.viewer.main import main
|
from calibre.gui2.viewer.main import main
|
||||||
vargs = ['ebook-viewer', '--debug-javascript']
|
vargs = ['ebook-viewer', '--debug-javascript']
|
||||||
|
@ -10,6 +10,7 @@ from PyQt4.Qt import QIcon, QMenu, Qt
|
|||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
from calibre.gui2.preferences.main import Preferences
|
from calibre.gui2.preferences.main import Preferences
|
||||||
from calibre.gui2 import error_dialog
|
from calibre.gui2 import error_dialog
|
||||||
|
from calibre.constants import DEBUG
|
||||||
|
|
||||||
class PreferencesAction(InterfaceAction):
|
class PreferencesAction(InterfaceAction):
|
||||||
|
|
||||||
@ -22,6 +23,10 @@ class PreferencesAction(InterfaceAction):
|
|||||||
pm.addAction(QIcon(I('config.png')), _('Preferences'), self.do_config)
|
pm.addAction(QIcon(I('config.png')), _('Preferences'), self.do_config)
|
||||||
pm.addAction(QIcon(I('wizard.png')), _('Run welcome wizard'),
|
pm.addAction(QIcon(I('wizard.png')), _('Run welcome wizard'),
|
||||||
self.gui.run_wizard)
|
self.gui.run_wizard)
|
||||||
|
if not DEBUG:
|
||||||
|
pm.addSeparator()
|
||||||
|
pm.addAction(QIcon(I('debug.png')), _('Restart in debug mode'),
|
||||||
|
self.debug_restart)
|
||||||
self.qaction.setMenu(pm)
|
self.qaction.setMenu(pm)
|
||||||
self.preferences_menu = pm
|
self.preferences_menu = pm
|
||||||
for x in (self.gui.preferences_action, self.qaction):
|
for x in (self.gui.preferences_action, self.qaction):
|
||||||
@ -44,4 +49,6 @@ class PreferencesAction(InterfaceAction):
|
|||||||
d.run_wizard_requested.connect(self.gui.run_wizard,
|
d.run_wizard_requested.connect(self.gui.run_wizard,
|
||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
|
|
||||||
|
def debug_restart(self, *args):
|
||||||
|
self.gui.quit(restart=True, debug_on_restart=True)
|
||||||
|
|
||||||
|
@ -135,9 +135,10 @@ class GuiRunner(QObject):
|
|||||||
'''Make sure an event loop is running before starting the main work of
|
'''Make sure an event loop is running before starting the main work of
|
||||||
initialization'''
|
initialization'''
|
||||||
|
|
||||||
def __init__(self, opts, args, actions, listener, app):
|
def __init__(self, opts, args, actions, listener, app, gui_debug=None):
|
||||||
self.startup_time = time.time()
|
self.startup_time = time.time()
|
||||||
self.opts, self.args, self.listener, self.app = opts, args, listener, app
|
self.opts, self.args, self.listener, self.app = opts, args, listener, app
|
||||||
|
self.gui_debug = gui_debug
|
||||||
self.actions = actions
|
self.actions = actions
|
||||||
self.main = None
|
self.main = None
|
||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
@ -148,7 +149,7 @@ class GuiRunner(QObject):
|
|||||||
|
|
||||||
def start_gui(self):
|
def start_gui(self):
|
||||||
from calibre.gui2.ui import Main
|
from calibre.gui2.ui import Main
|
||||||
main = Main(self.opts)
|
main = Main(self.opts, gui_debug=self.gui_debug)
|
||||||
if self.splash_screen is not None:
|
if self.splash_screen is not None:
|
||||||
self.splash_screen.showMessage(_('Initializing user interface...'))
|
self.splash_screen.showMessage(_('Initializing user interface...'))
|
||||||
self.splash_screen.finish(main)
|
self.splash_screen.finish(main)
|
||||||
@ -249,21 +250,39 @@ class GuiRunner(QObject):
|
|||||||
|
|
||||||
self.initialize_db()
|
self.initialize_db()
|
||||||
|
|
||||||
|
def run_in_debug_mode(logpath=None):
|
||||||
|
e = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
|
||||||
|
import tempfile, subprocess
|
||||||
|
fd, logpath = tempfile.mkstemp('.txt')
|
||||||
|
|
||||||
|
if hasattr(sys, 'frameworks_dir'):
|
||||||
|
base = os.path.dirname(sys.frameworks_dir)
|
||||||
|
if 'console.app' not in base:
|
||||||
|
base = os.path.join(base, 'console.app', 'Contents')
|
||||||
|
exe = os.path.basename(e)
|
||||||
|
exe = os.path.join(base, 'MacOS', exe+'-debug')
|
||||||
|
else:
|
||||||
|
base, ext = os.path.splitext(e)
|
||||||
|
exe = base + '-debug' + ext
|
||||||
|
print 'Starting debug executable:', exe
|
||||||
|
subprocess.Popen([exe, '--gui-debug', logpath], stdout=fd, stderr=fd)
|
||||||
|
|
||||||
def run_gui(opts, args, actions, listener, app):
|
def run_gui(opts, args, actions, listener, app, gui_debug=None):
|
||||||
initialize_file_icon_provider()
|
initialize_file_icon_provider()
|
||||||
if not dynamic.get('welcome_wizard_was_run', False):
|
if not dynamic.get('welcome_wizard_was_run', False):
|
||||||
from calibre.gui2.wizard import wizard
|
from calibre.gui2.wizard import wizard
|
||||||
wizard().exec_()
|
wizard().exec_()
|
||||||
dynamic.set('welcome_wizard_was_run', True)
|
dynamic.set('welcome_wizard_was_run', True)
|
||||||
runner = GuiRunner(opts, args, actions, listener, app)
|
runner = GuiRunner(opts, args, actions, listener, app, gui_debug=gui_debug)
|
||||||
ret = app.exec_()
|
ret = app.exec_()
|
||||||
if getattr(runner.main, 'run_wizard_b4_shutdown', False):
|
if getattr(runner.main, 'run_wizard_b4_shutdown', False):
|
||||||
from calibre.gui2.wizard import wizard
|
from calibre.gui2.wizard import wizard
|
||||||
wizard().exec_()
|
wizard().exec_()
|
||||||
if getattr(runner.main, 'restart_after_quit', False):
|
if getattr(runner.main, 'restart_after_quit', False):
|
||||||
e = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
|
e = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
|
||||||
|
if getattr(runner.main, 'debug_on_restart', False):
|
||||||
|
run_in_debug_mode()
|
||||||
|
else:
|
||||||
print 'Restarting with:', e, sys.argv
|
print 'Restarting with:', e, sys.argv
|
||||||
if hasattr(sys, 'frameworks_dir'):
|
if hasattr(sys, 'frameworks_dir'):
|
||||||
app = os.path.dirname(os.path.dirname(sys.frameworks_dir))
|
app = os.path.dirname(os.path.dirname(sys.frameworks_dir))
|
||||||
@ -277,6 +296,10 @@ def run_gui(opts, args, actions, listener, app):
|
|||||||
runner.main.system_tray_icon.hide()
|
runner.main.system_tray_icon.hide()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
if runner.main.gui_debug is not None:
|
||||||
|
e = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
|
||||||
|
import subprocess
|
||||||
|
subprocess.Popen([e, '--show-gui-debug', runner.main.gui_debug])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def cant_start(msg=_('If you are sure it is not running')+', ',
|
def cant_start(msg=_('If you are sure it is not running')+', ',
|
||||||
@ -317,6 +340,11 @@ def communicate(args):
|
|||||||
|
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
|
gui_debug = None
|
||||||
|
if args[0] == '__CALIBRE_GUI_DEBUG__':
|
||||||
|
gui_debug = args[1]
|
||||||
|
args = ['calibre']
|
||||||
|
|
||||||
app, opts, args, actions = init_qt(args)
|
app, opts, args, actions = init_qt(args)
|
||||||
from calibre.utils.lock import singleinstance
|
from calibre.utils.lock import singleinstance
|
||||||
from multiprocessing.connection import Listener
|
from multiprocessing.connection import Listener
|
||||||
@ -333,9 +361,11 @@ def main(args=sys.argv):
|
|||||||
except socket.error:
|
except socket.error:
|
||||||
cant_start()
|
cant_start()
|
||||||
else:
|
else:
|
||||||
return run_gui(opts, args, actions, listener, app)
|
return run_gui(opts, args, actions, listener, app,
|
||||||
|
gui_debug=gui_debug)
|
||||||
else:
|
else:
|
||||||
return run_gui(opts, args, actions, listener, app)
|
return run_gui(opts, args, actions, listener, app,
|
||||||
|
gui_debug=gui_debug)
|
||||||
otherinstance = False
|
otherinstance = False
|
||||||
try:
|
try:
|
||||||
listener = Listener(address=ADDRESS)
|
listener = Listener(address=ADDRESS)
|
||||||
@ -345,8 +375,7 @@ def main(args=sys.argv):
|
|||||||
# On windows only singleinstance can be trusted
|
# On windows only singleinstance can be trusted
|
||||||
otherinstance = True if iswindows else False
|
otherinstance = True if iswindows else False
|
||||||
if not otherinstance:
|
if not otherinstance:
|
||||||
sys.setcheckinterval(50) # Make GUI more responsive
|
return run_gui(opts, args, actions, listener, app, gui_debug=gui_debug)
|
||||||
return run_gui(opts, args, actions, listener, app)
|
|
||||||
|
|
||||||
communicate(args)
|
communicate(args)
|
||||||
|
|
||||||
|
@ -96,10 +96,11 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
'The main GUI'
|
'The main GUI'
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, opts, parent=None):
|
def __init__(self, opts, parent=None, gui_debug=None):
|
||||||
MainWindow.__init__(self, opts, parent)
|
MainWindow.__init__(self, opts, parent)
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.device_connected = None
|
self.device_connected = None
|
||||||
|
self.gui_debug = gui_debug
|
||||||
acmap = OrderedDict()
|
acmap = OrderedDict()
|
||||||
for action in interface_actions():
|
for action in interface_actions():
|
||||||
ac = action.load_actual_plugin(self)
|
ac = action.load_actual_plugin(self)
|
||||||
@ -261,6 +262,14 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
for ac in self.iactions.values():
|
for ac in self.iactions.values():
|
||||||
ac.initialization_complete()
|
ac.initialization_complete()
|
||||||
|
|
||||||
|
if show_gui and self.gui_debug is not None:
|
||||||
|
info_dialog(self, _('Debug mode'), '<p>' +
|
||||||
|
_('You have started calibre in debug mode. After you '
|
||||||
|
'quit calibre, the debug log will be available in '
|
||||||
|
'the file: %s<p>The '
|
||||||
|
'log will be displayed automatically.')%self.gui_debug, show=True)
|
||||||
|
|
||||||
|
|
||||||
def start_content_server(self):
|
def start_content_server(self):
|
||||||
from calibre.library.server.main import start_threaded_server
|
from calibre.library.server.main import start_threaded_server
|
||||||
from calibre.library.server import server_config
|
from calibre.library.server import server_config
|
||||||
@ -495,7 +504,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
dynamic.set('sort_history', self.library_view.model().sort_history)
|
dynamic.set('sort_history', self.library_view.model().sort_history)
|
||||||
self.save_layout_state()
|
self.save_layout_state()
|
||||||
|
|
||||||
def quit(self, checked=True, restart=False):
|
def quit(self, checked=True, restart=False, debug_on_restart=False):
|
||||||
if not self.confirm_quit():
|
if not self.confirm_quit():
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -503,6 +512,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.restart_after_quit = restart
|
self.restart_after_quit = restart
|
||||||
|
self.debug_on_restart = debug_on_restart
|
||||||
QApplication.instance().quit()
|
QApplication.instance().quit()
|
||||||
|
|
||||||
def donate(self, *args):
|
def donate(self, *args):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user