From 470b6792a9bda9a3fb523c94b0760c9896a46704 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 18 Aug 2009 17:40:20 -0600 Subject: [PATCH 1/3] Add button to read metadata from a particular format to the Edit meta informationn dialog --- src/calibre/gui2/dialogs/metadata_single.py | 41 ++++++- src/calibre/gui2/dialogs/metadata_single.ui | 31 ++++- src/calibre/library/database2.py | 125 +------------------- 3 files changed, 66 insertions(+), 131 deletions(-) diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 4f04590b1d..42785e3f3e 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -156,7 +156,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): self.formats.takeItem(row.row()) self.formats_changed = True - def set_cover(self): + def get_selected_format_metadata(self): row = self.formats.currentRow() fmt = self.formats.item(row) if fmt is None: @@ -165,7 +165,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): if fmt is None: error_dialog(self, _('No format selected'), _('No format selected')).exec_() - return + return None, None ext = fmt.ext.lower() if fmt.path is None: stream = self.db.format(self.row, ext, as_file=True) @@ -173,9 +173,44 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): stream = open(fmt.path, 'r+b') try: mi = get_metadata(stream, ext) + return mi, ext except: error_dialog(self, _('Could not read metadata'), _('Could not read metadata from %s format')%ext).exec_() + return None, None + + def set_metadata_from_format(self): + mi, ext = self.get_selected_format_metadata() + if mi is None: + return + if mi.title: + self.title.setText(mi.title) + if mi.authors: + self.authors.setEditText(authors_to_string(mi.authors)) + if mi.author_sort: + self.author_sort.setText(mi.author_sort) + if mi.rating is not None: + try: + self.rating.setValue(mi.rating) + except: + pass + if mi.publisher: + self.publisher.setEditText(mi.publisher) + if mi.tags: + self.tags.setText(', '.join(mi.tags)) + if mi.isbn: + self.isbn.setText(mi.isbn) + if mi.pubdate: + self.pubdate.setDate(QDate(mi.pubdate.year, mi.pubdate.month, + mi.pubdate.day)) + if mi.series: + self.series.setEditText(mi.series) + if mi.series_index is not None: + self.series_index.setValue(float(mi.series_index)) + + def set_cover(self): + mi, ext = self.get_selected_format_metadata() + if mi is None: return cdata = None if mi.cover and os.access(mi.cover, os.R_OK): @@ -253,6 +288,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): self.connect(self.formats, SIGNAL('itemDoubleClicked(QListWidgetItem*)'), self.show_format) self.connect(self.button_set_cover, SIGNAL('clicked()'), self.set_cover) + self.connect(self.button_set_metadata, SIGNAL('clicked()'), + self.set_metadata_from_format) self.connect(self.reset_cover, SIGNAL('clicked()'), self.do_reset_cover) self.connect(self.swap_button, SIGNAL('clicked()'), self.swap_title_author) self.timeout = float(prefs['network_timeout']) diff --git a/src/calibre/gui2/dialogs/metadata_single.ui b/src/calibre/gui2/dialogs/metadata_single.ui index f7cd6738d0..a20348885d 100644 --- a/src/calibre/gui2/dialogs/metadata_single.ui +++ b/src/calibre/gui2/dialogs/metadata_single.ui @@ -44,7 +44,7 @@ 0 0 879 - 710 + 711 @@ -415,7 +415,7 @@ - + @@ -437,7 +437,7 @@ - + Add a new format for this book to the database @@ -457,7 +457,7 @@ - + Remove the selected formats for this book from the database. @@ -477,7 +477,7 @@ - + Set the cover for the book from the selected format @@ -497,6 +497,26 @@ + + + + Update metadata from the metadata in the selected format + + + + + + + :/images/edit_input.svg:/images/edit_input.svg + + + + 32 + 32 + + + + @@ -680,7 +700,6 @@ fetch_metadata_button formats add_format_button - button_set_cover remove_format_button cover_path cover_button diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 3ab4f97f83..f1a9ea18dd 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -27,15 +27,12 @@ from calibre.library.sqlite import connect, IntegrityError from calibre.utils.search_query_parser import SearchQueryParser from calibre.ebooks.metadata import string_to_authors, authors_to_string, \ MetaInformation, authors_to_sort_string -from calibre.ebooks.metadata.meta import get_metadata, set_metadata, \ - metadata_from_formats -from calibre.ebooks.metadata.opf2 import metadata_to_opf +from calibre.ebooks.metadata.meta import get_metadata, metadata_from_formats from calibre.constants import preferred_encoding, iswindows, isosx, filesystem_encoding from calibre.ptempfile import PersistentTemporaryFile from calibre.customize.ui import run_plugins_on_import -from calibre.utils.filenames import ascii_filename, shorten_components_to, \ - supports_long_names +from calibre.utils.filenames import ascii_filename from calibre.ebooks import BOOK_EXTENSIONS if iswindows: @@ -1587,124 +1584,6 @@ books_series_link feeds progress.reset() return len(books) - def export_to_dir(self, dir, indices, byauthor=False, single_dir=False, - index_is_id=False, callback=None): - if not os.path.exists(dir): - raise IOError('Target directory does not exist: '+dir) - by_author = {} - count = 0 - path_len, au_len = (1000, 500) if supports_long_names(dir) else (240, 50) - for index in indices: - id = index if index_is_id else self.id(index) - au = self.conn.get('SELECT author_sort FROM books WHERE id=?', - (id,), all=False) - if not au: - au = self.authors(index, index_is_id=index_is_id) - if not au: - au = _('Unknown') - au = au.split(',')[0] - if not by_author.has_key(au): - by_author[au] = [] - by_author[au].append(index) - for au in by_author.keys(): - aname = ascii_filename(au)[:au_len] - apath = os.path.abspath(os.path.join(dir, aname)) - if not single_dir and not os.path.exists(apath): - os.mkdir(apath) - for idx in by_author[au]: - title = re.sub(r'\s', ' ', self.title(idx, index_is_id=index_is_id)) - name = au + ' - ' + title if byauthor else title + ' - ' + au - name = ascii_filename(name) - tname = ascii_filename(title) - tname, name = shorten_components_to(path_len-len(apath), (tname, - name)) - name += '_'+str(id) - - tpath = os.path.join(apath, tname) - id = idx if index_is_id else self.id(idx) - id = str(id) - if not single_dir and not os.path.exists(tpath): - os.makedirs(tpath) - - base = dir if single_dir else tpath - mi = self.get_metadata(idx, index_is_id=index_is_id, get_cover=True) - if not mi.authors: - mi.authors = [_('Unknown')] - cdata = self.cover(int(id), index_is_id=True) - if cdata is not None: - cname = name+'.jpg' - open(os.path.join(base, cname), 'wb').write(cdata) - mi.cover = cname - with open(os.path.join(base, name+'.opf'), - 'wb') as f: - f.write(metadata_to_opf(mi)) - - fmts = self.formats(idx, index_is_id=index_is_id) - if not fmts: - fmts = '' - for fmt in fmts.split(','): - data = self.format(idx, fmt, index_is_id=index_is_id) - if not data: - continue - fname = name +'.'+fmt.lower() - f = open(os.path.join(base, fname), 'w+b') - f.write(data) - f.flush() - f.seek(0) - try: - set_metadata(f, mi, fmt.lower()) - except: - pass - f.close() - count += 1 - if callable(callback): - if not callback(int(id), mi.title): - return - - def export_single_format_to_dir(self, dir, indices, format, - index_is_id=False, callback=None): - dir = os.path.abspath(dir) - if not index_is_id: - indices = map(self.id, indices) - failures = [] - plen = 1000 if supports_long_names(dir) else 245 - for count, id in enumerate(indices): - try: - data = self.format(id, format, index_is_id=True) - if not data: - failures.append((id, self.title(id, index_is_id=True))) - continue - except: - failures.append((id, self.title(id, index_is_id=True))) - continue - title = self.title(id, index_is_id=True) - au = self.authors(id, index_is_id=True) - if not au: - au = _('Unknown') - fname = '%s - %s'%(title, au) - while fname.endswith('.'): - fname = fname[:-1] - fname = ascii_filename(fname) - fname = fname + '.' + format.lower() - dir = os.path.abspath(dir) - fname = shorten_components_to(plen - len(dir), (fname,))[0] - if not os.path.exists(dir): - os.makedirs(dir) - f = open(os.path.join(dir, fname), 'w+b') - f.write(data) - f.flush() - f.seek(0) - try: - set_metadata(f, self.get_metadata(id, index_is_id=True, get_cover=True), - stream_type=format.lower()) - except: - pass - f.close() - if callable(callback): - if not callback(int(id), title): - break - return failures - def find_books_in_directory(self, dirpath, single_book_per_directory): dirpath = os.path.abspath(dirpath) if single_book_per_directory: From 4544754e1a5b21a932726e15e545526da2cbaf5d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 18 Aug 2009 21:04:32 -0600 Subject: [PATCH 2/3] Add history and history based completion to search boxes --- src/calibre/gui2/__init__.py | 6 + src/calibre/gui2/library.py | 96 +---- src/calibre/gui2/lrf_renderer/main.py | 98 ++--- src/calibre/gui2/main.py | 4 +- src/calibre/gui2/main.ui | 52 +-- src/calibre/gui2/search_box.py | 148 +++++++ src/calibre/gui2/viewer/main.py | 13 +- src/calibre/translations/calibre.pot | 568 +++++++++++++------------- 8 files changed, 509 insertions(+), 476 deletions(-) create mode 100644 src/calibre/gui2/search_box.py diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index b993b15e37..11b2d5674a 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -76,6 +76,12 @@ def _config(): 'only take place when the Enter or Return key is pressed.') c.add_opt('save_to_disk_template_history', default=[], help='Previously used Save to Disk templates') + c.add_opt('main_search_history', default=[], + help='Search history for the main GUI') + c.add_opt('viewer_search_history', default=[], + help='Search history for the ebook viewer') + c.add_opt('lrf_viewer_search_history', default=[], + help='Search history for the LRF viewer') return ConfigProxy(c) config = _config() diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py index f3bb4c21d0..be846c17f7 100644 --- a/src/calibre/gui2/library.py +++ b/src/calibre/gui2/library.py @@ -8,10 +8,10 @@ from operator import attrgetter from math import cos, sin, pi from PyQt4.QtGui import QTableView, QAbstractItemView, QColor, \ QItemDelegate, QPainterPath, QLinearGradient, QBrush, \ - QPen, QStyle, QPainter, QLineEdit, \ - QPalette, QImage, QApplication, QMenu, \ + QPen, QStyle, QPainter, \ + QImage, QApplication, QMenu, \ QStyledItemDelegate, QCompleter -from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, QString, \ +from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, \ SIGNAL, QObject, QSize, QModelIndex, QDate from calibre import strftime @@ -1100,94 +1100,4 @@ class DeviceBooksModel(BooksModel): self.editable = editable -class SearchBox(QLineEdit): - - INTERVAL = 1000 #: Time to wait before emitting search signal - - def __init__(self, parent, help_text=_('Search (For Advanced Search click the button to the left)')): - QLineEdit.__init__(self, parent) - self.help_text = help_text - self.initial_state = True - self.as_you_type = True - self.default_palette = QApplication.palette(self) - self.gray = QPalette(self.default_palette) - self.gray.setBrush(QPalette.Text, QBrush(QColor('gray'))) - self.prev_search = '' - self.timer = None - self.clear_to_help() - QObject.connect(self, SIGNAL('textEdited(QString)'), self.text_edited_slot) - - - def normalize_state(self): - self.setText('') - self.setPalette(self.default_palette) - self.setStyleSheet('QLineEdit { background-color: white; }') - - def clear_to_help(self): - self.setPalette(self.gray) - self.setText(self.help_text) - self.home(False) - self.initial_state = True - self.setStyleSheet('QLineEdit { background-color: white; }') - self.emit(SIGNAL('cleared()')) - - def clear(self): - self.clear_to_help() - self.emit(SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), '', False) - - def search_done(self, ok): - col = 'rgba(0,255,0,20%)' if ok else 'rgb(255,0,0,20%)' - self.setStyleSheet('QLineEdit { background-color: %s; }' % col) - - def keyPressEvent(self, event): - if self.initial_state: - self.normalize_state() - self.initial_state = False - if not self.as_you_type: - if event.key() in (Qt.Key_Return, Qt.Key_Enter): - self.do_search() - QLineEdit.keyPressEvent(self, event) - - def mouseReleaseEvent(self, event): - if self.initial_state: - self.normalize_state() - self.initial_state = False - QLineEdit.mouseReleaseEvent(self, event) - - def text_edited_slot(self, text): - if self.as_you_type: - text = qstring_to_unicode(text) if isinstance(text, QString) else unicode(text) - self.prev_text = text - self.timer = self.startTimer(self.__class__.INTERVAL) - - def timerEvent(self, event): - self.killTimer(event.timerId()) - if event.timerId() == self.timer: - self.do_search() - - def do_search(self): - text = qstring_to_unicode(self.text()) - refinement = text.startswith(self.prev_search) and ':' not in text - self.prev_search = text - self.emit(SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), text, refinement) - - def search_from_tokens(self, tokens, all): - ans = u' '.join([u'%s:%s'%x for x in tokens]) - if not all: - ans = '[' + ans + ']' - self.set_search_string(ans) - - def search_from_tags(self, tags, all): - joiner = ' and ' if all else ' or ' - self.set_search_string(joiner.join(tags)) - - def set_search_string(self, txt): - self.normalize_state() - self.setText(txt) - self.emit(SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), txt, False) - self.end(False) - self.initial_state = False - - def search_as_you_type(self, enabled): - self.as_you_type = enabled diff --git a/src/calibre/gui2/lrf_renderer/main.py b/src/calibre/gui2/lrf_renderer/main.py index c223f51d2e..5afe54e95c 100644 --- a/src/calibre/gui2/lrf_renderer/main.py +++ b/src/calibre/gui2/lrf_renderer/main.py @@ -15,10 +15,10 @@ from calibre.gui2.lrf_renderer.main_ui import Ui_MainWindow from calibre.gui2.lrf_renderer.config_ui import Ui_ViewerConfig from calibre.gui2.main_window import MainWindow from calibre.gui2.lrf_renderer.document import Document -from calibre.gui2.library import SearchBox +from calibre.gui2.search_box import SearchBox2 class RenderWorker(QThread): - + def __init__(self, parent, lrf_stream, logger, opts): QThread.__init__(self, parent) self.stream, self.logger, self.opts = lrf_stream, logger, opts @@ -26,7 +26,7 @@ class RenderWorker(QThread): self.lrf = None self.document = None self.exception = None - + def run(self): try: self.lrf = LRFDocument(self.stream) @@ -34,35 +34,35 @@ class RenderWorker(QThread): self.stream.close() self.stream = None if self.aborted: - self.lrf = None + self.lrf = None except Exception, err: self.lrf, self.stream = None, None self.exception = err self.formatted_traceback = traceback.format_exc() - + def abort(self): if self.lrf is not None: self.aborted = True self.lrf.keep_parsing = False - + class Config(QDialog, Ui_ViewerConfig): - + def __init__(self, parent, opts): QDialog.__init__(self, parent) Ui_ViewerConfig.__init__(self) self.setupUi(self) self.white_background.setChecked(opts.white_background) self.hyphenate.setChecked(opts.hyphenate) - + class Main(MainWindow, Ui_MainWindow): - + def __init__(self, logger, opts, parent=None): MainWindow.__init__(self, opts, parent) - Ui_MainWindow.__init__(self) + Ui_MainWindow.__init__(self) self.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle(__appname__ + _(' - LRF Viewer')) - + self.logger = logger self.opts = opts self.document = None @@ -73,18 +73,19 @@ class Main(MainWindow, Ui_MainWindow): self.slider_action = self.slider = QSlider(Qt.Horizontal) self.tool_bar.addWidget(self.slider) self.tool_bar.addSeparator() - self.search = SearchBox(self) + self.search = SearchBox2(self) + self.search.initialize('lrf_viewer_search_history') self.search_action = self.tool_bar.addWidget(self.search) QObject.connect(self.document, SIGNAL('chapter_rendered(int)'), self.chapter_rendered) QObject.connect(self.document, SIGNAL('page_changed(PyQt_PyObject)'), self.page_changed) - + QObject.connect(self.search, SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), self.find) - + self.action_next_page.setShortcuts([QKeySequence.MoveToNextPage, QKeySequence(Qt.Key_Space)]) self.action_previous_page.setShortcuts([QKeySequence.MoveToPreviousPage, QKeySequence(Qt.Key_Backspace)]) self.action_next_match.setShortcuts(QKeySequence.FindNext) self.addAction(self.action_next_match) - QObject.connect(self.action_next_page, SIGNAL('triggered(bool)'), self.next) + QObject.connect(self.action_next_page, SIGNAL('triggered(bool)'), self.next) QObject.connect(self.action_previous_page, SIGNAL('triggered(bool)'), self.previous) QObject.connect(self.action_back, SIGNAL('triggered(bool)'), self.back) QObject.connect(self.action_forward, SIGNAL('triggered(bool)'), self.forward) @@ -93,15 +94,15 @@ class Main(MainWindow, Ui_MainWindow): QObject.connect(self.action_configure, SIGNAL('triggered(bool)'), self.configure) QObject.connect(self.spin_box, SIGNAL('valueChanged(int)'), self.go_to_page) QObject.connect(self.slider, SIGNAL('valueChanged(int)'), self.go_to_page) - - + + self.graphics_view.setRenderHint(QPainter.Antialiasing, True) self.graphics_view.setRenderHint(QPainter.TextAntialiasing, True) self.graphics_view.setRenderHint(QPainter.SmoothPixmapTransform, True) - + self.closed = False - - + + def configure(self, triggered): opts = config['LRF_ebook_viewer_options'] if not opts: @@ -112,65 +113,64 @@ class Main(MainWindow, Ui_MainWindow): opts.white_background = bool(d.white_background.isChecked()) opts.hyphenate = bool(d.hyphenate.isChecked()) config['LRF_ebook_viewer_options'] = opts - + def set_ebook(self, stream): self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(0) self.progress_bar.setValue(0) - + if stream is not None: self.file_name = os.path.basename(stream.name) if hasattr(stream, 'name') else '' self.progress_label.setText('Parsing '+ self.file_name) self.renderer = RenderWorker(self, stream, self.logger, self.opts) QObject.connect(self.renderer, SIGNAL('finished()'), self.parsed, Qt.QueuedConnection) - self.search.help_text = 'Search' self.search.clear_to_help() self.last_search = None else: self.stack.setCurrentIndex(0) self.renderer = None - + def open_ebook(self, triggered): - files = choose_files(self, 'open ebook dialog', 'Choose ebook', - [('Ebooks', ['lrf'])], all_files=False, + files = choose_files(self, 'open ebook dialog', 'Choose ebook', + [('Ebooks', ['lrf'])], all_files=False, select_only_single_file=True) if files: file = files[0] self.set_ebook(open(file, 'rb')) self.render() - - + + def page_changed(self, num): self.slider.setValue(num) self.spin_box.setValue(num) - + def render(self): if self.renderer is not None: self.stack.setCurrentIndex(1) self.renderer.start() - + def find(self, search, refinement): self.last_search = search try: self.document.search(search) except StopIteration: error_dialog(self, _('No matches found'), _('No matches for the search phrase %s were found.')%(search,)).exec_() - + def parsed(self): if not self.renderer.aborted and self.renderer.lrf is not None: width, height = self.renderer.lrf.device_info.width, \ self.renderer.lrf.device_info.height hdelta = self.tool_bar.height()+3 - + from PyQt4.QtGui import QScrollBar s = QScrollBar(self) scrollbar_adjust = min(s.width(), s.height()) self.graphics_view.resize_for(width+scrollbar_adjust, height+scrollbar_adjust) - + desktop = QCoreApplication.instance().desktop() screen_height = desktop.availableGeometry(self).height() - 25 height = min(screen_height, height+hdelta+scrollbar_adjust) - self.resize(width+scrollbar_adjust, height) + self.resize(width+scrollbar_adjust, height) self.setWindowTitle(self.renderer.lrf.metadata.title + ' - ' + __appname__) self.document_title = self.renderer.lrf.metadata.title if self.opts.profile: @@ -183,7 +183,7 @@ class Main(MainWindow, Ui_MainWindow): self.document.render(self.renderer.lrf) print 'Layout time:', time.time()-start, 'seconds' self.renderer.lrf = None - + self.graphics_view.setScene(self.document) self.graphics_view.show() self.spin_box.setRange(1, self.document.num_of_pages) @@ -200,10 +200,10 @@ class Main(MainWindow, Ui_MainWindow): msg = u'

%s: '%(exception.__class__.__name__,) + unicode(str(exception), 'utf8', 'replace') + u'

' msg += u'

Failed to render document

' msg += u'

Detailed traceback:

'
-            msg += self.renderer.formatted_traceback + '
' + msg += self.renderer.formatted_traceback + '' d = ConversionErrorDialog(self, 'Error while rendering file', msg) d.exec_() - + def chapter_rendered(self, num): if num > 0: self.progress_bar.setMinimum(0) @@ -213,7 +213,7 @@ class Main(MainWindow, Ui_MainWindow): else: self.progress_bar.setValue(self.progress_bar.value()+1) QCoreApplication.processEvents() - + def next(self, triggered): self.document.next() @@ -222,19 +222,19 @@ class Main(MainWindow, Ui_MainWindow): self.document.next_match() except StopIteration: pass - + def previous(self, triggered): self.document.previous() - + def go_to_page(self, num): self.document.show_page(num) - + def forward(self, triggered): self.document.forward() - + def back(self, triggered): self.document.back() - + def wheelEvent(self, ev): if ev.delta() >= 0: self.document.previous() @@ -263,7 +263,7 @@ def file_renderer(stream, opts, parent=None, logger=None): m = Main(logger, opts, parent=parent) m.set_ebook(stream) return m - + def option_parser(): from calibre.gui2.main_window import option_parser @@ -295,7 +295,7 @@ def normalize_settings(parser, opts): continue setattr(saved_opts, opt.dest, getattr(opts, opt.dest)) return saved_opts - + def main(args=sys.argv, logger=None): parser = option_parser() @@ -310,17 +310,17 @@ def main(args=sys.argv, logger=None): QCoreApplication.setOrganizationName(ORG_NAME) QCoreApplication.setApplicationName(APP_UID) opts = normalize_settings(parser, opts) - stream = open(args[1], 'rb') if len(args) > 1 else None + stream = open(args[1], 'rb') if len(args) > 1 else None main = file_renderer(stream, opts, logger=logger) sys.excepthook = main.unhandled_exception main.show() main.render() main.activateWindow() main.raise_() - return app.exec_() + return app.exec_() return 0 if __name__ == '__main__': sys.exit(main()) - - + + diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index dc0cc0b2a9..df67842df6 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -121,6 +121,9 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): Ui_MainWindow.__init__(self) self.setupUi(self) self.setWindowTitle(__appname__) + self.search.initialize('main_search_history', colorize=True, + help_text=_('Search (For Advanced Search click the button to the left)')) + self.connect(self.clear_button, SIGNAL('clicked()'), self.search.clear) self.progress_indicator = ProgressIndicator(self) self.verbose = opts.verbose self.get_metadata = GetMetadata() @@ -148,7 +151,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.system_tray_icon.hide() else: self.system_tray_icon.show() - self.search.search_as_you_type(config['search_as_you_type']) self.system_tray_menu = QMenu(self) self.restore_action = self.system_tray_menu.addAction( QIcon(':/images/page.svg'), _('&Restore')) diff --git a/src/calibre/gui2/main.ui b/src/calibre/gui2/main.ui index 9ad7dbcc49..0ad69a2f59 100644 --- a/src/calibre/gui2/main.ui +++ b/src/calibre/gui2/main.ui @@ -185,33 +185,18 @@ - - - true - + - 1 + 0 0 - - false - - Search the list of books by title or author<br><br>Words separated by spaces are ANDed + <p>Search the list of books by title, author, publisher, tags, comments, etc.<br><br>Words separated by spaces are ANDed - Search the list of books by title, author, publisher, tags and comments<br><br>Words separated by spaces are ANDed - - - false - - - - - - true + <p>Search the list of books by title, author, publisher, tags, comments, etc.<br><br>Words separated by spaces are ANDed @@ -673,11 +658,6 @@ - - SearchBox - QLineEdit -
library.h
-
BooksView QTableView @@ -698,26 +678,14 @@ QTreeView
calibre/gui2/tag_view.h
+ + SearchBox2 + QComboBox +
calibre.gui2.search_box
+
- - - clear_button - clicked() - search - clear() - - - 787 - 215 - - - 755 - 213 - - - - + diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py new file mode 100644 index 0000000000..43487f2e8b --- /dev/null +++ b/src/calibre/gui2/search_box.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import with_statement + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from PyQt4.Qt import QComboBox, SIGNAL, Qt, QLineEdit, QStringList + +from calibre.gui2 import config + +class SearchLineEdit(QLineEdit): + + def keyPressEvent(self, event): + self.emit(SIGNAL('key_pressed(PyQt_PyObject)'), event) + QLineEdit.keyPressEvent(self, event) + + def mouseReleaseEvent(self, event): + self.emit(SIGNAL('mouse_released(PyQt_PyObject)'), event) + QLineEdit.mouseReleaseEvent(self, event) + +class SearchBox2(QComboBox): + + INTERVAL = 1500 #: Time to wait before emitting search signal + MAX_COUNT = 25 + + def __init__(self, parent=None): + QComboBox.__init__(self, parent) + 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.key_pressed, Qt.DirectConnection) + self.setEditable(True) + self.help_state = True + self.as_you_type = True + self.prev_search = '' + self.timer = None + self.setInsertPolicy(self.NoInsert) + self.setMaxCount(self.MAX_COUNT) + + def initialize(self, opt_name, colorize=False, + help_text=_('Search')): + self.as_you_type = config['search_as_you_type'] + self.opt_name = opt_name + self.addItems(QStringList(list(set(config[opt_name])))) + self.help_text = help_text + self.colorize = colorize + self.clear_to_help() + self.connect(self, SIGNAL('editTextChanged(QString)'), self.text_edited_slot) + + def normalize_state(self): + self.setEditText('') + self.line_edit.setStyleSheet('QLineEdit { color: black; background-color: white; }') + self.help_state = False + + def clear_to_help(self): + self.setEditText(self.help_text) + self.line_edit.home(False) + self.help_state = True + self.line_edit.setStyleSheet('QLineEdit { color: gray; background-color: white; }') + self.emit(SIGNAL('cleared()')) + + def text(self): + return self.currentText() + + def clear(self): + self.clear_to_help() + self.emit(SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), '', False) + + def search_done(self, ok): + if not unicode(self.currentText()).strip(): + return self.clear_to_help() + col = 'rgba(0,255,0,20%)' if ok else 'rgb(255,0,0,20%)' + if not self.colorize: + col = 'white' + self.line_edit.setStyleSheet('QLineEdit { color: black; background-color: %s; }' % col) + + def key_pressed(self, event): + if self.help_state: + self.normalize_state() + if not self.as_you_type: + if event.key() in (Qt.Key_Return, Qt.Key_Enter): + self.do_search() + + def mouse_released(self, event): + if self.help_state: + self.normalize_state() + + def text_edited_slot(self, text): + if self.as_you_type: + text = unicode(text) + self.prev_text = text + self.timer = self.startTimer(self.__class__.INTERVAL) + + def timerEvent(self, event): + self.killTimer(event.timerId()) + if event.timerId() == self.timer: + self.do_search() + + def do_search(self): + text = unicode(self.currentText()).strip() + if not text or text == self.help_text: + return self.clear() + self.help_state = False + refinement = text.startswith(self.prev_search) and ':' not in text + self.prev_search = text + self.emit(SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), text, refinement) + + idx = self.findText(text, Qt.MatchFixedString) + self.block_signals(True) + if idx < 0: + self.insertItem(0, text) + else: + t = self.itemText(idx) + self.removeItem(idx) + self.insertItem(0, t) + self.setCurrentIndex(0) + self.block_signals(False) + config[self.opt_name] = [unicode(self.itemText(i)) for i in + range(self.count())] + + def block_signals(self, yes): + self.blockSignals(yes) + self.line_edit.blockSignals(yes) + + def search_from_tokens(self, tokens, all): + ans = u' '.join([u'%s:%s'%x for x in tokens]) + if not all: + ans = '[' + ans + ']' + self.set_search_string(ans) + + def search_from_tags(self, tags, all): + joiner = ' and ' if all else ' or ' + self.set_search_string(joiner.join(tags)) + + def set_search_string(self, txt): + self.normalize_state() + self.setEditText(txt) + self.emit(SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), txt, False) + self.line_edit.end(False) + self.initial_state = False + + def search_as_you_type(self, enabled): + self.as_you_type = enabled + diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 6cf9f5c19f..684f3e1599 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -21,7 +21,7 @@ from calibre.ebooks.oeb.iterator import EbookIterator from calibre.ebooks import DRMError from calibre.constants import islinux from calibre.utils.config import Config, StringConfig, dynamic -from calibre.gui2.library import SearchBox +from calibre.gui2.search_box import SearchBox2 from calibre.ebooks.metadata import MetaInformation from calibre.customize.ui import available_input_formats @@ -218,7 +218,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.tool_bar2.insertWidget(self.action_find_next, self.reference) self.tool_bar2.insertSeparator(self.action_find_next) self.setFocusPolicy(Qt.StrongFocus) - self.search = SearchBox(self, _('Search')) + self.search = SearchBox2(self) + self.search.initialize('viewer_search_history') self.search.setToolTip(_('Search for text in book')) self.tool_bar2.insertWidget(self.action_find_next, self.search) self.view.set_manager(self) @@ -408,10 +409,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def find(self, text, refinement, repeat=False): if not text: - return + return self.search.search_done(False) if self.view.search(text): self.scrolled(self.view.scroll_fraction) - return + return self.search.search_done(True) index = self.iterator.search(text, self.current_index) if index is None: if self.current_index > 0: @@ -419,8 +420,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if index is None: info_dialog(self, _('No matches found'), _('No matches found for: %s')%text).exec_() - return - return + return self.search.search_done(True) + return self.search.search_done(True) self.pending_search = text self.load_path(self.iterator.spine[index]) diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 8ec3ead55c..651db81492 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: calibre 0.6.7\n" -"POT-Creation-Date: 2009-08-18 12:04+MDT\n" -"PO-Revision-Date: 2009-08-18 12:04+MDT\n" +"POT-Creation-Date: 2009-08-18 20:55+MDT\n" +"PO-Revision-Date: 2009-08-18 20:55+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -94,8 +94,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:29 #: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:139 #: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:141 -#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:253 -#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:260 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:258 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:265 #: /home/kovid/work/calibre/src/calibre/gui2/add.py:91 #: /home/kovid/work/calibre/src/calibre/gui2/add.py:98 #: /home/kovid/work/calibre/src/calibre/gui2/convert/__init__.py:19 @@ -109,7 +109,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf.py:48 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:106 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:139 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:350 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:387 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:34 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:39 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:40 @@ -120,16 +120,13 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/library.py:1000 #: /home/kovid/work/calibre/src/calibre/library/cli.py:265 #: /home/kovid/work/calibre/src/calibre/library/database.py:917 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:655 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:667 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1099 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1429 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1431 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1516 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1607 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1635 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1686 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:652 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:664 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1056 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1093 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1423 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1425 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1510 #: /home/kovid/work/calibre/src/calibre/library/server.py:309 #: /home/kovid/work/calibre/src/calibre/library/server.py:373 #: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45 @@ -528,9 +525,9 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:678 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:467 #: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:83 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1006 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1010 -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1333 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1000 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1004 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1327 msgid "News" msgstr "" @@ -1908,16 +1905,16 @@ msgstr "" msgid "Default action to perform when send to device button is clicked" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:120 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:397 msgid "Copied" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:144 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:149 msgid "Copy" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:144 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:149 msgid "Copy to Clipboard" msgstr "" @@ -2283,7 +2280,7 @@ msgid " is not a valid picture" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:166 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:372 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:377 msgid "Book Cover" msgstr "" @@ -2292,12 +2289,12 @@ msgid "Use cover from &source file" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:168 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:373 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:378 msgid "Change &cover image:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:169 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:374 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:379 msgid "Browse for an image to use as the cover of this book." msgstr "" @@ -2313,14 +2310,14 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:522 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:523 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:553 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:339 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:344 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:358 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:367 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:369 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:343 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:348 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:362 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:371 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:373 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:375 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:377 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:380 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:382 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:126 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:128 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:131 @@ -2328,25 +2325,25 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:267 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:269 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:270 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:338 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:340 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:346 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:333 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:335 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:341 msgid "..." msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:171 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:336 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:340 msgid "&Title: " msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:172 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:337 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:341 msgid "Change the title of this book" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:173 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:140 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:340 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:344 msgid "&Author(s): " msgstr "" @@ -2360,24 +2357,24 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:176 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:147 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:349 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:353 msgid "&Publisher: " msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:177 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:350 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:354 msgid "Ta&gs: " msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:178 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:149 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:351 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:355 msgid "Tags categorize the book. This is particularly useful while searching.

They can be any words or phrases, separated by commas." msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:179 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:154 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:354 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:358 msgid "&Series:" msgstr "" @@ -2385,13 +2382,13 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:181 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:155 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:156 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:355 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:356 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:359 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:360 msgid "List of known series. You can add new series." msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:182 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:361 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:365 msgid "Book " msgstr "" @@ -3125,7 +3122,7 @@ msgid "Access log:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:632 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:562 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:564 msgid "Failed to start content server" msgstr "" @@ -3175,11 +3172,11 @@ msgstr "" msgid "The following books had formats listed in the database that are not actually available. The entries for the formats have been removed. You should check them manually. This can happen if you manipulate the files in the library folder directly." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save.py:67 msgid "Invalid template" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save.py:68 msgid "The template %s is invalid:" msgstr "" @@ -3248,7 +3245,7 @@ msgid "&Saving books" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:485 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:372 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:367 #: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:173 msgid "Preferences" msgstr "" @@ -3593,7 +3590,7 @@ msgid "Edit Meta information" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:139 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:335 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:339 msgid "Meta information" msgstr "" @@ -3602,24 +3599,24 @@ msgid "Author s&ort: " msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:142 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:342 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:346 msgid "Specify how the author(s) of this book should be sorted. For example Charles Dickens should be sorted as Dickens, Charles." msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:143 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:345 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:349 msgid "&Rating:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:144 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:145 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:346 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:347 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:350 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:351 msgid "Rating of this book. 0-5 stars" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:146 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:348 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:352 msgid " stars" msgstr "" @@ -3629,8 +3626,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:150 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:151 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:352 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:353 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:356 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:357 msgid "Open Tag Editor" msgstr "" @@ -3659,131 +3656,135 @@ msgstr "" msgid "No format selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:177 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:178 msgid "Could not read metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:178 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:179 msgid "Could not read metadata from %s format" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:186 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:192 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:221 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:227 msgid "Could not read cover" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:187 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:222 msgid "Could not read cover from %s format" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:193 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:228 msgid "The cover in the %s format is invalid" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:407 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:444 msgid "Downloading cover..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:419 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:424 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:430 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:456 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:461 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:467 msgid "Cannot fetch cover" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:420 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:431 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:457 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:468 msgid "Could not fetch cover.
" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:421 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:458 msgid "The download timed out." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:425 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:462 msgid "Could not find cover for this book. Try specifying the ISBN first." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:437 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:474 msgid "Bad cover" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:438 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:475 msgid "The cover is not a valid picture" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:477 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:514 msgid "Cannot fetch metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:478 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:515 msgid "You must specify at least one of ISBN, Title, Authors or Publisher" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:504 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:541 msgid "Permission denied" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:505 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:542 msgid "Could not open %s. Is it being used by another program?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:334 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:338 msgid "Edit Meta Information" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:338 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:342 msgid "Swap the author and title" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:341 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:345 msgid "Author S&ort: " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:343 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:347 msgid "Automatically create the author sort entry based on the current author entry" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:357 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:361 msgid "Remove unused series (Series that have no books)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:359 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:363 msgid "IS&BN:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:360 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:364 msgid "Publishe&d:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:363 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:367 msgid "&Comments" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:364 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:368 msgid "&Fetch metadata from server" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:365 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:369 msgid "Available Formats" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:366 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:370 msgid "Add a new format for this book to the database" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:368 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:372 msgid "Remove the selected formats for this book from the database." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:370 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:374 msgid "Set the cover for the book from the selected format" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:376 +msgid "Update metadata from the metadata in the selected format" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:381 msgid "Reset cover to default" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:378 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:383 msgid "Download &cover" msgstr "" @@ -3812,7 +3813,7 @@ msgid "Scheduled" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:240 -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:221 +#: /home/kovid/work/calibre/src/calibre/gui2/search_box.py:45 msgid "Search" msgstr "" @@ -4384,10 +4385,6 @@ msgstr "" msgid "Double click to edit me

" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1107 -msgid "Search (For Advanced Search click the button to the left)" -msgstr "" - #: /home/kovid/work/calibre/src/calibre/gui2/lrf_renderer/config_ui.py:47 msgid "Configure Viewer" msgstr "" @@ -4413,7 +4410,7 @@ msgid "No matches for the search phrase %s were found." msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/lrf_renderer/main.py:157 -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:420 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:421 msgid "No matches found" msgstr "" @@ -4464,142 +4461,146 @@ msgstr "" msgid "Save single format to disk..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:138 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:993 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:125 +msgid "Search (For Advanced Search click the button to the left)" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:141 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:995 #: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:52 msgid "Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:139 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:142 msgid "Error communicating with device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:154 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:156 msgid "&Restore" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:156 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:158 msgid "&Donate to support calibre" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:161 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:163 msgid "&Restart" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:200 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:202 msgid "

For help visit %s.kovidgoyal.net
" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:203 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:205 msgid "%s: %s by Kovid Goyal %%(version)s
%%(device)s

" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:223 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:225 msgid "Edit metadata individually" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:225 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:227 msgid "Edit metadata in bulk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:227 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:229 msgid "Download metadata and covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:228 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:230 msgid "Download only metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:229 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:231 msgid "Download only covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:232 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:234 msgid "Add books from a single directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:233 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:235 msgid "Add books from directories, including sub-directories (One book per directory, assumes every ebook file is the same book in a different format)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:236 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:238 msgid "Add books from directories, including sub directories (Multiple books per directory, assumes every ebook file is a different book)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:239 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:241 msgid "Add Empty book. (Book entry with no formats)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:276 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:358 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:278 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:353 msgid "Save to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:277 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:279 msgid "Save to disk in a single directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:278 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1470 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:280 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1472 msgid "Save only %s format to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:286 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:364 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:288 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:359 msgid "View" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:287 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:289 msgid "View specific format" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:313 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:315 msgid "Convert individually" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:314 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:316 msgid "Bulk convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:329 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:331 msgid "Run welcome wizard" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:363 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:365 msgid "Similar books..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:422 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:423 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:424 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:425 msgid "Bad database location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:426 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1598 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:428 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1600 msgid "Choose a location for your ebook library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:605 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:607 msgid "Browse by covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:712 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:714 msgid "Device: " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:714 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:716 msgid " detected." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:736 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:738 msgid "Connected " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:748 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:750 msgid "Device database corrupted" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:749 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:751 msgid "" "\n" "

The database of books on the reader is corrupted. Try the following:\n" @@ -4610,422 +4611,419 @@ msgid "" " " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:825 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:868 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:827 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:870 msgid "Uploading books to device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:833 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:835 msgid "Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:834 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:836 msgid "EPUB Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:835 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:837 msgid "LRF Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:836 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:838 msgid "HTML Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:837 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:839 msgid "LIT Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:838 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:840 msgid "MOBI Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:839 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:841 msgid "Text books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:840 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:842 msgid "PDF Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:841 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:843 msgid "Comics" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:842 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:844 msgid "Archives" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:877 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:879 msgid "Failed to read metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:878 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:880 msgid "Failed to read metadata from the following" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:897 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:899 msgid "The selected books will be permanently deleted and the files removed from your computer. Are you sure?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:924 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:926 msgid "Deleting books from device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:955 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:957 msgid "Cannot download metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:956 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1004 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1034 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1059 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1194 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:958 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1006 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1036 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1061 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1196 msgid "No books selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:965 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967 msgid "covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:965 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967 msgid "metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:969 msgid "Downloading %s for %d book(s)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:988 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:990 msgid "Failed to download some metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:989 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:991 msgid "Failed to download metadata for the following:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:992 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:994 msgid "Failed to download metadata:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1003 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1033 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1035 msgid "Cannot edit metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1058 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1060 msgid "Cannot save to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1061 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1063 msgid "Choose destination directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1086 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1088 msgid "Error while saving" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1087 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1089 msgid "There was an error while saving." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1094 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1095 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1096 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1097 msgid "Could not save some books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1096 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1098 msgid "Click the show details button to see which ones." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1115 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1117 msgid "Fetching news from " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1128 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1130 msgid " fetched." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1193 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1195 msgid "Cannot convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1363 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1382 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1365 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1384 msgid "No book selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1363 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1415 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1365 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1417 msgid "Cannot view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1369 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1371 msgid "Choose the format to view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1381 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1383 msgid "Cannot open folder" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1398 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1400 msgid "Multiple Books Selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1399 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1401 msgid "You are attempting to open %d books. Opening too many books at once can be slow and have a negative effect on the responsiveness of your computer. Once started the process cannot be stopped until complete. Do you wish to continue?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1416 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1418 msgid "%s has no available formats." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1454 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1456 msgid "Cannot configure" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1455 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1457 msgid "Cannot configure while there are running jobs." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1499 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1501 msgid "No detailed info available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1500 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1502 msgid "No detailed information is available for books on the device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1548 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1550 msgid "Error talking to device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1549 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1551 msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1566 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1581 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1568 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1583 msgid "Conversion Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1567 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1569 msgid "

Could not convert: %s

It is a DRMed book. You must first remove the DRM using 3rd party tools." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1582 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1584 msgid "Failed" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1607 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1609 msgid "Invalid library location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1608 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1610 msgid "Could not access %s. Using %s as the library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1656 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1658 msgid "is the result of the efforts of many volunteers from all over the world. If you find it useful, please consider donating to support its development." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1680 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1682 msgid "There are active jobs. Are you sure you want to quit?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1683 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1685 msgid "" " is communicating with the device!
\n" " Quitting may cause corruption on the device.
\n" " Are you sure you want to quit?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1687 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1689 msgid "WARNING: Active jobs" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1738 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1740 msgid "will keep running in the system tray. To close it, choose Quit in the context menu of the system tray." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1757 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1759 msgid "Latest version: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1765 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1767 msgid "Update available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1766 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1768 msgid "%s has been updated to version %s. See the new features. Visit the download page?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1784 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1786 msgid "Use the library located at the specified path." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1786 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1788 msgid "Start minimized to system tray." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1788 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1790 msgid "Log debugging information to console" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1836 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1838 msgid "If you are sure it is not running" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1838 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1840 msgid "Cannot Start " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1839 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1841 msgid "%s is already running." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1842 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1844 msgid "may be running in the system tray, in the" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1844 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1846 msgid "upper right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1846 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1848 msgid "lower right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1849 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1851 msgid "try rebooting your computer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1851 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1871 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1873 msgid "try deleting the file" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:337 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:332 msgid "calibre" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:339 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:334 msgid "Advanced search" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:341 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:336 msgid "Alt+S" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:342 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:337 msgid "&Search:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:343 -msgid "Search the list of books by title or author

Words separated by spaces are ANDed" +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:338 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:339 +msgid "

Search the list of books by title, author, publisher, tags, comments, etc.

Words separated by spaces are ANDed" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:344 -msgid "Search the list of books by title, author, publisher, tags and comments

Words separated by spaces are ANDed" -msgstr "" - -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:345 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:340 msgid "Reset Quick Search" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:347 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:342 msgid "Match any" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:348 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:343 msgid "Match all" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:349 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:344 msgid "Sort by &popularity" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:350 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:345 msgid "Add books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:351 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:346 msgid "A" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:352 -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:353 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:347 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:348 msgid "Remove books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:354 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:349 msgid "Del" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:355 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:350 msgid "Edit meta information" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:356 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:351 msgid "E" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:357 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:352 msgid "Send to device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:359 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:354 msgid "S" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:360 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:355 msgid "Fetch news" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:361 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:356 msgid "F" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:362 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:357 msgid "Convert E-books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:363 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:358 msgid "C" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:365 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:360 msgid "V" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:366 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:361 msgid "Open containing folder" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:367 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:362 msgid "Show book details" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:368 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:363 msgid "Books by same author" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:369 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:364 msgid "Books in this series" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:370 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:365 msgid "Books by this publisher" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:371 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:366 msgid "Books with the same tags" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:373 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:368 msgid "Configure calibre" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:374 +#: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:369 msgid "Ctrl+P" msgstr "" @@ -5248,7 +5246,7 @@ msgid "Options to customize the ebook viewer" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:59 -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:649 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:650 msgid "Remember last used window size" msgstr "" @@ -5317,75 +5315,75 @@ msgstr "" msgid "Go to a reference. To get reference numbers, use the reference mode." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:222 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:223 msgid "Search for text in book" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:285 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:286 msgid "Print Preview" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:380 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:381 msgid "Choose ebook" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:381 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:382 msgid "Ebooks" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:400 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:401 msgid "Add bookmark" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:400 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:401 msgid "Enter title for bookmark:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:421 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:422 msgid "No matches found for: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:461 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:462 msgid "Loading flow..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:488 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:489 msgid "Laying out %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:517 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:518 msgid "Manage Bookmarks" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:552 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:553 msgid "Loading ebook..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:560 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:561 msgid "DRM Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:561 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:562 msgid "

This book is protected by DRM" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:565 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:566 msgid "Could not open ebook" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:639 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:640 msgid "Options to control the ebook viewer" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:646 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:647 msgid "If specified, viewer window will try to come to the front when started." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:651 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:652 msgid "Print javascript alert and console messages to the console" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:657 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:658 msgid "" "%prog [options] file\n" "\n" @@ -5961,15 +5959,15 @@ msgid "" "For help on an individual command: %%prog command --help\n" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1542 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1536 msgid "

Migrating old database to ebook library in %s

" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1571 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1565 msgid "Copying %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1588 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1582 msgid "Compacting database" msgstr "" @@ -6053,7 +6051,7 @@ msgstr "" msgid "The format in which to display dates. %d - day, %b - month, %Y - year. Default is: %b, %Y" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/save_to_disk.py:214 +#: /home/kovid/work/calibre/src/calibre/library/save_to_disk.py:215 msgid "Requested formats not available" msgstr "" @@ -6081,43 +6079,43 @@ msgstr "" msgid "Whenever you pass arguments to %prog that have spaces in them, enclose the arguments in quotation marks." msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:550 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:551 msgid "Path to the database in which books are stored" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:552 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:553 msgid "Pattern to guess metadata from filenames" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:554 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:555 msgid "Access key for isbndb.com" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:556 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:557 msgid "Default timeout for network operations (seconds)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:558 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:559 msgid "Path to directory in which your library of books is stored" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:560 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:561 msgid "The language in which to display the user interface" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:562 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:563 msgid "The default output format for ebook conversions." msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:566 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:567 msgid "Ordered list of formats to prefer for input." msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:568 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:569 msgid "Read metadata from files" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/config.py:570 +#: /home/kovid/work/calibre/src/calibre/utils/config.py:571 msgid "The priority of worker processes" msgstr "" @@ -6368,7 +6366,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_fudzilla.py:15 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_glasgow_herald.py:10 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_globe_and_mail.py:15 -#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_guardian.py:16 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_guardian.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_harpers.py:14 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_harpers_full.py:26 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_hindu.py:10 From 935b76f6c1d9792e3da502b060391db0be8fa6cc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 18 Aug 2009 21:21:09 -0600 Subject: [PATCH 3/3] IGN:Various fixes related to new search widget --- src/calibre/gui2/__init__.py | 3 ++ src/calibre/gui2/dialogs/scheduler.py | 52 +++++---------------------- src/calibre/gui2/lrf_renderer/main.py | 1 + src/calibre/gui2/search_box.py | 9 +++++ 4 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 11b2d5674a..eb93602fd1 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -82,6 +82,9 @@ def _config(): help='Search history for the ebook viewer') c.add_opt('lrf_viewer_search_history', default=[], help='Search history for the LRF viewer') + c.add_opt('scheduler_search_history', default=[], + help='Search history for the recipe scheduler') + return ConfigProxy(c) config = _config() diff --git a/src/calibre/gui2/dialogs/scheduler.py b/src/calibre/gui2/dialogs/scheduler.py index 3b45e9a759..f31e76b861 100644 --- a/src/calibre/gui2/dialogs/scheduler.py +++ b/src/calibre/gui2/dialogs/scheduler.py @@ -9,12 +9,13 @@ Scheduler for automated recipe downloads import sys, copy, time from datetime import datetime, timedelta, date -from PyQt4.Qt import QDialog, QApplication, QLineEdit, QPalette, SIGNAL, QBrush, \ +from PyQt4.Qt import QDialog, QApplication, SIGNAL, \ QColor, QAbstractItemModel, Qt, QVariant, QFont, QIcon, \ QFile, QObject, QTimer, QMutex, QMenu, QAction, QTime, QModelIndex from calibre import english_sort from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog +from calibre.gui2.search_box import SearchBox2 from calibre.web.feeds.recipes import recipes, recipe_modules, compile_recipe from calibre.utils.search_query_parser import SearchQueryParser from calibre.utils.pyparsing import ParseException @@ -163,7 +164,7 @@ class RecipeModel(QAbstractItemModel, SearchQueryParser): results.add(recipe) return results - def search(self, query): + def search(self, query, refinement): try: results = self.parse(unicode(query)) except ParseException: @@ -176,6 +177,7 @@ class RecipeModel(QAbstractItemModel, SearchQueryParser): if recipe in results: self._map[category].append(recipe) self.reset() + self.emit(SIGNAL('searched(PyQt_PyObject)'), True) def resort(self): self.recipes.sort() @@ -235,45 +237,6 @@ class RecipeModel(QAbstractItemModel, SearchQueryParser): srecipe.schedule = recipe.schedule -class Search(QLineEdit): - - HELP_TEXT = _('Search') - INTERVAL = 500 #: Time to wait before emitting search signal - - def __init__(self, *args): - QLineEdit.__init__(self, *args) - self.default_palette = QApplication.palette(self) - self.gray = QPalette(self.default_palette) - self.gray.setBrush(QPalette.Text, QBrush(QColor('gray'))) - self.connect(self, SIGNAL('editingFinished()'), - lambda : self.emit(SIGNAL('goto(PyQt_PyObject)'), unicode(self.text()))) - self.clear_to_help_mode() - self.timer = None - self.connect(self, SIGNAL('textEdited(QString)'), self.text_edited_slot) - - def focusInEvent(self, ev): - self.setPalette(QApplication.palette(self)) - if self.in_help_mode(): - self.setText('') - return QLineEdit.focusInEvent(self, ev) - - def in_help_mode(self): - return unicode(self.text()) == self.HELP_TEXT - - def clear_to_help_mode(self): - self.setPalette(self.gray) - self.setText(self.HELP_TEXT) - - def text_edited_slot(self, text): - text = unicode(text) - self.timer = self.startTimer(self.INTERVAL) - - def timerEvent(self, event): - self.killTimer(event.timerId()) - if event.timerId() == self.timer: - text = unicode(self.text()) - self.emit(SIGNAL('search(PyQt_PyObject)'), text) - def encode_schedule(day, hour, minute): day = 1e7 * (day+1) hour = 1e4 * (hour+1) @@ -291,7 +254,8 @@ class SchedulerDialog(QDialog, Ui_Dialog): def __init__(self, db, *args): QDialog.__init__(self, *args) self.setupUi(self) - self.search = Search(self) + self.search = SearchBox2(self) + self.search.initialize('scheduler_search_history') self.recipe_box.layout().insertWidget(0, self.search) self.detail_box.setVisible(False) self._model = RecipeModel(db) @@ -308,7 +272,9 @@ class SchedulerDialog(QDialog, Ui_Dialog): self.connect(self.time, SIGNAL('timeChanged(QTime)'), self.do_schedule) for button in (self.daily_button, self.interval_button): self.connect(button, SIGNAL('toggled(bool)'), self.do_schedule) - self.connect(self.search, SIGNAL('search(PyQt_PyObject)'), self._model.search) + self.connect(self.search, SIGNAL('search(PyQt_PyObject,PyQt_PyObject)'), self._model.search) + self.connect(self._model, SIGNAL('searched(PyQt_PyObject)'), + self.search.search_done) self.connect(self._model, SIGNAL('modelReset()'), lambda : self.detail_box.setVisible(False)) self.connect(self.download_all_button, SIGNAL('clicked()'), self.download_all) diff --git a/src/calibre/gui2/lrf_renderer/main.py b/src/calibre/gui2/lrf_renderer/main.py index 5afe54e95c..2ac4017fc7 100644 --- a/src/calibre/gui2/lrf_renderer/main.py +++ b/src/calibre/gui2/lrf_renderer/main.py @@ -155,6 +155,7 @@ class Main(MainWindow, Ui_MainWindow): self.document.search(search) except StopIteration: error_dialog(self, _('No matches found'), _('No matches for the search phrase %s were found.')%(search,)).exec_() + self.search.search_done(True) def parsed(self): if not self.renderer.aborted and self.renderer.lrf is not None: diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index 43487f2e8b..1263ff003e 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -22,6 +22,15 @@ class SearchLineEdit(QLineEdit): class SearchBox2(QComboBox): + ''' + To use this class: + + * Call initialize() + * Connect to the search() and cleared() signals from this widget + * Call search_done() after evry search is complete + * Use clear() to clear back to the help message + ''' + INTERVAL = 1500 #: Time to wait before emitting search signal MAX_COUNT = 25