diff --git a/src/calibre/ebooks/metadata/__init__.py b/src/calibre/ebooks/metadata/__init__.py index 8caca1f261..88d971ce4d 100644 --- a/src/calibre/ebooks/metadata/__init__.py +++ b/src/calibre/ebooks/metadata/__init__.py @@ -28,10 +28,14 @@ def authors_to_string(authors): else: return '' +_bracket_pat = re.compile(r'[\[({].*?[})\]]') def author_to_author_sort(author): + if not author: + return '' method = tweaks['author_sort_copy_method'] if method == 'copy' or (method == 'comma' and ',' in author): return author + author = _bracket_pat.sub('', author).strip() tokens = author.split() tokens = tokens[-1:] + tokens[:-1] if len(tokens) > 1: diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 3367ab14f6..46924cad1f 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -736,7 +736,9 @@ class OPF(object): def fget(self): ans = [] for tag in self.tags_path(self.metadata): - ans.append(self.get_text(tag)) + text = self.get_text(tag) + if text and text.strip(): + ans.extend([x.strip() for x in text.split(',')]) return ans def fset(self, val): diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index a3c51c287f..699978a92f 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -163,8 +163,7 @@ class ToolbarMixin(object): # {{{ self.convert_menu = cm pm = QMenu() - ap = self.action_preferences - pm.addAction(ap) + pm.addAction(QIcon(I('config.svg')), _('Preferences'), self.do_config) pm.addAction(QIcon(I('wizard.svg')), _('Run welcome wizard'), self.run_wizard) self.action_preferences.setMenu(pm) diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index ab0737b650..35bf7374a0 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -18,17 +18,20 @@ from calibre.utils.config import prefs from calibre.utils.search_query_parser import saved_searches class SearchLineEdit(QLineEdit): + key_pressed = pyqtSignal(object) + mouse_released = pyqtSignal(object) + focus_out = pyqtSignal(object) def keyPressEvent(self, event): - self.emit(SIGNAL('key_pressed(PyQt_PyObject)'), event) + self.key_pressed.emit(event) QLineEdit.keyPressEvent(self, event) def mouseReleaseEvent(self, event): - self.emit(SIGNAL('mouse_released(PyQt_PyObject)'), event) + self.mouse_released.emit(event) QLineEdit.mouseReleaseEvent(self, event) def focusOutEvent(self, event): - self.emit(SIGNAL('focus_out(PyQt_PyObject)'), event) + self.focus_out.emit(event) QLineEdit.focusOutEvent(self, event) def dropEvent(self, ev): @@ -68,10 +71,10 @@ class SearchBox2(QComboBox): self.normal_background = 'rgb(255, 255, 255, 0%)' self.line_edit = SearchLineEdit(self) self.setLineEdit(self.line_edit) - self.connect(self.line_edit, SIGNAL('key_pressed(PyQt_PyObject)'), - self.key_pressed, Qt.DirectConnection) - self.connect(self.line_edit, SIGNAL('mouse_released(PyQt_PyObject)'), - self.mouse_released, Qt.DirectConnection) + self.line_edit.key_pressed.connect(self.key_pressed, + type=Qt.DirectConnection) + self.line_edit.mouse_released.connect(self.mouse_released, + type=Qt.DirectConnection) self.setEditable(True) self.help_state = False self.as_you_type = True @@ -227,14 +230,13 @@ class SavedSearchBox(QComboBox): self.line_edit = SearchLineEdit(self) self.setLineEdit(self.line_edit) - self.connect(self.line_edit, SIGNAL('key_pressed(PyQt_PyObject)'), - self.key_pressed, Qt.DirectConnection) - self.connect(self.line_edit, SIGNAL('mouse_released(PyQt_PyObject)'), - self.mouse_released, Qt.DirectConnection) - self.connect(self.line_edit, SIGNAL('focus_out(PyQt_PyObject)'), - self.focus_out, Qt.DirectConnection) - self.connect(self, SIGNAL('activated(const QString&)'), - self.saved_search_selected) + self.line_edit.key_pressed.connect(self.key_pressed, + type=Qt.DirectConnection) + self.line_edit.mouse_released.connect(self.mouse_released, + type=Qt.DirectConnection) + self.line_edit.focus_out.connect(self.focus_out, + type=Qt.DirectConnection) + self.activated[str].connect(self.saved_search_selected) completer = QCompleter(self) # turn off auto-completion self.setCompleter(completer) @@ -282,7 +284,7 @@ class SavedSearchBox(QComboBox): if self.help_state: self.normalize_state() - def saved_search_selected (self, qname): + def saved_search_selected(self, qname): qname = unicode(qname) if qname is None or not qname.strip(): return diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index c7830187df..fe4aac12b5 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -136,6 +136,23 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.initialize_dynamic() def initialize_dynamic(self): + self.conn.executescript(''' + DROP TRIGGER IF EXISTS author_insert_trg; + CREATE TEMP TRIGGER author_insert_trg + AFTER INSERT ON authors + BEGIN + UPDATE authors SET sort=author_to_author_sort(NEW.name) WHERE id=NEW.id; + END; + DROP TRIGGER IF EXISTS author_update_trg; + CREATE TEMP TRIGGER author_update_trg + BEFORE UPDATE ON authors + BEGIN + UPDATE authors SET sort=author_to_author_sort(NEW.name) + WHERE id=NEW.id AND name <> NEW.name; + END; + ''') + self.conn.execute( + 'UPDATE authors SET sort=author_to_author_sort(name) WHERE sort IS NULL') self.conn.executescript(u''' CREATE TEMP VIEW IF NOT EXISTS tag_browser_news AS SELECT DISTINCT id, diff --git a/src/calibre/library/schema_upgrades.py b/src/calibre/library/schema_upgrades.py index a8ffd9cde4..1ba650f6fd 100644 --- a/src/calibre/library/schema_upgrades.py +++ b/src/calibre/library/schema_upgrades.py @@ -385,28 +385,5 @@ class SchemaUpgrade(object): if table.startswith('custom_column_') and link_table in tables: create_cust_tag_browser_view(table, link_table) - from calibre.ebooks.metadata import author_to_author_sort + self.conn.execute('UPDATE authors SET sort=author_to_author_sort(name)') - aut = self.conn.get('SELECT id, name FROM authors'); - records = [] - for (id, author) in aut: - records.append((id, author.replace('|', ','))) - for id,author in records: - self.conn.execute('UPDATE authors SET sort=? WHERE id=?', - (author_to_author_sort(author.replace('|', ',')).strip(), id)) - self.conn.commit() - self.conn.executescript(''' - DROP TRIGGER IF EXISTS author_insert_trg; - CREATE TRIGGER author_insert_trg - AFTER INSERT ON authors - BEGIN - UPDATE authors SET sort=author_to_author_sort(NEW.name) WHERE id=NEW.id; - END; - DROP TRIGGER IF EXISTS author_update_trg; - CREATE TRIGGER author_update_trg - BEFORE UPDATE ON authors - BEGIN - UPDATE authors SET sort=author_to_author_sort(NEW.name) - WHERE id=NEW.id AND name <> NEW.name; - END; - ''') diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py index 7e0458fba4..85954f6e0f 100644 --- a/src/calibre/library/sqlite.py +++ b/src/calibre/library/sqlite.py @@ -94,6 +94,9 @@ class Connection(sqlite.Connection): return ans[0] return ans.fetchall() +def _author_to_author_sort(x): + if not x: return '' + return author_to_author_sort(x.replace('|', ',')) class DBThread(Thread): @@ -121,7 +124,7 @@ class DBThread(Thread): else: self.conn.create_function('title_sort', 1, title_sort) self.conn.create_function('author_to_author_sort', 1, - lambda x: author_to_author_sort(x.replace('|', ','))) + _author_to_author_sort) self.conn.create_function('uuid4', 0, lambda : str(uuid.uuid4())) # Dummy functions for dynamically created filters self.conn.create_function('books_list_filter', 1, lambda x: 1)