Automatically fallback to Qt dialog if native dialog fails

This commit is contained in:
Kovid Goyal 2017-08-02 20:40:58 +05:30
parent 3aeaf65f3b
commit 674c3e98f8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -8,6 +8,7 @@ import functools
import os import os
import subprocess import subprocess
import sys import sys
import time
from threading import Thread from threading import Thread
from PyQt5.Qt import QEventLoop from PyQt5.Qt import QEventLoop
@ -270,29 +271,45 @@ def zenity_choose_images(window, name, title, select_only_single_file=True, form
# }}} # }}}
def show_dialog(func): def linux_native_dialog(name):
prefix = check_for_linux_native_dialogs()
func = globals()['{}_choose_{}'.format(prefix, name)]
@functools.wraps(func) @functools.wraps(func)
def looped(window, *args, **kwargs): def looped(window, *args, **kwargs):
if window is None: if hasattr(linux_native_dialog, 'native_failed'):
return func(window, *args, **kwargs) import importlib
ret = [None, None] m = importlib.import_module('calibre.gui2.qt_file_dialogs')
loop = QEventLoop(window) qfunc = getattr(m, 'choose_' + name)
return qfunc(window, *args, **kwargs)
try:
if window is None:
return func(window, *args, **kwargs)
ret = [None, None]
loop = QEventLoop(window)
def r(): def r():
try: while not loop.isRunning():
ret[0] = func(window, *args, **kwargs) time.sleep(0.001) # yield so that loop starts
except: try:
ret[1] = sys.exc_info() ret[0] = func(window, *args, **kwargs)
finally: except:
ret[1] = sys.exc_info()
sys.exc_clear()
loop.quit() loop.quit()
t = Thread(name='FileDialogHelper', target=r) t = Thread(name='FileDialogHelper', target=r)
t.daemon = True t.daemon = True
t.start() t.start()
loop.exec_(QEventLoop.ExcludeUserInputEvents) loop.exec_(QEventLoop.ExcludeUserInputEvents)
if ret[1] is not None: if ret[1] is not None:
raise ret[1][0], ret[1][1], ret[1][2] raise ret[1][0], ret[1][1], ret[1][2]
return ret[0] return ret[0]
except Exception:
linux_native_dialog.native_failed = True
import traceback
traceback.print_exc()
return looped(window, *args, **kwargs)
return looped return looped
@ -315,11 +332,6 @@ def check_for_linux_native_dialogs():
return ans return ans
def linux_native_dialog(name):
prefix = check_for_linux_native_dialogs()
return show_dialog(globals()['{}_choose_{}'.format(prefix, name)])
if __name__ == '__main__': if __name__ == '__main__':
print(repr(kdialog_choose_dir(None, 'testkddcd', 'Testing choose dir...'))) print(repr(kdialog_choose_dir(None, 'testkddcd', 'Testing choose dir...')))
# print(repr(kdialog_choose_files(None, 'testkddcf', 'Testing choose files...', select_only_single_file=True, filters=[ # print(repr(kdialog_choose_files(None, 'testkddcf', 'Testing choose files...', select_only_single_file=True, filters=[