Make tags completing line edit a stand alone widget. Use tag completing line edit in metadata single dialog.

This commit is contained in:
John Schember 2009-07-05 15:39:35 -04:00
parent 60bc41b33e
commit b8fc9de71d
4 changed files with 92 additions and 59 deletions

View File

@ -268,7 +268,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
aus = self.db.author_sort(row)
self.author_sort.setText(aus if aus else '')
tags = self.db.tags(row)
self.tags.setText(tags if tags else '')
self.tags.setText(', '.join(tags.split(',')) if tags else '')
self.tags.update_tags_cache(self.db.all_tags())
rating = self.db.rating(row)
if rating > 0:
self.rating.setValue(int(rating/2.))
@ -389,6 +390,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
if d.result() == QDialog.Accepted:
tag_string = ', '.join(d.tags)
self.tags.setText(tag_string)
self.tags.update_tags_cache(self.db.all_tags())
def fetch_cover(self):
isbn = unicode(self.isbn.text()).strip()

View File

@ -222,7 +222,7 @@
<item row="5" column="1" colspan="2">
<layout class="QHBoxLayout" name="_2">
<item>
<widget class="EnLineEdit" name="tags">
<widget class="TagsLineEdit" name="tags">
<property name="toolTip">
<string>Tags categorize the book. This is particularly useful while searching. &lt;br&gt;&lt;br&gt;They can be any words or phrases, separated by commas.</string>
</property>
@ -652,6 +652,11 @@
<extends>QComboBox</extends>
<header>widgets.h</header>
</customwidget>
<customwidget>
<class>TagsLineEdit</class>
<extends>QLineEdit</extends>
<header>widgets.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>title</tabstop>

View File

@ -19,7 +19,7 @@ from calibre.ptempfile import PersistentTemporaryFile
from calibre.library.database2 import FIELD_MAP
from calibre.gui2 import NONE, TableView, qstring_to_unicode, config, \
error_dialog
from calibre.gui2.widgets import EnLineEdit
from calibre.gui2.widgets import EnLineEdit, TagsLineEdit
from calibre.utils.search_query_parser import SearchQueryParser
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
from calibre.ebooks.metadata import string_to_authors, fmt_sidx
@ -118,50 +118,6 @@ class TextDelegate(QStyledItemDelegate):
editor = EnLineEdit(parent)
return editor
class CompleterLineEdit(EnLineEdit):
def __init__(self, *args):
EnLineEdit.__init__(self, *args)
QObject.connect(self, SIGNAL('textChanged(QString)'), self.text_changed)
def text_changed(self, text):
all_text = qstring_to_unicode(text)
text = all_text[:self.cursorPosition()]
prefix = text.split(',')[-1].strip()
text_tags = []
for t in all_text.split(','):
t1 = qstring_to_unicode(t).strip()
if t1 != '':
text_tags.append(t)
text_tags = list(set(text_tags))
self.emit(SIGNAL('text_changed(PyQt_PyObject, PyQt_PyObject)'), text_tags, prefix)
def complete_text(self, text):
cursor_pos = self.cursorPosition()
before_text = qstring_to_unicode(self.text())[:cursor_pos]
after_text = qstring_to_unicode(self.text())[cursor_pos:]
prefix_len = len(before_text.split(',')[-1].strip())
self.setText('%s%s, %s' % (before_text[:cursor_pos - prefix_len], text, after_text))
self.setCursorPosition(cursor_pos - prefix_len + len(text) + 2)
class TagsCompleter(QCompleter):
def __init__(self, parent, all_tags):
QCompleter.__init__(self, all_tags, parent)
self.all_tags = set(all_tags)
def update(self, text_tags, completion_prefix):
tags = list(self.all_tags.difference(text_tags))
model = QStringListModel(tags, self)
self.setModel(model)
self.setCompletionPrefix(completion_prefix)
if completion_prefix.strip() != '':
self.complete()
class TagsDelegate(QStyledItemDelegate):
def __init__(self, parent):
@ -172,18 +128,10 @@ class TagsDelegate(QStyledItemDelegate):
self.db = db
def createEditor(self, parent, option, index):
editor = CompleterLineEdit(parent)
if self.db:
completer = TagsCompleter(editor, self.db.all_tags())
completer.setCaseSensitivity(Qt.CaseInsensitive)
QObject.connect(editor,
SIGNAL('text_changed(PyQt_PyObject, PyQt_PyObject)'),
completer.update)
QObject.connect(completer, SIGNAL('activated(QString)'),
editor.complete_text)
completer.setWidget(editor)
editor = TagsLineEdit(parent, self.db.all_tags())
else:
editor = EnLineEdit(parent)
return editor
class BooksModel(QAbstractTableModel):

View File

@ -11,7 +11,7 @@ from PyQt4.Qt import QListView, QIcon, QFont, QLabel, QListWidget, \
QAbstractListModel, QVariant, Qt, SIGNAL, \
QRegExp, QSettings, QSize, QModelIndex, \
QAbstractButton, QPainter, QLineEdit, QComboBox, \
QMenu
QMenu, QStringListModel, QCompleter
from calibre.gui2 import human_readable, NONE, TableView, \
qstring_to_unicode, error_dialog
@ -500,6 +500,84 @@ class EnLineEdit(LineEditECM, QLineEdit):
pass
class TagsCompleter(QCompleter):
'''
A completer object that completes a list of tags. It is used in conjunction
with a CompleterLineEdit.
'''
def __init__(self, parent, all_tags):
QCompleter.__init__(self, all_tags, parent)
self.all_tags = set(all_tags)
def update(self, text_tags, completion_prefix):
tags = list(self.all_tags.difference(text_tags))
model = QStringListModel(tags, self)
self.setModel(model)
self.setCompletionPrefix(completion_prefix)
if completion_prefix.strip() != '':
self.complete()
def update_tags_cache(self, tags):
self.all_tags = set(tags)
model = QStringListModel(tags, self)
self.setModel(model)
class TagsLineEdit(EnLineEdit):
'''
A QLineEdit that can complete parts of text separated by separator.
'''
def __init__(self, parent=0, tags=[]):
EnLineEdit.__init__(self, parent)
self.separator = ','
self.connect(self, SIGNAL('textChanged(QString)'), self.text_changed)
self.completer = TagsCompleter(self, tags)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.connect(self,
SIGNAL('text_changed(PyQt_PyObject, PyQt_PyObject)'),
self.completer.update)
self.connect(self.completer, SIGNAL('activated(QString)'),
self.complete_text)
self.completer.setWidget(self)
def update_tags_cache(self, tags):
self.completer.update_tags_cache(tags)
def text_changed(self, text):
all_text = qstring_to_unicode(text)
text = all_text[:self.cursorPosition()]
prefix = text.split(',')[-1].strip()
text_tags = []
for t in all_text.split(self.separator):
t1 = qstring_to_unicode(t).strip()
if t1 != '':
text_tags.append(t)
text_tags = list(set(text_tags))
self.emit(SIGNAL('text_changed(PyQt_PyObject, PyQt_PyObject)'),
text_tags, prefix)
def complete_text(self, text):
cursor_pos = self.cursorPosition()
before_text = qstring_to_unicode(self.text())[:cursor_pos]
after_text = qstring_to_unicode(self.text())[cursor_pos:]
prefix_len = len(before_text.split(',')[-1].strip())
self.setText('%s%s%s %s' % (before_text[:cursor_pos - prefix_len],
text, self.separator, after_text))
self.setCursorPosition(cursor_pos - prefix_len + len(text) + 2)
class EnComboBox(QComboBox):
'''