%PDF- %PDF-
| Direktori : /usr/lib/calibre/calibre/gui2/dialogs/ |
| Current File : //usr/lib/calibre/calibre/gui2/dialogs/choose_library.py |
#!/usr/bin/env python3
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, errno
from threading import Thread, Event
from qt.core import QDialog, QTimer, Qt, pyqtSignal
from calibre.gui2.dialogs.choose_library_ui import Ui_Dialog
from calibre.gui2.dialogs.progress import ProgressDialog as PD
from calibre.gui2 import error_dialog, choose_dir
from calibre.constants import (filesystem_encoding, iswindows,
get_portable_base)
from calibre import isbytestring, patheq, force_unicode
class ProgressDialog(PD):
on_progress_update = pyqtSignal(object, object, object)
finished_moving = pyqtSignal()
def __init__(self, *args, **kwargs):
PD.__init__(self, *args, **kwargs)
self.on_progress_update.connect(self.progressed, type=Qt.ConnectionType.QueuedConnection)
self.finished_moving.connect(self.accept, type=Qt.ConnectionType.QueuedConnection)
def reject(self):
return
def progressed(self, item_name, count, total):
self.max = total
self.value = count
self.set_msg(item_name)
def show_new_progress(self, *args):
self.on_progress_update.emit(*args)
class ChooseLibrary(QDialog, Ui_Dialog):
def __init__(self, db, callback, parent):
QDialog.__init__(self, parent)
self.setupUi(self)
self.db = db
self.new_db = None
self.callback = callback
self.location.initialize('choose_library_dialog')
lp = db.library_path
if isbytestring(lp):
lp = lp.decode(filesystem_encoding)
loc = str(self.old_location.text()).format(lp)
self.old_location.setText(loc)
self.browse_button.clicked.connect(self.choose_loc)
self.empty_library.toggled.connect(self.empty_library_toggled)
self.copy_structure.setEnabled(False)
def empty_library_toggled(self, to_what):
self.copy_structure.setEnabled(to_what)
def choose_loc(self, *args):
base = get_portable_base()
if base is None:
loc = choose_dir(self, 'choose library location',
_('Choose location for calibre library'))
else:
name = force_unicode('choose library loc at' + base,
filesystem_encoding)
loc = choose_dir(self, name,
_('Choose location for calibre library'), default_dir=base,
no_save_dir=True)
if loc is not None:
self.location.setText(loc)
def check_action(self, ac, loc):
exists = self.db.exists_at(loc)
base = get_portable_base()
if patheq(loc, self.db.library_path):
error_dialog(self, _('Same as current'),
_('The location %s contains the current calibre'
' library')%loc, show=True)
return False
if base is not None and ac in ('new', 'move'):
abase = os.path.normcase(os.path.abspath(base))
cal = os.path.normcase(os.path.abspath(os.path.join(abase,
'Calibre')))
aloc = os.path.normcase(os.path.abspath(loc))
if (aloc.startswith(cal+os.sep) or aloc == cal):
error_dialog(self, _('Bad location'),
_('You should not create a library inside the calibre'
' folder as this folder is automatically deleted during upgrades.'),
show=True)
return False
if aloc.startswith(abase) and os.path.dirname(aloc) != abase:
error_dialog(self, _('Bad location'),
_('You can only create libraries inside %s at the top '
'level, not in sub-folders')%base, show=True)
return False
empty = not os.listdir(loc)
if ac == 'existing' and not exists:
error_dialog(self, _('No existing library found'),
_('There is no existing calibre library at %s')%loc,
show=True)
return False
if ac in ('new', 'move'):
from calibre.db.legacy import LibraryDatabase
if not empty:
error_dialog(self, _('Not empty'),
_('The folder %s is not empty. Please choose an empty'
' folder.')%loc,
show=True)
return False
if (iswindows and len(loc) >
LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT):
error_dialog(self, _('Too long'),
_('Path to library too long. It must be less than'
' %d characters.')%LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT,
show=True)
return False
return True
def perform_action(self, ac, loc):
if ac in ('new', 'existing'):
self.callback(loc, copy_structure=self.copy_structure.isChecked())
else:
# move library
self.db.prefs.disable_setting = True
abort_move = Event()
pd = ProgressDialog(_('Moving library, please wait...'), _('Scanning...'), max=0, min=0, icon='lt.png', parent=self)
pd.canceled_signal.connect(abort_move.set)
self.parent().library_view.model().stop_metadata_backup()
move_error = []
def do_move():
try:
self.db.new_api.move_library_to(loc, abort=abort_move, progress=pd.show_new_progress)
except Exception:
import traceback
move_error.append(traceback.format_exc())
finally:
pd.finished_moving.emit()
t = Thread(name='MoveLibrary', target=do_move)
QTimer.singleShot(0, t.start)
pd.exec()
if abort_move.is_set():
self.callback(self.db.library_path)
return
if move_error:
error_dialog(self.parent(), _('Failed to move library'), _(
'There was an error while moving the library. The operation has been aborted. Click'
' "Show details" for details.'), det_msg=move_error[0], show=True)
self.callback(self.db.library_path)
return
self.callback(loc, library_renamed=True)
def accept(self):
action = 'move'
if self.existing_library.isChecked():
action = 'existing'
elif self.empty_library.isChecked():
action = 'new'
text = str(self.location.text()).strip()
if not text:
return error_dialog(self, _('No location'), _('No location selected'),
show=True)
loc = os.path.abspath(text)
if action == 'move':
try:
os.makedirs(loc)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if not loc or not os.path.exists(loc) or not os.path.isdir(loc):
if action == 'new' and not os.path.exists(loc):
os.makedirs(loc)
else:
return error_dialog(self, _('Bad location'),
_('%s is not an existing folder')%loc, show=True)
if not self.check_action(action, loc):
return
self.location.save_history()
self.perform_action(action, loc)
QDialog.accept(self) # Must be after perform action otherwise the progress dialog is not updated on windows