mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix (I hope) crashes in MultiCompleteComboBox. Also the drop down arrow now only shows the items that start with whatever text is currently entered in the box
This commit is contained in:
parent
e6788b5814
commit
c8b5db5209
@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
from PyQt4.Qt import (QLineEdit, QAbstractListModel, Qt,
|
||||
QApplication, QCompleter, pyqtSignal)
|
||||
QApplication, QCompleter)
|
||||
|
||||
from calibre.utils.icu import sort_key, lower
|
||||
from calibre.gui2 import NONE
|
||||
@ -56,7 +56,7 @@ class MultiCompleteLineEdit(QLineEdit, LineEditECM):
|
||||
to complete non multiple fields as well.
|
||||
'''
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent=None, completer_widget=None):
|
||||
QLineEdit.__init__(self, parent)
|
||||
|
||||
self.sep = ','
|
||||
@ -66,7 +66,7 @@ class MultiCompleteLineEdit(QLineEdit, LineEditECM):
|
||||
|
||||
self._model = CompleteModel(parent=self)
|
||||
self._completer = c = QCompleter(self._model, self)
|
||||
c.setWidget(self)
|
||||
c.setWidget(self if completer_widget is None else completer_widget)
|
||||
c.setCompletionMode(QCompleter.PopupCompletion)
|
||||
c.setCaseSensitivity(Qt.CaseInsensitive)
|
||||
c.setModelSorting(self._model.sorting)
|
||||
@ -158,21 +158,13 @@ class MultiCompleteLineEdit(QLineEdit, LineEditECM):
|
||||
|
||||
class MultiCompleteComboBox(EnComboBox):
|
||||
|
||||
clear_edit_text = pyqtSignal()
|
||||
|
||||
def __init__(self, *args):
|
||||
EnComboBox.__init__(self, *args)
|
||||
self.setLineEdit(MultiCompleteLineEdit(self))
|
||||
# Needed to allow changing the case of an existing item
|
||||
# otherwise on focus out, the text is changed to the
|
||||
# item that matches case insensitively
|
||||
c = self.lineEdit().completer()
|
||||
c.setCaseSensitivity(Qt.CaseSensitive)
|
||||
self.dummy_model = CompleteModel(self)
|
||||
c.setModel(self.dummy_model)
|
||||
self.lineEdit()._completer.setWidget(self)
|
||||
self.clear_edit_text.connect(self.clearEditText,
|
||||
type=Qt.QueuedConnection)
|
||||
self.le = MultiCompleteLineEdit(self, completer_widget=self)
|
||||
self.setLineEdit(self.le)
|
||||
|
||||
def showPopup(self):
|
||||
self.le._completer.complete()
|
||||
|
||||
def update_items_cache(self, complete_items):
|
||||
self.lineEdit().update_items_cache(complete_items)
|
||||
@ -187,16 +179,8 @@ class MultiCompleteComboBox(EnComboBox):
|
||||
self.lineEdit().set_add_separator(what)
|
||||
|
||||
def show_initial_value(self, what):
|
||||
'''
|
||||
Show an initial value. Handle the case of the initial value being blank
|
||||
correctly (on Qt 4.8.0 having a blank value causes the first value from
|
||||
the completer to be shown, when the event loop runs).
|
||||
'''
|
||||
what = unicode(what)
|
||||
what = unicode(what) if what else u''
|
||||
le = self.lineEdit()
|
||||
if not what.strip():
|
||||
self.clear_edit_text.emit()
|
||||
else:
|
||||
self.setEditText(what)
|
||||
le.selectAll()
|
||||
|
||||
@ -207,5 +191,8 @@ if __name__ == '__main__':
|
||||
d.setLayout(QVBoxLayout())
|
||||
le = MultiCompleteComboBox(d)
|
||||
d.layout().addWidget(le)
|
||||
le.all_items = ['one', 'otwo', 'othree', 'ooone', 'ootwo', 'oothree']
|
||||
items = ['one', 'otwo', 'othree', 'ooone', 'ootwo',
|
||||
'oothree']
|
||||
le.update_items_cache(items)
|
||||
le.show_initial_value('')
|
||||
d.exec_()
|
||||
|
@ -12,8 +12,8 @@ from PyQt4.Qt import QPixmap, SIGNAL
|
||||
|
||||
from calibre.gui2 import choose_images, error_dialog
|
||||
from calibre.gui2.convert.metadata_ui import Ui_Form
|
||||
from calibre.ebooks.metadata import (authors_to_string, string_to_authors,
|
||||
MetaInformation, title_sort)
|
||||
from calibre.ebooks.metadata import (string_to_authors, MetaInformation,
|
||||
title_sort)
|
||||
from calibre.ebooks.metadata.opf2 import metadata_to_opf
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.gui2.convert import Widget
|
||||
@ -74,14 +74,12 @@ class MetadataWidget(Widget, Ui_Form):
|
||||
|
||||
mi = self.db.get_metadata(self.book_id, index_is_id=True)
|
||||
self.title.setText(mi.title)
|
||||
if mi.publisher:
|
||||
self.publisher.setCurrentIndex(self.publisher.findText(mi.publisher))
|
||||
self.publisher.show_initial_value(mi.publisher if mi.publisher else '')
|
||||
self.author_sort.setText(mi.author_sort if mi.author_sort else '')
|
||||
self.tags.setText(', '.join(mi.tags if mi.tags else []))
|
||||
self.tags.update_items_cache(self.db.all_tags())
|
||||
self.comment.html = comments_to_html(mi.comments) if mi.comments else ''
|
||||
if mi.series:
|
||||
self.series.setCurrentIndex(self.series.findText(mi.series))
|
||||
self.series.show_initial_value(mi.series if mi.series else '')
|
||||
if mi.series_index is not None:
|
||||
try:
|
||||
self.series_index.setValue(mi.series_index)
|
||||
@ -118,16 +116,11 @@ class MetadataWidget(Widget, Ui_Form):
|
||||
self.author.set_add_separator(tweaks['authors_completer_append_separator'])
|
||||
self.author.update_items_cache(self.db.all_author_names())
|
||||
|
||||
for i in all_authors:
|
||||
id, name = i
|
||||
name = authors_to_string([name.strip().replace('|', ',') for n in name.split(',')])
|
||||
self.author.addItem(name)
|
||||
|
||||
au = self.db.authors(self.book_id, True)
|
||||
if not au:
|
||||
au = _('Unknown')
|
||||
au = ' & '.join([a.strip().replace('|', ',') for a in au.split(',')])
|
||||
self.author.setEditText(au)
|
||||
self.author.show_initial_value(au)
|
||||
|
||||
def initialize_series(self):
|
||||
all_series = self.db.all_series()
|
||||
@ -135,22 +128,12 @@ class MetadataWidget(Widget, Ui_Form):
|
||||
self.series.set_separator(None)
|
||||
self.series.update_items_cache([x[1] for x in all_series])
|
||||
|
||||
for i in all_series:
|
||||
id, name = i
|
||||
self.series.addItem(name)
|
||||
self.series.setCurrentIndex(-1)
|
||||
|
||||
def initialize_publisher(self):
|
||||
all_publishers = self.db.all_publishers()
|
||||
all_publishers.sort(key=lambda x : sort_key(x[1]))
|
||||
self.publisher.set_separator(None)
|
||||
self.publisher.update_items_cache([x[1] for x in all_publishers])
|
||||
|
||||
for i in all_publishers:
|
||||
id, name = i
|
||||
self.publisher.addItem(name)
|
||||
self.publisher.setCurrentIndex(-1)
|
||||
|
||||
def get_title_and_authors(self):
|
||||
title = unicode(self.title.text()).strip()
|
||||
if not title:
|
||||
@ -179,6 +162,7 @@ class MetadataWidget(Widget, Ui_Form):
|
||||
if tags:
|
||||
mi.tags = tags
|
||||
|
||||
print (mi)
|
||||
return mi
|
||||
|
||||
def select_cover(self):
|
||||
|
@ -314,14 +314,7 @@ class Text(Base):
|
||||
if self.col_metadata['is_multiple']:
|
||||
self.setter(val)
|
||||
else:
|
||||
idx = None
|
||||
for i, c in enumerate(values):
|
||||
if c == val:
|
||||
idx = i
|
||||
self.widgets[1].addItem(c)
|
||||
self.widgets[1].setEditText('')
|
||||
if idx is not None:
|
||||
self.widgets[1].setCurrentIndex(idx)
|
||||
self.widgets[1].show_initial_value(val)
|
||||
|
||||
def setter(self, val):
|
||||
if self.col_metadata['is_multiple']:
|
||||
@ -396,16 +389,8 @@ class Series(Base):
|
||||
self.initial_index = s_index
|
||||
self.initial_val = val
|
||||
val = self.normalize_db_val(val)
|
||||
idx = None
|
||||
self.name_widget.clear()
|
||||
for i, c in enumerate(values):
|
||||
if c == val:
|
||||
idx = i
|
||||
self.name_widget.addItem(c)
|
||||
self.name_widget.update_items_cache(values)
|
||||
self.name_widget.setEditText('')
|
||||
if idx is not None:
|
||||
self.widgets[1].setCurrentIndex(idx)
|
||||
self.name_widget.show_initial_value(val)
|
||||
|
||||
def getter(self):
|
||||
n = unicode(self.name_widget.currentText()).strip()
|
||||
@ -860,8 +845,6 @@ class BulkSeries(BulkBase):
|
||||
self.idx_widget.setChecked(False)
|
||||
self.main_widget.set_separator(None)
|
||||
self.main_widget.update_items_cache(self.all_values)
|
||||
for c in self.all_values:
|
||||
self.main_widget.addItem(c)
|
||||
self.main_widget.setEditText('')
|
||||
self.a_c_checkbox.setChecked(False)
|
||||
|
||||
@ -1005,15 +988,8 @@ class BulkText(BulkBase):
|
||||
if not self.col_metadata['is_multiple']:
|
||||
val = self.get_initial_value(book_ids)
|
||||
self.initial_val = val = self.normalize_db_val(val)
|
||||
idx = None
|
||||
self.main_widget.blockSignals(True)
|
||||
for i, c in enumerate(self.all_values):
|
||||
if c == val:
|
||||
idx = i
|
||||
self.main_widget.addItem(c)
|
||||
self.main_widget.setEditText('')
|
||||
if idx is not None:
|
||||
self.main_widget.setCurrentIndex(idx)
|
||||
self.main_widget.show_initial_value(val)
|
||||
self.main_widget.blockSignals(False)
|
||||
|
||||
def commit(self, book_ids, notify=False):
|
||||
|
@ -6,8 +6,7 @@ __license__ = 'GPL v3'
|
||||
|
||||
from PyQt4.Qt import QDialog, QGridLayout, QLabel, QDialogButtonBox, \
|
||||
QApplication, QSpinBox, QToolButton, QIcon
|
||||
from calibre.ebooks.metadata import authors_to_string, string_to_authors
|
||||
from calibre.utils.icu import sort_key
|
||||
from calibre.ebooks.metadata import string_to_authors
|
||||
from calibre.gui2.complete import MultiCompleteComboBox
|
||||
from calibre.utils.config import tweaks
|
||||
|
||||
@ -56,17 +55,10 @@ class AddEmptyBookDialog(QDialog):
|
||||
self.authors_combo.setEditText(_('Unknown'))
|
||||
|
||||
def initialize_authors(self, db, author):
|
||||
all_authors = db.all_authors()
|
||||
all_authors.sort(key=lambda x : sort_key(x[1]))
|
||||
for i in all_authors:
|
||||
id, name = i
|
||||
name = [name.strip().replace('|', ',') for n in name.split(',')]
|
||||
self.authors_combo.addItem(authors_to_string(name))
|
||||
|
||||
au = author
|
||||
if not au:
|
||||
au = _('Unknown')
|
||||
self.authors_combo.setEditText(au.replace('|', ','))
|
||||
self.authors_combo.show_initial_value(au.replace('|', ','))
|
||||
|
||||
self.authors_combo.set_separator('&')
|
||||
self.authors_combo.set_space_before_sep(True)
|
||||
|
@ -876,38 +876,25 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
||||
all_authors = self.db.all_authors()
|
||||
all_authors.sort(key=lambda x : sort_key(x[1]))
|
||||
|
||||
for i in all_authors:
|
||||
id, name = i
|
||||
name = name.strip().replace('|', ',')
|
||||
self.authors.addItem(name)
|
||||
self.authors.setEditText('')
|
||||
|
||||
self.authors.set_separator('&')
|
||||
self.authors.set_space_before_sep(True)
|
||||
self.authors.set_add_separator(tweaks['authors_completer_append_separator'])
|
||||
self.authors.update_items_cache(self.db.all_author_names())
|
||||
self.authors.show_initial_value('')
|
||||
|
||||
def initialize_series(self):
|
||||
all_series = self.db.all_series()
|
||||
all_series.sort(key=lambda x : sort_key(x[1]))
|
||||
self.series.set_separator(None)
|
||||
self.series.update_items_cache([x[1] for x in all_series])
|
||||
|
||||
for i in all_series:
|
||||
id, name = i
|
||||
self.series.addItem(name)
|
||||
self.series.setEditText('')
|
||||
self.series.show_initial_value('')
|
||||
|
||||
def initialize_publisher(self):
|
||||
all_publishers = self.db.all_publishers()
|
||||
all_publishers.sort(key=lambda x : sort_key(x[1]))
|
||||
self.publisher.set_separator(None)
|
||||
self.publisher.update_items_cache([x[1] for x in all_publishers])
|
||||
|
||||
for i in all_publishers:
|
||||
id, name = i
|
||||
self.publisher.addItem(name)
|
||||
self.publisher.setEditText('')
|
||||
self.publisher.show_initial_value('')
|
||||
|
||||
def tag_editor(self, *args):
|
||||
d = TagEditor(self, self.db, None)
|
||||
|
@ -25,10 +25,6 @@ class SearchDialog(QDialog, Ui_Dialog):
|
||||
|
||||
all_authors = db.all_authors()
|
||||
all_authors.sort(key=lambda x : sort_key(x[1]))
|
||||
for i in all_authors:
|
||||
id, name = i
|
||||
name = name.strip().replace('|', ',')
|
||||
self.authors_box.addItem(name)
|
||||
self.authors_box.setEditText('')
|
||||
self.authors_box.set_separator('&')
|
||||
self.authors_box.set_space_before_sep(True)
|
||||
@ -39,10 +35,7 @@ class SearchDialog(QDialog, Ui_Dialog):
|
||||
all_series.sort(key=lambda x : sort_key(x[1]))
|
||||
self.series_box.set_separator(None)
|
||||
self.series_box.update_items_cache([x[1] for x in all_series])
|
||||
for i in all_series:
|
||||
id, name = i
|
||||
self.series_box.addItem(name)
|
||||
self.series_box.setEditText('')
|
||||
self.series_box.show_initial_value('')
|
||||
|
||||
all_tags = db.all_tags()
|
||||
self.tags_box.update_items_cache(all_tags)
|
||||
|
@ -32,8 +32,6 @@ class LanguagesEdit(MultiCompleteComboBox):
|
||||
all_items = sorted(self._lang_map.itervalues(),
|
||||
key=lambda x: (-pmap.get(x, 0), sort_key(x)))
|
||||
self.update_items_cache(all_items)
|
||||
for item in all_items:
|
||||
self.addItem(item)
|
||||
|
||||
@property
|
||||
def vals(self):
|
||||
|
@ -125,8 +125,6 @@ class TextDelegate(QStyledItemDelegate): # {{{
|
||||
editor.set_separator(None)
|
||||
complete_items = [i[1] for i in self.auto_complete_function()]
|
||||
editor.update_items_cache(complete_items)
|
||||
for item in sorted(complete_items, key=sort_key):
|
||||
editor.addItem(item)
|
||||
ct = index.data(Qt.DisplayRole).toString()
|
||||
editor.show_initial_value(ct)
|
||||
else:
|
||||
@ -166,8 +164,6 @@ class CompleteDelegate(QStyledItemDelegate): # {{{
|
||||
all_items = list(self.db.all_custom(
|
||||
label=self.db.field_metadata.key_to_label(col)))
|
||||
editor.update_items_cache(all_items)
|
||||
for item in sorted(all_items, key=sort_key):
|
||||
editor.addItem(item)
|
||||
ct = index.data(Qt.DisplayRole).toString()
|
||||
editor.show_initial_value(ct)
|
||||
else:
|
||||
|
@ -246,14 +246,6 @@ class AuthorsEdit(MultiCompleteComboBox):
|
||||
|
||||
def initialize(self, db, id_):
|
||||
self.books_to_refresh = set([])
|
||||
all_authors = db.all_authors()
|
||||
all_authors.sort(key=lambda x : sort_key(x[1]))
|
||||
self.clear()
|
||||
for i in all_authors:
|
||||
id, name = i
|
||||
name = name.strip().replace('|', ',')
|
||||
self.addItem(name)
|
||||
|
||||
self.set_separator('&')
|
||||
self.set_space_before_sep(True)
|
||||
self.set_add_separator(tweaks['authors_completer_append_separator'])
|
||||
@ -299,7 +291,6 @@ class AuthorsEdit(MultiCompleteComboBox):
|
||||
self.setEditText(' & '.join([x.strip() for x in val]))
|
||||
self.lineEdit().setCursorPosition(0)
|
||||
|
||||
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
def break_cycles(self):
|
||||
@ -488,19 +479,12 @@ class SeriesEdit(MultiCompleteComboBox):
|
||||
all_series.sort(key=lambda x : sort_key(x[1]))
|
||||
self.update_items_cache([x[1] for x in all_series])
|
||||
series_id = db.series_id(id_, index_is_id=True)
|
||||
idx, c = None, 0
|
||||
self.clear()
|
||||
inval = ''
|
||||
for i in all_series:
|
||||
id, name = i
|
||||
if id == series_id:
|
||||
idx = c
|
||||
self.addItem(name)
|
||||
c += 1
|
||||
|
||||
self.lineEdit().setText('')
|
||||
if idx is not None:
|
||||
self.setCurrentIndex(idx)
|
||||
self.original_val = self.current_val
|
||||
if i[0] == series_id:
|
||||
inval = i[1]
|
||||
break
|
||||
self.original_val = self.current_val = inval
|
||||
|
||||
def commit(self, db, id_):
|
||||
series = self.current_val
|
||||
@ -1373,17 +1357,12 @@ class PublisherEdit(MultiCompleteComboBox): # {{{
|
||||
all_publishers.sort(key=lambda x : sort_key(x[1]))
|
||||
self.update_items_cache([x[1] for x in all_publishers])
|
||||
publisher_id = db.publisher_id(id_, index_is_id=True)
|
||||
idx = None
|
||||
self.clear()
|
||||
for i, x in enumerate(all_publishers):
|
||||
id_, name = x
|
||||
if id_ == publisher_id:
|
||||
idx = i
|
||||
self.addItem(name)
|
||||
|
||||
self.setEditText('')
|
||||
if idx is not None:
|
||||
self.setCurrentIndex(idx)
|
||||
inval = ''
|
||||
for pid, name in all_publishers:
|
||||
if pid == publisher_id:
|
||||
inval = name
|
||||
break
|
||||
self.original_val = self.current_val = inval
|
||||
|
||||
def commit(self, db, id_):
|
||||
self.books_to_refresh |= db.set_publisher(id_, self.current_val,
|
||||
|
Loading…
x
Reference in New Issue
Block a user