From d080ac85d6053af7b472d049ecba70ea3ae4a29c Mon Sep 17 00:00:00 2001 From: ldolse Date: Tue, 8 Feb 2011 13:26:05 +0800 Subject: [PATCH 01/15] included divs in the fix indents option --- src/calibre/ebooks/conversion/utils.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/calibre/ebooks/conversion/utils.py b/src/calibre/ebooks/conversion/utils.py index d075390e8e..a87392b54f 100644 --- a/src/calibre/ebooks/conversion/utils.py +++ b/src/calibre/ebooks/conversion/utils.py @@ -77,22 +77,23 @@ class HeuristicProcessor(object): def insert_indent(self, match): pstyle = match.group('formatting') + tag = match.group('tagtype') span = match.group('span') self.found_indents = self.found_indents + 1 if pstyle: - if pstyle.lower().find('style'): + if pstyle.lower().find('style') != -1: pstyle = re.sub(r'"$', '; text-indent:3%"', pstyle) else: pstyle = pstyle+' style="text-indent:3%"' if not span: - return '

' + return '<'+tag+' '+pstyle+'>' else: - return '

'+span + return '<'+tag+' '+pstyle+'>'+span else: if not span: - return '

' + return '<'+tag+' style="text-indent:3%">' else: - return '

'+span + return '<'+tag+' style="text-indent:3%">'+span def no_markup(self, raw, percent): ''' @@ -365,7 +366,7 @@ class HeuristicProcessor(object): return html def fix_nbsp_indents(self, html): - txtindent = re.compile(ur'[^>]*)>\s*(?P(]*>\s*)+)?\s*(\u00a0){2,}', re.IGNORECASE) + txtindent = re.compile(ur'<(?Pp|div)(?P[^>]*)>\s*(?P(]*>\s*)+)?\s*(\u00a0){2,}', re.IGNORECASE) html = txtindent.sub(self.insert_indent, html) if self.found_indents > 1: self.log.debug("replaced "+unicode(self.found_indents)+ " nbsp indents with inline styles") From dbc133be1335ee34f9df8e1c44d7666afcd406f7 Mon Sep 17 00:00:00 2001 From: John Schember Date: Tue, 8 Feb 2011 07:03:28 -0500 Subject: [PATCH 02/15] TXT Output: Textile don't blindly remove %'s, modify html2textile to not write % from spans. --- src/calibre/ebooks/txt/textileml.py | 1 - src/calibre/utils/html2textile.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/txt/textileml.py b/src/calibre/ebooks/txt/textileml.py index 284e4846d9..d7e11695c5 100644 --- a/src/calibre/ebooks/txt/textileml.py +++ b/src/calibre/ebooks/txt/textileml.py @@ -41,7 +41,6 @@ class TextileMLizer(object): html = re.sub(r'<\s*img[^>]*>', '', html) text = html2textile(html) - text = text.replace('%', '') # Ensure the section ends with at least two new line characters. # This is to prevent the last paragraph from a section being diff --git a/src/calibre/utils/html2textile.py b/src/calibre/utils/html2textile.py index 82797a81ad..786e912e36 100644 --- a/src/calibre/utils/html2textile.py +++ b/src/calibre/utils/html2textile.py @@ -77,7 +77,7 @@ class EchoTarget: new_tag = '~' newline = '' elif tag == 'span': - new_tag = '%' + new_tag = '' newline = '' elif tag == 'a': self.block = True @@ -147,7 +147,7 @@ class EchoTarget: elif tag == 'sub': self.final_output.append('~') elif tag == 'span': - self.final_output.append('%') + self.final_output.append('') elif tag == 'a': if self.a_part['title']: textilized = ' "%s (%s)":%s ' % ( From 196060f8d27316d35d8ac1a12ce1ab1f1961c041 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 13:27:39 -0700 Subject: [PATCH 03/15] Fix #8873 (Can't get Calibre to recognize Huawei Ideos S7 tablet) --- src/calibre/devices/android/driver.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py index 11d636791b..e9021461eb 100644 --- a/src/calibre/devices/android/driver.py +++ b/src/calibre/devices/android/driver.py @@ -62,6 +62,9 @@ class ANDROID(USBMS): # Archos 0x0e79 : { 0x1419: [0x0216], 0x1420 : [0x0216], 0x1422 : [0x0216]}, + # Huawei + 0x45e : { 0x00e1 : [0x007], }, + } EBOOK_DIR_MAIN = ['eBooks/import', 'wordplayer/calibretransfer', 'Books'] EXTRA_CUSTOMIZATION_MESSAGE = _('Comma separated list of directories to ' @@ -71,12 +74,13 @@ class ANDROID(USBMS): VENDOR_NAME = ['HTC', 'MOTOROLA', 'GOOGLE_', 'ANDROID', 'ACER', 'GT-I5700', 'SAMSUNG', 'DELL', 'LINUX', 'GOOGLE', 'ARCHOS', - 'TELECHIP'] + 'TELECHIP', 'HUAWEI', ] WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE', '__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897', 'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE', - 'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT', 'A70H'] + 'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT', 'A70H', + 'IDEOS_TABLET'] WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD', 'A70S', 'A101IT'] From bdd690df127cba1f785f6bd3da2c5d649d75a5f6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 15:46:02 -0700 Subject: [PATCH 04/15] Completion: Restore adding of comma at end after completion for tags type fields. Add a tweak to control if an & is added after completion for author type fields --- resources/default_tweaks.py | 5 +- src/calibre/gui2/complete.py | 65 ++++++++++++--------- src/calibre/gui2/convert/metadata.py | 2 + src/calibre/gui2/dialogs/add_empty_book.py | 2 + src/calibre/gui2/dialogs/metadata_bulk.py | 1 + src/calibre/gui2/dialogs/metadata_single.py | 1 + src/calibre/gui2/dialogs/search.py | 2 + src/calibre/gui2/library/delegates.py | 2 + src/calibre/gui2/metadata/basic_widgets.py | 1 + 9 files changed, 50 insertions(+), 31 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index 893c8b6b6a..81088da520 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -32,9 +32,10 @@ series_index_auto_increment = 'next' # Should the completion separator be append # to the end of the completed text to -# automatically begin a new completion operation. +# automatically begin a new completion operation +# for authors. # Can be either True or False -completer_append_separator = False +authors_completer_append_separator = False # The algorithm used to copy author to author_sort diff --git a/src/calibre/gui2/complete.py b/src/calibre/gui2/complete.py index 58020f924a..2eb97b128d 100644 --- a/src/calibre/gui2/complete.py +++ b/src/calibre/gui2/complete.py @@ -9,7 +9,6 @@ __docformat__ = 'restructuredtext en' from PyQt4.Qt import QLineEdit, QAbstractListModel, Qt, \ QApplication, QCompleter -from calibre.utils.config import tweaks from calibre.utils.icu import sort_key, lower from calibre.gui2 import NONE from calibre.gui2.widgets import EnComboBox @@ -55,6 +54,8 @@ class MultiCompleteLineEdit(QLineEdit): self.sep = ',' self.space_before_sep = False + self.add_separator = True + self.original_cursor_pos = None self._model = CompleteModel(parent=self) self._completer = c = QCompleter(self._model, self) @@ -82,6 +83,9 @@ class MultiCompleteLineEdit(QLineEdit): def set_space_before_sep(self, space_before): self.space_before_sep = space_before + def set_add_separator(self, what): + self.add_separator = bool(what) + # }}} def item_entered(self, idx): @@ -93,7 +97,7 @@ class MultiCompleteLineEdit(QLineEdit): def update_completions(self): ' Update the list of completions ' - cpos = self.cursorPosition() + self.original_cursor_pos = cpos = self.cursorPosition() text = unicode(self.text()) prefix = text[:cpos] self.current_prefix = prefix @@ -103,38 +107,38 @@ class MultiCompleteLineEdit(QLineEdit): self._completer.setCompletionPrefix(complete_prefix) def get_completed_text(self, text): - ''' - Get completed text from current cursor position and the completion - text - ''' + 'Get completed text in before and after parts' if self.sep is None: - return -1, text + return text, '' else: - cursor_pos = self.cursorPosition() - before_text = unicode(self.text())[:cursor_pos] - after_text = unicode(self.text())[cursor_pos:] - prefix_len = len(before_text.split(self.sep)[-1].lstrip()) - if tweaks['completer_append_separator']: - prefix_len = len(before_text.split(self.sep)[-1].lstrip()) - completed_text = before_text[:cursor_pos - prefix_len] + text + self.sep + ' ' + after_text - prefix_len = prefix_len - len(self.sep) - 1 - if prefix_len < 0: - prefix_len = 0 + cursor_pos = self.original_cursor_pos + if cursor_pos is None: + cursor_pos = self.cursorPosition() + self.original_cursor_pos = None + # Split text + curtext = unicode(self.text()) + before_text = curtext[:cursor_pos] + after_text = curtext[cursor_pos:].rstrip() + # Remove the completion prefix from the before text + before_text = self.sep.join(before_text.split(self.sep)[:-1]).rstrip() + if before_text: + # Add the separator to the end of before_text + if self.space_before_sep: + before_text += ' ' + before_text += self.sep + ' ' + if self.add_separator or after_text: + # Add separator to the end of completed text + if self.space_before_sep: + text = text.rstrip() + ' ' + completed_text = text + self.sep + ' ' else: - prefix_len = len(before_text.split(self.sep)[-1].lstrip()) - completed_text = before_text[:cursor_pos - prefix_len] + text + after_text - return prefix_len, completed_text - + completed_text = text + return before_text + completed_text, after_text def completion_selected(self, text): - prefix_len, ctext = self.get_completed_text(unicode(text)) - if self.sep is None: - self.setText(ctext) - self.setCursorPosition(len(ctext)) - else: - cursor_pos = self.cursorPosition() - self.setText(ctext) - self.setCursorPosition(cursor_pos - prefix_len + len(text)) + before_text, after_text = self.get_completed_text(unicode(text)) + self.setText(before_text + after_text) + self.setCursorPosition(len(before_text)) @dynamic_property def all_items(self): @@ -164,6 +168,9 @@ class MultiCompleteComboBox(EnComboBox): def set_space_before_sep(self, space_before): self.lineEdit().set_space_before_sep(space_before) + def set_add_separator(self, what): + self.lineEdit().set_add_separator(what) + if __name__ == '__main__': diff --git a/src/calibre/gui2/convert/metadata.py b/src/calibre/gui2/convert/metadata.py index 81274f25a8..95dd7623c9 100644 --- a/src/calibre/gui2/convert/metadata.py +++ b/src/calibre/gui2/convert/metadata.py @@ -19,6 +19,7 @@ from calibre.ptempfile import PersistentTemporaryFile from calibre.gui2.convert import Widget from calibre.utils.icu import sort_key from calibre.library.comments import comments_to_html +from calibre.utils.config import tweaks def create_opf_file(db, book_id): mi = db.get_metadata(book_id, index_is_id=True) @@ -108,6 +109,7 @@ class MetadataWidget(Widget, Ui_Form): all_authors.sort(key=lambda x : sort_key(x[1])) self.author.set_separator('&') self.author.set_space_before_sep(True) + self.author.set_add_separator(tweaks['authors_completer_append_separator']) self.author.update_items_cache(self.db.all_author_names()) for i in all_authors: diff --git a/src/calibre/gui2/dialogs/add_empty_book.py b/src/calibre/gui2/dialogs/add_empty_book.py index 9e5fb07308..d4990e14d4 100644 --- a/src/calibre/gui2/dialogs/add_empty_book.py +++ b/src/calibre/gui2/dialogs/add_empty_book.py @@ -9,6 +9,7 @@ from PyQt4.Qt import QDialog, QGridLayout, QLabel, QDialogButtonBox, \ from calibre.ebooks.metadata import authors_to_string, string_to_authors from calibre.utils.icu import sort_key from calibre.gui2.complete import MultiCompleteComboBox +from calibre.utils.config import tweaks class AddEmptyBookDialog(QDialog): @@ -69,6 +70,7 @@ class AddEmptyBookDialog(QDialog): self.authors_combo.set_separator('&') self.authors_combo.set_space_before_sep(True) + self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator']) self.authors_combo.update_items_cache(db.all_author_names()) @property diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index e355144544..9ad61d515b 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -781,6 +781,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): self.authors.set_separator('&') self.authors.set_space_before_sep(True) + self.authors.set_add_separator(tweaks['authors_completer_append_separator']) self.authors.update_items_cache(self.db.all_author_names()) def initialize_series(self): diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 52d263fe36..d95c905f42 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -735,6 +735,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): self.authors.set_separator('&') self.authors.set_space_before_sep(True) + self.authors.set_add_separator(tweaks['authors_completer_append_separator']) self.authors.update_items_cache(self.db.all_author_names()) def initialize_series(self): diff --git a/src/calibre/gui2/dialogs/search.py b/src/calibre/gui2/dialogs/search.py index 9c91446f3c..b4976e2657 100644 --- a/src/calibre/gui2/dialogs/search.py +++ b/src/calibre/gui2/dialogs/search.py @@ -9,6 +9,7 @@ from calibre.gui2.dialogs.search_ui import Ui_Dialog from calibre.library.caches import CONTAINS_MATCH, EQUALS_MATCH from calibre.gui2 import gprefs from calibre.utils.icu import sort_key +from calibre.utils.config import tweaks box_values = {} @@ -31,6 +32,7 @@ class SearchDialog(QDialog, Ui_Dialog): self.authors_box.setEditText('') self.authors_box.set_separator('&') self.authors_box.set_space_before_sep(True) + self.authors_box.set_add_separator(tweaks['authors_completer_append_separator']) self.authors_box.update_items_cache(db.all_author_names()) all_series = db.all_series() diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py index fed2e42470..87da6818eb 100644 --- a/src/calibre/gui2/library/delegates.py +++ b/src/calibre/gui2/library/delegates.py @@ -177,6 +177,8 @@ class CompleteDelegate(QStyledItemDelegate): # {{{ editor = MultiCompleteLineEdit(parent) editor.set_separator(self.sep) editor.set_space_before_sep(self.space_before_sep) + if self.sep == '&': + editor.set_add_separator(tweaks['authors_completer_append_separator']) if not index.model().is_custom_column(col): all_items = getattr(self.db, self.items_func_name)() else: diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index f9058fc333..a135176daf 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -177,6 +177,7 @@ class AuthorsEdit(MultiCompleteComboBox): self.set_separator('&') self.set_space_before_sep(True) + self.set_add_separator(tweaks['authors_completer_append_separator']) self.update_items_cache(db.all_author_names()) au = db.authors(id_, index_is_id=True) From becf2584133a72476558320a31e1943637a88ce0 Mon Sep 17 00:00:00 2001 From: John Schember Date: Tue, 8 Feb 2011 17:55:06 -0500 Subject: [PATCH 05/15] TXTZ Output: GUI options widget. --- src/calibre/gui2/convert/txt_output.py | 2 -- src/calibre/gui2/convert/txtz_output.py | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/calibre/gui2/convert/txtz_output.py diff --git a/src/calibre/gui2/convert/txt_output.py b/src/calibre/gui2/convert/txt_output.py index 33ed64cef1..8427f83824 100644 --- a/src/calibre/gui2/convert/txt_output.py +++ b/src/calibre/gui2/convert/txt_output.py @@ -8,8 +8,6 @@ __docformat__ = 'restructuredtext en' from calibre.gui2.convert.txt_output_ui import Ui_Form from calibre.gui2.convert import Widget -newline_model = None - class PluginWidget(Widget, Ui_Form): TITLE = _('TXT Output') diff --git a/src/calibre/gui2/convert/txtz_output.py b/src/calibre/gui2/convert/txtz_output.py new file mode 100644 index 0000000000..f22c682044 --- /dev/null +++ b/src/calibre/gui2/convert/txtz_output.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +__license__ = 'GPL 3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + + +from calibre.gui2.convert.txt_output import PluginWidget as TXTPluginWidget + +class PluginWidget(TXTPluginWidget): + + TITLE = _('TXTZ Output') + HELP = _('Options specific to')+' TXTZ '+_('output') + COMMIT_NAME = 'txtz_output' From 806f6d742535988a805e206c03722173aff5eb88 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 16:11:51 -0700 Subject: [PATCH 06/15] When automatically sending news to device, send to main memory preferentially, if it has enough space. Fixes #8877 (Nook magazine default will not reset to main memory after setting to Card A) --- src/calibre/gui2/device.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 8efa7f154c..735eb7782b 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -1026,6 +1026,17 @@ class DeviceMixin(object): # {{{ self.location_manager.free[1] : 'carda', self.location_manager.free[2] : 'cardb' } on_card = space.get(sorted(space.keys(), reverse=True)[0], None) + try: + total_size = sum([os.stat(f).st_size for f in files]) + except: + try: + traceback.print_exc() + except: + pass + total_size = self.location_manager.free[0] + if self.location_manager.free[0] > total_size + (1024**2): + # Send news to main memory if enough space available + on_card = None self.upload_books(files, names, metadata, on_card=on_card, memory=[files, remove]) From f461783a37efc3f4edd2aca2739b8b1714eabb54 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 16:21:18 -0700 Subject: [PATCH 07/15] LIT Input: Workaround LIT files generated by some broken software that sets the OPF namespace to http://openebook.org/namespaces/oeb-package/1.0. Fixes #8875 (OEBError: Invalid namespace, when opening LIT eBook in Ebookreader from Calibre) --- src/calibre/ebooks/oeb/reader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/ebooks/oeb/reader.py b/src/calibre/ebooks/oeb/reader.py index d08a68c0bc..4a09e0b1d4 100644 --- a/src/calibre/ebooks/oeb/reader.py +++ b/src/calibre/ebooks/oeb/reader.py @@ -103,6 +103,8 @@ class OEBReader(object): data = self.oeb.container.read(None) data = self.oeb.decode(data) data = XMLDECL_RE.sub('', data) + data = data.replace('http://openebook.org/namespaces/oeb-package/1.0', + OPF1_NS) try: opf = etree.fromstring(data) except etree.XMLSyntaxError: From a4e8f8b8b5cb04d749f97ab7f270efeeb3091d1c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 16:25:44 -0700 Subject: [PATCH 08/15] ... --- src/calibre/gui2/device.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 735eb7782b..ea86885484 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -1036,6 +1036,8 @@ class DeviceMixin(object): # {{{ total_size = self.location_manager.free[0] if self.location_manager.free[0] > total_size + (1024**2): # Send news to main memory if enough space available + # as some devices like the Nook Color cannot handle + # periodicals on SD cards properly on_card = None self.upload_books(files, names, metadata, on_card=on_card, From 761631a49b3259284a21db8ea342cc12db059047 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 16:26:44 -0700 Subject: [PATCH 09/15] ... --- src/calibre/gui2/device.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index ea86885484..3540575f81 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -1030,6 +1030,7 @@ class DeviceMixin(object): # {{{ total_size = sum([os.stat(f).st_size for f in files]) except: try: + import traceback traceback.print_exc() except: pass From 2988b28a8f81c8af6f8d5c3607c9dba6be8ce2a4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 Feb 2011 16:36:43 -0700 Subject: [PATCH 10/15] ... --- src/calibre/gui2/complete.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/complete.py b/src/calibre/gui2/complete.py index 2eb97b128d..226fe8b9c7 100644 --- a/src/calibre/gui2/complete.py +++ b/src/calibre/gui2/complete.py @@ -11,7 +11,7 @@ from PyQt4.Qt import QLineEdit, QAbstractListModel, Qt, \ from calibre.utils.icu import sort_key, lower from calibre.gui2 import NONE -from calibre.gui2.widgets import EnComboBox +from calibre.gui2.widgets import EnComboBox, LineEditECM class CompleteModel(QAbstractListModel): @@ -38,7 +38,7 @@ class CompleteModel(QAbstractListModel): return NONE -class MultiCompleteLineEdit(QLineEdit): +class MultiCompleteLineEdit(QLineEdit, LineEditECM): ''' A line edit that completes on multiple items separated by a separator. Use the :meth:`update_items_cache` to set the list of From 251b1f8aa47adc91b23cb4b0d45f80b232ca201c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 9 Feb 2011 09:02:02 -0700 Subject: [PATCH 11/15] Fix #8882 (ERROR: Unhandled exception: TypeError: index() takes exactly 4 arguments (3 given)) --- src/calibre/gui2/preferences/plugins.py | 4 +--- src/calibre/manual/faq.rst | 22 +++++----------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/calibre/gui2/preferences/plugins.py b/src/calibre/gui2/preferences/plugins.py index 4b83df71c7..acf42fee16 100644 --- a/src/calibre/gui2/preferences/plugins.py +++ b/src/calibre/gui2/preferences/plugins.py @@ -109,7 +109,7 @@ class PluginModel(QAbstractItemModel, SearchQueryParser): # {{{ return self.index(ans[0], 0, QModelIndex()) if ans[1] < 0 else \ self.index(ans[1], 0, self.index(ans[0], 0, QModelIndex())) - def index(self, row, column, parent): + def index(self, row, column, parent=QModelIndex()): if not self.hasIndex(row, column, parent): return QModelIndex() @@ -165,8 +165,6 @@ class PluginModel(QAbstractItemModel, SearchQueryParser): # {{{ def flags(self, index): if not index.isValid(): return 0 - if index.internalId() == 0: - return Qt.ItemIsEnabled flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled return flags diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index cdae20ea3b..cb7f4d62ff 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -182,11 +182,6 @@ If you don't want to uninstall it altogether, there are a couple of tricks you c simplest is to simply re-name the executable file that launches the library program. More detail `in the forums `_. -Can I use the collections feature of the SONY reader? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -|app| has full support for collections. When you add tags to a book's metadata, those tags are turned into collections when you upload the book to the SONY reader. Also, the series information is automatically -turned into a collection on the reader. Note that the PRS-500 does not support collections for books stored on the SD card. The PRS-505 does. - How do I use |app| with my iPad/iPhone/iTouch? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -375,13 +370,6 @@ Content From The Web :depth: 1 :local: -My downloaded news content causes the reader to reset. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This is a bug in the SONY firmware. The problem can be mitigated by switching the output format to EPUB -in the configuration dialog. Alternatively, you can use the LRF output format and use the SONY software -to transfer the files to the reader. The SONY software pre-paginates the LRF file, -thereby reducing the number of resets. - I obtained a recipe for a news site as a .py file from somewhere, how do I use it? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start the :guilabel:`Add custom news sources` dialog (from the :guilabel:`Fetch news` menu) and click the :guilabel:`Switch to advanced mode` button. Delete everything in the box with the recipe source code and copy paste the contents of your .py file into the box. Click :guilabel:`Add/update recipe`. @@ -391,7 +379,7 @@ I want |app| to download news from my favorite news website. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you are reasonably proficient with computers, you can teach |app| to download news from any website of your choosing. To learn how to do this see :ref:`news`. -Otherwise, you can register a request for a particular news site by adding a comment `to this ticket `_. +Otherwise, you can request a particular news site by posting in the `calibre Recipes forum `_. Can I use web2disk to download an arbitrary website? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -480,7 +468,7 @@ How do I backup |app|? The most important thing to backup is the |app| library folder, that contains all your books and metadata. This is the folder you chose for your |app| library when you ran |app| for the first time. You can get the path to the library folder by clicking the |app| icon on the main toolbar. You must backup this complete folder with all its files and sub-folders. -You can switch |app| to using a backed up library folder by simply clicking the |app| icon on the toolbar and choosing your backup library folder. +You can switch |app| to using a backed up library folder by simply clicking the |app| icon on the toolbar and choosing your backup library folder. A backed up library folder backs up your custom columns and saved searches as well as all your books and metadata. If you want to backup the |app| configuration/plugins, you have to backup the config directory. You can find this config directory via :guilabel:`Preferences->Miscellaneous`. Note that restoring configuration directories is not officially supported, but should work in most cases. Just copy the contents of the backup directory into the current configuration directory to restore. @@ -491,7 +479,7 @@ Most purchased EPUB books have `DRM `_. Thi I am getting a "Permission Denied" error? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A permission denied error can occur because of many possible reasons, none of them having anything to do with |app|. You can get permission denied errors if you are using an SD card with write protect enabled. Or if you, or some program you used changed the file permissions of the files in question to read only. Or if there is a filesystem error on the device which caused your operating system to mount the filesystem in read only mode or mark a particular file as read only pending recovery. Or if the files have their owner set to a user other than you. You will need to fix the underlying cause of the permissions error before resuming to use |app|. Read the error message carefully, see what file it points to and fix the permissions on that file. +A permission denied error can occur because of many possible reasons, none of them having anything to do with |app|. You can get permission denied errors if you are using an SD card with write protect enabled. Or if you, or some program you used changed the file permissions of the files in question to read only. Or if there is a filesystem error on the device which caused your operating system to mount the filesystem in read only mode or mark a particular file as read only pending recovery. Or if the files have their owner set to a user other than you. Or if your file is open in another program. You will need to fix the underlying cause of the permissions error before resuming to use |app|. Read the error message carefully, see what file it points to and fix the permissions on that file. Can I have the comment metadata show up on my reader? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -504,7 +492,7 @@ I want some feature added to |app|. What can I do? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You have two choices: 1. Create a patch by hacking on |app| and send it to me for review and inclusion. See `Development `_. - 2. `Open a ticket `_ (you have to register and login first) and hopefully I will find the time to implement your feature. + 2. `Open a ticket `_ (you have to register and login first). Remember that |app| development is done by volunteers, so if you get no response to your feature request, it means no one feels like implementing it. Can I include |app| on a CD to be distributed with my product/magazine? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -522,7 +510,7 @@ Why are there so many calibre-parallel processes on my system? In addition to this some conversion plugins run tasks in their own pool of processes, so for example if you bulk convert comics, each comic conversion will use three separate processes to render the images. The job manager knows this so it will run only a single comic conversion simultaneously. -And since I'm sure someone will ask: The reason adding/saving books are in separate processes is because of PDF. PDF processing libraries can crash on reading PDFs and I dont want the crash to take down all of calibre. Also when adding EPUB books, in order to extract the cover you have to sometimes render the HTML of the first page, which means that it either has to run the GUI thread of the main process or in a separate process. +And since I'm sure someone will ask: The reason adding/saving books are in separate processes is because of PDF. PDF processing libraries can crash on reading PDFs and I dont want the crash to take down all of calibre. Also when adding EPUB books, in order to extract the cover you have to sometimes render the HTML of the first page, which means that it either has to run in the GUI thread of the main process or in a separate process. Finally, the reason calibre keep workers alive and idle instead of launching on demand is to workaround the slow startup time of python processes. From 50e482dc73efd18b30f631741a4ef496f6d4db20 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 9 Feb 2011 09:04:02 -0700 Subject: [PATCH 12/15] Fix #8884 (taz Digiabo: Download server changed) --- resources/recipes/taz.recipe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/recipes/taz.recipe b/resources/recipes/taz.recipe index 93ce5fded0..b777d7ad51 100644 --- a/resources/recipes/taz.recipe +++ b/resources/recipes/taz.recipe @@ -27,7 +27,7 @@ class TazDigiabo(BasicNewsRecipe): } def build_index(self): - domain = "http://www.taz.de" + domain = "http://dl.taz.de" url = domain + "/epub/" From 87c484e9c0020ca157c88cfff9074b82a7654e94 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 9 Feb 2011 09:05:00 -0700 Subject: [PATCH 13/15] Fix #8887 (Updated recipe for B92) --- resources/recipes/b92.recipe | 52 +++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/resources/recipes/b92.recipe b/resources/recipes/b92.recipe index 20b844b57d..7181419682 100644 --- a/resources/recipes/b92.recipe +++ b/resources/recipes/b92.recipe @@ -1,6 +1,6 @@ __license__ = 'GPL v3' -__copyright__ = '2008-2010, Darko Miletic ' +__copyright__ = '2008-2011, Darko Miletic ' ''' b92.net ''' @@ -10,7 +10,7 @@ from calibre.web.feeds.news import BasicNewsRecipe class B92(BasicNewsRecipe): title = 'B92' __author__ = 'Darko Miletic' - description = 'B92 info, najnovije vesti iz Srbije, regiona i sveta' + description = 'Najnovije vesti iz Srbije, regiona i sveta, aktuelne teme iz sveta politike, ekonomije, drustva, foto galerija, kolumne' publisher = 'B92' category = 'news, politics, Serbia' oldest_article = 2 @@ -20,34 +20,44 @@ class B92(BasicNewsRecipe): encoding = 'cp1250' language = 'sr' publication_type = 'newsportal' - extra_css = ' @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} body{font-family: serif1, serif} .article_description{font-family: serif1, serif} ' + masthead_url = 'http://www.b92.net/images/fp/logo.gif' + extra_css = """ + @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} + @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} + body{font-family: Arial,Helvetica,sans1,sans-serif} + .articledescription{font-family: serif1, serif} + .article-info2,.article-info1{text-transform: uppercase; font-size: small} + """ conversion_options = { - 'comment' : description - , 'tags' : category - , 'publisher' : publisher - , 'language' : language + 'comment' : description + , 'tags' : category + , 'publisher': publisher + , 'language' : language , 'linearize_tables' : True } preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')] - keep_only_tags = [dict(name='table', attrs={'class':'maindocument'})] - - remove_tags = [ - dict(name='ul', attrs={'class':'comment-nav'}) - ,dict(name=['embed','link','base'] ) - ,dict(name='div', attrs={'class':'udokum'} ) - ] + keep_only_tags = [dict(attrs={'class':['article-info1','article-text']})] + remove_attributes = ['width','height','align','hspace','vspace','border'] + remove_tags = [dict(name=['embed','link','base','meta'])] feeds = [ - (u'Vesti', u'http://www.b92.net/info/rss/vesti.xml') - ,(u'Biz' , u'http://www.b92.net/info/rss/biz.xml' ) + (u'Vesti' , u'http://www.b92.net/info/rss/vesti.xml' ) + ,(u'Biz' , u'http://www.b92.net/info/rss/biz.xml' ) + ,(u'Sport' , u'http://www.b92.net/info/rss/sport.xml' ) + ,(u'Zivot' , u'http://www.b92.net/info/rss/zivot.xml' ) + ,(u'Kultura' , u'http://www.b92.net/info/rss/kultura.xml' ) + ,(u'Automobili' , u'http://www.b92.net/info/rss/automobili.xml') + ,(u'Tehnopolis' , u'http://www.b92.net/info/rss/tehnopolis.xml') ] - def print_version(self, url): - return url + '&version=print' - def preprocess_html(self, soup): - return self.adeify_images(soup) - + for item in soup.findAll(style=True): + del item['style'] + for alink in soup.findAll('a'): + if alink.string is not None: + tstr = alink.string + alink.replaceWith(tstr) + return soup From 0379b914e7d0592f503818b76901bb005642581d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 9 Feb 2011 09:06:50 -0700 Subject: [PATCH 14/15] Fix #8889 (New recipe for njuz.net website) --- resources/images/news/njuz_net.png | Bin 0 -> 914 bytes resources/recipes/njuz_net.recipe | 61 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 resources/images/news/njuz_net.png create mode 100644 resources/recipes/njuz_net.recipe diff --git a/resources/images/news/njuz_net.png b/resources/images/news/njuz_net.png new file mode 100644 index 0000000000000000000000000000000000000000..86f2f77e17f3a01fd3820538ad5b83b2f242551e GIT binary patch literal 914 zcmV;D18w|?P)lu%$(WNI}t7O+y<^1rs3=QW7HxFTC*NgBt%BA9>Ix zV}9}Gl@&_XOrw{-g}TX(zn=iC{;S$*QwN#H6MXwQqaM?p70e{}%WN&%cRbh;6`K};})I98aQ8Ambv1KW*7Fd^vNg|pmPyO5-M zv{LE2CGa~jK>s(}trl!PS(d>Ps5HX8XC6t{zZ%1lX$76J-<&u~n2k|o z8d_`b>JK-*K6qgC_~C=&pa1#rG1~18qA*4n1nlbXCH#2LpJI%kO;d$br5jF%E_9|@ z94AyMwIsNCc3Av4;rFpMmt(j=LI zJN5eVhr$skFTdma622#q z_gr{h4xGAXM@9&Wjd5x-;i;88PEuyWa;3C+y7l_fwo&OLt;yF;A3k*8OWUPVsi3FcJmwV({@ae= zu$IThMpl?C4pH)qCNG14B4&ep-p9wETtK<63{76w*EY}8pRSyXqWA>a9oAWj>Okf8 z2dCyP^IjmmP&j#G|9uhD3(E%OP*5ZL_Iy{X4X%@tVS>TS$?o~{=Pn&RI&p_T|GVrQ zl*<)V2ZtcYj$r>njM4U%2-)4a_hzOhjvTpfi#X2{C>ommW8>JpyMic+dS{Y|$oI{> oD?7DX|CK_q@Yv$)`bU5P0DvuQWND}bivR!s07*qoM6N<$f{#$RCIA2c literal 0 HcmV?d00001 diff --git a/resources/recipes/njuz_net.recipe b/resources/recipes/njuz_net.recipe new file mode 100644 index 0000000000..23069d7604 --- /dev/null +++ b/resources/recipes/njuz_net.recipe @@ -0,0 +1,61 @@ + +__license__ = 'GPL v3' +__copyright__ = '2011, Darko Miletic ' +''' +njuz.net +''' +import re +from calibre.web.feeds.news import BasicNewsRecipe + +class NjuzNet(BasicNewsRecipe): + title = 'Njuz.net' + __author__ = 'Darko Miletic' + description = 'Iscasene vesti iz Srbije, regiona i sveta' + publisher = 'njuz.net' + category = 'news, politics, humor, Serbia' + oldest_article = 2 + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + encoding = 'utf8' + language = 'sr' + publication_type = 'newsportal' + masthead_url = 'http://www.njuz.net/njuznet.jpg' + extra_css = """ + @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} + body{font-family: serif1, serif} + .articledescription{font-family: serif1, serif} + .wp-caption-text{font-size: x-small} + """ + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language + } + + preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')] + + keep_only_tags = [ + dict(attrs={'id':'entryMeta'}) + ,dict(attrs={'class':'post'}) + ] + + remove_tags = [ + dict(name=['embed','link','base','iframe','object','meta','fb:like']) + ,dict(name='div', attrs={'id':'tagsandcats'}) + ] + remove_tags_after= dict(name='div', attrs={'id':'tagsandcats'}) + remove_attributes= ['lang'] + feeds = [(u'Clanci', u'http://www.njuz.net/feed/')] + + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + for alink in soup.findAll('a'): + if alink.string is not None: + tstr = alink.string + alink.replaceWith(tstr) + return soup + From 3d385196fd68033842195249e4d9b42d8341e1a5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 9 Feb 2011 09:13:18 -0700 Subject: [PATCH 15/15] Fix #8888 (Request support for T-mobile MyTouch 4g) --- src/calibre/devices/android/driver.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py index e9021461eb..e6ad786cac 100644 --- a/src/calibre/devices/android/driver.py +++ b/src/calibre/devices/android/driver.py @@ -65,6 +65,9 @@ class ANDROID(USBMS): # Huawei 0x45e : { 0x00e1 : [0x007], }, + # T-Mobile + 0x0408 : { 0x03ba : [0x0109], }, + } EBOOK_DIR_MAIN = ['eBooks/import', 'wordplayer/calibretransfer', 'Books'] EXTRA_CUSTOMIZATION_MESSAGE = _('Comma separated list of directories to ' @@ -74,13 +77,13 @@ class ANDROID(USBMS): VENDOR_NAME = ['HTC', 'MOTOROLA', 'GOOGLE_', 'ANDROID', 'ACER', 'GT-I5700', 'SAMSUNG', 'DELL', 'LINUX', 'GOOGLE', 'ARCHOS', - 'TELECHIP', 'HUAWEI', ] + 'TELECHIP', 'HUAWEI', 'T-MOBILE', ] WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE', '__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897', 'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE', 'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT', 'A70H', - 'IDEOS_TABLET'] + 'IDEOS_TABLET', 'MYTOUCH_4G'] WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD', 'A70S', 'A101IT']