From 405ba87f8e912836654c54c13948da1040d13b14 Mon Sep 17 00:00:00 2001 From: John Schember Date: Sat, 26 Mar 2011 18:36:46 -0400 Subject: [PATCH 1/5] Implement bug #742686: Allow users to specify what items are shown in the second toolbar. --- src/calibre/gui2/__init__.py | 2 + src/calibre/gui2/layout.py | 65 ++++++++++------------- src/calibre/gui2/preferences/look_feel.ui | 6 +-- src/calibre/gui2/preferences/toolbar.py | 1 + 4 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 9649a79cc1..ade4b496fe 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -29,6 +29,8 @@ gprefs.defaults['action-layout-toolbar'] = ( 'Connect Share', None, 'Remove Books', None, 'Help', 'Preferences', ) +gprefs.defaults['action-layout-toolbar-child'] = () + gprefs.defaults['action-layout-toolbar-device'] = ( 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', 'Send To Device', None, None, 'Location Manager', None, None, diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index e8a4e79384..e4814ffbb8 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -278,11 +278,16 @@ class ToolBar(QToolBar): # {{{ pass def build_bar(self): - self.child_bar.setVisible(gprefs['show_child_bar']) self.showing_donate = False showing_device = self.location_manager.has_device - actions = '-device' if showing_device else '' - actions = gprefs['action-layout-toolbar'+actions] + mactions = '-device' if showing_device else '' + mactions = gprefs['action-layout-toolbar'+mactions] + cactions = gprefs['action-layout-toolbar-child'] + + show_child = gprefs['show_child_bar'] + if not len(cactions): + show_child = False + self.child_bar.setVisible(show_child) for ac in self.added_actions: m = ac.menu() @@ -292,41 +297,27 @@ class ToolBar(QToolBar): # {{{ self.clear() self.child_bar.clear() self.added_actions = [] - self.spacers = [Spacer(self.child_bar), Spacer(self.child_bar), - Spacer(self), Spacer(self)] - self.child_bar.addWidget(self.spacers[0]) - if gprefs['show_child_bar']: - self.addWidget(self.spacers[2]) - for what in actions: - if what is None and not gprefs['show_child_bar']: - self.addSeparator() - elif what == 'Location Manager': - for ac in self.location_manager.available_actions: - self.addAction(ac) - self.added_actions.append(ac) - self.setup_tool_button(ac, QToolButton.MenuButtonPopup) - elif what == 'Donate': - self.d_widget = QWidget() - self.d_widget.setLayout(QVBoxLayout()) - self.d_widget.layout().addWidget(self.donate_button) - self.addWidget(self.d_widget) - self.showing_donate = True - elif what in self.gui.iactions: - action = self.gui.iactions[what] - bar = self - if action.action_type == 'current' and gprefs['show_child_bar']: - bar = self.child_bar - bar.addAction(action.qaction) - self.added_actions.append(action.qaction) - self.setup_tool_button(action.qaction, action.popup_type) - - self.child_bar.addWidget(self.spacers[1]) - if gprefs['show_child_bar']: - self.addWidget(self.spacers[3]) - else: - for s in self.spacers[2:]: - s.setVisible(False) + for bar, actions in ((self, mactions), (self.child_bar, cactions)): + for what in actions: + if what is None: + bar.addSeparator() + elif what == 'Location Manager': + for ac in self.location_manager.available_actions: + bar.addAction(ac) + bar.added_actions.append(ac) + bar.setup_tool_button(ac, QToolButton.MenuButtonPopup) + elif what == 'Donate': + self.d_widget = QWidget() + self.d_widget.setLayout(QVBoxLayout()) + self.d_widget.layout().addWidget(self.donate_button) + bar.addWidget(self.d_widget) + self.showing_donate = True + elif what in self.gui.iactions: + action = self.gui.iactions[what] + bar.addAction(action.qaction) + self.added_actions.append(action.qaction) + self.setup_tool_button(action.qaction, action.popup_type) def setup_tool_button(self, ac, menu_mode=None): ch = self.widgetForAction(ac) diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index bc965b89fa..048c664934 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -6,8 +6,8 @@ 0 0 - 670 - 422 + 717 + 444 @@ -247,7 +247,7 @@ then the tags will be displayed each on their own line. - &Split the toolbar into two toolbars + Add a &second toolbar diff --git a/src/calibre/gui2/preferences/toolbar.py b/src/calibre/gui2/preferences/toolbar.py index a0d48f3910..a17531c7d3 100644 --- a/src/calibre/gui2/preferences/toolbar.py +++ b/src/calibre/gui2/preferences/toolbar.py @@ -208,6 +208,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): LOCATIONS = [ ('toolbar', _('The main toolbar')), + ('toolbar-child', _('The second toolbar')), ('toolbar-device', _('The main toolbar when a device is connected')), ('context-menu', _('The context menu for the books in the ' 'calibre library')), From a929a0ff9f88b7c905b79e7608613de0619a2d19 Mon Sep 17 00:00:00 2001 From: John Schember Date: Sat, 26 Mar 2011 21:58:57 -0400 Subject: [PATCH 2/5] Update mobi docs. --- format_docs/pdb/mobi.txt | 126 ++++++++++++++++++++++++++++++++++----- 1 file changed, 112 insertions(+), 14 deletions(-) diff --git a/format_docs/pdb/mobi.txt b/format_docs/pdb/mobi.txt index e378e1622b..f240686269 100644 --- a/format_docs/pdb/mobi.txt +++ b/format_docs/pdb/mobi.txt @@ -210,21 +210,23 @@ record type usual length name comments 114 versionnumber 115 sample 116 startreading -118 retail price (as text) -119 retail price currency (as text) -201 coveroffset -202 thumboffset +117 3 adult Mobipocket Creator adds this if Adult only is checked; contents: "yes" +118 retail price As text, e.g. "4.99" +119 retail price currency As text, e.g. "USD" +201 4 coveroffset Add to first image field in Mobi Header to find PDB record containing the cover image +202 4 thumboffset Add to first image field in Mobi Header to find PDB record containing the thumbnail cover image 203 hasfakecover -204 204 Unknown -205 205 Unknown -206 206 Unknown -207 207 Unknown -208 208 Unknown -300 300 Unknown -401 clippinglimit +204 4 Creator Software Records 204-207 are usually the same for all books from a certain source, e.g. 1-6-2-41 for Baen and 201-1-0-85 for project gutenberg, 200-1-0-85 for amazon when converted to a 32 bit integer. +205 4 Creator Major Version +206 4 Creator Minor Version +207 4 Creator Build Number +208 watermark +209 tamper proof keys Used by the Kindle (and Android app) for generating book-specific PIDs. +300 fontsignature +401 1 clippinglimit 402 publisherlimit 403 403 Unknown -404 404 ttsflag +404 1 404 ttsflag 501 4 cdetype PDOC - Personal Doc; EBOK - ebook; 502 lastupdatetime @@ -287,9 +289,9 @@ content at the beginning of the following record. The trailing entry ends with a byte containing a count of the overlapping bytes plus additional flags. offset bytes content comments -0 0-3 N terminal bytes +0 0-3 N terminal bytes of a multibyte - character + character N 1 Size & flags bits 1-2 encode N, use of bits 3-8 is unknown @@ -328,6 +330,102 @@ programs may ignore them entirely. They are stored at the end of the file itself so the full file needs to be scanned when loaded to find them. +Image Records +------------- + +If the file contains images, they follow the text blocks, with each image using a +single block. The 4096-byte record size in the PalmDoc header applies only to +text records; image records may be larger. + + +Magic Records +------------- + +In some cases, MobiPocket Creator adds a 2-zero-byte record after the text +records in a file. This record is not included in the "record count" of text +records in the PalmDoc header, and is also not used as the "first non-book +index" in the MOBI header. (If the 2-zero-byte record is present, the index of +the following block is used as the "first non-book index".) + +MobiPocket Creator also ends files with three records: 'FLIS', 'FCIS', and +'end-of-file', in that order. The 'FLIS' and 'FCIS' records do not seem to be +necessary for MobiPocket Reader or the Amazon Kindle 2 to read the file. The +'end-of-file' record might be necessary. + + +FLIS Record +----------- + +The FLIS record appears to have a fixed value. The meaning of the values is not known. + +offset bytes content comments +0 4 identifier the characters F L I S (0x46 0x4c 0x49 0x53) +4 4 ? fixed value: 8 +8 2 ? fixed value: 65 +10 2 ? fixed value: 0 +12 4 ? fixed value: 0 +16 4 ? fixed value: -1 +20 2 ? fixed value: 1 +22 2 ? fixed value: 3 +24 4 ? fixed value: 3 +28 4 ? fixed value: 1 +32 4 ? fixed value: -1 + + +FCIS Record +----------- + +The FCIS record appears to have mostly fixed values. + +offset bytes content comments +0 4 identifier the characters F C I S (0x46 0x43 0x49 0x53) +4 4 ? fixed value: 20 +8 4 ? fixed value: 16 +12 4 ? fixed value: 1 +16 4 ? fixed value: 0 +20 4 ? text length (the same value as "text length" in the PalmDoc header) +24 4 ? fixed value: 0 +28 4 ? fixed value: 32 +32 4 ? fixed value: 8 +36 2 ? fixed value: 1 +38 2 ? fixed value: 1 +40 4 ? fixed value: 0 + + +End-of-file Record +------------------ + +The end-of-file record is a fixed 4-byte record. While the last two bytes +appear to be a CRLF marker, the meaning of the first two bytes is unknown. + +offset bytes content comments +0 1 ? fixed value: 233 (0xe9) +1 1 ? fixed value: 142 (0x8e) +2 1 ? fixed value: 13 (0x0d) +3 1 ? fixed value: 10 (0x0a) + + +SRCS Record +----------- + +kindlegen creates a record whose content is a zip archive of all source files +(i.e., .opf, .ncx, .htm, .jpg, ...) given to the command and puts it in the +generated MOBI file. The record begins with the "SRCS" signature and is +located just before the #End-of-file Record. + +MOBI files created with Mobipocket creator, Amazon's Personal Document Service, +or Kindle Direct Publishing (former Amazon DTP) don't include SRCS record. +In a past, kindlegen had an undocumented option to suppress this record, but +the option was removed in 2010. + +offset bytes content comments +0 4 identifier "SRCS" (0x53 0x52 0x43 0x53) +4 4 ? fixed value(?): 0x00000010 +8 4 ? fixed value(?): 0x0000002f +12 4 ? fixed value(?): 0x00000001 +16 zip The zip archive continues to the end of this record + + MBP --- From ab1a2a9e09b7f5f32353a74132548ecf180dc6c6 Mon Sep 17 00:00:00 2001 From: John Schember Date: Sat, 26 Mar 2011 22:01:25 -0400 Subject: [PATCH 3/5] Update mobi docs. --- format_docs/pdb/mobi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format_docs/pdb/mobi.txt b/format_docs/pdb/mobi.txt index f240686269..bf08bd8b71 100644 --- a/format_docs/pdb/mobi.txt +++ b/format_docs/pdb/mobi.txt @@ -225,7 +225,7 @@ record type usual length name comments 300 fontsignature 401 1 clippinglimit 402 publisherlimit -403 403 Unknown +403 403 Unknown 1 - Text to Speech disabled; 0 - Text to Speech enabled 404 1 404 ttsflag 501 4 cdetype PDOC - Personal Doc; EBOK - ebook; From 6de969a50667f4875b83283b3549269778e25a3c Mon Sep 17 00:00:00 2001 From: John Schember Date: Sat, 26 Mar 2011 22:15:57 -0400 Subject: [PATCH 4/5] Minor cleanup --- src/calibre/ebooks/mobi/writer.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 2be699e525..1893f68d4c 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -1098,7 +1098,7 @@ class MobiWriter(object): nodeCountValue = 0x80 if nodeCountValue == 0 else nodeCountValue tbSequence += chr(nodeCountValue) else : - tbSequence += decint(0x00, DECINT_FORWARD) # arg1 = 0x80 + tbSequence += decint(0x00, DECINT_FORWARD) # arg1 = 0x80 tbSequence += decint(len(tbSequence) + 1, DECINT_FORWARD) # len @@ -1644,14 +1644,14 @@ class MobiWriter(object): self._oeb.log('Generating INDX ...') self._primary_index_record = None - # Build the NCXEntries and INDX + # Build the NCXEntries and INDX indxt, indxt_count, indices, last_name = self._generate_indxt() if last_name is None: self._oeb.log.warn('Input document has no TOC. No index generated.') return - # Assemble the INDX0[0] and INDX1[0] output streams + # Assemble the INDX0[0] and INDX1[0] output streams indx1 = StringIO() indx1.write('INDX'+pack('>I', 0xc0)) # header length @@ -2310,10 +2310,8 @@ class MobiWriter(object): parentIndex = sectionParent.parentIndex self._write_section_node(indxt, indices, sectionParent.myCtocMapIndex, index, offset, length, c, firstArticle, lastArticle, parentIndex) - last_name = "%04X"%c - # articles - for (i, article) in enumerate(list(sectionParent.articles)) : + for article in list(sectionParent.articles): index = article.myCtocMapIndex offset = article.startAddress length = article.articleLength @@ -2413,7 +2411,6 @@ class MobiWriter(object): # Article(s) child.depth() = 1 # Section 2 - documentType = "unknown" sectionIndices = [] sectionParents = [] currentSection = 0 # Starting section number @@ -2421,7 +2418,6 @@ class MobiWriter(object): indxt, indices, c = StringIO(), StringIO(), 0 indices.write('IDXT') - c = 0 last_name = None # 'book', 'periodical' or None @@ -2449,8 +2445,8 @@ class MobiWriter(object): if self.opts.verbose > 3 : self._oeb.logger.info("unknown document type %12.12s \tdepth:%d" % (child.title, child.depth()) ) - # Original code starts here - # test first node for depth/class + # Original code starts here + # test first node for depth/class entries = list(toc.iter())[1:] for (i, child) in enumerate(entries): if not child.title or not child.title.strip(): From 177d15bdbb6e5946bac2a5289fe293d13d7396a8 Mon Sep 17 00:00:00 2001 From: John Schember Date: Sat, 26 Mar 2011 22:19:54 -0400 Subject: [PATCH 5/5] Minor cleanup --- src/calibre/ebooks/mobi/writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 1893f68d4c..fccaad8811 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -1188,7 +1188,7 @@ class MobiWriter(object): toc = self._oeb.toc nodes = list(toc.iter())[1:] toc_conforms = True - for (i, child) in enumerate(nodes) : + for child in nodes: if child.klass == "periodical" and child.depth() != 3 or \ child.klass == "section" and child.depth() != 2 or \ child.klass == "article" and child.depth() != 1 :