mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix #8405 (Completion on multiple authors)
This commit is contained in:
commit
799b0f6033
@ -68,6 +68,9 @@ class MetadataWidget(Widget, Ui_Form):
|
|||||||
def initialize_metadata_options(self):
|
def initialize_metadata_options(self):
|
||||||
self.initialize_combos()
|
self.initialize_combos()
|
||||||
self.author.editTextChanged.connect(self.deduce_author_sort)
|
self.author.editTextChanged.connect(self.deduce_author_sort)
|
||||||
|
self.author.set_separator('&')
|
||||||
|
self.author.set_space_before_sep(True)
|
||||||
|
self.author.update_items_cache(self.db.all_author_names())
|
||||||
|
|
||||||
mi = self.db.get_metadata(self.book_id, index_is_id=True)
|
mi = self.db.get_metadata(self.book_id, index_is_id=True)
|
||||||
self.title.setText(mi.title)
|
self.title.setText(mi.title)
|
||||||
@ -75,7 +78,7 @@ class MetadataWidget(Widget, Ui_Form):
|
|||||||
self.publisher.setCurrentIndex(self.publisher.findText(mi.publisher))
|
self.publisher.setCurrentIndex(self.publisher.findText(mi.publisher))
|
||||||
self.author_sort.setText(mi.author_sort if mi.author_sort 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.setText(', '.join(mi.tags if mi.tags else []))
|
||||||
self.tags.update_tags_cache(self.db.all_tags())
|
self.tags.update_items_cache(self.db.all_tags())
|
||||||
self.comment.setPlainText(mi.comments if mi.comments else '')
|
self.comment.setPlainText(mi.comments if mi.comments else '')
|
||||||
if mi.series:
|
if mi.series:
|
||||||
self.series.setCurrentIndex(self.series.findText(mi.series))
|
self.series.setCurrentIndex(self.series.findText(mi.series))
|
||||||
|
@ -190,7 +190,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="TagsLineEdit" name="tags">
|
<widget class="CompleteLineEdit" name="tags">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -255,7 +255,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="EnComboBox" name="author">
|
<widget class="CompleteComboBox" name="author">
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -310,7 +310,12 @@
|
|||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TagsLineEdit</class>
|
<class>CompleteComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>widgets.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CompleteLineEdit</class>
|
||||||
<extends>QLineEdit</extends>
|
<extends>QLineEdit</extends>
|
||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
@ -14,7 +14,7 @@ from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
|
|||||||
QPushButton
|
QPushButton
|
||||||
|
|
||||||
from calibre.utils.date import qt_to_dt, now
|
from calibre.utils.date import qt_to_dt, now
|
||||||
from calibre.gui2.widgets import TagsLineEdit, EnComboBox
|
from calibre.gui2.widgets import CompleteLineEdit, EnComboBox
|
||||||
from calibre.gui2.comments_editor import Editor as CommentsEditor
|
from calibre.gui2.comments_editor import Editor as CommentsEditor
|
||||||
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
|
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
|
||||||
from calibre.utils.config import tweaks
|
from calibre.utils.config import tweaks
|
||||||
@ -212,7 +212,7 @@ class Text(Base):
|
|||||||
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
||||||
values.sort(key=sort_key)
|
values.sort(key=sort_key)
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
w = TagsLineEdit(parent, values)
|
w = CompleteLineEdit(parent, values)
|
||||||
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
else:
|
else:
|
||||||
w = EnComboBox(parent)
|
w = EnComboBox(parent)
|
||||||
@ -226,7 +226,7 @@ class Text(Base):
|
|||||||
val = self.normalize_db_val(val)
|
val = self.normalize_db_val(val)
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
self.setter(val)
|
self.setter(val)
|
||||||
self.widgets[1].update_tags_cache(self.all_values)
|
self.widgets[1].update_items_cache(self.all_values)
|
||||||
else:
|
else:
|
||||||
idx = None
|
idx = None
|
||||||
for i, c in enumerate(self.all_values):
|
for i, c in enumerate(self.all_values):
|
||||||
@ -656,7 +656,7 @@ class RemoveTags(QWidget):
|
|||||||
layout.setSpacing(5)
|
layout.setSpacing(5)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
self.tags_box = TagsLineEdit(parent, values)
|
self.tags_box = CompleteLineEdit(parent, values)
|
||||||
layout.addWidget(self.tags_box, stretch = 1)
|
layout.addWidget(self.tags_box, stretch = 1)
|
||||||
# self.tags_box.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
# self.tags_box.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
|
|
||||||
@ -678,7 +678,7 @@ class BulkText(BulkBase):
|
|||||||
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
||||||
values.sort(key=sort_key)
|
values.sort(key=sort_key)
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
w = TagsLineEdit(parent, values)
|
w = CompleteLineEdit(parent, values)
|
||||||
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
self.widgets = [QLabel('&'+self.col_metadata['name']+': ' +
|
self.widgets = [QLabel('&'+self.col_metadata['name']+': ' +
|
||||||
_('tags to add'), parent), w]
|
_('tags to add'), parent), w]
|
||||||
@ -697,7 +697,7 @@ class BulkText(BulkBase):
|
|||||||
|
|
||||||
def initialize(self, book_ids):
|
def initialize(self, book_ids):
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
self.widgets[1].update_tags_cache(self.all_values)
|
self.widgets[1].update_items_cache(self.all_values)
|
||||||
else:
|
else:
|
||||||
val = self.get_initial_value(book_ids)
|
val = self.get_initial_value(book_ids)
|
||||||
self.initial_val = val = self.normalize_db_val(val)
|
self.initial_val = val = self.normalize_db_val(val)
|
||||||
|
@ -279,8 +279,8 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
self.changed = False
|
self.changed = False
|
||||||
|
|
||||||
all_tags = self.db.all_tags()
|
all_tags = self.db.all_tags()
|
||||||
self.tags.update_tags_cache(all_tags)
|
self.tags.update_items_cache(all_tags)
|
||||||
self.remove_tags.update_tags_cache(all_tags)
|
self.remove_tags.update_items_cache(all_tags)
|
||||||
|
|
||||||
self.initialize_combos()
|
self.initialize_combos()
|
||||||
|
|
||||||
@ -726,6 +726,10 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
name = name.strip().replace('|', ',')
|
name = name.strip().replace('|', ',')
|
||||||
self.authors.addItem(name)
|
self.authors.addItem(name)
|
||||||
self.authors.setEditText('')
|
self.authors.setEditText('')
|
||||||
|
|
||||||
|
self.authors.set_separator('&')
|
||||||
|
self.authors.set_space_before_sep(True)
|
||||||
|
self.authors.update_items_cache(self.db.all_author_names())
|
||||||
|
|
||||||
def initialize_series(self):
|
def initialize_series(self):
|
||||||
all_series = self.db.all_series()
|
all_series = self.db.all_series()
|
||||||
@ -751,8 +755,8 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
if d.result() == QDialog.Accepted:
|
if d.result() == QDialog.Accepted:
|
||||||
tag_string = ', '.join(d.tags)
|
tag_string = ', '.join(d.tags)
|
||||||
self.tags.setText(tag_string)
|
self.tags.setText(tag_string)
|
||||||
self.tags.update_tags_cache(self.db.all_tags())
|
self.tags.update_items_cache(self.db.all_tags())
|
||||||
self.remove_tags.update_tags_cache(self.db.all_tags())
|
self.remove_tags.update_items_cache(self.db.all_tags())
|
||||||
|
|
||||||
def auto_number_changed(self, state):
|
def auto_number_changed(self, state):
|
||||||
if state:
|
if state:
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="EnComboBox" name="authors">
|
<widget class="CompleteComboBox" name="authors">
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -195,7 +195,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="TagsLineEdit" name="tags">
|
<widget class="CompleteLineEdit" name="tags">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -229,7 +229,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="TagsLineEdit" name="remove_tags">
|
<widget class="CompleteLineEdit" name="remove_tags">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Comma separated list of tags to remove from the books. </string>
|
<string>Comma separated list of tags to remove from the books. </string>
|
||||||
</property>
|
</property>
|
||||||
@ -955,7 +955,12 @@ not multiple and the destination field is multiple</string>
|
|||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TagsLineEdit</class>
|
<class>CompleteComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>widgets.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CompleteLineEdit</class>
|
||||||
<extends>QLineEdit</extends>
|
<extends>QLineEdit</extends>
|
||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
@ -556,7 +556,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
tags = self.db.tags(row)
|
tags = self.db.tags(row)
|
||||||
self.original_tags = ', '.join(tags.split(',')) if tags else ''
|
self.original_tags = ', '.join(tags.split(',')) if tags else ''
|
||||||
self.tags.setText(self.original_tags)
|
self.tags.setText(self.original_tags)
|
||||||
self.tags.update_tags_cache(self.db.all_tags())
|
self.tags.update_items_cache(self.db.all_tags())
|
||||||
rating = self.db.rating(row)
|
rating = self.db.rating(row)
|
||||||
if rating > 0:
|
if rating > 0:
|
||||||
self.rating.setValue(int(rating/2.))
|
self.rating.setValue(int(rating/2.))
|
||||||
@ -724,6 +724,10 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
au = _('Unknown')
|
au = _('Unknown')
|
||||||
au = ' & '.join([a.strip().replace('|', ',') for a in au.split(',')])
|
au = ' & '.join([a.strip().replace('|', ',') for a in au.split(',')])
|
||||||
self.authors.setEditText(au)
|
self.authors.setEditText(au)
|
||||||
|
|
||||||
|
self.authors.set_separator('&')
|
||||||
|
self.authors.set_space_before_sep(True)
|
||||||
|
self.authors.update_items_cache(self.db.all_author_names())
|
||||||
|
|
||||||
def initialize_series(self):
|
def initialize_series(self):
|
||||||
self.series.setSizeAdjustPolicy(self.series.AdjustToContentsOnFirstShow)
|
self.series.setSizeAdjustPolicy(self.series.AdjustToContentsOnFirstShow)
|
||||||
@ -776,7 +780,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
if d.result() == QDialog.Accepted:
|
if d.result() == QDialog.Accepted:
|
||||||
tag_string = ', '.join(d.tags)
|
tag_string = ', '.join(d.tags)
|
||||||
self.tags.setText(tag_string)
|
self.tags.setText(tag_string)
|
||||||
self.tags.update_tags_cache(self.db.all_tags())
|
self.tags.update_items_cache(self.db.all_tags())
|
||||||
|
|
||||||
|
|
||||||
def fetch_metadata(self):
|
def fetch_metadata(self):
|
||||||
|
@ -240,7 +240,7 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="EnComboBox" name="authors">
|
<widget class="CompleteComboBox" name="authors">
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -335,7 +335,7 @@ If the box is colored green, then text matches the individual author's sort stri
|
|||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<layout class="QHBoxLayout" name="_2">
|
<layout class="QHBoxLayout" name="_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="TagsLineEdit" name="tags">
|
<widget class="CompleteLineEdit" name="tags">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -842,10 +842,15 @@ If the box is colored green, then text matches the individual author's sort stri
|
|||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TagsLineEdit</class>
|
<class>CompleteLineEdit</class>
|
||||||
<extends>QLineEdit</extends>
|
<extends>QLineEdit</extends>
|
||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CompleteComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>widgets.h</header>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>FormatList</class>
|
<class>FormatList</class>
|
||||||
<extends>QListWidget</extends>
|
<extends>QListWidget</extends>
|
||||||
|
@ -31,6 +31,9 @@ class SearchDialog(QDialog, Ui_Dialog):
|
|||||||
self.authors_box.setEditText('')
|
self.authors_box.setEditText('')
|
||||||
self.authors_box.completer().setCompletionMode(QCompleter.PopupCompletion)
|
self.authors_box.completer().setCompletionMode(QCompleter.PopupCompletion)
|
||||||
self.authors_box.setAutoCompletionCaseSensitivity(Qt.CaseInsensitive)
|
self.authors_box.setAutoCompletionCaseSensitivity(Qt.CaseInsensitive)
|
||||||
|
self.authors_box.set_separator('&')
|
||||||
|
self.authors_box.set_space_before_sep(True)
|
||||||
|
self.authors_box.update_items_cache(db.all_author_names())
|
||||||
|
|
||||||
all_series = db.all_series()
|
all_series = db.all_series()
|
||||||
all_series.sort(key=lambda x : sort_key(x[1]))
|
all_series.sort(key=lambda x : sort_key(x[1]))
|
||||||
@ -42,7 +45,7 @@ class SearchDialog(QDialog, Ui_Dialog):
|
|||||||
self.series_box.setAutoCompletionCaseSensitivity(Qt.CaseInsensitive)
|
self.series_box.setAutoCompletionCaseSensitivity(Qt.CaseInsensitive)
|
||||||
|
|
||||||
all_tags = db.all_tags()
|
all_tags = db.all_tags()
|
||||||
self.tags_box.update_tags_cache(all_tags)
|
self.tags_box.update_items_cache(all_tags)
|
||||||
|
|
||||||
self.box_last_values = copy.deepcopy(box_values)
|
self.box_last_values = copy.deepcopy(box_values)
|
||||||
if self.box_last_values:
|
if self.box_last_values:
|
||||||
|
@ -265,7 +265,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="EnComboBox" name="authors_box">
|
<widget class="CompleteComboBox" name="authors_box">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Enter an author's name. Only one author can be used.</string>
|
<string>Enter an author's name. Only one author can be used.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -279,7 +279,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="TagsLineEdit" name="tags_box">
|
<widget class="CompleteLineEdit" name="tags_box">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Enter tags separated by spaces</string>
|
<string>Enter tags separated by spaces</string>
|
||||||
</property>
|
</property>
|
||||||
@ -360,10 +360,15 @@
|
|||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TagsLineEdit</class>
|
<class>CompleteLineEdit</class>
|
||||||
<extends>QLineEdit</extends>
|
<extends>QLineEdit</extends>
|
||||||
<header>widgets.h</header>
|
<header>widgets.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CompleteComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>widgets.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>all</tabstop>
|
<tabstop>all</tabstop>
|
||||||
|
@ -16,7 +16,7 @@ from PyQt4.Qt import QColor, Qt, QModelIndex, QSize, \
|
|||||||
QComboBox, QTextDocument
|
QComboBox, QTextDocument
|
||||||
|
|
||||||
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
|
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
|
||||||
from calibre.gui2.widgets import EnLineEdit, TagsLineEdit
|
from calibre.gui2.widgets import EnLineEdit, CompleteLineEdit
|
||||||
from calibre.utils.date import now, format_date
|
from calibre.utils.date import now, format_date
|
||||||
from calibre.utils.config import tweaks
|
from calibre.utils.config import tweaks
|
||||||
from calibre.utils.formatter import validation_formatter
|
from calibre.utils.formatter import validation_formatter
|
||||||
@ -173,9 +173,9 @@ class TagsDelegate(QStyledItemDelegate): # {{{
|
|||||||
if self.db:
|
if self.db:
|
||||||
col = index.model().column_map[index.column()]
|
col = index.model().column_map[index.column()]
|
||||||
if not index.model().is_custom_column(col):
|
if not index.model().is_custom_column(col):
|
||||||
editor = TagsLineEdit(parent, self.db.all_tags())
|
editor = CompleteLineEdit(parent, self.db.all_tags())
|
||||||
else:
|
else:
|
||||||
editor = TagsLineEdit(parent,
|
editor = CompleteLineEdit(parent,
|
||||||
sorted(list(self.db.all_custom(label=self.db.field_metadata.key_to_label(col))),
|
sorted(list(self.db.all_custom(label=self.db.field_metadata.key_to_label(col))),
|
||||||
key=sort_key))
|
key=sort_key))
|
||||||
return editor
|
return editor
|
||||||
@ -184,6 +184,31 @@ class TagsDelegate(QStyledItemDelegate): # {{{
|
|||||||
return editor
|
return editor
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
class CompleteDelegate(QStyledItemDelegate): # {{{
|
||||||
|
def __init__(self, parent, sep, items_func_name, space_before_sep=False):
|
||||||
|
QStyledItemDelegate.__init__(self, parent)
|
||||||
|
self.sep = sep
|
||||||
|
self.items_func_name = items_func_name
|
||||||
|
self.space_before_sep = space_before_sep
|
||||||
|
|
||||||
|
def set_database(self, db):
|
||||||
|
self.db = db
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
if self.db and hasattr(self.db, self.items_func_name):
|
||||||
|
col = index.model().column_map[index.column()]
|
||||||
|
if not index.model().is_custom_column(col):
|
||||||
|
editor = CompleteLineEdit(parent, getattr(self.db, self.items_func_name)(),
|
||||||
|
self.sep, self.space_before_sep)
|
||||||
|
else:
|
||||||
|
editor = CompleteLineEdit(parent,
|
||||||
|
sorted(list(self.db.all_custom(label=self.db.field_metadata.key_to_label(col))),
|
||||||
|
key=sort_key), self.sep, self.space_before_sep)
|
||||||
|
else:
|
||||||
|
editor = EnLineEdit(parent)
|
||||||
|
return editor
|
||||||
|
# }}}
|
||||||
|
|
||||||
class CcDateDelegate(QStyledItemDelegate): # {{{
|
class CcDateDelegate(QStyledItemDelegate): # {{{
|
||||||
'''
|
'''
|
||||||
Delegate for custom columns dates. Because this delegate stores the
|
Delegate for custom columns dates. Because this delegate stores the
|
||||||
|
@ -13,7 +13,7 @@ from PyQt4.Qt import QTableView, Qt, QAbstractItemView, QMenu, pyqtSignal, \
|
|||||||
QPoint, QPixmap, QUrl, QImage, QPainter, QColor, QRect
|
QPoint, QPixmap, QUrl, QImage, QPainter, QColor, QRect
|
||||||
|
|
||||||
from calibre.gui2.library.delegates import RatingDelegate, PubDateDelegate, \
|
from calibre.gui2.library.delegates import RatingDelegate, PubDateDelegate, \
|
||||||
TextDelegate, DateDelegate, TagsDelegate, CcTextDelegate, \
|
TextDelegate, DateDelegate, CompleteDelegate, CcTextDelegate, \
|
||||||
CcBoolDelegate, CcCommentsDelegate, CcDateDelegate, CcTemplateDelegate, \
|
CcBoolDelegate, CcCommentsDelegate, CcDateDelegate, CcTemplateDelegate, \
|
||||||
CcEnumDelegate
|
CcEnumDelegate
|
||||||
from calibre.gui2.library.models import BooksModel, DeviceBooksModel
|
from calibre.gui2.library.models import BooksModel, DeviceBooksModel
|
||||||
@ -76,8 +76,8 @@ class BooksView(QTableView): # {{{
|
|||||||
self.rating_delegate = RatingDelegate(self)
|
self.rating_delegate = RatingDelegate(self)
|
||||||
self.timestamp_delegate = DateDelegate(self)
|
self.timestamp_delegate = DateDelegate(self)
|
||||||
self.pubdate_delegate = PubDateDelegate(self)
|
self.pubdate_delegate = PubDateDelegate(self)
|
||||||
self.tags_delegate = TagsDelegate(self)
|
self.tags_delegate = CompleteDelegate(self, ',', 'all_tags')
|
||||||
self.authors_delegate = TextDelegate(self)
|
self.authors_delegate = CompleteDelegate(self, '&', 'all_author_names', True)
|
||||||
self.series_delegate = TextDelegate(self)
|
self.series_delegate = TextDelegate(self)
|
||||||
self.publisher_delegate = TextDelegate(self)
|
self.publisher_delegate = TextDelegate(self)
|
||||||
self.text_delegate = TextDelegate(self)
|
self.text_delegate = TextDelegate(self)
|
||||||
@ -410,8 +410,7 @@ class BooksView(QTableView): # {{{
|
|||||||
self.save_state()
|
self.save_state()
|
||||||
self._model.set_database(db)
|
self._model.set_database(db)
|
||||||
self.tags_delegate.set_database(db)
|
self.tags_delegate.set_database(db)
|
||||||
self.authors_delegate.set_auto_complete_function(
|
self.authors_delegate.set_database(db)
|
||||||
lambda: [(x, y.replace('|', ',')) for (x, y) in db.all_authors()])
|
|
||||||
self.series_delegate.set_auto_complete_function(db.all_series)
|
self.series_delegate.set_auto_complete_function(db.all_series)
|
||||||
self.publisher_delegate.set_auto_complete_function(db.all_publishers)
|
self.publisher_delegate.set_auto_complete_function(db.all_publishers)
|
||||||
|
|
||||||
|
@ -426,46 +426,47 @@ class EnLineEdit(LineEditECM, QLineEdit):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TagsCompleter(QCompleter):
|
class ItemsCompleter(QCompleter):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
A completer object that completes a list of tags. It is used in conjunction
|
A completer object that completes a list of tags. It is used in conjunction
|
||||||
with a CompleterLineEdit.
|
with a CompleterLineEdit.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, parent, all_tags):
|
def __init__(self, parent, all_items):
|
||||||
QCompleter.__init__(self, all_tags, parent)
|
QCompleter.__init__(self, all_items, parent)
|
||||||
self.all_tags = set(all_tags)
|
self.all_items = set(all_items)
|
||||||
|
|
||||||
def update(self, text_tags, completion_prefix):
|
def update(self, text_items, completion_prefix):
|
||||||
tags = list(self.all_tags.difference(text_tags))
|
items = list(self.all_items.difference(text_items))
|
||||||
model = QStringListModel(tags, self)
|
model = QStringListModel(items, self)
|
||||||
self.setModel(model)
|
self.setModel(model)
|
||||||
|
|
||||||
self.setCompletionPrefix(completion_prefix)
|
self.setCompletionPrefix(completion_prefix)
|
||||||
if completion_prefix.strip() != '':
|
if completion_prefix.strip() != '':
|
||||||
self.complete()
|
self.complete()
|
||||||
|
|
||||||
def update_tags_cache(self, tags):
|
def update_items_cache(self, items):
|
||||||
self.all_tags = set(tags)
|
self.all_items = set(items)
|
||||||
model = QStringListModel(tags, self)
|
model = QStringListModel(items, self)
|
||||||
self.setModel(model)
|
self.setModel(model)
|
||||||
|
|
||||||
|
|
||||||
class TagsLineEdit(EnLineEdit):
|
class CompleteLineEdit(EnLineEdit):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
A QLineEdit that can complete parts of text separated by separator.
|
A QLineEdit that can complete parts of text separated by separator.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, parent=0, tags=[]):
|
def __init__(self, parent=0, complete_items=[], sep=',', space_before_sep=False):
|
||||||
EnLineEdit.__init__(self, parent)
|
EnLineEdit.__init__(self, parent)
|
||||||
|
|
||||||
self.separator = ','
|
self.separator = sep
|
||||||
|
self.space_before_sep = space_before_sep
|
||||||
|
|
||||||
self.connect(self, SIGNAL('textChanged(QString)'), self.text_changed)
|
self.connect(self, SIGNAL('textChanged(QString)'), self.text_changed)
|
||||||
|
|
||||||
self.completer = TagsCompleter(self, tags)
|
self.completer = ItemsCompleter(self, complete_items)
|
||||||
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
|
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
|
||||||
|
|
||||||
self.connect(self,
|
self.connect(self,
|
||||||
@ -476,32 +477,43 @@ class TagsLineEdit(EnLineEdit):
|
|||||||
|
|
||||||
self.completer.setWidget(self)
|
self.completer.setWidget(self)
|
||||||
|
|
||||||
def update_tags_cache(self, tags):
|
def update_items_cache(self, complete_items):
|
||||||
self.completer.update_tags_cache(tags)
|
self.completer.update_items_cache(complete_items)
|
||||||
|
|
||||||
|
def set_separator(self, sep):
|
||||||
|
self.separator = sep
|
||||||
|
|
||||||
|
def set_space_before_sep(self, space_before):
|
||||||
|
self.space_before_sep = space_before
|
||||||
|
|
||||||
def text_changed(self, text):
|
def text_changed(self, text):
|
||||||
all_text = unicode(text)
|
all_text = unicode(text)
|
||||||
text = all_text[:self.cursorPosition()]
|
text = all_text[:self.cursorPosition()]
|
||||||
prefix = text.split(',')[-1].strip()
|
prefix = text.split(self.separator)[-1].strip()
|
||||||
|
|
||||||
text_tags = []
|
text_items = []
|
||||||
for t in all_text.split(self.separator):
|
for t in all_text.split(self.separator):
|
||||||
t1 = unicode(t).strip()
|
t1 = unicode(t).strip()
|
||||||
if t1 != '':
|
if t1 != '':
|
||||||
text_tags.append(t)
|
text_items.append(t)
|
||||||
text_tags = list(set(text_tags))
|
text_items = list(set(text_items))
|
||||||
|
|
||||||
self.emit(SIGNAL('text_changed(PyQt_PyObject, PyQt_PyObject)'),
|
self.emit(SIGNAL('text_changed(PyQt_PyObject, PyQt_PyObject)'),
|
||||||
text_tags, prefix)
|
text_items, prefix)
|
||||||
|
|
||||||
def complete_text(self, text):
|
def complete_text(self, text):
|
||||||
cursor_pos = self.cursorPosition()
|
cursor_pos = self.cursorPosition()
|
||||||
before_text = unicode(self.text())[:cursor_pos]
|
before_text = unicode(self.text())[:cursor_pos]
|
||||||
after_text = unicode(self.text())[cursor_pos:]
|
after_text = unicode(self.text())[cursor_pos:]
|
||||||
prefix_len = len(before_text.split(',')[-1].strip())
|
prefix_len = len(before_text.split(self.separator)[-1].strip())
|
||||||
self.setText('%s%s%s %s' % (before_text[:cursor_pos - prefix_len],
|
if self.space_before_sep:
|
||||||
text, self.separator, after_text))
|
complete_text_pat = '%s%s %s %s'
|
||||||
self.setCursorPosition(cursor_pos - prefix_len + len(text) + 2)
|
len_extra = 3
|
||||||
|
else:
|
||||||
|
complete_text_pat = '%s%s%s %s'
|
||||||
|
len_extra = 2
|
||||||
|
self.setText(complete_text_pat % (before_text[:cursor_pos - prefix_len], text, self.separator, after_text))
|
||||||
|
self.setCursorPosition(cursor_pos - prefix_len + len(text) + len_extra)
|
||||||
|
|
||||||
|
|
||||||
class EnComboBox(QComboBox):
|
class EnComboBox(QComboBox):
|
||||||
@ -528,6 +540,22 @@ class EnComboBox(QComboBox):
|
|||||||
idx = 0
|
idx = 0
|
||||||
self.setCurrentIndex(idx)
|
self.setCurrentIndex(idx)
|
||||||
|
|
||||||
|
class CompleteComboBox(EnComboBox):
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
EnComboBox.__init__(self, *args)
|
||||||
|
self.setLineEdit(CompleteLineEdit(self))
|
||||||
|
|
||||||
|
def update_items_cache(self, complete_items):
|
||||||
|
self.lineEdit().update_items_cache(complete_items)
|
||||||
|
|
||||||
|
def set_separator(self, sep):
|
||||||
|
self.lineEdit().set_separator(sep)
|
||||||
|
|
||||||
|
def set_space_before_sep(self, space_before):
|
||||||
|
self.lineEdit().set_space_before_sep(space_before)
|
||||||
|
|
||||||
|
|
||||||
class HistoryLineEdit(QComboBox):
|
class HistoryLineEdit(QComboBox):
|
||||||
|
|
||||||
lost_focus = pyqtSignal()
|
lost_focus = pyqtSignal()
|
||||||
|
@ -1060,6 +1060,10 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
return [ (i[0], i[1]) for i in \
|
return [ (i[0], i[1]) for i in \
|
||||||
self.conn.get('SELECT id, name FROM authors')]
|
self.conn.get('SELECT id, name FROM authors')]
|
||||||
|
|
||||||
|
def all_author_names(self):
|
||||||
|
return filter(None, [i[0].strip().replace('|', ',') for i in self.conn.get(
|
||||||
|
'SELECT name FROM authors')])
|
||||||
|
|
||||||
def all_publishers(self):
|
def all_publishers(self):
|
||||||
return [ (i[0], i[1]) for i in \
|
return [ (i[0], i[1]) for i in \
|
||||||
self.conn.get('SELECT id, name FROM publishers')]
|
self.conn.get('SELECT id, name FROM publishers')]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user