mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement choose library action
This commit is contained in:
parent
0ad6ab164f
commit
12a4797a6f
82
src/calibre/gui2/dialogs/choose_library.py
Normal file
82
src/calibre/gui2/dialogs/choose_library.py
Normal file
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
|
||||
from PyQt4.Qt import QDialog
|
||||
|
||||
from calibre.gui2.dialogs.choose_library_ui import Ui_Dialog
|
||||
from calibre.gui2 import error_dialog, choose_dir
|
||||
from calibre.constants import filesystem_encoding
|
||||
from calibre import isbytestring, patheq
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.gui2.wizard import move_library
|
||||
|
||||
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
|
||||
|
||||
lp = db.library_path
|
||||
if isbytestring(lp):
|
||||
lp = lp.decode(filesystem_encoding)
|
||||
loc = unicode(self.old_location.text()).format(lp)
|
||||
self.old_location.setText(loc)
|
||||
self.browse_button.clicked.connect(self.choose_loc)
|
||||
|
||||
def choose_loc(self, *args):
|
||||
loc = choose_dir(self, 'choose library location',
|
||||
_('Choose location for calibre library'))
|
||||
if loc is not None:
|
||||
self.location.setText(loc)
|
||||
|
||||
def check_action(self, ac, loc):
|
||||
exists = self.db.exists_at(loc)
|
||||
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
|
||||
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') and not empty:
|
||||
error_dialog(self, _('Not empty'),
|
||||
_('The folder %s is not empty. Please choose an empty'
|
||||
' folder')%loc,
|
||||
show=True)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def perform_action(self, ac, loc):
|
||||
if ac in ('new', 'existing'):
|
||||
prefs['library_path'] = loc
|
||||
self.callback(loc)
|
||||
else:
|
||||
move_library(self.db.library_path, loc, self.parent(),
|
||||
self.callback)
|
||||
|
||||
def accept(self):
|
||||
action = 'move'
|
||||
if self.existing_library.isChecked():
|
||||
action = 'existing'
|
||||
elif self.empty_library.isChecked():
|
||||
action = 'new'
|
||||
loc = os.path.abspath(unicode(self.location.text()).strip())
|
||||
if not loc or not os.path.exists(loc) or not self.check_action(action,
|
||||
loc):
|
||||
return
|
||||
QDialog.accept(self)
|
||||
self.perform_action(action, loc)
|
171
src/calibre/gui2/dialogs/choose_library.ui
Normal file
171
src/calibre/gui2/dialogs/choose_library.ui
Normal file
@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>602</width>
|
||||
<height>245</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Choose your calibre library</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../../../resources/images.qrc">
|
||||
<normaloff>:/images/lt.png</normaloff>:/images/lt.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QLabel" name="old_location">
|
||||
<property name="text">
|
||||
<string>Your calibre library is currently located at {0}</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>New &Location:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>location</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="location">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QRadioButton" name="existing_library">
|
||||
<property name="text">
|
||||
<string>Use &existing library at the new location</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="empty_library">
|
||||
<property name="text">
|
||||
<string>&Create an empty library at the new location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="move_library">
|
||||
<property name="text">
|
||||
<string>&Move current library to new location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QToolButton" name="browse_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../resources/images.qrc">
|
||||
<normaloff>:/images/document_open.svg</normaloff>:/images/document_open.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../../resources/images.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -14,7 +14,7 @@ from PyQt4.Qt import QDialog, QListWidgetItem, QIcon, \
|
||||
from calibre.constants import iswindows, isosx
|
||||
from calibre.gui2.dialogs.config.config_ui import Ui_Dialog
|
||||
from calibre.gui2.dialogs.config.create_custom_column import CreateCustomColumn
|
||||
from calibre.gui2 import choose_dir, error_dialog, config, gprefs, \
|
||||
from calibre.gui2 import error_dialog, config, gprefs, \
|
||||
open_url, open_local_file, \
|
||||
ALL_COLUMNS, NONE, info_dialog, choose_files, \
|
||||
warning_dialog, ResizableDialog, question_dialog
|
||||
@ -343,9 +343,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
self.model = library_view.model()
|
||||
self.db = self.model.db
|
||||
self.server = server
|
||||
path = prefs['library_path']
|
||||
self.location.setText(path if path else '')
|
||||
self.connect(self.browse_button, SIGNAL('clicked(bool)'), self.browse)
|
||||
self.connect(self.compact_button, SIGNAL('clicked(bool)'), self.compact)
|
||||
|
||||
input_map = prefs['input_format_order']
|
||||
@ -808,12 +805,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
d = CheckIntegrity(self.db, self)
|
||||
d.exec_()
|
||||
|
||||
def browse(self):
|
||||
dir = choose_dir(self, 'database location dialog',
|
||||
_('Select location for books'))
|
||||
if dir:
|
||||
self.location.setText(dir)
|
||||
|
||||
def accept(self):
|
||||
mcs = unicode(self.max_cover_size.text()).strip()
|
||||
if not re.match(r'\d+x\d+', mcs):
|
||||
@ -834,7 +825,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
config['use_roman_numerals_for_series_number'] = bool(self.roman_numerals.isChecked())
|
||||
config['new_version_notification'] = bool(self.new_version_notification.isChecked())
|
||||
prefs['network_timeout'] = int(self.timeout.value())
|
||||
path = unicode(self.location.text())
|
||||
input_cols = [unicode(self.input_order.item(i).data(Qt.UserRole).toString()) for i in range(self.input_order.count())]
|
||||
prefs['input_format_order'] = input_cols
|
||||
|
||||
@ -875,17 +865,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
val = self.opt_gui_layout.itemData(self.opt_gui_layout.currentIndex()).toString()
|
||||
config['gui_layout'] = unicode(val)
|
||||
|
||||
if not path or not os.path.exists(path) or not os.path.isdir(path):
|
||||
d = error_dialog(self, _('Invalid database location'),
|
||||
_('Invalid database location ')+path+
|
||||
_('<br>Must be a directory.'))
|
||||
d.exec_()
|
||||
elif not os.access(path, os.W_OK):
|
||||
d = error_dialog(self, _('Invalid database location'),
|
||||
_('Invalid database location.<br>Cannot write to ')+path)
|
||||
d.exec_()
|
||||
else:
|
||||
self.database_location = os.path.abspath(path)
|
||||
if must_restart:
|
||||
warning_dialog(self, _('Must restart'),
|
||||
_('The changes you made require that Calibre be '
|
||||
|
@ -113,50 +113,6 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="page_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Location of ebooks (The ebooks are stored in folders sorted by author and metadata is stored in the file metadata.db)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>location</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="location"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="browse_button">
|
||||
<property name="toolTip">
|
||||
<string>Browse for the new database location</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../../resources/images.qrc">
|
||||
<normaloff>:/images/mimetypes/dir.svg</normaloff>:/images/mimetypes/dir.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="new_version_notification">
|
||||
<property name="text">
|
||||
|
@ -329,6 +329,7 @@ class MainWindowMixin(object):
|
||||
self.tool_bar = ToolBar(all_actions, self.donate_button,
|
||||
self.location_manager, self)
|
||||
self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
|
||||
self.tool_bar.choose_action.triggered.connect(self.choose_library)
|
||||
|
||||
l = self.centralwidget.layout()
|
||||
l.addWidget(self.search_bar)
|
||||
@ -337,6 +338,12 @@ class MainWindowMixin(object):
|
||||
def read_toolbar_settings(self):
|
||||
pass
|
||||
|
||||
def choose_library(self, *args):
|
||||
from calibre.gui2.dialogs.choose_library import ChooseLibrary
|
||||
db = self.library_view.model().db
|
||||
c = ChooseLibrary(db, self.library_moved, self)
|
||||
c.exec_()
|
||||
|
||||
def setup_actions(self): # {{{
|
||||
all_actions = []
|
||||
|
||||
|
@ -18,7 +18,7 @@ from PyQt4.Qt import Qt, SIGNAL, QTimer, \
|
||||
QSystemTrayIcon, QApplication, QKeySequence, QAction, \
|
||||
QMessageBox, QHelpEvent
|
||||
|
||||
from calibre import prints, patheq
|
||||
from calibre import prints
|
||||
from calibre.constants import __appname__, isosx
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.utils.config import prefs, dynamic
|
||||
@ -27,7 +27,6 @@ from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \
|
||||
gprefs, max_available_height, config, info_dialog
|
||||
from calibre.gui2.cover_flow import CoverFlowMixin
|
||||
from calibre.gui2.widgets import ProgressIndicator
|
||||
from calibre.gui2.wizard import move_library
|
||||
from calibre.gui2.dialogs.scheduler import Scheduler
|
||||
from calibre.gui2.update import UpdateMixin
|
||||
from calibre.gui2.main_window import MainWindow
|
||||
@ -389,10 +388,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
||||
self.tags_view.recount()
|
||||
self.create_device_menu()
|
||||
self.set_device_menu_items_state(bool(self.device_connected))
|
||||
if not patheq(self.library_path, d.database_location):
|
||||
newloc = d.database_location
|
||||
move_library(self.library_path, newloc, self,
|
||||
self.library_moved)
|
||||
|
||||
def library_moved(self, newloc):
|
||||
if newloc is None: return
|
||||
|
@ -116,6 +116,10 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
# missing functions
|
||||
self.books_list_filter = self.conn.create_dynamic_filter('books_list_filter')
|
||||
|
||||
@classmethod
|
||||
def exists_at(cls, path):
|
||||
return path and os.path.exists(os.path.join(path, 'metadata.db'))
|
||||
|
||||
def __init__(self, library_path, row_factory=False):
|
||||
self.field_metadata = FieldMetadata()
|
||||
if not os.path.exists(library_path):
|
||||
|
Loading…
x
Reference in New Issue
Block a user