mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Device drivers: Add option to allow calibre to automatically manage metadata on the device in Preferences->Add/Save->Sending to device
This commit is contained in:
commit
8f580384a7
@ -132,6 +132,8 @@ class CollectionsBookList(BookList):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_collections(self, collection_attributes):
|
def get_collections(self, collection_attributes):
|
||||||
|
from calibre.devices.usbms.driver import debug_print
|
||||||
|
debug_print('Starting get_collections:', prefs['manage_device_metadata'])
|
||||||
collections = {}
|
collections = {}
|
||||||
series_categories = set([])
|
series_categories = set([])
|
||||||
# This map of sets is used to avoid linear searches when testing for
|
# This map of sets is used to avoid linear searches when testing for
|
||||||
@ -146,14 +148,19 @@ class CollectionsBookList(BookList):
|
|||||||
# book in all existing collections. Do not add any new ones.
|
# book in all existing collections. Do not add any new ones.
|
||||||
attrs = ['device_collections']
|
attrs = ['device_collections']
|
||||||
if getattr(book, '_new_book', False):
|
if getattr(book, '_new_book', False):
|
||||||
if prefs['preserve_user_collections']:
|
if prefs['manage_device_metadata'] == 'manual':
|
||||||
# Ensure that the book is in all the book's existing
|
# Ensure that the book is in all the book's existing
|
||||||
# collections plus all metadata collections
|
# collections plus all metadata collections
|
||||||
attrs += collection_attributes
|
attrs += collection_attributes
|
||||||
else:
|
else:
|
||||||
# The book's existing collections are ignored. Put the book
|
# For new books, both 'on_send' and 'on_connect' do the same
|
||||||
# in collections defined by its metadata.
|
# thing. The book's existing collections are ignored. Put
|
||||||
|
# the book in collections defined by its metadata.
|
||||||
attrs = collection_attributes
|
attrs = collection_attributes
|
||||||
|
elif prefs['manage_device_metadata'] == 'on_connect':
|
||||||
|
# For existing books, modify the collections only if the user
|
||||||
|
# specified 'on_connect'
|
||||||
|
attrs = collection_attributes
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
attr = attr.strip()
|
attr = attr.strip()
|
||||||
val = getattr(book, attr, None)
|
val = getattr(book, attr, None)
|
||||||
|
@ -58,7 +58,7 @@ class USBMS(CLI, Device):
|
|||||||
|
|
||||||
debug_print ('USBMS: Fetching list of books from device. oncard=', oncard)
|
debug_print ('USBMS: Fetching list of books from device. oncard=', oncard)
|
||||||
|
|
||||||
dummy_bl = BookList(None, None, None)
|
dummy_bl = self.booklist_class(None, None, None)
|
||||||
|
|
||||||
if oncard == 'carda' and not self._card_a_prefix:
|
if oncard == 'carda' and not self._card_a_prefix:
|
||||||
self.report_progress(1.0, _('Getting list of books on device...'))
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
@ -78,6 +78,8 @@ class USBMS(CLI, Device):
|
|||||||
self.EBOOK_DIR_CARD_B if oncard == 'cardb' else \
|
self.EBOOK_DIR_CARD_B if oncard == 'cardb' else \
|
||||||
self.get_main_ebook_dir()
|
self.get_main_ebook_dir()
|
||||||
|
|
||||||
|
debug_print ('USBMS: dirs are:', prefix, ebook_dirs)
|
||||||
|
|
||||||
# get the metadata cache
|
# get the metadata cache
|
||||||
bl = self.booklist_class(oncard, prefix, self.settings)
|
bl = self.booklist_class(oncard, prefix, self.settings)
|
||||||
need_sync = self.parse_metadata_cache(bl, prefix, self.METADATA_CACHE)
|
need_sync = self.parse_metadata_cache(bl, prefix, self.METADATA_CACHE)
|
||||||
|
@ -21,7 +21,7 @@ class Epubcheck(ePubFixer):
|
|||||||
def long_description(self):
|
def long_description(self):
|
||||||
return _('Workarounds for bugs in the latest release of epubcheck. '
|
return _('Workarounds for bugs in the latest release of epubcheck. '
|
||||||
'epubcheck reports many things as errors that are not '
|
'epubcheck reports many things as errors that are not '
|
||||||
'actually errors. %prog will try to detect these and replace '
|
'actually errors. epub-fix will try to detect these and replace '
|
||||||
'them with constructs that epubcheck likes. This may cause '
|
'them with constructs that epubcheck likes. This may cause '
|
||||||
'significant changes to your epub, complain to the epubcheck '
|
'significant changes to your epub, complain to the epubcheck '
|
||||||
'project.')
|
'project.')
|
||||||
|
@ -18,7 +18,7 @@ class Unmanifested(ePubFixer):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def long_description(self):
|
def long_description(self):
|
||||||
return _('Fix unmanifested files. %prog can either add them to '
|
return _('Fix unmanifested files. epub-fix can either add them to '
|
||||||
'the manifest or delete them as specified by the '
|
'the manifest or delete them as specified by the '
|
||||||
'delete unmanifested option.')
|
'delete unmanifested option.')
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ from calibre.devices.apple.driver import ITUNES_ASYNC
|
|||||||
from calibre.devices.folder_device.driver import FOLDER_DEVICE
|
from calibre.devices.folder_device.driver import FOLDER_DEVICE
|
||||||
from calibre.ebooks.metadata.meta import set_metadata
|
from calibre.ebooks.metadata.meta import set_metadata
|
||||||
from calibre.constants import DEBUG
|
from calibre.constants import DEBUG
|
||||||
|
from calibre.utils.config import prefs
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@ -1424,19 +1425,24 @@ class DeviceMixin(object): # {{{
|
|||||||
aus = re.sub('(?u)\W|[_]', '', aus)
|
aus = re.sub('(?u)\W|[_]', '', aus)
|
||||||
self.db_book_title_cache[title]['author_sort'][aus] = mi
|
self.db_book_title_cache[title]['author_sort'][aus] = mi
|
||||||
self.db_book_title_cache[title]['db_ids'][mi.application_id] = mi
|
self.db_book_title_cache[title]['db_ids'][mi.application_id] = mi
|
||||||
self.db_book_uuid_cache[mi.uuid] = mi.application_id
|
self.db_book_uuid_cache[mi.uuid] = mi
|
||||||
|
|
||||||
# Now iterate through all the books on the device, setting the
|
# Now iterate through all the books on the device, setting the
|
||||||
# in_library field Fastest and most accurate key is the uuid. Second is
|
# in_library field Fastest and most accurate key is the uuid. Second is
|
||||||
# the application_id, which is really the db key, but as this can
|
# the application_id, which is really the db key, but as this can
|
||||||
# accidentally match across libraries we also verify the title. The
|
# accidentally match across libraries we also verify the title. The
|
||||||
# db_id exists on Sony devices. Fallback is title and author match
|
# db_id exists on Sony devices. Fallback is title and author match
|
||||||
|
|
||||||
|
update_metadata = prefs['manage_device_metadata'] == 'on_connect'
|
||||||
for booklist in booklists:
|
for booklist in booklists:
|
||||||
for book in booklist:
|
for book in booklist:
|
||||||
if getattr(book, 'uuid', None) in self.db_book_uuid_cache:
|
if getattr(book, 'uuid', None) in self.db_book_uuid_cache:
|
||||||
|
if update_metadata:
|
||||||
|
book.smart_update(self.db_book_uuid_cache[book.uuid])
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
# ensure that the correct application_id is set
|
# ensure that the correct application_id is set
|
||||||
book.application_id = self.db_book_uuid_cache[book.uuid]
|
book.application_id = \
|
||||||
|
self.db_book_uuid_cache[book.uuid].application_id
|
||||||
continue
|
continue
|
||||||
|
|
||||||
book_title = book.title.lower() if book.title else ''
|
book_title = book.title.lower() if book.title else ''
|
||||||
@ -1446,11 +1452,13 @@ class DeviceMixin(object): # {{{
|
|||||||
if d is not None:
|
if d is not None:
|
||||||
if getattr(book, 'application_id', None) in d['db_ids']:
|
if getattr(book, 'application_id', None) in d['db_ids']:
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
book.smart_update(d['db_ids'][book.application_id])
|
if update_metadata:
|
||||||
|
book.smart_update(d['db_ids'][book.application_id])
|
||||||
continue
|
continue
|
||||||
if book.db_id in d['db_ids']:
|
if book.db_id in d['db_ids']:
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
book.smart_update(d['db_ids'][book.db_id])
|
if update_metadata:
|
||||||
|
book.smart_update(d['db_ids'][book.db_id])
|
||||||
continue
|
continue
|
||||||
if book.authors:
|
if book.authors:
|
||||||
# Compare against both author and author sort, because
|
# Compare against both author and author sort, because
|
||||||
@ -1459,14 +1467,19 @@ class DeviceMixin(object): # {{{
|
|||||||
book_authors = re.sub('(?u)\W|[_]', '', book_authors)
|
book_authors = re.sub('(?u)\W|[_]', '', book_authors)
|
||||||
if book_authors in d['authors']:
|
if book_authors in d['authors']:
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
book.smart_update(d['authors'][book_authors])
|
if update_metadata:
|
||||||
|
book.smart_update(d['authors'][book_authors])
|
||||||
elif book_authors in d['author_sort']:
|
elif book_authors in d['author_sort']:
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
book.smart_update(d['author_sort'][book_authors])
|
if update_metadata:
|
||||||
|
book.smart_update(d['author_sort'][book_authors])
|
||||||
# Set author_sort if it isn't already
|
# Set author_sort if it isn't already
|
||||||
asort = getattr(book, 'author_sort', None)
|
asort = getattr(book, 'author_sort', None)
|
||||||
if not asort and book.authors:
|
if not asort and book.authors:
|
||||||
book.author_sort = self.library_view.model().db.author_sort_from_authors(book.authors)
|
book.author_sort = self.library_view.model().db.author_sort_from_authors(book.authors)
|
||||||
|
|
||||||
|
if update_metadata:
|
||||||
|
if self.device_manager.is_device_connected:
|
||||||
|
self.device_manager.sync_booklists(None, booklists)
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -45,7 +45,12 @@ class AddSave(QTabWidget, Ui_TabWidget):
|
|||||||
self.metadata_box.layout().insertWidget(0, self.filename_pattern)
|
self.metadata_box.layout().insertWidget(0, self.filename_pattern)
|
||||||
self.opt_swap_author_names.setChecked(prefs['swap_author_names'])
|
self.opt_swap_author_names.setChecked(prefs['swap_author_names'])
|
||||||
self.opt_add_formats_to_existing.setChecked(prefs['add_formats_to_existing'])
|
self.opt_add_formats_to_existing.setChecked(prefs['add_formats_to_existing'])
|
||||||
self.preserve_user_collections.setChecked(prefs['preserve_user_collections'])
|
if prefs['manage_device_metadata'] == 'manual':
|
||||||
|
self.manage_device_metadata.setCurrentIndex(0)
|
||||||
|
elif prefs['manage_device_metadata'] == 'on_send':
|
||||||
|
self.manage_device_metadata.setCurrentIndex(1)
|
||||||
|
else:
|
||||||
|
self.manage_device_metadata.setCurrentIndex(2)
|
||||||
help = '\n'.join(textwrap.wrap(c.get_option('template').help, 75))
|
help = '\n'.join(textwrap.wrap(c.get_option('template').help, 75))
|
||||||
self.save_template.initialize('save_to_disk', opts.template, help)
|
self.save_template.initialize('save_to_disk', opts.template, help)
|
||||||
self.send_template.initialize('send_to_device', opts.send_template, help)
|
self.send_template.initialize('send_to_device', opts.send_template, help)
|
||||||
@ -72,12 +77,14 @@ class AddSave(QTabWidget, Ui_TabWidget):
|
|||||||
prefs['filename_pattern'] = pattern
|
prefs['filename_pattern'] = pattern
|
||||||
prefs['swap_author_names'] = bool(self.opt_swap_author_names.isChecked())
|
prefs['swap_author_names'] = bool(self.opt_swap_author_names.isChecked())
|
||||||
prefs['add_formats_to_existing'] = bool(self.opt_add_formats_to_existing.isChecked())
|
prefs['add_formats_to_existing'] = bool(self.opt_add_formats_to_existing.isChecked())
|
||||||
prefs['preserve_user_collections'] = bool(self.preserve_user_collections.isChecked())
|
if self.manage_device_metadata.currentIndex() == 0:
|
||||||
|
prefs['manage_device_metadata'] = 'manual'
|
||||||
|
elif self.manage_device_metadata.currentIndex() == 1:
|
||||||
|
prefs['manage_device_metadata'] = 'on_send'
|
||||||
|
else:
|
||||||
|
prefs['manage_device_metadata'] = 'on_connect'
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from PyQt4.Qt import QApplication
|
from PyQt4.Qt import QApplication
|
||||||
app=QApplication([])
|
app=QApplication([])
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>588</width>
|
<width>953</width>
|
||||||
<height>516</height>
|
<height>516</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -177,32 +177,37 @@ Title match ignores leading indefinite articles ("the", "a",
|
|||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Sending to &device</string>
|
<string>Sending to &device</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item>
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="preserve_user_collections">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Preserve device collections.</string>
|
<string>Metadata &management:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>manage_device_metadata</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="1" column="0" colspan="3">
|
||||||
<widget class="QLabel" name="label_41">
|
<widget class="QLabel" name="label_41">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>If checked, collections will not be deleted even if a book with changed metadata is resent and the collection is not in the book's metadata. In addition, editing collections in the device view will be enabled. If unchecked, collections will be always reflect only the metadata in the calibre library.</string>
|
<string><li><b>Manual Management</b>: Calibre updates the metadata and adds collections only when a book is sent. With this option, calibre will never remove a collection.</li>
|
||||||
|
<li><b>Only on send</b>: Calibre updates metadata and adds/removes collections for a book only when it is sent to the device. </li>
|
||||||
|
<li><b>Automatic management</b>: Calibre automatically keeps metadata on the device in sync with the calibre library, on every connect</li></ul></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_42">
|
<widget class="QLabel" name="label_42">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string> </string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="3" column="0" colspan="3">
|
||||||
<widget class="QLabel" name="label_43">
|
<widget class="QLabel" name="label_43">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Here you can control how calibre will save your books when you click the Send to Device button. This setting can be overriden for individual devices by customizing the device interface plugins in Preferences->Plugins</string>
|
<string>Here you can control how calibre will save your books when you click the Send to Device button. This setting can be overriden for individual devices by customizing the device interface plugins in Preferences->Plugins</string>
|
||||||
@ -212,9 +217,28 @@ Title match ignores leading indefinite articles ("the", "a",
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="4" column="0" colspan="3">
|
||||||
<widget class="SaveTemplate" name="send_template" native="true"/>
|
<widget class="SaveTemplate" name="send_template" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QComboBox" name="manage_device_metadata">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string extracomment="foobar">Manual management</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Only on send</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Automatic management</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -409,7 +409,8 @@ class StatusBar(QStatusBar): # {{{
|
|||||||
self.clearMessage()
|
self.clearMessage()
|
||||||
|
|
||||||
def message_changed(self, msg):
|
def message_changed(self, msg):
|
||||||
if not msg or msg.isEmpty() or msg.isNull():
|
if not msg or msg.isEmpty() or msg.isNull() or \
|
||||||
|
not unicode(msg).strip():
|
||||||
extra = ''
|
extra = ''
|
||||||
if self.device_string:
|
if self.device_string:
|
||||||
extra = ' ..::.. ' + self.device_string
|
extra = ' ..::.. ' + self.device_string
|
||||||
|
@ -8,12 +8,13 @@ __docformat__ = 'restructuredtext en'
|
|||||||
from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, QVariant, \
|
from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, QVariant, \
|
||||||
QAbstractListModel, QFont, QApplication, QPalette, pyqtSignal, QToolButton, \
|
QAbstractListModel, QFont, QApplication, QPalette, pyqtSignal, QToolButton, \
|
||||||
QModelIndex, QListView, QAbstractButton, QPainter, QPixmap, QColor, \
|
QModelIndex, QListView, QAbstractButton, QPainter, QPixmap, QColor, \
|
||||||
QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QComboBox
|
QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout
|
||||||
|
|
||||||
from calibre.constants import __appname__, filesystem_encoding
|
from calibre.constants import __appname__, filesystem_encoding
|
||||||
from calibre.gui2.search_box import SearchBox2, SavedSearchBox
|
from calibre.gui2.search_box import SearchBox2, SavedSearchBox
|
||||||
from calibre.gui2.throbber import ThrobbingButton
|
from calibre.gui2.throbber import ThrobbingButton
|
||||||
from calibre.gui2 import NONE
|
from calibre.gui2 import NONE
|
||||||
|
from calibre.gui2.widgets import ComboBoxWithHelp
|
||||||
from calibre import human_readable
|
from calibre import human_readable
|
||||||
|
|
||||||
class ToolBar(QToolBar): # {{{
|
class ToolBar(QToolBar): # {{{
|
||||||
@ -280,12 +281,7 @@ class SearchBar(QWidget): # {{{
|
|||||||
self._layout = l = QHBoxLayout()
|
self._layout = l = QHBoxLayout()
|
||||||
self.setLayout(self._layout)
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
self.restriction_label = QLabel(_("&Restrict to:"))
|
x = ComboBoxWithHelp(self)
|
||||||
l.addWidget(self.restriction_label)
|
|
||||||
self.restriction_label.setSizePolicy(QSizePolicy.Minimum,
|
|
||||||
QSizePolicy.Minimum)
|
|
||||||
|
|
||||||
x = QComboBox(self)
|
|
||||||
x.setMaximumSize(QSize(150, 16777215))
|
x.setMaximumSize(QSize(150, 16777215))
|
||||||
x.setObjectName("search_restriction")
|
x.setObjectName("search_restriction")
|
||||||
x.setToolTip(_("Books display will be restricted to those matching the selected saved search"))
|
x.setToolTip(_("Books display will be restricted to those matching the selected saved search"))
|
||||||
@ -344,7 +340,6 @@ class SearchBar(QWidget): # {{{
|
|||||||
x.setToolTip(_("Delete current saved search"))
|
x.setToolTip(_("Delete current saved search"))
|
||||||
|
|
||||||
self.label.setBuddy(parent.search)
|
self.label.setBuddy(parent.search)
|
||||||
self.restriction_label.setBuddy(parent.search_restriction)
|
|
||||||
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
@ -944,7 +944,7 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
(cname == 'collections' and \
|
(cname == 'collections' and \
|
||||||
callable(getattr(self.db, 'supports_collections', None)) and \
|
callable(getattr(self.db, 'supports_collections', None)) and \
|
||||||
self.db.supports_collections() and \
|
self.db.supports_collections() and \
|
||||||
prefs['preserve_user_collections']):
|
prefs['manage_device_metadata']=='manual'):
|
||||||
flags |= Qt.ItemIsEditable
|
flags |= Qt.ItemIsEditable
|
||||||
return flags
|
return flags
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ class DeviceBooksView(BooksView): # {{{
|
|||||||
self.edit_collections_menu.setVisible(
|
self.edit_collections_menu.setVisible(
|
||||||
callable(getattr(self._model.db, 'supports_collections', None)) and \
|
callable(getattr(self._model.db, 'supports_collections', None)) and \
|
||||||
self._model.db.supports_collections() and \
|
self._model.db.supports_collections() and \
|
||||||
prefs['preserve_user_collections'])
|
prefs['manage_device_metadata'] == 'manual')
|
||||||
self.context_menu.popup(event.globalPos())
|
self.context_menu.popup(event.globalPos())
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@ Created on 10 Jun 2010
|
|||||||
class SearchRestrictionMixin(object):
|
class SearchRestrictionMixin(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.search_restriction.activated[str].connect(self.apply_search_restriction)
|
self.search_restriction.initialize(help_text=_('Restrict to'))
|
||||||
|
self.search_restriction.activated[int].connect(self.apply_search_restriction)
|
||||||
self.library_view.model().count_changed_signal.connect(self.restriction_count_changed)
|
self.library_view.model().count_changed_signal.connect(self.restriction_count_changed)
|
||||||
self.search_restriction.setSizeAdjustPolicy(self.search_restriction.AdjustToMinimumContentsLengthWithIcon)
|
self.search_restriction.setSizeAdjustPolicy(self.search_restriction.AdjustToMinimumContentsLengthWithIcon)
|
||||||
self.search_restriction.setMinimumContentsLength(10)
|
self.search_restriction.setMinimumContentsLength(10)
|
||||||
@ -27,8 +28,8 @@ class SearchRestrictionMixin(object):
|
|||||||
if self.restriction_in_effect:
|
if self.restriction_in_effect:
|
||||||
self.set_number_of_books_shown()
|
self.set_number_of_books_shown()
|
||||||
|
|
||||||
def apply_search_restriction(self, r):
|
def apply_search_restriction(self, i):
|
||||||
r = unicode(r)
|
r = unicode(self.search_restriction.currentText())
|
||||||
if r is not None and r != '':
|
if r is not None and r != '':
|
||||||
self.restriction_in_effect = True
|
self.restriction_in_effect = True
|
||||||
restriction = 'search:"%s"'%(r)
|
restriction = 'search:"%s"'%(r)
|
||||||
|
@ -538,6 +538,53 @@ class HistoryLineEdit(QComboBox):
|
|||||||
def text(self):
|
def text(self):
|
||||||
return self.currentText()
|
return self.currentText()
|
||||||
|
|
||||||
|
class ComboBoxWithHelp(QComboBox):
|
||||||
|
'''
|
||||||
|
A combobox where item 0 is help text. CurrentText will return '' for item 0.
|
||||||
|
Be sure to always fetch the text with currentText. Don't use the signals
|
||||||
|
that pass a string, because they will not correct the text.
|
||||||
|
'''
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QComboBox.__init__(self, parent)
|
||||||
|
self.currentIndexChanged[int].connect(self.index_changed)
|
||||||
|
self.help_text = ''
|
||||||
|
self.state_set = False
|
||||||
|
|
||||||
|
def initialize(self, help_text=_('Search')):
|
||||||
|
self.help_text = help_text
|
||||||
|
self.set_state()
|
||||||
|
|
||||||
|
def set_state(self):
|
||||||
|
if not self.state_set:
|
||||||
|
if self.currentIndex() == 0:
|
||||||
|
self.setItemText(0, self.help_text)
|
||||||
|
self.setStyleSheet('QComboBox { color: gray }')
|
||||||
|
else:
|
||||||
|
self.setItemText(0, '')
|
||||||
|
self.setStyleSheet('QComboBox { color: black }')
|
||||||
|
|
||||||
|
def index_changed(self, index):
|
||||||
|
self.state_set = False
|
||||||
|
self.set_state()
|
||||||
|
|
||||||
|
def currentText(self):
|
||||||
|
if self.currentIndex() == 0:
|
||||||
|
return ''
|
||||||
|
return QComboBox.currentText(self)
|
||||||
|
|
||||||
|
def itemText(self, idx):
|
||||||
|
if idx == 0:
|
||||||
|
return ''
|
||||||
|
return QComboBox.itemText(self, idx)
|
||||||
|
|
||||||
|
def showPopup(self):
|
||||||
|
self.setItemText(0, '')
|
||||||
|
QComboBox.showPopup(self)
|
||||||
|
|
||||||
|
def hidePopup(self):
|
||||||
|
QComboBox.hidePopup(self)
|
||||||
|
self.set_state()
|
||||||
|
|
||||||
class PythonHighlighter(QSyntaxHighlighter):
|
class PythonHighlighter(QSyntaxHighlighter):
|
||||||
|
|
||||||
Rules = []
|
Rules = []
|
||||||
|
@ -698,8 +698,8 @@ def _prefs():
|
|||||||
# calibre server can execute searches
|
# calibre server can execute searches
|
||||||
c.add_opt('saved_searches', default={}, help=_('List of named saved searches'))
|
c.add_opt('saved_searches', default={}, help=_('List of named saved searches'))
|
||||||
c.add_opt('user_categories', default={}, help=_('User-created tag browser categories'))
|
c.add_opt('user_categories', default={}, help=_('User-created tag browser categories'))
|
||||||
c.add_opt('preserve_user_collections', default=True,
|
c.add_opt('manage_device_metadata', default='manual',
|
||||||
help=_('Preserve all collections even if not in library metadata.'))
|
help=_('How and when calibre updates metadata on the device.'))
|
||||||
|
|
||||||
c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.')
|
c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.')
|
||||||
return c
|
return c
|
||||||
|
Loading…
x
Reference in New Issue
Block a user