%PDF- %PDF-
| Direktori : /lib/calibre/calibre/gui2/ |
| Current File : //lib/calibre/calibre/gui2/qt_file_dialogs.py |
#!/usr/bin/env python3
# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
import os
from qt.core import QFileDialog, QObject
from calibre.gui2.linux_file_dialogs import dialog_name, image_extensions
from polyglot.builtins import string_or_bytes
from polyglot.urllib import unquote
def select_initial_dir(q):
while q:
c = os.path.dirname(q)
if c == q:
break
if os.path.exists(c):
return c
q = c
return os.path.expanduser('~')
class Dummy:
def __enter__(self):
pass
def __exit__(self, *a):
pass
class FileDialog(QObject):
def __init__(
self, title=_('Choose Files'),
filters=[],
add_all_files_filter=True,
parent=None,
modal=True,
name='',
mode=QFileDialog.FileMode.ExistingFiles,
default_dir='~',
no_save_dir=False,
combine_file_and_saved_dir=False
):
from calibre.gui2 import dynamic, sanitize_env_vars
from calibre.gui2.ui import get_gui
gui = get_gui()
adapt_menubar = gui.bars_manager.adapt_menu_bar_for_dialog if gui is not None else Dummy()
QObject.__init__(self)
ftext = ''
has_long_filter = False
if filters:
for filter in filters:
text, extensions = filter
if not extensions or (len(extensions) == 1 and extensions[0] == '*'):
extensions = ['*']
else:
extensions = ['*'+(i if i.startswith('.') else '.'+i) for i in
extensions]
etext = '%s (%s);;'%(text, ' '.join(extensions))
if len(etext) > 72:
has_long_filter = True
ftext += etext
if add_all_files_filter or not ftext:
ftext += 'All files (*)'
if ftext.endswith(';;'):
ftext = ftext[:-2]
self.dialog_name = dialog_name(name, title)
self.selected_files = None
self.fd = None
if combine_file_and_saved_dir:
bn = os.path.basename(default_dir)
prev = dynamic.get(self.dialog_name,
os.path.expanduser('~'))
if os.path.exists(prev):
if os.path.isfile(prev):
prev = os.path.dirname(prev)
else:
prev = os.path.expanduser('~')
initial_dir = os.path.join(prev, bn)
elif no_save_dir:
initial_dir = os.path.expanduser(default_dir)
else:
initial_dir = dynamic.get(self.dialog_name,
os.path.expanduser(default_dir))
if not isinstance(initial_dir, string_or_bytes):
initial_dir = os.path.expanduser(default_dir)
if not initial_dir or (not os.path.exists(initial_dir) and not (
mode == QFileDialog.FileMode.AnyFile and (no_save_dir or combine_file_and_saved_dir))):
initial_dir = select_initial_dir(initial_dir)
self.selected_files = []
use_native_dialog = 'CALIBRE_NO_NATIVE_FILEDIALOGS' not in os.environ
with sanitize_env_vars():
opts = QFileDialog.Option()
if not use_native_dialog:
opts |= QFileDialog.Option.DontUseNativeDialog
if has_long_filter:
opts |= QFileDialog.Option.HideNameFilterDetails
if mode == QFileDialog.FileMode.AnyFile:
with adapt_menubar:
f = QFileDialog.getSaveFileName(parent, title,
initial_dir, ftext, "", opts)
if f and f[0]:
self.selected_files.append(f[0])
elif mode == QFileDialog.FileMode.ExistingFile:
with adapt_menubar:
f = QFileDialog.getOpenFileName(parent, title,
initial_dir, ftext, "", opts)
if f and f[0] and os.path.exists(f[0]):
self.selected_files.append(f[0])
elif mode == QFileDialog.FileMode.ExistingFiles:
with adapt_menubar:
fs = QFileDialog.getOpenFileNames(parent, title, initial_dir,
ftext, "", opts)
if fs and fs[0]:
for f in fs[0]:
f = str(f)
if not f:
continue
if not os.path.exists(f):
# QFileDialog for some reason quotes spaces
# on linux if there is more than one space in a row
f = unquote(f)
if f and os.path.exists(f):
self.selected_files.append(f)
else:
if mode == QFileDialog.FileMode.Directory:
opts |= QFileDialog.Option.ShowDirsOnly
with adapt_menubar:
f = str(QFileDialog.getExistingDirectory(parent, title, initial_dir, opts))
if os.path.exists(f):
self.selected_files.append(f)
if self.selected_files:
self.selected_files = [str(q) for q in self.selected_files]
saved_loc = self.selected_files[0]
if os.path.isfile(saved_loc):
saved_loc = os.path.dirname(saved_loc)
if not no_save_dir:
dynamic[self.dialog_name] = saved_loc
self.accepted = bool(self.selected_files)
def get_files(self):
if self.selected_files is None:
return tuple(os.path.abspath(str(i)) for i in self.fd.selectedFiles())
return tuple(self.selected_files)
def choose_dir(window, name, title, default_dir='~', no_save_dir=False):
fd = FileDialog(title=title, filters=[], add_all_files_filter=False,
parent=window, name=name, mode=QFileDialog.FileMode.Directory,
default_dir=default_dir, no_save_dir=no_save_dir)
dir = fd.get_files()
fd.setParent(None)
if dir:
return dir[0]
def choose_files(window, name, title,
filters=[], all_files=True, select_only_single_file=False, default_dir='~'):
'''
Ask user to choose a bunch of files.
:param name: Unique dialog name used to store the opened directory
:param title: Title to show in dialogs titlebar
:param filters: list of allowable extensions. Each element of the list
must be a 2-tuple with first element a string describing
the type of files to be filtered and second element a list
of extensions.
:param all_files: If True add All files to filters.
:param select_only_single_file: If True only one file can be selected
'''
mode = QFileDialog.FileMode.ExistingFile if select_only_single_file else QFileDialog.FileMode.ExistingFiles
fd = FileDialog(title=title, name=name, filters=filters, default_dir=default_dir,
parent=window, add_all_files_filter=all_files, mode=mode,
)
fd.setParent(None)
if fd.accepted:
return fd.get_files()
return None
def choose_save_file(window, name, title, filters=[], all_files=True, initial_path=None, initial_filename=None):
'''
Ask user to choose a file to save to. Can be a non-existent file.
:param filters: list of allowable extensions. Each element of the list
must be a 2-tuple with first element a string describing
the type of files to be filtered and second element a list
of extensions.
:param all_files: If True add All files to filters.
:param initial_path: The initially selected path (does not need to exist). Cannot be used with initial_filename.
:param initial_filename: If specified, the initially selected path is this filename in the previously used directory. Cannot be used with initial_path.
'''
kwargs = dict(title=title, name=name, filters=filters,
parent=window, add_all_files_filter=all_files, mode=QFileDialog.FileMode.AnyFile)
if initial_path is not None:
kwargs['no_save_dir'] = True
kwargs['default_dir'] = initial_path
elif initial_filename is not None:
kwargs['combine_file_and_saved_dir'] = True
kwargs['default_dir'] = initial_filename
fd = FileDialog(**kwargs)
fd.setParent(None)
ans = None
if fd.accepted:
ans = fd.get_files()
if ans:
ans = ans[0]
return ans
def choose_images(window, name, title, select_only_single_file=True, formats=None):
mode = QFileDialog.FileMode.ExistingFile if select_only_single_file else QFileDialog.FileMode.ExistingFiles
if formats is None:
formats = image_extensions()
fd = FileDialog(title=title, name=name,
filters=[(_('Images'), list(formats))],
parent=window, add_all_files_filter=False, mode=mode,
)
fd.setParent(None)
if fd.accepted:
return fd.get_files()
return None